Merge branch 'holger/openmoko-merges' into org.openembedded.dev
[vuplus_openembedded] / packages / u-boot / u-boot-mkimage-openmoko-native / boot-menu.patch
1 board/neo1973/bootmenu.c: simple configurable boot menu
2 board/neo1973/neo1973.c (neo1973_new_second): return 1 if a new second has
3   started since the last call
4 board/neo1973/neo1973.c (neo1973_on_key_pressed): return 1 if the $POWER key is
5   pressed
6 board/neo1973/neo1973.c (board_late_init): make use of neo1973_new_second and
7   neo1973_on_key_pressed
8 board/neo1973/neo1973.h: added function prototypes
9 u-boot/board/neo1973/neo1973.c (board_late_init): enter the boot menu when 
10   "AUX" was pressed at least half the time
11 u-boot/board/neo1973/neo1973.c (board_late_init): minor code cleanup
12 u-boot/common/console.c, include/console.h: added "console_poll_hook" to be
13   called when waiting for console in put in "getc" and "tstc"
14 board/neo1973/neo1973.c (board_late_init): poll for the boot menu also on RAM
15   boot, reset, or unknown cause
16 board/neo1973/neo1973.c (board_late_init): don't look for the power key if
17   woken up by the charger
18 board/neo1973/neo1973.h, board/neo1973/neo1973.c, board/neo1973/bootmenu.c:
19   renamed neo1973_911_key_pressed to neo1973_aux_key_pressed
20
21 - Werner Almesberger <werner@openmoko.org>
22
23 Index: u-boot/board/neo1973/common/bootmenu.c
24 ===================================================================
25 --- /dev/null
26 +++ u-boot/board/neo1973/common/bootmenu.c
27 @@ -0,0 +1,120 @@
28 +/*
29 + * bootmenu.c - Boot menu
30 + *
31 + * Copyright (C) 2006-2007 by Openmoko, Inc.
32 + * Written by Werner Almesberger <werner@openmoko.org>
33 + * All Rights Reserved
34 + *
35 + * This program is free software; you can redistribute it and/or modify
36 + * it under the terms of the GNU General Public License as published by
37 + * the Free Software Foundation; either version 2 of the License, or
38 + * (at your option) any later version.
39 + *
40 + * This program is distributed in the hope that it will be useful,
41 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43 + * GNU General Public License for more details.
44 + *
45 + * You should have received a copy of the GNU General Public License along
46 + * with this program; if not, write to the Free Software Foundation, Inc.,
47 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
48 + */
49 +
50 +
51 +#include <common.h>
52 +#include <environment.h>
53 +#include <bootmenu.h>
54 +#include <asm/atomic.h>
55 +
56 +#ifdef CONFIG_USBD_DFU
57 +#include "usbdcore.h"
58 +#include "usb_dfu.h"
59 +#endif
60 +
61 +#include "neo1973.h"
62 +
63 +
64 +#define DEBOUNCE_LOOPS         1000    /* wild guess */
65 +
66 +
67 +static int debounce(int (*fn)(void), int *last)
68 +{
69 +       int on, i;
70 +
71 +again:
72 +       on = fn();
73 +       if (on != *last)
74 +               for (i = DEBOUNCE_LOOPS; i; i--)
75 +                       if (on != fn())
76 +                               goto again;
77 +       *last = on;
78 +       return on;
79 +}
80 +
81 +
82 +static int aux_key(void *user)
83 +{
84 +       static int last_aux = -1;
85 +
86 +       return debounce(neo1973_aux_key_pressed, &last_aux);
87 +}
88 +
89 +
90 +static int on_key(void *user)
91 +{
92 +       static int last_on = -1;
93 +
94 +       return debounce(neo1973_on_key_pressed, &last_on);
95 +}
96 +
97 +
98 +static void factory_reset(void *user)
99 +{
100 +       default_env();
101 +       run_command("dynpart", 0);
102 +       run_command("bootd", 0);
103 +}
104 +
105 +
106 +static int seconds(void *user)
107 +{
108 +       return neo1973_new_second();
109 +}
110 +
111 +
112 +static int system_idle(void)
113 +{
114 +#ifdef  CONFIG_USBD_DFU
115 +       if (system_dfu_state)
116 +               return *system_dfu_state == DFU_STATE_appIDLE;
117 +#endif
118 +        return 1;
119 +}
120 +
121 +
122 +static void poweroff_if_idle(void *user)
123 +{
124 +       unsigned long flags;
125 +
126 +       local_irq_save(flags);
127 +       if (system_idle())
128 +               neo1973_poweroff();
129 +       local_irq_restore(flags);
130 +}
131 +
132 +
133 +static struct bootmenu_setup bootmenu_setup = {
134 +       .next_key = aux_key,
135 +       .enter_key = on_key,
136 +       .seconds = seconds,
137 +       .idle_action = poweroff_if_idle,
138 +};
139 +
140 +
141 +void neo1973_bootmenu(void)
142 +{
143 +       bootmenu_add("Boot", NULL, "bootd");
144 +       bootmenu_init(&bootmenu_setup);
145 +       bootmenu_add("Factory reset", factory_reset, NULL);
146 +       bootmenu();
147 +}
148 Index: u-boot/board/neo1973/gta01/gta01.c
149 ===================================================================
150 --- u-boot.orig/board/neo1973/gta01/gta01.c
151 +++ u-boot/board/neo1973/gta01/gta01.c
152 @@ -229,10 +229,15 @@ int board_late_init(void)
153         extern unsigned char booted_from_nand;
154         unsigned char tmp;
155         char buf[32];
156 +       int menu_vote = 0; /* <= 0: no, > 0: yes */
157 +       int seconds = 0;
158  
159         /* Initialize the Power Management Unit with a safe register set */
160         pcf50606_init();
161  
162 +       /* if there's no other reason, must be regular reset */
163 +       neo1973_wakeup_cause = NEO1973_WAKEUP_RESET;
164 +
165         if (!booted_from_nand)
166                 goto woken_by_reset;
167  
168 @@ -242,45 +247,41 @@ int board_late_init(void)
169         setenv("pcf50606_int1", buf);
170  
171         if (tmp & PCF50606_INT1_ALARM) {
172 -               /* we've been woken up by RTC alarm or charger insert, boot */
173 +               /* we've been woken up by RTC alarm, boot */
174                 neo1973_wakeup_cause = NEO1973_WAKEUP_ALARM;
175                 goto continue_boot;
176         }
177         if (tmp & PCF50606_INT1_EXTONR) {
178 +               /* we've been woken up by charger insert */
179                 neo1973_wakeup_cause = NEO1973_WAKEUP_CHARGER;
180         }
181  
182         if (tmp & PCF50606_INT1_ONKEYF) {
183 -               int seconds = 0;
184 -               neo1973_wakeup_cause = NEO1973_WAKEUP_POWER_KEY;
185                 /* we've been woken up by a falling edge of the onkey */
186 +               neo1973_wakeup_cause = NEO1973_WAKEUP_POWER_KEY;
187 +       }
188  
189 -               /* we can't just setenv(bootdelay,-1) because that would
190 -                * accidentially become permanent if the user does saveenv */
191 -               if (neo1973_911_key_pressed())
192 -                       nobootdelay = 1;
193 -
194 -               while (1) {
195 -                       u_int8_t int1, oocs;
196 -
197 -                       oocs = pcf50606_reg_read(PCF50606_REG_OOCS);
198 -                       if (oocs & PFC50606_OOCS_ONKEY)
199 -                               break;
200 -
201 -                       int1 = pcf50606_reg_read(PCF50606_REG_INT1);
202 -                       if (int1 & PCF50606_INT1_SECOND)
203 -                               seconds++;
204 -
205 -                       if (seconds >= POWER_KEY_SECONDS)
206 -                               goto continue_boot;
207 -               }
208 -               /* Power off if minimum number of seconds not reached */
209 -               neo1973_poweroff();
210 +       if (neo1973_wakeup_cause == NEO1973_WAKEUP_CHARGER) {
211 +               /* if we still think it was only a charger insert, boot */
212 +               goto continue_boot;
213         }
214  
215  woken_by_reset:
216 -       /* if there's no other reason, must be regular reset */
217 -       neo1973_wakeup_cause = NEO1973_WAKEUP_RESET;
218 +
219 +       while (neo1973_wakeup_cause == NEO1973_WAKEUP_RESET ||
220 +           neo1973_on_key_pressed()) {
221 +               if (neo1973_aux_key_pressed())
222 +                       menu_vote++;
223 +               else
224 +                       menu_vote--;
225 +
226 +               if (neo1973_new_second())
227 +                       seconds++;
228 +               if (seconds >= POWER_KEY_SECONDS)
229 +                       goto continue_boot;
230 +       }
231 +       /* Power off if minimum number of seconds not reached */
232 +       neo1973_poweroff();
233  
234  continue_boot:
235         jbt6k74_init();
236 @@ -304,6 +305,11 @@ continue_boot:
237         }
238  #endif
239  
240 +       if (menu_vote > 0) {
241 +               neo1973_bootmenu();
242 +               nobootdelay = 1;
243 +       }
244 +
245         return 0;
246  }
247  
248 @@ -369,7 +375,17 @@ void neo1973_vibrator(int on)
249  #endif
250  }
251  
252 -int neo1973_911_key_pressed(void)
253 +int neo1973_new_second(void)
254 +{
255 +       return pcf50606_reg_read(PCF50606_REG_INT1) & PCF50606_INT1_SECOND;
256 +}
257 +
258 +int neo1973_on_key_pressed(void)
259 +{
260 +       return !(pcf50606_reg_read(PCF50606_REG_OOCS) & PFC50606_OOCS_ONKEY);
261 +}
262 +
263 +int neo1973_aux_key_pressed(void)
264  {
265         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
266         if (gpio->GPFDAT & (1 << 6))
267 Index: u-boot/board/neo1973/gta01/Makefile
268 ===================================================================
269 --- u-boot.orig/board/neo1973/gta01/Makefile
270 +++ u-boot/board/neo1973/gta01/Makefile
271 @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk
272  
273  LIB    = lib$(BOARD).a
274  
275 -OBJS   := gta01.o pcf50606.o ../common/cmd_neo1973.o ../common/jbt6k74.o ../common/udc.o
276 +OBJS   := gta01.o pcf50606.o ../common/cmd_neo1973.o ../common/jbt6k74.o ../common/udc.o ../common/bootmenu.o
277  SOBJS  := ../common/lowlevel_init.o
278  
279  .PHONY:        all
280 Index: u-boot/board/neo1973/common/neo1973.h
281 ===================================================================
282 --- u-boot.orig/board/neo1973/common/neo1973.h
283 +++ u-boot/board/neo1973/common/neo1973.h
284 @@ -29,4 +29,10 @@ int neo1973_911_key_pressed(void);
285  const char *neo1973_get_charge_status(void);
286  int neo1973_set_charge_mode(enum neo1973_charger_cmd cmd);
287  
288 +int neo1973_new_second(void);
289 +int neo1973_on_key_pressed(void);
290 +int neo1973_aux_key_pressed(void);
291 +
292 +void neo1973_bootmenu(void);
293 +
294  #endif
295 Index: u-boot/common/console.c
296 ===================================================================
297 --- u-boot.orig/common/console.c
298 +++ u-boot/common/console.c
299 @@ -160,8 +160,12 @@ void fprintf (int file, const char *fmt,
300  
301  /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/
302  
303 +void (*console_poll_hook)(int activity);
304 +
305  int getc (void)
306  {
307 +       while (console_poll_hook && !tstc());
308 +
309         if (gd->flags & GD_FLG_DEVINIT) {
310                 /* Get from the standard input */
311                 return fgetc (stdin);
312 @@ -171,7 +175,7 @@ int getc (void)
313         return serial_getc ();
314  }
315  
316 -int tstc (void)
317 +static int do_tstc (void)
318  {
319         if (gd->flags & GD_FLG_DEVINIT) {
320                 /* Test the standard input */
321 @@ -182,6 +186,16 @@ int tstc (void)
322         return serial_tstc ();
323  }
324  
325 +int tstc (void)
326 +{
327 +       int ret;
328 +
329 +       ret = do_tstc();
330 +       if (console_poll_hook)
331 +               console_poll_hook(ret);
332 +       return ret;
333 +}
334 +
335  void putc (const char c)
336  {
337  #ifdef CONFIG_SILENT_CONSOLE
338 Index: u-boot/include/console.h
339 ===================================================================
340 --- u-boot.orig/include/console.h
341 +++ u-boot/include/console.h
342 @@ -33,6 +33,8 @@
343  extern device_t        *stdio_devices[] ;
344  extern char *stdio_names[MAX_FILES] ;
345  
346 +extern void (*console_poll_hook)(int activity);
347 +
348  int console_realloc(int top);
349  
350  #endif
351 Index: u-boot/common/Makefile
352 ===================================================================
353 --- u-boot.orig/common/Makefile
354 +++ u-boot/common/Makefile
355 @@ -50,7 +50,8 @@ COBJS = main.o ACEX1K.o altera.o bedbug.
356           memsize.o miiphybb.o miiphyutil.o \
357           s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \
358           usb.o usb_kbd.o usb_storage.o \
359 -         virtex2.o xilinx.o crc16.o xyzModem.o cmd_mac.o cmd_mfsl.o
360 +         virtex2.o xilinx.o crc16.o xyzModem.o cmd_mac.o cmd_mfsl.o \
361 +         bootmenu.o
362  
363  SRCS   := $(AOBJS:.o=.S) $(COBJS:.o=.c)
364  OBJS   := $(addprefix $(obj),$(AOBJS) $(COBJS))
365 Index: u-boot/common/bootmenu.c
366 ===================================================================
367 --- /dev/null
368 +++ u-boot/common/bootmenu.c
369 @@ -0,0 +1,311 @@
370 +/*
371 + * bootmenu.c - Boot menu
372 + *
373 + * Copyright (C) 2006-2007 by Openmoko, Inc.
374 + * Written by Werner Almesberger <werner@openmoko.org>
375 + * All Rights Reserved
376 + *
377 + * This program is free software; you can redistribute it and/or modify
378 + * it under the terms of the GNU General Public License as published by
379 + * the Free Software Foundation; either version 2 of the License, or
380 + * (at your option) any later version.
381 + *
382 + * This program is distributed in the hope that it will be useful,
383 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
384 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
385 + * GNU General Public License for more details.
386 + *
387 + * You should have received a copy of the GNU General Public License along
388 + * with this program; if not, write to the Free Software Foundation, Inc.,
389 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
390 + */
391 +
392 +
393 +#include <common.h>
394 +
395 +#ifdef CFG_BOOTMENU
396 +
397 +#include <malloc.h>
398 +#include <devices.h>
399 +#include <console.h>
400 +#include <bootmenu.h>
401 +
402 +
403 +extern const char version_string[];
404 +
405 +
406 +#define ANSI_CLEAR     "\e[2J"
407 +#define ANSI_REVERSE   "\e[7m"
408 +#define        ANSI_NORMAL     "\e[m"
409 +#define ANSI_GOTOYX    "\e[%d;%dH"
410 +
411 +/*
412 + * MIN_BOOT_MENU_TIMEOUT ensures that users can't by accident set the timeout
413 + * unusably short.
414 + */
415 +#define MIN_BOOT_MENU_TIMEOUT  10      /* 10 seconds */
416 +#define BOOT_MENU_TIMEOUT      60      /* 60 seconds */
417 +#define AFTER_COMMAND_WAIT     3       /* wait (2,3] after running commands */
418 +#define        MAX_MENU_ITEMS          10      /* cut off after that many */
419 +
420 +#define        TOP_ROW         2
421 +#define        MENU_0_ROW      (TOP_ROW+5)
422 +
423 +
424 +struct option {
425 +       const char *label;
426 +       void (*fn)(void *user); /* run_command if NULL */
427 +       void *user;
428 +};
429 +
430 +
431 +static const struct bootmenu_setup *setup;
432 +static struct option options[MAX_MENU_ITEMS];
433 +static int num_options = 0;
434 +static int max_width = 0;
435 +
436 +static device_t *bm_con;
437 +
438 +
439 +static void bm_printf(const char *fmt, ...)
440 +{
441 +       va_list args;
442 +       char printbuffer[CFG_PBSIZE];
443 +
444 +       va_start(args, fmt);
445 +       vsprintf(printbuffer, fmt, args);
446 +       va_end(args);
447 +
448 +       bm_con->puts(printbuffer);
449 +}
450 +
451 +
452 +static char *get_option(int n)
453 +{
454 +       char name[] = "menu_XX";
455 +
456 +       sprintf(name+5, "%d", n);
457 +       return getenv(name);
458 +}
459 +
460 +
461 +static void print_option(const struct option *option, int reverse)
462 +{
463 +       int n = option-options;
464 +
465 +       bm_printf(ANSI_GOTOYX, MENU_0_ROW+n, 1);
466 +       if (reverse)
467 +               bm_printf(ANSI_REVERSE);
468 +       bm_printf("  %-*s  ", max_width, option->label);
469 +       if (reverse)
470 +               bm_printf(ANSI_NORMAL);
471 +}
472 +
473 +
474 +static int get_var_positive_int(char *var, int default_value)
475 +{
476 +       const char *s;
477 +       char *end;
478 +       int n;
479 +
480 +       s = getenv(var);
481 +       if (!s)
482 +               return default_value;
483 +        n = simple_strtoul(s, &end, 0);
484 +       if (!*s || *end || n < 1)
485 +               return default_value;
486 +       return n;
487 +}
488 +
489 +
490 +static void show_bootmenu(void)
491 +{
492 +       const struct option *option;
493 +
494 +       bm_printf(ANSI_CLEAR ANSI_GOTOYX "%s", TOP_ROW, 1, version_string);
495 +       bm_printf(ANSI_GOTOYX "*** BOOT MENU ***", TOP_ROW+3, 1);
496 +       bm_printf(ANSI_GOTOYX, MENU_0_ROW, 1);
497 +
498 +       for (option = options; option != options+num_options; option++)
499 +               print_option(option, option == options);
500 +
501 +       bm_printf("\n\nPress [AUX] to select, [POWER] to execute.\n");
502 +}
503 +
504 +
505 +static void redirect_console(int grab)
506 +{
507 +       static device_t *orig_stdout, *orig_stderr;
508 +
509 +       if (grab) {
510 +               orig_stdout = stdio_devices[stdout];
511 +               orig_stderr = stdio_devices[stderr];
512 +               stdio_devices[stdout] = bm_con;
513 +               stdio_devices[stderr] = bm_con;
514 +       }
515 +       else {
516 +               /*
517 +                * Make this conditional, because the command may also change
518 +                * the console.
519 +                */
520 +               if (stdio_devices[stdout] == bm_con)
521 +                       stdio_devices[stdout] = orig_stdout;
522 +               if (stdio_devices[stderr] == bm_con)
523 +                       stdio_devices[stderr] = orig_stderr;
524 +       }
525 +}
526 +
527 +
528 +static void do_option(const struct option *option)
529 +{
530 +       int seconds, aux;
531 +
532 +       bm_printf(ANSI_CLEAR ANSI_GOTOYX, 1, 1);
533 +       redirect_console(1);
534 +
535 +       if (option->fn)
536 +               option->fn(option->user);
537 +       else
538 +               run_command(option->user, 0);
539 +
540 +       redirect_console(0);
541 +       seconds = get_var_positive_int("after_command_wait",
542 +           AFTER_COMMAND_WAIT);
543 +       if (seconds)
544 +               bm_printf("\nPress [AUX] to %s.",
545 +                   option ? "return to boot menu" : "power off");
546 +       aux = 1; /* require up-down transition */
547 +       while (seconds) {
548 +               int tmp;
549 +
550 +               tmp = setup->next_key(setup->user);
551 +               if (tmp && !aux)
552 +                       break;
553 +               aux = tmp;
554 +               if (setup->seconds(setup->user))
555 +                       seconds--;
556 +       }
557 +       if (!option)
558 +               setup->idle_action(setup->idle_action);
559 +       show_bootmenu();
560 +}
561 +
562 +
563 +static void bootmenu_hook(int activity)
564 +{
565 +       static int aux = 1, on = 1;
566 +       static const struct option *option = options;
567 +       static int seconds = 0;
568 +       int tmp;
569 +
570 +       if (activity)
571 +               seconds = 0;
572 +       tmp = setup->next_key(setup->user);
573 +       if (tmp && !aux) {
574 +               print_option(option, 0);
575 +               option++;
576 +               if (option == options+num_options)
577 +                       option = options;
578 +               print_option(option, 1);
579 +               seconds = 0;
580 +       }
581 +       aux = tmp;
582 +       tmp = setup->enter_key(setup->user);
583 +       if (tmp && !on) {
584 +               do_option(option);
585 +               option = options;
586 +               seconds = 0;
587 +       }
588 +       on = tmp;
589 +       if (setup->seconds(setup->user)) {
590 +               int timeout;
591 +
592 +               timeout = get_var_positive_int("boot_menu_timeout",
593 +                   BOOT_MENU_TIMEOUT);
594 +               if (timeout < MIN_BOOT_MENU_TIMEOUT)
595 +                       timeout = MIN_BOOT_MENU_TIMEOUT;
596 +               if (++seconds > timeout) {
597 +                       setup->idle_action(setup->idle_action);
598 +                       seconds = 0;
599 +               }
600 +       }
601 +}
602 +
603 +
604 +static device_t *find_console(const char *name)
605 +{
606 +       int i;
607 +
608 +       for (i = 1; i != ListNumItems(devlist); i++) {
609 +               device_t *dev = ListGetPtrToItem(devlist, i);
610 +
611 +               if (!strcmp(name, dev->name))
612 +                       if (dev->flags & DEV_FLAGS_OUTPUT)
613 +                               return dev;
614 +       }
615 +       return NULL;
616 +}
617 +
618 +
619 +void bootmenu_add(const char *label, void (*fn)(void *user), void *user)
620 +{
621 +       int len;
622 +
623 +       options[num_options].label = label;
624 +       options[num_options].fn = fn;
625 +       options[num_options].user = user;
626 +       num_options++;
627 +
628 +       len = strlen(label);
629 +       if (len > max_width)
630 +               max_width = len;
631 +}
632 +
633 +
634 +void bootmenu_init(struct bootmenu_setup *__setup)
635 +{
636 +       int n;
637 +
638 +       setup = __setup;
639 +       for (n = 1; n != MAX_MENU_ITEMS+1; n++) {
640 +               const char *spec, *colon;
641 +
642 +               spec = get_option(n);
643 +               if (!spec)
644 +                       continue;
645 +               colon = strchr(spec, ':');
646 +               if (!colon)
647 +                       bootmenu_add(spec, NULL, (char *) spec);
648 +               else {
649 +                       char *label;
650 +                       int len = colon-spec;
651 +
652 +                       label = malloc(len+1);
653 +                       if (!label)
654 +                               return;
655 +                       memcpy(label, spec, len);
656 +                       label[len] = 0;
657 +                       bootmenu_add(label, NULL, (char *) colon+1);
658 +               }
659 +       }
660 +}
661 +
662 +
663 +void bootmenu(void)
664 +{
665 +       bm_con = find_console("vga");
666 +       if (bm_con && bm_con->start && bm_con->start() < 0)
667 +               bm_con = NULL;
668 +       if (!bm_con)
669 +               bm_con = stdio_devices[stdout];
670 +       if (!bm_con)
671 +               return;
672 +#if 0
673 +       console_assign(stdout, "vga");
674 +       console_assign(stderr, "vga");
675 +#endif
676 +       show_bootmenu();
677 +       console_poll_hook = bootmenu_hook;
678 +}
679 +
680 +#endif /* CFG_BOOTMENU */
681 Index: u-boot/include/bootmenu.h
682 ===================================================================
683 --- /dev/null
684 +++ u-boot/include/bootmenu.h
685 @@ -0,0 +1,71 @@
686 +/*
687 + * bootmenu.h - Boot menu
688 + *
689 + * Copyright (C) 2006-2007 by Openmoko, Inc.
690 + * Written by Werner Almesberger <werner@openmoko.org>
691 + * All Rights Reserved
692 + *
693 + * This program is free software; you can redistribute it and/or modify
694 + * it under the terms of the GNU General Public License as published by
695 + * the Free Software Foundation; either version 2 of the License, or
696 + * (at your option) any later version.
697 + *
698 + * This program is distributed in the hope that it will be useful,
699 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
700 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
701 + * GNU General Public License for more details.
702 + *
703 + * You should have received a copy of the GNU General Public License along
704 + * with this program; if not, write to the Free Software Foundation, Inc.,
705 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
706 + */
707 +
708 +#ifndef BOOTMENU_H
709 +#define BOOTMENU_H
710 +
711 +#define MIN_BOOT_MENU_TIMEOUT  10      /* 10 seconds */
712 +#define BOOT_MENU_TIMEOUT      60      /* 60 seconds */
713 +#define AFTER_COMMAND_WAIT     3       /* wait (2,3] after running commands */
714 +#define MAX_MENU_ITEMS         10      /* cut off after that many */
715 +
716 +
717 +struct bootmenu_setup {
718 +       /* non-zero while the "next" key is being pressed */
719 +       int (*next_key)(void *user);
720 +
721 +       /* non-zero while the "enter" key is being pressed */
722 +       int (*enter_key)(void *user);
723 +
724 +       /* return the number of seconds that have passed since the last call
725 +          to "seconds". It's okay to limit the range to [0, 1]. */
726 +       int (*seconds)(void *user);
727 +
728 +       /* action to take if the boot menu times out */
729 +       void (*idle_action)(void *user);
730 +
731 +       /* user-specific data, passes "as is" to the functions above */
732 +       void *user;
733 +};
734 +
735 +
736 +/*
737 + * Initialize the menu from the environment.
738 + */
739 +
740 +void bootmenu_init(struct bootmenu_setup *setup);
741 +
742 +/*
743 + * To add entries on top of the boot menu, call bootmenu_add before
744 + * bootmenu_init. To add entries at the end, call it after bootmenu_init.
745 + * If "fn" is NULL, the command specified in "user" is executed.
746 + */
747 +
748 +void bootmenu_add(const char *label, void (*fn)(void *user), void *user);
749 +
750 +/*
751 + * Run the boot menu.
752 + */
753 +
754 +void bootmenu(void);
755 +
756 +#endif /* !BOOTMENU_H */
757 Index: u-boot/include/configs/neo1973_gta01.h
758 ===================================================================
759 --- u-boot.orig/include/configs/neo1973_gta01.h
760 +++ u-boot/include/configs/neo1973_gta01.h
761 @@ -160,6 +160,8 @@
762  /* valid baudrates */
763  #define CFG_BAUDRATE_TABLE     { 9600, 19200, 38400, 57600, 115200 }
764  
765 +#define CFG_BOOTMENU
766 +
767  /*-----------------------------------------------------------------------
768   * Stack sizes
769   *