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 | 46 +++++++++++++++++++++++++++++----------------- include/hw/i386/smbios.h | 15 ++++++++++++--- 2 files changed, 41 insertions(+), 20 deletions(-)
diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index 382b75d..2f0755f 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -521,21 +521,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; @@ -543,6 +546,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]; @@ -555,13 +561,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 */ @@ -575,6 +581,11 @@ static void smbios_build_type_17_table(unsigned instance, ram_addr_t size) 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; } @@ -590,13 +601,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 */ diff --git a/include/hw/i386/smbios.h b/include/hw/i386/smbios.h index 9067139..4525c9b 100644 --- a/include/hw/i386/smbios.h +++ b/include/hw/i386/smbios.h @@ -127,7 +127,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; @@ -136,9 +136,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 (v2.3) */ +/* SMBIOS type 17 - Memory Device (v2.8) */ struct smbios_type_17 { struct smbios_structure_header header; uint16_t physical_memory_array_handle; @@ -157,15 +158,23 @@ struct smbios_type_17 { 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 */