xref: /openbmc/u-boot/common/main.c (revision e1bf824dfd6881f6f633238c275bfa1e5d83c433)
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 /* #define	DEBUG	*/
9 
10 #include <common.h>
11 #include <cli.h>
12 #include <command.h>
13 #include <fdtdec.h>
14 #include <cli_hush.h>
15 #include <malloc.h>
16 #include <menu.h>
17 #include <post.h>
18 #include <version.h>
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 /*
23  * Board-specific Platform code can reimplement show_boot_progress () if needed
24  */
25 void inline __show_boot_progress (int val) {}
26 void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress")));
27 
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 #ifdef CONFIG_MODEM_SUPPORT
37 int do_mdm_init = 0;
38 extern void mdm_init(void); /* defined in board.c */
39 #endif
40 
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 void main_loop(void)
390 {
391 #ifdef CONFIG_PREBOOT
392 	char *p;
393 #endif
394 
395 	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
396 
397 #ifndef CONFIG_SYS_GENERIC_BOARD
398 	puts("Warning: Your board does not use generic board. Please read\n");
399 	puts("doc/README.generic-board and take action. Boards not\n");
400 	puts("upgraded by the late 2014 may break or be removed.\n");
401 #endif
402 
403 #ifdef CONFIG_MODEM_SUPPORT
404 	debug("DEBUG: main_loop:   do_mdm_init=%d\n", do_mdm_init);
405 	if (do_mdm_init) {
406 		char *str = strdup(getenv("mdm_cmd"));
407 		setenv("preboot", str);  /* set or delete definition */
408 		if (str != NULL)
409 			free(str);
410 		mdm_init(); /* wait for modem connection */
411 	}
412 #endif  /* CONFIG_MODEM_SUPPORT */
413 
414 #ifdef CONFIG_VERSION_VARIABLE
415 	{
416 		setenv("ver", version_string);  /* set version variable */
417 	}
418 #endif /* CONFIG_VERSION_VARIABLE */
419 
420 #ifdef CONFIG_SYS_HUSH_PARSER
421 	u_boot_hush_start();
422 #endif
423 
424 #if defined(CONFIG_HUSH_INIT_VAR)
425 	hush_init_var();
426 #endif
427 
428 #ifdef CONFIG_PREBOOT
429 	p = getenv("preboot");
430 	if (p != NULL) {
431 # ifdef CONFIG_AUTOBOOT_KEYED
432 		int prev = disable_ctrlc(1);	/* disable Control C checking */
433 # endif
434 
435 		run_command_list(p, -1, 0);
436 
437 # ifdef CONFIG_AUTOBOOT_KEYED
438 		disable_ctrlc(prev);	/* restore Control C checking */
439 # endif
440 	}
441 #endif /* CONFIG_PREBOOT */
442 
443 #if defined(CONFIG_UPDATE_TFTP)
444 	update_tftp(0UL);
445 #endif /* CONFIG_UPDATE_TFTP */
446 
447 #ifdef CONFIG_BOOTDELAY
448 	process_boot_delay();
449 #endif
450 	/*
451 	 * Main Loop for Monitor Command Processing
452 	 */
453 #ifdef CONFIG_SYS_HUSH_PARSER
454 	parse_file_outer();
455 	/* This point is never reached */
456 	for (;;);
457 #else
458 	cli_loop();
459 #endif /*CONFIG_SYS_HUSH_PARSER*/
460 }
461 
462 /****************************************************************************/
463 
464 /*
465  * Run a command using the selected parser.
466  *
467  * @param cmd	Command to run
468  * @param flag	Execution flags (CMD_FLAG_...)
469  * @return 0 on success, or != 0 on error.
470  */
471 int run_command(const char *cmd, int flag)
472 {
473 #ifndef CONFIG_SYS_HUSH_PARSER
474 	/*
475 	 * cli_run_command can return 0 or 1 for success, so clean up
476 	 * its result.
477 	 */
478 	if (cli_simple_run_command(cmd, flag) == -1)
479 		return 1;
480 
481 	return 0;
482 #else
483 	return parse_string_outer(cmd,
484 			FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
485 #endif
486 }
487 
488 int run_command_list(const char *cmd, int len, int flag)
489 {
490 	int need_buff = 1;
491 	char *buff = (char *)cmd;	/* cast away const */
492 	int rcode = 0;
493 
494 	if (len == -1) {
495 		len = strlen(cmd);
496 #ifdef CONFIG_SYS_HUSH_PARSER
497 		/* hush will never change our string */
498 		need_buff = 0;
499 #else
500 		/* the built-in parser will change our string if it sees \n */
501 		need_buff = strchr(cmd, '\n') != NULL;
502 #endif
503 	}
504 	if (need_buff) {
505 		buff = malloc(len + 1);
506 		if (!buff)
507 			return 1;
508 		memcpy(buff, cmd, len);
509 		buff[len] = '\0';
510 	}
511 #ifdef CONFIG_SYS_HUSH_PARSER
512 	rcode = parse_string_outer(buff, FLAG_PARSE_SEMICOLON);
513 #else
514 	/*
515 	 * This function will overwrite any \n it sees with a \0, which
516 	 * is why it can't work with a const char *. Here we are making
517 	 * using of internal knowledge of this function, to avoid always
518 	 * doing a malloc() which is actually required only in a case that
519 	 * is pretty rare.
520 	 */
521 	rcode = cli_simple_run_command_list(buff, flag);
522 	if (need_buff)
523 		free(buff);
524 #endif
525 
526 	return rcode;
527 }
528 
529 /****************************************************************************/
530 
531 #if defined(CONFIG_CMD_RUN)
532 int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
533 {
534 	int i;
535 
536 	if (argc < 2)
537 		return CMD_RET_USAGE;
538 
539 	for (i=1; i<argc; ++i) {
540 		char *arg;
541 
542 		if ((arg = getenv (argv[i])) == NULL) {
543 			printf ("## Error: \"%s\" not defined\n", argv[i]);
544 			return 1;
545 		}
546 
547 		if (run_command_list(arg, -1, flag) != 0)
548 			return 1;
549 	}
550 	return 0;
551 }
552 #endif
553