xref: /plan9-contrib/sys/src/nboot/efi/sub.c (revision 529c1f209803c78c4f2cda11b13818a57f01c872)
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
print(char * s)9 print(char *s)
10 {
11 	while(*s != 0){
12 		if(*s == '\n')
13 			putc('\r');
14 		putc(*s++);
15 	}
16 }
17 
18 int
readn(void * f,void * data,int len)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
memmove(void * dst,void * src,int n)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
memcmp(void * src,void * dst,int n)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
strlen(char * s)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*
strchr(char * s,int c)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
memset(void * dst,int v,int n)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
readline(void * f,char * buf)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
timeout(int ms)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*
getconf(char * s,char * buf)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
delconf(char * s)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*
configure(void * f,char * path)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*
numfmt(char * s,ulong b,ulong i,ulong a)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*
hexfmt(char * s,int i,uvlong a)307 hexfmt(char *s, int i, uvlong a)
308 {
309 	if(i > 8 || i == 0 && (a>>32) != 0){
310 		s = numfmt(s, 16, i ? i-8 : 0, a>>32);
311 		i = 8;
312 	}
313 	return numfmt(s, 16, i, a);
314 }
315 
316 char*
decfmt(char * s,int i,ulong a)317 decfmt(char *s, int i, ulong a)
318 {
319 	return numfmt(s, 10, i, a);
320 }
321 
322 static ulong
beswal(ulong l)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*
bootkern(void * f)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 }
374