Add new copy_smbios_30() function, that will be used to support SMBIOS 3.0 entry points.
The SMBIOS 3.0 entry point will be tracked in a separate SMBios30Addr variable, because both 2.1 and 3.0 entry points may exist at the same time.
Adjust the smbios_get_tables(), smbios_major_version(), and smbios_minor_version() helpers to use the SMBIOS 3.0 entry point if available.
Signed-off-by: Eduardo Habkost ehabkost@redhat.com --- src/std/smbios.h | 13 +++++++++++++ src/fw/biostables.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/src/std/smbios.h b/src/std/smbios.h index 17fdfed6..208440b1 100644 --- a/src/std/smbios.h +++ b/src/std/smbios.h @@ -25,6 +25,19 @@ struct smbios_21_entry_point { u8 smbios_bcd_revision; } PACKED;
+struct smbios_30_entry_point { + char signature[5]; + u8 checksum; + u8 length; + u8 smbios_major_version; + u8 smbios_minor_version; + u8 smbios_docrev; + u8 entry_point_revision; + u8 reserved; + u32 structure_table_max_size; + u64 structure_table_address; +} PACKED; + /* This goes at the beginning of every SMBIOS structure. */ struct smbios_structure_header { u8 type; diff --git a/src/fw/biostables.c b/src/fw/biostables.c index 91fe7470..b2c84a12 100644 --- a/src/fw/biostables.c +++ b/src/fw/biostables.c @@ -315,8 +315,36 @@ copy_smbios_21(void *pos) SMBios21Addr = copy_fseg_table("SMBIOS", pos, p->length); }
+static struct smbios_30_entry_point *SMBios30Addr; + +static int +valid_smbios_30_signature(struct smbios_30_entry_point *p) +{ + return !memcmp(p->signature, "_SM3_", 5); +} + +void +copy_smbios_30(void *pos) +{ + if (SMBios30Addr) + return; + struct smbios_30_entry_point *p = pos; + if (!valid_smbios_30_signature(p)) + return; + if (checksum(pos, p->length) != 0) + return; + SMBios30Addr = copy_fseg_table("SMBIOS 3.0", pos, p->length); +} + void *smbios_get_tables(u32 *length) { + if (SMBios30Addr) { + u32 addr32 = SMBios30Addr->structure_table_address; + if (addr32 == SMBios30Addr->structure_table_address) { + *length = SMBios30Addr->structure_table_max_size; + return (void *)addr32; + } + } if (SMBios21Addr) { *length = SMBios21Addr->structure_table_length; return (void *)SMBios21Addr->structure_table_address; @@ -327,7 +355,9 @@ void *smbios_get_tables(u32 *length) static int smbios_major_version(void) { - if (SMBios21Addr) + if (SMBios30Addr) + return SMBios30Addr->smbios_major_version; + else if (SMBios21Addr) return SMBios21Addr->smbios_major_version; else return 0; @@ -336,7 +366,9 @@ smbios_major_version(void) static int smbios_minor_version(void) { - if (SMBios21Addr) + if (SMBios30Addr) + return SMBios30Addr->smbios_minor_version; + else if (SMBios21Addr) return SMBios21Addr->smbios_minor_version; else return 0;