]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/pc/sub.c
9boot: use 500 ms timeout
[plan9front.git] / sys / src / boot / pc / sub.c
1 #include <u.h>
2 #include <a.out.h>
3 #include "fns.h"
4 #include "mem.h"
5
6 void
7 memset(void *p, int v, int n)
8 {
9         uchar *d = p;
10         while(n > 0){
11                 *d++ = v;
12                 n--;
13         }
14 }
15
16 void
17 memmove(void *dst, void *src, int n)
18 {
19         uchar *d = dst;
20         uchar *s = src;
21
22         if(d < s){
23                 while(n > 0){
24                         *d++ = *s++;
25                         n--;
26                 }
27         } if(d > s){
28                 s += n;
29                 d += n;
30                 while(n > 0){
31                         *--d = *--s;
32                         n--;
33                 }
34         }
35 }
36
37 int
38 memcmp(void *src, void *dst, int n)
39 {
40         uchar *d = dst;
41         uchar *s = src;
42         int r = 0;
43         while((n > 0) && (r = (*d++ - *s++)) == 0)
44                 n--;
45         return r;
46 }
47
48 int
49 strlen(char *s)
50 {
51         char *p = s;
52         while(*p)
53                 p++;
54         return p - s;
55 }
56
57 char*
58 strchr(char *s, int c)
59 {
60         for(; *s; s++)
61                 if(*s == c)
62                         return s;
63         return 0;
64 }
65
66 char*
67 strrchr(char *s, int c)
68 {
69         char *r;
70         r = 0;
71         while(s = strchr(s, c))
72                 r = s++;
73         return r;
74 }
75
76 void
77 print(char *s)
78 {
79         while(*s)
80                 putc(*s++);
81 }
82
83 int
84 readn(void *f, void *data, int len)
85 {
86         uchar *p, *e;
87
88         p = data;
89         e = p + len;
90         while(p < e){
91                 if((len = read(f, p, e - p)) <= 0)
92                         break;
93                 p += len;
94         }
95         return p - (uchar*)data;
96 }
97
98 static int
99 readline(void *f, char buf[64])
100 {
101         static char white[] = "\t ";
102         char *p;
103
104         p = buf;
105         do{
106                 if(!f)
107                         putc('>');
108                 while(p < buf + 64-1){
109                         if(!f){
110                                 putc(*p = getc());
111                                 if(*p == '\r')
112                                         putc('\n');
113                                 else if(*p == 0x08 && p > buf){
114                                         p--;
115                                         continue;
116                                 }
117                         }else if(read(f, p, 1) <= 0)
118                                 return 0;
119                         if(p == buf && strchr(white, *p))
120                                 continue;
121                         if(strchr(crnl, *p))
122                                 break;
123                         p++;
124                 }
125                 while(p > buf && strchr(white, p[-1]))
126                         p--;
127         }while(p == buf);
128         *p = 0;
129         return p - buf;
130 }
131
132 static int
133 timeout(int ms)
134 {
135         while(ms > 0){
136                 if(gotc())
137                         return 1;
138                 usleep(100000);
139                 ms -= 100;
140         }
141         return 0;
142 }
143
144 #define BOOTLINE        ((char*)CONFADDR)
145 #define BOOTLINELEN     64
146 #define BOOTARGS        ((char*)(CONFADDR+BOOTLINELEN))
147 #define BOOTARGSLEN     (4096-0x200-BOOTLINELEN)
148
149 char *confend;
150
151 static void apmconf(int);
152
153 char*
154 configure(void *f, char *path)
155 {
156         char line[64], *kern, *p;
157         int inblock, n;
158 Clear:
159         kern = 0;
160         inblock = 0;
161
162         confend = (char*)BOOTARGS;
163         memset(confend, 0, BOOTARGSLEN);
164 Loop:
165         while((n = readline(f, line)) > 0){
166                 if(*line == 0 || strchr("#;=", *line))
167                         continue;
168                 if(*line == '['){
169                         inblock = memcmp("[common]", line, 8);
170                         continue;
171                 }
172                 if(!memcmp("clear", line, 6)){
173                         print("ok\r\n");
174                         goto Clear;
175                 }
176                 if(!memcmp("boot", line, 5))
177                         break;
178                 if(inblock || !strrchr(line, '='))
179                         continue;
180                 if(!memcmp("bootfile=", line, 9))
181                         memmove(kern = path, line+9, 1 + n-9);
182                 if(!memcmp("apm", line, 3) && line[4]=='='){
183                         apmconf('0' - line[3]);
184                         continue;
185                 }
186                 memmove(confend, line, n); confend += n;
187                 *confend++ = '\n';
188                 print(line); print(crnl);
189         }
190         *confend = 0;
191
192         if(f){
193                 close(f);
194                 f = 0;
195
196                 if(kern && timeout(500))
197                         goto Loop;
198         }
199
200         if(!kern){
201                 print("no bootfile\r\n");
202                 goto Loop;
203         }
204         if(p = strrchr(kern, '!'))
205                 kern = p+1;
206
207         return kern;
208 }
209
210
211 static ushort
212 beswab(ushort s)
213 {
214         uchar *p;
215
216         p = (uchar*)&s;
217         return (p[0]<<8) | p[1];
218 }
219
220 static ulong
221 beswal(ulong l)
222 {
223         uchar *p;
224
225         p = (uchar*)&l;
226         return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
227 }
228
229 static void
230 hexfmt(char *s, int i, ulong a)
231 {
232         s += i;
233         while(i > 0){
234                 *--s = hex[a&15];
235                 a >>= 4;
236                 i--;
237         }
238 }
239
240 static void
241 addconfx(char *s, int w, ulong v)
242 {
243         int n;
244
245         n = strlen(s);
246         memmove(confend, s, n);
247         hexfmt(confend+n, w, v);
248         confend += n+w;
249         *confend = 0;
250 }
251
252 void apm(int id);
253
254 static void
255 apmconf(int id)
256 {
257         uchar *a;
258         char *s;
259
260         a = (uchar*)CONFADDR;
261         memset(a, 0, 20);
262
263         apm(id);
264         if(memcmp(a, "APM", 4))
265                 return;
266
267         s = confend;
268
269         addconfx("apm", 1, id);
270         addconfx("=ax=", 4, *((ushort*)(a+4)));
271         addconfx(" ebx=", 8, *((ulong*)(a+12)));
272         addconfx(" cx=", 4, *((ushort*)(a+6)));
273         addconfx(" dx=", 4, *((ushort*)(a+8)));
274         addconfx(" di=", 4, *((ushort*)(a+10)));
275         addconfx(" esi=", 8, *((ulong*)(a+16)));
276
277         print(s); print(crnl);
278
279         *confend++ = '\n';
280 }
281
282 ulong e820(ulong bx, void *p);
283
284 static void
285 e820conf(void)
286 {
287         struct {
288                 uvlong  base;
289                 uvlong  len;
290                 ulong   typ;
291                 ulong   ext;
292         } e;
293         uvlong v;
294         ulong bx;
295         char *s;
296
297         memset(&e, 0, sizeof(e));
298         if((bx = e820(0, &e)) == 0)
299                 return;
300
301         s = confend;
302         memmove(confend, "e820=", 5);
303         confend += 5;
304
305         do{
306                 if(e.typ == 1 && (e.ext & 1) == 0 && e.len){
307                         v = e.base;
308                         addconfx("", 8, v>>32);
309                         addconfx("", 8, v&0xffffffff);
310                         v = e.base + e.len;
311                         addconfx(" ", 8, v>>32);
312                         addconfx("", 8, v&0xffffffff);
313                         *confend++ = ' ';
314                 }
315
316                 memset(&e, 0, sizeof(e));
317         } while(bx = e820(bx, &e));
318
319         *confend = 0;
320         print(s); print(crnl);
321
322         *confend++ = '\n';
323 }
324
325 void a20(void);
326
327 char*
328 bootkern(void *f)
329 {
330         uchar *e, *d, *t;
331         ulong n;
332         Exec ex;
333
334         e820conf();
335
336         a20();
337         if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
338                 return "bad header";
339         if(beswal(ex.magic) != I_MAGIC)
340                 return "bad magic";
341
342         e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL);
343         t = e;
344         n = beswal(ex.text);
345         if(readn(f, t, n) != n)
346                 goto Error;
347         d = (uchar*)PGROUND((ulong)t + n);
348         n = beswal(ex.data);
349         if(readn(f, d, n) != n)
350                 goto Error;
351         close(f);
352         unload();
353         memset(BOOTLINE, 0, BOOTLINELEN);
354         jump(e);
355 Error:          
356         return "i/o error";
357 }