From d03799004640abfeb656e9db48d6f9b9e24383fb Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 15 Dec 2022 10:15:50 +0100 Subject: fastboot: remove #ifdef CONFIG when it is possible Much of the fastboot code predates the introduction of Kconfig and has quite a few #ifdefs in it which is unnecessary now that we can use IS_ENABLED() et al. Signed-off-by: Patrick Delaunay Reviewed-by: Mattijs Korpershoek Reviewed-by: Sean Anderson Tested-by: Mattijs Korpershoek # on vim3l --- include/fastboot.h | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'include') diff --git a/include/fastboot.h b/include/fastboot.h index 57daaf12982..d062a3469ef 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -24,10 +24,8 @@ enum { FASTBOOT_COMMAND_GETVAR = 0, FASTBOOT_COMMAND_DOWNLOAD, -#if CONFIG_IS_ENABLED(FASTBOOT_FLASH) FASTBOOT_COMMAND_FLASH, FASTBOOT_COMMAND_ERASE, -#endif FASTBOOT_COMMAND_BOOT, FASTBOOT_COMMAND_CONTINUE, FASTBOOT_COMMAND_REBOOT, @@ -35,20 +33,11 @@ enum { FASTBOOT_COMMAND_REBOOT_FASTBOOTD, FASTBOOT_COMMAND_REBOOT_RECOVERY, FASTBOOT_COMMAND_SET_ACTIVE, -#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT) FASTBOOT_COMMAND_OEM_FORMAT, -#endif -#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_PARTCONF) FASTBOOT_COMMAND_OEM_PARTCONF, -#endif -#if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS) FASTBOOT_COMMAND_OEM_BOOTBUS, -#endif -#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) FASTBOOT_COMMAND_ACMD, FASTBOOT_COMMAND_UCMD, -#endif - FASTBOOT_COMMAND_COUNT }; @@ -173,7 +162,5 @@ void fastboot_data_download(const void *fastboot_data, */ void fastboot_data_complete(char *response); -#if CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT) void fastboot_acmd_complete(void); -#endif #endif /* _FASTBOOT_H_ */ -- cgit v1.3.1 From f3d914cfdd5ac611d99f04096497f4cd13dd6aaa Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Fri, 16 Dec 2022 13:20:16 -0500 Subject: fastboot: Add OEM run command This adds the UUU UCmd functionality as an OEM command. While the fastboot tool allows sending arbitrary commands as long as they are prefixed with "oem". This allows running generic U-Boot commands over fastboot without UUU, which is especially useful when not using USB. This is really the route we should have gone in the first place when adding these commands. While we're here, clean up the UUU Kconfig a bit. Signed-off-by: Sean Anderson Reviewed-by: Heiko Schocher --- doc/android/fastboot.rst | 18 ++++++++++++++++++ drivers/fastboot/Kconfig | 19 ++++++++++++++----- drivers/fastboot/fb_command.c | 4 ++++ include/fastboot.h | 1 + 4 files changed, 37 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/doc/android/fastboot.rst b/doc/android/fastboot.rst index 7611f07038e..1ad8a897c85 100644 --- a/doc/android/fastboot.rst +++ b/doc/android/fastboot.rst @@ -28,6 +28,7 @@ The following OEM commands are supported (if enabled): - ``oem partconf`` - this executes ``mmc partconf %x 0`` to configure eMMC with = boot_ack boot_partition - ``oem bootbus`` - this executes ``mmc bootbus %x %s`` to configure eMMC +- ``oem run`` - this executes an arbitrary U-Boot command Support for both eMMC and NAND devices is included. @@ -227,6 +228,23 @@ and on the U-Boot side you should see:: Starting kernel ... +Running Shell Commands +^^^^^^^^^^^^^^^^^^^^^^ + +Normally, arbitrary U-Boot command execution is not enabled. This is so +fastboot can be used to update systems using verified boot. However, such +functionality can be useful for production or when verified boot is not in use. +Enable ``CONFIG_FASTBOOT_OEM_RUN`` to use this functionality. This will enable +``oem run`` command, which can be used with the fastboot client. For example, +to print "Hello at 115200 baud" (or whatever ``CONFIG_BAUDRATE`` is), run:: + + $ fastboot oem run:'echo Hello at $baudrate baud' + +You can run any command you would normally run on the U-Boot command line, +including multiple commands (using e.g. ``;`` or ``&&``) and control structures +(``if``, ``while``, etc.). The exit code of ``fastboot`` will reflect the exit +code of the command you ran. + References ---------- diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index b97c67bf609..eefa34779c4 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -80,12 +80,13 @@ config FASTBOOT_FLASH this to enable the "fastboot flash" command. config FASTBOOT_UUU_SUPPORT - bool "Enable FASTBOOT i.MX UUU special command" + bool "Enable UUU support" help - The fastboot protocol includes "UCmd" and "ACmd" command. - Be aware that you provide full access to any U-Boot command, - including working with memory and may open a huge backdoor, - when enabling this option. + This extends the fastboot protocol with the "UCmd" and "ACmd" + commands, which are used by NXP's "universal update utility" (UUU). + These commands allow running any shell command. Do not enable this + feature if you are using verified boot, as it will allow an attacker + to bypass any restrictions you have in place. choice prompt "Flash provider for FASTBOOT" @@ -218,6 +219,14 @@ config FASTBOOT_CMD_OEM_BOOTBUS Add support for the "oem bootbus" command from a client. This set the mmc boot configuration for the selecting eMMC device. +config FASTBOOT_OEM_RUN + bool "Enable the 'oem run' command" + help + This extends the fastboot protocol with an "oem run" command. This + command allows running arbitrary U-Boot shell commands. Do not enable + this feature if you are using verified boot, as it will allow an + attacker to bypass any restrictions you have in place. + endif # FASTBOOT endmenu diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c index f0fd605854d..67a94798287 100644 --- a/drivers/fastboot/fb_command.c +++ b/drivers/fastboot/fb_command.c @@ -102,6 +102,10 @@ static const struct { .command = "oem bootbus", .dispatch = CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_BOOTBUS, (oem_bootbus), (NULL)) }, + [FASTBOOT_COMMAND_OEM_RUN] = { + .command = "oem run", + .dispatch = CONFIG_IS_ENABLED(FASTBOOT_OEM_RUN, (run_ucmd), (NULL)) + }, [FASTBOOT_COMMAND_UCMD] = { .command = "UCmd", .dispatch = CONFIG_IS_ENABLED(FASTBOOT_UUU_SUPPORT, (run_ucmd), (NULL)) diff --git a/include/fastboot.h b/include/fastboot.h index d062a3469ef..07f4c8fa711 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -36,6 +36,7 @@ enum { FASTBOOT_COMMAND_OEM_FORMAT, FASTBOOT_COMMAND_OEM_PARTCONF, FASTBOOT_COMMAND_OEM_BOOTBUS, + FASTBOOT_COMMAND_OEM_RUN, FASTBOOT_COMMAND_ACMD, FASTBOOT_COMMAND_UCMD, FASTBOOT_COMMAND_COUNT -- cgit v1.3.1 From f08dcd9fd063af293a4551c1b195efec2ad5f7df Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 20 Dec 2022 07:26:00 +0100 Subject: test: cmd: exit: Add unit test for exit and partly run commands Add a test which validates that exit from environment script works as expected, including return value propagation and clipping to positive integers. Reviewed-by: Simon Glass Signed-off-by: Marek Vasut --- include/test/suites.h | 1 + test/cmd/Makefile | 2 +- test/cmd/exit.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++ test/cmd_ut.c | 1 + 4 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 test/cmd/exit.c (limited to 'include') diff --git a/include/test/suites.h b/include/test/suites.h index a01000e127b..9ce49cbb031 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -38,6 +38,7 @@ int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_exit(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_font(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); diff --git a/test/cmd/Makefile b/test/cmd/Makefile index bc961df3dce..09e410ec30e 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -8,7 +8,7 @@ endif ifdef CONFIG_CONSOLE_RECORD obj-$(CONFIG_CMD_PAUSE) += test_pause.o endif -obj-y += mem.o +obj-y += exit.o mem.o obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o obj-$(CONFIG_CMD_FDT) += fdt.o obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o diff --git a/test/cmd/exit.c b/test/cmd/exit.c new file mode 100644 index 00000000000..ca34abef899 --- /dev/null +++ b/test/cmd/exit.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for exit command + * + * Copyright 2022 Marek Vasut + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Declare a new exit test */ +#define EXIT_TEST(_name, _flags) UNIT_TEST(_name, _flags, exit_test) + +/* Test 'exit addr' getting/setting address */ +static int cmd_exit_test(struct unit_test_state *uts) +{ + int i; + + /* + * Test 'exit' with parameter -3, -2, -1, 0, 1, 2, 3 . Use all those + * parameters to cover also the special return value -2 that is used + * in HUSH to detect exit command. + * + * Always test whether 'exit' command: + * - exits out of the 'run' command + * - return value is propagated out of the 'run' command + * - return value can be tested on outside of 'run' command + * - return value can be printed outside of 'run' command + */ + for (i = -3; i <= 3; i++) { + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; exit %d ; echo baz' ; run foo ; echo $?", i)); + ut_assert_nextline("bar"); + ut_assert_nextline("%d", i > 0 ? i : 0); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; exit %d ; echo baz' ; run foo && echo quux ; echo $?", i)); + ut_assert_nextline("bar"); + if (i <= 0) + ut_assert_nextline("quux"); + ut_assert_nextline("%d", i > 0 ? i : 0); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; exit %d ; echo baz' ; run foo || echo quux ; echo $?", i)); + ut_assert_nextline("bar"); + if (i > 0) + ut_assert_nextline("quux"); + /* Either 'exit' returns 0, or 'echo quux' returns 0 */ + ut_assert_nextline("0"); + ut_assertok(ut_check_console_end(uts)); + } + + /* Validate that 'exit' behaves the same way as 'exit 0' */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo ; echo $?", i)); + ut_assert_nextline("bar"); + ut_assert_nextline("0"); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo && echo quux ; echo $?", i)); + ut_assert_nextline("bar"); + ut_assert_nextline("quux"); + ut_assert_nextline("0"); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; exit ; echo baz' ; run foo || echo quux ; echo $?", i)); + ut_assert_nextline("bar"); + /* Either 'exit' returns 0, or 'echo quux' returns 0 */ + ut_assert_nextline("0"); + ut_assertok(ut_check_console_end(uts)); + + /* Validate that return value still propagates from 'run' command */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo ; echo $?", i)); + ut_assert_nextline("bar"); + ut_assert_nextline("0"); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo && echo quux ; echo $?", i)); + ut_assert_nextline("bar"); + ut_assert_nextline("quux"); + ut_assert_nextline("0"); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; true' ; run foo || echo quux ; echo $?", i)); + ut_assert_nextline("bar"); + /* The 'true' returns 0 */ + ut_assert_nextline("0"); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo ; echo $?", i)); + ut_assert_nextline("bar"); + ut_assert_nextline("1"); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo && echo quux ; echo $?", i)); + ut_assert_nextline("bar"); + ut_assert_nextline("1"); + ut_assertok(ut_check_console_end(uts)); + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("setenv foo 'echo bar ; false' ; run foo || echo quux ; echo $?", i)); + ut_assert_nextline("bar"); + ut_assert_nextline("quux"); + /* The 'echo quux' returns 0 */ + ut_assert_nextline("0"); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} + +EXIT_TEST(cmd_exit_test, UT_TESTF_CONSOLE_REC); + +int do_ut_exit(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(exit_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(exit_test); + + return cmd_ut_category("cmd_exit", "exit_test_", tests, n_ents, + argc, argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 2736582f11c..067bd0828a1 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -65,6 +65,7 @@ static struct cmd_tbl cmd_ut_sub[] = { #if defined(CONFIG_UT_ENV) U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""), #endif + U_BOOT_CMD_MKENT(exit, CONFIG_SYS_MAXARGS, 1, do_ut_exit, "", ""), #ifdef CONFIG_CMD_FDT U_BOOT_CMD_MKENT(fdt, CONFIG_SYS_MAXARGS, 1, do_ut_fdt, "", ""), #endif -- cgit v1.3.1