static void pvscsi_init_rings(void *iobase, struct pvscsi_ring_dsc_s **ring_dsc) { struct PVSCSICmdDescSetupRings cmd = {0,}; struct pvscsi_ring_dsc_s *dsc = memalign_high(PAGE_SIZE, sizeof(*dsc)); if (!dsc) { warn_noalloc(); return; } dsc->ring_state = (struct PVSCSIRingsState *)memalign_high(PAGE_SIZE, PAGE_SIZE); dsc->ring_reqs = (struct PVSCSIRingReqDesc *)memalign_high(PAGE_SIZE, PAGE_SIZE); dsc->ring_cmps = (struct PVSCSIRingCmpDesc *)memalign_high(PAGE_SIZE, PAGE_SIZE); if (!dsc->ring_state || !dsc->ring_reqs || !dsc->ring_cmps) { warn_noalloc(); return; } memset(dsc->ring_state, 0, PAGE_SIZE); memset(dsc->ring_reqs, 0, PAGE_SIZE); memset(dsc->ring_cmps, 0, PAGE_SIZE); cmd.reqRingNumPages = 1; cmd.cmpRingNumPages = 1; cmd.ringsStatePPN = virt_to_phys(dsc->ring_state) >> PAGE_SHIFT; cmd.reqRingPPNs[0] = virt_to_phys(dsc->ring_reqs) >> PAGE_SHIFT; cmd.cmpRingPPNs[0] = virt_to_phys(dsc->ring_cmps) >> PAGE_SHIFT; pvscsi_write_cmd_desc(iobase, PVSCSI_CMD_SETUP_RINGS, &cmd, sizeof(cmd)); *ring_dsc = dsc; }
int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize) { ASSERT32FLAT(); if (! CONFIG_USB_EHCI) return -1; dprintf(5, "ehci_control %p (dir=%d cmd=%d data=%d)\n" , p, dir, cmdsize, datasize); if (datasize > 4*4096 || cmdsize > 4*4096) { // XXX - should support larger sizes. warn_noalloc(); return -1; } struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); // Setup transfer descriptors struct ehci_qtd *tds = memalign_tmphigh(EHCI_QTD_ALIGN, sizeof(*tds) * 3); if (!tds) { warn_noalloc(); return -1; } memset(tds, 0, sizeof(*tds) * 3); struct ehci_qtd *td = tds; td->qtd_next = (u32)&td[1]; td->alt_next = EHCI_PTR_TERM; td->token = (ehci_explen(cmdsize) | QTD_STS_ACTIVE | QTD_PID_SETUP | ehci_maxerr(3)); u16 maxpacket = pipe->pipe.maxpacket; fillTDbuffer(td, maxpacket, cmd, cmdsize); td++; if (datasize) { td->qtd_next = (u32)&td[1]; td->alt_next = EHCI_PTR_TERM; td->token = (QTD_TOGGLE | ehci_explen(datasize) | QTD_STS_ACTIVE | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3)); fillTDbuffer(td, maxpacket, data, datasize); td++; } td->qtd_next = EHCI_PTR_TERM; td->alt_next = EHCI_PTR_TERM; td->token = (QTD_TOGGLE | QTD_STS_ACTIVE | (dir ? QTD_PID_OUT : QTD_PID_IN) | ehci_maxerr(3)); // Transfer data barrier(); pipe->qh.qtd_next = (u32)tds; int i, ret=0; for (i=0; i<3; i++) { struct ehci_qtd *td = &tds[i]; ret = ehci_wait_td(pipe, td, 500); if (ret) break; } free(tds); return ret; }
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(); }
static int usb_msc_lun_setup(struct usb_pipe *inpipe, struct usb_pipe *outpipe, struct usbdevice_s *usbdev, int lun) { // Allocate drive structure. struct usbdrive_s *drive = malloc_fseg(sizeof(*drive)); if (!drive) { warn_noalloc(); return -1; } memset(drive, 0, sizeof(*drive)); if (usb_32bit_pipe(inpipe)) drive->drive.type = DTYPE_USB_32; else drive->drive.type = DTYPE_USB; drive->bulkin = inpipe; drive->bulkout = outpipe; drive->lun = lun; int prio = bootprio_find_usb(usbdev, lun); int ret = scsi_drive_setup(&drive->drive, "USB MSC", prio); if (ret) { dprintf(1, "Unable to configure USB MSC drive.\n"); free(drive); return -1; } return 0; }
void copy_mptable(void *pos) { struct mptable_floating_s *p = pos; if (p->signature != MPTABLE_SIGNATURE) return; if (!p->physaddr) return; if (checksum(pos, sizeof(*p)) != 0) return; u32 length = p->length * 16; u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length; // Allocate final memory location. (In theory the config // structure can go in high memory, but Linux kernels before // v2.6.30 crash with that.) struct mptable_floating_s *newpos = malloc_fseg(length + mpclength); if (!newpos) { warn_noalloc(); return; } dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos); memcpy(newpos, pos, length); newpos->physaddr = (u32)newpos + length; newpos->checksum -= checksum(newpos, sizeof(*newpos)); memcpy((void*)newpos + length, (void*)p->physaddr, mpclength); }
struct usb_pipe * ehci_alloc_bulk_pipe(struct usb_pipe *dummy) { // XXX - this func is same as alloc_control except for malloc_low if (! CONFIG_USB_EHCI) return NULL; struct usb_ehci_s *cntl = container_of( dummy->cntl, struct usb_ehci_s, usb); dprintf(7, "ehci_alloc_bulk_pipe %p\n", &cntl->usb); // Allocate a queue head. struct ehci_pipe *pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); if (!pipe) { warn_noalloc(); return NULL; } memset(pipe, 0, sizeof(*pipe)); memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM; // Add queue head to controller list. struct ehci_qh *async_qh = cntl->async_qh; pipe->qh.next = async_qh->next; barrier(); async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; return &pipe->pipe; }
static void copy_acpi_rsdp(void *pos) { if (RsdpAddr) return; struct rsdp_descriptor *p = pos; if (p->signature != RSDP_SIGNATURE) return; u32 length = 20; if (checksum(pos, length) != 0) return; if (p->revision > 1) { length = p->length; if (checksum(pos, length) != 0) return; } void *newpos = malloc_fseg(length); if (!newpos) { warn_noalloc(); return; } dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos); memcpy(newpos, pos, length); RsdpAddr = newpos; }
static int pvscsi_add_lun(struct pci_device *pci, void *iobase, struct pvscsi_ring_dsc_s *ring_dsc, u8 target, u8 lun) { struct pvscsi_lun_s *plun = malloc_fseg(sizeof(*plun)); if (!plun) { warn_noalloc(); return -1; } memset(plun, 0, sizeof(*plun)); plun->drive.type = DTYPE_PVSCSI; plun->drive.cntl_id = pci->bdf; plun->target = target; plun->lun = lun; plun->iobase = iobase; plun->ring_dsc = ring_dsc; char *name = znprintf(MAXDESCSIZE, "pvscsi %pP %d:%d", pci, target, lun); int prio = bootprio_find_scsi_device(pci, target, lun); int ret = scsi_drive_setup(&plun->drive, name, prio); free(name); if (ret) goto fail; return 0; fail: free(plun); return -1; }
// 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 void copy_mptable(void *pos) { struct mptable_floating_s *p = pos; if (p->signature != MPTABLE_SIGNATURE) return; if (!p->physaddr) return; if (checksum(pos, sizeof(*p)) != 0) return; u16 mpflength = p->length * 16; u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length; u16 mpelength = ((struct mptable_config_s *)p->physaddr)->exttable_length; u16 totallength = mpflength + mpclength + mpelength; struct mptable_floating_s *newpos = malloc_fseg(totallength); if (!newpos) { warn_noalloc(); return; } dprintf(1, "Copying MPTABLE from %p/%x to %p with length %x\n", pos, p->physaddr, newpos, totallength); memcpy(newpos, pos, mpflength); dprintf(8, "Copied MPTable FPS from %p to %p with length %x\n", pos, newpos, mpflength); newpos->physaddr = (u32)newpos + mpflength; newpos->checksum -= checksum(newpos, sizeof(*newpos)); memcpy((void*)newpos + mpflength, (void*)p->physaddr, mpclength); dprintf(8, "Copied MPTable MPC from %p to %p with length %x\n", (void*)newpos + mpflength, (void*)p->physaddr, mpclength); if (mpelength) { memcpy((void*)newpos + mpflength + mpclength, (void*)p->physaddr + mpclength, mpelength); dprintf(8, "Copied MPTable MPE from %p to %p with length %x\n", (void*)newpos + mpflength + mpelength, (void*)p->physaddr + mpclength, mpelength); } }
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) { warn_noalloc(); 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 vp_find_vq(unsigned int ioaddr, int queue_index, struct vring_virtqueue **p_vq) { u16 num; ASSERT32FLAT(); struct vring_virtqueue *vq = *p_vq = memalign_low(PAGE_SIZE, sizeof(*vq)); if (!vq) { warn_noalloc(); goto fail; } memset(vq, 0, sizeof(*vq)); /* select the queue */ outw(queue_index, ioaddr + VIRTIO_PCI_QUEUE_SEL); /* check if the queue is available */ num = inw(ioaddr + VIRTIO_PCI_QUEUE_NUM); if (!num) { dprintf(1, "ERROR: queue size is 0\n"); goto fail; } if (num > MAX_QUEUE_NUM) { dprintf(1, "ERROR: queue size %d > %d\n", num, MAX_QUEUE_NUM); goto fail; } /* check if the queue is already active */ if (inl(ioaddr + VIRTIO_PCI_QUEUE_PFN)) { dprintf(1, "ERROR: queue already active\n"); goto fail; } vq->queue_index = queue_index; /* initialize the queue */ struct vring * vr = &vq->vring; vring_init(vr, num, (unsigned char*)&vq->queue); /* activate the queue * * NOTE: vr->desc is initialized by vring_init() */ outl((unsigned long)virt_to_phys(vr->desc) >> PAGE_SHIFT, ioaddr + VIRTIO_PCI_QUEUE_PFN); return num; fail: free(vq); *p_vq = NULL; return -1; }
int create_bounce_buf(void) { if (bounce_buf_fl) return 0; u8 *buf = malloc_low(CDROM_SECTOR_SIZE); if (!buf) { warn_noalloc(); return -1; } bounce_buf_fl = buf; return 0; }
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 romfile_loader_execute(const char *name) { struct romfile_loader_entry_s *entry; int size, offset = 0, nfiles; struct romfile_loader_files *files; void *data = romfile_loadfile(name, &size); if (!data) return -1; if (size % sizeof(*entry)) { warn_internalerror(); goto err; } /* (over)estimate the number of files to load. */ nfiles = size / sizeof(*entry); files = malloc_tmp(sizeof(*files) + nfiles * sizeof(files->files[0])); if (!files) { warn_noalloc(); goto err; } files->nfiles = 0; for (offset = 0; offset < size; offset += sizeof(*entry)) { entry = data + offset; switch (le32_to_cpu(entry->command)) { case ROMFILE_LOADER_COMMAND_ALLOCATE: romfile_loader_allocate(entry, files); break; case ROMFILE_LOADER_COMMAND_ADD_POINTER: romfile_loader_add_pointer(entry, files); break; case ROMFILE_LOADER_COMMAND_ADD_CHECKSUM: romfile_loader_add_checksum(entry, files); default: /* Skip commands that we don't recognize. */ break; } } free(files); free(data); return 0; err: free(data); return -1; }
// Insert an entry in the e820_list at the given position. static void insert_e820(int i, u64 start, u64 size, u32 type) { if (e820_count >= BUILD_MAX_E820) { warn_noalloc(); return; } memmove(&e820_list[i+1], &e820_list[i] , sizeof(e820_list[0]) * (e820_count - i)); e820_count++; struct e820entry *e = &e820_list[i]; e->start = start; e->size = size; e->type = type; }
static void copy_acpi_rsdp(void *pos) { if (RsdpAddr) return; int length = get_acpi_rsdp_length(pos, -1); if (length < 0) return; void *newpos = malloc_fseg(length); if (!newpos) { warn_noalloc(); return; } dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos); memcpy(newpos, pos, length); RsdpAddr = newpos; }
static void romfile_loader_allocate(struct romfile_loader_entry_s *entry, struct romfile_loader_files *files) { struct zone_s *zone; struct romfile_loader_file *file = &files->files[files->nfiles]; void *data; int ret; unsigned alloc_align = le32_to_cpu(entry->alloc_align); if (alloc_align & (alloc_align - 1)) goto err; switch (entry->alloc_zone) { case ROMFILE_LOADER_ALLOC_ZONE_HIGH: zone = &ZoneHigh; break; case ROMFILE_LOADER_ALLOC_ZONE_FSEG: zone = &ZoneFSeg; break; default: goto err; } if (alloc_align < MALLOC_MIN_ALIGN) alloc_align = MALLOC_MIN_ALIGN; if (entry->alloc_file[ROMFILE_LOADER_FILESZ - 1]) goto err; file->file = romfile_find(entry->alloc_file); if (!file->file || !file->file->size) return; data = _malloc(zone, MALLOC_DEFAULT_HANDLE, file->file->size, alloc_align); if (!data) { warn_noalloc(); return; } ret = file->file->copy(file->file, data, file->file->size); if (ret != file->file->size) goto file_err; file->data = data; files->nfiles++; return; file_err: free(data); err: warn_internalerror(); }
struct usb_pipe * ehci_alloc_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { if (! CONFIG_USB_EHCI) return NULL; u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; if (eptype == USB_ENDPOINT_XFER_INT) return ehci_alloc_intr_pipe(usbdev, epdesc); struct usb_ehci_s *cntl = container_of( usbdev->hub->cntl, struct usb_ehci_s, usb); dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype); struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype); if (usbpipe) { // Use previously allocated pipe. struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe); ehci_desc2pipe(pipe, usbdev, epdesc); return usbpipe; } // Allocate a new queue head. struct ehci_pipe *pipe; if (eptype == USB_ENDPOINT_XFER_CONTROL) pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe)); else pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); if (!pipe) { warn_noalloc(); return NULL; } memset(pipe, 0, sizeof(*pipe)); ehci_desc2pipe(pipe, usbdev, epdesc); pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM; // Add queue head to controller list. struct ehci_qh *async_qh = cntl->async_qh; pipe->qh.next = async_qh->next; barrier(); async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; return &pipe->pipe; }
static void copy_pir(void *pos) { struct pir_header *p = pos; if (p->signature != PIR_SIGNATURE) return; if (PirAddr) return; if (p->size < sizeof(*p)) return; if (checksum(pos, p->size) != 0) return; void *newpos = malloc_fseg(p->size); if (!newpos) { warn_noalloc(); return; } dprintf(1, "Copying PIR from %p to %p\n", pos, newpos); memcpy(newpos, pos, p->size); PirAddr = newpos; }
void cdrom_prepboot(void) { if (!CONFIG_CDROM_EMU) return; if (!CDCount) return; if (create_bounce_buf() < 0) return; struct drive_s *drive_g = malloc_fseg(sizeof(*drive_g)); if (!drive_g) { warn_noalloc(); free(drive_g); return; } cdemu_drive_gf = drive_g; memset(drive_g, 0, sizeof(*drive_g)); drive_g->type = DTYPE_CDEMU; drive_g->blksize = DISK_SECTOR_SIZE; drive_g->sectors = (u64)-1; }
void copy_smbios(void *pos) { if (SMBiosAddr) return; struct smbios_entry_point *p = pos; if (memcmp(p->anchor_string, "_SM_", 4)) return; if (checksum(pos, 0x10) != 0) return; if (memcmp(p->intermediate_anchor_string, "_DMI_", 5)) return; if (checksum(pos+0x10, p->length-0x10) != 0) return; struct smbios_entry_point *newpos = malloc_fseg(p->length); if (!newpos) { warn_noalloc(); return; } dprintf(1, "Copying SMBIOS entry point from %p to %p\n", pos, newpos); memcpy(newpos, pos, p->length); SMBiosAddr = newpos; }
static void copy_mptable(void *pos) { struct mptable_floating_s *p = pos; if (p->signature != MPTABLE_SIGNATURE) return; if (!p->physaddr) return; if (checksum(pos, sizeof(*p)) != 0) return; u32 length = p->length * 16; u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length; struct mptable_floating_s *newpos = malloc_fseg(length + mpclength); if (!newpos) { warn_noalloc(); return; } dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos); memcpy(newpos, pos, length); newpos->physaddr = (u32)newpos + length; newpos->checksum -= checksum(newpos, sizeof(*newpos)); memcpy((void*)newpos + length, (void*)p->physaddr, mpclength); }
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 mptable_setup(void) { if (! CONFIG_MPTABLE) return; dprintf(3, "init MPTable\n"); // Config structure in temp area. struct mptable_config_s *config = malloc_tmp(32*1024); if (!config) { warn_noalloc(); return; } memset(config, 0, sizeof(*config)); config->signature = MPCONFIG_SIGNATURE; config->spec = 4; memcpy(config->oemid, BUILD_CPUNAME8, sizeof(config->oemid)); memcpy(config->productid, "0.1 ", sizeof(config->productid)); config->lapic = BUILD_APIC_ADDR; // Detect cpu info u32 cpuid_signature, ebx, ecx, cpuid_features; cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features); if (! cpuid_signature) { // Use default values. cpuid_signature = 0x600; cpuid_features = 0x201; } int pkgcpus = 1; if (cpuid_features & (1 << 28)) { /* Only populate the MPS tables with the first logical CPU in each package */ pkgcpus = (ebx >> 16) & 0xff; pkgcpus = 1 << (__fls(pkgcpus - 1) + 1); /* round up to power of 2 */ }
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; }
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; }
static void configure_ehci(void *data) { struct usb_ehci_s *cntl = data; // Allocate ram for schedule storage struct ehci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl)); struct ehci_qh *intr_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*intr_qh)); struct ehci_qh *async_qh = memalign_high(EHCI_QH_ALIGN, sizeof(*async_qh)); if (!fl || !intr_qh || !async_qh) { warn_noalloc(); goto fail; } // XXX - check for halted? // Reset the HC u32 cmd = readl(&cntl->regs->usbcmd); writel(&cntl->regs->usbcmd, (cmd & ~(CMD_ASE | CMD_PSE)) | CMD_HCRESET); u64 end = calc_future_tsc(250); for (;;) { cmd = readl(&cntl->regs->usbcmd); if (!(cmd & CMD_HCRESET)) break; if (check_tsc(end)) { warn_timeout(); goto fail; } yield(); } // Disable interrupts (just to be safe). writel(&cntl->regs->usbintr, 0); // Set schedule to point to primary intr queue head memset(intr_qh, 0, sizeof(*intr_qh)); intr_qh->next = EHCI_PTR_TERM; intr_qh->info2 = (0x01 << QH_SMASK_SHIFT); intr_qh->token = QTD_STS_HALT; intr_qh->qtd_next = intr_qh->alt_next = EHCI_PTR_TERM; int i; for (i=0; i<ARRAY_SIZE(fl->links); i++) fl->links[i] = (u32)intr_qh | EHCI_PTR_QH; writel(&cntl->regs->periodiclistbase, (u32)fl); // Set async list to point to primary async queue head memset(async_qh, 0, sizeof(*async_qh)); async_qh->next = (u32)async_qh | EHCI_PTR_QH; async_qh->info1 = QH_HEAD; async_qh->token = QTD_STS_HALT; async_qh->qtd_next = async_qh->alt_next = EHCI_PTR_TERM; cntl->async_qh = async_qh; writel(&cntl->regs->asynclistbase, (u32)async_qh); // Enable queues writel(&cntl->regs->usbcmd, cmd | CMD_ASE | CMD_PSE | CMD_RUN); // Set default of high speed for root hub. writel(&cntl->regs->configflag, 1); cntl->checkports = readl(&cntl->caps->hcsparams) & HCS_N_PORTS_MASK; // Find devices int count = check_ehci_ports(cntl); ehci_free_pipes(cntl); if (count) // Success return; // No devices found - shutdown and free controller. writel(&cntl->regs->usbcmd, cmd & ~CMD_RUN); msleep(4); // 2ms to stop reading memory - XXX fail: free(fl); free(intr_qh); free(async_qh); free(cntl); }
static struct usb_pipe * ehci_alloc_intr_pipe(struct usbdevice_s *usbdev , struct usb_endpoint_descriptor *epdesc) { struct usb_ehci_s *cntl = container_of( usbdev->hub->cntl, struct usb_ehci_s, usb); int frameexp = usb_getFrameExp(usbdev, epdesc); dprintf(7, "ehci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp); if (frameexp > 10) frameexp = 10; int maxpacket = epdesc->wMaxPacketSize; // Determine number of entries needed for 2 timer ticks. int ms = 1<<frameexp; int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms); struct ehci_pipe *pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); struct ehci_qtd *tds = memalign_low(EHCI_QTD_ALIGN, sizeof(*tds) * count); void *data = malloc_low(maxpacket * count); if (!pipe || !tds || !data) { warn_noalloc(); goto fail; } memset(pipe, 0, sizeof(*pipe)); ehci_desc2pipe(pipe, usbdev, epdesc); pipe->next_td = pipe->tds = tds; pipe->data = data; pipe->qh.qtd_next = (u32)tds; int i; for (i=0; i<count; i++) { struct ehci_qtd *td = &tds[i]; td->qtd_next = (i==count-1 ? (u32)tds : (u32)&td[1]); td->alt_next = EHCI_PTR_TERM; td->token = (ehci_explen(maxpacket) | QTD_STS_ACTIVE | QTD_PID_IN | ehci_maxerr(3)); td->buf[0] = (u32)data + maxpacket * i; } // Add to interrupt schedule. struct ehci_framelist *fl = (void*)readl(&cntl->regs->periodiclistbase); if (frameexp == 0) { // Add to existing interrupt entry. struct ehci_qh *intr_qh = (void*)(fl->links[0] & ~EHCI_PTR_BITS); pipe->qh.next = intr_qh->next; barrier(); intr_qh->next = (u32)&pipe->qh | EHCI_PTR_QH; } else { int startpos = 1<<(frameexp-1); pipe->qh.next = fl->links[startpos]; barrier(); for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms) fl->links[i] = (u32)&pipe->qh | EHCI_PTR_QH; } return &pipe->pipe; fail: free(pipe); free(tds); free(data); return NULL; }
int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs, unsigned *max_struct_size, char *end) { static u64 used_bitmap[4] = { 0 }; char *start = *p; int i; /* Check if we've already reported these tables */ if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f))) return 1; /* Don't introduce spurious end markers */ if (type == 127) return 0; for (i = qemu_cfg_smbios_entries(); i > 0; i--) { struct smbios_table table; struct smbios_structure_header *header = (void *)*p; int string; qemu_cfg_read((u8 *)&table, sizeof(struct smbios_header)); table.header.length -= sizeof(struct smbios_header); if (table.header.type != SMBIOS_TABLE_ENTRY) { qemu_cfg_skip(table.header.length); continue; } if (end - *p < sizeof(struct smbios_structure_header)) { warn_noalloc(); break; } qemu_cfg_read((u8 *)*p, sizeof(struct smbios_structure_header)); table.header.length -= sizeof(struct smbios_structure_header); if (header->type != type) { qemu_cfg_skip(table.header.length); continue; } *p += sizeof(struct smbios_structure_header); /* Entries end with a double NULL char, if there's a string at * the end (length is greater than formatted length), the string * terminator provides the first NULL. */ string = header->length < table.header.length + sizeof(struct smbios_structure_header); /* Read the rest and terminate the entry */ if (end - *p < table.header.length) { warn_noalloc(); *p -= sizeof(struct smbios_structure_header); continue; } qemu_cfg_read((u8 *)*p, table.header.length); *p += table.header.length; *((u8*)*p) = 0; (*p)++; if (!string) { *((u8*)*p) = 0; (*p)++; } (*nr_structs)++; if (*p - (char *)header > *max_struct_size) *max_struct_size = *p - (char *)header; } if (start != *p) { /* Mark that we've reported on this type */ used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f)); return 1; }