cd14fa13b346dc3211244e852528ee2ffa05c5a1
[coreboot.git] / src / boot / filo.c
1 /*
2  * Copyright (C) 2003 by SONE Takeshi <ts1@tsn.or.jp> and others.
3  * This program is licensed under the terms of GNU General Public License.
4  *
5  * Modified for coreboot by Greg Watson <gwatson@lanl.gov>
6  */
7
8 #include <console/console.h>
9 #include <delay.h>
10 #include <string.h>
11 #include <boot/tables.h>
12 #include <boot/elf.h>
13
14 #define ENTER '\r'
15 #define ESCAPE '\x1b'
16
17 #ifndef AUTOBOOT_CMDLINE
18 #define autoboot(mem)
19 #endif
20
21 #if !AUTOBOOT_DELAY
22 #define autoboot_delay() 0 /* success */
23 #endif
24
25 #define havechar() console_tst_byte()
26 #define putchar(c) console_tx_byte(c)
27 #define getchar(c) console_rx_byte(c)
28
29 extern char *boot_file;
30
31 int getline(char *buf, int max)
32 {
33     int cur, ch, nonspace_seen;
34
35     cur = 0;
36     while (buf[cur]) {
37         putchar(buf[cur]);
38         cur++;
39     }
40     for (;;) {
41         ch = getchar();
42         switch (ch) {
43         /* end of line */
44         case '\r':
45         case '\n':
46             putchar('\n');
47             goto out;
48         /* backspace */
49         case '\b':
50         case '\x7f':
51             if (cur > 0) {
52                 cur--;
53                 putchar('\b');
54                 putchar(' ');
55                 putchar('\b');
56             }
57             break;
58         /* word erase */
59         case 'W' & 0x1f: /* ^W */
60             nonspace_seen = 0;
61             while (cur) {
62                 if (buf[cur-1] != ' ')
63                     nonspace_seen = 1;
64                 putchar('\b');
65                 putchar(' ');
66                 putchar('\b');
67                 cur--;
68                 if (nonspace_seen && cur < max-1 && cur > 0 && buf[cur-1]==' ')
69                     break;
70             }
71             break;
72         /* line erase */
73         case 'U' & 0x1f: /* ^U */
74             while (cur) {
75                 putchar('\b');
76                 putchar(' ');
77                 putchar('\b');
78                 cur--;
79             }
80             cur = 0;
81             break;
82         default:
83             if (ch < 0x20)
84                 break; /* ignore control char */
85             if (ch >= 0x7f)
86                 break;
87             if (cur + 1 < max) {
88                 putchar(ch); /* echo back */
89                 buf[cur] = ch;
90                 cur++;
91             }
92         }
93     }
94 out:
95     if (cur >= max)
96         cur = max - 1;
97     buf[cur] = '\0';
98     return cur;
99 }
100
101 static void boot(struct lb_memory *mem, const char *line)
102 {
103     char *param;
104
105     /* Split filename and parameter */
106     boot_file = strdup(line);
107     param = strchr(boot_file, ' ');
108     if (param) {
109         *param = '\0';
110         param++;
111     }
112
113     if (!elfboot(mem))
114         printk_info("Unsupported image format\n");
115     free(boot_file);
116 }
117
118 #ifdef AUTOBOOT_CMDLINE
119 #if AUTOBOOT_DELAY
120 static inline int autoboot_delay(void)
121 {
122     unsigned int timeout;
123     int sec, tmp;
124     char key;
125     
126     key = 0;
127
128     printk_info("Press <Enter> for default boot, or <Esc> for boot prompt... ");
129     for (sec = AUTOBOOT_DELAY; sec>0 && key==0; sec--) {
130         printk_info("%d", sec);
131         timeout = 10;
132         while (timeout-- > 0) {
133             if (havechar()) {
134                 key = getchar();
135                 if (key==ENTER || key==ESCAPE)
136                     break;
137             }
138             mdelay(100);
139         }
140         for (tmp = sec; tmp; tmp /= 10)
141             printk_info("\b \b");
142     }
143     if (key == 0) {
144         printk_info("timed out\n");
145         return 0; /* success */
146     } else {
147         putchar('\n');
148         if (key == ESCAPE)
149             return -1; /* canceled */
150         else
151             return 0; /* default accepted */
152     }
153 }
154 #endif /* AUTOBOOT_DELAY */
155
156 static void autoboot(struct lb_memory *mem)
157 {
158     /* If Escape key is pressed already, skip autoboot */
159     if (havechar() && getchar()==ESCAPE)
160         return;
161
162     if (autoboot_delay()==0) {
163         printk_info("boot: %s\n", AUTOBOOT_CMDLINE);
164         boot(mem, AUTOBOOT_CMDLINE);
165     }
166 }
167 #endif /* AUTOBOOT_CMDLINE */
168
169 /* The main routine */
170 int filo(struct lb_memory *mem)
171 {
172     char line[256];
173
174     printk_info("FILO version 0.4.1\n");
175
176     /* Try default image */
177     autoboot(mem);
178
179     /* The above didn't work, ask user */
180     while (havechar())
181         getchar();
182 #ifdef AUTOBOOT_CMDLINE
183     strncpy(line, AUTOBOOT_CMDLINE, sizeof(line)-1);
184     line[sizeof(line)-1] = '\0';
185 #else
186     line[0] = '\0';
187 #endif
188     for (;;) {
189         printk_info("boot: ");
190         getline(line, sizeof line);
191         if (line[0])
192             boot(mem, line);
193     }
194 }