| /* |
| * Copyright (C) 2003 by SONE Takeshi <ts1@tsn.or.jp> and others. |
| * This program is licensed under the terms of GNU General Public License. |
| * |
| * Modified for LinuxBIOS by Greg Watson <gwatson@lanl.gov> |
| */ |
| |
| #include <console/console.h> |
| #include <delay.h> |
| #include <string.h> |
| #include <boot/tables.h> |
| #include <boot/elf.h> |
| |
| #define ENTER '\r' |
| #define ESCAPE '\x1b' |
| |
| #ifndef AUTOBOOT_CMDLINE |
| #define autoboot(mem) |
| #endif |
| |
| #ifndef AUTOBOOT_DELAY |
| #define autoboot_delay() 0 /* success */ |
| #endif |
| |
| #define havechar() console_tst_byte() |
| #define putchar(c) console_tx_byte(c) |
| #define getchar(c) console_rx_byte(c) |
| |
| extern char *boot_file; |
| |
| int getline(char *buf, int max) |
| { |
| int cur, ch, nonspace_seen; |
| |
| cur = 0; |
| while (buf[cur]) { |
| putchar(buf[cur]); |
| cur++; |
| } |
| for (;;) { |
| ch = getchar(); |
| switch (ch) { |
| /* end of line */ |
| case '\r': |
| case '\n': |
| putchar('\n'); |
| goto out; |
| /* backspace */ |
| case '\b': |
| case '\x7f': |
| if (cur > 0) { |
| cur--; |
| putchar('\b'); |
| putchar(' '); |
| putchar('\b'); |
| } |
| break; |
| /* word erase */ |
| case 'W' & 0x1f: /* ^W */ |
| nonspace_seen = 0; |
| while (cur) { |
| if (buf[cur-1] != ' ') |
| nonspace_seen = 1; |
| putchar('\b'); |
| putchar(' '); |
| putchar('\b'); |
| cur--; |
| if (nonspace_seen && cur < max-1 && cur > 0 && buf[cur-1]==' ') |
| break; |
| } |
| break; |
| /* line erase */ |
| case 'U' & 0x1f: /* ^U */ |
| while (cur) { |
| putchar('\b'); |
| putchar(' '); |
| putchar('\b'); |
| cur--; |
| } |
| cur = 0; |
| break; |
| default: |
| if (ch < 0x20) |
| break; /* ignore control char */ |
| if (ch >= 0x7f) |
| break; |
| if (cur + 1 < max) { |
| putchar(ch); /* echo back */ |
| buf[cur] = ch; |
| cur++; |
| } |
| } |
| } |
| out: |
| if (cur >= max) |
| cur = max - 1; |
| buf[cur] = '\0'; |
| return cur; |
| } |
| |
| static void boot(struct lb_memory *mem, const char *line) |
| { |
| char *param; |
| |
| /* Split filename and parameter */ |
| boot_file = strdup(line); |
| param = strchr(boot_file, ' '); |
| if (param) { |
| *param = '\0'; |
| param++; |
| } |
| |
| if (!elfboot(mem)) |
| printk_info("Unsupported image format\n"); |
| free(boot_file); |
| } |
| |
| #ifdef AUTOBOOT_CMDLINE |
| #if AUTOBOOT_DELAY |
| static inline int autoboot_delay(void) |
| { |
| unsigned int timeout; |
| int sec, tmp; |
| char key; |
| |
| key = 0; |
| |
| printk_info("Press <Enter> for default boot, or <Esc> for boot prompt... "); |
| for (sec = AUTOBOOT_DELAY; sec>0 && key==0; sec--) { |
| printk_info("%d", sec); |
| timeout = 10; |
| while (timeout-- > 0) { |
| if (havechar()) { |
| key = getchar(); |
| if (key==ENTER || key==ESCAPE) |
| break; |
| } |
| mdelay(100); |
| } |
| for (tmp = sec; tmp; tmp /= 10) |
| printk_info("\b \b"); |
| } |
| if (key == 0) { |
| printk_info("timed out\n"); |
| return 0; /* success */ |
| } else { |
| putchar('\n'); |
| if (key == ESCAPE) |
| return -1; /* canceled */ |
| else |
| return 0; /* default accepted */ |
| } |
| } |
| #endif /* AUTOBOOT_DELAY */ |
| |
| static void autoboot(struct lb_memory *mem) |
| { |
| /* If Escape key is pressed already, skip autoboot */ |
| if (havechar() && getchar()==ESCAPE) |
| return; |
| |
| if (autoboot_delay()==0) { |
| printk_info("boot: %s\n", AUTOBOOT_CMDLINE); |
| boot(mem, AUTOBOOT_CMDLINE); |
| } |
| } |
| #endif /* AUTOBOOT_CMDLINE */ |
| |
| /* The main routine */ |
| int filo(struct lb_memory *mem) |
| { |
| char line[256]; |
| |
| printk_info("FILO version 0.4.1\n"); |
| |
| /* Try default image */ |
| autoboot(mem); |
| |
| /* The above didn't work, ask user */ |
| while (havechar()) |
| getchar(); |
| #ifdef AUTOBOOT_CMDLINE |
| strncpy(line, AUTOBOOT_CMDLINE, sizeof(line)-1); |
| line[sizeof(line)-1] = '\0'; |
| #else |
| line[0] = '\0'; |
| #endif |
| for (;;) { |
| printk_info("boot: "); |
| getline(line, sizeof line); |
| if (line[0]) |
| boot(mem, line); |
| } |
| } |