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