mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	Merge branch 'agust@denx.de' of git://git.denx.de/u-boot-staging
This commit is contained in:
		
						commit
						5644369450
					
				@ -561,7 +561,8 @@ static char *menu_handle(struct menu_display *display)
 | 
				
			|||||||
	char *s;
 | 
						char *s;
 | 
				
			||||||
	char temp[6][200];
 | 
						char temp[6][200];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m = menu_create(display->title, display->timeout, 1, ait_menu_print);
 | 
						m = menu_create(display->title, display->timeout, 1, ait_menu_print,
 | 
				
			||||||
 | 
								NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; display->menulist[i]; i++) {
 | 
						for (i = 0; display->menulist[i]; i++) {
 | 
				
			||||||
		sprintf(key, "%d", i + 1);
 | 
							sprintf(key, "%d", i + 1);
 | 
				
			||||||
 | 
				
			|||||||
@ -75,6 +75,7 @@ COBJS-$(CONFIG_CMD_SOURCE) += cmd_source.o
 | 
				
			|||||||
COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o
 | 
					COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o
 | 
				
			||||||
COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o
 | 
					COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.o
 | 
				
			||||||
COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o
 | 
					COBJS-$(CONFIG_CMD_BMP) += cmd_bmp.o
 | 
				
			||||||
 | 
					COBJS-$(CONFIG_CMD_BOOTMENU) += cmd_bootmenu.o
 | 
				
			||||||
COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o
 | 
					COBJS-$(CONFIG_CMD_BOOTLDR) += cmd_bootldr.o
 | 
				
			||||||
COBJS-$(CONFIG_CMD_BOOTSTAGE) += cmd_bootstage.o
 | 
					COBJS-$(CONFIG_CMD_BOOTSTAGE) += cmd_bootstage.o
 | 
				
			||||||
COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o
 | 
					COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										517
									
								
								common/cmd_bootmenu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										517
									
								
								common/cmd_bootmenu.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,517 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * (C) Copyright 2011-2013 Pali Rohár <pali.rohar@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See file CREDITS for list of people who contributed to this
 | 
				
			||||||
 | 
					 * project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU General Public License as
 | 
				
			||||||
 | 
					 * published by the Free Software Foundation; either version 2 of
 | 
				
			||||||
 | 
					 * the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 | 
				
			||||||
 | 
					 * MA 02111-1307 USA
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <common.h>
 | 
				
			||||||
 | 
					#include <command.h>
 | 
				
			||||||
 | 
					#include <ansi.h>
 | 
				
			||||||
 | 
					#include <menu.h>
 | 
				
			||||||
 | 
					#include <hush.h>
 | 
				
			||||||
 | 
					#include <watchdog.h>
 | 
				
			||||||
 | 
					#include <malloc.h>
 | 
				
			||||||
 | 
					#include <linux/string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* maximum bootmenu entries */
 | 
				
			||||||
 | 
					#define MAX_COUNT	99
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* maximal size of bootmenu env
 | 
				
			||||||
 | 
					 *  9 = strlen("bootmenu_")
 | 
				
			||||||
 | 
					 *  2 = strlen(MAX_COUNT)
 | 
				
			||||||
 | 
					 *  1 = NULL term
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define MAX_ENV_SIZE	(9 + 2 + 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bootmenu_entry {
 | 
				
			||||||
 | 
						unsigned short int num;		/* unique number 0 .. MAX_COUNT */
 | 
				
			||||||
 | 
						char key[3];			/* key identifier of number */
 | 
				
			||||||
 | 
						char *title;			/* title of entry */
 | 
				
			||||||
 | 
						char *command;			/* hush command of entry */
 | 
				
			||||||
 | 
						struct bootmenu_data *menu;	/* this bootmenu */
 | 
				
			||||||
 | 
						struct bootmenu_entry *next;	/* next menu entry (num+1) */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct bootmenu_data {
 | 
				
			||||||
 | 
						int delay;			/* delay for autoboot */
 | 
				
			||||||
 | 
						int active;			/* active menu entry */
 | 
				
			||||||
 | 
						int count;			/* total count of menu entries */
 | 
				
			||||||
 | 
						struct bootmenu_entry *first;	/* first menu entry */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum bootmenu_key {
 | 
				
			||||||
 | 
						KEY_NONE = 0,
 | 
				
			||||||
 | 
						KEY_UP,
 | 
				
			||||||
 | 
						KEY_DOWN,
 | 
				
			||||||
 | 
						KEY_SELECT,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char *bootmenu_getoption(unsigned short int n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char name[MAX_ENV_SIZE] = "bootmenu_";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (n > MAX_COUNT)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sprintf(name + 9, "%d", n);
 | 
				
			||||||
 | 
						return getenv(name);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bootmenu_print_entry(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct bootmenu_entry *entry = data;
 | 
				
			||||||
 | 
						int reverse = (entry->menu->active == entry->num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Move cursor to line where the entry will be drown (entry->num)
 | 
				
			||||||
 | 
						 * First 3 lines contain bootmenu header + 1 empty line
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, entry->num + 4, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						puts("     ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (reverse)
 | 
				
			||||||
 | 
							puts(ANSI_COLOR_REVERSE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						puts(entry->title);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (reverse)
 | 
				
			||||||
 | 
							puts(ANSI_COLOR_RESET);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bootmenu_autoboot_loop(struct bootmenu_data *menu,
 | 
				
			||||||
 | 
									enum bootmenu_key *key, int *esc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i, c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (menu->delay > 0) {
 | 
				
			||||||
 | 
							printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
 | 
				
			||||||
 | 
							printf("  Hit any key to stop autoboot: %2d ", menu->delay);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (menu->delay > 0) {
 | 
				
			||||||
 | 
							for (i = 0; i < 100; ++i) {
 | 
				
			||||||
 | 
								if (!tstc()) {
 | 
				
			||||||
 | 
									WATCHDOG_RESET();
 | 
				
			||||||
 | 
									mdelay(10);
 | 
				
			||||||
 | 
									continue;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								menu->delay = -1;
 | 
				
			||||||
 | 
								c = getc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								switch (c) {
 | 
				
			||||||
 | 
								case '\e':
 | 
				
			||||||
 | 
									*esc = 1;
 | 
				
			||||||
 | 
									*key = KEY_NONE;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								case '\r':
 | 
				
			||||||
 | 
									*key = KEY_SELECT;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								default:
 | 
				
			||||||
 | 
									*key = KEY_NONE;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (menu->delay < 0)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							--menu->delay;
 | 
				
			||||||
 | 
							printf("\b\b\b%2d ", menu->delay);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
 | 
				
			||||||
 | 
						puts(ANSI_CLEAR_LINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (menu->delay == 0)
 | 
				
			||||||
 | 
							*key = KEY_SELECT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bootmenu_loop(struct bootmenu_data *menu,
 | 
				
			||||||
 | 
							enum bootmenu_key *key, int *esc)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!tstc()) {
 | 
				
			||||||
 | 
							WATCHDOG_RESET();
 | 
				
			||||||
 | 
							mdelay(10);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c = getc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (*esc) {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							/* First char of ANSI escape sequence '\e' */
 | 
				
			||||||
 | 
							if (c == '\e') {
 | 
				
			||||||
 | 
								*esc = 1;
 | 
				
			||||||
 | 
								*key = KEY_NONE;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							/* Second char of ANSI '[' */
 | 
				
			||||||
 | 
							if (c == '[') {
 | 
				
			||||||
 | 
								*esc = 2;
 | 
				
			||||||
 | 
								*key = KEY_NONE;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								*esc = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							/* Third char of ANSI (number '1') - optional */
 | 
				
			||||||
 | 
							if (*esc == 2 && c == '1') {
 | 
				
			||||||
 | 
								*esc = 3;
 | 
				
			||||||
 | 
								*key = KEY_NONE;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							*esc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* ANSI 'A' - key up was pressed */
 | 
				
			||||||
 | 
							if (c == 'A')
 | 
				
			||||||
 | 
								*key = KEY_UP;
 | 
				
			||||||
 | 
							/* ANSI 'B' - key down was pressed */
 | 
				
			||||||
 | 
							else if (c == 'B')
 | 
				
			||||||
 | 
								*key = KEY_DOWN;
 | 
				
			||||||
 | 
							/* other key was pressed */
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								*key = KEY_NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* enter key was pressed */
 | 
				
			||||||
 | 
						if (c == '\r')
 | 
				
			||||||
 | 
							*key = KEY_SELECT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char *bootmenu_choice_entry(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct bootmenu_data *menu = data;
 | 
				
			||||||
 | 
						struct bootmenu_entry *iter;
 | 
				
			||||||
 | 
						enum bootmenu_key key = KEY_NONE;
 | 
				
			||||||
 | 
						int esc = 0;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (1) {
 | 
				
			||||||
 | 
							if (menu->delay >= 0) {
 | 
				
			||||||
 | 
								/* Autoboot was not stopped */
 | 
				
			||||||
 | 
								bootmenu_autoboot_loop(menu, &key, &esc);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* Some key was pressed, so autoboot was stopped */
 | 
				
			||||||
 | 
								bootmenu_loop(menu, &key, &esc);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (key) {
 | 
				
			||||||
 | 
							case KEY_UP:
 | 
				
			||||||
 | 
								if (menu->active > 0)
 | 
				
			||||||
 | 
									--menu->active;
 | 
				
			||||||
 | 
								/* no menu key selected, regenerate menu */
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							case KEY_DOWN:
 | 
				
			||||||
 | 
								if (menu->active < menu->count - 1)
 | 
				
			||||||
 | 
									++menu->active;
 | 
				
			||||||
 | 
								/* no menu key selected, regenerate menu */
 | 
				
			||||||
 | 
								return NULL;
 | 
				
			||||||
 | 
							case KEY_SELECT:
 | 
				
			||||||
 | 
								iter = menu->first;
 | 
				
			||||||
 | 
								for (i = 0; i < menu->active; ++i)
 | 
				
			||||||
 | 
									iter = iter->next;
 | 
				
			||||||
 | 
								return iter->key;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* never happens */
 | 
				
			||||||
 | 
						debug("bootmenu: this should not happen");
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bootmenu_destroy(struct bootmenu_data *menu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct bootmenu_entry *iter = menu->first;
 | 
				
			||||||
 | 
						struct bootmenu_entry *next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (iter) {
 | 
				
			||||||
 | 
							next = iter->next;
 | 
				
			||||||
 | 
							free(iter->title);
 | 
				
			||||||
 | 
							free(iter->command);
 | 
				
			||||||
 | 
							free(iter);
 | 
				
			||||||
 | 
							iter = next;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(menu);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct bootmenu_data *bootmenu_create(int delay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned short int i = 0;
 | 
				
			||||||
 | 
						const char *option;
 | 
				
			||||||
 | 
						struct bootmenu_data *menu;
 | 
				
			||||||
 | 
						struct bootmenu_entry *iter = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int len;
 | 
				
			||||||
 | 
						char *sep;
 | 
				
			||||||
 | 
						struct bootmenu_entry *entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						menu = malloc(sizeof(struct bootmenu_data));
 | 
				
			||||||
 | 
						if (!menu)
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						menu->delay = delay;
 | 
				
			||||||
 | 
						menu->active = 0;
 | 
				
			||||||
 | 
						menu->first = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while ((option = bootmenu_getoption(i))) {
 | 
				
			||||||
 | 
							sep = strchr(option, '=');
 | 
				
			||||||
 | 
							if (!sep) {
 | 
				
			||||||
 | 
								printf("Invalid bootmenu entry: %s\n", option);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							entry = malloc(sizeof(struct bootmenu_entry));
 | 
				
			||||||
 | 
							if (!entry)
 | 
				
			||||||
 | 
								goto cleanup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							len = sep-option;
 | 
				
			||||||
 | 
							entry->title = malloc(len + 1);
 | 
				
			||||||
 | 
							if (!entry->title) {
 | 
				
			||||||
 | 
								free(entry);
 | 
				
			||||||
 | 
								goto cleanup;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							memcpy(entry->title, option, len);
 | 
				
			||||||
 | 
							entry->title[len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							len = strlen(sep + 1);
 | 
				
			||||||
 | 
							entry->command = malloc(len + 1);
 | 
				
			||||||
 | 
							if (!entry->command) {
 | 
				
			||||||
 | 
								free(entry->title);
 | 
				
			||||||
 | 
								free(entry);
 | 
				
			||||||
 | 
								goto cleanup;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							memcpy(entry->command, sep + 1, len);
 | 
				
			||||||
 | 
							entry->command[len] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sprintf(entry->key, "%d", i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							entry->num = i;
 | 
				
			||||||
 | 
							entry->menu = menu;
 | 
				
			||||||
 | 
							entry->next = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!iter)
 | 
				
			||||||
 | 
								menu->first = entry;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								iter->next = entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							iter = entry;
 | 
				
			||||||
 | 
							++i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (i == MAX_COUNT - 1)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Add U-Boot console entry at the end */
 | 
				
			||||||
 | 
						if (i <= MAX_COUNT - 1) {
 | 
				
			||||||
 | 
							entry = malloc(sizeof(struct bootmenu_entry));
 | 
				
			||||||
 | 
							if (!entry)
 | 
				
			||||||
 | 
								goto cleanup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							entry->title = strdup("U-Boot console");
 | 
				
			||||||
 | 
							if (!entry->title) {
 | 
				
			||||||
 | 
								free(entry);
 | 
				
			||||||
 | 
								goto cleanup;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							entry->command = strdup("");
 | 
				
			||||||
 | 
							if (!entry->command) {
 | 
				
			||||||
 | 
								free(entry->title);
 | 
				
			||||||
 | 
								free(entry);
 | 
				
			||||||
 | 
								goto cleanup;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							sprintf(entry->key, "%d", i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							entry->num = i;
 | 
				
			||||||
 | 
							entry->menu = menu;
 | 
				
			||||||
 | 
							entry->next = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!iter)
 | 
				
			||||||
 | 
								menu->first = entry;
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								iter->next = entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							iter = entry;
 | 
				
			||||||
 | 
							++i;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						menu->count = i;
 | 
				
			||||||
 | 
						return menu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cleanup:
 | 
				
			||||||
 | 
						bootmenu_destroy(menu);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void bootmenu_show(int delay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int init = 0;
 | 
				
			||||||
 | 
						void *choice = NULL;
 | 
				
			||||||
 | 
						char *title = NULL;
 | 
				
			||||||
 | 
						char *command = NULL;
 | 
				
			||||||
 | 
						struct menu *menu;
 | 
				
			||||||
 | 
						struct bootmenu_data *bootmenu;
 | 
				
			||||||
 | 
						struct bootmenu_entry *iter;
 | 
				
			||||||
 | 
						char *option, *sep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If delay is 0 do not create menu, just run first entry */
 | 
				
			||||||
 | 
						if (delay == 0) {
 | 
				
			||||||
 | 
							option = bootmenu_getoption(0);
 | 
				
			||||||
 | 
							if (!option) {
 | 
				
			||||||
 | 
								puts("bootmenu option 0 was not found\n");
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							sep = strchr(option, '=');
 | 
				
			||||||
 | 
							if (!sep) {
 | 
				
			||||||
 | 
								puts("bootmenu option 0 is invalid\n");
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							run_command(sep+1, 0);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bootmenu = bootmenu_create(delay);
 | 
				
			||||||
 | 
						if (!bootmenu)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						menu = menu_create(NULL, bootmenu->delay, 1, bootmenu_print_entry,
 | 
				
			||||||
 | 
								   bootmenu_choice_entry, bootmenu);
 | 
				
			||||||
 | 
						if (!menu) {
 | 
				
			||||||
 | 
							bootmenu_destroy(bootmenu);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (iter = bootmenu->first; iter; iter = iter->next) {
 | 
				
			||||||
 | 
							if (!menu_item_add(menu, iter->key, iter))
 | 
				
			||||||
 | 
								goto cleanup;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Default menu entry is always first */
 | 
				
			||||||
 | 
						menu_default_set(menu, "0");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						puts(ANSI_CURSOR_HIDE);
 | 
				
			||||||
 | 
						puts(ANSI_CLEAR_CONSOLE);
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, 1, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						init = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (menu_get_choice(menu, &choice)) {
 | 
				
			||||||
 | 
							iter = choice;
 | 
				
			||||||
 | 
							title = strdup(iter->title);
 | 
				
			||||||
 | 
							command = strdup(iter->command);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cleanup:
 | 
				
			||||||
 | 
						menu_destroy(menu);
 | 
				
			||||||
 | 
						bootmenu_destroy(bootmenu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (init) {
 | 
				
			||||||
 | 
							puts(ANSI_CURSOR_SHOW);
 | 
				
			||||||
 | 
							puts(ANSI_CLEAR_CONSOLE);
 | 
				
			||||||
 | 
							printf(ANSI_CURSOR_POSITION, 1, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (title && command) {
 | 
				
			||||||
 | 
							debug("Starting entry '%s'\n", title);
 | 
				
			||||||
 | 
							free(title);
 | 
				
			||||||
 | 
							run_command(command, 0);
 | 
				
			||||||
 | 
							free(command);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_POSTBOOTMENU
 | 
				
			||||||
 | 
						run_command(CONFIG_POSTBOOTMENU, 0);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void menu_display_statusline(struct menu *m)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct bootmenu_entry *entry;
 | 
				
			||||||
 | 
						struct bootmenu_data *menu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (menu_default_choice(m, (void *)&entry) < 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						menu = entry->menu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, 1, 1);
 | 
				
			||||||
 | 
						puts(ANSI_CLEAR_LINE);
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, 2, 1);
 | 
				
			||||||
 | 
						puts("  *** U-Boot Boot Menu ***");
 | 
				
			||||||
 | 
						puts(ANSI_CLEAR_LINE_TO_END);
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, 3, 1);
 | 
				
			||||||
 | 
						puts(ANSI_CLEAR_LINE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* First 3 lines are bootmenu header + 2 empty lines between entries */
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, menu->count + 5, 1);
 | 
				
			||||||
 | 
						puts(ANSI_CLEAR_LINE);
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, menu->count + 6, 1);
 | 
				
			||||||
 | 
						puts("  Press UP/DOWN to move, ENTER to select");
 | 
				
			||||||
 | 
						puts(ANSI_CLEAR_LINE_TO_END);
 | 
				
			||||||
 | 
						printf(ANSI_CURSOR_POSITION, menu->count + 7, 1);
 | 
				
			||||||
 | 
						puts(ANSI_CLEAR_LINE);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_MENU_SHOW
 | 
				
			||||||
 | 
					int menu_show(int bootdelay)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bootmenu_show(bootdelay);
 | 
				
			||||||
 | 
						return -1; /* -1 - abort boot and run monitor code */
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int do_bootmenu(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char *delay_str = NULL;
 | 
				
			||||||
 | 
						int delay = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
 | 
				
			||||||
 | 
						delay = CONFIG_BOOTDELAY;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (argc >= 2)
 | 
				
			||||||
 | 
							delay_str = argv[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!delay_str)
 | 
				
			||||||
 | 
							delay_str = getenv("bootmenu_delay");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (delay_str)
 | 
				
			||||||
 | 
							delay = (int)simple_strtol(delay_str, NULL, 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bootmenu_show(delay);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					U_BOOT_CMD(
 | 
				
			||||||
 | 
						bootmenu, 2, 1, do_bootmenu,
 | 
				
			||||||
 | 
						"ANSI terminal bootmenu",
 | 
				
			||||||
 | 
						"[delay]\n"
 | 
				
			||||||
 | 
						"    - show ANSI terminal bootmenu with autoboot delay"
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
@ -1280,7 +1280,8 @@ static struct menu *pxe_menu_to_menu(struct pxe_menu *cfg)
 | 
				
			|||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Create a menu and add items for all the labels.
 | 
						 * Create a menu and add items for all the labels.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print);
 | 
						m = menu_create(cfg->title, cfg->timeout, cfg->prompt, label_print,
 | 
				
			||||||
 | 
								NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!m)
 | 
						if (!m)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,8 @@ struct menu {
 | 
				
			|||||||
	char *title;
 | 
						char *title;
 | 
				
			||||||
	int prompt;
 | 
						int prompt;
 | 
				
			||||||
	void (*item_data_print)(void *);
 | 
						void (*item_data_print)(void *);
 | 
				
			||||||
 | 
						char *(*item_choice)(void *);
 | 
				
			||||||
 | 
						void *item_choice_data;
 | 
				
			||||||
	struct list_head items;
 | 
						struct list_head items;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -174,7 +176,7 @@ static inline struct menu_item *menu_item_by_key(struct menu *m,
 | 
				
			|||||||
 * Set *choice to point to the default item's data, if any default item was
 | 
					 * Set *choice to point to the default item's data, if any default item was
 | 
				
			||||||
 * set, and returns 1. If no default item was set, returns -ENOENT.
 | 
					 * set, and returns 1. If no default item was set, returns -ENOENT.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline int menu_default_choice(struct menu *m, void **choice)
 | 
					int menu_default_choice(struct menu *m, void **choice)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (m->default_item) {
 | 
						if (m->default_item) {
 | 
				
			||||||
		*choice = m->default_item->data;
 | 
							*choice = m->default_item->data;
 | 
				
			||||||
@ -204,19 +206,27 @@ static inline int menu_interactive_choice(struct menu *m, void **choice)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		menu_display(m);
 | 
							menu_display(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!m->item_choice) {
 | 
				
			||||||
			readret = readline_into_buffer("Enter choice: ", cbuf,
 | 
								readret = readline_into_buffer("Enter choice: ", cbuf,
 | 
				
			||||||
					m->timeout / 10);
 | 
										m->timeout / 10);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (readret >= 0) {
 | 
								if (readret >= 0) {
 | 
				
			||||||
				choice_item = menu_item_by_key(m, cbuf);
 | 
									choice_item = menu_item_by_key(m, cbuf);
 | 
				
			||||||
 | 
									if (!choice_item)
 | 
				
			||||||
			if (!choice_item) {
 | 
					 | 
				
			||||||
					printf("%s not found\n", cbuf);
 | 
										printf("%s not found\n", cbuf);
 | 
				
			||||||
				m->timeout = 0;
 | 
								} else {
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else
 | 
					 | 
				
			||||||
				return menu_default_choice(m, choice);
 | 
									return menu_default_choice(m, choice);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								char *key = m->item_choice(m->item_choice_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (key)
 | 
				
			||||||
 | 
									choice_item = menu_item_by_key(m, key);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!choice_item)
 | 
				
			||||||
 | 
								m->timeout = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	*choice = choice_item->data;
 | 
						*choice = choice_item->data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -348,11 +358,19 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data)
 | 
				
			|||||||
 * what must be entered to select an item, the item_data_print function should
 | 
					 * what must be entered to select an item, the item_data_print function should
 | 
				
			||||||
 * make it obvious what the key for each entry is.
 | 
					 * make it obvious what the key for each entry is.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
					 * item_choice - If not NULL, will be called when asking the user to choose an
 | 
				
			||||||
 | 
					 * item. Returns a key string corresponding to the choosen item or NULL if
 | 
				
			||||||
 | 
					 * no item has been selected.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * item_choice_data - Will be passed as the argument to the item_choice function
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 * Returns a pointer to the menu if successful, or NULL if there is
 | 
					 * Returns a pointer to the menu if successful, or NULL if there is
 | 
				
			||||||
 * insufficient memory available to create the menu.
 | 
					 * insufficient memory available to create the menu.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct menu *menu_create(char *title, int timeout, int prompt,
 | 
					struct menu *menu_create(char *title, int timeout, int prompt,
 | 
				
			||||||
				void (*item_data_print)(void *))
 | 
									void (*item_data_print)(void *),
 | 
				
			||||||
 | 
									char *(*item_choice)(void *),
 | 
				
			||||||
 | 
									void *item_choice_data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct menu *m;
 | 
						struct menu *m;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -365,6 +383,8 @@ struct menu *menu_create(char *title, int timeout, int prompt,
 | 
				
			|||||||
	m->prompt = prompt;
 | 
						m->prompt = prompt;
 | 
				
			||||||
	m->timeout = timeout;
 | 
						m->timeout = timeout;
 | 
				
			||||||
	m->item_data_print = item_data_print;
 | 
						m->item_data_print = item_data_print;
 | 
				
			||||||
 | 
						m->item_choice = item_choice;
 | 
				
			||||||
 | 
						m->item_choice_data = item_choice_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (title) {
 | 
						if (title) {
 | 
				
			||||||
		m->title = strdup(title);
 | 
							m->title = strdup(title);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										115
									
								
								doc/README.bootmenu
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								doc/README.bootmenu
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * (C) Copyright 2011-2012 Pali Rohár <pali.rohar@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See file CREDITS for list of people who contributed to this
 | 
				
			||||||
 | 
					 * project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU General Public License as
 | 
				
			||||||
 | 
					 * published by the Free Software Foundation; either version 2 of
 | 
				
			||||||
 | 
					 * the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 | 
				
			||||||
 | 
					 * MA 02111-1307 USA
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ANSI terminal bootmenu command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The "bootmenu" command uses U-Boot menu interfaces and provides
 | 
				
			||||||
 | 
					a simple mechanism for creating menus with different boot items.
 | 
				
			||||||
 | 
					The cursor keys "Up" and "Down" are used for navigation through
 | 
				
			||||||
 | 
					the items. Current active menu item is highlighted and can be
 | 
				
			||||||
 | 
					selected using the "Enter" key. The selection of the highlighted
 | 
				
			||||||
 | 
					menu entry invokes an U-Boot command (or a list of commands)
 | 
				
			||||||
 | 
					associated with this menu entry.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The "bootmenu" command interprets ANSI escape sequencies, so
 | 
				
			||||||
 | 
					an ANSI terminal is required for proper menu rendering and item
 | 
				
			||||||
 | 
					selection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The assembling of the menu is done via a set of environment variables
 | 
				
			||||||
 | 
					"bootmenu_<num>" and "bootmenu_delay", i.e.:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bootmenu_delay=<delay>
 | 
				
			||||||
 | 
					  bootmenu_<num>="<title>=<commands>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <delay> is the autoboot delay in seconds, after which the first
 | 
				
			||||||
 | 
					  menu entry will be selected automatically
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <num> is the boot menu entry number, starting from zero
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <title> is the text of the menu entry shown on the console
 | 
				
			||||||
 | 
					  or on the boot screen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <commands> are commands which will be executed when a menu
 | 
				
			||||||
 | 
					  entry is selected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  (title and commands are separated by first appearance of '='
 | 
				
			||||||
 | 
					   character in the environment variable)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					First (optional) argument of the "bootmenu" command is a delay specifier
 | 
				
			||||||
 | 
					and it overrides the delay value defined by "bootmenu_delay" environment
 | 
				
			||||||
 | 
					variable. If the environment variable "bootmenu_delay" is not set or if
 | 
				
			||||||
 | 
					the argument of the "bootmenu" command is not specified, the default delay
 | 
				
			||||||
 | 
					will be CONFIG_BOOTDELAY. If delay is 0, no menu entries will be shown on
 | 
				
			||||||
 | 
					the console (or on the screen) and the command of the first menu entry will
 | 
				
			||||||
 | 
					be called immediately. If delay is less then 0, bootmenu will be shown and
 | 
				
			||||||
 | 
					autoboot will be disabled.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bootmenu always adds menu entry "U-Boot console" at the end of all menu
 | 
				
			||||||
 | 
					entries specified by environment variables. When selecting this entry
 | 
				
			||||||
 | 
					the bootmenu terminates and the usual U-Boot command prompt is presented
 | 
				
			||||||
 | 
					to the user.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Example environment:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  setenv bootmenu_0 Boot 1. kernel=bootm 0x82000000  # Set first menu entry
 | 
				
			||||||
 | 
					  setenv bootmenu_1 Boot 2. kernel=bootm 0x83000000  # Set second menu entry
 | 
				
			||||||
 | 
					  setenv bootmenu_2 Reset board=reset                # Set third menu entry
 | 
				
			||||||
 | 
					  setenv bootmenu_3 U-Boot boot order=boot           # Set fourth menu entry
 | 
				
			||||||
 | 
					  bootmenu 20        # Run bootmenu with autoboot delay 20s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above example will be rendered as below
 | 
				
			||||||
 | 
					(without decorating rectangle):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					┌──────────────────────────────────────────┐
 | 
				
			||||||
 | 
					│                                          │
 | 
				
			||||||
 | 
					│  *** U-Boot Boot Menu ***                │
 | 
				
			||||||
 | 
					│                                          │
 | 
				
			||||||
 | 
					│     Boot 1. kernel                       │
 | 
				
			||||||
 | 
					│     Boot 2. kernel                       │
 | 
				
			||||||
 | 
					│     Reset board                          │
 | 
				
			||||||
 | 
					│     U-Boot boot order                    │
 | 
				
			||||||
 | 
					│     U-Boot console                       │
 | 
				
			||||||
 | 
					│                                          │
 | 
				
			||||||
 | 
					│  Hit any key to stop autoboot: 20        │
 | 
				
			||||||
 | 
					│  Press UP/DOWN to move, ENTER to select  │
 | 
				
			||||||
 | 
					│                                          │
 | 
				
			||||||
 | 
					└──────────────────────────────────────────┘
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Selected menu entry will be highlighted - it will have inverted
 | 
				
			||||||
 | 
					background and text colors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To enable the "bootmenu" command add following definitions to the
 | 
				
			||||||
 | 
					board config file:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #define CONFIG_CMD_BOOTMENU
 | 
				
			||||||
 | 
					  #define CONFIG_MENU
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To run the bootmenu at startup add these additional definitions:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  #define CONFIG_AUTOBOOT_KEYED
 | 
				
			||||||
 | 
					  #define CONFIG_BOOTDELAY 30
 | 
				
			||||||
 | 
					  #define CONFIG_MENU_SHOW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When you intend to use the bootmenu on color frame buffer console,
 | 
				
			||||||
 | 
					make sure to additionally define CONFIG_CFB_CONSOLE_ANSI in the
 | 
				
			||||||
 | 
					board config file.
 | 
				
			||||||
@ -51,7 +51,9 @@ struct menu;
 | 
				
			|||||||
 * menu_create() - Creates a menu handle with default settings
 | 
					 * menu_create() - Creates a menu handle with default settings
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct menu *menu_create(char *title, int timeout, int prompt,
 | 
					struct menu *menu_create(char *title, int timeout, int prompt,
 | 
				
			||||||
				void (*item_data_print)(void *));
 | 
									void (*item_data_print)(void *),
 | 
				
			||||||
 | 
									char *(*item_choice)(void *),
 | 
				
			||||||
 | 
									void *item_choice_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * menu_item_add() - Adds or replaces a menu item
 | 
					 * menu_item_add() - Adds or replaces a menu item
 | 
				
			||||||
@ -63,6 +65,11 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
int menu_default_set(struct menu *m, char *item_key);
 | 
					int menu_default_set(struct menu *m, char *item_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * menu_default_choice() - Set *choice to point to the default item's data
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int menu_default_choice(struct menu *m, void **choice);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * menu_get_choice() - Returns the user's selected menu entry, or the
 | 
					 * menu_get_choice() - Returns the user's selected menu entry, or the
 | 
				
			||||||
 * default if the menu is set to not prompt or the timeout expires.
 | 
					 * default if the menu is set to not prompt or the timeout expires.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										42
									
								
								include/ansi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								include/ansi.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * (C) Copyright 2012
 | 
				
			||||||
 | 
					 * Pali Rohár <pali.rohar@gmail.com>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * See file CREDITS for list of people who contributed to this
 | 
				
			||||||
 | 
					 * project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU General Public License as
 | 
				
			||||||
 | 
					 * published by the Free Software Foundation; either version 2 of
 | 
				
			||||||
 | 
					 * the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 | 
				
			||||||
 | 
					 * MA 02111-1307 USA
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * ANSI terminal
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_UP			"\e[%dA"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_DOWN		"\e[%dB"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_FORWARD		"\e[%dC"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_BACK		"\e[%dD"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_NEXTLINE		"\e[%dE"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_PREVIOUSLINE	"\e[%dF"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_COLUMN		"\e[%dG"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_POSITION		"\e[%d;%dH"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_SHOW		"\e[?25h"
 | 
				
			||||||
 | 
					#define ANSI_CURSOR_HIDE		"\e[?25l"
 | 
				
			||||||
 | 
					#define ANSI_CLEAR_CONSOLE		"\e[2J"
 | 
				
			||||||
 | 
					#define ANSI_CLEAR_LINE_TO_END		"\e[0K"
 | 
				
			||||||
 | 
					#define ANSI_CLEAR_LINE			"\e[2K"
 | 
				
			||||||
 | 
					#define ANSI_COLOR_RESET		"\e[0m"
 | 
				
			||||||
 | 
					#define ANSI_COLOR_REVERSE		"\e[7m"
 | 
				
			||||||
@ -148,6 +148,7 @@
 | 
				
			|||||||
#define CONFIG_CMDLINE_EDITING		/* add command line history */
 | 
					#define CONFIG_CMDLINE_EDITING		/* add command line history */
 | 
				
			||||||
#define CONFIG_AUTO_COMPLETE		/* add autocompletion support */
 | 
					#define CONFIG_AUTO_COMPLETE		/* add autocompletion support */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CONFIG_CMD_BOOTMENU		/* ANSI terminal Boot Menu */
 | 
				
			||||||
#define CONFIG_CMD_CLEAR		/* ANSI terminal clear screen command */
 | 
					#define CONFIG_CMD_CLEAR		/* ANSI terminal clear screen command */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef ONENAND_SUPPORT
 | 
					#ifdef ONENAND_SUPPORT
 | 
				
			||||||
@ -287,8 +288,6 @@ int rx51_kp_getc(void);
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Environment information */
 | 
					/* Environment information */
 | 
				
			||||||
#define CONFIG_BOOTDELAY		3
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define CONFIG_EXTRA_ENV_SETTINGS \
 | 
					#define CONFIG_EXTRA_ENV_SETTINGS \
 | 
				
			||||||
	"mtdparts=" MTDPARTS_DEFAULT "\0" \
 | 
						"mtdparts=" MTDPARTS_DEFAULT "\0" \
 | 
				
			||||||
	"usbtty=cdc_acm\0" \
 | 
						"usbtty=cdc_acm\0" \
 | 
				
			||||||
@ -360,10 +359,40 @@ int rx51_kp_getc(void);
 | 
				
			|||||||
		"fi\0" \
 | 
							"fi\0" \
 | 
				
			||||||
	"emmcboot=setenv mmcnum 1; run trymmcboot\0" \
 | 
						"emmcboot=setenv mmcnum 1; run trymmcboot\0" \
 | 
				
			||||||
	"sdboot=setenv mmcnum 0; run trymmcboot\0" \
 | 
						"sdboot=setenv mmcnum 0; run trymmcboot\0" \
 | 
				
			||||||
 | 
						"menucmd=bootmenu\0" \
 | 
				
			||||||
 | 
						"bootmenu_0=Attached kernel=run attachboot\0" \
 | 
				
			||||||
 | 
						"bootmenu_1=Internal eMMC=run emmcboot\0" \
 | 
				
			||||||
 | 
						"bootmenu_2=External SD card=run sdboot\0" \
 | 
				
			||||||
 | 
						"bootmenu_3=U-Boot boot order=boot\0" \
 | 
				
			||||||
 | 
						"bootmenu_delay=30\0" \
 | 
				
			||||||
	""
 | 
						""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CONFIG_PREBOOT \
 | 
					#define CONFIG_PREBOOT \
 | 
				
			||||||
	"if run slide; then true; else run attachboot; fi;" \
 | 
						"setenv mmcnum 1; setenv mmcpart 1;" \
 | 
				
			||||||
 | 
						"setenv mmcscriptfile bootmenu.scr;" \
 | 
				
			||||||
 | 
						"if run switchmmc; then " \
 | 
				
			||||||
 | 
							"setenv mmcdone true;" \
 | 
				
			||||||
 | 
							"setenv mmctype fat;" \
 | 
				
			||||||
 | 
							"if run scriptload; then true; else " \
 | 
				
			||||||
 | 
								"setenv mmctype ext2;" \
 | 
				
			||||||
 | 
								"if run scriptload; then true; else " \
 | 
				
			||||||
 | 
									"setenv mmctype ext4;" \
 | 
				
			||||||
 | 
									"if run scriptload; then true; else " \
 | 
				
			||||||
 | 
										"setenv mmcdone false;" \
 | 
				
			||||||
 | 
									"fi;" \
 | 
				
			||||||
 | 
								"fi;" \
 | 
				
			||||||
 | 
							"fi;" \
 | 
				
			||||||
 | 
							"if ${mmcdone}; then " \
 | 
				
			||||||
 | 
								"run scriptboot;" \
 | 
				
			||||||
 | 
							"fi;" \
 | 
				
			||||||
 | 
						"fi;" \
 | 
				
			||||||
 | 
						"if run slide; then true; else " \
 | 
				
			||||||
 | 
							"setenv bootmenu_delay 0;" \
 | 
				
			||||||
 | 
							"setenv bootdelay 0;" \
 | 
				
			||||||
 | 
						"fi"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CONFIG_POSTBOOTMENU \
 | 
				
			||||||
 | 
						"echo;" \
 | 
				
			||||||
	"echo Extra commands:;" \
 | 
						"echo Extra commands:;" \
 | 
				
			||||||
	"echo run sercon - Use serial port for control.;" \
 | 
						"echo run sercon - Use serial port for control.;" \
 | 
				
			||||||
	"echo run usbcon - Use usbtty for control.;" \
 | 
						"echo run usbcon - Use usbtty for control.;" \
 | 
				
			||||||
@ -379,6 +408,11 @@ int rx51_kp_getc(void);
 | 
				
			|||||||
	"run attachboot;" \
 | 
						"run attachboot;" \
 | 
				
			||||||
	"echo"
 | 
						"echo"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CONFIG_BOOTDELAY 30
 | 
				
			||||||
 | 
					#define CONFIG_AUTOBOOT_KEYED
 | 
				
			||||||
 | 
					#define CONFIG_MENU
 | 
				
			||||||
 | 
					#define CONFIG_MENU_SHOW
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Miscellaneous configurable options
 | 
					 * Miscellaneous configurable options
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
				
			|||||||
@ -21,12 +21,15 @@
 | 
				
			|||||||
struct menu;
 | 
					struct menu;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct menu *menu_create(char *title, int timeout, int prompt,
 | 
					struct menu *menu_create(char *title, int timeout, int prompt,
 | 
				
			||||||
				void (*item_data_print)(void *));
 | 
									void (*item_data_print)(void *),
 | 
				
			||||||
 | 
									char *(*item_choice)(void *),
 | 
				
			||||||
 | 
									void *item_choice_data);
 | 
				
			||||||
int menu_default_set(struct menu *m, char *item_key);
 | 
					int menu_default_set(struct menu *m, char *item_key);
 | 
				
			||||||
int menu_get_choice(struct menu *m, void **choice);
 | 
					int menu_get_choice(struct menu *m, void **choice);
 | 
				
			||||||
int menu_item_add(struct menu *m, char *item_key, void *item_data);
 | 
					int menu_item_add(struct menu *m, char *item_key, void *item_data);
 | 
				
			||||||
int menu_destroy(struct menu *m);
 | 
					int menu_destroy(struct menu *m);
 | 
				
			||||||
void menu_display_statusline(struct menu *m);
 | 
					void menu_display_statusline(struct menu *m);
 | 
				
			||||||
 | 
					int menu_default_choice(struct menu *m, void **choice);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(CONFIG_MENU_SHOW)
 | 
					#if defined(CONFIG_MENU_SHOW)
 | 
				
			||||||
int menu_show(int bootdelay);
 | 
					int menu_show(int bootdelay);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user