This patch adds extended start/end address and extended size fields to each memory table type.
Signed-off-by: Gabriel Somlo somlo@cmu.edu --- hw/i386/smbios.c | 52 ++++++++++++++++++++++++++++++++---------------- include/hw/i386/smbios.h | 20 ++++++++++++++++--- 2 files changed, 52 insertions(+), 20 deletions(-)
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index 8b524a9..ebb25b1 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -498,21 +498,24 @@ static void smbios_build_type_4_table(unsigned instance) #define ONE_MB ((ram_addr_t)1 << 20) #define ONE_GB ((ram_addr_t)1 << 30)
+#define MAX_T16_STD_SZ 0x80000000 /* 2T in Kilobytes */ + static void smbios_build_type_16_table(unsigned dimm_cnt) { - ram_addr_t ram_size_kb = ram_size >> 10; + ram_addr_t size_kb;
SMBIOS_BUILD_TABLE_PRE(16, 0x1000, true); /* required */
t->location = 0x01; /* Other */ t->use = 0x03; /* System memory */ t->error_correction = 0x06; /* Multi-bit ECC (for Microsoft, per SeaBIOS) */ - /* if ram_size < 2T, use value in Kilobytes; 0x80000000 == 2T and over */ - t->maximum_capacity = (ram_size_kb < 0x80000000) ? ram_size_kb : 0x80000000; - if (t->maximum_capacity == 0x80000000) { - /* TODO: support smbios v2.7 extended capacity */ - fprintf(stderr, "qemu: warning: SMBIOS v2.7+ required for " - "ram_size >= 2T (%ld)\n", ram_size); + size_kb = QEMU_ALIGN_UP(ram_size, ONE_KB) / ONE_KB; + if (size_kb < MAX_T16_STD_SZ) { + t->maximum_capacity = size_kb; + t->extended_maximum_capacity = 0; + } else { + t->maximum_capacity = MAX_T16_STD_SZ; + t->extended_maximum_capacity = ram_size; } t->memory_error_information_handle = 0xFFFE; /* Not provided */ t->number_of_memory_devices = dimm_cnt; @@ -520,6 +523,9 @@ static void smbios_build_type_16_table(unsigned dimm_cnt) SMBIOS_BUILD_TABLE_POST; }
+#define MAX_T17_STD_SZ 0x7FFF /* (32G - 1M), in Megabytes */ +#define MAX_T18_EXT_SZ 0x80000000 /* in Megabytes */ + static void smbios_build_type_17_table(unsigned instance, ram_addr_t size) { char loc_str[128]; @@ -532,13 +538,13 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size) t->total_width = 0xFFFF; /* Unknown */ t->data_width = 0xFFFF; /* Unknown */ size_mb = QEMU_ALIGN_UP(size, ONE_MB) / ONE_MB; - if (size_mb < 0x7FFF) { + if (size_mb < MAX_T17_STD_SZ) { t->size = size_mb; + t->extended_size = 0; } else { - t->size = 0x7FFF; - /* TODO: support smbios v2.7 extended capacity */ - fprintf(stderr, "qemu: warning: SMBIOS v2.7+ required for " - "DIMM size >= 0x7FFF Mbytes (0x%lx)\n", size_mb); + assert(size_mb < MAX_T18_EXT_SZ); + t->size = MAX_T17_STD_SZ; + t->extended_size = size_mb; } t->form_factor = 0x09; /* DIMM */ t->device_set = 0; /* Not in a set */ @@ -547,6 +553,16 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size) SMBIOS_TABLE_SET_STR(17, bank_locator_str, type17.bank); t->memory_type = 0x07; /* RAM */ t->type_detail = 0x02; /* Other */ + t->speed = 0; /* Unknown */ + SMBIOS_TABLE_SET_STR(17, manufacturer_str, type17.manufacturer); + SMBIOS_TABLE_SET_STR(17, serial_number_str, type17.serial); + SMBIOS_TABLE_SET_STR(17, asset_tag_number_str, type17.asset); + SMBIOS_TABLE_SET_STR(17, part_number_str, type17.part); + t->attributes = 0; /* Unknown */ + t->configured_clock_speed = 0; /* Unknown */ + t->minimum_voltage = 0; /* Unknown */ + t->maximum_voltage = 0; /* Unknown */ + t->configured_voltage = 0; /* Unknown */
SMBIOS_BUILD_TABLE_POST; } @@ -562,13 +578,14 @@ static void smbios_build_type_19_table(unsigned instance, assert(end > start); start_kb = start / ONE_KB; end_kb = end / ONE_KB; - if (start_kb >= UINT32_MAX || end_kb >= UINT32_MAX) { - t->starting_address = t->ending_address = UINT32_MAX; - fprintf(stderr, "qemu: warning: SMBIOS v2.7+ required for " - "type19(start=%lx, size=%lx)\n", start, size); - } else { + if (start_kb < UINT32_MAX && end_kb < UINT32_MAX) { t->starting_address = start_kb; t->ending_address = end_kb; + t->extended_starting_address = t->extended_ending_address = 0; + } else { + t->starting_address = t->ending_address = UINT32_MAX; + t->extended_starting_address = start; + t->extended_ending_address = end; } t->memory_array_handle = 0x1000; /* Type 16 (Phys. Mem. Array) */ t->partition_width = 1; /* One device per row */ @@ -623,6 +640,7 @@ void smbios_set_defaults(const char *manufacturer, SMBIOS_SET_DEFAULT(type4.manufacturer, manufacturer); SMBIOS_SET_DEFAULT(type4.version, version); SMBIOS_SET_DEFAULT(type17.loc_pfx, "DIMM"); + SMBIOS_SET_DEFAULT(type17.manufacturer, manufacturer); }
static void smbios_entry_point_setup(void) diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h index 649c80c..096d12b 100644 --- a/include/hw/i386/smbios.h +++ b/include/hw/i386/smbios.h @@ -148,7 +148,7 @@ struct smbios_type_4 { uint16_t processor_family2; } QEMU_PACKED;
-/* SMBIOS type 16 - Physical Memory Array */ +/* SMBIOS type 16 - Physical Memory Array (v2.7) */ struct smbios_type_16 { struct smbios_structure_header header; uint8_t location; @@ -157,9 +157,10 @@ struct smbios_type_16 { uint32_t maximum_capacity; uint16_t memory_error_information_handle; uint16_t number_of_memory_devices; + uint64_t extended_maximum_capacity; } QEMU_PACKED;
-/* SMBIOS type 17 - Memory Device */ +/* SMBIOS type 17 - Memory Device (v2.8) */ struct smbios_type_17 { struct smbios_structure_header header; uint16_t physical_memory_array_handle; @@ -173,15 +174,28 @@ struct smbios_type_17 { uint8_t bank_locator_str; uint8_t memory_type; uint16_t type_detail; + uint16_t speed; + uint8_t manufacturer_str; + uint8_t serial_number_str; + uint8_t asset_tag_number_str; + uint8_t part_number_str; + uint8_t attributes; + uint32_t extended_size; + uint32_t configured_clock_speed; + uint32_t minimum_voltage; + uint32_t maximum_voltage; + uint32_t configured_voltage; } QEMU_PACKED;
-/* SMBIOS type 19 - Memory Array Mapped Address */ +/* SMBIOS type 19 - Memory Array Mapped Address (v2.7) */ struct smbios_type_19 { struct smbios_structure_header header; uint32_t starting_address; uint32_t ending_address; uint16_t memory_array_handle; uint8_t partition_width; + uint64_t extended_starting_address; + uint64_t extended_ending_address; } QEMU_PACKED;
/* SMBIOS type 32 - System Boot Information */