From: "Gabriel L. Somlo" <so...@cmu.edu> Build full smbios type 19 (memory array mapped address) tables, and make them available via fw_cfg
Signed-off-by: Gabriel Somlo <so...@cmu.edu> --- hw/i386/pc_piix.c | 3 ++- hw/i386/pc_q35.c | 3 ++- hw/i386/smbios.c | 27 ++++++++++++++++++++++++++- include/hw/i386/smbios.h | 4 +++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index ef2d062..5950d7f 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -146,7 +146,8 @@ static void pc_init1(QEMUMachineInitArgs *args, if (smbios_defaults) { /* These values are guest ABI, do not change */ smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", - args->machine->name); + args->machine->name, + below_4g_mem_size, above_4g_mem_size); } /* allocate ram and load rom/bios */ diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index dfcc252..482f466 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -133,7 +133,8 @@ static void pc_q35_init(QEMUMachineInitArgs *args) if (smbios_defaults) { /* These values are guest ABI, do not change */ smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", - args->machine->name); + args->machine->name, + below_4g_mem_size, above_4g_mem_size); } /* allocate ram and load rom/bios */ diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index 3c2a985..c9cd295 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -43,6 +43,7 @@ static int smbios_type4_count = 0; static bool smbios_immutable; static bool smbios_have_defaults; static uint32_t smbios_cpuid_version, smbios_cpuid_features; /* for type 4 */ +static ram_addr_t smbios_below_4g_ram, smbios_above_4g_ram; /* for type 19 */ static DECLARE_BITMAP(have_binfile_bitmap, SMBIOS_MAX_TYPE+1); static DECLARE_BITMAP(have_fields_bitmap, SMBIOS_MAX_TYPE+1); @@ -552,6 +553,19 @@ static void smbios_build_type_17_table(unsigned instance, unsigned size_mb) SMBIOS_BUILD_TABLE_POST; } +static void smbios_build_type_19_table(unsigned instance, + unsigned start_kb, unsigned size_kb) +{ + SMBIOS_BUILD_TABLE_PRE(19, 0x1300 + instance, true); /* required */ + + t->starting_address = start_kb; + t->ending_address = start_kb + size_kb - 1; + t->memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */ + t->partition_width = 1; /* hardcoded in SeaBIOS */ + + SMBIOS_BUILD_TABLE_POST; +} + #define SMBIOS_SET_DEFAULT(field, value) \ if (!field) { \ field = value; \ @@ -564,9 +578,16 @@ void smbios_set_cpuid(uint32_t version, uint32_t features) } void smbios_set_defaults(const char *manufacturer, - const char *product, const char *version) + const char *product, const char *version, + ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size) { smbios_have_defaults = true; + + assert(ram_size == below_4g_mem_size + above_4g_mem_size); + smbios_below_4g_ram = below_4g_mem_size; + smbios_above_4g_ram = above_4g_mem_size; + SMBIOS_SET_DEFAULT(type0.vendor, manufacturer); SMBIOS_SET_DEFAULT(type0.version, version); SMBIOS_SET_DEFAULT(type0.date, "01/01/2014"); @@ -607,6 +628,10 @@ uint8_t *smbios_get_table(size_t *length) ((ram_size_mb - 1) & 0x3FFF) + 1 : 0x4000; smbios_build_type_17_table(i, size_mb); } + smbios_build_type_19_table(0, 0, smbios_below_4g_ram >> 10); + if (smbios_above_4g_ram) { + smbios_build_type_19_table(1, 4 << 20, smbios_above_4g_ram >> 10); + } smbios_validate_table(); smbios_immutable = true; } diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h index bc05a5f..c20852a 100644 --- a/include/hw/i386/smbios.h +++ b/include/hw/i386/smbios.h @@ -20,7 +20,9 @@ void smbios_entry_add(QemuOpts *opts); void smbios_set_cpuid(uint32_t version, uint32_t features); void smbios_set_defaults(const char *manufacturer, - const char *product, const char *version); + const char *product, const char *version, + ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size); uint8_t *smbios_get_table(size_t *length); /* -- 1.8.1.4