]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - common/cli.c
dm: Adjust lists_bind_fdt() to return the bound device
[karo-tx-uboot.git] / common / cli.c
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 }