diff options
author | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
---|---|---|
committer | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
commit | 709c4d66e0b107ca606941b988bad717c0b45d9b (patch) | |
tree | 37ee08b1eb308f3b2b6426d5793545c38396b838 /recipes/u-boot/u-boot-mkimage-openmoko-native/boot-menu.patch | |
parent | fa6cd5a3b993f16c27de4ff82b42684516d433ba (diff) |
rename packages/ to recipes/ per earlier agreement
See links below for more details:
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816
Signed-off-by: Denys Dmytriyenko <denis@denix.org>
Acked-by: Mike Westerhof <mwester@dls.net>
Acked-by: Philip Balister <philip@balister.org>
Acked-by: Khem Raj <raj.khem@gmail.com>
Acked-by: Marcin Juszkiewicz <hrw@openembedded.org>
Acked-by: Koen Kooi <koen@openembedded.org>
Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'recipes/u-boot/u-boot-mkimage-openmoko-native/boot-menu.patch')
-rw-r--r-- | recipes/u-boot/u-boot-mkimage-openmoko-native/boot-menu.patch | 769 |
1 files changed, 769 insertions, 0 deletions
diff --git a/recipes/u-boot/u-boot-mkimage-openmoko-native/boot-menu.patch b/recipes/u-boot/u-boot-mkimage-openmoko-native/boot-menu.patch new file mode 100644 index 0000000000..b524ace65d --- /dev/null +++ b/recipes/u-boot/u-boot-mkimage-openmoko-native/boot-menu.patch @@ -0,0 +1,769 @@ +board/neo1973/bootmenu.c: simple configurable boot menu +board/neo1973/neo1973.c (neo1973_new_second): return 1 if a new second has + started since the last call +board/neo1973/neo1973.c (neo1973_on_key_pressed): return 1 if the $POWER key is + pressed +board/neo1973/neo1973.c (board_late_init): make use of neo1973_new_second and + neo1973_on_key_pressed +board/neo1973/neo1973.h: added function prototypes +u-boot/board/neo1973/neo1973.c (board_late_init): enter the boot menu when + "AUX" was pressed at least half the time +u-boot/board/neo1973/neo1973.c (board_late_init): minor code cleanup +u-boot/common/console.c, include/console.h: added "console_poll_hook" to be + called when waiting for console in put in "getc" and "tstc" +board/neo1973/neo1973.c (board_late_init): poll for the boot menu also on RAM + boot, reset, or unknown cause +board/neo1973/neo1973.c (board_late_init): don't look for the power key if + woken up by the charger +board/neo1973/neo1973.h, board/neo1973/neo1973.c, board/neo1973/bootmenu.c: + renamed neo1973_911_key_pressed to neo1973_aux_key_pressed + +- Werner Almesberger <werner@openmoko.org> + +Index: u-boot/board/neo1973/common/bootmenu.c +=================================================================== +--- /dev/null ++++ u-boot/board/neo1973/common/bootmenu.c +@@ -0,0 +1,120 @@ ++/* ++ * bootmenu.c - Boot menu ++ * ++ * Copyright (C) 2006-2007 by Openmoko, Inc. ++ * Written by Werner Almesberger <werner@openmoko.org> ++ * All Rights Reserved ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++ ++#include <common.h> ++#include <environment.h> ++#include <bootmenu.h> ++#include <asm/atomic.h> ++ ++#ifdef CONFIG_USBD_DFU ++#include "usbdcore.h" ++#include "usb_dfu.h" ++#endif ++ ++#include "neo1973.h" ++ ++ ++#define DEBOUNCE_LOOPS 1000 /* wild guess */ ++ ++ ++static int debounce(int (*fn)(void), int *last) ++{ ++ int on, i; ++ ++again: ++ on = fn(); ++ if (on != *last) ++ for (i = DEBOUNCE_LOOPS; i; i--) ++ if (on != fn()) ++ goto again; ++ *last = on; ++ return on; ++} ++ ++ ++static int aux_key(void *user) ++{ ++ static int last_aux = -1; ++ ++ return debounce(neo1973_aux_key_pressed, &last_aux); ++} ++ ++ ++static int on_key(void *user) ++{ ++ static int last_on = -1; ++ ++ return debounce(neo1973_on_key_pressed, &last_on); ++} ++ ++ ++static void factory_reset(void *user) ++{ ++ default_env(); ++ run_command("dynpart", 0); ++ run_command("bootd", 0); ++} ++ ++ ++static int seconds(void *user) ++{ ++ return neo1973_new_second(); ++} ++ ++ ++static int system_idle(void) ++{ ++#ifdef CONFIG_USBD_DFU ++ if (system_dfu_state) ++ return *system_dfu_state == DFU_STATE_appIDLE; ++#endif ++ return 1; ++} ++ ++ ++static void poweroff_if_idle(void *user) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ if (system_idle()) ++ neo1973_poweroff(); ++ local_irq_restore(flags); ++} ++ ++ ++static struct bootmenu_setup bootmenu_setup = { ++ .next_key = aux_key, ++ .enter_key = on_key, ++ .seconds = seconds, ++ .idle_action = poweroff_if_idle, ++}; ++ ++ ++void neo1973_bootmenu(void) ++{ ++ bootmenu_add("Boot", NULL, "bootd"); ++ bootmenu_init(&bootmenu_setup); ++ bootmenu_add("Factory reset", factory_reset, NULL); ++ bootmenu(); ++} +Index: u-boot/board/neo1973/gta01/gta01.c +=================================================================== +--- u-boot.orig/board/neo1973/gta01/gta01.c ++++ u-boot/board/neo1973/gta01/gta01.c +@@ -229,10 +229,15 @@ int board_late_init(void) + extern unsigned char booted_from_nand; + unsigned char tmp; + char buf[32]; ++ int menu_vote = 0; /* <= 0: no, > 0: yes */ ++ int seconds = 0; + + /* Initialize the Power Management Unit with a safe register set */ + pcf50606_init(); + ++ /* if there's no other reason, must be regular reset */ ++ neo1973_wakeup_cause = NEO1973_WAKEUP_RESET; ++ + if (!booted_from_nand) + goto woken_by_reset; + +@@ -242,45 +247,41 @@ int board_late_init(void) + setenv("pcf50606_int1", buf); + + if (tmp & PCF50606_INT1_ALARM) { +- /* we've been woken up by RTC alarm or charger insert, boot */ ++ /* we've been woken up by RTC alarm, boot */ + neo1973_wakeup_cause = NEO1973_WAKEUP_ALARM; + goto continue_boot; + } + if (tmp & PCF50606_INT1_EXTONR) { ++ /* we've been woken up by charger insert */ + neo1973_wakeup_cause = NEO1973_WAKEUP_CHARGER; + } + + if (tmp & PCF50606_INT1_ONKEYF) { +- int seconds = 0; +- neo1973_wakeup_cause = NEO1973_WAKEUP_POWER_KEY; + /* we've been woken up by a falling edge of the onkey */ ++ neo1973_wakeup_cause = NEO1973_WAKEUP_POWER_KEY; ++ } + +- /* we can't just setenv(bootdelay,-1) because that would +- * accidentially become permanent if the user does saveenv */ +- if (neo1973_911_key_pressed()) +- nobootdelay = 1; +- +- while (1) { +- u_int8_t int1, oocs; +- +- oocs = pcf50606_reg_read(PCF50606_REG_OOCS); +- if (oocs & PFC50606_OOCS_ONKEY) +- break; +- +- int1 = pcf50606_reg_read(PCF50606_REG_INT1); +- if (int1 & PCF50606_INT1_SECOND) +- seconds++; +- +- if (seconds >= POWER_KEY_SECONDS) +- goto continue_boot; +- } +- /* Power off if minimum number of seconds not reached */ +- neo1973_poweroff(); ++ if (neo1973_wakeup_cause == NEO1973_WAKEUP_CHARGER) { ++ /* if we still think it was only a charger insert, boot */ ++ goto continue_boot; + } + + woken_by_reset: +- /* if there's no other reason, must be regular reset */ +- neo1973_wakeup_cause = NEO1973_WAKEUP_RESET; ++ ++ while (neo1973_wakeup_cause == NEO1973_WAKEUP_RESET || ++ neo1973_on_key_pressed()) { ++ if (neo1973_aux_key_pressed()) ++ menu_vote++; ++ else ++ menu_vote--; ++ ++ if (neo1973_new_second()) ++ seconds++; ++ if (seconds >= POWER_KEY_SECONDS) ++ goto continue_boot; ++ } ++ /* Power off if minimum number of seconds not reached */ ++ neo1973_poweroff(); + + continue_boot: + jbt6k74_init(); +@@ -304,6 +305,11 @@ continue_boot: + } + #endif + ++ if (menu_vote > 0) { ++ neo1973_bootmenu(); ++ nobootdelay = 1; ++ } ++ + return 0; + } + +@@ -369,7 +375,17 @@ void neo1973_vibrator(int on) + #endif + } + +-int neo1973_911_key_pressed(void) ++int neo1973_new_second(void) ++{ ++ return pcf50606_reg_read(PCF50606_REG_INT1) & PCF50606_INT1_SECOND; ++} ++ ++int neo1973_on_key_pressed(void) ++{ ++ return !(pcf50606_reg_read(PCF50606_REG_OOCS) & PFC50606_OOCS_ONKEY); ++} ++ ++int neo1973_aux_key_pressed(void) + { + S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); + if (gpio->GPFDAT & (1 << 6)) +Index: u-boot/board/neo1973/gta01/Makefile +=================================================================== +--- u-boot.orig/board/neo1973/gta01/Makefile ++++ u-boot/board/neo1973/gta01/Makefile +@@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk + + LIB = lib$(BOARD).a + +-OBJS := gta01.o pcf50606.o ../common/cmd_neo1973.o ../common/jbt6k74.o ../common/udc.o ++OBJS := gta01.o pcf50606.o ../common/cmd_neo1973.o ../common/jbt6k74.o ../common/udc.o ../common/bootmenu.o + SOBJS := ../common/lowlevel_init.o + + .PHONY: all +Index: u-boot/board/neo1973/common/neo1973.h +=================================================================== +--- u-boot.orig/board/neo1973/common/neo1973.h ++++ u-boot/board/neo1973/common/neo1973.h +@@ -29,4 +29,10 @@ int neo1973_911_key_pressed(void); + const char *neo1973_get_charge_status(void); + int neo1973_set_charge_mode(enum neo1973_charger_cmd cmd); + ++int neo1973_new_second(void); ++int neo1973_on_key_pressed(void); ++int neo1973_aux_key_pressed(void); ++ ++void neo1973_bootmenu(void); ++ + #endif +Index: u-boot/common/console.c +=================================================================== +--- u-boot.orig/common/console.c ++++ u-boot/common/console.c +@@ -160,8 +160,12 @@ void fprintf (int file, const char *fmt, + + /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/ + ++void (*console_poll_hook)(int activity); ++ + int getc (void) + { ++ while (console_poll_hook && !tstc()); ++ + if (gd->flags & GD_FLG_DEVINIT) { + /* Get from the standard input */ + return fgetc (stdin); +@@ -171,7 +175,7 @@ int getc (void) + return serial_getc (); + } + +-int tstc (void) ++static int do_tstc (void) + { + if (gd->flags & GD_FLG_DEVINIT) { + /* Test the standard input */ +@@ -182,6 +186,16 @@ int tstc (void) + return serial_tstc (); + } + ++int tstc (void) ++{ ++ int ret; ++ ++ ret = do_tstc(); ++ if (console_poll_hook) ++ console_poll_hook(ret); ++ return ret; ++} ++ + void putc (const char c) + { + #ifdef CONFIG_SILENT_CONSOLE +Index: u-boot/include/console.h +=================================================================== +--- u-boot.orig/include/console.h ++++ u-boot/include/console.h +@@ -33,6 +33,8 @@ + extern device_t *stdio_devices[] ; + extern char *stdio_names[MAX_FILES] ; + ++extern void (*console_poll_hook)(int activity); ++ + int console_realloc(int top); + + #endif +Index: u-boot/common/Makefile +=================================================================== +--- u-boot.orig/common/Makefile ++++ u-boot/common/Makefile +@@ -50,7 +50,8 @@ COBJS = main.o ACEX1K.o altera.o bedbug. + memsize.o miiphybb.o miiphyutil.o \ + s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \ + usb.o usb_kbd.o usb_storage.o \ +- virtex2.o xilinx.o crc16.o xyzModem.o cmd_mac.o cmd_mfsl.o ++ virtex2.o xilinx.o crc16.o xyzModem.o cmd_mac.o cmd_mfsl.o \ ++ bootmenu.o + + SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS)) +Index: u-boot/common/bootmenu.c +=================================================================== +--- /dev/null ++++ u-boot/common/bootmenu.c +@@ -0,0 +1,311 @@ ++/* ++ * bootmenu.c - Boot menu ++ * ++ * Copyright (C) 2006-2007 by Openmoko, Inc. ++ * Written by Werner Almesberger <werner@openmoko.org> ++ * All Rights Reserved ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++ ++#include <common.h> ++ ++#ifdef CFG_BOOTMENU ++ ++#include <malloc.h> ++#include <devices.h> ++#include <console.h> ++#include <bootmenu.h> ++ ++ ++extern const char version_string[]; ++ ++ ++#define ANSI_CLEAR "\e[2J" ++#define ANSI_REVERSE "\e[7m" ++#define ANSI_NORMAL "\e[m" ++#define ANSI_GOTOYX "\e[%d;%dH" ++ ++/* ++ * MIN_BOOT_MENU_TIMEOUT ensures that users can't by accident set the timeout ++ * unusably short. ++ */ ++#define MIN_BOOT_MENU_TIMEOUT 10 /* 10 seconds */ ++#define BOOT_MENU_TIMEOUT 60 /* 60 seconds */ ++#define AFTER_COMMAND_WAIT 3 /* wait (2,3] after running commands */ ++#define MAX_MENU_ITEMS 10 /* cut off after that many */ ++ ++#define TOP_ROW 2 ++#define MENU_0_ROW (TOP_ROW+5) ++ ++ ++struct option { ++ const char *label; ++ void (*fn)(void *user); /* run_command if NULL */ ++ void *user; ++}; ++ ++ ++static const struct bootmenu_setup *setup; ++static struct option options[MAX_MENU_ITEMS]; ++static int num_options = 0; ++static int max_width = 0; ++ ++static device_t *bm_con; ++ ++ ++static void bm_printf(const char *fmt, ...) ++{ ++ va_list args; ++ char printbuffer[CFG_PBSIZE]; ++ ++ va_start(args, fmt); ++ vsprintf(printbuffer, fmt, args); ++ va_end(args); ++ ++ bm_con->puts(printbuffer); ++} ++ ++ ++static char *get_option(int n) ++{ ++ char name[] = "menu_XX"; ++ ++ sprintf(name+5, "%d", n); ++ return getenv(name); ++} ++ ++ ++static void print_option(const struct option *option, int reverse) ++{ ++ int n = option-options; ++ ++ bm_printf(ANSI_GOTOYX, MENU_0_ROW+n, 1); ++ if (reverse) ++ bm_printf(ANSI_REVERSE); ++ bm_printf(" %-*s ", max_width, option->label); ++ if (reverse) ++ bm_printf(ANSI_NORMAL); ++} ++ ++ ++static int get_var_positive_int(char *var, int default_value) ++{ ++ const char *s; ++ char *end; ++ int n; ++ ++ s = getenv(var); ++ if (!s) ++ return default_value; ++ n = simple_strtoul(s, &end, 0); ++ if (!*s || *end || n < 1) ++ return default_value; ++ return n; ++} ++ ++ ++static void show_bootmenu(void) ++{ ++ const struct option *option; ++ ++ bm_printf(ANSI_CLEAR ANSI_GOTOYX "%s", TOP_ROW, 1, version_string); ++ bm_printf(ANSI_GOTOYX "*** BOOT MENU ***", TOP_ROW+3, 1); ++ bm_printf(ANSI_GOTOYX, MENU_0_ROW, 1); ++ ++ for (option = options; option != options+num_options; option++) ++ print_option(option, option == options); ++ ++ bm_printf("\n\nPress [AUX] to select, [POWER] to execute.\n"); ++} ++ ++ ++static void redirect_console(int grab) ++{ ++ static device_t *orig_stdout, *orig_stderr; ++ ++ if (grab) { ++ orig_stdout = stdio_devices[stdout]; ++ orig_stderr = stdio_devices[stderr]; ++ stdio_devices[stdout] = bm_con; ++ stdio_devices[stderr] = bm_con; ++ } ++ else { ++ /* ++ * Make this conditional, because the command may also change ++ * the console. ++ */ ++ if (stdio_devices[stdout] == bm_con) ++ stdio_devices[stdout] = orig_stdout; ++ if (stdio_devices[stderr] == bm_con) ++ stdio_devices[stderr] = orig_stderr; ++ } ++} ++ ++ ++static void do_option(const struct option *option) ++{ ++ int seconds, aux; ++ ++ bm_printf(ANSI_CLEAR ANSI_GOTOYX, 1, 1); ++ redirect_console(1); ++ ++ if (option->fn) ++ option->fn(option->user); ++ else ++ run_command(option->user, 0); ++ ++ redirect_console(0); ++ seconds = get_var_positive_int("after_command_wait", ++ AFTER_COMMAND_WAIT); ++ if (seconds) ++ bm_printf("\nPress [AUX] to %s.", ++ option ? "return to boot menu" : "power off"); ++ aux = 1; /* require up-down transition */ ++ while (seconds) { ++ int tmp; ++ ++ tmp = setup->next_key(setup->user); ++ if (tmp && !aux) ++ break; ++ aux = tmp; ++ if (setup->seconds(setup->user)) ++ seconds--; ++ } ++ if (!option) ++ setup->idle_action(setup->idle_action); ++ show_bootmenu(); ++} ++ ++ ++static void bootmenu_hook(int activity) ++{ ++ static int aux = 1, on = 1; ++ static const struct option *option = options; ++ static int seconds = 0; ++ int tmp; ++ ++ if (activity) ++ seconds = 0; ++ tmp = setup->next_key(setup->user); ++ if (tmp && !aux) { ++ print_option(option, 0); ++ option++; ++ if (option == options+num_options) ++ option = options; ++ print_option(option, 1); ++ seconds = 0; ++ } ++ aux = tmp; ++ tmp = setup->enter_key(setup->user); ++ if (tmp && !on) { ++ do_option(option); ++ option = options; ++ seconds = 0; ++ } ++ on = tmp; ++ if (setup->seconds(setup->user)) { ++ int timeout; ++ ++ timeout = get_var_positive_int("boot_menu_timeout", ++ BOOT_MENU_TIMEOUT); ++ if (timeout < MIN_BOOT_MENU_TIMEOUT) ++ timeout = MIN_BOOT_MENU_TIMEOUT; ++ if (++seconds > timeout) { ++ setup->idle_action(setup->idle_action); ++ seconds = 0; ++ } ++ } ++} ++ ++ ++static device_t *find_console(const char *name) ++{ ++ int i; ++ ++ for (i = 1; i != ListNumItems(devlist); i++) { ++ device_t *dev = ListGetPtrToItem(devlist, i); ++ ++ if (!strcmp(name, dev->name)) ++ if (dev->flags & DEV_FLAGS_OUTPUT) ++ return dev; ++ } ++ return NULL; ++} ++ ++ ++void bootmenu_add(const char *label, void (*fn)(void *user), void *user) ++{ ++ int len; ++ ++ options[num_options].label = label; ++ options[num_options].fn = fn; ++ options[num_options].user = user; ++ num_options++; ++ ++ len = strlen(label); ++ if (len > max_width) ++ max_width = len; ++} ++ ++ ++void bootmenu_init(struct bootmenu_setup *__setup) ++{ ++ int n; ++ ++ setup = __setup; ++ for (n = 1; n != MAX_MENU_ITEMS+1; n++) { ++ const char *spec, *colon; ++ ++ spec = get_option(n); ++ if (!spec) ++ continue; ++ colon = strchr(spec, ':'); ++ if (!colon) ++ bootmenu_add(spec, NULL, (char *) spec); ++ else { ++ char *label; ++ int len = colon-spec; ++ ++ label = malloc(len+1); ++ if (!label) ++ return; ++ memcpy(label, spec, len); ++ label[len] = 0; ++ bootmenu_add(label, NULL, (char *) colon+1); ++ } ++ } ++} ++ ++ ++void bootmenu(void) ++{ ++ bm_con = find_console("vga"); ++ if (bm_con && bm_con->start && bm_con->start() < 0) ++ bm_con = NULL; ++ if (!bm_con) ++ bm_con = stdio_devices[stdout]; ++ if (!bm_con) ++ return; ++#if 0 ++ console_assign(stdout, "vga"); ++ console_assign(stderr, "vga"); ++#endif ++ show_bootmenu(); ++ console_poll_hook = bootmenu_hook; ++} ++ ++#endif /* CFG_BOOTMENU */ +Index: u-boot/include/bootmenu.h +=================================================================== +--- /dev/null ++++ u-boot/include/bootmenu.h +@@ -0,0 +1,71 @@ ++/* ++ * bootmenu.h - Boot menu ++ * ++ * Copyright (C) 2006-2007 by Openmoko, Inc. ++ * Written by Werner Almesberger <werner@openmoko.org> ++ * All Rights Reserved ++ * ++ * 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., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#ifndef BOOTMENU_H ++#define BOOTMENU_H ++ ++#define MIN_BOOT_MENU_TIMEOUT 10 /* 10 seconds */ ++#define BOOT_MENU_TIMEOUT 60 /* 60 seconds */ ++#define AFTER_COMMAND_WAIT 3 /* wait (2,3] after running commands */ ++#define MAX_MENU_ITEMS 10 /* cut off after that many */ ++ ++ ++struct bootmenu_setup { ++ /* non-zero while the "next" key is being pressed */ ++ int (*next_key)(void *user); ++ ++ /* non-zero while the "enter" key is being pressed */ ++ int (*enter_key)(void *user); ++ ++ /* return the number of seconds that have passed since the last call ++ to "seconds". It's okay to limit the range to [0, 1]. */ ++ int (*seconds)(void *user); ++ ++ /* action to take if the boot menu times out */ ++ void (*idle_action)(void *user); ++ ++ /* user-specific data, passes "as is" to the functions above */ ++ void *user; ++}; ++ ++ ++/* ++ * Initialize the menu from the environment. ++ */ ++ ++void bootmenu_init(struct bootmenu_setup *setup); ++ ++/* ++ * To add entries on top of the boot menu, call bootmenu_add before ++ * bootmenu_init. To add entries at the end, call it after bootmenu_init. ++ * If "fn" is NULL, the command specified in "user" is executed. ++ */ ++ ++void bootmenu_add(const char *label, void (*fn)(void *user), void *user); ++ ++/* ++ * Run the boot menu. ++ */ ++ ++void bootmenu(void); ++ ++#endif /* !BOOTMENU_H */ +Index: u-boot/include/configs/neo1973_gta01.h +=================================================================== +--- u-boot.orig/include/configs/neo1973_gta01.h ++++ u-boot/include/configs/neo1973_gta01.h +@@ -160,6 +160,8 @@ + /* valid baudrates */ + #define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + ++#define CFG_BOOTMENU ++ + /*----------------------------------------------------------------------- + * Stack sizes + * |