3 #include <asm/arch/gpio.h>
9 /* game buttons as in GPIO bank 4 */
12 #define BTN_DOWN GPIO7
18 int (*handler)(struct menu_item *item);
22 static struct menu_item *menu_items[24];
23 static int menu_item_count;
25 static int do_cmd(const char *fmt, ...)
31 vsprintf(cmdbuff, fmt, args);
34 return !parse_string_outer(cmdbuff,
35 FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP);
38 static u32 menu_wait_for_input(int down)
40 struct gpio *gpio4_base = (struct gpio *)OMAP34XX_GPIO4_BASE;
44 btns = ~readl(&gpio4_base->datain) &
45 (BTN_UP|BTN_DOWN|BTN_G2|BTN_G3);
54 static int menu_do_default(struct menu_item *item)
59 static int menu_do_poweroff(struct menu_item *item)
63 printf("power off.\n");
65 twl4030_i2c_read_u8(TWL4030_CHIP_PM_MASTER, &d, TWL4030_PM_MASTER_P1_SW_EVENTS);
66 d |= TWL4030_PM_MASTER_SW_EVENTS_DEVOFF;
67 twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, d, TWL4030_PM_MASTER_P1_SW_EVENTS);
72 static int menu_do_usb_serial(struct menu_item *item)
74 do_cmd("dcache off"); /* doesn't work with dcache */
76 printf("Switched to USB serial.\n");
78 setenv("stdout", "usbtty");
79 setenv("stdin", "usbtty");
80 setenv("stderr", "usbtty");
81 setenv("bootcmd", "");
85 static int menu_do_serial(struct menu_item *item)
87 printf("Switched to serial.\n");
89 setenv("stdout", "serial");
90 setenv("bootcmd", "");
94 static int menu_do_script_cmd(struct menu_item *item)
98 if (item->cmd == NULL || !do_cmd(item->cmd))
101 printf("script %s.\n", failed ? "failed" : "finished");
103 menu_wait_for_input(0);
104 menu_wait_for_input(1);
108 static void add_menu_item(const char *name,
109 int (*handler)(struct menu_item *), const char *cmd)
111 struct menu_item *mitem;
113 mitem = malloc(sizeof(*mitem));
116 mitem->name = strdup(name);
117 mitem->handler = handler;
118 mitem->cmd = strdup(cmd);
120 if (menu_item_count < ARRAY_SIZE(menu_items))
121 menu_items[menu_item_count++] = mitem;
124 static char *bootmenu_next_ctl(char *p)
126 while (*p && *p != '|' && *p != '\r' && *p != '\n')
132 static char *bootmenu_skip_blanks(char *p)
134 while (*p && (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n'))
140 static char *bootmenu_skip_line(char *p)
142 while (*p && *p != '\r' && *p != '\n')
148 static void parse_bootmenu(char *buf)
150 char *p = buf, *name, *cmd;
155 p = bootmenu_skip_blanks(p);
159 p = bootmenu_skip_line(p);
164 p = bootmenu_next_ctl(p);
166 printf("bootmenu.txt: invalid line ~%d\n", i);
167 p = bootmenu_skip_line(p);
173 p = bootmenu_skip_line(p);
177 add_menu_item(name, menu_do_script_cmd, cmd);
181 static struct menu_item default_menu_items[] = {
182 { "default boot", menu_do_default, },
183 { "power off", menu_do_poweroff, },
184 { "USB serial prompt", menu_do_usb_serial, },
185 { "serial prompt", menu_do_serial, },
188 static void menu_init(void)
190 const char *check_format1 = "%sload mmc1 0:%d ${loadaddr} boot.scr 4";
191 const char *check_format2 = "%sload mmc1 0:%d ${loadaddr} boot.txt 4";
192 const char *run_format1 = "%sload mmc1 0:%d ${loadaddr} boot.scr;source ${loadaddr}";
193 const char *run_format2 = "mw.l ${loadaddr} 0 1024;%sload mmc1 0:%d ${loadaddr} boot.txt;"
194 "ssource ${loadaddr}";
195 disk_partition_t part_info;
196 block_dev_desc_t *dev_desc;
197 char tmp_name[32], tmp_cmd[128];
200 for (i = 0; i < 2; i++)
201 menu_items[i] = &default_menu_items[i];
204 if (!do_cmd("mmc rescan"))
207 dev_desc = get_dev("mmc1", 0);
208 if (dev_desc == NULL) {
209 printf("dev desc null\n");
213 /* kill stdout while we search for bootfiles */
214 setenv("stdout", "nulldev");
216 for (i = 1; menu_item_count < ARRAY_SIZE(menu_items); i++) {
217 if (get_partition_info(dev_desc, i, &part_info))
219 if (do_cmd("fatls mmc1 0:%d", i)) {
220 if (do_cmd(check_format1, "fat", i)) {
221 sprintf(tmp_cmd, run_format1, "fat", i);
224 if (do_cmd(check_format2, "fat", i)) {
225 sprintf(tmp_cmd, run_format2, "fat", i);
230 if (do_cmd("ext2ls mmc1 0:%d", i)) {
231 if (do_cmd(check_format1, "ext2", i)) {
232 sprintf(tmp_cmd, run_format1, "ext2", i);
235 if (do_cmd(check_format2, "ext2", i)) {
236 sprintf(tmp_cmd, run_format2, "ext2", i);
244 sprintf(tmp_name, "boot from SD1:%d", i);
245 add_menu_item(tmp_name, menu_do_script_cmd, tmp_cmd);
249 setenv("stdout", "serial");
251 if (do_cmd("ubi part boot && ubifsmount boot")) {
252 ulong addr = getenv_ulong("loadaddr", 16, 0);
253 if ((int)addr < (int)0x90000000) {
254 if (do_cmd("ubifsload ${loadaddr} bootmenu.txt")) {
255 ulong size = getenv_ulong("filesize", 16, 0);
256 *(char *)(addr + size) = 0;
257 parse_bootmenu((char *)addr);
262 for (i = 2; i < ARRAY_SIZE(default_menu_items); i++) {
263 if (menu_item_count >= ARRAY_SIZE(menu_items))
265 menu_items[menu_item_count++] = &default_menu_items[i];
268 setenv("stdout", "lcd");
271 static int boot_menu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
273 int i, sel = 0, max_sel;
279 tl_row = panel_info.vl_row / 16 / 2 - (menu_item_count + 2) / 2;
280 max_sel = menu_item_count - 1;
283 console_row = tl_row;
284 lcd_printf("Boot menu");
288 for (i = 0; i < menu_item_count; i++) {
290 console_row = tl_row + 2 + i;
291 lcd_printf(menu_items[i]->name);
294 for (i = 0; i < menu_item_count; i++) {
296 console_row = tl_row + 2 + i;
297 lcd_printf(i == sel ? ">" : " ");
301 menu_wait_for_input(0);
302 btns = menu_wait_for_input(1);
308 else if (btns & BTN_DOWN) {
315 if (menu_items[sel]->handler(menu_items[sel]))
325 pmenu, 1, 1, boot_menu,
326 "show pandora's boot menu",
331 static int do_ssource(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
338 addr = simple_strtoul(argv[1], NULL, 16);
340 printf("## Executing plain script at %08lx\n", addr);
341 return parse_string_outer((char *)addr, FLAG_PARSE_SEMICOLON);
345 ssource, 2, 0, do_ssource,
346 "run script from memory (no header)",
350 static int do_usbinit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
352 extern int drv_usbtty_init(void);
353 static int usbinit_done;
356 return !drv_usbtty_init();
362 usbinit, 1, 0, do_usbinit,
367 static int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
369 menu_do_poweroff(NULL);
374 poweroff, 1, 0, do_poweroff,
375 "power off this device",