diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/boot/Config.lb | 3 | ||||
-rw-r--r-- | src/boot/filo.c | 194 | ||||
-rw-r--r-- | src/boot/hardwaremain.c | 4 |
3 files changed, 201 insertions, 0 deletions
diff --git a/src/boot/Config.lb b/src/boot/Config.lb index 0264bb96ad..9e38661824 100644 --- a/src/boot/Config.lb +++ b/src/boot/Config.lb @@ -1,2 +1,5 @@ object elfboot.o object hardwaremain.o +if CONFIG_FS_STREAM + object filo.o +end diff --git a/src/boot/filo.c b/src/boot/filo.c new file mode 100644 index 0000000000..f5c5bda420 --- /dev/null +++ b/src/boot/filo.c @@ -0,0 +1,194 @@ +/* + * 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); + } +} diff --git a/src/boot/hardwaremain.c b/src/boot/hardwaremain.c index 6231d1167e..fed5302261 100644 --- a/src/boot/hardwaremain.c +++ b/src/boot/hardwaremain.c @@ -217,6 +217,10 @@ void hardwaremain(int boot_complete) CONFIGURE(CONF_PASS_PRE_BOOT); +#if CONFIG_FS_STREAM == 1 + filo(lb_mem); +#else elfboot(lb_mem); +#endif } |