From 58c638330ab15c8ee465fa61e40c66234f9e7909 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 31 Dec 2023 08:25:44 -0700 Subject: smbios: Refactor 32-bit code into an else statement In preparation for adding support for SMBIOS3 move this code into an else statement. There is no functional change. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/smbios.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) (limited to 'lib/smbios.c') diff --git a/lib/smbios.c b/lib/smbios.c index 45480b01af..b417f8a905 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -589,14 +589,6 @@ ulong write_smbios_table(ulong addr) len += tmp; } - memcpy(se->anchor, "_SM_", 4); - se->length = sizeof(struct smbios_entry); - se->major_ver = SMBIOS_MAJOR_VER; - se->minor_ver = SMBIOS_MINOR_VER; - se->max_struct_size = max_struct_size; - memcpy(se->intermediate_anchor, "_DMI_", 5); - se->struct_table_length = len; - /* * We must use a pointer here so things work correctly on sandbox. The * user of this table is not aware of the mapping of addresses to @@ -612,16 +604,28 @@ ulong write_smbios_table(ulong addr) (unsigned long long)table_addr); addr = 0; goto out; + } else { + memcpy(se->anchor, "_SM_", 4); + se->length = sizeof(struct smbios_entry); + se->major_ver = SMBIOS_MAJOR_VER; + se->minor_ver = SMBIOS_MINOR_VER; + se->max_struct_size = max_struct_size; + memcpy(se->intermediate_anchor, "_DMI_", 5); + se->struct_table_length = len; + + se->struct_table_address = table_addr; + + se->struct_count = handle; + + /* calculate checksums */ + istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET; + isize = sizeof(struct smbios_entry) - + SMBIOS_INTERMEDIATE_OFFSET; + se->intermediate_checksum = table_compute_checksum(istart, + isize); + se->checksum = table_compute_checksum(se, + sizeof(struct smbios_entry)); } - se->struct_table_address = table_addr; - - se->struct_count = handle; - - /* calculate checksums */ - istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET; - isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET; - se->intermediate_checksum = table_compute_checksum(istart, isize); - se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry)); out: unmap_sysmem(se); -- cgit v1.2.3 From f19cf8d43adb061f1e744447a4676322cd326829 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 31 Dec 2023 08:25:45 -0700 Subject: smbios: Move the rest of the SMBIOS2 code Move all of this logic into the else clause, since it will not be used for SMBIOS3 Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- lib/smbios.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'lib/smbios.c') diff --git a/lib/smbios.c b/lib/smbios.c index b417f8a905..eea72670bd 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -544,9 +544,8 @@ static struct smbios_write_method smbios_write_funcs[] = { ulong write_smbios_table(ulong addr) { ofnode parent_node = ofnode_null(); - struct smbios_entry *se; + ulong table_addr, start_addr; struct smbios_ctx ctx; - ulong table_addr; ulong tables; int len = 0; int max_struct_size = 0; @@ -566,9 +565,7 @@ ulong write_smbios_table(ulong addr) /* 16 byte align the table address */ addr = ALIGN(addr, 16); - - se = map_sysmem(addr, sizeof(struct smbios_entry)); - memset(se, 0, sizeof(struct smbios_entry)); + start_addr = addr; addr += sizeof(struct smbios_entry); addr = ALIGN(addr, 16); @@ -603,8 +600,11 @@ ulong write_smbios_table(ulong addr) printf("WARNING: SMBIOS table_address overflow %llx\n", (unsigned long long)table_addr); addr = 0; - goto out; } else { + struct smbios_entry *se; + + se = map_sysmem(start_addr, sizeof(struct smbios_entry)); + memset(se, '\0', sizeof(struct smbios_entry)); memcpy(se->anchor, "_SM_", 4); se->length = sizeof(struct smbios_entry); se->major_ver = SMBIOS_MAJOR_VER; @@ -625,9 +625,8 @@ ulong write_smbios_table(ulong addr) isize); se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry)); + unmap_sysmem(se); } -out: - unmap_sysmem(se); return addr; } -- cgit v1.2.3 From 70924294f375c351339f029b9615b52608e04cf4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 31 Dec 2023 08:25:47 -0700 Subject: smbios: Use SMBIOS 3.0 to support an address above 4GB When the SMBIOS table is written to an address above 4GB a 32-bit table address is not large enough. Use an SMBIOS3 table in that case. Note that we cannot use efi_allocate_pages() since this function has nothing to do with EFI. There is no equivalent function to allocate memory below 4GB in U-Boot. One solution would be to create a separate malloc() pool, or just always put the malloc() pool below 4GB. - Use log_debug() for warning - Rebase on Heinrich's smbios.h patch - Set the checksum for SMBIOS3 Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt --- include/smbios.h | 6 +++++- lib/smbios.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) (limited to 'lib/smbios.c') diff --git a/include/smbios.h b/include/smbios.h index e601283d29..77be58887a 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -12,7 +12,7 @@ /* SMBIOS spec version implemented */ #define SMBIOS_MAJOR_VER 3 -#define SMBIOS_MINOR_VER 0 +#define SMBIOS_MINOR_VER 7 enum { SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */ @@ -80,6 +80,10 @@ struct __packed smbios3_entry { u64 struct_table_address; }; +/* These two structures should use the same amount of 16-byte-aligned space */ +static_assert(ALIGN(16, sizeof(struct smbios_entry)) == + ALIGN(16, sizeof(struct smbios3_entry))); + /* BIOS characteristics */ #define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7) #define BIOS_CHARACTERISTICS_UPGRADEABLE (1 << 11) diff --git a/lib/smbios.c b/lib/smbios.c index eea72670bd..7f79d969c9 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -567,7 +567,11 @@ ulong write_smbios_table(ulong addr) addr = ALIGN(addr, 16); start_addr = addr; - addr += sizeof(struct smbios_entry); + /* + * So far we don't know which struct will be used, but they both end + * up using the same amount of 16-bit-aligned space + */ + addr += max(sizeof(struct smbios_entry), sizeof(struct smbios3_entry)); addr = ALIGN(addr, 16); tables = addr; @@ -590,16 +594,32 @@ ulong write_smbios_table(ulong addr) * We must use a pointer here so things work correctly on sandbox. The * user of this table is not aware of the mapping of addresses to * sandbox's DRAM buffer. + * + * Check the address of the end of the tables. If it is above 4GB then + * it is sensible to use SMBIOS3 even if the start of the table is below + * 4GB (this case is very unlikely to happen in practice) */ table_addr = (ulong)map_sysmem(tables, 0); - if (sizeof(table_addr) > sizeof(u32) && table_addr > (ulong)UINT_MAX) { + if (sizeof(table_addr) > sizeof(u32) && addr >= (ulong)UINT_MAX) { + struct smbios3_entry *se; /* * We need to put this >32-bit pointer into the table but the * field is only 32 bits wide. */ - printf("WARNING: SMBIOS table_address overflow %llx\n", - (unsigned long long)table_addr); - addr = 0; + log_debug("WARNING: Using SMBIOS3.0 due to table-address overflow %lx\n", + table_addr); + se = map_sysmem(start_addr, sizeof(struct smbios_entry)); + memset(se, '\0', sizeof(struct smbios_entry)); + memcpy(se->anchor, "_SM3_", 5); + se->length = sizeof(struct smbios3_entry); + se->major_ver = SMBIOS_MAJOR_VER; + se->minor_ver = SMBIOS_MINOR_VER; + se->doc_rev = 0; + se->entry_point_rev = 1; + se->max_struct_size = len; + se->struct_table_address = table_addr; + se->checksum = table_compute_checksum(se, + sizeof(struct smbios3_entry)); } else { struct smbios_entry *se; -- cgit v1.2.3 From 31f950a963a382d48193ecd79698f795b7603846 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 31 Dec 2023 08:25:50 -0700 Subject: smbios: Require the caller to align the SMBIOS table All callers handle this alignment, so drop the unnecessary code. This simplifies things a little. Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- include/smbios.h | 9 +++++---- lib/smbios.c | 2 -- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'lib/smbios.c') diff --git a/include/smbios.h b/include/smbios.h index 77be58887a..49de32fec2 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -258,12 +258,13 @@ static inline void fill_smbios_header(void *table, int type, * * This writes SMBIOS table at a given address. * - * @addr: start address to write SMBIOS table. If this is not - * 16-byte-aligned then it will be aligned before the table is - * written. + * @addr: start address to write SMBIOS table, 16-byte-alignment + * recommended. Note that while the SMBIOS tables themself have no alignment + * requirement, some systems may requires alignment. For example x86 systems + * which put tables at f0000 require 16-byte alignment + * * Return: end address of SMBIOS table (and start address for next entry) * or NULL in case of an error - * */ ulong write_smbios_table(ulong addr); diff --git a/lib/smbios.c b/lib/smbios.c index 7f79d969c9..cfd451e408 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -563,8 +563,6 @@ ulong write_smbios_table(ulong addr) ctx.dev = NULL; } - /* 16 byte align the table address */ - addr = ALIGN(addr, 16); start_addr = addr; /* -- cgit v1.2.3 From 1c5f6fa3883d18fbdaea53cae99e911748957bb0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 31 Dec 2023 08:25:51 -0700 Subject: smbios: Drop support for SMBIOS2 tables These tables are a pain since there is no way to handle memory above 4GB. Use SMBIOS3 always. This should hopefully not create problems on x86 devices, since SMBIOS3 was released seven years ago (2015). Signed-off-by: Simon Glass Reviewed-by: Heinrich Schuchardt Reviewed-by: Peter Robinson --- lib/smbios.c | 76 ++++++++++++++---------------------------------------------- 1 file changed, 17 insertions(+), 59 deletions(-) (limited to 'lib/smbios.c') diff --git a/lib/smbios.c b/lib/smbios.c index cfd451e408..d9d52bd58d 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -545,13 +545,12 @@ ulong write_smbios_table(ulong addr) { ofnode parent_node = ofnode_null(); ulong table_addr, start_addr; + struct smbios3_entry *se; struct smbios_ctx ctx; ulong tables; int len = 0; int max_struct_size = 0; int handle = 0; - char *istart; - int isize; int i; ctx.node = ofnode_null(); @@ -565,12 +564,8 @@ ulong write_smbios_table(ulong addr) start_addr = addr; - /* - * So far we don't know which struct will be used, but they both end - * up using the same amount of 16-bit-aligned space - */ - addr += max(sizeof(struct smbios_entry), sizeof(struct smbios3_entry)); - addr = ALIGN(addr, 16); + /* move past the (so-far-unwritten) header to start writing structs */ + addr = ALIGN(addr + sizeof(struct smbios3_entry), 16); tables = addr; /* populate minimum required tables */ @@ -592,59 +587,22 @@ ulong write_smbios_table(ulong addr) * We must use a pointer here so things work correctly on sandbox. The * user of this table is not aware of the mapping of addresses to * sandbox's DRAM buffer. - * - * Check the address of the end of the tables. If it is above 4GB then - * it is sensible to use SMBIOS3 even if the start of the table is below - * 4GB (this case is very unlikely to happen in practice) */ table_addr = (ulong)map_sysmem(tables, 0); - if (sizeof(table_addr) > sizeof(u32) && addr >= (ulong)UINT_MAX) { - struct smbios3_entry *se; - /* - * We need to put this >32-bit pointer into the table but the - * field is only 32 bits wide. - */ - log_debug("WARNING: Using SMBIOS3.0 due to table-address overflow %lx\n", - table_addr); - se = map_sysmem(start_addr, sizeof(struct smbios_entry)); - memset(se, '\0', sizeof(struct smbios_entry)); - memcpy(se->anchor, "_SM3_", 5); - se->length = sizeof(struct smbios3_entry); - se->major_ver = SMBIOS_MAJOR_VER; - se->minor_ver = SMBIOS_MINOR_VER; - se->doc_rev = 0; - se->entry_point_rev = 1; - se->max_struct_size = len; - se->struct_table_address = table_addr; - se->checksum = table_compute_checksum(se, - sizeof(struct smbios3_entry)); - } else { - struct smbios_entry *se; - - se = map_sysmem(start_addr, sizeof(struct smbios_entry)); - memset(se, '\0', sizeof(struct smbios_entry)); - memcpy(se->anchor, "_SM_", 4); - se->length = sizeof(struct smbios_entry); - se->major_ver = SMBIOS_MAJOR_VER; - se->minor_ver = SMBIOS_MINOR_VER; - se->max_struct_size = max_struct_size; - memcpy(se->intermediate_anchor, "_DMI_", 5); - se->struct_table_length = len; - - se->struct_table_address = table_addr; - - se->struct_count = handle; - - /* calculate checksums */ - istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET; - isize = sizeof(struct smbios_entry) - - SMBIOS_INTERMEDIATE_OFFSET; - se->intermediate_checksum = table_compute_checksum(istart, - isize); - se->checksum = table_compute_checksum(se, - sizeof(struct smbios_entry)); - unmap_sysmem(se); - } + + /* now go back and write the SMBIOS3 header */ + se = map_sysmem(start_addr, sizeof(struct smbios_entry)); + memset(se, '\0', sizeof(struct smbios_entry)); + memcpy(se->anchor, "_SM3_", 5); + se->length = sizeof(struct smbios3_entry); + se->major_ver = SMBIOS_MAJOR_VER; + se->minor_ver = SMBIOS_MINOR_VER; + se->doc_rev = 0; + se->entry_point_rev = 1; + se->max_struct_size = len; + se->struct_table_address = table_addr; + se->checksum = table_compute_checksum(se, sizeof(struct smbios3_entry)); + unmap_sysmem(se); return addr; } -- cgit v1.2.3