[PATCH v5 00/12] smbios: Deal with tables beyond 4GB

When the malloc() region extends beyond 4GB on ARM we may end up with an SMBIOS table in that region.
Add support for writing an SMBIOS3 table, which supports a 64-bit address.
Note that this problem does not happen on x86 since it requires the tables to be placed just below 1MB in memory, unless CONFIG_BLOBLIST_TABLES is enabled.
v5 drops support for SMBIOS2 tables as well. It also adds some changes to memory mapping which should allow an EFI app (launched from sandbox) to read the ACPI tables correctly.
Changes in v5: - Update comment to mention x86 alignment - Add new patch to drop support for SMBIOS2 tables - Add new patch to drop support for SMBIOS2 tables with EFI - Add new patch to rename test dm_test_setup_ctx_and_base_tables() - Add new patch to write pointers to tables instead of addresses - Add new patch to correct smbios-table installation
Changes in v4: - Bring in this patch from Heinrich's series - Check the start of the table rather than the end
Changes in v2: - Check the end of the table rather than the start. - Add a new patch to correct gd_smbios_start() - Add a note about why unmap_system() is called
Heinrich Schuchardt (1): smbios: SMBIOS 3.0 (64-bit) Entry Point structure
Simon Glass (11): smbios: Refactor 32-bit code into an else statement smbios: Move the rest of the SMBIOS2 code smbios: Use SMBIOS 3.0 to support an address above 4GB smbios: Correct gd_smbios_start() efi: Use the correct GUID for the SMBIOS table smbios: Require the caller to align the SMBIOS table smbios: Drop support for SMBIOS2 tables efi: smbios: Drop support for SMBIOS2 tables acpi: Rename test dm_test_setup_ctx_and_base_tables() acpi: Write pointers to tables instead of addresses efi: Correct smbios-table installation
arch/sandbox/include/asm/io.h | 16 +++++++++ arch/x86/lib/acpi_table.c | 6 ++-- cmd/acpi.c | 12 +++---- include/asm-generic/global_data.h | 2 +- include/efi_api.h | 4 +++ include/mapmem.h | 18 ++++++++++ include/smbios.h | 41 ++++++++++++++++++++--- lib/acpi/acpi.c | 12 +++---- lib/acpi/acpi_table.c | 4 +-- lib/acpi/base.c | 4 +-- lib/efi_loader/efi_smbios.c | 28 +++++++++------- lib/smbios.c | 55 ++++++++++--------------------- test/dm/acpi.c | 14 ++++---- 13 files changed, 134 insertions(+), 82 deletions(-)

In preparation for adding support for SMBIOS3 move this code into an else statement. There is no functional change.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v1)
lib/smbios.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index 45480b01af4..b417f8a9057 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);

In preparation for adding support for SMBIOS3 move this code into an else statement. There is no functional change.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v1)
lib/smbios.c | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-)
Applied to u-boot-dm/next, thanks!

Move all of this logic into the else clause, since it will not be used for SMBIOS3
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v1)
lib/smbios.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index b417f8a9057..eea72670bd9 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; }

Move all of this logic into the else clause, since it will not be used for SMBIOS3
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v1)
lib/smbios.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
Applied to u-boot-dm/next, thanks!

From: Heinrich Schuchardt heinrich.schuchardt@canonical.com
Add definition of the SMBIOS 3.0 (64-bit) Entry Point structure.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v4)
Changes in v4: - Bring in this patch from Heinrich's series
include/smbios.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
diff --git a/include/smbios.h b/include/smbios.h index c9df2706f5a..e601283d293 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -54,6 +54,32 @@ struct __packed smbios_entry { u8 bcd_rev; };
+/** + * struct smbios3_entry - SMBIOS 3.0 (64-bit) Entry Point structure + */ +struct __packed smbios3_entry { + /** @anchor: anchor string */ + u8 anchor[5]; + /** @checksum: checksum of the entry point structure */ + u8 checksum; + /** @length: length of the entry point structure */ + u8 length; + /** @major_ver: major version of the SMBIOS specification */ + u8 major_ver; + /** @minor_ver: minor version of the SMBIOS specification */ + u8 minor_ver; + /** @docrev: revision of the SMBIOS specification */ + u8 doc_rev; + /** @entry_point_rev: revision of the entry point structure */ + u8 entry_point_rev; + /** @reserved: reserved */ + u8 reserved; + /** maximum size of SMBIOS table */ + u32 max_struct_size; + /** @struct_table_address: 64-bit physical starting address */ + u64 struct_table_address; +}; + /* BIOS characteristics */ #define BIOS_CHARACTERISTICS_PCI_SUPPORTED (1 << 7) #define BIOS_CHARACTERISTICS_UPGRADEABLE (1 << 11)

From: Heinrich Schuchardt heinrich.schuchardt@canonical.com
Add definition of the SMBIOS 3.0 (64-bit) Entry Point structure.
Signed-off-by: Heinrich Schuchardt heinrich.schuchardt@canonical.com Reviewed-by: Simon Glass sjg@chromium.org Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org
Signed-off-by: Simon Glass sjg@chromium.org ---
(no changes since v4)
Changes in v4: - Bring in this patch from Heinrich's series
include/smbios.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+)
Applied to u-boot-dm/next, thanks!

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 sjg@chromium.org ---
(no changes since v4)
Changes in v4: - Check the start of the table rather than the end
Changes in v2: - Check the end of the table rather than the start.
include/smbios.h | 6 +++++- lib/smbios.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/include/smbios.h b/include/smbios.h index e601283d293..77be58887a2 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 eea72670bd9..7f79d969c92 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;

