예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
파일: usb.c 프로젝트: jidongxiao/twinkvm
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();
}
예제 #4
0
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;
}
예제 #5
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);
}
예제 #6
0
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;
}
예제 #7
0
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;
}
예제 #8
0
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;
}
예제 #9
0
// 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;
}
예제 #10
0
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);
    }
}
예제 #11
0
파일: usb.c 프로젝트: vathpela/seabios
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;
}
예제 #12
0
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;
}
예제 #13
0
파일: block.c 프로젝트: ts468/seabios-tpm
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;
}
예제 #14
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;
}
예제 #15
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;
}
예제 #16
0
// 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;
}
예제 #17
0
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;
}
예제 #18
0
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();
}
예제 #19
0
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;
}
예제 #20
0
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;
}
예제 #21
0
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;
}
예제 #22
0
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;
}
예제 #23
0
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);
}
예제 #24
0
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);
}
예제 #25
0
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 */
    }
예제 #26
0
파일: bootsplash.c 프로젝트: cgvarela/fvm
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;
}
예제 #27
0
파일: bootsplash.c 프로젝트: Ruinland/PQEMU
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;
}
예제 #28
0
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);
}
예제 #29
0
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;
}
예제 #30
0
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;
    }