mirror of
https://git.yoctoproject.org/poky
synced 2026-03-03 22:09:39 +01:00
git-svn-id: https://svn.o-hand.com/repos/poky/trunk@3014 311d38ba-8fff-0310-9ca6-ca027cbcb966
770 lines
19 KiB
Diff
770 lines
19 KiB
Diff
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
|
|
*
|