]> git.lizzy.rs Git - plan9front.git/blob - sys/src/boot/efi/sub.c
efi: use LocateHandle() and HandleProtocol() to check for multiple gop protocols...
[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[64])
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                                 putc(*p);
114                                 if(*p == '\r')
115                                         putc('\n');
116                                 else if(*p == '\b' && p > buf){
117                                         p--;
118                                         continue;
119                                 }
120                         }else if(read(f, p, 1) <= 0)
121                                 return 0;
122                         if(strchr("\r\n", *p) != nil)
123                                 break;
124                         if(p == buf && strchr(white, *p) != nil)
125                                 continue;       /* whitespace on start of line */
126                         if(p >= buf + 64-1){
127                                 if(f == nil){
128                                         putc('\b');
129                                         putc(' ');
130                                         putc('\b');
131                                 }
132                                 continue;       /* line full do not advance */
133                         }
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(getc() != 0)
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 char*
164 getconf(char *s, char *buf)
165 {
166         char *p, *e;
167         int n;
168
169         n = strlen(s);
170         for(p = BOOTARGS; p < confend; p = e+1){
171                 for(e = p+1; e < confend; e++)
172                         if(*e == '\n')
173                                 break;
174                 if(memcmp(p, s, n) == 0){
175                         p += n;
176                         n = e - p;
177                         buf[n] = 0;
178                         memmove(buf, p, n);
179                         return buf;
180                 }
181         }
182         return nil;
183 }
184
185 static int
186 delconf(char *s)
187 {
188         char *p, *e;
189
190         for(p = BOOTARGS; p < confend; p = e){
191                 for(e = p+1; e < confend; e++){
192                         if(*e == '\n'){
193                                 e++;
194                                 break;
195                         }
196                 }
197                 if(memcmp(p, s, strlen(s)) == 0){
198                         memmove(p, e, confend - e);
199                         confend -= e - p;
200                         *confend = 0;
201                         return 1;
202                 }
203         }
204         return 0;
205 }
206
207 char*
208 configure(void *f, char *path)
209 {
210         char line[64], *kern, *s, *p;
211         int inblock, nowait, n;
212         static int once = 1;
213
214         if(once){
215                 once = 0;
216 Clear:
217                 memset(BOOTLINE, 0, BOOTLINELEN);
218
219                 confend = BOOTARGS;
220                 memset(confend, 0, BOOTARGSLEN);
221                 eficonfig(&confend);
222         }
223         nowait = 1;
224         inblock = 0;
225 Loop:
226         while(readline(f, line) > 0){
227                 if(*line == 0 || strchr("#;=", *line) != nil)
228                         continue;
229                 if(*line == '['){
230                         inblock = memcmp("[common]", line, 8) != 0;
231                         continue;
232                 }
233                 if(memcmp("boot", line, 5) == 0){
234                         nowait=1;
235                         break;
236                 }
237                 if(memcmp("wait", line, 5) == 0){
238                         nowait=0;
239                         continue;
240                 }
241                 if(memcmp("show", line, 5) == 0){
242                         print(BOOTARGS);
243                         continue;
244                 }
245                 if(memcmp("clear", line, 5) == 0){
246                         if(line[5] == '\0'){
247                                 print("ok\n");
248                                 goto Clear;
249                         } else if(line[5] == ' ' && delconf(line+6))
250                                 print("ok\n");
251                         continue;
252                 }
253                 if(inblock != 0 || (p = strchr(line, '=')) == nil)
254                         continue;
255                 *p++ = 0;
256                 delconf(line);
257                 s = confend;
258                 memmove(confend, line, n = strlen(line)); confend += n;
259                 *confend++ = '=';
260                 memmove(confend, p, n = strlen(p)); confend += n;
261                 *confend++ = '\n';
262                 *confend = 0;
263                 print(s);
264         }
265         kern = getconf("bootfile=", path);
266
267         if(f != nil){
268                 close(f);
269                 f = nil;
270
271                 if(kern != nil && (nowait==0 || timeout(1000)))
272                         goto Loop;
273         }
274
275         if(kern == nil){
276                 print("no bootfile\n");
277                 goto Loop;
278         }
279         while((p = strchr(kern, '!')) != nil)
280                 kern = p+1;
281
282         return kern;
283 }
284
285 static char*
286 numfmt(char *s, ulong b, ulong i, ulong a)
287 {
288         char *r;
289
290         if(i == 0){
291                 ulong v = a;
292                 while(v != 0){
293                         v /= b;
294                         i++;
295                 }
296                 if(i == 0)
297                         i = 1;
298         }
299
300         s += i;
301         r = s;
302         while(i > 0){
303                 *--s = hex[a % b];
304                 a /= b;
305                 i--;
306         }
307         return r;
308 }
309
310 char*
311 hexfmt(char *s, int i, uvlong a)
312 {
313         if(i > 8){
314                 s = numfmt(s, 16, i-8, a>>32);
315                 i = 8;
316         }
317         return numfmt(s, 16, i, a);
318 }
319
320 char*
321 decfmt(char *s, int i, ulong a)
322 {
323         return numfmt(s, 10, i, a);
324 }
325
326 static ulong
327 beswal(ulong l)
328 {
329         uchar *p = (uchar*)&l;
330         return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
331 }
332
333 char*
334 bootkern(void *f)
335 {
336         uchar *e, *d, *t;
337         ulong n;
338         Exec ex;
339
340         if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
341                 return "bad header";
342
343         e = (uchar*)(beswal(ex.entry) & ~0xF0000000UL);
344         switch(beswal(ex.magic)){
345         case S_MAGIC:
346                 if(readn(f, e, 8) != 8)
347                         goto Error;
348         case I_MAGIC:
349                 break;
350         default:
351                 return "bad magic";
352         }
353
354         t = e;
355         n = beswal(ex.text);
356         if(readn(f, t, n) != n)
357                 goto Error;
358         t += n;
359         d = (uchar*)PGROUND((uintptr)t);
360         memset(t, 0, d - t);
361         n = beswal(ex.data);
362         if(readn(f, d, n) != n)
363                 goto Error;
364         d += n;
365         t = (uchar*)PGROUND((uintptr)d);
366         t += PGROUND(beswal(ex.bss));
367         memset(d, 0, t - d);
368
369         close(f);
370         print("boot\n");
371         unload();
372
373         jump(e);
374
375 Error:          
376         return "i/o error";
377 }