Re: [PATCH v2] smbios: arm64: Allow table to be written at a fixed addr
Heinrich Schuchardt
xypron.glpk at gmx.de
Wed Oct 25 02:45:11 CEST 2023
Am 25. Oktober 2023 01:31:19 MESZ schrieb Simon Glass <sjg at chromium.org>:
>U-Boot typically sets up its malloc() pool near the top of memory. On
>ARM64 systems this can result in an SMBIOS table above 4GB which is
>not supported by SMBIOSv2.
>
>Work around this problem by providing a new option to choose an address
>below 4GB (but as high as possible), if needed.
You must not overwrite memory controlled by the EFI subsystem without calling its allocator. We should provide SMBIOS 3. SMBIOS 2 is only a fallback for outdated tools.
Best regards
Heinrich
>
>Signed-off-by: Simon Glass <sjg at chromium.org>
>---
>
>Changes in v2:
>- Update to search for a suitable area automatically, if enabled
>
> lib/Kconfig | 12 +++++++
> lib/efi_loader/efi_smbios.c | 63 ++++++++++++++++++++++++++++++++++++-
> 2 files changed, 74 insertions(+), 1 deletion(-)
>
>diff --git a/lib/Kconfig b/lib/Kconfig
>index f6ca559897e7..a1eec98b392f 100644
>--- a/lib/Kconfig
>+++ b/lib/Kconfig
>@@ -994,6 +994,18 @@ config GENERATE_SMBIOS_TABLE
> See also SMBIOS_SYSINFO which allows SMBIOS values to be provided in
> the devicetree.
>
>+config SMBIOS_TABLE_FIXED
>+ bool "Place the SMBIOS table at a special address"
>+ depends on GENERATE_SMBIOS_TABLE && ARM64 && SMBIOS && EFI_LOADER
>+ default y
>+ help
>+ Use this option to place the SMBIOS table at a special address.
>+
>+ U-Boot typically sets up its malloc() pool near the top of memory. On
>+ ARM64 systems this can result in an SMBIOS table above 4GB which is
>+ not supported by SMBIOSv2. This option works around this problem by
>+ chosing an address just below 4GB, if needed.
>+
> endmenu
>
> config LIB_RATIONAL
>diff --git a/lib/efi_loader/efi_smbios.c b/lib/efi_loader/efi_smbios.c
>index 48446f654d9b..bdbce4c4d785 100644
>--- a/lib/efi_loader/efi_smbios.c
>+++ b/lib/efi_loader/efi_smbios.c
>@@ -47,6 +47,60 @@ efi_status_t efi_smbios_register(void)
> map_sysmem(addr, 0));
> }
>
>+/**
>+ * find_addr_below() - Find a usable region below the given max_addr
>+ *
>+ * Check if *addrp is suitable to define a memory region which finishes below
>+ * @max_addr + @req_size. If so, do nothing and return 0
>+ *
>+ * As a backup, if CONFIG_SMBIOS_TABLE_FIXED is enabled, search for a
>+ * 4KB-aligned DRAM region which is large enough. Make sure it is below U-Boot's
>+ * stack space, assumed to be 64KB.
>+ *
>+ * @max_addr: Maximum address that can be used (region must finish before here)
>+ * @req:size: Required size of region
>+ * @addrp: On entry: Current proposed address; on exit, holds the new address,
>+ * on success
>+ * Return 0 if OK (existing region was OK, or a new one was found), -ENOSPC if
>+ * nothing suitable was found
>+ */
>+static int find_addr_below(ulong max_addr, ulong req_size, ulong *addrp)
>+{
>+ struct bd_info *bd = gd->bd;
>+ ulong max_base;
>+ int i;
>+
>+ max_base = max_addr - req_size;
>+ if (*addrp <= max_base)
>+ return 0;
>+
>+ if (!IS_ENABLED(CONFIG_SMBIOS_TABLE_FIXED))
>+ return -ENOSPC;
>+
>+ /* Make sure that the base is at least 64KB below the stack */
>+ max_base = min(max_base,
>+ ALIGN(gd->start_addr_sp - SZ_64K - req_size, SZ_4K));
>+
>+ for (i = CONFIG_NR_DRAM_BANKS - 1; i >= 0; i--) {
>+ ulong start = bd->bi_dram[i].start;
>+ ulong size = bd->bi_dram[i].size;
>+ ulong addr;
>+
>+ /* chose an address at most req_size bytes before the end */
>+ addr = min(max_base, start - req_size + size);
>+
>+ /* check this is in the range */
>+ if (addr >= start && addr + req_size < start + size) {
>+ *addrp = addr;
>+ log_warning("Forcing SMBIOS table to address %lx\n",
>+ addr);
>+ return 0;
>+ }
>+ }
>+
>+ return -ENOSPC;
>+}
>+
> static int install_smbios_table(void)
> {
> ulong addr;
>@@ -61,7 +115,14 @@ static int install_smbios_table(void)
> return log_msg_ret("mem", -ENOMEM);
>
> addr = map_to_sysmem(buf);
>- if (!write_smbios_table(addr)) {
>+
>+ /*
>+ * Deal with a fixed address if needed. For simplicity we assume that
>+ * the SMBIOS-table size is <64KB. If a suitable address cannot be
>+ * found, then write_smbios_table() returns an error.
>+ */
>+ if (find_addr_below(SZ_4G, SZ_64K, &addr) ||
>+ !write_smbios_table(addr)) {
> log_err("Failed to write SMBIOS table\n");
> return log_msg_ret("smbios", -EINVAL);
> }
More information about the U-Boot
mailing list