From 05e8e2403c533cc9e7a2a548486e2e41dfd5ce53 Mon Sep 17 00:00:00 2001 From: Nikita Shubin Date: Mon, 19 Dec 2022 11:05:27 +0300 Subject: [PATCH 01/11] imxtract: specify max gunzip size Specify max gunzip size from config to override SYS_XIMG_LEN default value wich is 0x800000. In case we have a large portion of FIT image, for example gzipped kernel with decompressed size large than 0x800000 we should enlarge imxract area, otherwise extracting it will fail. It used to be a hardcoded define in cmd/ximg.c and we are moving it to config. Signed-off-by: Nikita Shubin Reviewed-by: Simon Glass --- cmd/Kconfig | 10 ++++++++++ cmd/ximg.c | 7 +------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/cmd/Kconfig b/cmd/Kconfig index 24bfbe50572..5a7678f0ac9 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -495,6 +495,16 @@ config CMD_XIMG help Extract a part of a multi-image. +config SYS_XIMG_LEN + hex "imxtract max gunzip size" + default 0x800000 + depends on CMD_XIMG && GZIP + help + This provides the size of the commad-line argument area + used by imxtract for extracting pieces of FIT image. + It should be large enough to fit uncompressed size of + FIT piece we are extracting. + config CMD_SPL bool "spl export - Export boot information for Falcon boot" depends on SPL diff --git a/cmd/ximg.c b/cmd/ximg.c index a50dd20b19a..0e7eead8d19 100644 --- a/cmd/ximg.c +++ b/cmd/ximg.c @@ -27,11 +27,6 @@ #include #include -#ifndef CFG_SYS_XIMG_LEN -/* use 8MByte as default max gunzip size */ -#define CFG_SYS_XIMG_LEN 0x800000 -#endif - static int do_imgextract(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { @@ -52,7 +47,7 @@ do_imgextract(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) size_t fit_len; #endif #ifdef CONFIG_GZIP - uint unc_len = CFG_SYS_XIMG_LEN; + uint unc_len = CONFIG_SYS_XIMG_LEN; #endif uint8_t comp; From ece85cc0202717ee8eaf5acb0772c0912b7f8e9d Mon Sep 17 00:00:00 2001 From: Ayoub Zaki Date: Sat, 26 Aug 2023 13:53:29 +0200 Subject: [PATCH 02/11] rsa: use pkcs11 uri as defined in rfc7512 pkcs11 : change engine uri to use full pk11-URI as defined in: https://www.rfc-editor.org/rfc/rfc7512.html Signed-off-by: Ayoub Zaki --- doc/usage/fit/signature.rst | 2 +- lib/rsa/rsa-sign.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/usage/fit/signature.rst b/doc/usage/fit/signature.rst index 39edba14630..03a71b5192d 100644 --- a/doc/usage/fit/signature.rst +++ b/doc/usage/fit/signature.rst @@ -671,7 +671,7 @@ Create the fitImage:: Sign the fitImage with the hardware key:: $ ./tools/mkimage -F -k \ - "model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29" \ + "pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29" \ -K u-boot.dtb -N pkcs11 -r fitImage diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index d20bdb58a57..7ae163f264b 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -116,15 +116,15 @@ static int rsa_engine_get_pub_key(const char *keydir, const char *name, if (keydir) if (strstr(keydir, "object=")) snprintf(key_id, sizeof(key_id), - "pkcs11:%s;type=public", + "%s;type=public", keydir); else snprintf(key_id, sizeof(key_id), - "pkcs11:%s;object=%s;type=public", + "%s;object=%s;type=public", keydir, name); else snprintf(key_id, sizeof(key_id), - "pkcs11:object=%s;type=public", + "object=%s;type=public", name); } else if (engine_id) { if (keydir) @@ -238,15 +238,15 @@ static int rsa_engine_get_priv_key(const char *keydir, const char *name, if (keydir) if (strstr(keydir, "object=")) snprintf(key_id, sizeof(key_id), - "pkcs11:%s;type=private", + "%s;type=private", keydir); else snprintf(key_id, sizeof(key_id), - "pkcs11:%s;object=%s;type=private", + "%s;object=%s;type=private", keydir, name); else snprintf(key_id, sizeof(key_id), - "pkcs11:object=%s;type=private", + "object=%s;type=private", name); } else if (engine_id) { if (keydir && name) From 785834d62ef3c4121601a4a68a032d96100b7475 Mon Sep 17 00:00:00 2001 From: Robert Catherall Date: Thu, 23 Nov 2023 14:16:01 +0000 Subject: [PATCH 03/11] arm: afs: Set the filesize env. var. on load The `afs load` command copies data to RAM. Set the filesize environment variable to record how much data was 'loaded' Signed-off-by: Robert Catherall Reviewed-by: Andre Przywara Tested-by: Andre Przywara --- cmd/armflash.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/armflash.c b/cmd/armflash.c index d1466f73aa4..fdaea5ad811 100644 --- a/cmd/armflash.c +++ b/cmd/armflash.c @@ -180,6 +180,7 @@ static int load_image(const char * const name, const ulong address) { struct afs_image *afi = NULL; int i; + loff_t len_read = 0; parse_flash(); for (i = 0; i < num_afs_images; i++) { @@ -197,6 +198,7 @@ static int load_image(const char * const name, const ulong address) for (i = 0; i < afi->region_count; i++) { ulong from, to; + u32 size; from = afi->flash_mem_start + afi->regions[i].offset; if (address) { @@ -208,14 +210,20 @@ static int load_image(const char * const name, const ulong address) return CMD_RET_FAILURE; } - memcpy((void *)to, (void *)from, afi->regions[i].size); + size = afi->regions[i].size; + memcpy((void *)to, (void *)from, size); printf("loaded region %d from %08lX to %08lX, %08X bytes\n", i, from, to, - afi->regions[i].size); + size); + + len_read += size; } + + env_set_hex("filesize", len_read); + return CMD_RET_SUCCESS; } From 7481632b192f61b5bcb028c885a460d8b9c2731c Mon Sep 17 00:00:00 2001 From: Piotr Kubik Date: Fri, 24 Nov 2023 17:30:46 +0100 Subject: [PATCH 04/11] bootm: Fix flags used for bootargs string substitution Commit 51bb33846ad2 ("bootm: Support string substitution in bootargs") introduced a feature of bootargs string substitution and changed a flag used in bootm_process_cmdline_env() call to be either true or false. With this flag value, condition in bootm_process_cmdline() `if (flags & BOOTM_CL_SUBST)` is never true and process_subst() is never called. Add a simple test to verify if substitution works OK. Signed-off-by: Piotr Kubik Reviewed-by: Simon Glass --- boot/bootm.c | 6 +++++- test/py/tests/test_fit.py | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/boot/bootm.c b/boot/bootm.c index 301cfded05c..4cf66cca0d1 100644 --- a/boot/bootm.c +++ b/boot/bootm.c @@ -1103,7 +1103,11 @@ int do_bootm_states(struct cmd_tbl *cmdtp, int flag, int argc, if (!ret && (states & BOOTM_STATE_OS_BD_T)) ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_PREP)) { - ret = bootm_process_cmdline_env(images->os.os == IH_OS_LINUX); + int flags = 0; + /* For Linux OS do all substitutions at console processing */ + if (images->os.os == IH_OS_LINUX) + flags = BOOTM_CL_ALL; + ret = bootm_process_cmdline_env(flags); if (ret) { printf("Cmdline setup failed (err=%d)\n", ret); ret = CMD_RET_FAILURE; diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py index 04f64fd4bc6..8f9c4b26411 100755 --- a/test/py/tests/test_fit.py +++ b/test/py/tests/test_fit.py @@ -339,6 +339,14 @@ def test_fit(u_boot_console): 'U-Boot loaded FDT from offset %#x, FDT is actually at %#x' % (fit_offset, real_fit_offset)) + # Check if bootargs strings substitution works + output = cons.run_command_list([ + 'env set bootargs \\\"\'my_boot_var=${foo}\'\\\"', + 'env set foo bar', + 'bootm prep', + 'env print bootargs']) + assert 'bootargs="my_boot_var=bar"' in output, "Bootargs strings not substituted" + # Now a kernel and an FDT with cons.log.section('Kernel + FDT load'): params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr'] From 921f63e5723880bbbaf65429564e5638b7bbd002 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 29 Nov 2023 10:31:19 -0700 Subject: [PATCH 05/11] bootflow: Allow setting a cmdline arg with no value This is supposed to be supported by the 'bootflow cmd' command, at least according to the help. There is a 'bootflow cmd clear' but it is often more intuitive to use 'bootcmd cmd set' with an empty value. Update the command to pass BOOTFLOWCL_EMPTY in this case. Signed-off-by: Simon Glass --- cmd/bootflow.c | 4 ++-- test/boot/bootflow.c | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/bootflow.c b/cmd/bootflow.c index 4a47265ebd5..cc6dfae1668 100644 --- a/cmd/bootflow.c +++ b/cmd/bootflow.c @@ -543,9 +543,9 @@ static int do_bootflow_cmdline(struct cmd_tbl *cmdtp, int flag, int argc, op = argv[1]; arg = argv[2]; if (*op == 's') { - if (argc < 4) + if (argc < 3) return CMD_RET_USAGE; - val = argv[3]; + val = argv[3] ?: (const char *)BOOTFLOWCL_EMPTY; } switch (*op) { diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index f3e5a839da4..a9b555c7794 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -1095,6 +1095,10 @@ static int bootflow_cmdline(struct unit_test_state *uts) ut_asserteq(0, run_command("bootflow cmdline get mary", 0)); ut_assert_nextline_empty(); + ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0)); + ut_asserteq(0, run_command("bootflow cmdline set mary", 0)); + ut_assert_nextline_empty(); + ut_assert_console_end(); return 0; From 400cb2a850546e8cc9246cf97f0902ffe57867ab Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 2 Dec 2023 21:52:30 +0100 Subject: [PATCH 06/11] command: Allocate history buffer using calloc() The history buffer is currently a static array which can be some 10-40 kiB depending on configuration, and so adds considerably to the U-Boot binary size. Allocate it dynamically instead to reduce the U-Boot binary size. Signed-off-by: Marek Vasut --- common/cli_readline.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/common/cli_readline.c b/common/cli_readline.c index 06b8d465044..85453beed76 100644 --- a/common/cli_readline.c +++ b/common/cli_readline.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -85,7 +87,6 @@ static int hist_cur = -1; static unsigned hist_num; static char *hist_list[HIST_MAX]; -static char hist_lines[HIST_MAX][HIST_SIZE + 1]; /* Save room for NULL */ #define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1) @@ -97,8 +98,9 @@ static void getcmd_putchars(int count, int ch) getcmd_putch(ch); } -static void hist_init(void) +static int hist_init(void) { + unsigned char *hist; int i; hist_max = 0; @@ -106,10 +108,14 @@ static void hist_init(void) hist_cur = -1; hist_num = 0; - for (i = 0; i < HIST_MAX; i++) { - hist_list[i] = hist_lines[i]; - hist_list[i][0] = '\0'; - } + hist = calloc(HIST_MAX, HIST_SIZE + 1); + if (!hist) + return -ENOMEM; + + for (i = 0; i < HIST_MAX; i++) + hist_list[i] = hist + (i * (HIST_SIZE + 1)); + + return 0; } static void cread_add_to_hist(char *line) @@ -493,8 +499,9 @@ static int cread_line(const char *const prompt, char *buf, unsigned int *len, #else /* !CONFIG_CMDLINE_EDITING */ -static inline void hist_init(void) +static inline int hist_init(void) { + return 0; } static int cread_line(const char *const prompt, char *buf, unsigned int *len, @@ -643,8 +650,9 @@ int cli_readline_into_buffer(const char *const prompt, char *buffer, */ if (IS_ENABLED(CONFIG_CMDLINE_EDITING) && (gd->flags & GD_FLG_RELOC)) { if (!initted) { - hist_init(); - initted = 1; + rc = hist_init(); + if (rc == 0) + initted = 1; } if (prompt) From 0de448d03254617a902bc6081a7aba214b54b69d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sat, 2 Dec 2023 21:52:31 +0100 Subject: [PATCH 07/11] command: Move command completion temporary buffer to stack The command completion temporary buffer seems to be only used by the argv tokenizer, move it to stack. This saves 2 kiB from the binary size (depends on configuration) per: $ aarch64-linux-gnu-readelf -s u-boot | sort -n -k 3 Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- common/command.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/command.c b/common/command.c index 846e16e2ada..7821c273dae 100644 --- a/common/command.c +++ b/common/command.c @@ -355,10 +355,9 @@ static int find_common_prefix(char *const argv[]) return len; } -static char tmp_buf[CONFIG_SYS_CBSIZE + 1]; /* copy of console I/O buffer */ - int cmd_auto_complete(const char *const prompt, char *buf, int *np, int *colp) { + char tmp_buf[CONFIG_SYS_CBSIZE + 1]; /* copy of console I/O buffer */ int n = *np, col = *colp; char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */ char *cmdv[20]; From 4268ef9282c5870aaf45375e3816d0a8c644b214 Mon Sep 17 00:00:00 2001 From: Michael Trimarchi Date: Thu, 7 Dec 2023 15:28:19 +0100 Subject: [PATCH 08/11] pxe_utils: Increase feedback to user when fdt file is not found extlinux.conf can set fdtdir. fdtdir look for fdt file using information found in the environment variable. The function does not report any error in the case the file is not found Scanning for bootflows in all bootdevs Seq Method State Uclass Part Name Filename --- ----------- ------ -------- ---- ------------------------ ---------------- Scanning global bootmeth 'efi_mgr': No EFI system partition No EFI system partition Failed to persist EFI variables Scanning bootdev 'mmc@fa10000.bootdev': 0 extlinux ready mmc 1 mmc@fa10000.bootdev.part_ /boot/extlinux/extlinux.conf ** Booting bootflow 'mmc@fa10000.bootdev.part_1' with extlinux 1: am62x-sk-buildroot Retrieving file: /boot/Image append: console=ttyS2,115200n8 root=PARTUUID=c586a30c-0bf1-4323-aba8-779c814ee135 rw rootfstype=ext4 rootwait earlycon=ns16550a,mmio32,0x02800000 Retrieving file: /boot/k3-am623_ccm_m3.dtb Skipping fdtdir /boot/ for failure retrieving dts Signed-off-by: Michael Trimarchi Reviewed-by: Simon Glass --- boot/pxe_utils.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index a92bb896c63..83bc1677856 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -700,6 +700,11 @@ static int label_boot(struct pxe_context *ctx, struct pxe_label *label) label->name); goto cleanup; } + + if (label->fdtdir) { + printf("Skipping fdtdir %s for failure retrieving dts\n", + label->fdtdir); + } } if (label->kaslrseed) From a986ccea541b8e38ca219dc142f1bfef9a93ab66 Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Thu, 7 Dec 2023 11:18:49 +0200 Subject: [PATCH 09/11] smbios: Simplify reporting of unknown values If a value is not valid during the DT or SYSINFO parsing, we explicitly set that to "Unknown Product" and "Unknown" for the product and manufacturer respectively. It's cleaner if we move the checks insisde smbios_add_prop_si() and provide an alternative string in case the primary is NULL or empty pre-patch dmidecode Handle 0x0001, DMI type 1, 27 bytes System Information Manufacturer: Unknown Product Name: Unknown Product Version: Not Specified Serial Number: Not Specified UUID: Not Settable Wake-up Type: Reserved SKU Number: Not Specified Family: Not Specified [...] post-patch dmidecode: Handle 0x0001, DMI type 1, 27 bytes System Information Manufacturer: Unknown Product Name: Unknown Version: Unknown Serial Number: Unknown UUID: Not Settable Wake-up Type: Reserved SKU Number: Unknown Family: Unknown [...] While at it make smbios_add_prop_si() add a string directly if the prop node is NULL and replace smbios_add_string() calls with smbios_add_prop_si(ctx, NULL, ....) Signed-off-by: Ilias Apalodimas Reviewed-by: Peter Robinson Tested-by: Peter Robinson --- lib/smbios.c | 73 +++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/lib/smbios.c b/lib/smbios.c index d7f4999e8b2..444aa245a27 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -102,9 +102,6 @@ static int smbios_add_string(struct smbios_ctx *ctx, const char *str) int i = 1; char *p = ctx->eos; - if (!*str) - str = "Unknown"; - for (;;) { if (!*p) { ctx->last_str = p; @@ -134,11 +131,18 @@ static int smbios_add_string(struct smbios_ctx *ctx, const char *str) * * @ctx: context for writing the tables * @prop: property to write + * @dval: Default value to use if the string is not found or is empty * Return: 0 if not found, else SMBIOS string number (1 or more) */ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, - int sysinfo_id) + int sysinfo_id, const char *dval) { + if (!dval || !*dval) + dval = "Unknown"; + + if (!prop) + return smbios_add_string(ctx, dval); + if (sysinfo_id && ctx->dev) { char val[SMBIOS_STR_MAX]; int ret; @@ -151,8 +155,8 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, const char *str; str = ofnode_read_string(ctx->node, prop); - if (str) - return smbios_add_string(ctx, str); + + return smbios_add_string(ctx, str ? str : dval); } return 0; @@ -161,12 +165,15 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, /** * smbios_add_prop() - Add a property from the devicetree * - * @prop: property to write + * @prop: property to write. The default string will be written if + * prop is NULL + * @dval: Default value to use if the string is not found or is empty * Return: 0 if not found, else SMBIOS string number (1 or more) */ -static int smbios_add_prop(struct smbios_ctx *ctx, const char *prop) +static int smbios_add_prop(struct smbios_ctx *ctx, const char *prop, + const char *dval) { - return smbios_add_prop_si(ctx, prop, SYSINFO_ID_NONE); + return smbios_add_prop_si(ctx, prop, SYSINFO_ID_NONE, dval); } static void smbios_set_eos(struct smbios_ctx *ctx, char *eos) @@ -228,11 +235,9 @@ static int smbios_write_type0(ulong *current, int handle, memset(t, 0, sizeof(struct smbios_type0)); fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->vendor = smbios_add_string(ctx, "U-Boot"); + t->vendor = smbios_add_prop(ctx, NULL, "U-Boot"); - t->bios_ver = smbios_add_prop(ctx, "version"); - if (!t->bios_ver) - t->bios_ver = smbios_add_string(ctx, PLAIN_VERSION); + t->bios_ver = smbios_add_prop(ctx, "version", PLAIN_VERSION); if (t->bios_ver) gd->smbios_version = ctx->last_str; log_debug("smbios_version = %p: '%s'\n", gd->smbios_version, @@ -241,7 +246,7 @@ static int smbios_write_type0(ulong *current, int handle, print_buffer((ulong)gd->smbios_version, gd->smbios_version, 1, strlen(gd->smbios_version) + 1, 0); #endif - t->bios_release_date = smbios_add_string(ctx, U_BOOT_DMI_DATE); + t->bios_release_date = smbios_add_prop(ctx, NULL, U_BOOT_DMI_DATE); #ifdef CONFIG_ROM_SIZE t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1; #endif @@ -280,22 +285,19 @@ static int smbios_write_type1(ulong *current, int handle, memset(t, 0, sizeof(struct smbios_type1)); fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->manufacturer = smbios_add_prop(ctx, "manufacturer"); - if (!t->manufacturer) - t->manufacturer = smbios_add_string(ctx, "Unknown"); - t->product_name = smbios_add_prop(ctx, "product"); - if (!t->product_name) - t->product_name = smbios_add_string(ctx, "Unknown Product"); + t->manufacturer = smbios_add_prop(ctx, "manufacturer", "Unknown"); + t->product_name = smbios_add_prop(ctx, "product", "Unknown"); t->version = smbios_add_prop_si(ctx, "version", - SYSINFO_ID_SMBIOS_SYSTEM_VERSION); + SYSINFO_ID_SMBIOS_SYSTEM_VERSION, + "Unknown"); if (serial_str) { - t->serial_number = smbios_add_string(ctx, serial_str); + t->serial_number = smbios_add_prop(ctx, NULL, serial_str); strncpy((char *)t->uuid, serial_str, sizeof(t->uuid)); } else { - t->serial_number = smbios_add_prop(ctx, "serial"); + t->serial_number = smbios_add_prop(ctx, "serial", "Unknown"); } - t->sku_number = smbios_add_prop(ctx, "sku"); - t->family = smbios_add_prop(ctx, "family"); + t->sku_number = smbios_add_prop(ctx, "sku", "Unknown"); + t->family = smbios_add_prop(ctx, "family", "Unknown"); len = t->length + smbios_string_table_len(ctx); *current += len; @@ -314,15 +316,12 @@ static int smbios_write_type2(ulong *current, int handle, memset(t, 0, sizeof(struct smbios_type2)); fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->manufacturer = smbios_add_prop(ctx, "manufacturer"); - if (!t->manufacturer) - t->manufacturer = smbios_add_string(ctx, "Unknown"); - t->product_name = smbios_add_prop(ctx, "product"); - if (!t->product_name) - t->product_name = smbios_add_string(ctx, "Unknown Product"); + t->manufacturer = smbios_add_prop(ctx, "manufacturer", "Unknown"); + t->product_name = smbios_add_prop(ctx, "product", "Unknown"); t->version = smbios_add_prop_si(ctx, "version", - SYSINFO_ID_SMBIOS_BASEBOARD_VERSION); - t->asset_tag_number = smbios_add_prop(ctx, "asset-tag"); + SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, + "Unknown"); + t->asset_tag_number = smbios_add_prop(ctx, "asset-tag", "Unknown"); t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING; t->board_type = SMBIOS_BOARD_MOTHERBOARD; @@ -343,9 +342,7 @@ static int smbios_write_type3(ulong *current, int handle, memset(t, 0, sizeof(struct smbios_type3)); fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle); smbios_set_eos(ctx, t->eos); - t->manufacturer = smbios_add_prop(ctx, "manufacturer"); - if (!t->manufacturer) - t->manufacturer = smbios_add_string(ctx, "Unknown"); + t->manufacturer = smbios_add_prop(ctx, "manufacturer", "Unknown"); t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP; t->bootup_state = SMBIOS_STATE_SAFE; t->power_supply_state = SMBIOS_STATE_SAFE; @@ -388,8 +385,8 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, #endif t->processor_family = processor_family; - t->processor_manufacturer = smbios_add_string(ctx, vendor); - t->processor_version = smbios_add_string(ctx, name); + t->processor_manufacturer = smbios_add_prop(ctx, NULL, vendor); + t->processor_version = smbios_add_prop(ctx, NULL, name); } static int smbios_write_type4(ulong *current, int handle, From 738b34668f289ba98e3657f86e3a58385c09059d Mon Sep 17 00:00:00 2001 From: Ilias Apalodimas Date: Thu, 7 Dec 2023 11:18:50 +0200 Subject: [PATCH 10/11] smbios: Fallback to the default DT if sysinfo nodes are missing In order to fill in the SMBIOS tables U-Boot currently relies on a "u-boot,sysinfo-smbios" compatible node. This is fine for the boards that already include such nodes. However with some recent EFI changes, the majority of boards can boot up distros, which usually rely on things like dmidecode etc for their reporting. For boards that lack this special node the SMBIOS output looks like: System Information Manufacturer: Unknown Product Name: Unknown Version: Unknown Serial Number: Unknown UUID: Not Settable Wake-up Type: Reserved SKU Number: Unknown Family: Unknown This looks problematic since most of the info are "Unknown". The DT spec specifies standard properties containing relevant information like 'model' and 'compatible' for which the suggested format is . Unfortunately the 'model' string found in DTs is usually lacking the manufacturer so we can't use it for both 'Manufacturer' and 'Product Name' SMBIOS entries reliably. So let's add a last resort to our current smbios parsing. If none of the sysinfo properties are found, scan for those information in the root node of the device tree. Use the 'model' to fill the 'Product Name' and the first value of 'compatible' for the 'Manufacturer', since that always contains one. pre-patch: Handle 0x0001, DMI type 1, 27 bytes System Information Manufacturer: Unknown Product Name: Unknown Version: Unknown Serial Number: 100000000bb24ceb UUID: 30303031-3030-3030-3061-613234636435 Wake-up Type: Reserved SKU Number: Unknown Family: Unknown [...] and post patch: Handle 0x0001, DMI type 1, 27 bytes System Information Manufacturer: raspberrypi Product Name: Raspberry Pi 4 Model B Rev 1.1 Version: Unknown Serial Number: 100000000bb24ceb UUID: 30303031-3030-3030-3061-613234636435 Wake-up Type: Reserved SKU Number: Unknown Family: Unknown [...] Signed-off-by: Ilias Apalodimas Reviewed-by: Peter Robinson Tested-by: Peter Robinson --- lib/smbios.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 4 deletions(-) diff --git a/lib/smbios.c b/lib/smbios.c index 444aa245a27..3f0e1d52953 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -9,11 +9,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #ifdef CONFIG_CPU #include #include @@ -43,6 +46,25 @@ DECLARE_GLOBAL_DATA_PTR; +/** + * struct map_sysinfo - Mapping of sysinfo strings to DT + * + * @sysinfo_str: sysinfo string + * @dt_str: DT string + * @max: Max index of the tokenized string to pick. Counting starts from 0 + * + */ +struct map_sysinfo { + const char *sysinfo_str; + const char *dt_str; + int max; +}; + +static const struct map_sysinfo sysinfo_to_dt[] = { + { .sysinfo_str = "product", .dt_str = "model", 2 }, + { .sysinfo_str = "manufacturer", .dt_str = "compatible", 1 }, +}; + /** * struct smbios_ctx - context for writing SMBIOS tables * @@ -87,6 +109,18 @@ struct smbios_write_method { const char *subnode_name; }; +static const struct map_sysinfo *convert_sysinfo_to_dt(const char *sysinfo_str) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sysinfo_to_dt); i++) { + if (!strcmp(sysinfo_str, sysinfo_to_dt[i].sysinfo_str)) + return &sysinfo_to_dt[i]; + } + + return NULL; +} + /** * smbios_add_string() - add a string to the string area * @@ -124,6 +158,42 @@ static int smbios_add_string(struct smbios_ctx *ctx, const char *str) } } +/** + * get_str_from_dt - Get a substring from a DT property. + * After finding the property in the DT, the function + * will parse comma-separated values and return the value. + * If nprop->max exceeds the number of comma-separated + * elements, the last non NULL value will be returned. + * Counting starts from zero. + * + * @nprop: sysinfo property to use + * @str: pointer to fill with data + * @size: str buffer length + */ +static +void get_str_from_dt(const struct map_sysinfo *nprop, char *str, size_t size) +{ + const char *dt_str; + int cnt = 0; + char *token; + + memset(str, 0, size); + if (!nprop || !nprop->max) + return; + + dt_str = ofnode_read_string(ofnode_root(), nprop->dt_str); + if (!dt_str) + return; + + memcpy(str, dt_str, size); + token = strtok(str, ","); + while (token && cnt < nprop->max) { + strlcpy(str, token, strlen(token) + 1); + token = strtok(NULL, ","); + cnt++; + } +} + /** * smbios_add_prop_si() - Add a property from the devicetree or sysinfo * @@ -137,6 +207,8 @@ static int smbios_add_string(struct smbios_ctx *ctx, const char *str) static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, int sysinfo_id, const char *dval) { + int ret; + if (!dval || !*dval) dval = "Unknown"; @@ -145,18 +217,30 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, if (sysinfo_id && ctx->dev) { char val[SMBIOS_STR_MAX]; - int ret; ret = sysinfo_get_str(ctx->dev, sysinfo_id, sizeof(val), val); if (!ret) return smbios_add_string(ctx, val); } if (IS_ENABLED(CONFIG_OF_CONTROL)) { - const char *str; + const char *str = NULL; + char str_dt[128] = { 0 }; + /* + * If the node is not valid fallback and try the entire DT + * so we can at least fill in manufacturer and board type + */ + if (ofnode_valid(ctx->node)) { + str = ofnode_read_string(ctx->node, prop); + } else { + const struct map_sysinfo *nprop; - str = ofnode_read_string(ctx->node, prop); + nprop = convert_sysinfo_to_dt(prop); + get_str_from_dt(nprop, str_dt, sizeof(str_dt)); + str = (const char *)str_dt; + } - return smbios_add_string(ctx, str ? str : dval); + ret = smbios_add_string(ctx, str && *str ? str : dval); + return ret; } return 0; From 97135d9f4220e54b38f69a3f2416b2fd9d8f378c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Sun, 10 Dec 2023 22:25:07 +0100 Subject: [PATCH 11/11] cmd: part: Cover both part type entries with GUID ifdef The 'part type' subcommand depends on GUID partition table support. The help text exposes one of two 'part type' subcommand entries, hide both in case GUID partition table support is not enabled to avoid confusing users. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/part.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/part.c b/cmd/part.c index 0ce190005d3..c75f85acd52 100644 --- a/cmd/part.c +++ b/cmd/part.c @@ -308,9 +308,9 @@ U_BOOT_CMD( #ifdef CONFIG_PARTITION_TYPE_GUID "part type :\n" " - print partition type\n" -#endif "part type : \n" " - set environment variable to partition type\n" +#endif "part set type\n" " - set partition type for a device\n" "part types\n"