void usb_enumerate(struct usbhub_s *hub) { u32 portcount = hub->portcount; hub->threads = portcount; hub->detectend = timer_calc(USB_TIME_SIGATT); // Launch a thread for every port. int i; for (i=0; i<portcount; i++) { struct usbdevice_s *usbdev = malloc_tmphigh(sizeof(*usbdev)); if (!usbdev) { warn_noalloc(); continue; } memset(usbdev, 0, sizeof(*usbdev)); usbdev->hub = hub; usbdev->port = i; run_thread(usb_hub_port_setup, usbdev); } // Wait for threads to complete. while (hub->threads) yield(); }
// Helper function to find, malloc_tmphigh, and copy a romfile. This // function adds a trailing zero to the malloc'd copy. void * romfile_loadfile(const char *name, int *psize) { struct romfile_s *file = romfile_find(name); if (!file) return NULL; int filesize = file->size; if (!filesize) return NULL; char *data = malloc_tmphigh(filesize+1); if (!data) { warn_noalloc(); return NULL; } dprintf(5, "Copying romfile '%s' (len %d)\n", name, filesize); int ret = file->copy(file, data, filesize); if (ret < 0) { free(data); return NULL; } if (psize) *psize = filesize; data[filesize] = '\0'; return data; }
static struct usb_config_descriptor * get_device_config(struct usb_pipe *pipe) { struct usb_config_descriptor cfg; struct usb_ctrlrequest req; req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE; req.bRequest = USB_REQ_GET_DESCRIPTOR; req.wValue = USB_DT_CONFIG<<8; req.wIndex = 0; req.wLength = sizeof(cfg); int ret = usb_send_default_control(pipe, &req, &cfg); if (ret) return NULL; void *config = malloc_tmphigh(cfg.wTotalLength); if (!config) return NULL; req.wLength = cfg.wTotalLength; ret = usb_send_default_control(pipe, &req, config); if (ret) { free(config); return NULL; } //hexdump(config, cfg.wTotalLength); return config; }
int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci) { if (! CONFIG_USB_EHCI) return -1; u16 bdf = pci->bdf; u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0); struct ehci_caps *caps = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK); u32 hcc_params = readl(&caps->hccparams); if (hcc_params & HCC_64BIT_ADDR) { dprintf(1, "No support for 64bit EHCI\n"); return -1; } struct usb_ehci_s *cntl = malloc_tmphigh(sizeof(*cntl)); if (!cntl) { warn_noalloc(); return -1; } memset(cntl, 0, sizeof(*cntl)); cntl->usb.busid = busid; cntl->usb.pci = pci; cntl->usb.type = USB_TYPE_EHCI; cntl->caps = caps; cntl->regs = (void*)caps + readb(&caps->caplength); dprintf(1, "EHCI init on dev %02x:%02x.%x (regs=%p)\n" , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf) , pci_bdf_to_fn(bdf), cntl->regs); pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER); // XXX - check for and disable SMM control? // Find companion controllers. int count = 0; for (;;) { if (!comppci || comppci == pci) break; if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_UHCI) cntl->companion[count++] = comppci; else if (pci_classprog(comppci) == PCI_CLASS_SERIAL_USB_OHCI) cntl->companion[count++] = comppci; comppci = comppci->next; } run_thread(configure_ehci, cntl); return 0; }
int ohci_control(u32 endp, int dir, const void *cmd, int cmdsize , void *data, int datasize) { if (! CONFIG_USB_OHCI) return -1; dprintf(5, "ohci_control %x\n", endp); struct usb_s *cntl = endp2cntl(endp); int maxpacket = endp2maxsize(endp); int lowspeed = endp2speed(endp); int devaddr = endp2devaddr(endp) | (endp2ep(endp) << 7); // Setup transfer descriptors struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3); tds[0].hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC; tds[0].hwCBP = (u32)cmd; tds[0].hwNextTD = (u32)&tds[1]; tds[0].hwBE = (u32)cmd + cmdsize - 1; tds[1].hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC; tds[1].hwCBP = datasize ? (u32)data : 0; tds[1].hwNextTD = (u32)&tds[2]; tds[1].hwBE = (u32)data + datasize - 1; tds[2].hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC; tds[2].hwCBP = 0; tds[2].hwNextTD = (u32)&tds[3]; tds[2].hwBE = 0; // Transfer data struct ohci_ed *ed = cntl->ohci.control_ed; ed->hwINFO = ED_SKIP; barrier(); ed->hwHeadP = (u32)&tds[0]; ed->hwTailP = (u32)&tds[3]; barrier(); ed->hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0); writel(&cntl->ohci.regs->cmdstatus, OHCI_CLF); int ret = wait_ed(ed); ed->hwINFO = ED_SKIP; if (ret) usleep(1); // XXX - in case controller still accessing tds free(tds); return ret; }
static void loadBootOrder(void) { if (!CONFIG_BOOTORDER) return; char *f = romfile_loadfile("bootorder", NULL); if (!f) return; int i = 0; BootorderCount = 1; while (f[i]) { if (f[i] == '\n') BootorderCount++; i++; } Bootorder = malloc_tmphigh(BootorderCount*sizeof(char*)); if (!Bootorder) { warn_noalloc(); free(f); BootorderCount = 0; return; } dprintf(1, "boot order:\n"); i = 0; do { Bootorder[i] = f; f = strchr(f, '\n'); if (f) *(f++) = '\0'; Bootorder[i] = nullTrailingSpace(Bootorder[i]); dprintf(1, "%d: %s\n", i+1, Bootorder[i]); i++; } while (f); }
void enable_bootsplash(void) { if (!CONFIG_BOOTSPLASH) return; dprintf(3, "Checking for bootsplash\n"); u32 file = romfile_find("bootsplash.jpg"); if (!file) return; int filesize = romfile_size(file); u8 *picture = NULL; u8 *filedata = malloc_tmphigh(filesize); struct vesa_info *vesa_info = malloc_tmplow(sizeof(*vesa_info)); struct vesa_mode_info *mode_info = malloc_tmplow(sizeof(*mode_info)); struct jpeg_decdata *jpeg = jpeg_alloc(); if (!filedata || !jpeg || !vesa_info || !mode_info) { warn_noalloc(); goto done; } /* Check whether we have a VESA 2.0 compliant BIOS */ memset(vesa_info, 0, sizeof(struct vesa_info)); vesa_info->vesa_signature = VBE2_SIGNATURE; struct bregs br; memset(&br, 0, sizeof(br)); br.ax = 0x4f00; br.di = FLATPTR_TO_OFFSET(vesa_info); br.es = FLATPTR_TO_SEG(vesa_info); call16_int10(&br); if (vesa_info->vesa_signature != VESA_SIGNATURE) { dprintf(1,"No VBE2 found.\n"); goto done; } /* Print some debugging information about our card. */ char *vendor = SEGOFF_TO_FLATPTR(vesa_info->oem_vendor_name_ptr); char *product = SEGOFF_TO_FLATPTR(vesa_info->oem_product_name_ptr); dprintf(3, "VESA %d.%d\nVENDOR: %s\nPRODUCT: %s\n", vesa_info->vesa_version>>8, vesa_info->vesa_version&0xff, vendor, product); // Parse jpeg and get image size. dprintf(5, "Copying bootsplash.jpg\n"); romfile_copy(file, filedata, filesize); dprintf(5, "Decoding bootsplash.jpg\n"); int ret = jpeg_decode(jpeg, filedata); if (ret) { dprintf(1, "jpeg_decode failed with return code %d...\n", ret); goto done; } int width, height; jpeg_get_size(jpeg, &width, &height); // Try to find a graphics mode with the corresponding dimensions. int videomode = find_videomode(vesa_info, mode_info, width, height); if (videomode < 0) goto done; void *framebuffer = mode_info->phys_base_ptr; int depth = mode_info->bits_per_pixel; dprintf(3, "mode: %04x\n", videomode); dprintf(3, "framebuffer: %p\n", framebuffer); dprintf(3, "bytes per scanline: %d\n", mode_info->bytes_per_scanline); dprintf(3, "bits per pixel: %d\n", depth); // Allocate space for image and decompress it. int imagesize = width * height * (depth / 8); picture = malloc_tmphigh(imagesize); if (!picture) { warn_noalloc(); goto done; } dprintf(5, "Decompressing bootsplash.jpg\n"); ret = jpeg_show(jpeg, picture, width, height, depth); if (ret) { dprintf(1, "jpeg_show failed with return code %d...\n", ret); goto done; } /* Switch to graphics mode */ dprintf(5, "Switching to graphics mode\n"); memset(&br, 0, sizeof(br)); br.ax = 0x4f02; br.bx = (1 << 14) | videomode; call16_int10(&br); if (br.ax != 0x4f) { dprintf(1, "set_mode failed.\n"); goto done; } /* Show the picture */ dprintf(5, "Showing bootsplash.jpg\n"); iomemcpy(framebuffer, picture, imagesize); dprintf(5, "Bootsplash copy complete\n"); BootsplashActive = 1; done: free(filedata); free(picture); free(vesa_info); free(mode_info); free(jpeg); return; }
void enable_bootsplash(void) { if (!CONFIG_BOOTSPLASH) return; /* splash picture can be bmp or jpeg file */ dprintf(3, "Checking for bootsplash\n"); u8 type = 0; /* 0 means jpg, 1 means bmp, default is 0=jpg */ int filesize; u8 *filedata = romfile_loadfile("bootsplash.jpg", &filesize); if (!filedata) { filedata = romfile_loadfile("bootsplash.bmp", &filesize); if (!filedata) return; type = 1; } dprintf(3, "start showing bootsplash\n"); u8 *picture = NULL; /* data buff used to be flushed to the video buf */ struct jpeg_decdata *jpeg = NULL; struct bmp_decdata *bmp = NULL; struct vbe_info *vesa_info = malloc_tmplow(sizeof(*vesa_info)); struct vbe_mode_info *mode_info = malloc_tmplow(sizeof(*mode_info)); if (!vesa_info || !mode_info) { warn_noalloc(); goto done; } /* Check whether we have a VESA 2.0 compliant BIOS */ memset(vesa_info, 0, sizeof(struct vbe_info)); vesa_info->signature = VBE2_SIGNATURE; struct bregs br; memset(&br, 0, sizeof(br)); br.ax = 0x4f00; br.di = FLATPTR_TO_OFFSET(vesa_info); br.es = FLATPTR_TO_SEG(vesa_info); call16_int10(&br); if (vesa_info->signature != VESA_SIGNATURE) { dprintf(1,"No VBE2 found.\n"); goto done; } /* Print some debugging information about our card. */ char *vendor = SEGOFF_TO_FLATPTR(vesa_info->oem_vendor_string); char *product = SEGOFF_TO_FLATPTR(vesa_info->oem_product_string); dprintf(3, "VESA %d.%d\nVENDOR: %s\nPRODUCT: %s\n", vesa_info->version>>8, vesa_info->version&0xff, vendor, product); int ret, width, height; int bpp_require = 0; if (type == 0) { jpeg = jpeg_alloc(); if (!jpeg) { warn_noalloc(); goto done; } /* Parse jpeg and get image size. */ dprintf(5, "Decoding bootsplash.jpg\n"); ret = jpeg_decode(jpeg, filedata); if (ret) { dprintf(1, "jpeg_decode failed with return code %d...\n", ret); goto done; } jpeg_get_size(jpeg, &width, &height); } else { bmp = bmp_alloc(); if (!bmp) { warn_noalloc(); goto done; } /* Parse bmp and get image size. */ dprintf(5, "Decoding bootsplash.bmp\n"); ret = bmp_decode(bmp, filedata, filesize); if (ret) { dprintf(1, "bmp_decode failed with return code %d...\n", ret); goto done; } bmp_get_size(bmp, &width, &height); bpp_require = 24; } /* jpeg would use 16 or 24 bpp video mode, BMP use 24bpp mode only */ // Try to find a graphics mode with the corresponding dimensions. int videomode = find_videomode(vesa_info, mode_info, width, height, bpp_require); if (videomode < 0) { dprintf(1, "failed to find a videomode with %dx%d %dbpp (0=any).\n", width, height, bpp_require); goto done; } void *framebuffer = (void *)mode_info->phys_base; int depth = mode_info->bits_per_pixel; dprintf(3, "mode: %04x\n", videomode); dprintf(3, "framebuffer: %p\n", framebuffer); dprintf(3, "bytes per scanline: %d\n", mode_info->bytes_per_scanline); dprintf(3, "bits per pixel: %d\n", depth); // Allocate space for image and decompress it. int imagesize = height * mode_info->bytes_per_scanline; picture = malloc_tmphigh(imagesize); if (!picture) { warn_noalloc(); goto done; } if (type == 0) { dprintf(5, "Decompressing bootsplash.jpg\n"); ret = jpeg_show(jpeg, picture, width, height, depth, mode_info->bytes_per_scanline); if (ret) { dprintf(1, "jpeg_show failed with return code %d...\n", ret); goto done; } } else { dprintf(5, "Decompressing bootsplash.bmp\n"); ret = bmp_show(bmp, picture, width, height, depth, mode_info->bytes_per_scanline); if (ret) { dprintf(1, "bmp_show failed with return code %d...\n", ret); goto done; } } /* Switch to graphics mode */ dprintf(5, "Switching to graphics mode\n"); memset(&br, 0, sizeof(br)); br.ax = 0x4f02; br.bx = videomode | VBE_MODE_LINEAR_FRAME_BUFFER; call16_int10(&br); if (br.ax != 0x4f) { dprintf(1, "set_mode failed.\n"); goto done; } /* Show the picture */ dprintf(5, "Showing bootsplash picture\n"); iomemcpy(framebuffer, picture, imagesize); dprintf(5, "Bootsplash copy complete\n"); BootsplashActive = 1; done: free(filedata); free(picture); free(vesa_info); free(mode_info); free(jpeg); free(bmp); return; }
static int smbios_romfile_setup(void) { struct romfile_s *f_anchor = romfile_find("etc/smbios/smbios-anchor"); struct romfile_s *f_tables = romfile_find("etc/smbios/smbios-tables"); struct smbios_entry_point ep; struct smbios_type_0 *t0; u16 qtables_len, need_t0 = 1; u8 *qtables, *tables; if (!f_anchor || !f_tables || f_anchor->size != sizeof(ep)) return 0; f_anchor->copy(f_anchor, &ep, f_anchor->size); if (f_tables->size != ep.structure_table_length) return 0; qtables = malloc_tmphigh(f_tables->size); if (!qtables) { warn_noalloc(); return 0; } f_tables->copy(f_tables, qtables, f_tables->size); ep.structure_table_address = (u32)qtables; /* for smbios_next(), below */ /* did we get a type 0 structure ? */ for (t0 = smbios_next(&ep, NULL); t0; t0 = smbios_next(&ep, t0)) if (t0->header.type == 0) { need_t0 = 0; break; } qtables_len = ep.structure_table_length; if (need_t0) { /* common case: add our own type 0, with 3 strings and 4 '\0's */ u16 t0_len = sizeof(struct smbios_type_0) + strlen(BIOS_NAME) + strlen(VERSION) + strlen(BIOS_DATE) + 4; ep.structure_table_length += t0_len; if (t0_len > ep.max_structure_size) ep.max_structure_size = t0_len; ep.number_of_structures++; } /* allocate final blob and record its address in the entry point */ if (ep.structure_table_length > BUILD_MAX_SMBIOS_FSEG) tables = malloc_high(ep.structure_table_length); else tables = malloc_fseg(ep.structure_table_length); if (!tables) { warn_noalloc(); free(qtables); return 0; } ep.structure_table_address = (u32)tables; /* populate final blob */ if (need_t0) tables = smbios_new_type_0(tables, BIOS_NAME, VERSION, BIOS_DATE); memcpy(tables, qtables, qtables_len); free(qtables); /* finalize entry point */ ep.checksum -= checksum(&ep, 0x10); ep.intermediate_checksum -= checksum((void *)&ep + 0x10, ep.length - 0x10); copy_smbios(&ep); return 1; }