1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2011-2013 Pali Rohár <pali@kernel.org>
4  */
5 
6 #include <charset.h>
7 #include <cli.h>
8 #include <command.h>
9 #include <ansi.h>
10 #include <efi_config.h>
11 #include <efi_variable.h>
12 #include <env.h>
13 #include <log.h>
14 #include <menu.h>
15 #include <watchdog.h>
16 #include <malloc.h>
17 #include <linux/delay.h>
18 #include <linux/string.h>
19 
20 /* maximum bootmenu entries */
21 #define MAX_COUNT	99
22 
23 /* maximal size of bootmenu env
24  *  9 = strlen("bootmenu_")
25  *  2 = strlen(MAX_COUNT)
26  *  1 = NULL term
27  */
28 #define MAX_ENV_SIZE	(9 + 2 + 1)
29 
30 enum bootmenu_ret {
31 	BOOTMENU_RET_SUCCESS = 0,
32 	BOOTMENU_RET_FAIL,
33 	BOOTMENU_RET_QUIT,
34 	BOOTMENU_RET_UPDATED,
35 };
36 
37 enum boot_type {
38 	BOOTMENU_TYPE_NONE = 0,
39 	BOOTMENU_TYPE_BOOTMENU,
40 	BOOTMENU_TYPE_UEFI_BOOT_OPTION,
41 };
42 
43 struct bootmenu_entry {
44 	unsigned short int num;		/* unique number 0 .. MAX_COUNT */
45 	char key[3];			/* key identifier of number */
46 	char *title;			/* title of entry */
47 	char *command;			/* hush command of entry */
48 	enum boot_type type;		/* boot type of entry */
49 	u16 bootorder;			/* order for each boot type */
50 	struct bootmenu_data *menu;	/* this bootmenu */
51 	struct bootmenu_entry *next;	/* next menu entry (num+1) */
52 };
53 
bootmenu_getoption(unsigned short int n)54 static char *bootmenu_getoption(unsigned short int n)
55 {
56 	char name[MAX_ENV_SIZE];
57 
58 	if (n > MAX_COUNT)
59 		return NULL;
60 
61 	sprintf(name, "bootmenu_%d", n);
62 	return env_get(name);
63 }
64 
bootmenu_print_entry(void * data)65 static void bootmenu_print_entry(void *data)
66 {
67 	struct bootmenu_entry *entry = data;
68 	int reverse = (entry->menu->active == entry->num);
69 
70 	/*
71 	 * Move cursor to line where the entry will be drown (entry->num)
72 	 * First 3 lines contain bootmenu header + 1 empty line
73 	 */
74 	printf(ANSI_CURSOR_POSITION, entry->num + 4, 7);
75 
76 	if (reverse)
77 		puts(ANSI_COLOR_REVERSE);
78 
79 	printf("%s", entry->title);
80 
81 	if (reverse)
82 		puts(ANSI_COLOR_RESET);
83 }
84 
bootmenu_choice_entry(void * data)85 static char *bootmenu_choice_entry(void *data)
86 {
87 	struct cli_ch_state s_cch, *cch = &s_cch;
88 	struct bootmenu_data *menu = data;
89 	struct bootmenu_entry *iter;
90 	enum bootmenu_key key = BKEY_NONE;
91 	int i;
92 
93 	cli_ch_init(cch);
94 
95 	while (1) {
96 		if (menu->delay >= 0) {
97 			/* Autoboot was not stopped */
98 			key = bootmenu_autoboot_loop(menu, cch);
99 		} else {
100 			/* Some key was pressed, so autoboot was stopped */
101 			key = bootmenu_loop(menu, cch);
102 		}
103 
104 		switch (key) {
105 		case BKEY_UP:
106 			menu->last_active = menu->active;
107 			if (menu->active > 0)
108 				--menu->active;
109 			/* no menu key selected, regenerate menu */
110 			return NULL;
111 		case BKEY_DOWN:
112 			menu->last_active = menu->active;
113 			if (menu->active < menu->count - 1)
114 				++menu->active;
115 			/* no menu key selected, regenerate menu */
116 			return NULL;
117 		case BKEY_SHORTCUT:
118 			/* invalid shortcut, regenerate menu */
119 			if (cch->shortcut_key >= menu->count - 1)
120 				return NULL;
121 			/* shortcut_key value for Exit is is -1 */
122 			menu->active = cch->shortcut_key < 0 ? menu->count - 1 :
123 							       cch->shortcut_key;
124 			fallthrough;
125 		case BKEY_SELECT:
126 			iter = menu->first;
127 			for (i = 0; i < menu->active; ++i)
128 				iter = iter->next;
129 			return iter->key;
130 		case BKEY_QUIT:
131 			/* Quit by choosing the last entry */
132 			iter = menu->first;
133 			while (iter->next)
134 				iter = iter->next;
135 			return iter->key;
136 		default:
137 			break;
138 		}
139 	}
140 
141 	/* never happens */
142 	debug("bootmenu: this should not happen");
143 	return NULL;
144 }
145 
bootmenu_need_reprint(void * data)146 static bool bootmenu_need_reprint(void *data)
147 {
148 	struct bootmenu_data *menu = data;
149 	bool need_reprint;
150 
151 	need_reprint = menu->last_active != menu->active;
152 	menu->last_active = menu->active;
153 
154 	return need_reprint;
155 }
156 
bootmenu_destroy(struct bootmenu_data * menu)157 static void bootmenu_destroy(struct bootmenu_data *menu)
158 {
159 	struct bootmenu_entry *iter = menu->first;
160 	struct bootmenu_entry *next;
161 
162 	while (iter) {
163 		next = iter->next;
164 		free(iter->title);
165 		free(iter->command);
166 		free(iter);
167 		iter = next;
168 	}
169 	free(menu);
170 }
171 
bootmenu_entry_shortcut_key(int index)172 static char bootmenu_entry_shortcut_key(int index)
173 {
174 	switch (index) {
175 	/* 1-9 shortcut key (0 reserved) */
176 	case 0 ... 8:
177 		return '1' + index;
178 	/* a-z shortcut key  */
179 	case 9 ... 34:
180 		return 'a' + index - 9;
181 	/* We support shortcut for up to 34 options (0 reserved) */
182 	default:
183 		return -ENOENT;
184 	}
185 }
186 
187 /**
188  * prepare_bootmenu_entry() - generate the bootmenu_xx entries
189  *
190  * This function read the "bootmenu_x" U-Boot environment variable
191  * and generate the bootmenu entries.
192  *
193  * @menu:	pointer to the bootmenu structure
194  * @current:	pointer to the last bootmenu entry list
195  * @index:	pointer to the index of the last bootmenu entry,
196  *		the number of bootmenu entry is added by this function
197  * Return:	1 on success, negative value on error
198  */
prepare_bootmenu_entry(struct bootmenu_data * menu,struct bootmenu_entry ** current,unsigned short int * index)199 static int prepare_bootmenu_entry(struct bootmenu_data *menu,
200 				  struct bootmenu_entry **current,
201 				  unsigned short int *index)
202 {
203 	char *sep;
204 	const char *option;
205 	unsigned short int i = *index;
206 	struct bootmenu_entry *entry = NULL;
207 	struct bootmenu_entry *iter = *current;
208 
209 	while ((option = bootmenu_getoption(i))) {
210 		char shortcut_key;
211 		int len;
212 
213 		/* bootmenu_[num] format is "[title]=[commands]" */
214 		sep = strchr(option, '=');
215 		if (!sep) {
216 			printf("Invalid bootmenu entry: %s\n", option);
217 			break;
218 		}
219 
220 		entry = malloc(sizeof(struct bootmenu_entry));
221 		if (!entry)
222 			return -ENOMEM;
223 
224 		/* Add shotcut key option: %c. %s\0 */
225 		len = sep - option + 4;
226 
227 		entry->title = malloc(len);
228 		if (!entry->title) {
229 			free(entry);
230 			return -ENOMEM;
231 		}
232 
233 		shortcut_key = bootmenu_entry_shortcut_key(i);
234 		/* Use emtpy space if entry doesn't support shortcut key */
235 		snprintf(entry->title, len, "%c%c %s",
236 			 shortcut_key > 0 ? shortcut_key : ' ',
237 			 shortcut_key > 0 ? '.' : ' ',
238 			 option);
239 
240 		entry->command = strdup(sep + 1);
241 		if (!entry->command) {
242 			free(entry->title);
243 			free(entry);
244 			return -ENOMEM;
245 		}
246 
247 		sprintf(entry->key, "%d", i);
248 
249 		entry->num = i;
250 		entry->menu = menu;
251 		entry->type = BOOTMENU_TYPE_BOOTMENU;
252 		entry->bootorder = i;
253 		entry->next = NULL;
254 
255 		if (!iter)
256 			menu->first = entry;
257 		else
258 			iter->next = entry;
259 
260 		iter = entry;
261 		++i;
262 
263 		if (i == MAX_COUNT - 1)
264 			break;
265 	}
266 
267 	*index = i;
268 	*current = iter;
269 
270 	return 1;
271 }
272 
273 #if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) && (IS_ENABLED(CONFIG_CMD_EFICONFIG))
274 /**
275  * prepare_uefi_bootorder_entry() - generate the uefi bootmenu entries
276  *
277  * This function reads the "BootOrder" UEFI variable
278  * and generate the bootmenu entries in the order of "BootOrder".
279  *
280  * @menu:	pointer to the bootmenu structure
281  * @current:	pointer to the last bootmenu entry list
282  * @index:	pointer to the index of the last bootmenu entry,
283  *		the number of uefi entry is added by this function
284  * Return:	1 on success, negative value on error
285  */
prepare_uefi_bootorder_entry(struct bootmenu_data * menu,struct bootmenu_entry ** current,unsigned short int * index)286 static int prepare_uefi_bootorder_entry(struct bootmenu_data *menu,
287 					struct bootmenu_entry **current,
288 					unsigned short int *index)
289 {
290 	u16 *bootorder;
291 	efi_status_t ret;
292 	unsigned short j;
293 	efi_uintn_t num, size;
294 	void *load_option;
295 	struct efi_load_option lo;
296 	u16 varname[] = u"Boot####";
297 	unsigned short int i = *index;
298 	struct bootmenu_entry *entry = NULL;
299 	struct bootmenu_entry *iter = *current;
300 
301 	bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
302 	if (!bootorder)
303 		return -ENOENT;
304 
305 	num = size / sizeof(u16);
306 	for (j = 0; j < num; j++) {
307 		entry = malloc(sizeof(struct bootmenu_entry));
308 		if (!entry)
309 			return -ENOMEM;
310 
311 		efi_create_indexed_name(varname, sizeof(varname),
312 					"Boot", bootorder[j]);
313 		load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
314 		if (!load_option)
315 			continue;
316 
317 		ret = efi_deserialize_load_option(&lo, load_option, &size);
318 		if (ret != EFI_SUCCESS) {
319 			log_warning("Invalid load option for %ls\n", varname);
320 			free(load_option);
321 			free(entry);
322 			continue;
323 		}
324 
325 		if (lo.attributes & LOAD_OPTION_ACTIVE) {
326 			char *buf;
327 
328 			buf = calloc(1, utf16_utf8_strlen(lo.label) + 1);
329 			if (!buf) {
330 				free(load_option);
331 				free(entry);
332 				free(bootorder);
333 				return -ENOMEM;
334 			}
335 			entry->title = buf;
336 			utf16_utf8_strncpy(&buf, lo.label, u16_strlen(lo.label));
337 			entry->command = strdup("bootefi bootmgr");
338 			sprintf(entry->key, "%d", i);
339 			entry->num = i;
340 			entry->menu = menu;
341 			entry->type = BOOTMENU_TYPE_UEFI_BOOT_OPTION;
342 			entry->bootorder = bootorder[j];
343 			entry->next = NULL;
344 
345 			if (!iter)
346 				menu->first = entry;
347 			else
348 				iter->next = entry;
349 
350 			iter = entry;
351 			i++;
352 		}
353 
354 		free(load_option);
355 
356 		if (i == MAX_COUNT - 1)
357 			break;
358 	}
359 
360 	free(bootorder);
361 	*index = i;
362 	*current = iter;
363 
364 	return 1;
365 }
366 #endif
367 
368 /**
369  * bootmenu_create() - create boot menu entries
370  *
371  * @uefi:	consider UEFI boot options
372  * @delay:	autostart delay in seconds
373  */
bootmenu_create(int uefi,int delay)374 static struct bootmenu_data *bootmenu_create(int uefi, int delay)
375 {
376 	int ret;
377 	unsigned short int i = 0;
378 	struct bootmenu_data *menu;
379 	struct bootmenu_entry *iter = NULL;
380 	struct bootmenu_entry *entry;
381 	char *default_str;
382 
383 	menu = malloc(sizeof(struct bootmenu_data));
384 	if (!menu)
385 		return NULL;
386 
387 	menu->delay = delay;
388 	menu->active = 0;
389 	menu->last_active = -1;
390 	menu->first = NULL;
391 
392 	default_str = env_get("bootmenu_default");
393 	if (default_str)
394 		menu->active = (int)simple_strtol(default_str, NULL, 10);
395 
396 	ret = prepare_bootmenu_entry(menu, &iter, &i);
397 	if (ret < 0)
398 		goto cleanup;
399 
400 #if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) && (IS_ENABLED(CONFIG_CMD_EFICONFIG))
401 	if (uefi && i < MAX_COUNT - 1) {
402 		efi_status_t efi_ret;
403 
404 		/*
405 		 * UEFI specification requires booting from removal media using
406 		 * a architecture-specific default image name such as BOOTAA64.EFI.
407 		 */
408 		efi_ret = efi_bootmgr_update_media_device_boot_option();
409 		if (efi_ret != EFI_SUCCESS)
410 			goto cleanup;
411 
412 		ret = prepare_uefi_bootorder_entry(menu, &iter, &i);
413 		if (ret < 0 && ret != -ENOENT)
414 			goto cleanup;
415 	}
416 #endif
417 
418 	/* Add Exit entry at the end */
419 	if (i <= MAX_COUNT - 1) {
420 		entry = malloc(sizeof(struct bootmenu_entry));
421 		if (!entry)
422 			goto cleanup;
423 
424 		/* Add Quit entry if exiting bootmenu is disabled */
425 		if (!IS_ENABLED(CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE))
426 			entry->title = strdup("0. Exit");
427 		else
428 			entry->title = strdup("0. Quit");
429 
430 		if (!entry->title) {
431 			free(entry);
432 			goto cleanup;
433 		}
434 
435 		entry->command = strdup("");
436 		if (!entry->command) {
437 			free(entry->title);
438 			free(entry);
439 			goto cleanup;
440 		}
441 
442 		sprintf(entry->key, "%d", i);
443 
444 		entry->num = i;
445 		entry->menu = menu;
446 		entry->type = BOOTMENU_TYPE_NONE;
447 		entry->next = NULL;
448 
449 		if (!iter)
450 			menu->first = entry;
451 		else
452 			iter->next = entry;
453 
454 		iter = entry;
455 		++i;
456 	}
457 
458 	menu->count = i;
459 
460 	if ((menu->active >= menu->count)||(menu->active < 0)) { //ensure active menuitem is inside menu
461 		printf("active menuitem (%d) is outside menu (0..%d)\n",menu->active,menu->count-1);
462 		menu->active=0;
463 	}
464 
465 	return menu;
466 
467 cleanup:
468 	bootmenu_destroy(menu);
469 	return NULL;
470 }
471 
menu_display_statusline(struct menu * m)472 static void menu_display_statusline(struct menu *m)
473 {
474 	struct bootmenu_entry *entry;
475 	struct bootmenu_data *menu;
476 
477 	if (menu_default_choice(m, (void *)&entry) < 0)
478 		return;
479 
480 	menu = entry->menu;
481 
482 	printf(ANSI_CURSOR_POSITION, 1, 1);
483 	puts(ANSI_CLEAR_LINE);
484 	printf(ANSI_CURSOR_POSITION, 2, 3);
485 	puts("*** U-Boot Boot Menu ***");
486 	puts(ANSI_CLEAR_LINE_TO_END);
487 	printf(ANSI_CURSOR_POSITION, 3, 1);
488 	puts(ANSI_CLEAR_LINE);
489 
490 	/* First 3 lines are bootmenu header + 2 empty lines between entries */
491 	printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
492 	puts(ANSI_CLEAR_LINE);
493 	printf(ANSI_CURSOR_POSITION, menu->count + 6, 3);
494 	puts("Press UP/DOWN to move, ENTER to select, ESC to quit");
495 	puts(ANSI_CLEAR_LINE_TO_END);
496 	printf(ANSI_CURSOR_POSITION, menu->count + 7, 1);
497 	puts(ANSI_CLEAR_LINE);
498 }
499 
handle_uefi_bootnext(void)500 static void handle_uefi_bootnext(void)
501 {
502 	u16 bootnext;
503 	efi_status_t ret;
504 	efi_uintn_t size;
505 
506 	/* Initialize EFI drivers */
507 	ret = efi_init_obj_list();
508 	if (ret != EFI_SUCCESS) {
509 		log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
510 			ret & ~EFI_ERROR_MASK);
511 
512 		return;
513 	}
514 
515 	/* If UEFI BootNext variable is set, boot the BootNext load option */
516 	size = sizeof(u16);
517 	ret = efi_get_variable_int(u"BootNext",
518 				   &efi_global_variable_guid,
519 				   NULL, &size, &bootnext, NULL);
520 	if (ret == EFI_SUCCESS)
521 		/* BootNext does exist here, try to boot */
522 		run_command("bootefi bootmgr", 0);
523 }
524 
525 /**
526  * bootmenu_show - display boot menu
527  *
528  * @uefi:	generated entries for UEFI boot options
529  * @delay:	autoboot delay in seconds
530  */
bootmenu_show(int uefi,int delay)531 static enum bootmenu_ret bootmenu_show(int uefi, int delay)
532 {
533 	int cmd_ret;
534 	int init = 0;
535 	void *choice = NULL;
536 	char *title = NULL;
537 	char *command = NULL;
538 	struct menu *menu;
539 	struct bootmenu_entry *iter;
540 	int ret = BOOTMENU_RET_SUCCESS;
541 	struct bootmenu_data *bootmenu;
542 	efi_status_t efi_ret = EFI_SUCCESS;
543 	char *option, *sep;
544 
545 	if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR) && uefi)
546 		handle_uefi_bootnext();
547 
548 	/* If delay is 0 do not create menu, just run first entry */
549 	if (delay == 0) {
550 		option = bootmenu_getoption(0);
551 		if (!option) {
552 			puts("bootmenu option 0 was not found\n");
553 			return BOOTMENU_RET_FAIL;
554 		}
555 		sep = strchr(option, '=');
556 		if (!sep) {
557 			puts("bootmenu option 0 is invalid\n");
558 			return BOOTMENU_RET_FAIL;
559 		}
560 		cmd_ret = run_command(sep + 1, 0);
561 		return (cmd_ret == CMD_RET_SUCCESS ? BOOTMENU_RET_SUCCESS : BOOTMENU_RET_FAIL);
562 	}
563 
564 	bootmenu = bootmenu_create(uefi, delay);
565 	if (!bootmenu)
566 		return BOOTMENU_RET_FAIL;
567 
568 	menu = menu_create(NULL, bootmenu->delay, 1, menu_display_statusline,
569 			   bootmenu_print_entry, bootmenu_choice_entry,
570 			   bootmenu_need_reprint, bootmenu);
571 	if (!menu) {
572 		bootmenu_destroy(bootmenu);
573 		return BOOTMENU_RET_FAIL;
574 	}
575 
576 	for (iter = bootmenu->first; iter; iter = iter->next) {
577 		if (menu_item_add(menu, iter->key, iter) != 1)
578 			goto cleanup;
579 	}
580 
581 	/* Default menu entry is always first */
582 	menu_default_set(menu, "0");
583 
584 	puts(ANSI_CURSOR_HIDE);
585 	puts(ANSI_CLEAR_CONSOLE);
586 	printf(ANSI_CURSOR_POSITION, 1, 1);
587 
588 	init = 1;
589 
590 	if (menu_get_choice(menu, &choice) == 1) {
591 		iter = choice;
592 		title = strdup(iter->title);
593 		command = strdup(iter->command);
594 
595 		/* last entry exits bootmenu */
596 		if (iter->num == iter->menu->count - 1) {
597 			ret = BOOTMENU_RET_QUIT;
598 			goto cleanup;
599 		}
600 	} else {
601 		goto cleanup;
602 	}
603 
604 	/*
605 	 * If the selected entry is UEFI BOOT####, set the BootNext variable.
606 	 * Then uefi bootmgr is invoked by the preset command in iter->command.
607 	 */
608 	if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) {
609 		if (iter->type == BOOTMENU_TYPE_UEFI_BOOT_OPTION) {
610 			/*
611 			 * UEFI specification requires BootNext variable needs non-volatile
612 			 * attribute, but this BootNext is only used inside of U-Boot and
613 			 * removed by efi bootmgr once BootNext is processed.
614 			 * So this BootNext can be volatile.
615 			 */
616 			efi_ret = efi_set_variable_int(u"BootNext", &efi_global_variable_guid,
617 						       EFI_VARIABLE_BOOTSERVICE_ACCESS |
618 						       EFI_VARIABLE_RUNTIME_ACCESS,
619 						       sizeof(u16), &iter->bootorder, false);
620 			if (efi_ret != EFI_SUCCESS)
621 				goto cleanup;
622 		}
623 	}
624 
625 cleanup:
626 	menu_destroy(menu);
627 	bootmenu_destroy(bootmenu);
628 
629 	if (init) {
630 		puts(ANSI_CURSOR_SHOW);
631 		puts(ANSI_CLEAR_CONSOLE);
632 		printf(ANSI_CURSOR_POSITION, 1, 1);
633 	}
634 
635 	if (title && command) {
636 		debug("Starting entry '%s'\n", title);
637 		free(title);
638 		if (efi_ret == EFI_SUCCESS)
639 			cmd_ret = run_command(command, 0);
640 		free(command);
641 	}
642 
643 #ifdef CFG_POSTBOOTMENU
644 	run_command(CFG_POSTBOOTMENU, 0);
645 #endif
646 
647 	if (efi_ret != EFI_SUCCESS || cmd_ret != CMD_RET_SUCCESS)
648 		ret = BOOTMENU_RET_FAIL;
649 
650 	return ret;
651 }
652 
653 #ifdef CONFIG_AUTOBOOT_MENU_SHOW
menu_show(int bootdelay)654 int menu_show(int bootdelay)
655 {
656 	int ret;
657 
658 	while (1) {
659 		ret = bootmenu_show(1, bootdelay);
660 		bootdelay = -1;
661 		if (ret == BOOTMENU_RET_UPDATED)
662 			continue;
663 
664 		if (IS_ENABLED(CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE)) {
665 			if (ret == BOOTMENU_RET_QUIT) {
666 				/* default boot process */
667 				if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR))
668 					run_command("bootefi bootmgr", 0);
669 
670 				run_command("run bootcmd", 0);
671 			}
672 		} else {
673 			break;
674 		}
675 	}
676 
677 	return -1; /* -1 - abort boot and run monitor code */
678 }
679 #endif
680 
do_bootmenu(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])681 int do_bootmenu(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
682 {
683 	char *delay_str = NULL;
684 	int delay = 10;
685 	int uefi = 0;
686 
687 #if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
688 	delay = CONFIG_BOOTDELAY;
689 #endif
690 
691 	if (argc >= 2) {
692 		if (!strcmp("-e", argv[1])) {
693 			uefi = 1;
694 			--argc;
695 			++argv;
696 		}
697 	}
698 	if (argc >= 2)
699 		delay_str = argv[1];
700 
701 	if (!delay_str)
702 		delay_str = env_get("bootmenu_delay");
703 
704 	if (delay_str)
705 		delay = (int)simple_strtol(delay_str, NULL, 10);
706 
707 	bootmenu_show(uefi, delay);
708 	return 0;
709 }
710 
711 U_BOOT_CMD(
712 	bootmenu, 2, 1, do_bootmenu,
713 	"ANSI terminal bootmenu",
714 	"[-e] [delay]\n"
715 	"-e    - show UEFI entries\n"
716 	"delay - show ANSI terminal bootmenu with autoboot delay"
717 );
718