summaryrefslogtreecommitdiff
path: root/src/boot/filo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot/filo.c')
-rw-r--r--src/boot/filo.c194
1 files changed, 194 insertions, 0 deletions
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);
+ }
+}