diff options
| -rw-r--r-- | board/ait/cam_enc_4xx/cam_enc_4xx.c | 3 | ||||
| -rw-r--r-- | common/Makefile | 1 | ||||
| -rw-r--r-- | common/cmd_bootmenu.c | 517 | ||||
| -rw-r--r-- | common/cmd_pxe.c | 3 | ||||
| -rw-r--r-- | common/menu.c | 44 | ||||
| -rw-r--r-- | doc/README.bootmenu | 115 | ||||
| -rw-r--r-- | doc/README.menu | 9 | ||||
| -rw-r--r-- | include/ansi.h | 42 | ||||
| -rw-r--r-- | include/configs/nokia_rx51.h | 40 | ||||
| -rw-r--r-- | include/menu.h | 5 | 
10 files changed, 760 insertions, 19 deletions
| diff --git a/board/ait/cam_enc_4xx/cam_enc_4xx.c b/board/ait/cam_enc_4xx/cam_enc_4xx.c index 32b28f927..644c44569 100644 --- a/board/ait/cam_enc_4xx/cam_enc_4xx.c +++ b/board/ait/cam_enc_4xx/cam_enc_4xx.c @@ -561,7 +561,8 @@ static char *menu_handle(struct menu_display *display)  	char *s;  	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++) {  		sprintf(key, "%d", i + 1); diff --git a/common/Makefile b/common/Makefile index 1abf4ea79..f6313110c 100644 --- a/common/Makefile +++ b/common/Makefile @@ -75,6 +75,7 @@ COBJS-$(CONFIG_CMD_SOURCE) += cmd_source.o  COBJS-$(CONFIG_CMD_BDI) += cmd_bdinfo.o  COBJS-$(CONFIG_CMD_BEDBUG) += bedbug.o cmd_bedbug.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_BOOTSTAGE) += cmd_bootstage.o  COBJS-$(CONFIG_CMD_CACHE) += cmd_cache.o diff --git a/common/cmd_bootmenu.c b/common/cmd_bootmenu.c new file mode 100644 index 000000000..a3cbffab2 --- /dev/null +++ b/common/cmd_bootmenu.c @@ -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" +); diff --git a/common/cmd_pxe.c b/common/cmd_pxe.c index ee75db968..2dbd49cbd 100644 --- a/common/cmd_pxe.c +++ b/common/cmd_pxe.c @@ -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.  	 */ -	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)  		return NULL; diff --git a/common/menu.c b/common/menu.c index 6b2a2db3e..64b461abb 100644 --- a/common/menu.c +++ b/common/menu.c @@ -47,6 +47,8 @@ struct menu {  	char *title;  	int prompt;  	void (*item_data_print)(void *); +	char *(*item_choice)(void *); +	void *item_choice_data;  	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, 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) {  		*choice = m->default_item->data; @@ -204,18 +206,26 @@ static inline int menu_interactive_choice(struct menu *m, void **choice)  		menu_display(m); -		readret = readline_into_buffer("Enter choice: ", cbuf, -				m->timeout / 10); +		if (!m->item_choice) { +			readret = readline_into_buffer("Enter choice: ", cbuf, +					m->timeout / 10); -		if (readret >= 0) { -			choice_item = menu_item_by_key(m, cbuf); - -			if (!choice_item) { -				printf("%s not found\n", cbuf); -				m->timeout = 0; +			if (readret >= 0) { +				choice_item = menu_item_by_key(m, cbuf); +				if (!choice_item) +					printf("%s not found\n", cbuf); +			} else { +				return menu_default_choice(m, choice);  			} -		} else -			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; @@ -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   * 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   * insufficient memory available to create the menu.   */  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; @@ -365,6 +383,8 @@ struct menu *menu_create(char *title, int timeout, int prompt,  	m->prompt = prompt;  	m->timeout = timeout;  	m->item_data_print = item_data_print; +	m->item_choice = item_choice; +	m->item_choice_data = item_choice_data;  	if (title) {  		m->title = strdup(title); diff --git a/doc/README.bootmenu b/doc/README.bootmenu new file mode 100644 index 000000000..9e85b4099 --- /dev/null +++ b/doc/README.bootmenu @@ -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. diff --git a/doc/README.menu b/doc/README.menu index 6ce6bbab8..a8999cab5 100644 --- a/doc/README.menu +++ b/doc/README.menu @@ -51,7 +51,9 @@ struct menu;   * menu_create() - Creates a menu handle with default settings   */  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 @@ -64,6 +66,11 @@ int menu_item_add(struct menu *m, char *item_key, void *item_data);  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   * default if the menu is set to not prompt or the timeout expires.   */ diff --git a/include/ansi.h b/include/ansi.h new file mode 100644 index 000000000..0e40b1d4e --- /dev/null +++ b/include/ansi.h @@ -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" diff --git a/include/configs/nokia_rx51.h b/include/configs/nokia_rx51.h index 8506604a7..965330aa3 100644 --- a/include/configs/nokia_rx51.h +++ b/include/configs/nokia_rx51.h @@ -148,6 +148,7 @@  #define CONFIG_CMDLINE_EDITING		/* add command line history */  #define CONFIG_AUTO_COMPLETE		/* add autocompletion support */ +#define CONFIG_CMD_BOOTMENU		/* ANSI terminal Boot Menu */  #define CONFIG_CMD_CLEAR		/* ANSI terminal clear screen command */  #ifdef ONENAND_SUPPORT @@ -287,8 +288,6 @@ int rx51_kp_getc(void);  #endif  /* Environment information */ -#define CONFIG_BOOTDELAY		3 -  #define CONFIG_EXTRA_ENV_SETTINGS \  	"mtdparts=" MTDPARTS_DEFAULT "\0" \  	"usbtty=cdc_acm\0" \ @@ -360,10 +359,40 @@ int rx51_kp_getc(void);  		"fi\0" \  	"emmcboot=setenv mmcnum 1; 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 \ -	"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 run sercon - Use serial port for control.;" \  	"echo run usbcon - Use usbtty for control.;" \ @@ -379,6 +408,11 @@ int rx51_kp_getc(void);  	"run attachboot;" \  	"echo" +#define CONFIG_BOOTDELAY 30 +#define CONFIG_AUTOBOOT_KEYED +#define CONFIG_MENU +#define CONFIG_MENU_SHOW +  /*   * Miscellaneous configurable options   */ diff --git a/include/menu.h b/include/menu.h index 7af5fdb0e..d8200eee8 100644 --- a/include/menu.h +++ b/include/menu.h @@ -21,12 +21,15 @@  struct menu;  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_get_choice(struct menu *m, void **choice);  int menu_item_add(struct menu *m, char *item_key, void *item_data);  int menu_destroy(struct menu *m);  void menu_display_statusline(struct menu *m); +int menu_default_choice(struct menu *m, void **choice);  #if defined(CONFIG_MENU_SHOW)  int menu_show(int bootdelay); |