On 12/31/23 16:25, Simon Glass wrote:
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 sjg@chromium.org
(no changes since v4)
Changes in v4:
- Check the start of the table rather than the end
Changes in v2:
Check the end of the table rather than the start.
include/smbios.h | 6 +++++- lib/smbios.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/include/smbios.h b/include/smbios.h index e601283d293..77be58887a2 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 eea72670bd9..7f79d969c92 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
*/ table_addr = (ulong)map_sysmem(tables, 0);* 4GB (this case is very unlikely to happen in practice)
- if (sizeof(table_addr) > sizeof(u32) && table_addr > (ulong)UINT_MAX) {
- if (sizeof(table_addr) > sizeof(u32) && addr >= (ulong)UINT_MAX) {
All SMBIOS specifications since version 3.0.0, published 2015, allow using a SMBIOS3 anchor in all cases. SMBIOS_MAJOR_VER == 3.
Our target is to keep the code size small. Why do you increase the code size here?
Best regards
Heinrich
/*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,
} else { struct smbios_entry *se;sizeof(struct smbios3_entry));

On 12/31/23 17:11, Heinrich Schuchardt wrote:
On 12/31/23 16:25, Simon Glass wrote:
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 sjg@chromium.org
(no changes since v4)
Changes in v4:
- Check the start of the table rather than the end
Changes in v2:
- Check the end of the table rather than the start.
include/smbios.h | 6 +++++- lib/smbios.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/include/smbios.h b/include/smbios.h index e601283d293..77be58887a2 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 eea72670bd9..7f79d969c92 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) {
All SMBIOS specifications since version 3.0.0, published 2015, allow using a SMBIOS3 anchor in all cases. SMBIOS_MAJOR_VER == 3.
Our target is to keep the code size small. Why do you increase the code size here?
You drop SMBIOS2 in patch 8.
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
Best regards
Heinrich
+ 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;

On 12/31/23 16:25, Simon Glass wrote:
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 sjg@chromium.org
(no changes since v4)
Changes in v4:
- Check the start of the table rather than the end
Changes in v2:
Check the end of the table rather than the start.
include/smbios.h | 6 +++++- lib/smbios.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/include/smbios.h b/include/smbios.h index e601283d293..77be58887a2 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 */
I cannot see from where you take such a requirement. By chance it is fulfilled by the current definitions. If this a leftover from debugging we should remove it.
Best regards
Heinrich
+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 eea72670bd9..7f79d969c92 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
*/ table_addr = (ulong)map_sysmem(tables, 0);* 4GB (this case is very unlikely to happen in practice)
- 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,
} else { struct smbios_entry *se;sizeof(struct smbios3_entry));

Hi Heinrich,
On Mon, Jan 1, 2024 at 10:34 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12/31/23 16:25, Simon Glass wrote:
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 sjg@chromium.org
(no changes since v4)
Changes in v4:
- Check the start of the table rather than the end
Changes in v2:
Check the end of the table rather than the start.
include/smbios.h | 6 +++++- lib/smbios.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/include/smbios.h b/include/smbios.h index e601283d293..77be58887a2 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 */
I cannot see from where you take such a requirement. By chance it is fulfilled by the current definitions. If this a leftover from debugging we should remove it.
Oh, I just assumed it was a requirement, perhaps. Yes we can remove this, if you like. In fact perhaps we should remove all SMBIOS2 stuff as a follow-up?
Regards, Simon

Hi Heinrich,
On Mon, Jan 1, 2024 at 10:34 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12/31/23 16:25, Simon Glass wrote:
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 sjg@chromium.org
(no changes since v4)
Changes in v4:
- Check the start of the table rather than the end
Changes in v2:
Check the end of the table rather than the start.
include/smbios.h | 6 +++++- lib/smbios.c | 30 +++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-)
Applied to u-boot-dm/next, thanks!

This should access arch-specific properties. Fix it and update the existing usage.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v2)
Changes in v2: - Add a new patch to correct gd_smbios_start()
include/asm-generic/global_data.h | 2 +- lib/efi_loader/efi_smbios.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 99bde9ec7e4..fcc3c6e14ca 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -553,7 +553,7 @@ static_assert(sizeof(struct global_data) == GD_SIZE); #endif
#ifdef CONFIG_SMBIOS -#define gd_smbios_start() gd->smbios_start +#define gd_smbios_start() gd->arch.smbios_start #define gd_set_smbios_start(addr) gd->arch.smbios_start = addr #else #define gd_smbios_start() 0UL diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index bbb8421ce14..49adc87e45a 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -28,7 +28,7 @@ efi_status_t efi_smbios_register(void) ulong addr; efi_status_t ret;
- addr = gd->arch.smbios_start; + addr = gd_smbios_start(); if (!addr) { log_err("No SMBIOS tables to install\n"); return EFI_NOT_FOUND;

This should access arch-specific properties. Fix it and update the existing usage.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v2)
Changes in v2: - Add a new patch to correct gd_smbios_start()
include/asm-generic/global_data.h | 2 +- lib/efi_loader/efi_smbios.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next, thanks!

