1 /* 2 * (C) Copyright 2000 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * Add to readline cmdline-editing by 6 * (C) Copyright 2005 7 * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com> 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 */ 11 12 #include <common.h> 13 #include <cli.h> 14 #include <cli_hush.h> 15 #include <fdtdec.h> 16 #include <malloc.h> 17 18 DECLARE_GLOBAL_DATA_PTR; 19 20 /* 21 * Run a command using the selected parser. 22 * 23 * @param cmd Command to run 24 * @param flag Execution flags (CMD_FLAG_...) 25 * @return 0 on success, or != 0 on error. 26 */ 27 int run_command(const char *cmd, int flag) 28 { 29 #ifndef CONFIG_SYS_HUSH_PARSER 30 /* 31 * cli_run_command can return 0 or 1 for success, so clean up 32 * its result. 33 */ 34 if (cli_simple_run_command(cmd, flag) == -1) 35 return 1; 36 37 return 0; 38 #else 39 int hush_flags = FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP; 40 41 if (flag & CMD_FLAG_ENV) 42 hush_flags |= FLAG_CONT_ON_NEWLINE; 43 return parse_string_outer(cmd, hush_flags); 44 #endif 45 } 46 47 /* 48 * Run a command using the selected parser, and check if it is repeatable. 49 * 50 * @param cmd Command to run 51 * @param flag Execution flags (CMD_FLAG_...) 52 * @return 0 (not repeatable) or 1 (repeatable) on success, -1 on error. 53 */ 54 int run_command_repeatable(const char *cmd, int flag) 55 { 56 #ifndef CONFIG_SYS_HUSH_PARSER 57 return cli_simple_run_command(cmd, flag); 58 #else 59 /* 60 * parse_string_outer() returns 1 for failure, so clean up 61 * its result. 62 */ 63 if (parse_string_outer(cmd, 64 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP)) 65 return -1; 66 67 return 0; 68 #endif 69 } 70 71 int run_command_list(const char *cmd, int len, int flag) 72 { 73 int need_buff = 1; 74 char *buff = (char *)cmd; /* cast away const */ 75 int rcode = 0; 76 77 if (len == -1) { 78 len = strlen(cmd); 79 #ifdef CONFIG_SYS_HUSH_PARSER 80 /* hush will never change our string */ 81 need_buff = 0; 82 #else 83 /* the built-in parser will change our string if it sees \n */ 84 need_buff = strchr(cmd, '\n') != NULL; 85 #endif 86 } 87 if (need_buff) { 88 buff = malloc(len + 1); 89 if (!buff) 90 return 1; 91 memcpy(buff, cmd, len); 92 buff[len] = '\0'; 93 } 94 #ifdef CONFIG_SYS_HUSH_PARSER 95 rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON); 96 #else 97 /* 98 * This function will overwrite any \n it sees with a \0, which 99 * is why it can't work with a const char *. Here we are making 100 * using of internal knowledge of this function, to avoid always 101 * doing a malloc() which is actually required only in a case that 102 * is pretty rare. 103 */ 104 rcode = cli_simple_run_command_list(buff, flag); 105 if (need_buff) 106 free(buff); 107 #endif 108 109 return rcode; 110 } 111 112 /****************************************************************************/ 113 114 #if defined(CONFIG_CMD_RUN) 115 int do_run(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 116 { 117 int i; 118 119 if (argc < 2) 120 return CMD_RET_USAGE; 121 122 for (i = 1; i < argc; ++i) { 123 char *arg; 124 125 arg = getenv(argv[i]); 126 if (arg == NULL) { 127 printf("## Error: \"%s\" not defined\n", argv[i]); 128 return 1; 129 } 130 131 if (run_command(arg, flag | CMD_FLAG_ENV) != 0) 132 return 1; 133 } 134 return 0; 135 } 136 #endif 137 138 #ifdef CONFIG_OF_CONTROL 139 bool cli_process_fdt(const char **cmdp) 140 { 141 /* Allow the fdt to override the boot command */ 142 char *env = fdtdec_get_config_string(gd->fdt_blob, "bootcmd"); 143 if (env) 144 *cmdp = env; 145 /* 146 * If the bootsecure option was chosen, use secure_boot_cmd(). 147 * Always use 'env' in this case, since bootsecure requres that the 148 * bootcmd was specified in the FDT too. 149 */ 150 return fdtdec_get_config_int(gd->fdt_blob, "bootsecure", 0) != 0; 151 } 152 153 /* 154 * Runs the given boot command securely. Specifically: 155 * - Doesn't run the command with the shell (run_command or parse_string_outer), 156 * since that's a lot of code surface that an attacker might exploit. 157 * Because of this, we don't do any argument parsing--the secure boot command 158 * has to be a full-fledged u-boot command. 159 * - Doesn't check for keypresses before booting, since that could be a 160 * security hole; also disables Ctrl-C. 161 * - Doesn't allow the command to return. 162 * 163 * Upon any failures, this function will drop into an infinite loop after 164 * printing the error message to console. 165 */ 166 void cli_secure_boot_cmd(const char *cmd) 167 { 168 cmd_tbl_t *cmdtp; 169 int rc; 170 171 if (!cmd) { 172 printf("## Error: Secure boot command not specified\n"); 173 goto err; 174 } 175 176 /* Disable Ctrl-C just in case some command is used that checks it. */ 177 disable_ctrlc(1); 178 179 /* Find the command directly. */ 180 cmdtp = find_cmd(cmd); 181 if (!cmdtp) { 182 printf("## Error: \"%s\" not defined\n", cmd); 183 goto err; 184 } 185 186 /* Run the command, forcing no flags and faking argc and argv. */ 187 rc = (cmdtp->cmd)(cmdtp, 0, 1, (char **)&cmd); 188 189 /* Shouldn't ever return from boot command. */ 190 printf("## Error: \"%s\" returned (code %d)\n", cmd, rc); 191 192 err: 193 /* 194 * Not a whole lot to do here. Rebooting won't help much, since we'll 195 * just end up right back here. Just loop. 196 */ 197 hang(); 198 } 199 #endif /* CONFIG_OF_CONTROL */ 200 201 void cli_loop(void) 202 { 203 #ifdef CONFIG_SYS_HUSH_PARSER 204 parse_file_outer(); 205 /* This point is never reached */ 206 for (;;); 207 #else 208 cli_simple_loop(); 209 #endif /*CONFIG_SYS_HUSH_PARSER*/ 210 } 211 212 void cli_init(void) 213 { 214 #ifdef CONFIG_SYS_HUSH_PARSER 215 u_boot_hush_start(); 216 #endif 217 218 #if defined(CONFIG_HUSH_INIT_VAR) 219 hush_init_var(); 220 #endif 221 } 222