summaryrefslogtreecommitdiffstats
path: root/qemu/roms/seabios/src/fw/biostables.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/seabios/src/fw/biostables.c')
-rw-r--r--qemu/roms/seabios/src/fw/biostables.c491
1 files changed, 0 insertions, 491 deletions
diff --git a/qemu/roms/seabios/src/fw/biostables.c b/qemu/roms/seabios/src/fw/biostables.c
deleted file mode 100644
index 9fb9ff9df..000000000
--- a/qemu/roms/seabios/src/fw/biostables.c
+++ /dev/null
@@ -1,491 +0,0 @@
-// Support for manipulating bios tables (pir, mptable, acpi, smbios).
-//
-// Copyright (C) 2008,2009 Kevin O'Connor <kevin@koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "byteorder.h" // le32_to_cpu
-#include "config.h" // CONFIG_*
-#include "hw/pci.h" // pci_config_writeb
-#include "malloc.h" // malloc_fseg
-#include "memmap.h" // SYMBOL
-#include "output.h" // dprintf
-#include "romfile.h" // romfile_find
-#include "std/acpi.h" // struct rsdp_descriptor
-#include "std/mptable.h" // MPTABLE_SIGNATURE
-#include "std/pirtable.h" // struct pir_header
-#include "std/smbios.h" // struct smbios_entry_point
-#include "string.h" // memcpy
-#include "util.h" // copy_table
-#include "x86.h" // outb
-
-struct pir_header *PirAddr VARFSEG;
-
-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
-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;
- if (length + mpclength > BUILD_MAX_MPTABLE_FSEG) {
- dprintf(1, "Skipping MPTABLE copy due to large size (%d bytes)\n"
- , length + mpclength);
- return;
- }
- // 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);
-}
-
-
-/****************************************************************
- * ACPI
- ****************************************************************/
-
-static int
-get_acpi_rsdp_length(void *pos, unsigned size)
-{
- struct rsdp_descriptor *p = pos;
- if (p->signature != RSDP_SIGNATURE)
- return -1;
- u32 length = 20;
- if (length > size)
- return -1;
- if (checksum(pos, length) != 0)
- return -1;
- if (p->revision > 1) {
- length = p->length;
- if (length > size)
- return -1;
- if (checksum(pos, length) != 0)
- return -1;
- }
- return length;
-}
-
-struct rsdp_descriptor *RsdpAddr;
-
-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 *find_acpi_rsdp(void)
-{
- unsigned long start = SYMBOL(zonefseg_start);
- unsigned long end = SYMBOL(zonefseg_end);
- unsigned long pos;
-
- for (pos = ALIGN(start, 0x10); pos <= ALIGN_DOWN(end, 0x10); pos += 0x10)
- if (get_acpi_rsdp_length((void *)pos, end - pos) >= 0)
- return (void *)pos;
-
- return NULL;
-}
-
-static struct fadt_descriptor_rev1 *
-find_fadt(void)
-{
- dprintf(4, "rsdp=%p\n", RsdpAddr);
- if (!RsdpAddr || RsdpAddr->signature != RSDP_SIGNATURE)
- return NULL;
- struct rsdt_descriptor_rev1 *rsdt = (void*)RsdpAddr->rsdt_physical_address;
- dprintf(4, "rsdt=%p\n", rsdt);
- if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
- return NULL;
- void *end = (void*)rsdt + rsdt->length;
- int i;
- for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
- struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[i];
- if (!fadt || fadt->signature != FACP_SIGNATURE)
- continue;
- dprintf(4, "fadt=%p\n", fadt);
- return fadt;
- }
- dprintf(4, "no fadt found\n");
- return NULL;
-}
-
-u32
-find_resume_vector(void)
-{
- struct fadt_descriptor_rev1 *fadt = find_fadt();
- if (!fadt)
- return 0;
- struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl;
- dprintf(4, "facs=%p\n", facs);
- if (! facs || facs->signature != FACS_SIGNATURE)
- return 0;
- // Found it.
- dprintf(4, "resume addr=%d\n", facs->firmware_waking_vector);
- return facs->firmware_waking_vector;
-}
-
-static struct acpi_20_generic_address acpi_reset_reg;
-static u8 acpi_reset_val;
-u32 acpi_pm1a_cnt VARFSEG;
-u16 acpi_pm_base = 0xb000;
-
-#define acpi_ga_to_bdf(addr) pci_to_bdf(0, (addr >> 32) & 0xffff, (addr >> 16) & 0xffff)
-
-void
-acpi_reboot(void)
-{
- // Check it passed the sanity checks in acpi_set_reset_reg() and was set
- if (acpi_reset_reg.register_bit_width != 8)
- return;
-
- u64 addr = le64_to_cpu(acpi_reset_reg.address);
-
- dprintf(1, "ACPI hard reset %d:%llx (%x)\n",
- acpi_reset_reg.address_space_id, addr, acpi_reset_val);
-
- switch (acpi_reset_reg.address_space_id) {
- case 0: // System Memory
- writeb((void *)(u32)addr, acpi_reset_val);
- break;
- case 1: // System I/O
- outb(acpi_reset_val, addr);
- break;
- case 2: // PCI config space
- pci_config_writeb(acpi_ga_to_bdf(addr), addr & 0xffff, acpi_reset_val);
- break;
- }
-}
-
-static void
-acpi_set_reset_reg(struct acpi_20_generic_address *reg, u8 val)
-{
- if (!reg || reg->address_space_id > 2 ||
- reg->register_bit_width != 8 || reg->register_bit_offset)
- return;
-
- acpi_reset_reg = *reg;
- acpi_reset_val = val;
-}
-
-void
-find_acpi_features(void)
-{
- struct fadt_descriptor_rev1 *fadt = find_fadt();
- if (!fadt)
- return;
- u32 pm_tmr = le32_to_cpu(fadt->pm_tmr_blk);
- u32 pm1a_cnt = le32_to_cpu(fadt->pm1a_cnt_blk);
- dprintf(4, "pm_tmr_blk=%x\n", pm_tmr);
- if (pm_tmr)
- pmtimer_setup(pm_tmr);
- if (pm1a_cnt)
- acpi_pm1a_cnt = pm1a_cnt;
-
- // Theoretically we should check the 'reset_reg_sup' flag, but Windows
- // doesn't and thus nobody seems to *set* it. If the table is large enough
- // to include it, let the sanity checks in acpi_set_reset_reg() suffice.
- if (fadt->length >= 129) {
- void *p = fadt;
- acpi_set_reset_reg(p + 116, *(u8 *)(p + 128));
- }
-}
-
-
-/****************************************************************
- * SMBIOS
- ****************************************************************/
-
-// Iterator for each sub-table in the smbios blob.
-void *
-smbios_next(struct smbios_entry_point *smbios, void *prev)
-{
- if (!smbios)
- return NULL;
- void *start = (void*)smbios->structure_table_address;
- void *end = start + smbios->structure_table_length;
-
- if (!prev) {
- prev = start;
- } else {
- struct smbios_structure_header *hdr = prev;
- if (prev + sizeof(*hdr) > end)
- return NULL;
- prev += hdr->length + 2;
- while (prev < end && (*(u8*)(prev-1) != '\0' || *(u8*)(prev-2) != '\0'))
- prev++;
- }
- struct smbios_structure_header *hdr = prev;
- if (prev >= end || prev + sizeof(*hdr) >= end || prev + hdr->length >= end)
- return NULL;
- return prev;
-}
-
-struct smbios_entry_point *SMBiosAddr;
-
-void
-copy_smbios(void *pos)
-{
- if (SMBiosAddr)
- return;
- struct smbios_entry_point *p = pos;
- if (p->signature != SMBIOS_SIGNATURE)
- 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;
-}
-
-void
-display_uuid(void)
-{
- struct smbios_type_1 *tbl = smbios_next(SMBiosAddr, NULL);
- int minlen = offsetof(struct smbios_type_1, uuid) + sizeof(tbl->uuid);
- for (; tbl; tbl = smbios_next(SMBiosAddr, tbl))
- if (tbl->header.type == 1 && tbl->header.length >= minlen) {
- u8 *uuid = tbl->uuid;
- u8 empty_uuid[sizeof(tbl->uuid)] = { 0 };
- if (memcmp(uuid, empty_uuid, sizeof(empty_uuid)) == 0)
- return;
-
- /*
- * According to SMBIOS v2.6 the first three fields are encoded in
- * little-endian format. Versions prior to v2.6 did not specify
- * the encoding, but we follow dmidecode and assume big-endian
- * encoding.
- */
- if (SMBiosAddr->smbios_major_version > 2 ||
- (SMBiosAddr->smbios_major_version == 2 &&
- SMBiosAddr->smbios_minor_version >= 6)) {
- printf("Machine UUID"
- " %02x%02x%02x%02x"
- "-%02x%02x"
- "-%02x%02x"
- "-%02x%02x"
- "-%02x%02x%02x%02x%02x%02x\n"
- , uuid[ 3], uuid[ 2], uuid[ 1], uuid[ 0]
- , uuid[ 5], uuid[ 4]
- , uuid[ 7], uuid[ 6]
- , uuid[ 8], uuid[ 9]
- , uuid[10], uuid[11], uuid[12]
- , uuid[13], uuid[14], uuid[15]);
- } else {
- printf("Machine UUID"
- " %02x%02x%02x%02x"
- "-%02x%02x"
- "-%02x%02x"
- "-%02x%02x"
- "-%02x%02x%02x%02x%02x%02x\n"
- , uuid[ 0], uuid[ 1], uuid[ 2], uuid[ 3]
- , uuid[ 4], uuid[ 5]
- , uuid[ 6], uuid[ 7]
- , uuid[ 8], uuid[ 9]
- , uuid[10], uuid[11], uuid[12]
- , uuid[13], uuid[14], uuid[15]);
- }
-
- return;
- }
-}
-
-#define set_str_field_or_skip(type, field, value) \
- do { \
- int size = (value != NULL) ? strlen(value) + 1 : 0; \
- if (size > 1) { \
- memcpy(end, value, size); \
- end += size; \
- p->field = ++str_index; \
- } else { \
- p->field = 0; \
- } \
- } while (0)
-
-static void *
-smbios_new_type_0(void *start,
- const char *vendor, const char *version, const char *date)
-{
- struct smbios_type_0 *p = (struct smbios_type_0 *)start;
- char *end = (char *)start + sizeof(struct smbios_type_0);
- int str_index = 0;
-
- p->header.type = 0;
- p->header.length = sizeof(struct smbios_type_0);
- p->header.handle = 0;
-
- set_str_field_or_skip(0, vendor_str, vendor);
- set_str_field_or_skip(0, bios_version_str, version);
- p->bios_starting_address_segment = 0xe800;
- set_str_field_or_skip(0, bios_release_date_str, date);
-
- p->bios_rom_size = 0; /* FIXME */
-
- /* BIOS characteristics not supported */
- memset(p->bios_characteristics, 0, 8);
- p->bios_characteristics[0] = 0x08;
-
- /* Enable targeted content distribution (needed for SVVP) */
- p->bios_characteristics_extension_bytes[0] = 0;
- p->bios_characteristics_extension_bytes[1] = 4;
-
- p->system_bios_major_release = 0;
- p->system_bios_minor_release = 0;
- p->embedded_controller_major_release = 0xFF;
- p->embedded_controller_minor_release = 0xFF;
-
- *end = 0;
- end++;
- if (!str_index) {
- *end = 0;
- end++;
- }
-
- return end;
-}
-
-#define BIOS_NAME "SeaBIOS"
-#define BIOS_DATE "04/01/2014"
-
-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;
-}
-
-void
-smbios_setup(void)
-{
- if (smbios_romfile_setup())
- return;
- smbios_legacy_setup();
-}
-
-void
-copy_table(void *pos)
-{
- copy_pir(pos);
- copy_mptable(pos);
- copy_acpi_rsdp(pos);
- copy_smbios(pos);
-}