EFI does not use the 'anchor string' to determine the SMBIOS table version, instead preferring to have two separate GUIDs. Use the correct one, depending on the table version.
Call unmap_system() to balance to the use of map_sysmem()
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v2)
Changes in v2: - Add a note about why unmap_system() is called
include/efi_api.h | 4 ++++ lib/efi_loader/efi_smbios.c | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/include/efi_api.h b/include/efi_api.h index 0e92cb8a7f6..ab40b1b5ddf 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -433,6 +433,10 @@ struct efi_runtime_services { EFI_GUID(0xeb9d2d31, 0x2d88, 0x11d3, \ 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+#define SMBIOS3_TABLE_GUID \ + EFI_GUID(0xf2fd1544, 0x9794, 0x4a2c, \ + 0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94) + #define EFI_LOAD_FILE_PROTOCOL_GUID \ EFI_GUID(0x56ec3091, 0x954c, 0x11d2, \ 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index 49adc87e45a..5cbce6dc4eb 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -14,6 +14,8 @@ #include <smbios.h> #include <linux/sizes.h>
+const efi_guid_t smbios3_guid = SMBIOS3_TABLE_GUID; + enum { TABLE_SIZE = SZ_4K, }; @@ -25,8 +27,10 @@ enum { */ efi_status_t efi_smbios_register(void) { + const efi_guid_t *guid; ulong addr; efi_status_t ret; + void *buf;
addr = gd_smbios_start(); if (!addr) { @@ -42,8 +46,12 @@ efi_status_t efi_smbios_register(void) log_debug("EFI using SMBIOS tables at %lx\n", addr);
/* Install SMBIOS information as configuration table */ - return efi_install_configuration_table(&smbios_guid, - map_sysmem(addr, 0)); + buf = map_sysmem(addr, 0); + guid = !memcmp(buf, "_SM_", 4) ? &smbios_guid : &smbios3_guid; + ret = efi_install_configuration_table(guid, buf); + unmap_sysmem(buf); + + return ret; }
static int install_smbios_table(void)

EFI does not use the 'anchor string' to determine the SMBIOS table version, instead preferring to have two separate GUIDs. Use the correct one, depending on the table version.
Call unmap_system() to balance to the use of map_sysmem()
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
(no changes since v2)
Changes in v2: - Add a note about why unmap_system() is called
include/efi_api.h | 4 ++++ lib/efi_loader/efi_smbios.c | 12 ++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next, thanks!

All callers handle this alignment, so drop the unnecessary code. This simplifies things a little.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
Changes in v5: - Update comment to mention x86 alignment
include/smbios.h | 9 +++++---- lib/smbios.c | 2 -- 2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/include/smbios.h b/include/smbios.h index 77be58887a2..49de32fec2d 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 7f79d969c92..cfd451e4088 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;
/*

All callers handle this alignment, so drop the unnecessary code. This simplifies things a little.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de Reviewed-by: Ilias Apalodimas ilias.apalodimas@linaro.org ---
Changes in v5: - Update comment to mention x86 alignment
include/smbios.h | 9 +++++---- lib/smbios.c | 2 -- 2 files changed, 5 insertions(+), 6 deletions(-)
Applied to u-boot-dm/next, thanks!

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 sjg@chromium.org ---
Changes in v5: - Add new patch to drop support for SMBIOS2 tables
lib/smbios.c | 76 ++++++++++++---------------------------------------- 1 file changed, 17 insertions(+), 59 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index cfd451e4088..d9d52bd58d7 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; }

On 12/31/23 16:25, Simon Glass wrote:
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 sjg@chromium.org
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
Changes in v5:
Add new patch to drop support for SMBIOS2 tables
lib/smbios.c | 76 ++++++++++++---------------------------------------- 1 file changed, 17 insertions(+), 59 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index cfd451e4088..d9d52bd58d7 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
*/ table_addr = (ulong)map_sysmem(tables, 0);* 4GB (this case is very unlikely to happen in practice)
- 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; }

On Sun, Dec 31, 2023 at 3:26 PM Simon Glass sjg@chromium.org wrote:
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 sjg@chromium.org
Reviewed-by: Peter Robinson pbrobinson@gmail.com
It's also worth noting here the aarch64 Server Base Boot Requirements (SBBR) has required SMBIOS v3 since version 1.0 of the spec [1].
[1] https://documentation-service.arm.com/static/5fb7e5adca04df4095c1d64d
Changes in v5:
- Add new patch to drop support for SMBIOS2 tables
lib/smbios.c | 76 ++++++++++++---------------------------------------- 1 file changed, 17 insertions(+), 59 deletions(-)
diff --git a/lib/smbios.c b/lib/smbios.c index cfd451e4088..d9d52bd58d7 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;
}
2.34.1

On Sun, Dec 31, 2023 at 3:26 PM Simon Glass sjg@chromium.org wrote:
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 sjg@chromium.org
Reviewed-by: Peter Robinson pbrobinson@gmail.com
It's also worth noting here the aarch64 Server Base Boot Requirements (SBBR) has required SMBIOS v3 since version 1.0 of the spec [1].
[1] https://documentation-service.arm.com/static/5fb7e5adca04df4095c1d64d
Changes in v5:
- Add new patch to drop support for SMBIOS2 tables
lib/smbios.c | 76 ++++++++++++---------------------------------------- 1 file changed, 17 insertions(+), 59 deletions(-)
Applied to u-boot-dm/next, thanks!

Only the v3 table is supported now, so always use this when installing the EFI table.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v5: - Add new patch to drop support for SMBIOS2 tables with EFI
lib/efi_loader/efi_smbios.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index 5cbce6dc4eb..5db342ee0d7 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -27,7 +27,6 @@ enum { */ efi_status_t efi_smbios_register(void) { - const efi_guid_t *guid; ulong addr; efi_status_t ret; void *buf; @@ -47,8 +46,7 @@ efi_status_t efi_smbios_register(void)
/* Install SMBIOS information as configuration table */ buf = map_sysmem(addr, 0); - guid = !memcmp(buf, "_SM_", 4) ? &smbios_guid : &smbios3_guid; - ret = efi_install_configuration_table(guid, buf); + ret = efi_install_configuration_table(&smbios3_guid, buf); unmap_sysmem(buf);
return ret;

On 12/31/23 16:25, Simon Glass wrote:
Only the v3 table is supported now, so always use this when installing the EFI table.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
Changes in v5:
Add new patch to drop support for SMBIOS2 tables with EFI
lib/efi_loader/efi_smbios.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index 5cbce6dc4eb..5db342ee0d7 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -27,7 +27,6 @@ enum { */ efi_status_t efi_smbios_register(void) {
- const efi_guid_t *guid; ulong addr; efi_status_t ret; void *buf;
@@ -47,8 +46,7 @@ efi_status_t efi_smbios_register(void)
/* Install SMBIOS information as configuration table */ buf = map_sysmem(addr, 0);
- guid = !memcmp(buf, "_SM_", 4) ? &smbios_guid : &smbios3_guid;
- ret = efi_install_configuration_table(guid, buf);
ret = efi_install_configuration_table(&smbios3_guid, buf); unmap_sysmem(buf);
return ret;

On 12/31/23 16:25, Simon Glass wrote:
Only the v3 table is supported now, so always use this when installing the EFI table.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
Changes in v5:
Add new patch to drop support for SMBIOS2 tables with EFI
lib/efi_loader/efi_smbios.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
Applied to u-boot-dm/next, thanks!

Use the word 'acpi' in this test so that it runs along with all the other ACPI tests.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v5: - Add new patch to rename test dm_test_setup_ctx_and_base_tables()
test/dm/acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/dm/acpi.c b/test/dm/acpi.c index fb071902b45..1211e2f0e7f 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -330,7 +330,7 @@ static int dm_test_acpi_basic(struct unit_test_state *uts) DM_TEST(dm_test_acpi_basic, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test setup_ctx_and_base_tables */ -static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts) +static int dm_test_acpi_ctx_and_base_tables(struct unit_test_state *uts) { struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; @@ -376,7 +376,7 @@ static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts)
return 0; } -DM_TEST(dm_test_setup_ctx_and_base_tables, +DM_TEST(dm_test_acpi_ctx_and_base_tables, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test 'acpi list' command */

Am 31. Dezember 2023 16:25:53 MEZ schrieb Simon Glass sjg@chromium.org:
Use the word 'acpi' in this test so that it runs along with all the other ACPI tests.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
Changes in v5:
- Add new patch to rename test dm_test_setup_ctx_and_base_tables()
test/dm/acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/dm/acpi.c b/test/dm/acpi.c index fb071902b45..1211e2f0e7f 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -330,7 +330,7 @@ static int dm_test_acpi_basic(struct unit_test_state *uts) DM_TEST(dm_test_acpi_basic, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test setup_ctx_and_base_tables */ -static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts) +static int dm_test_acpi_ctx_and_base_tables(struct unit_test_state *uts) { struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; @@ -376,7 +376,7 @@ static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts)
return 0; } -DM_TEST(dm_test_setup_ctx_and_base_tables, +DM_TEST(dm_test_acpi_ctx_and_base_tables, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test 'acpi list' command */

Am 31. Dezember 2023 16:25:53 MEZ schrieb Simon Glass sjg@chromium.org:
Use the word 'acpi' in this test so that it runs along with all the other ACPI tests.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Heinrich Schuchardt xypron.glpk@gmx.de
Changes in v5:
- Add new patch to rename test dm_test_setup_ctx_and_base_tables()
test/dm/acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next, thanks!

Sandbox uses an API to map between addresses and pointers. This allows it to have (emulated) memory at zero and avoid arch-specific addressing details. It also allows memory-mapped peripherals to work.
As an example, on many machines sandbox maps address 100 to pointer value 10000000.
However this is not correct for ACPI, if sandbox starts another program (e.g EFI app) and passes it the tables. That app has no knowledge of sandbox's address mapping. So to make this work we want to store 10000000 as the value in the table.
Add two new 'nomap' functions which clearly make this exeption to how sandbox works.
This should allow EFI apps to access ACPI tables with sandbox, e.g. for testing purposes.
Signed-off-by: Simon Glass sjg@chromium.org Suggested-by: Heinrich Schuchardt xypron.glpk@gmx.de ---
Changes in v5: - Add new patch to write pointers to tables instead of addresses
arch/sandbox/include/asm/io.h | 16 ++++++++++++++++ arch/x86/lib/acpi_table.c | 6 +++--- cmd/acpi.c | 12 ++++++------ include/mapmem.h | 18 ++++++++++++++++++ lib/acpi/acpi.c | 12 ++++++------ lib/acpi/acpi_table.c | 4 ++-- lib/acpi/base.c | 4 ++-- test/dm/acpi.c | 10 +++++----- 8 files changed, 58 insertions(+), 24 deletions(-)
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index 3c0a102697e..a23bd64994a 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -231,5 +231,21 @@ static inline void unmap_sysmem(const void *vaddr) unmap_physmem(vaddr, MAP_WRBACK); }
+/** + * nomap_sysmem() - pass through an address unchanged + * + * This is used to indicate an address which should NOT be mapped, e.g. in + * SMBIOS tables. Using this function instead of a case shows that the sandbox + * conversion has been done + */ +static inline void *nomap_sysmem(phys_addr_t paddr, unsigned long len) +{ + return (void *)(uintptr_t)paddr; +} + +static inline phys_addr_t nomap_to_sysmem(const void *ptr) +{ + return (phys_addr_t)(uintptr_t)ptr; +}
#endif diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index c5b33dc65de..b366e44e337 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -197,7 +197,7 @@ int acpi_write_tcpa(struct acpi_ctx *ctx, const struct acpi_writer *entry)
tcpa->platform_class = 0; tcpa->laml = size; - tcpa->lasa = map_to_sysmem(log); + tcpa->lasa = nomap_to_sysmem(log);
/* (Re)calculate length and checksum */ current = (u32)tcpa + sizeof(struct acpi_tcpa); @@ -268,7 +268,7 @@ static int acpi_write_tpm2(struct acpi_ctx *ctx,
/* Fill the log area size and start address fields. */ tpm2->laml = tpm2_log_len; - tpm2->lasa = map_to_sysmem(lasa); + tpm2->lasa = nomap_to_sysmem(lasa);
/* Calculate checksum. */ header->checksum = table_compute_checksum(tpm2, header->length); @@ -430,7 +430,7 @@ int acpi_write_gnvs(struct acpi_ctx *ctx, const struct acpi_writer *entry) u32 *gnvs = (u32 *)((u32)ctx->dsdt + i);
if (*gnvs == ACPI_GNVS_ADDR) { - *gnvs = map_to_sysmem(ctx->current); + *gnvs = nomap_to_sysmem(ctx->current); log_debug("Fix up global NVS in DSDT to %#08x\n", *gnvs); break; diff --git a/cmd/acpi.c b/cmd/acpi.c index 0c144092420..79e9335b5db 100644 --- a/cmd/acpi.c +++ b/cmd/acpi.c @@ -45,7 +45,7 @@ static int dump_table_name(const char *sig) if (!hdr) return -ENOENT; printf("%.*s @ %16lx\n", ACPI_NAME_LEN, hdr->signature, - (ulong)map_to_sysmem(hdr)); + (ulong)nomap_to_sysmem(hdr)); print_buffer(0, hdr, 1, hdr->length, 0);
return 0; @@ -54,9 +54,9 @@ static int dump_table_name(const char *sig) static void list_fadt(struct acpi_fadt *fadt) { if (fadt->dsdt) - dump_hdr(map_sysmem(fadt->dsdt, 0)); + dump_hdr(nomap_sysmem(fadt->dsdt, 0)); if (fadt->firmware_ctrl) - dump_hdr(map_sysmem(fadt->firmware_ctrl, 0)); + dump_hdr(nomap_sysmem(fadt->firmware_ctrl, 0)); }
static void list_rsdt(struct acpi_rsdp *rsdp) @@ -66,11 +66,11 @@ static void list_rsdt(struct acpi_rsdp *rsdp) struct acpi_xsdt *xsdt;
if (rsdp->rsdt_address) { - rsdt = map_sysmem(rsdp->rsdt_address, 0); + rsdt = nomap_sysmem(rsdp->rsdt_address, 0); dump_hdr(&rsdt->header); } if (rsdp->xsdt_address) { - xsdt = map_sysmem(rsdp->xsdt_address, 0); + xsdt = nomap_sysmem(rsdp->xsdt_address, 0); dump_hdr(&xsdt->header); len = xsdt->header.length - sizeof(xsdt->header); count = len / sizeof(u64); @@ -91,7 +91,7 @@ static void list_rsdt(struct acpi_rsdp *rsdp) entry = rsdt->entry[i]; if (!entry) break; - hdr = map_sysmem(entry, 0); + hdr = nomap_sysmem(entry, 0); dump_hdr(hdr); if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) list_fadt((struct acpi_fadt *)hdr); diff --git a/include/mapmem.h b/include/mapmem.h index bb68b4c11af..f496c96d16c 100644 --- a/include/mapmem.h +++ b/include/mapmem.h @@ -28,6 +28,24 @@ static inline phys_addr_t map_to_sysmem(const void *ptr) { return (phys_addr_t)(uintptr_t)ptr; } + +/** + * nomap_sysmem() - pass through an address unchanged + * + * This is used to indicate an address which should NOT be mapped, e.g. in + * SMBIOS tables. Using this function instead of a case shows that the sandbox + * conversion has been done + */ +static inline void *nomap_sysmem(phys_addr_t paddr, unsigned long len) +{ + return (void *)(uintptr_t)paddr; +} + +static inline phys_addr_t nomap_to_sysmem(const void *ptr) +{ + return (phys_addr_t)(uintptr_t)ptr; +} + # endif
#endif /* __MAPMEM_H */ diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c index 939a638bb5b..bcafd771750 100644 --- a/lib/acpi/acpi.c +++ b/lib/acpi/acpi.c @@ -22,13 +22,13 @@ struct acpi_table_header *acpi_find_table(const char *sig) if (!rsdp) return NULL; if (rsdp->xsdt_address) { - xsdt = map_sysmem(rsdp->xsdt_address, 0); + xsdt = nomap_sysmem(rsdp->xsdt_address, 0); len = xsdt->header.length - sizeof(xsdt->header); count = len / sizeof(u64); } else { if (!rsdp->rsdt_address) return NULL; - rsdt = map_sysmem(rsdp->rsdt_address, 0); + rsdt = nomap_sysmem(rsdp->rsdt_address, 0); len = rsdt->header.length - sizeof(rsdt->header); count = len / sizeof(u32); } @@ -36,19 +36,19 @@ struct acpi_table_header *acpi_find_table(const char *sig) struct acpi_table_header *hdr;
if (rsdp->xsdt_address) - hdr = map_sysmem(xsdt->entry[i], 0); + hdr = nomap_sysmem(xsdt->entry[i], 0); else - hdr = map_sysmem(rsdt->entry[i], 0); + hdr = nomap_sysmem(rsdt->entry[i], 0); if (!memcmp(hdr->signature, sig, ACPI_NAME_LEN)) return hdr; if (!memcmp(hdr->signature, "FACP", ACPI_NAME_LEN)) { struct acpi_fadt *fadt = (struct acpi_fadt *)hdr;
if (!memcmp(sig, "DSDT", ACPI_NAME_LEN) && fadt->dsdt) - return map_sysmem(fadt->dsdt, 0); + return nomap_sysmem(fadt->dsdt, 0); if (!memcmp(sig, "FACS", ACPI_NAME_LEN) && fadt->firmware_ctrl) - return map_sysmem(fadt->firmware_ctrl, 0); + return nomap_sysmem(fadt->firmware_ctrl, 0); } }
diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index e74522e9972..39dd53ec402 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -167,7 +167,7 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table) }
/* Add table to the RSDT */ - rsdt->entry[i] = map_to_sysmem(table); + rsdt->entry[i] = nomap_to_sysmem(table);
/* Fix RSDT length or the kernel will assume invalid entries */ rsdt->header.length = sizeof(struct acpi_table_header) + @@ -185,7 +185,7 @@ int acpi_add_table(struct acpi_ctx *ctx, void *table) xsdt = ctx->xsdt;
/* Add table to the XSDT */ - xsdt->entry[i] = map_to_sysmem(table); + xsdt->entry[i] = nomap_to_sysmem(table);
/* Fix XSDT length */ xsdt->header.length = sizeof(struct acpi_table_header) + diff --git a/lib/acpi/base.c b/lib/acpi/base.c index 07b53e0c561..8b6af2bc43a 100644 --- a/lib/acpi/base.c +++ b/lib/acpi/base.c @@ -24,10 +24,10 @@ void acpi_write_rsdp(struct acpi_rsdp *rsdp, struct acpi_rsdt *rsdt, memcpy(rsdp->oem_id, OEM_ID, 6);
if (rsdt) - rsdp->rsdt_address = map_to_sysmem(rsdt); + rsdp->rsdt_address = nomap_to_sysmem(rsdt);
if (xsdt) - rsdp->xsdt_address = map_to_sysmem(xsdt); + rsdp->xsdt_address = nomap_to_sysmem(xsdt);
rsdp->length = sizeof(struct acpi_rsdp); rsdp->revision = ACPI_RSDP_REV_ACPI_2_0; diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 1211e2f0e7f..c53ebcdb1c1 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -291,8 +291,8 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts)
/* Check that the pointers were added correctly */ for (i = 0; i < 3; i++) { - ut_asserteq(map_to_sysmem(dmar + i), ctx.rsdt->entry[i]); - ut_asserteq(map_to_sysmem(dmar + i), ctx.xsdt->entry[i]); + ut_asserteq(nomap_to_sysmem(dmar + i), ctx.rsdt->entry[i]); + ut_asserteq(nomap_to_sysmem(dmar + i), ctx.xsdt->entry[i]); } ut_asserteq(0, ctx.rsdt->entry[3]); ut_asserteq(0, ctx.xsdt->entry[3]); @@ -371,8 +371,8 @@ static int dm_test_acpi_ctx_and_base_tables(struct unit_test_state *uts) end = PTR_ALIGN((void *)xsdt + sizeof(*xsdt), 64); ut_asserteq_ptr(end, ctx.current);
- ut_asserteq(map_to_sysmem(rsdt), rsdp->rsdt_address); - ut_asserteq(map_to_sysmem(xsdt), rsdp->xsdt_address); + ut_asserteq(nomap_to_sysmem(rsdt), rsdp->rsdt_address); + ut_asserteq(nomap_to_sysmem(xsdt), rsdp->xsdt_address);
return 0; } @@ -445,7 +445,7 @@ static int dm_test_acpi_cmd_dump(struct unit_test_state *uts) /* Now a real table */ console_record_reset(); run_command("acpi dump dmar", 0); - addr = ALIGN(map_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64); + addr = ALIGN(nomap_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64); ut_assert_nextline("DMAR @ %16lx", addr); ut_assert_nextlines_are_dump(0x30); ut_assert_console_end();

On 12/31/23 16:25, Simon Glass wrote:
Sandbox uses an API to map between addresses and pointers. This allows it to have (emulated) memory at zero and avoid arch-specific addressing details. It also allows memory-mapped peripherals to work.
As an example, on many machines sandbox maps address 100 to pointer value 10000000.
However this is not correct for ACPI, if sandbox starts another program (e.g EFI app) and passes it the tables. That app has no knowledge of sandbox's address mapping. So to make this work we want to store 10000000 as the value in the table.
Add two new 'nomap' functions which clearly make this exeption to how sandbox works.
This should allow EFI apps to access ACPI tables with sandbox, e.g. for testing purposes.
Signed-off-by: Simon Glasssjg@chromium.org Suggested-by: Heinrich Schuchardtxypron.glpk@gmx.de
Thanks a lot for making this change.
Best regards
Heinrich

On 12/31/23 16:25, Simon Glass wrote:
Sandbox uses an API to map between addresses and pointers. This allows it to have (emulated) memory at zero and avoid arch-specific addressing details. It also allows memory-mapped peripherals to work.
As an example, on many machines sandbox maps address 100 to pointer value 10000000.
However this is not correct for ACPI, if sandbox starts another program (e.g EFI app) and passes it the tables. That app has no knowledge of sandbox's address mapping. So to make this work we want to store 10000000 as the value in the table.
Add two new 'nomap' functions which clearly make this exeption to how sandbox works.
This should allow EFI apps to access ACPI tables with sandbox, e.g. for testing purposes.
Signed-off-by: Simon Glasssjg@chromium.org Suggested-by: Heinrich Schuchardtxypron.glpk@gmx.de
Thanks a lot for making this change.
Best regards
Heinrich
Applied to u-boot-dm/next, thanks!

At present this code allocates memory when writing the tables and then unnecessarily adds another memory map when installing it.
Adjust the code to allocate the tables using the normal U-Boot mechanism. This avoids doing an EFI memory allocation early in U-Boot, which may use memory that would be overwritten by a 'load' command, for example.
Signed-off-by: Simon Glass sjg@chromium.org --- I believe this is the fix we agreed on for after the release, so I am including it in this series.
Changes in v5: - Add new patch to correct smbios-table installation
lib/efi_loader/efi_smbios.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c index 5db342ee0d7..eb6d2ba43c9 100644 --- a/lib/efi_loader/efi_smbios.c +++ b/lib/efi_loader/efi_smbios.c @@ -54,27 +54,25 @@ efi_status_t efi_smbios_register(void)
static int install_smbios_table(void) { - u64 addr; - efi_status_t ret; + ulong addr; + void *buf;
if (!IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE) || IS_ENABLED(CONFIG_X86)) return 0;
- addr = SZ_4G; - ret = efi_allocate_pages(EFI_ALLOCATE_MAX_ADDRESS, - EFI_RUNTIME_SERVICES_DATA, - efi_size_in_pages(TABLE_SIZE), &addr); - if (ret != EFI_SUCCESS) + /* Align the table to a 4KB boundary to keep EFI happy */ + buf = memalign(SZ_4K, TABLE_SIZE); + if (!buf) return log_msg_ret("mem", -ENOMEM);
- addr = map_to_sysmem((void *)(uintptr_t)addr); + addr = map_to_sysmem(buf); if (!write_smbios_table(addr)) { log_err("Failed to write SMBIOS table\n"); return log_msg_ret("smbios", -EINVAL); }
/* Make a note of where we put it */ - log_debug("SMBIOS tables written to %llx\n", addr); + log_debug("SMBIOS tables written to %lx\n", addr); gd->arch.smbios_start = addr;
return 0;

On 12/31/23 16:25, Simon Glass wrote:
At present this code allocates memory when writing the tables and then unnecessarily adds another memory map when installing it.
Adjust the code to allocate the tables using the normal U-Boot mechanism. This avoids doing an EFI memory allocation early in U-Boot, which may use memory that would be overwritten by a 'load' command, for example.
Signed-off-by: Simon Glass sjg@chromium.org
In patch 11/12 you changed the address fields in ACPI tables from sandbox virtual addresses to pointers. Do you plan to do the same for SMBIOS?
Best regards
Heinrich

Hi Heinrich,
On Sun, Dec 31, 2023 at 9:27 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12/31/23 16:25, Simon Glass wrote:
At present this code allocates memory when writing the tables and then unnecessarily adds another memory map when installing it.
Adjust the code to allocate the tables using the normal U-Boot mechanism. This avoids doing an EFI memory allocation early in U-Boot, which may use memory that would be overwritten by a 'load' command, for example.
Signed-off-by: Simon Glass sjg@chromium.org
In patch 11/12 you changed the address fields in ACPI tables from sandbox virtual addresses to pointers. Do you plan to do the same for SMBIOS?
I haven't looked at it, but could if it would help. Are you planning to add an EFI test app for sandbox?
Regards, Simon

On 1/1/24 01:37, Simon Glass wrote:
Hi Heinrich,
On Sun, Dec 31, 2023 at 9:27 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12/31/23 16:25, Simon Glass wrote:
At present this code allocates memory when writing the tables and then unnecessarily adds another memory map when installing it.
Adjust the code to allocate the tables using the normal U-Boot mechanism. This avoids doing an EFI memory allocation early in U-Boot, which may use memory that would be overwritten by a 'load' command, for example.
Signed-off-by: Simon Glass sjg@chromium.org
In patch 11/12 you changed the address fields in ACPI tables from sandbox virtual addresses to pointers. Do you plan to do the same for SMBIOS?
I haven't looked at it, but could if it would help. Are you planning to add an EFI test app for sandbox?
Yes, we need a test checking that the SMBIOS protocol is correctly installed. A tool like dtbdump.efi (lib/efi_loader/dtbdump.efi) would allow to dump the SMBIOS table to file and then use dmidecode to check the tables for consistency.
Best regards
Heinrich

On 1/1/24 01:37, Simon Glass wrote:
Hi Heinrich,
On Sun, Dec 31, 2023 at 9:27 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12/31/23 16:25, Simon Glass wrote:
At present this code allocates memory when writing the tables and then unnecessarily adds another memory map when installing it.
Adjust the code to allocate the tables using the normal U-Boot mechanism. This avoids doing an EFI memory allocation early in U-Boot, which may use memory that would be overwritten by a 'load' command, for example.
Signed-off-by: Simon Glass sjg@chromium.org
In patch 11/12 you changed the address fields in ACPI tables from sandbox virtual addresses to pointers. Do you plan to do the same for SMBIOS?
I haven't looked at it, but could if it would help. Are you planning to add an EFI test app for sandbox?
Yes, we need a test checking that the SMBIOS protocol is correctly installed. A tool like dtbdump.efi (lib/efi_loader/dtbdump.efi) would allow to dump the SMBIOS table to file and then use dmidecode to check the tables for consistency.
Best regards
Heinrich
Applied to u-boot-dm/next, thanks!

Am 31. Dezember 2023 16:25:43 MEZ schrieb Simon Glass sjg@chromium.org:
When the malloc() region extends beyond 4GB on ARM we may end up with an SMBIOS table in that region.
Add support for writing an SMBIOS3 table, which supports a 64-bit address.
Note that this problem does not happen on x86 since it requires the tables to be placed just below 1MB in memory, unless CONFIG_BLOBLIST_TABLES is enabled.
The ACPI specification only requires that a low memory RSDP exists on non-UEFI x86 systems.
Nothing stops us from copying the RSDP only to low memory when not booting via EFI. Maybe that way we could have more common code. But this is beyond the scope of this series.
Best regards
Heinrich
v5 drops support for SMBIOS2 tables as well. It also adds some changes to memory mapping which should allow an EFI app (launched from sandbox) to read the ACPI tables correctly.
Changes in v5:
- Update comment to mention x86 alignment
- Add new patch to drop support for SMBIOS2 tables
- Add new patch to drop support for SMBIOS2 tables with EFI
- Add new patch to rename test dm_test_setup_ctx_and_base_tables()
- Add new patch to write pointers to tables instead of addresses
- Add new patch to correct smbios-table installation
Changes in v4:
- Bring in this patch from Heinrich's series
- Check the start of the table rather than the end
Changes in v2:
- Check the end of the table rather than the start.
- Add a new patch to correct gd_smbios_start()
- Add a note about why unmap_system() is called
Heinrich Schuchardt (1): smbios: SMBIOS 3.0 (64-bit) Entry Point structure
Simon Glass (11): smbios: Refactor 32-bit code into an else statement smbios: Move the rest of the SMBIOS2 code smbios: Use SMBIOS 3.0 to support an address above 4GB smbios: Correct gd_smbios_start() efi: Use the correct GUID for the SMBIOS table smbios: Require the caller to align the SMBIOS table smbios: Drop support for SMBIOS2 tables efi: smbios: Drop support for SMBIOS2 tables acpi: Rename test dm_test_setup_ctx_and_base_tables() acpi: Write pointers to tables instead of addresses efi: Correct smbios-table installation
arch/sandbox/include/asm/io.h | 16 +++++++++ arch/x86/lib/acpi_table.c | 6 ++-- cmd/acpi.c | 12 +++---- include/asm-generic/global_data.h | 2 +- include/efi_api.h | 4 +++ include/mapmem.h | 18 ++++++++++ include/smbios.h | 41 ++++++++++++++++++++--- lib/acpi/acpi.c | 12 +++---- lib/acpi/acpi_table.c | 4 +-- lib/acpi/base.c | 4 +-- lib/efi_loader/efi_smbios.c | 28 +++++++++------- lib/smbios.c | 55 ++++++++++--------------------- test/dm/acpi.c | 14 ++++---- 13 files changed, 134 insertions(+), 82 deletions(-)

On 12/31/23 16:56, Heinrich Schuchardt wrote:
Am 31. Dezember 2023 16:25:43 MEZ schrieb Simon Glass sjg@chromium.org:
When the malloc() region extends beyond 4GB on ARM we may end up with an SMBIOS table in that region.
Add support for writing an SMBIOS3 table, which supports a 64-bit address.
Note that this problem does not happen on x86 since it requires the tables to be placed just below 1MB in memory, unless CONFIG_BLOBLIST_TABLES is enabled.
The ACPI specification only requires that a low memory RSDP exists on non-UEFI x86 systems.
Nothing stops us from copying the RSDP only to low memory when not booting via EFI. Maybe that way we could have more common code. But this is beyond the scope of this series.
Same is true for the SMBIOS anchor. You could have all tables in high memory and only copy the anchor to low memory when booting non-UEFI x86.
Best regards
Heinrich
v5 drops support for SMBIOS2 tables as well. It also adds some changes to memory mapping which should allow an EFI app (launched from sandbox) to read the ACPI tables correctly.
Changes in v5:
- Update comment to mention x86 alignment
- Add new patch to drop support for SMBIOS2 tables
- Add new patch to drop support for SMBIOS2 tables with EFI
- Add new patch to rename test dm_test_setup_ctx_and_base_tables()
- Add new patch to write pointers to tables instead of addresses
- Add new patch to correct smbios-table installation
Changes in v4:
- Bring in this patch from Heinrich's series
- Check the start of the table rather than the end
Changes in v2:
- Check the end of the table rather than the start.
- Add a new patch to correct gd_smbios_start()
- Add a note about why unmap_system() is called
Heinrich Schuchardt (1): smbios: SMBIOS 3.0 (64-bit) Entry Point structure
Simon Glass (11): smbios: Refactor 32-bit code into an else statement smbios: Move the rest of the SMBIOS2 code smbios: Use SMBIOS 3.0 to support an address above 4GB smbios: Correct gd_smbios_start() efi: Use the correct GUID for the SMBIOS table smbios: Require the caller to align the SMBIOS table smbios: Drop support for SMBIOS2 tables efi: smbios: Drop support for SMBIOS2 tables acpi: Rename test dm_test_setup_ctx_and_base_tables() acpi: Write pointers to tables instead of addresses efi: Correct smbios-table installation
arch/sandbox/include/asm/io.h | 16 +++++++++ arch/x86/lib/acpi_table.c | 6 ++-- cmd/acpi.c | 12 +++---- include/asm-generic/global_data.h | 2 +- include/efi_api.h | 4 +++ include/mapmem.h | 18 ++++++++++ include/smbios.h | 41 ++++++++++++++++++++--- lib/acpi/acpi.c | 12 +++---- lib/acpi/acpi_table.c | 4 +-- lib/acpi/base.c | 4 +-- lib/efi_loader/efi_smbios.c | 28 +++++++++------- lib/smbios.c | 55 ++++++++++--------------------- test/dm/acpi.c | 14 ++++---- 13 files changed, 134 insertions(+), 82 deletions(-)

Hi Heinrich,
On Sun, Dec 31, 2023 at 9:07 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12/31/23 16:56, Heinrich Schuchardt wrote:
Am 31. Dezember 2023 16:25:43 MEZ schrieb Simon Glass sjg@chromium.org:
When the malloc() region extends beyond 4GB on ARM we may end up with an SMBIOS table in that region.
Add support for writing an SMBIOS3 table, which supports a 64-bit address.
Note that this problem does not happen on x86 since it requires the tables to be placed just below 1MB in memory, unless CONFIG_BLOBLIST_TABLES is enabled.
The ACPI specification only requires that a low memory RSDP exists on non-UEFI x86 systems.
Nothing stops us from copying the RSDP only to low memory when not booting via EFI. Maybe that way we could have more common code. But this is beyond the scope of this series.
Same is true for the SMBIOS anchor. You could have all tables in high memory and only copy the anchor to low memory when booting non-UEFI x86.
Yes, that's right...do you think it is worth mentioning that, though?
[..]
Regards, Simon

Am 1. Januar 2024 01:37:39 MEZ schrieb Simon Glass sjg@chromium.org:
Hi Heinrich,
On Sun, Dec 31, 2023 at 9:07 AM Heinrich Schuchardt xypron.glpk@gmx.de wrote:
On 12/31/23 16:56, Heinrich Schuchardt wrote:
Am 31. Dezember 2023 16:25:43 MEZ schrieb Simon Glass sjg@chromium.org:
When the malloc() region extends beyond 4GB on ARM we may end up with an SMBIOS table in that region.
Add support for writing an SMBIOS3 table, which supports a 64-bit address.
Note that this problem does not happen on x86 since it requires the tables to be placed just below 1MB in memory, unless CONFIG_BLOBLIST_TABLES is enabled.
The ACPI specification only requires that a low memory RSDP exists on non-UEFI x86 systems.
Nothing stops us from copying the RSDP only to low memory when not booting via EFI. Maybe that way we could have more common code. But this is beyond the scope of this series.
Same is true for the SMBIOS anchor. You could have all tables in high memory and only copy the anchor to low memory when booting non-UEFI x86.
Yes, that's right...do you think it is worth mentioning that, though?
Reducing the x86 speific code is something we should investigate in future. The current patch series looks good to me and hopefully will be merged soon.
Regards
Heinrich
[..]
Regards, Simon
participants (3)
-
Heinrich Schuchardt
-
Peter Robinson
-
Simon Glass