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