// format disk track static void disk_1305(struct bregs *regs, struct drive_s *drive_g) { debug_stub(regs); u16 nlc, nlh, nlspt; fillLCHS(drive_g, &nlc, &nlh, &nlspt); u8 num_sectors = regs->al; u8 head = regs->dh; if (head >= nlh || num_sectors == 0 || num_sectors > nlspt) { disk_ret(regs, DISK_RET_EPARAM); return; } struct disk_op_s dop; dop.drive_g = drive_g; dop.command = CMD_FORMAT; dop.lba = head; dop.count = num_sectors; dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx); int status = send_disk_op(&dop); disk_ret(regs, status); }
static void bda_init(void) { dprintf(3, "init bda\n"); struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0); memset(bda, 0, sizeof(*bda)); int esize = EBDA_SIZE_START; u16 ebda_seg = EBDA_SEGMENT_START; if (!CONFIG_MALLOC_UPPERMEMORY) ebda_seg = FLATPTR_TO_SEG(ALIGN_DOWN(SYMBOL(final_varlow_start), 1024) - EBDA_SIZE_START*1024); SET_BDA(ebda_seg, ebda_seg); SET_BDA(mem_size_kb, ebda_seg / (1024/16)); // Init ebda struct extended_bios_data_area_s *ebda = get_ebda_ptr(); memset(ebda, 0, sizeof(*ebda)); ebda->size = esize; e820_add((u32)ebda, BUILD_LOWRAM_END-(u32)ebda, E820_RESERVED); // Init extra stack StackPos = &ExtraStack[BUILD_EXTRA_STACK_SIZE] - SYMBOL(zonelow_base); }
// format disk track static void noinline disk_1305(struct bregs *regs, struct drive_s *drive_gf) { debug_stub(regs); struct chs_s chs = getLCHS(drive_gf); u16 nlc=chs.cylinder, nlh=chs.head, nls=chs.sector; u8 count = regs->al; u8 cylinder = regs->ch; u8 head = regs->dh; if (cylinder >= nlc || head >= nlh || count == 0 || count > nls) { disk_ret(regs, DISK_RET_EPARAM); return; } struct disk_op_s dop; dop.drive_gf = drive_gf; dop.command = CMD_FORMAT; dop.lba = (((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nls; dop.count = count; dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx); int status = send_disk_op(&dop); disk_ret(regs, status); }
/* Legacy16InitializeYourself */ static void handle_csm_0000(struct bregs *regs) { qemu_preinit(); dprintf(3, "Legacy16InitializeYourself table %04x:%04x\n", regs->es, regs->bx); csm_init_table = MAKE_FLATPTR(regs->es, regs->bx); dprintf(3, "BiosLessThan1MB %08x\n", csm_init_table->BiosLessThan1MB); dprintf(3, "HiPmmMemory %08x\n", csm_init_table->HiPmmMemory); dprintf(3, "HiPmmMemorySize %08x\n", csm_init_table->HiPmmMemorySizeInBytes); dprintf(3, "ReverseThunk %04x:%04x\n", csm_init_table->ReverseThunkCallSegment, csm_init_table->ReverseThunkCallOffset); dprintf(3, "NumE820Entries %08x\n", csm_init_table->NumberE820Entries); dprintf(3, "OsMemoryAbove1M %08x\n", csm_init_table->OsMemoryAbove1Mb); dprintf(3, "ThunkStart %08x\n", csm_init_table->ThunkStart); dprintf(3, "ThunkSize %08x\n", csm_init_table->ThunkSizeInBytes); dprintf(3, "LoPmmMemory %08x\n", csm_init_table->LowPmmMemory); dprintf(3, "LoPmmMemorySize %08x\n", csm_init_table->LowPmmMemorySizeInBytes); csm_malloc_preinit(csm_init_table->LowPmmMemory, csm_init_table->LowPmmMemorySizeInBytes, csm_init_table->HiPmmMemory, csm_init_table->HiPmmMemorySizeInBytes); reloc_preinit(csm_maininit, regs); }
/* Legacy16UpdateBbs */ static void handle_csm_0001(struct bregs *regs) { if (!CONFIG_BOOT) { regs->ax = 1; return; } dprintf(3, "Legacy16UpdateBbs table %04x:%04x\n", regs->es, regs->bx); csm_boot_table = MAKE_FLATPTR(regs->es, regs->bx); dprintf(3, "MajorVersion %04x\n", csm_boot_table->MajorVersion); dprintf(3, "MinorVersion %04x\n", csm_boot_table->MinorVersion); dprintf(3, "AcpiTable %08x\n", csm_boot_table->AcpiTable); dprintf(3, "SmbiosTable %08x\n", csm_boot_table->SmbiosTable); dprintf(3, "SmbiosTableLength %08x\n", csm_boot_table->SmbiosTableLength); // dprintf(3, "SioData %08x\n", csm_boot_table->SioData); dprintf(3, "DevicePathType %04x\n", csm_boot_table->DevicePathType); dprintf(3, "PciIrqMask %04x\n", csm_boot_table->PciIrqMask); dprintf(3, "NumberE820Entries %08x\n", csm_boot_table->NumberE820Entries); // dprintf(3, "HddInfo %08x\n", csm_boot_table->HddInfo); dprintf(3, "NumberBbsEntries %08x\n", csm_boot_table->NumberBbsEntries); dprintf(3, "BBsTable %08x\n", csm_boot_table->BbsTable); dprintf(3, "SmmTable %08x\n", csm_boot_table->SmmTable); dprintf(3, "OsMemoryAbove1Mb %08x\n", csm_boot_table->OsMemoryAbove1Mb); dprintf(3, "UnconventionalDeviceTable %08x\n", csm_boot_table->UnconventionalDeviceTable); regs->ax = 0; }
int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) { if (! CONFIG_USB_EHCI) return -1; struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe); dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n" , &pipe->qh, dir, data, datasize); // Allocate 4 tds on stack (with required alignment) u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1]; struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN); memset(tds, 0, sizeof(*tds) * STACKQTDS); barrier(); SET_LOWFLAT(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds)); u16 maxpacket = GET_LOWFLAT(pipe->pipe.maxpacket); int tdpos = 0; while (datasize) { struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; int ret = ehci_wait_td(pipe, td, 5000); if (ret) return -1; struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS) , &tds[tdpos % STACKQTDS]); int transfer = fillTDbuffer(td, maxpacket, data, datasize); td->qtd_next = (transfer==datasize ? EHCI_PTR_TERM : (u32)nexttd_fl); td->alt_next = EHCI_PTR_TERM; barrier(); td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3)); data += transfer; datasize -= transfer; } int i; for (i=0; i<STACKQTDS; i++) { struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS]; int ret = ehci_wait_td(pipe, td, 5000); if (ret) return -1; } return 0; }
static void init_bda(void) { dprintf(3, "init bda\n"); struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0); memset(bda, 0, sizeof(*bda)); int esize = EBDA_SIZE_START; SET_BDA(mem_size_kb, BUILD_LOWRAM_END/1024 - esize); u16 ebda_seg = EBDA_SEGMENT_START; SET_BDA(ebda_seg, ebda_seg); // Init ebda struct extended_bios_data_area_s *ebda = get_ebda_ptr(); memset(ebda, 0, sizeof(*ebda)); ebda->size = esize; add_e820((u32)MAKE_FLATPTR(ebda_seg, 0), GET_EBDA(ebda_seg, size) * 1024 , E820_RESERVED); // Init extra stack StackPos = (void*)(&ExtraStack[BUILD_EXTRA_STACK_SIZE] - datalow_base); }
int usb_poll_intr(struct usb_pipe *pipe_fl, void *data) { ASSERT16(); switch (GET_LOWFLAT(pipe_fl->type)) { default: case USB_TYPE_UHCI: return uhci_poll_intr(pipe_fl, data); case USB_TYPE_OHCI: return ohci_poll_intr(pipe_fl, data); case USB_TYPE_EHCI: return ehci_poll_intr(pipe_fl, data); case USB_TYPE_XHCI: ; return call32_params(xhci_poll_intr, pipe_fl , MAKE_FLATPTR(GET_SEG(SS), data), 0, -1); } }
int usb_poll_intr(struct usb_pipe *pipe_fl, void *data) { ASSERT16(); switch (GET_LOWFLAT(pipe_fl->type)) { default: case USB_TYPE_UHCI: return uhci_poll_intr(pipe_fl, data); case USB_TYPE_OHCI: return ohci_poll_intr(pipe_fl, data); case USB_TYPE_EHCI: return ehci_poll_intr(pipe_fl, data); case USB_TYPE_XHCI: ; extern void _cfunc32flat_xhci_poll_intr(void); return call32_params(_cfunc32flat_xhci_poll_intr, (u32)pipe_fl , (u32)MAKE_FLATPTR(GET_SEG(SS), (u32)data), 0, -1); } }
// Perform read/write/verify using old-style chs accesses static void basic_access(struct bregs *regs, struct drive_s *drive_g, u16 command) { struct disk_op_s dop; dop.drive_g = drive_g; dop.command = command; u8 count = regs->al; u16 cylinder = regs->ch | ((((u16)regs->cl) << 2) & 0x300); u16 sector = regs->cl & 0x3f; u16 head = regs->dh; if (count > 128 || count == 0 || sector == 0) { dprintf(1, "int13_harddisk: function %02x, parameter out of range!\n" , regs->ah); disk_ret(regs, DISK_RET_EPARAM); return; } dop.count = count; u16 nlc, nlh, nlspt; fillLCHS(drive_g, &nlc, &nlh, &nlspt); // sanity check on cyl heads, sec if (cylinder >= nlc || head >= nlh || sector > nlspt) { dprintf(1, "int13_harddisk: function %02x, parameters out of" " range %04x/%04x/%04x!\n" , regs->ah, cylinder, head, sector); disk_ret(regs, DISK_RET_EPARAM); return; } // translate lchs to lba dop.lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt) + (u32)sector - 1); dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx); int status = send_disk_op(&dop); regs->al = dop.count; disk_ret(regs, status); }
// Perform read/write/verify using old-style chs accesses static void noinline basic_access(struct bregs *regs, struct drive_s *drive_g, u16 command) { struct disk_op_s dop; dop.drive_g = drive_g; dop.command = command; u8 count = regs->al; u16 cylinder = regs->ch | ((((u16)regs->cl) << 2) & 0x300); u16 sector = regs->cl & 0x3f; u16 head = regs->dh; if (count > 128 || count == 0 || sector == 0) { warn_invalid(regs); disk_ret(regs, DISK_RET_EPARAM); return; } dop.count = count; u16 nlc, nlh, nlspt; fillLCHS(drive_g, &nlc, &nlh, &nlspt); // sanity check on cyl heads, sec if (cylinder >= nlc || head >= nlh || sector > nlspt) { warn_invalid(regs); disk_ret(regs, DISK_RET_EPARAM); return; } // translate lchs to lba dop.lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt) + (u32)sector - 1); dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx); int status = send_disk_op(&dop); regs->al = dop.count; disk_ret(regs, status); }
static void bda_init(void) { dprintf(3, "init bda\n"); struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0); memset(bda, 0, sizeof(*bda)); #if CONFIG_INT10_SERIAL_CONSOLE // set the default INT10 to serial console value #if CONFIG_CHECK_CMOS_SETTING_FOR_CONSOLE_ENABLE if (!cmos_serial_console_debug_level) SET_BDA(video_mode, UART_OUTPUT_DISABLED); else SET_BDA(video_mode, UART_OUTPUT_ENABLED); #else SET_BDA(video_mode, UART_OUTPUT_ENABLED); #endif #endif int esize = EBDA_SIZE_START; u16 ebda_seg = EBDA_SEGMENT_START; extern u8 final_varlow_start[]; if (!CONFIG_MALLOC_UPPERMEMORY) ebda_seg = FLATPTR_TO_SEG(ALIGN_DOWN((u32)final_varlow_start, 1024) - EBDA_SIZE_START*1024); SET_BDA(ebda_seg, ebda_seg); SET_BDA(mem_size_kb, ebda_seg / (1024/16)); // Init ebda struct extended_bios_data_area_s *ebda = get_ebda_ptr(); memset(ebda, 0, sizeof(*ebda)); ebda->size = esize; add_e820((u32)ebda, BUILD_LOWRAM_END-(u32)ebda, E820_RESERVED); // Init extra stack StackPos = (void*)(&ExtraStack[BUILD_EXTRA_STACK_SIZE] - zonelow_base); }
int cdrom_boot(struct drive_s *drive_g) { ASSERT32FLAT(); struct disk_op_s dop; int cdid = getDriveId(EXTTYPE_CD, drive_g); memset(&dop, 0, sizeof(dop)); dop.drive_g = drive_g; if (!dop.drive_g || cdid < 0) return 1; int ret = scsi_is_ready(&dop); if (ret) dprintf(1, "scsi_is_ready returned %d\n", ret); // Read the Boot Record Volume Descriptor u8 buffer[CDROM_SECTOR_SIZE]; dop.lba = 0x11; dop.count = 1; dop.buf_fl = buffer; ret = cdb_read(&dop); if (ret) return 3; // Validity checks if (buffer[0]) return 4; if (strcmp((char*)&buffer[1], "CD001\001EL TORITO SPECIFICATION") != 0) return 5; // ok, now we calculate the Boot catalog address u32 lba = *(u32*)&buffer[0x47]; // And we read the Boot Catalog dop.lba = lba; dop.count = 1; ret = cdb_read(&dop); if (ret) return 7; // Validation entry if (buffer[0x00] != 0x01) return 8; // Header if (buffer[0x01] != 0x00) return 9; // Platform if (buffer[0x1E] != 0x55) return 10; // key 1 if (buffer[0x1F] != 0xAA) return 10; // key 2 // Initial/Default Entry if (buffer[0x20] != 0x88) return 11; // Bootable u8 media = buffer[0x21]; CDEmu.media = media; CDEmu.emulated_drive_gf = dop.drive_g; u16 boot_segment = *(u16*)&buffer[0x22]; if (!boot_segment) boot_segment = 0x07C0; CDEmu.load_segment = boot_segment; CDEmu.buffer_segment = 0x0000; u16 nbsectors = *(u16*)&buffer[0x26]; CDEmu.sector_count = nbsectors; lba = *(u32*)&buffer[0x28]; CDEmu.ilba = lba; // And we read the image in memory dop.lba = lba; dop.count = DIV_ROUND_UP(nbsectors, 4); dop.buf_fl = MAKE_FLATPTR(boot_segment, 0); ret = cdb_read(&dop); if (ret) return 12; if (media == 0) { // No emulation requested - return success. CDEmu.emulated_extdrive = EXTSTART_CD + cdid; return 0; } // Emulation of a floppy/harddisk requested if (! CONFIG_CDROM_EMU || !cdemu_drive_gf) return 13; // Set emulated drive id and increase bios installed hardware // number of devices if (media < 4) { // Floppy emulation CDEmu.emulated_extdrive = 0x00; // XXX - get and set actual floppy count. set_equipment_flags(0x41, 0x41); switch (media) { case 0x01: // 1.2M floppy CDEmu.lchs.spt = 15; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; case 0x02: // 1.44M floppy CDEmu.lchs.spt = 18; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; case 0x03: // 2.88M floppy CDEmu.lchs.spt = 36; CDEmu.lchs.cylinders = 80; CDEmu.lchs.heads = 2; break; } } else { // Harddrive emulation CDEmu.emulated_extdrive = 0x80; SET_BDA(hdcount, GET_BDA(hdcount) + 1); // Peak at partition table to get chs. struct mbr_s *mbr = (void*)0; u8 sptcyl = GET_FARVAR(boot_segment, mbr->partitions[0].last.sptcyl); u8 cyllow = GET_FARVAR(boot_segment, mbr->partitions[0].last.cyllow); u8 heads = GET_FARVAR(boot_segment, mbr->partitions[0].last.heads); CDEmu.lchs.spt = sptcyl & 0x3f; CDEmu.lchs.cylinders = ((sptcyl<<2)&0x300) + cyllow + 1; CDEmu.lchs.heads = heads + 1; } // everything is ok, so from now on, the emulation is active CDEmu.active = 0x01; dprintf(6, "cdemu media=%d\n", media); return 0; }
/* PrepareToBoot */ static void handle_csm_0002(struct bregs *regs) { if (!CONFIG_BOOT) { regs->ax = 1; return; } dprintf(3, "PrepareToBoot table %04x:%04x\n", regs->es, regs->bx); struct e820entry *p = (void *)csm_compat_table.E820Pointer; int i; for (i=0; i < csm_compat_table.E820Length / sizeof(struct e820entry); i++) e820_add(p[i].start, p[i].size, p[i].type); if (csm_init_table->HiPmmMemorySizeInBytes > BUILD_MAX_HIGHTABLE) { u32 hi_pmm_end = csm_init_table->HiPmmMemory + csm_init_table->HiPmmMemorySizeInBytes; e820_add(hi_pmm_end - BUILD_MAX_HIGHTABLE, BUILD_MAX_HIGHTABLE, E820_RESERVED); } // For PCIBIOS 1ab10e if (csm_compat_table.IrqRoutingTablePointer && csm_compat_table.IrqRoutingTableLength) { PirAddr = (void *)csm_compat_table.IrqRoutingTablePointer; dprintf(3, "CSM PIRQ table at %p\n", PirAddr); } // For find_resume_vector()... and find_acpi_features() if (csm_rsdp.signature == RSDP_SIGNATURE) { RsdpAddr = &csm_rsdp; dprintf(3, "CSM ACPI RSDP at %p\n", RsdpAddr); find_acpi_features(); } // SMBIOS table needs to be copied into the f-seg // XX: OVMF doesn't seem to set SmbiosTableLength so don't check it if (csm_boot_table->SmbiosTable && !SMBiosAddr) copy_smbios((void *)csm_boot_table->SmbiosTable); // MPTABLE is just there; we don't care where. // EFI may have reinitialised the video using its *own* driver. enable_vga_console(); // EFI fills this in for us. Zero it for now... struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0); bda->hdcount = 0; thread_setup(); mathcp_setup(); timer_setup(); clock_setup(); device_hardware_setup(); wait_threads(); interactive_bootmenu(); prepareboot(); regs->ax = 0; }