3 #include <asm/arch/gpio.h>
9 #include "pandora-buttons.h"
13 int (*handler)(struct menu_item *item);
17 static struct menu_item *menu_items[24];
18 static int menu_item_count;
20 static int do_cmd(const char *fmt, ...)
26 vsprintf(cmdbuff, fmt, args);
29 return !parse_string_outer(cmdbuff,
30 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
33 static u32 menu_wait_for_input(int down)
35 struct gpio *gpio4_base = (struct gpio *)OMAP34XX_GPIO4_BASE;
39 btns = ~readl(&gpio4_base->datain) &
40 (BTN_UP|BTN_DOWN|BTN_G2|BTN_G3);
49 static int menu_do_default(struct menu_item *item)
54 static int menu_do_poweroff(struct menu_item *item)
58 printf("power off.\n");
60 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, &d, TWL4030_PM_MASTER_P1_SW_EVENTS);
61 d |= TWL4030_PM_MASTER_SW_EVENTS_DEVOFF;
62 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, d, TWL4030_PM_MASTER_P1_SW_EVENTS);
67 static int menu_do_usb_serial(struct menu_item *item)
69 do_cmd("dcache off"); /* doesn't work with dcache */
71 printf("Switched to USB serial.\n");
73 setenv("stdout", "usbtty");
74 setenv("stdin", "usbtty");
75 setenv("stderr", "usbtty");
76 setenv("bootcmd", "");
80 static int menu_do_serial(struct menu_item *item)
82 printf("Switched to serial.\n");
84 setenv("stdout", "serial");
85 setenv("bootcmd", "");
89 #ifdef CONFIG_KEYBOARD
90 static int menu_do_console(struct menu_item *item)
92 printf("Switched to console.\n");
93 setenv("stdout", "lcd");
94 setenv("stderr", "lcd");
95 setenv("stdin", "kbd");
96 setenv("bootcmd", "");
101 static int menu_do_script_cmd(struct menu_item *item)
105 if (item->cmd == NULL || !do_cmd(item->cmd))
108 printf("script %s.\n", failed ? "failed" : "finished");
110 menu_wait_for_input(0);
111 menu_wait_for_input(1);
115 static void add_menu_item(const char *name,
116 int (*handler)(struct menu_item *), const char *cmd)
118 struct menu_item *mitem;
120 mitem = malloc(sizeof(*mitem));
123 mitem->name = strdup(name);
124 mitem->handler = handler;
125 mitem->cmd = strdup(cmd);
127 if (menu_item_count < ARRAY_SIZE(menu_items))
128 menu_items[menu_item_count++] = mitem;
131 static char *bootmenu_next_ctl(char *p)
133 while (*p && *p != '|' && *p != '\r' && *p != '\n')
139 static char *bootmenu_skip_blanks(char *p)
141 while (*p && (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n'))
147 static char *bootmenu_skip_line(char *p)
149 while (*p && *p != '\r' && *p != '\n')
155 static void parse_bootmenu(char *buf)
157 char *p = buf, *name, *cmd;
162 p = bootmenu_skip_blanks(p);
166 p = bootmenu_skip_line(p);
171 p = bootmenu_next_ctl(p);
173 printf("bootmenu.txt: invalid line ~%d\n", i);
174 p = bootmenu_skip_line(p);
180 p = bootmenu_skip_line(p);
184 add_menu_item(name, menu_do_script_cmd, cmd);
188 static struct menu_item default_menu_items[] = {
189 { "default boot", menu_do_default, },
190 { "power off", menu_do_poweroff, },
191 { "USB serial prompt", menu_do_usb_serial, },
192 { "serial prompt", menu_do_serial, },
193 #ifdef CONFIG_KEYBOARD
194 { "console prompt", menu_do_console, },
198 static void do_mmc(int dev_id)
200 static const char *check_format1 = "%sload mmc %d:%d ${loadaddr} boot.scr 4";
201 static const char *check_format2 = "%sload mmc %d:%d ${loadaddr} boot.txt 4";
202 static const char *run_format1 = "%sload mmc %d:%d ${loadaddr} boot.scr;source ${loadaddr}";
203 static const char *run_format2 = "%sload mmc %d:%d ${loadaddr} boot.txt;ssource ${loadaddr} ${filesize}";
204 disk_partition_t part_info;
205 block_dev_desc_t *dev_desc;
206 char tmp_name[32], tmp_cmd[128];
209 dev_desc = get_dev("mmc", dev_id);
210 if (dev_desc == NULL) {
211 printf("dev desc null\n");
215 for (i = 1; menu_item_count < ARRAY_SIZE(menu_items); i++) {
216 if (get_partition_info(dev_desc, i, &part_info))
218 if (do_cmd("fatls mmc %d:%d", dev_id, i)) {
219 if (do_cmd(check_format1, "fat", dev_id, i)) {
220 sprintf(tmp_cmd, run_format1, "fat", dev_id, i);
223 if (do_cmd(check_format2, "fat", dev_id, i)) {
224 sprintf(tmp_cmd, run_format2, "fat", dev_id, i);
229 if (do_cmd("ext2ls mmc %d:%d", dev_id, i)) {
230 if (do_cmd(check_format1, "ext2", dev_id, i)) {
231 sprintf(tmp_cmd, run_format1, "ext2", dev_id, i);
234 if (do_cmd(check_format2, "ext2", dev_id, i)) {
235 sprintf(tmp_cmd, run_format2, "ext2", dev_id, i);
243 sprintf(tmp_name, "boot from SD%d:%d", dev_id + 1, i);
244 add_menu_item(tmp_name, menu_do_script_cmd, tmp_cmd);
248 static void menu_init(void)
252 for (i = 0; i < 2; i++)
253 menu_items[i] = &default_menu_items[i];
256 if (do_cmd("mmc dev 0 && mmc rescan"))
258 /* kill stdout while we search for bootfiles */
259 setenv("stdout", "nulldev");
261 setenv("stdout", "serial");
264 if (do_cmd("mmc dev 1 && mmc rescan"))
266 setenv("stdout", "nulldev");
268 setenv("stdout", "serial");
273 if (do_cmd("ubi part boot && ubifsmount boot")) {
274 ulong addr = getenv_ulong("loadaddr", 16, 0);
275 if ((int)addr < (int)0x90000000) {
276 if (do_cmd("ubifsload ${loadaddr} bootmenu.txt")) {
277 ulong size = getenv_ulong("filesize", 16, 0);
278 *(char *)(addr + size) = 0;
279 parse_bootmenu((char *)addr);
284 for (i = 2; i < ARRAY_SIZE(default_menu_items); i++) {
285 if (menu_item_count >= ARRAY_SIZE(menu_items))
287 menu_items[menu_item_count++] = &default_menu_items[i];
290 setenv("stdout", "lcd");
293 static int boot_menu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
295 int i, sel = 0, max_sel;
301 tl_row = panel_info.vl_row / 16 / 2 - (menu_item_count + 2) / 2;
302 max_sel = menu_item_count - 1;
305 console_row = tl_row;
306 lcd_printf("Boot menu");
310 for (i = 0; i < menu_item_count; i++) {
312 console_row = tl_row + 2 + i;
313 lcd_printf(menu_items[i]->name);
316 for (i = 0; i < menu_item_count; i++) {
318 console_row = tl_row + 2 + i;
319 lcd_printf(i == sel ? ">" : " ");
323 menu_wait_for_input(0);
324 btns = menu_wait_for_input(1);
330 else if (btns & BTN_DOWN) {
337 if (menu_items[sel]->handler(menu_items[sel]))
347 pmenu, 1, 1, boot_menu,
348 "show pandora's boot menu",
353 static int do_ssource(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
355 ulong addr, size = 0;
360 addr = simple_strtoul(argv[1], NULL, 16);
362 size = simple_strtoul(argv[2], NULL, 16);
363 *(char *)(addr + size) = 0;
366 printf("## Executing plain script at %08lx, size %ld\n", addr, size);
367 return parse_string_outer((char *)addr, FLAG_PARSE_SEMICOLON);
371 ssource, 3, 0, do_ssource,
372 "run script from memory (no header)",
373 "<addr> [size_hex]" /* note: without size may parse trash after the script */
376 static int do_usbinit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
378 extern int drv_usbtty_init(void);
379 static int usbinit_done;
382 return !drv_usbtty_init();
388 usbinit, 1, 0, do_usbinit,
393 static int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
395 menu_do_poweroff(NULL);
400 poweroff, 1, 0, do_poweroff,
401 "power off this device",