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