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