@@ -558,6 +558,23 @@ static void smbios_build_type_19_table(unsigned instance,
SMBIOS_BUILD_TABLE_POST;
}
+static void smbios_build_type_20_table(unsigned instance,
+ unsigned dev_hndl, unsigned array_hndl,
+ unsigned start_kb, unsigned size_kb)
+{
+ SMBIOS_BUILD_TABLE_PRE(20, 0x1400 + instance, true); /* required */
+
+ t->starting_address = start_kb;
+ t->ending_address = start_kb + size_kb - 1;
+ t->memory_device_handle = 0x1100 + dev_hndl; /* Type 17 (Memory Device) */
+ t->memory_array_mapped_address_handle = 0x1300 + array_hndl; /* Type 19 */
+ t->partition_row_position = 1; /* hardcoded in SeaBIOS */
+ t->interleave_position = 0; /* Not interleaved */
+ t->interleaved_data_depth = 0; /* Not interleaved */
+
+ SMBIOS_BUILD_TABLE_POST;
+}
+
#define SMBIOS_SET_DEFAULT(field, value) \
if (!field) { \
field = value; \
@@ -625,8 +642,20 @@ uint8_t *smbios_get_table(size_t *length)
smbios_build_type_17_table(i, size_mb);
}
smbios_build_type_19_table(0, 0, smbios_below_4g_ram >> 10);
+ smbios_build_type_20_table(0, 0, 0, 0, smbios_below_4g_ram >> 10);
if (smbios_above_4g_ram) {
+ uint32_t start_mb = 4096, size_mb, j;
smbios_build_type_19_table(1, 4 << 20, smbios_above_4g_ram >> 10);
+ for (j = 1, i = 0; i < memdev_count; i++, j++) {
+ size_mb = (i == memdev_count - 1) ?
+ ((ram_size_mb - 1) & 0x3FFF) + 1 : 0x4000;
+ if (i == 0) {
+ size_mb -= smbios_below_4g_ram >> 20;
+ }
+ smbios_build_type_20_table(j, i, 1,
+ start_mb << 10, size_mb << 10);
+ start_mb += size_mb;
+ }
}
smbios_validate_table();
smbios_immutable = true;