Skip to content

Commit

Permalink
arch/x86/smbios: add generation of type 16/19/20 tables
Browse files Browse the repository at this point in the history
if available, use data from MEMINFO CBMEM table to generate
type 16/19/20 SBMBIOS tables

Change-Id: I2574d6209d973a8e7f112eb3ef61f5d26986e47b
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
  • Loading branch information
MrChromebox committed May 12, 2020
1 parent f8a9159 commit 3e93c4f
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 0 deletions.
115 changes: 115 additions & 0 deletions src/arch/x86/smbios.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
len += tmp; \
} while (0)

static int type16_table_handle = 0;
static int type17_table_handle = 0;
static int type19_table_handle = 0;

static u8 smbios_checksum(u8 *p, u32 length)
{
u8 ret = 0;
Expand Down Expand Up @@ -323,6 +327,7 @@ static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
t->size = 0x7fff;
t->extended_size = dimm->dimm_size & 0x7fffffff;
}
t->phys_memory_array_handle=type16_table_handle;
t->data_width = 8 * (1 << (dimm->bus_width & 0x7));
t->total_width = t->data_width + 8 * ((dimm->bus_width & 0x18) >> 3);

Expand Down Expand Up @@ -363,6 +368,8 @@ static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
t->memory_error_information_handle = 0xFFFE;
t->attributes = dimm->rank_per_dimm;
t->handle = *handle;
if (type17_table_handle == 0)
type17_table_handle = *handle;
*handle += 1;
t->length = sizeof(struct smbios_type17) - 2;
return t->length + smbios_string_table_len(t->eos);
Expand Down Expand Up @@ -953,6 +960,31 @@ static int smbios_write_type11(unsigned long *current, int *handle)
return len;
}

static int smbios_write_type16(unsigned long *current, int handle)
{
struct smbios_type16 *t = (struct smbios_type16 *)*current;
memset(t, 0, sizeof(struct smbios_type16));
int len = sizeof(struct smbios_type16);
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 16\n");
t->type = SMBIOS_PHYS_MEMORY_ARRAY;
t->location = 0x3; /* on mainboard */
t->use = 0x3; /* system memory */
t->memory_error_correction = 0x3; /* none */
t->maximum_capacity = 0x01000000; /* 16GB */
t->memory_error_information_handle = 0xFFFE; /* not provided */
t->number_of_memory_devices = meminfo->dimm_cnt;
t->handle = handle;
type16_table_handle = handle; /* save handle for use/reference in type19 table */
t->length = len - 2;
*current += len;
return len;
}

static int smbios_write_type17(unsigned long *current, int *handle)
{
int len = sizeof(struct smbios_type17);
Expand All @@ -976,6 +1008,82 @@ static int smbios_write_type17(unsigned long *current, int *handle)
return totallen;
}

static int smbios_write_type19(unsigned long *current, int handle)
{
struct smbios_type19 *t = (struct smbios_type19 *)*current;
memset(t, 0, sizeof(struct smbios_type19));
int len = sizeof(struct smbios_type19);
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 19\n");
t->type = SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS;
t->memory_array_handle = type16_table_handle;
t->phys_addr_start = 0;

for (i = 0; i < meminfo->dimm_cnt && i < ARRAY_SIZE(meminfo->dimm); i++) {
struct dimm_info *dimm;
dimm = &meminfo->dimm[i];
t->phys_addr_end += dimm->dimm_size;
}
t->phys_addr_end = (t->phys_addr_end << 10) - 1;
t->partition_width = meminfo->dimm_cnt;
t->handle = handle;
type19_table_handle = handle; /* save handle for use/reference in type20 table */
t->length = len - 2;
*current += len;
return len;
}

static int smbios_write_type20_table(unsigned long *current, int *handle, u32 addr_start, u32 addr_end)
{
struct smbios_type20 *t = (struct smbios_type20 *)*current;
memset(t, 0, sizeof(struct smbios_type20));
int len = sizeof(struct smbios_type20);

t->type = SMBIOS_MEMORY_DEVICE_MAPPED_ADDRESS;
t->memory_device_handle = type17_table_handle++;
t->memory_array_mapped_address_handle = type19_table_handle;
t->addr_start = addr_start;
t->addr_end = addr_end;
t->partition_row_pos = 0xFF;
t->interleave_pos = 0xFF;
t->interleave_depth = 0xFF;
t->handle = *handle;
*handle += 1;
t->length = len - 2;
return len;
}

static int smbios_write_type20(unsigned long *current, int *handle)
{
u32 start_addr = 0;
int len;
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;
len = smbios_write_type20_table(current, handle, start_addr, end_addr);
start_addr += (end_addr + 1);
*current += len;
totallen += len;
}
return totallen;
}

static int smbios_write_type32(unsigned long *current, int handle)
{
struct smbios_type32 *t = (struct smbios_type32 *)*current;
Expand Down Expand Up @@ -1191,8 +1299,14 @@ unsigned long smbios_write_tables(unsigned long current)
if (CONFIG(ELOG))
update_max(len, max_struct_size,
elog_smbios_write_type15(&current,handle++));
update_max(len, max_struct_size, smbios_write_type16(&current,
handle++));
update_max(len, max_struct_size, smbios_write_type17(&current,
&handle));
update_max(len, max_struct_size, smbios_write_type19(&current,
handle++));
update_max(len, max_struct_size, smbios_write_type20(&current,
&handle));
update_max(len, max_struct_size, smbios_write_type32(&current,
handle++));

Expand All @@ -1209,6 +1323,7 @@ unsigned long smbios_write_tables(unsigned long current)
se->minor_version = 8;
se->max_struct_size = max_struct_size;
se->struct_count = handle;
se->smbios_bcd_revision = 0x27;
memcpy(se->intermediate_anchor_string, "_DMI_", 5);

se->struct_table_address = (u32)tables;
Expand Down
30 changes: 30 additions & 0 deletions src/include/smbios.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ typedef enum {
SMBIOS_PHYS_MEMORY_ARRAY = 16,
SMBIOS_MEMORY_DEVICE = 17,
SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS = 19,
SMBIOS_MEMORY_DEVICE_MAPPED_ADDRESS = 20,
SMBIOS_SYSTEM_BOOT_INFORMATION = 32,
SMBIOS_IPMI_DEVICE_INFORMATION = 38,
SMBIOS_ONBOARD_DEVICES_EXTENDED_INFORMATION = 41,
Expand Down Expand Up @@ -709,6 +710,35 @@ struct smbios_type17 {
u8 eos[2];
} __packed;

struct smbios_type19 {
u8 type;
u8 length;
u16 handle;
u32 phys_addr_start;
u32 phys_addr_end;
u16 memory_array_handle;
u8 partition_width;
u64 ext_phys_addr_start;
u64 ext_phys_addr_end;
char eos[2];
} __attribute__((packed));

struct smbios_type20 {
u8 type;
u8 length;
u16 handle;
u32 addr_start;
u32 addr_end;
u16 memory_device_handle;
u16 memory_array_mapped_address_handle;
u8 partition_row_pos;
u8 interleave_pos;
u8 interleave_depth;
u64 ext_addr_start;
u64 ext_addr_end;
char eos [2];
} __attribute__((packed));

struct smbios_type32 {
u8 type;
u8 length;
Expand Down

0 comments on commit 3e93c4f

Please sign in to comment.