summaryrefslogtreecommitdiff
path: root/src/arch/x86
diff options
context:
space:
mode:
authorMatt DeVillier <matt.devillier@gmail.com>2016-09-02 21:41:26 -0500
committerFelix Held <felix-coreboot@felixheld.de>2021-10-15 00:18:40 +0000
commitd1c1afdf574931eb15c7dec1094c6a9bc3ee60a7 (patch)
tree3279acfa885e238b1f2186d0219f6e2480d6ca93 /src/arch/x86
parent291294d137393bb1f4d59b388f287134943f2a95 (diff)
arch/x86/smbios: Add generation of type 20 table
If available, use data from MEMINFO CBMEM table and saved handles from type 17/19 tables to generate type 20 (Memory Device Mapped Address) SMBIOS table. Windows 10/11 and some other OSes use this table to report the total memory available on a given device. Change-Id: I2574d6209d973a8e7f112eb3ef61f5d26986e47b Signed-off-by: Matt DeVillier <matt.devillier@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/58271 Reviewed-by: Angel Pons <th3fanbus@gmail.com> Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/arch/x86')
-rw-r--r--src/arch/x86/smbios.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c
index e9c8f47a44..04f8717e72 100644
--- a/src/arch/x86/smbios.c
+++ b/src/arch/x86/smbios.c
@@ -1031,6 +1031,50 @@ static int smbios_write_type19(unsigned long *current, int *handle, int type16)
return len;
}
+static int smbios_write_type20_table(unsigned long *current, int *handle, u32 addr_start,
+ u32 addr_end, int type17_handle, int type19_handle)
+{
+ struct smbios_type20 *t = smbios_carve_table(*current, SMBIOS_MEMORY_DEVICE_MAPPED_ADDRESS,
+ sizeof(*t), *handle);
+
+ t->memory_device_handle = type17_handle;
+ t->memory_array_mapped_address_handle = type19_handle;
+ t->addr_start = addr_start;
+ t->addr_end = addr_end;
+ t->partition_row_pos = 0xff;
+ t->interleave_pos = 0xff;
+ t->interleave_depth = 0xff;
+
+ const int len = smbios_full_table_len(&t->header, t->eos);
+ *current += len;
+ *handle += 1;
+ return len;
+}
+
+static int smbios_write_type20(unsigned long *current, int *handle,
+ int type17_handle, int type19_handle)
+{
+ u32 start_addr = 0;
+ int totallen = 0;
+ int i;
+
+ struct memory_info *meminfo;
+ meminfo = cbmem_find(CBMEM_ID_MEMINFO);
+ if (meminfo == NULL)
+ return 0; /* can't find mem info in cbmem */
+
+ printk(BIOS_INFO, "Create SMBIOS type 20\n");
+ for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
+ struct dimm_info *dimm;
+ dimm = &meminfo->dimm[i];
+ u32 end_addr = start_addr + (dimm->dimm_size << 10) - 1;
+ totallen += smbios_write_type20_table(current, handle, start_addr, end_addr,
+ type17_handle, type19_handle);
+ start_addr = end_addr + 1;
+ }
+ return totallen;
+}
+
static int smbios_write_type32(unsigned long *current, int handle)
{
struct smbios_type32 *t = smbios_carve_table(*current, SMBIOS_SYSTEM_BOOT_INFORMATION,
@@ -1281,8 +1325,12 @@ unsigned long smbios_write_tables(unsigned long current)
const int type16 = handle;
update_max(len, max_struct_size, smbios_write_type16(&current, &handle));
+ const int type17 = handle;
update_max(len, max_struct_size, smbios_write_type17(&current, &handle, type16));
+ const int type19 = handle;
update_max(len, max_struct_size, smbios_write_type19(&current, &handle, type16));
+ update_max(len, max_struct_size,
+ smbios_write_type20(&current, &handle, type17, type19));
update_max(len, max_struct_size, smbios_write_type32(&current, handle++));
update_max(len, max_struct_size, smbios_walk_device_tree(all_devices,