aboutsummaryrefslogtreecommitdiff
path: root/src/mainboard/emulation/qemu-i440fx/fw_cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainboard/emulation/qemu-i440fx/fw_cfg.c')
-rw-r--r--src/mainboard/emulation/qemu-i440fx/fw_cfg.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/mainboard/emulation/qemu-i440fx/fw_cfg.c b/src/mainboard/emulation/qemu-i440fx/fw_cfg.c
index 44256be442..242f218692 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();