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