X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=common%2Fcli.c;h=a433ef21663cfb112cb6acd40e38057f22acab1e;hb=beb71279d865deb77b2faa86d7d1d180df8339a0;hp=4ac9b3f017cbe547aa93ad810c02cff10cc15459;hpb=c1bb2cd0b6a3d1b152be3686601234b3a363772b;p=oweals%2Fu-boot.git diff --git a/common/cli.c b/common/cli.c index 4ac9b3f017..a433ef2166 100644 --- a/common/cli.c +++ b/common/cli.c @@ -12,8 +12,13 @@ #include #include #include +#include +#include #include +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_CMDLINE /* * Run a command using the selected parser. * @@ -23,7 +28,7 @@ */ int run_command(const char *cmd, int flag) { -#ifndef CONFIG_SYS_HUSH_PARSER +#ifndef CONFIG_HUSH_PARSER /* * cli_run_command can return 0 or 1 for success, so clean up * its result. @@ -33,10 +38,38 @@ int run_command(const char *cmd, int flag) return 0; #else - return parse_string_outer(cmd, - FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP); + int hush_flags = FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP; + + if (flag & CMD_FLAG_ENV) + hush_flags |= FLAG_CONT_ON_NEWLINE; + return parse_string_outer(cmd, hush_flags); +#endif +} + +/* + * Run a command using the selected parser, and check if it is repeatable. + * + * @param cmd Command to run + * @param flag Execution flags (CMD_FLAG_...) + * @return 0 (not repeatable) or 1 (repeatable) on success, -1 on error. + */ +int run_command_repeatable(const char *cmd, int flag) +{ +#ifndef CONFIG_HUSH_PARSER + return cli_simple_run_command(cmd, flag); +#else + /* + * parse_string_outer() returns 1 for failure, so clean up + * its result. + */ + if (parse_string_outer(cmd, + FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP)) + return -1; + + return 0; #endif } +#endif /* CONFIG_CMDLINE */ int run_command_list(const char *cmd, int len, int flag) { @@ -46,7 +79,7 @@ int run_command_list(const char *cmd, int len, int flag) if (len == -1) { len = strlen(cmd); -#ifdef CONFIG_SYS_HUSH_PARSER +#ifdef CONFIG_HUSH_PARSER /* hush will never change our string */ need_buff = 0; #else @@ -61,7 +94,7 @@ int run_command_list(const char *cmd, int len, int flag) memcpy(buff, cmd, len); buff[len] = '\0'; } -#ifdef CONFIG_SYS_HUSH_PARSER +#ifdef CONFIG_HUSH_PARSER rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON); #else /* @@ -71,10 +104,14 @@ int run_command_list(const char *cmd, int len, int flag) * doing a malloc() which is actually required only in a case that * is pretty rare. */ +#ifdef CONFIG_CMDLINE rcode = cli_simple_run_command_list(buff, flag); +#else + rcode = board_run_command(buff); +#endif +#endif if (need_buff) free(buff); -#endif return rcode; } @@ -98,27 +135,99 @@ int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; } - if (run_command(arg, flag) != 0) + if (run_command(arg, flag | CMD_FLAG_ENV) != 0) return 1; } return 0; } #endif +#if CONFIG_IS_ENABLED(OF_CONTROL) +bool cli_process_fdt(const char **cmdp) +{ + /* Allow the fdt to override the boot command */ + char *env = fdtdec_get_config_string(gd->fdt_blob, "bootcmd"); + if (env) + *cmdp = env; + /* + * If the bootsecure option was chosen, use secure_boot_cmd(). + * Always use 'env' in this case, since bootsecure requres that the + * bootcmd was specified in the FDT too. + */ + return fdtdec_get_config_int(gd->fdt_blob, "bootsecure", 0) != 0; +} + +/* + * Runs the given boot command securely. Specifically: + * - Doesn't run the command with the shell (run_command or parse_string_outer), + * since that's a lot of code surface that an attacker might exploit. + * Because of this, we don't do any argument parsing--the secure boot command + * has to be a full-fledged u-boot command. + * - Doesn't check for keypresses before booting, since that could be a + * security hole; also disables Ctrl-C. + * - Doesn't allow the command to return. + * + * Upon any failures, this function will drop into an infinite loop after + * printing the error message to console. + */ +void cli_secure_boot_cmd(const char *cmd) +{ +#ifdef CONFIG_CMDLINE + cmd_tbl_t *cmdtp; +#endif + int rc; + + if (!cmd) { + printf("## Error: Secure boot command not specified\n"); + goto err; + } + + /* Disable Ctrl-C just in case some command is used that checks it. */ + disable_ctrlc(1); + + /* Find the command directly. */ +#ifdef CONFIG_CMDLINE + cmdtp = find_cmd(cmd); + if (!cmdtp) { + printf("## Error: \"%s\" not defined\n", cmd); + goto err; + } + + /* Run the command, forcing no flags and faking argc and argv. */ + rc = (cmdtp->cmd)(cmdtp, 0, 1, (char **)&cmd); + +#else + rc = board_run_command(cmd); +#endif + + /* Shouldn't ever return from boot command. */ + printf("## Error: \"%s\" returned (code %d)\n", cmd, rc); + +err: + /* + * Not a whole lot to do here. Rebooting won't help much, since we'll + * just end up right back here. Just loop. + */ + hang(); +} +#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ + void cli_loop(void) { -#ifdef CONFIG_SYS_HUSH_PARSER +#ifdef CONFIG_HUSH_PARSER parse_file_outer(); /* This point is never reached */ for (;;); -#else +#elif defined(CONFIG_CMDLINE) cli_simple_loop(); -#endif /*CONFIG_SYS_HUSH_PARSER*/ +#else + printf("## U-Boot command line is disabled. Please enable CONFIG_CMDLINE\n"); +#endif /*CONFIG_HUSH_PARSER*/ } void cli_init(void) { -#ifdef CONFIG_SYS_HUSH_PARSER +#ifdef CONFIG_HUSH_PARSER u_boot_hush_start(); #endif