void mptable_init(void) { if (! CONFIG_MPTABLE) return; dprintf(3, "init MPTable\n"); // Allocate memory int length = (sizeof(struct mptable_config_s) + sizeof(struct mpt_cpu) * MaxCountCPUs + sizeof(struct mpt_bus) + sizeof(struct mpt_ioapic) + sizeof(struct mpt_intsrc) * 18); struct mptable_config_s *config = malloc_fseg(length); struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating)); if (!config || !floating) { dprintf(1, "No room for MPTABLE!\n"); free(config); free(floating); return; } /* floating pointer structure */ memset(floating, 0, sizeof(*floating)); floating->signature = MPTABLE_SIGNATURE; floating->physaddr = (u32)config; floating->length = 1; floating->spec_rev = 4; floating->checksum -= checksum(floating, sizeof(*floating)); // Config structure. memset(config, 0, sizeof(*config)); config->signature = MPCONFIG_SIGNATURE; config->spec = 4; memcpy(config->oemid, CONFIG_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); 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 */ }
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 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; }
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); }
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 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; }
void fw_cfg_setup(void) { int i, n; fw_cfg_select(FW_CFG_ID); version = fw_cfg_readl_le(); fw_cfg_select(FW_CFG_FILE_DIR); n = fw_cfg_readl_be(); filecnt = n; files = malloc_fseg(sizeof(files[0]) * n); fw_cfg_read(files, sizeof(files[0]) * n); for (i = 0; i < n; i++) { struct fw_cfg_file *f = &files[i]; f->size = bswap32(f->size); f->select = bswap16(f->select); } }
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 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; }