diff options
author | Tom Rini <trini@konsulko.com> | 2022-12-31 16:30:31 -0500 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-12-31 16:30:31 -0500 |
commit | 3aa14d76182dbbaf9fed4deeaf362f083b9d2f5b (patch) | |
tree | 9a4c733db8ec3b99444a5ff9177aeb709459ad07 | |
parent | 3e4cbe184a0f6537abb457d6afa61224396c4e46 (diff) | |
parent | bcc85b96b5ffbbce19a89747138feb873d918915 (diff) |
Merge branch '2022-12-31-cmd-source-support-specifying-config-name' into next
To quote the author:
This series adds support for using configs with the source command.
And to paraphrase the rest, see the patch commit messages for more
details.
-rw-r--r-- | arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c | 2 | ||||
-rw-r--r-- | boot/bootmeth_script.c | 2 | ||||
-rw-r--r-- | cmd/source.c | 84 | ||||
-rw-r--r-- | doc/uImage.FIT/source_file_format.txt | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/f_sdp.c | 2 | ||||
-rw-r--r-- | include/image.h | 22 | ||||
-rw-r--r-- | test/py/tests/source.its | 43 | ||||
-rw-r--r-- | test/py/tests/test_source.py | 37 |
8 files changed, 162 insertions, 33 deletions
diff --git a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c index 007f713130..cb13a14d82 100644 --- a/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c +++ b/arch/arm/mach-stm32mp/cmd_stm32prog/cmd_stm32prog.c @@ -154,7 +154,7 @@ static int do_stm32prog(struct cmd_tbl *cmdtp, int flag, int argc, do_bootz(cmdtp, 0, 4, bootm_argv); } if (data->script) - image_source_script(data->script, "script@stm32prog"); + image_source_script(data->script, NULL, NULL); if (reset) { puts("Reset...\n"); diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index d1c3f94003..6c84721d1c 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -101,7 +101,7 @@ static int script_boot(struct udevice *dev, struct bootflow *bflow) log_debug("mmc_bootdev: %s\n", env_get("mmc_bootdev")); addr = map_to_sysmem(bflow->buf); - ret = image_source_script(addr, NULL); + ret = image_source_script(addr, NULL, NULL); if (ret) return log_msg_ret("boot", ret); diff --git a/cmd/source.c b/cmd/source.c index 698d9f86d9..94da5d8d6a 100644 --- a/cmd/source.c +++ b/cmd/source.c @@ -42,7 +42,7 @@ static const char *get_default_image(const void *fit) } #endif -int image_source_script(ulong addr, const char *fit_uname) +int image_source_script(ulong addr, const char *fit_uname, const char *confname) { ulong len; #if defined(CONFIG_LEGACY_IMAGE_FORMAT) @@ -112,32 +112,58 @@ int image_source_script(ulong addr, const char *fit_uname) return 1; } - if (!fit_uname) - fit_uname = get_default_image(fit_hdr); - if (!fit_uname) { - puts("No FIT subimage unit name\n"); - return 1; - } + /* If confname is empty, use the default */ + if (confname && *confname) + noffset = fit_conf_get_node(fit_hdr, confname); + else + noffset = fit_conf_get_node(fit_hdr, NULL); + if (noffset < 0) { + if (!confname) + goto fallback; + printf("Could not find config %s\n", confname); + return 1; + } - /* get script component image node offset */ - noffset = fit_image_get_node (fit_hdr, fit_uname); - if (noffset < 0) { - printf ("Can't find '%s' FIT subimage\n", fit_uname); - return 1; + if (verify && fit_config_verify(fit_hdr, noffset)) + return 1; + + noffset = fit_conf_get_prop_node(fit_hdr, noffset, + FIT_SCRIPT_PROP, + IH_PHASE_NONE); + if (noffset < 0) { + if (!confname) + goto fallback; + printf("Could not find script in %s\n", confname); + return 1; + } + } else { +fallback: + if (!fit_uname || !*fit_uname) + fit_uname = get_default_image(fit_hdr); + if (!fit_uname) { + puts("No FIT subimage unit name\n"); + return 1; + } + + /* get script component image node offset */ + noffset = fit_image_get_node(fit_hdr, fit_uname); + if (noffset < 0) { + printf("Can't find '%s' FIT subimage\n", + fit_uname); + return 1; + } } if (!fit_image_check_type (fit_hdr, noffset, IH_TYPE_SCRIPT)) { - puts ("Not a image image\n"); + puts("Not a script image\n"); return 1; } /* verify integrity */ - if (verify) { - if (!fit_image_verify(fit_hdr, noffset)) { - puts ("Bad Data Hash\n"); - return 1; - } + if (verify && !fit_image_verify(fit_hdr, noffset)) { + puts("Bad Data Hash\n"); + return 1; } /* get script subimage data address and length */ @@ -166,7 +192,7 @@ static int do_source(struct cmd_tbl *cmdtp, int flag, int argc, { ulong addr; int rcode; - const char *fit_uname = NULL; + const char *fit_uname = NULL, *confname = NULL; /* Find script image */ if (argc < 2) { @@ -177,6 +203,9 @@ static int do_source(struct cmd_tbl *cmdtp, int flag, int argc, &fit_uname)) { debug("* source: subimage '%s' from FIT image at 0x%08lx\n", fit_uname, addr); + } else if (fit_parse_conf(argv[1], image_load_addr, &addr, &confname)) { + debug("* source: config '%s' from FIT image at 0x%08lx\n", + confname, addr); #endif } else { addr = hextoul(argv[1], NULL); @@ -184,21 +213,22 @@ static int do_source(struct cmd_tbl *cmdtp, int flag, int argc, } printf ("## Executing script at %08lx\n", addr); - rcode = image_source_script(addr, fit_uname); + rcode = image_source_script(addr, fit_uname, confname); return rcode; } #ifdef CONFIG_SYS_LONGHELP static char source_help_text[] = - "[addr]\n" - "\t- run script starting at addr\n" - "\t- A valid image header must be present" #if defined(CONFIG_FIT) - "\n" - "For FIT format uImage addr must include subimage\n" - "unit name in the form of addr:<subimg_uname>" + "[<addr>][:[<image>]|#[<config>]]\n" + "\t- Run script starting at addr\n" + "\t- A FIT config name or subimage name may be specified with : or #\n" + "\t (like bootm). If the image or config name is omitted, the\n" + "\t default is used."; +#else + "[<addr>]\n" + "\t- Run script starting at addr"; #endif - ""; #endif U_BOOT_CMD( diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt index 4640e38e3c..269e1fa0b5 100644 --- a/doc/uImage.FIT/source_file_format.txt +++ b/doc/uImage.FIT/source_file_format.txt @@ -247,6 +247,7 @@ o config-1 |- kernel = "kernel sub-node unit name" |- fdt = "fdt sub-node unit-name" [, "fdt overlay sub-node unit-name", ...] |- loadables = "loadables sub-node unit-name" + |- script = " |- compatible = "vendor,board-style device tree compatible string" @@ -268,6 +269,8 @@ o config-1 of strings. U-Boot will load each binary at its given start-address and may optionally invoke additional post-processing steps on this binary based on its component image node type. + - script : The image to use when loading a U-Boot script (for use with the + source command). - compatible : The root compatible string of the U-Boot device tree that this configuration shall automatically match when CONFIG_FIT_BEST_MATCH is enabled. If this property is not provided, the compatible string will be diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index af4b167e17..5ae5b62741 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -868,7 +868,7 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, jump_to_image_no_args(&spl_image); #else /* In U-Boot, allow jumps to scripts */ - image_source_script(sdp_func->jmp_address, "script@1"); + image_source_script(sdp_func->jmp_address, NULL, NULL); #endif } diff --git a/include/image.h b/include/image.h index b6a809834a..bed75ce1b3 100644 --- a/include/image.h +++ b/include/image.h @@ -711,15 +711,23 @@ int fit_image_load(struct bootm_headers *images, ulong addr, /** * image_source_script() - Execute a script + * @addr: Address of script + * @fit_uname: FIT subimage name + * @confname: FIT config name. The subimage is chosen based on FIT_SCRIPT_PROP. * * Executes a U-Boot script at a particular address in memory. The script should * have a header (FIT or legacy) with the script type (IH_TYPE_SCRIPT). * - * @addr: Address of script - * @fit_uname: FIT subimage name + * If @fit_uname is the empty string, then the default image is used. If + * @confname is the empty string, the default config is used. If @confname and + * @fit_uname are both non-%NULL, then @confname is ignored. If @confname and + * @fit_uname are both %NULL, then first the default config is tried, and then + * the default image. + * * Return: result code (enum command_ret_t) */ -int image_source_script(ulong addr, const char *fit_uname); +int image_source_script(ulong addr, const char *fit_uname, + const char *confname); /** * fit_get_node_from_config() - Look up an image a FIT by type @@ -1032,6 +1040,7 @@ int booti_setup(ulong image, ulong *relocated_addr, ulong *size, #define FIT_FPGA_PROP "fpga" #define FIT_FIRMWARE_PROP "firmware" #define FIT_STANDALONE_PROP "standalone" +#define FIT_SCRIPT_PROP "script" #define FIT_PHASE_PROP "phase" #define FIT_MAX_HASH_LEN HASH_MAX_DIGEST_SIZE @@ -1259,7 +1268,14 @@ int fit_image_verify_with_data(const void *fit, int image_noffset, size_t size); int fit_image_verify(const void *fit, int noffset); +#if CONFIG_IS_ENABLED(FIT_SIGNATURE) int fit_config_verify(const void *fit, int conf_noffset); +#else +static inline int fit_config_verify(const void *fit, int conf_noffset) +{ + return 0; +} +#endif int fit_all_image_verify(const void *fit); int fit_config_decrypt(const void *fit, int conf_noffset); int fit_image_check_os(const void *fit, int noffset, uint8_t os); diff --git a/test/py/tests/source.its b/test/py/tests/source.its new file mode 100644 index 0000000000..3c62f777f1 --- /dev/null +++ b/test/py/tests/source.its @@ -0,0 +1,43 @@ +/dts-v1/; + +/ { + description = "FIT image to test the source command"; + #address-cells = <1>; + + images { + default = "script-1"; + + script-1 { + data = "echo 1"; + type = "script"; + arch = "sandbox"; + compression = "none"; + }; + + script-2 { + data = "echo 2"; + type = "script"; + arch = "sandbox"; + compression = "none"; + }; + + not-a-script { + data = "echo 3"; + type = "kernel"; + arch = "sandbox"; + compression = "none"; + }; + }; + + configurations { + default = "conf-2"; + + conf-1 { + script = "script-1"; + }; + + conf-2 { + script = "script-2"; + }; + }; +}; diff --git a/test/py/tests/test_source.py b/test/py/tests/test_source.py new file mode 100644 index 0000000000..bbc311df6d --- /dev/null +++ b/test/py/tests/test_source.py @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com> + +import os +import pytest +import u_boot_utils as util + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('cmd_echo') +@pytest.mark.buildconfigspec('cmd_source') +@pytest.mark.buildconfigspec('fit') +def test_source(u_boot_console): + # Compile our test script image + cons = u_boot_console + mkimage = os.path.join(cons.config.build_dir, 'tools/mkimage') + its = os.path.join(cons.config.source_dir, 'test/py/tests/source.its') + fit = os.path.join(cons.config.build_dir, 'source.itb') + util.run_and_log(cons, (mkimage, '-f', its, fit)) + cons.run_command(f'host load hostfs - $loadaddr {fit}') + + assert '2' in cons.run_command('source') + assert '1' in cons.run_command('source :') + assert '1' in cons.run_command('source :script-1') + assert '2' in cons.run_command('source :script-2') + assert 'Fail' in cons.run_command('source :not-a-script || echo Fail') + assert '2' in cons.run_command('source \\#') + assert '1' in cons.run_command('source \\#conf-1') + assert '2' in cons.run_command('source \\#conf-2') + + cons.run_command('fdt addr $loadaddr') + cons.run_command('fdt rm /configurations default') + assert '1' in cons.run_command('source') + assert 'Fail' in cons.run_command('source \\# || echo Fail') + + cons.run_command('fdt rm /images default') + assert 'Fail' in cons.run_command('source || echo Fail') + assert 'Fail' in cons.run_command('source \\# || echo Fail') |