]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/pc/sub.c
merge
[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 #define BOOTLINE        ((char*)CONFADDR)
133 #define BOOTLINELEN     64
134 #define BOOTARGS        ((char*)(CONFADDR+BOOTLINELEN))
135 #define BOOTARGSLEN     (4096-0x200-BOOTLINELEN)
136
137 char *confend;
138
139 static void apmconf(int);
140
141 char*
142 configure(void *f, char *path)
143 {
144         char line[64], *kern, *p;
145         int inblock, n;
146 Clear:
147         kern = 0;
148         inblock = 0;
149
150         confend = (char*)BOOTARGS;
151         memset(confend, 0, BOOTARGSLEN);
152 Loop:
153         while((n = readline(f, line)) > 0){
154                 if(*line == 0 || strchr("#;=", *line))
155                         continue;
156                 if(*line == '['){
157                         inblock = memcmp("[common]", line, 8);
158                         continue;
159                 }
160                 if(!memcmp("clear", line, 6)){
161                         print("ok\r\n");
162                         goto Clear;
163                 }
164                 if(!memcmp("boot", line, 5))
165                         break;
166                 if(inblock || !strrchr(line, '='))
167                         continue;
168                 if(!memcmp("bootfile=", line, 9))
169                         memmove(kern = path, line+9, 1 + n-9);
170                 if(!memcmp("apm", line, 3) && line[4]=='='){
171                         apmconf('0' - line[3]);
172                         continue;
173                 }
174                 memmove(confend, line, n); confend += n;
175                 *confend++ = '\n';
176                 print(line); print(crnl);
177         }
178         *confend = 0;
179         if(f){
180                 close(f);
181                 f = 0;
182         }
183         if(!kern){
184                 print("no bootfile\r\n");
185                 goto Loop;
186         }
187         for(n=0; n<10000; n++)
188                 if(gotc())
189                         goto Loop;
190         if(p = strrchr(kern, '!'))
191                 kern = p+1;
192
193         return kern;
194 }
195
196
197 static ushort
198 beswab(ushort s)
199 {
200         uchar *p;
201
202         p = (uchar*)&s;
203         return (p[0]<<8) | p[1];
204 }
205
206 static ulong
207 beswal(ulong l)
208 {
209         uchar *p;
210
211         p = (uchar*)&l;
212         return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
213 }
214
215 static void
216 hexfmt(char *s, int i, ulong a)
217 {
218         s += i;
219         while(i > 0){
220                 *--s = hex[a&15];
221                 a >>= 4;
222                 i--;
223         }
224 }
225
226 static void
227 addconfx(char *s, int w, ulong v)
228 {
229         int n;
230
231         n = strlen(s);
232         memmove(confend, s, n);
233         hexfmt(confend+n, w, v);
234         confend += n+w;
235         *confend = 0;
236 }
237
238 void apm(int id);
239
240 static void
241 apmconf(int id)
242 {
243         uchar *a;
244         char *s;
245
246         a = (uchar*)CONFADDR;
247         memset(a, 0, 20);
248
249         apm(id);
250         if(memcmp(a, "APM", 4))
251                 return;
252
253         s = confend;
254
255         addconfx("apm", 1, id);
256         addconfx("=ax=", 4, *((ushort*)(a+4)));
257         addconfx(" ebx=", 8, *((ulong*)(a+12)));
258         addconfx(" cx=", 4, *((ushort*)(a+6)));
259         addconfx(" dx=", 4, *((ushort*)(a+8)));
260         addconfx(" di=", 4, *((ushort*)(a+10)));
261         addconfx(" esi=", 8, *((ulong*)(a+16)));
262
263         print(s); print(crnl);
264
265         *confend++ = '\n';
266 }
267
268 ulong e820(ulong bx, void *p);
269
270 static void
271 e820conf(void)
272 {
273         struct {
274                 uvlong  base;
275                 uvlong  len;
276                 ulong   typ;
277                 ulong   ext;
278         } e;
279         uvlong v;
280         ulong bx;
281         char *s;
282
283         memset(&e, 0, sizeof(e));
284         if((bx = e820(0, &e)) == 0)
285                 return;
286
287         memmove(confend, "e820=", 5);
288         confend += 5;
289
290         do{
291                 s = confend;
292                 v = e.base;
293                 addconfx("", 8, v>>32);
294                 addconfx("", 8, v&0xffffffff);
295                 v = e.base + e.len;
296                 addconfx(" ", 8, v>>32);
297                 addconfx("", 8, v&0xffffffff);
298
299                 print(s);
300
301                 switch(e.typ){
302                 case 1:
303                         print(" ram");
304                         break;
305                 case 2:
306                         print(" reserved");
307                         break;
308                 case 3:
309                         print(" acpi reclaim");
310                         break;
311                 case 4:
312                         print(" acpi nvs");
313                         break;
314                 case 5:
315                         print(" bad");
316                         break;
317                 default:
318                         print(" ???");
319                 }
320                 print(crnl);
321
322                 if(e.typ == 1 && (e.ext & 1) == 0)
323                         *confend++ = ' ';
324                 else
325                         confend = s;
326                 memset(&e, 0, sizeof(e));
327         } while(bx = e820(bx, &e));
328
329         *confend++ = '\n';
330         *confend = 0;
331 }
332
333 void a20(void);
334
335 char*
336 bootkern(void *f)
337 {
338         uchar *e, *d, *t;
339         ulong n;
340         Exec ex;
341
342         e820conf();
343
344         a20();
345         if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
346                 return "bad header";
347         if(beswal(ex.magic) != I_MAGIC)
348                 return "bad magic";
349
350         e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL);
351         t = e;
352         n = beswal(ex.text);
353         if(readn(f, t, n) != n)
354                 goto Error;
355         d = (uchar*)PGROUND((ulong)t + n);
356         n = beswal(ex.data);
357         if(readn(f, d, n) != n)
358                 goto Error;
359         close(f);
360         unload();
361         memset(BOOTLINE, 0, BOOTLINELEN);
362         jump(e);
363 Error:          
364         return "i/o error";
365 }