Gerd Hoffmann (kraxel@redhat.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/8608
-gerrit
commit 68c7e659100c6247f2169df5766ba3f8d83b03b3 Author: Gerd Hoffmann kraxel@redhat.com Date: Wed Aug 27 11:25:13 2014 +0200
qemu: 2.1+ smbios tables support
Starting with version 2.1 qemu provides a full set of smbios tables for the virtual hardware emulated, except type 0 (bios information).
This patch adds support for loading those tables to coreboot. The code is used by both i440fx and q35.
Change-Id: Id034f0c214e8890194145a92f06354201dee7963 Signed-off-by: Gerd Hoffmann kraxel@redhat.com --- 3rdparty | 2 +- src/mainboard/emulation/qemu-i440fx/fw_cfg.c | 83 +++++++++++++++++++++++ src/mainboard/emulation/qemu-i440fx/fw_cfg.h | 1 + src/mainboard/emulation/qemu-i440fx/northbridge.c | 5 ++ 4 files changed, 90 insertions(+), 1 deletion(-)
diff --git a/3rdparty b/3rdparty index f42b78f..5eb7a9c 160000 --- a/3rdparty +++ b/3rdparty @@ -1 +1 @@ -Subproject commit f42b78f4f4df5ebc83f937f0dce4d348c9943a92 +Subproject commit 5eb7a9cf0897134f2fbe6d32b3b6e45b7981932f diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg.c b/src/mainboard/emulation/qemu-i440fx/fw_cfg.c index 44256be..242f218 100644 --- a/src/mainboard/emulation/qemu-i440fx/fw_cfg.c +++ b/src/mainboard/emulation/qemu-i440fx/fw_cfg.c @@ -362,6 +362,89 @@ static void fw_cfg_smbios_init(void) } }
+static unsigned long smbios_next(unsigned long current) +{ + struct smbios_type0 *t0; + int l, count = 0; + char *s; + + t0 = (void*)current; + current += t0->length; + for (;;) { + s = (void*)current; + l = strlen(s); + if (!l) + return current + (count ? 1 : 2); + current += l + 1; + count++; + } +} + +/* + * Starting with version 2.1 qemu provides a full set of smbios tables + * for the virtual hardware emulated, except type 0 (bios information). + * + * What we are going to do here is find the type0 table, keep it, and + * override everything else generated by coreboot with the qemu smbios + * tables. + * + * It's a bit hackish, but qemu is a special case (compared to real + * hardware) and this way we don't need special qemu support in the + * generic smbios code. + */ +unsigned long fw_cfg_smbios_tables(int *handle, unsigned long *current) +{ + struct smbios_type0 *t0; + unsigned long start, end; + int len, ret, i, count = 1; + char *str; + + len = fw_cfg_check_file("etc/smbios/smbios-tables"); + if (len < 0) + return 0; + printk(BIOS_DEBUG, "QEMU: found smbios tables in fw_cfg (len %d).\n", len); + + /* + * Search backwards for "coreboot" (first string in type0 table, + * see src/arch/x86/boot/smbios.c), then find type0 table. + */ + for (i = 0; i < 16384; i++) { + str = (char*)(*current - i); + if (strcmp(str, "coreboot") == 0) + break; + } + if (i == 16384) + return 0; + i += sizeof(struct smbios_type0) - 2; + t0 = (struct smbios_type0*)(*current - i); + if (t0->type != SMBIOS_BIOS_INFORMATION || t0->handle != 0) + return 0; + printk(BIOS_DEBUG, "QEMU: coreboot type0 table found at 0x%lx.\n", + *current - i); + start = smbios_next(*current - i); + + /* + * Fetch smbios tables from qemu, go find the end marker. + * We'll exclude the end marker as coreboot will add one. + */ + printk(BIOS_DEBUG, "QEMU: loading smbios tables to 0x%lx\n", start); + fw_cfg_load_file("etc/smbios/smbios-tables", (void*)start); + end = start; + do { + t0 = (struct smbios_type0*)end; + if (t0->type == SMBIOS_END_OF_TABLE) + break; + end = smbios_next(end); + count++; + } while (end < start + len); + + /* final fixups. */ + ret = end - *current; + *current = end; + *handle = count; + return ret; +} + const char *smbios_mainboard_manufacturer(void) { fw_cfg_smbios_init(); diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg.h b/src/mainboard/emulation/qemu-i440fx/fw_cfg.h index 2a10d8b..51ecaa8 100644 --- a/src/mainboard/emulation/qemu-i440fx/fw_cfg.h +++ b/src/mainboard/emulation/qemu-i440fx/fw_cfg.h @@ -19,3 +19,4 @@ void fw_cfg_get(int entry, void *dst, int dstlen); int fw_cfg_check_file(const char *name); void fw_cfg_load_file(const char *name, void *dst); int fw_cfg_max_cpus(void); +unsigned long fw_cfg_smbios_tables(int *handle, unsigned long *current); diff --git a/src/mainboard/emulation/qemu-i440fx/northbridge.c b/src/mainboard/emulation/qemu-i440fx/northbridge.c index 08d563f..f12a272 100644 --- a/src/mainboard/emulation/qemu-i440fx/northbridge.c +++ b/src/mainboard/emulation/qemu-i440fx/northbridge.c @@ -213,6 +213,11 @@ static int qemu_get_smbios_data17(int handle, int parent_handle, unsigned long * static int qemu_get_smbios_data(device_t dev, int *handle, unsigned long *current) { int len; + + len = fw_cfg_smbios_tables(handle, current); + if (len != 0) + return len; + len = qemu_get_smbios_data16(*handle, current); len += qemu_get_smbios_data17(*handle+1, *handle, current); *handle += 2;