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