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