Commit 66ded17dfc8110f0d9aa9d50fe140a320bfa4e53
Committed by
Tom Rini
1 parent
e1bf824dfd
Exists in
v2017.01-smarct4x
and in
40 other branches
Move autoboot code to autoboot.c
The autoboot code is complex and long. It deserves its own file with a simple interface from main.c. Signed-off-by: Simon Glass <sjg@chromium.org>
Showing 4 changed files with 393 additions and 364 deletions Side-by-side Diff
common/Makefile
... | ... | @@ -23,6 +23,11 @@ |
23 | 23 | obj-y += xyzModem.o |
24 | 24 | obj-y += cmd_disk.o |
25 | 25 | |
26 | +# This option is not just y/n - it can have a numeric value | |
27 | +ifdef CONFIG_BOOTDELAY | |
28 | +obj-y += autoboot.o | |
29 | +endif | |
30 | + | |
26 | 31 | # boards |
27 | 32 | obj-$(CONFIG_SYS_GENERIC_BOARD) += board_f.o |
28 | 33 | obj-$(CONFIG_SYS_GENERIC_BOARD) += board_r.o |
common/autoboot.c
1 | +/* | |
2 | + * (C) Copyright 2000 | |
3 | + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
4 | + * | |
5 | + * SPDX-License-Identifier: GPL-2.0+ | |
6 | + */ | |
7 | + | |
8 | +#include <common.h> | |
9 | +#include <cli.h> | |
10 | +#include <fdtdec.h> | |
11 | +#include <menu.h> | |
12 | +#include <post.h> | |
13 | + | |
14 | +DECLARE_GLOBAL_DATA_PTR; | |
15 | + | |
16 | +#define MAX_DELAY_STOP_STR 32 | |
17 | + | |
18 | +#ifndef DEBUG_BOOTKEYS | |
19 | +#define DEBUG_BOOTKEYS 0 | |
20 | +#endif | |
21 | +#define debug_bootkeys(fmt, args...) \ | |
22 | + debug_cond(DEBUG_BOOTKEYS, fmt, ##args) | |
23 | + | |
24 | +/*************************************************************************** | |
25 | + * Watch for 'delay' seconds for autoboot stop or autoboot delay string. | |
26 | + * returns: 0 - no key string, allow autoboot 1 - got key string, abort | |
27 | + */ | |
28 | +# if defined(CONFIG_AUTOBOOT_KEYED) | |
29 | +static int abortboot_keyed(int bootdelay) | |
30 | +{ | |
31 | + int abort = 0; | |
32 | + uint64_t etime = endtick(bootdelay); | |
33 | + struct { | |
34 | + char *str; | |
35 | + u_int len; | |
36 | + int retry; | |
37 | + } | |
38 | + delaykey[] = { | |
39 | + { str: getenv("bootdelaykey"), retry: 1 }, | |
40 | + { str: getenv("bootdelaykey2"), retry: 1 }, | |
41 | + { str: getenv("bootstopkey"), retry: 0 }, | |
42 | + { str: getenv("bootstopkey2"), retry: 0 }, | |
43 | + }; | |
44 | + | |
45 | + char presskey[MAX_DELAY_STOP_STR]; | |
46 | + u_int presskey_len = 0; | |
47 | + u_int presskey_max = 0; | |
48 | + u_int i; | |
49 | + | |
50 | +#ifndef CONFIG_ZERO_BOOTDELAY_CHECK | |
51 | + if (bootdelay == 0) | |
52 | + return 0; | |
53 | +#endif | |
54 | + | |
55 | +# ifdef CONFIG_AUTOBOOT_PROMPT | |
56 | + printf(CONFIG_AUTOBOOT_PROMPT); | |
57 | +# endif | |
58 | + | |
59 | +# ifdef CONFIG_AUTOBOOT_DELAY_STR | |
60 | + if (delaykey[0].str == NULL) | |
61 | + delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; | |
62 | +# endif | |
63 | +# ifdef CONFIG_AUTOBOOT_DELAY_STR2 | |
64 | + if (delaykey[1].str == NULL) | |
65 | + delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2; | |
66 | +# endif | |
67 | +# ifdef CONFIG_AUTOBOOT_STOP_STR | |
68 | + if (delaykey[2].str == NULL) | |
69 | + delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR; | |
70 | +# endif | |
71 | +# ifdef CONFIG_AUTOBOOT_STOP_STR2 | |
72 | + if (delaykey[3].str == NULL) | |
73 | + delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2; | |
74 | +# endif | |
75 | + | |
76 | + for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) { | |
77 | + delaykey[i].len = delaykey[i].str == NULL ? | |
78 | + 0 : strlen(delaykey[i].str); | |
79 | + delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ? | |
80 | + MAX_DELAY_STOP_STR : delaykey[i].len; | |
81 | + | |
82 | + presskey_max = presskey_max > delaykey[i].len ? | |
83 | + presskey_max : delaykey[i].len; | |
84 | + | |
85 | + debug_bootkeys("%s key:<%s>\n", | |
86 | + delaykey[i].retry ? "delay" : "stop", | |
87 | + delaykey[i].str ? delaykey[i].str : "NULL"); | |
88 | + } | |
89 | + | |
90 | + /* In order to keep up with incoming data, check timeout only | |
91 | + * when catch up. | |
92 | + */ | |
93 | + do { | |
94 | + if (tstc()) { | |
95 | + if (presskey_len < presskey_max) { | |
96 | + presskey[presskey_len++] = getc(); | |
97 | + } else { | |
98 | + for (i = 0; i < presskey_max - 1; i++) | |
99 | + presskey[i] = presskey[i + 1]; | |
100 | + | |
101 | + presskey[i] = getc(); | |
102 | + } | |
103 | + } | |
104 | + | |
105 | + for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i++) { | |
106 | + if (delaykey[i].len > 0 && | |
107 | + presskey_len >= delaykey[i].len && | |
108 | + memcmp(presskey + presskey_len - | |
109 | + delaykey[i].len, delaykey[i].str, | |
110 | + delaykey[i].len) == 0) { | |
111 | + debug_bootkeys("got %skey\n", | |
112 | + delaykey[i].retry ? "delay" : | |
113 | + "stop"); | |
114 | + | |
115 | +# ifdef CONFIG_BOOT_RETRY_TIME | |
116 | + /* don't retry auto boot */ | |
117 | + if (!delaykey[i].retry) | |
118 | + bootretry_dont_retry(); | |
119 | +# endif | |
120 | + abort = 1; | |
121 | + } | |
122 | + } | |
123 | + } while (!abort && get_ticks() <= etime); | |
124 | + | |
125 | + if (!abort) | |
126 | + debug_bootkeys("key timeout\n"); | |
127 | + | |
128 | +#ifdef CONFIG_SILENT_CONSOLE | |
129 | + if (abort) | |
130 | + gd->flags &= ~GD_FLG_SILENT; | |
131 | +#endif | |
132 | + | |
133 | + return abort; | |
134 | +} | |
135 | + | |
136 | +# else /* !defined(CONFIG_AUTOBOOT_KEYED) */ | |
137 | + | |
138 | +#ifdef CONFIG_MENUKEY | |
139 | +static int menukey; | |
140 | +#endif | |
141 | + | |
142 | +static int abortboot_normal(int bootdelay) | |
143 | +{ | |
144 | + int abort = 0; | |
145 | + unsigned long ts; | |
146 | + | |
147 | +#ifdef CONFIG_MENUPROMPT | |
148 | + printf(CONFIG_MENUPROMPT); | |
149 | +#else | |
150 | + if (bootdelay >= 0) | |
151 | + printf("Hit any key to stop autoboot: %2d ", bootdelay); | |
152 | +#endif | |
153 | + | |
154 | +#if defined CONFIG_ZERO_BOOTDELAY_CHECK | |
155 | + /* | |
156 | + * Check if key already pressed | |
157 | + * Don't check if bootdelay < 0 | |
158 | + */ | |
159 | + if (bootdelay >= 0) { | |
160 | + if (tstc()) { /* we got a key press */ | |
161 | + (void) getc(); /* consume input */ | |
162 | + puts("\b\b\b 0"); | |
163 | + abort = 1; /* don't auto boot */ | |
164 | + } | |
165 | + } | |
166 | +#endif | |
167 | + | |
168 | + while ((bootdelay > 0) && (!abort)) { | |
169 | + --bootdelay; | |
170 | + /* delay 1000 ms */ | |
171 | + ts = get_timer(0); | |
172 | + do { | |
173 | + if (tstc()) { /* we got a key press */ | |
174 | + abort = 1; /* don't auto boot */ | |
175 | + bootdelay = 0; /* no more delay */ | |
176 | +# ifdef CONFIG_MENUKEY | |
177 | + menukey = getc(); | |
178 | +# else | |
179 | + (void) getc(); /* consume input */ | |
180 | +# endif | |
181 | + break; | |
182 | + } | |
183 | + udelay(10000); | |
184 | + } while (!abort && get_timer(ts) < 1000); | |
185 | + | |
186 | + printf("\b\b\b%2d ", bootdelay); | |
187 | + } | |
188 | + | |
189 | + putc('\n'); | |
190 | + | |
191 | +#ifdef CONFIG_SILENT_CONSOLE | |
192 | + if (abort) | |
193 | + gd->flags &= ~GD_FLG_SILENT; | |
194 | +#endif | |
195 | + | |
196 | + return abort; | |
197 | +} | |
198 | +# endif /* CONFIG_AUTOBOOT_KEYED */ | |
199 | + | |
200 | +static int abortboot(int bootdelay) | |
201 | +{ | |
202 | +#ifdef CONFIG_AUTOBOOT_KEYED | |
203 | + return abortboot_keyed(bootdelay); | |
204 | +#else | |
205 | + return abortboot_normal(bootdelay); | |
206 | +#endif | |
207 | +} | |
208 | + | |
209 | +/* | |
210 | + * Runs the given boot command securely. Specifically: | |
211 | + * - Doesn't run the command with the shell (run_command or parse_string_outer), | |
212 | + * since that's a lot of code surface that an attacker might exploit. | |
213 | + * Because of this, we don't do any argument parsing--the secure boot command | |
214 | + * has to be a full-fledged u-boot command. | |
215 | + * - Doesn't check for keypresses before booting, since that could be a | |
216 | + * security hole; also disables Ctrl-C. | |
217 | + * - Doesn't allow the command to return. | |
218 | + * | |
219 | + * Upon any failures, this function will drop into an infinite loop after | |
220 | + * printing the error message to console. | |
221 | + */ | |
222 | + | |
223 | +#if defined(CONFIG_OF_CONTROL) | |
224 | +static void secure_boot_cmd(char *cmd) | |
225 | +{ | |
226 | + cmd_tbl_t *cmdtp; | |
227 | + int rc; | |
228 | + | |
229 | + if (!cmd) { | |
230 | + printf("## Error: Secure boot command not specified\n"); | |
231 | + goto err; | |
232 | + } | |
233 | + | |
234 | + /* Disable Ctrl-C just in case some command is used that checks it. */ | |
235 | + disable_ctrlc(1); | |
236 | + | |
237 | + /* Find the command directly. */ | |
238 | + cmdtp = find_cmd(cmd); | |
239 | + if (!cmdtp) { | |
240 | + printf("## Error: \"%s\" not defined\n", cmd); | |
241 | + goto err; | |
242 | + } | |
243 | + | |
244 | + /* Run the command, forcing no flags and faking argc and argv. */ | |
245 | + rc = (cmdtp->cmd)(cmdtp, 0, 1, &cmd); | |
246 | + | |
247 | + /* Shouldn't ever return from boot command. */ | |
248 | + printf("## Error: \"%s\" returned (code %d)\n", cmd, rc); | |
249 | + | |
250 | +err: | |
251 | + /* | |
252 | + * Not a whole lot to do here. Rebooting won't help much, since we'll | |
253 | + * just end up right back here. Just loop. | |
254 | + */ | |
255 | + hang(); | |
256 | +} | |
257 | + | |
258 | +static void process_fdt_options(const void *blob) | |
259 | +{ | |
260 | + ulong addr; | |
261 | + | |
262 | + /* Add an env variable to point to a kernel payload, if available */ | |
263 | + addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0); | |
264 | + if (addr) | |
265 | + setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr)); | |
266 | + | |
267 | + /* Add an env variable to point to a root disk, if available */ | |
268 | + addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0); | |
269 | + if (addr) | |
270 | + setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr)); | |
271 | +} | |
272 | +#endif /* CONFIG_OF_CONTROL */ | |
273 | + | |
274 | +void bootdelay_process(void) | |
275 | +{ | |
276 | +#ifdef CONFIG_OF_CONTROL | |
277 | + char *env; | |
278 | +#endif | |
279 | + char *s; | |
280 | + int bootdelay; | |
281 | +#ifdef CONFIG_BOOTCOUNT_LIMIT | |
282 | + unsigned long bootcount = 0; | |
283 | + unsigned long bootlimit = 0; | |
284 | +#endif /* CONFIG_BOOTCOUNT_LIMIT */ | |
285 | + | |
286 | +#ifdef CONFIG_BOOTCOUNT_LIMIT | |
287 | + bootcount = bootcount_load(); | |
288 | + bootcount++; | |
289 | + bootcount_store(bootcount); | |
290 | + setenv_ulong("bootcount", bootcount); | |
291 | + bootlimit = getenv_ulong("bootlimit", 10, 0); | |
292 | +#endif /* CONFIG_BOOTCOUNT_LIMIT */ | |
293 | + | |
294 | + s = getenv("bootdelay"); | |
295 | + bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; | |
296 | + | |
297 | +#ifdef CONFIG_OF_CONTROL | |
298 | + bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", | |
299 | + bootdelay); | |
300 | +#endif | |
301 | + | |
302 | + debug("### main_loop entered: bootdelay=%d\n\n", bootdelay); | |
303 | + | |
304 | +#if defined(CONFIG_MENU_SHOW) | |
305 | + bootdelay = menu_show(bootdelay); | |
306 | +#endif | |
307 | +# ifdef CONFIG_BOOT_RETRY_TIME | |
308 | + init_cmd_timeout(); | |
309 | +# endif /* CONFIG_BOOT_RETRY_TIME */ | |
310 | + | |
311 | +#ifdef CONFIG_POST | |
312 | + if (gd->flags & GD_FLG_POSTFAIL) { | |
313 | + s = getenv("failbootcmd"); | |
314 | + } else | |
315 | +#endif /* CONFIG_POST */ | |
316 | +#ifdef CONFIG_BOOTCOUNT_LIMIT | |
317 | + if (bootlimit && (bootcount > bootlimit)) { | |
318 | + printf("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n", | |
319 | + (unsigned)bootlimit); | |
320 | + s = getenv("altbootcmd"); | |
321 | + } else | |
322 | +#endif /* CONFIG_BOOTCOUNT_LIMIT */ | |
323 | + s = getenv("bootcmd"); | |
324 | +#ifdef CONFIG_OF_CONTROL | |
325 | + /* Allow the fdt to override the boot command */ | |
326 | + env = fdtdec_get_config_string(gd->fdt_blob, "bootcmd"); | |
327 | + if (env) | |
328 | + s = env; | |
329 | + | |
330 | + process_fdt_options(gd->fdt_blob); | |
331 | + | |
332 | + /* | |
333 | + * If the bootsecure option was chosen, use secure_boot_cmd(). | |
334 | + * Always use 'env' in this case, since bootsecure requres that the | |
335 | + * bootcmd was specified in the FDT too. | |
336 | + */ | |
337 | + if (fdtdec_get_config_int(gd->fdt_blob, "bootsecure", 0)) | |
338 | + secure_boot_cmd(env); | |
339 | + | |
340 | +#endif /* CONFIG_OF_CONTROL */ | |
341 | + | |
342 | + debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); | |
343 | + | |
344 | + if (bootdelay != -1 && s && !abortboot(bootdelay)) { | |
345 | +#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC) | |
346 | + int prev = disable_ctrlc(1); /* disable Control C checking */ | |
347 | +#endif | |
348 | + | |
349 | + run_command_list(s, -1, 0); | |
350 | + | |
351 | +#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC) | |
352 | + disable_ctrlc(prev); /* restore Control C checking */ | |
353 | +#endif | |
354 | + } | |
355 | + | |
356 | +#ifdef CONFIG_MENUKEY | |
357 | + if (menukey == CONFIG_MENUKEY) { | |
358 | + s = getenv("menucmd"); | |
359 | + if (s) | |
360 | + run_command_list(s, -1, 0); | |
361 | + } | |
362 | +#endif /* CONFIG_MENUKEY */ | |
363 | +} |
common/main.c
... | ... | @@ -8,384 +8,24 @@ |
8 | 8 | /* #define DEBUG */ |
9 | 9 | |
10 | 10 | #include <common.h> |
11 | +#include <autoboot.h> | |
11 | 12 | #include <cli.h> |
12 | 13 | #include <command.h> |
13 | -#include <fdtdec.h> | |
14 | 14 | #include <cli_hush.h> |
15 | 15 | #include <malloc.h> |
16 | -#include <menu.h> | |
17 | -#include <post.h> | |
18 | 16 | #include <version.h> |
19 | 17 | |
20 | -DECLARE_GLOBAL_DATA_PTR; | |
21 | - | |
22 | 18 | /* |
23 | 19 | * Board-specific Platform code can reimplement show_boot_progress () if needed |
24 | 20 | */ |
25 | 21 | void inline __show_boot_progress (int val) {} |
26 | 22 | void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress"))); |
27 | 23 | |
28 | -#define MAX_DELAY_STOP_STR 32 | |
29 | - | |
30 | -#ifndef DEBUG_BOOTKEYS | |
31 | -#define DEBUG_BOOTKEYS 0 | |
32 | -#endif | |
33 | -#define debug_bootkeys(fmt, args...) \ | |
34 | - debug_cond(DEBUG_BOOTKEYS, fmt, ##args) | |
35 | - | |
36 | 24 | #ifdef CONFIG_MODEM_SUPPORT |
37 | 25 | int do_mdm_init = 0; |
38 | 26 | extern void mdm_init(void); /* defined in board.c */ |
39 | 27 | #endif |
40 | 28 | |
41 | -/*************************************************************************** | |
42 | - * Watch for 'delay' seconds for autoboot stop or autoboot delay string. | |
43 | - * returns: 0 - no key string, allow autoboot 1 - got key string, abort | |
44 | - */ | |
45 | -#if defined(CONFIG_BOOTDELAY) | |
46 | -# if defined(CONFIG_AUTOBOOT_KEYED) | |
47 | -static int abortboot_keyed(int bootdelay) | |
48 | -{ | |
49 | - int abort = 0; | |
50 | - uint64_t etime = endtick(bootdelay); | |
51 | - struct { | |
52 | - char* str; | |
53 | - u_int len; | |
54 | - int retry; | |
55 | - } | |
56 | - delaykey [] = { | |
57 | - { str: getenv ("bootdelaykey"), retry: 1 }, | |
58 | - { str: getenv ("bootdelaykey2"), retry: 1 }, | |
59 | - { str: getenv ("bootstopkey"), retry: 0 }, | |
60 | - { str: getenv ("bootstopkey2"), retry: 0 }, | |
61 | - }; | |
62 | - | |
63 | - char presskey [MAX_DELAY_STOP_STR]; | |
64 | - u_int presskey_len = 0; | |
65 | - u_int presskey_max = 0; | |
66 | - u_int i; | |
67 | - | |
68 | -#ifndef CONFIG_ZERO_BOOTDELAY_CHECK | |
69 | - if (bootdelay == 0) | |
70 | - return 0; | |
71 | -#endif | |
72 | - | |
73 | -# ifdef CONFIG_AUTOBOOT_PROMPT | |
74 | - printf(CONFIG_AUTOBOOT_PROMPT); | |
75 | -# endif | |
76 | - | |
77 | -# ifdef CONFIG_AUTOBOOT_DELAY_STR | |
78 | - if (delaykey[0].str == NULL) | |
79 | - delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; | |
80 | -# endif | |
81 | -# ifdef CONFIG_AUTOBOOT_DELAY_STR2 | |
82 | - if (delaykey[1].str == NULL) | |
83 | - delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2; | |
84 | -# endif | |
85 | -# ifdef CONFIG_AUTOBOOT_STOP_STR | |
86 | - if (delaykey[2].str == NULL) | |
87 | - delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR; | |
88 | -# endif | |
89 | -# ifdef CONFIG_AUTOBOOT_STOP_STR2 | |
90 | - if (delaykey[3].str == NULL) | |
91 | - delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2; | |
92 | -# endif | |
93 | - | |
94 | - for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { | |
95 | - delaykey[i].len = delaykey[i].str == NULL ? | |
96 | - 0 : strlen (delaykey[i].str); | |
97 | - delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ? | |
98 | - MAX_DELAY_STOP_STR : delaykey[i].len; | |
99 | - | |
100 | - presskey_max = presskey_max > delaykey[i].len ? | |
101 | - presskey_max : delaykey[i].len; | |
102 | - | |
103 | - debug_bootkeys("%s key:<%s>\n", | |
104 | - delaykey[i].retry ? "delay" : "stop", | |
105 | - delaykey[i].str ? delaykey[i].str : "NULL"); | |
106 | - } | |
107 | - | |
108 | - /* In order to keep up with incoming data, check timeout only | |
109 | - * when catch up. | |
110 | - */ | |
111 | - do { | |
112 | - if (tstc()) { | |
113 | - if (presskey_len < presskey_max) { | |
114 | - presskey [presskey_len ++] = getc(); | |
115 | - } | |
116 | - else { | |
117 | - for (i = 0; i < presskey_max - 1; i ++) | |
118 | - presskey [i] = presskey [i + 1]; | |
119 | - | |
120 | - presskey [i] = getc(); | |
121 | - } | |
122 | - } | |
123 | - | |
124 | - for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { | |
125 | - if (delaykey[i].len > 0 && | |
126 | - presskey_len >= delaykey[i].len && | |
127 | - memcmp (presskey + presskey_len - delaykey[i].len, | |
128 | - delaykey[i].str, | |
129 | - delaykey[i].len) == 0) { | |
130 | - debug_bootkeys("got %skey\n", | |
131 | - delaykey[i].retry ? "delay" : | |
132 | - "stop"); | |
133 | - | |
134 | -# ifdef CONFIG_BOOT_RETRY_TIME | |
135 | - /* don't retry auto boot */ | |
136 | - if (! delaykey[i].retry) | |
137 | - bootretry_dont_retry(); | |
138 | -# endif | |
139 | - abort = 1; | |
140 | - } | |
141 | - } | |
142 | - } while (!abort && get_ticks() <= etime); | |
143 | - | |
144 | - if (!abort) | |
145 | - debug_bootkeys("key timeout\n"); | |
146 | - | |
147 | -#ifdef CONFIG_SILENT_CONSOLE | |
148 | - if (abort) | |
149 | - gd->flags &= ~GD_FLG_SILENT; | |
150 | -#endif | |
151 | - | |
152 | - return abort; | |
153 | -} | |
154 | - | |
155 | -# else /* !defined(CONFIG_AUTOBOOT_KEYED) */ | |
156 | - | |
157 | -#ifdef CONFIG_MENUKEY | |
158 | -static int menukey = 0; | |
159 | -#endif | |
160 | - | |
161 | -static int abortboot_normal(int bootdelay) | |
162 | -{ | |
163 | - int abort = 0; | |
164 | - unsigned long ts; | |
165 | - | |
166 | -#ifdef CONFIG_MENUPROMPT | |
167 | - printf(CONFIG_MENUPROMPT); | |
168 | -#else | |
169 | - if (bootdelay >= 0) | |
170 | - printf("Hit any key to stop autoboot: %2d ", bootdelay); | |
171 | -#endif | |
172 | - | |
173 | -#if defined CONFIG_ZERO_BOOTDELAY_CHECK | |
174 | - /* | |
175 | - * Check if key already pressed | |
176 | - * Don't check if bootdelay < 0 | |
177 | - */ | |
178 | - if (bootdelay >= 0) { | |
179 | - if (tstc()) { /* we got a key press */ | |
180 | - (void) getc(); /* consume input */ | |
181 | - puts ("\b\b\b 0"); | |
182 | - abort = 1; /* don't auto boot */ | |
183 | - } | |
184 | - } | |
185 | -#endif | |
186 | - | |
187 | - while ((bootdelay > 0) && (!abort)) { | |
188 | - --bootdelay; | |
189 | - /* delay 1000 ms */ | |
190 | - ts = get_timer(0); | |
191 | - do { | |
192 | - if (tstc()) { /* we got a key press */ | |
193 | - abort = 1; /* don't auto boot */ | |
194 | - bootdelay = 0; /* no more delay */ | |
195 | -# ifdef CONFIG_MENUKEY | |
196 | - menukey = getc(); | |
197 | -# else | |
198 | - (void) getc(); /* consume input */ | |
199 | -# endif | |
200 | - break; | |
201 | - } | |
202 | - udelay(10000); | |
203 | - } while (!abort && get_timer(ts) < 1000); | |
204 | - | |
205 | - printf("\b\b\b%2d ", bootdelay); | |
206 | - } | |
207 | - | |
208 | - putc('\n'); | |
209 | - | |
210 | -#ifdef CONFIG_SILENT_CONSOLE | |
211 | - if (abort) | |
212 | - gd->flags &= ~GD_FLG_SILENT; | |
213 | -#endif | |
214 | - | |
215 | - return abort; | |
216 | -} | |
217 | -# endif /* CONFIG_AUTOBOOT_KEYED */ | |
218 | - | |
219 | -static int abortboot(int bootdelay) | |
220 | -{ | |
221 | -#ifdef CONFIG_AUTOBOOT_KEYED | |
222 | - return abortboot_keyed(bootdelay); | |
223 | -#else | |
224 | - return abortboot_normal(bootdelay); | |
225 | -#endif | |
226 | -} | |
227 | -#endif /* CONFIG_BOOTDELAY */ | |
228 | - | |
229 | -/* | |
230 | - * Runs the given boot command securely. Specifically: | |
231 | - * - Doesn't run the command with the shell (run_command or parse_string_outer), | |
232 | - * since that's a lot of code surface that an attacker might exploit. | |
233 | - * Because of this, we don't do any argument parsing--the secure boot command | |
234 | - * has to be a full-fledged u-boot command. | |
235 | - * - Doesn't check for keypresses before booting, since that could be a | |
236 | - * security hole; also disables Ctrl-C. | |
237 | - * - Doesn't allow the command to return. | |
238 | - * | |
239 | - * Upon any failures, this function will drop into an infinite loop after | |
240 | - * printing the error message to console. | |
241 | - */ | |
242 | - | |
243 | -#if defined(CONFIG_BOOTDELAY) && defined(CONFIG_OF_CONTROL) | |
244 | -static void secure_boot_cmd(char *cmd) | |
245 | -{ | |
246 | - cmd_tbl_t *cmdtp; | |
247 | - int rc; | |
248 | - | |
249 | - if (!cmd) { | |
250 | - printf("## Error: Secure boot command not specified\n"); | |
251 | - goto err; | |
252 | - } | |
253 | - | |
254 | - /* Disable Ctrl-C just in case some command is used that checks it. */ | |
255 | - disable_ctrlc(1); | |
256 | - | |
257 | - /* Find the command directly. */ | |
258 | - cmdtp = find_cmd(cmd); | |
259 | - if (!cmdtp) { | |
260 | - printf("## Error: \"%s\" not defined\n", cmd); | |
261 | - goto err; | |
262 | - } | |
263 | - | |
264 | - /* Run the command, forcing no flags and faking argc and argv. */ | |
265 | - rc = (cmdtp->cmd)(cmdtp, 0, 1, &cmd); | |
266 | - | |
267 | - /* Shouldn't ever return from boot command. */ | |
268 | - printf("## Error: \"%s\" returned (code %d)\n", cmd, rc); | |
269 | - | |
270 | -err: | |
271 | - /* | |
272 | - * Not a whole lot to do here. Rebooting won't help much, since we'll | |
273 | - * just end up right back here. Just loop. | |
274 | - */ | |
275 | - hang(); | |
276 | -} | |
277 | - | |
278 | -static void process_fdt_options(const void *blob) | |
279 | -{ | |
280 | - ulong addr; | |
281 | - | |
282 | - /* Add an env variable to point to a kernel payload, if available */ | |
283 | - addr = fdtdec_get_config_int(gd->fdt_blob, "kernel-offset", 0); | |
284 | - if (addr) | |
285 | - setenv_addr("kernaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr)); | |
286 | - | |
287 | - /* Add an env variable to point to a root disk, if available */ | |
288 | - addr = fdtdec_get_config_int(gd->fdt_blob, "rootdisk-offset", 0); | |
289 | - if (addr) | |
290 | - setenv_addr("rootaddr", (void *)(CONFIG_SYS_TEXT_BASE + addr)); | |
291 | -} | |
292 | -#endif /* CONFIG_OF_CONTROL */ | |
293 | - | |
294 | -#ifdef CONFIG_BOOTDELAY | |
295 | -static void process_boot_delay(void) | |
296 | -{ | |
297 | -#ifdef CONFIG_OF_CONTROL | |
298 | - char *env; | |
299 | -#endif | |
300 | - char *s; | |
301 | - int bootdelay; | |
302 | -#ifdef CONFIG_BOOTCOUNT_LIMIT | |
303 | - unsigned long bootcount = 0; | |
304 | - unsigned long bootlimit = 0; | |
305 | -#endif /* CONFIG_BOOTCOUNT_LIMIT */ | |
306 | - | |
307 | -#ifdef CONFIG_BOOTCOUNT_LIMIT | |
308 | - bootcount = bootcount_load(); | |
309 | - bootcount++; | |
310 | - bootcount_store (bootcount); | |
311 | - setenv_ulong("bootcount", bootcount); | |
312 | - bootlimit = getenv_ulong("bootlimit", 10, 0); | |
313 | -#endif /* CONFIG_BOOTCOUNT_LIMIT */ | |
314 | - | |
315 | - s = getenv ("bootdelay"); | |
316 | - bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; | |
317 | - | |
318 | -#ifdef CONFIG_OF_CONTROL | |
319 | - bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", | |
320 | - bootdelay); | |
321 | -#endif | |
322 | - | |
323 | - debug ("### main_loop entered: bootdelay=%d\n\n", bootdelay); | |
324 | - | |
325 | -#if defined(CONFIG_MENU_SHOW) | |
326 | - bootdelay = menu_show(bootdelay); | |
327 | -#endif | |
328 | -# ifdef CONFIG_BOOT_RETRY_TIME | |
329 | - init_cmd_timeout (); | |
330 | -# endif /* CONFIG_BOOT_RETRY_TIME */ | |
331 | - | |
332 | -#ifdef CONFIG_POST | |
333 | - if (gd->flags & GD_FLG_POSTFAIL) { | |
334 | - s = getenv("failbootcmd"); | |
335 | - } | |
336 | - else | |
337 | -#endif /* CONFIG_POST */ | |
338 | -#ifdef CONFIG_BOOTCOUNT_LIMIT | |
339 | - if (bootlimit && (bootcount > bootlimit)) { | |
340 | - printf ("Warning: Bootlimit (%u) exceeded. Using altbootcmd.\n", | |
341 | - (unsigned)bootlimit); | |
342 | - s = getenv ("altbootcmd"); | |
343 | - } | |
344 | - else | |
345 | -#endif /* CONFIG_BOOTCOUNT_LIMIT */ | |
346 | - s = getenv ("bootcmd"); | |
347 | -#ifdef CONFIG_OF_CONTROL | |
348 | - /* Allow the fdt to override the boot command */ | |
349 | - env = fdtdec_get_config_string(gd->fdt_blob, "bootcmd"); | |
350 | - if (env) | |
351 | - s = env; | |
352 | - | |
353 | - process_fdt_options(gd->fdt_blob); | |
354 | - | |
355 | - /* | |
356 | - * If the bootsecure option was chosen, use secure_boot_cmd(). | |
357 | - * Always use 'env' in this case, since bootsecure requres that the | |
358 | - * bootcmd was specified in the FDT too. | |
359 | - */ | |
360 | - if (fdtdec_get_config_int(gd->fdt_blob, "bootsecure", 0)) | |
361 | - secure_boot_cmd(env); | |
362 | - | |
363 | -#endif /* CONFIG_OF_CONTROL */ | |
364 | - | |
365 | - debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>"); | |
366 | - | |
367 | - if (bootdelay != -1 && s && !abortboot(bootdelay)) { | |
368 | -#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC) | |
369 | - int prev = disable_ctrlc(1); /* disable Control C checking */ | |
370 | -#endif | |
371 | - | |
372 | - run_command_list(s, -1, 0); | |
373 | - | |
374 | -#if defined(CONFIG_AUTOBOOT_KEYED) && !defined(CONFIG_AUTOBOOT_KEYED_CTRLC) | |
375 | - disable_ctrlc(prev); /* restore Control C checking */ | |
376 | -#endif | |
377 | - } | |
378 | - | |
379 | -#ifdef CONFIG_MENUKEY | |
380 | - if (menukey == CONFIG_MENUKEY) { | |
381 | - s = getenv("menucmd"); | |
382 | - if (s) | |
383 | - run_command_list(s, -1, 0); | |
384 | - } | |
385 | -#endif /* CONFIG_MENUKEY */ | |
386 | -} | |
387 | -#endif /* CONFIG_BOOTDELAY */ | |
388 | - | |
389 | 29 | void main_loop(void) |
390 | 30 | { |
391 | 31 | #ifdef CONFIG_PREBOOT |
... | ... | @@ -444,9 +84,7 @@ |
444 | 84 | update_tftp(0UL); |
445 | 85 | #endif /* CONFIG_UPDATE_TFTP */ |
446 | 86 | |
447 | -#ifdef CONFIG_BOOTDELAY | |
448 | - process_boot_delay(); | |
449 | -#endif | |
87 | + bootdelay_process(); | |
450 | 88 | /* |
451 | 89 | * Main Loop for Monitor Command Processing |
452 | 90 | */ |
include/autoboot.h
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 | +#ifndef __AUTOBOOT_H | |
13 | +#define __AUTOBOOT_H | |
14 | + | |
15 | +#ifdef CONFIG_BOOTDELAY | |
16 | +void bootdelay_process(void); | |
17 | +#else | |
18 | +static inline void bootdelay_process(void) | |
19 | +{ | |
20 | +} | |
21 | +#endif | |
22 | + | |
23 | +#endif |