]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/pc/sub.c
9boot: add support for clearing single config settings
[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, n;
193
194 Clear:
195         kern = 0;
196         inblock = 0;
197
198         memset(BOOTLINE, 0, BOOTLINELEN);
199
200         confend = BOOTARGS;
201         memset(confend, 0, BOOTARGSLEN);
202
203         e820conf();
204 Loop:
205         while(readline(f, line) > 0){
206                 if(*line == 0 || strchr("#;=", *line))
207                         continue;
208                 if(*line == '['){
209                         inblock = memcmp("[common]", line, 8);
210                         continue;
211                 }
212                 if(!memcmp("boot", line, 5))
213                         break;
214                 if(!memcmp("clear", line, 5)){
215                         if(line[5] == 0){
216                                 print("ok");
217                                 print(crnl);
218                                 goto Clear;
219                         } else if(line[5] == ' ' && delconf(line+6)){
220                                 print("ok");
221                                 print(crnl);
222                         }
223                         continue;
224                 }
225                 if(inblock || (p = strchr(line, '=')) == nil)
226                         continue;
227                 *p++ = 0;
228                 delconf(line);
229                 if(!memcmp("apm", line, 3)){
230                         apmconf('0' - line[3]);
231                         continue;
232                 }
233                 if(!memcmp("bootfile", line, 8))
234                         memmove(kern = path, p, strlen(p)+1);
235
236                 s = confend;
237                 memmove(confend, line, n = strlen(line)); confend += n;
238                 *confend++ = '=';
239                 memmove(confend, p, n = strlen(p)); confend += n;
240                 *confend = 0;
241
242                 print(s); print(crnl);
243
244                 *confend++ = '\n';
245                 *confend = 0;
246         }
247
248         if(f){
249                 close(f);
250                 f = 0;
251
252                 if(kern && timeout(1000))
253                         goto Loop;
254         }
255
256         if(!kern){
257                 print("no bootfile\r\n");
258                 goto Loop;
259         }
260         if(p = strrchr(kern, '!'))
261                 kern = p+1;
262
263         return kern;
264 }
265
266
267 static void
268 hexfmt(char *s, int i, ulong a)
269 {
270         s += i;
271         while(i > 0){
272                 *--s = hex[a&15];
273                 a >>= 4;
274                 i--;
275         }
276 }
277
278 static void
279 addconfx(char *s, int w, ulong v)
280 {
281         int n;
282
283         n = strlen(s);
284         memmove(confend, s, n);
285         hexfmt(confend+n, w, v);
286         confend += n+w;
287         *confend = 0;
288 }
289
290 void apm(int id);
291
292 static void
293 apmconf(int id)
294 {
295         uchar *a;
296         char *s;
297
298         a = (uchar*)CONFADDR;
299         memset(a, 0, 20);
300
301         apm(id);
302         if(memcmp(a, "APM", 4))
303                 return;
304
305         s = confend;
306
307         addconfx("apm", 1, id);
308         addconfx("=ax=", 4, *((ushort*)(a+4)));
309         addconfx(" ebx=", 8, *((ulong*)(a+12)));
310         addconfx(" cx=", 4, *((ushort*)(a+6)));
311         addconfx(" dx=", 4, *((ushort*)(a+8)));
312         addconfx(" di=", 4, *((ushort*)(a+10)));
313         addconfx(" esi=", 8, *((ulong*)(a+16)));
314
315         print(s); print(crnl);
316
317         *confend++ = '\n';
318         *confend = 0;
319 }
320
321 ulong e820(ulong bx, void *p);
322
323 static void
324 e820conf(void)
325 {
326         struct {
327                 uvlong  base;
328                 uvlong  len;
329                 ulong   typ;
330                 ulong   ext;
331         } e;
332         uvlong v;
333         ulong bx;
334         char *s;
335
336         memset(&e, 0, sizeof(e));
337         if((bx = e820(0, &e)) == 0)
338                 return;
339
340         s = confend;
341         memmove(confend, "e820=", 5);
342         confend += 5;
343
344         do{
345                 if(e.typ == 1 && (e.ext & 1) == 0 && e.len){
346                         v = e.base;
347                         addconfx("", 8, v>>32);
348                         addconfx("", 8, v&0xffffffff);
349                         v = e.base + e.len;
350                         addconfx(" ", 8, v>>32);
351                         addconfx("", 8, v&0xffffffff);
352                         *confend++ = ' ';
353                 }
354
355                 memset(&e, 0, sizeof(e));
356         } while(bx = e820(bx, &e));
357
358         *confend = 0;
359         print(s); print(crnl);
360
361         *confend++ = '\n';
362         *confend = 0;
363 }
364
365 static ushort
366 beswab(ushort s)
367 {
368         uchar *p;
369
370         p = (uchar*)&s;
371         return (p[0]<<8) | p[1];
372 }
373
374 static ulong
375 beswal(ulong l)
376 {
377         uchar *p;
378
379         p = (uchar*)&l;
380         return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
381 }
382
383 void a20(void);
384
385 char*
386 bootkern(void *f)
387 {
388         uchar *e, *d, *t;
389         ulong n;
390         Exec ex;
391
392         a20();
393
394         if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
395                 return "bad header";
396         if(beswal(ex.magic) != I_MAGIC)
397                 return "bad magic";
398
399         e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL);
400         t = e;
401         n = beswal(ex.text);
402
403         if(readn(f, t, n) != n)
404                 goto Error;
405         d = (uchar*)PGROUND((ulong)t + n);
406         n = beswal(ex.data);
407
408         if(readn(f, d, n) != n)
409                 goto Error;
410         close(f);
411         unload();
412
413         print("boot");
414         print(crnl);
415
416         jump(e);
417
418 Error:          
419         return "i/o error";
420 }