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