diff options
Diffstat (limited to 'meta/packages/uboot/u-boot-mkimage-openmoko-native/boot-menu.patch')
-rw-r--r-- | meta/packages/uboot/u-boot-mkimage-openmoko-native/boot-menu.patch | 769 |
1 files changed, 769 insertions, 0 deletions
diff --git a/meta/packages/uboot/u-boot-mkimage-openmoko-native/boot-menu.patch b/meta/packages/uboot/u-boot-mkimage-openmoko-native/boot-menu.patch new file mode 100644 index 0000000000..352967ae06 --- /dev/null +++ b/meta/packages/uboot/u-boot-mkimage-openmoko-native/boot-menu.patch | |||
@@ -0,0 +1,769 @@ | |||
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 | * | ||