[SeaBIOS] [QEMU v6 PATCH 17/17] SMBIOS: Update memory table types (16, 17, and 19) to smbios spec v2.8

Gabriel L. Somlo gsomlo at gmail.com
Mon Apr 14 22:55:11 CEST 2014


This patch adds extended start/end address and extended size fields
to each memory table type.

Signed-off-by: Gabriel Somlo <somlo at 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 */
-- 
1.9.0




More information about the SeaBIOS mailing list