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