xref: /plan9-contrib/sys/src/boot/vt4/boot.c (revision da917039c7f233c1a27d212bf012c6afa758af39)
1*da917039SDavid du Colombier #include "include.h"
2*da917039SDavid du Colombier #include "ip.h"
3*da917039SDavid du Colombier #include "/sys/src/libmach/elf.h"
4*da917039SDavid du Colombier 
5*da917039SDavid du Colombier int	tftpupload(char *name, void *p, int len);
6*da917039SDavid du Colombier 
7*da917039SDavid du Colombier extern ulong cpuentry;
8*da917039SDavid du Colombier 
9*da917039SDavid du Colombier static uchar elfident[7] = {
10*da917039SDavid du Colombier 	'\177', 'E', 'L', 'F', '\1', '\1', '\1'
11*da917039SDavid du Colombier };
12*da917039SDavid du Colombier static Ehdr ehdr, rehdr;
13*da917039SDavid du Colombier static Phdr *phdr;
14*da917039SDavid du Colombier static int curphdr;
15*da917039SDavid du Colombier static ulong curoff;
16*da917039SDavid du Colombier static ulong elftotal;
17*da917039SDavid du Colombier 
18*da917039SDavid du Colombier static long (*swal)(long);
19*da917039SDavid du Colombier static ushort (*swab)(ushort);
20*da917039SDavid du Colombier 
21*da917039SDavid du Colombier /*
22*da917039SDavid du Colombier  * big-endian short
23*da917039SDavid du Colombier  */
24*da917039SDavid du Colombier ushort
beswab(ushort s)25*da917039SDavid du Colombier beswab(ushort s)
26*da917039SDavid du Colombier {
27*da917039SDavid du Colombier 	uchar *p;
28*da917039SDavid du Colombier 
29*da917039SDavid du Colombier 	p = (uchar*)&s;
30*da917039SDavid du Colombier 	return (p[0]<<8) | p[1];
31*da917039SDavid du Colombier }
32*da917039SDavid du Colombier 
33*da917039SDavid du Colombier /*
34*da917039SDavid du Colombier  * big-endian long
35*da917039SDavid du Colombier  */
36*da917039SDavid du Colombier long
beswal(long l)37*da917039SDavid du Colombier beswal(long l)
38*da917039SDavid du Colombier {
39*da917039SDavid du Colombier 	uchar *p;
40*da917039SDavid du Colombier 
41*da917039SDavid du Colombier 	p = (uchar*)&l;
42*da917039SDavid du Colombier 	return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
43*da917039SDavid du Colombier }
44*da917039SDavid du Colombier 
45*da917039SDavid du Colombier /*
46*da917039SDavid du Colombier  * little-endian short
47*da917039SDavid du Colombier  */
48*da917039SDavid du Colombier ushort
leswab(ushort s)49*da917039SDavid du Colombier leswab(ushort s)
50*da917039SDavid du Colombier {
51*da917039SDavid du Colombier 	uchar *p;
52*da917039SDavid du Colombier 
53*da917039SDavid du Colombier 	p = (uchar*)&s;
54*da917039SDavid du Colombier 	return (p[1]<<8) | p[0];
55*da917039SDavid du Colombier }
56*da917039SDavid du Colombier 
57*da917039SDavid du Colombier /*
58*da917039SDavid du Colombier  * little-endian long
59*da917039SDavid du Colombier  */
60*da917039SDavid du Colombier long
leswal(long l)61*da917039SDavid du Colombier leswal(long l)
62*da917039SDavid du Colombier {
63*da917039SDavid du Colombier 	uchar *p;
64*da917039SDavid du Colombier 
65*da917039SDavid du Colombier 	p = (uchar*)&l;
66*da917039SDavid du Colombier 	return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
67*da917039SDavid du Colombier }
68*da917039SDavid du Colombier 
69*da917039SDavid du Colombier /*
70*da917039SDavid du Colombier  * Convert header to canonical form
71*da917039SDavid du Colombier  */
72*da917039SDavid du Colombier static void
hswal(long * lp,int n,long (* swap)(long))73*da917039SDavid du Colombier hswal(long *lp, int n, long (*swap) (long))
74*da917039SDavid du Colombier {
75*da917039SDavid du Colombier 	while (n--) {
76*da917039SDavid du Colombier 		*lp = (*swap) (*lp);
77*da917039SDavid du Colombier 		lp++;
78*da917039SDavid du Colombier 	}
79*da917039SDavid du Colombier }
80*da917039SDavid du Colombier 
81*da917039SDavid du Colombier static int
readehdr(Boot * b)82*da917039SDavid du Colombier readehdr(Boot *b)
83*da917039SDavid du Colombier {
84*da917039SDavid du Colombier 	int i;
85*da917039SDavid du Colombier 
86*da917039SDavid du Colombier 	/* bitswap the header according to the DATA format */
87*da917039SDavid du Colombier 	if(ehdr.ident[CLASS] != ELFCLASS32) {
88*da917039SDavid du Colombier 		print("bad ELF class - not 32 bit\n");
89*da917039SDavid du Colombier 		return 0;
90*da917039SDavid du Colombier 	}
91*da917039SDavid du Colombier 	if(ehdr.ident[DATA] == ELFDATA2LSB) {
92*da917039SDavid du Colombier 		swab = leswab;
93*da917039SDavid du Colombier 		swal = leswal;
94*da917039SDavid du Colombier 	} else if(ehdr.ident[DATA] == ELFDATA2MSB) {
95*da917039SDavid du Colombier 		swab = beswab;
96*da917039SDavid du Colombier 		swal = beswal;
97*da917039SDavid du Colombier 	} else {
98*da917039SDavid du Colombier 		print("bad ELF encoding - not big or little endian\n");
99*da917039SDavid du Colombier 		return 0;
100*da917039SDavid du Colombier 	}
101*da917039SDavid du Colombier 	memmove(&rehdr, &ehdr, sizeof(Ehdr));
102*da917039SDavid du Colombier 
103*da917039SDavid du Colombier 	ehdr.type = swab(ehdr.type);
104*da917039SDavid du Colombier 	ehdr.machine = swab(ehdr.machine);
105*da917039SDavid du Colombier 	ehdr.version = swal(ehdr.version);
106*da917039SDavid du Colombier 	ehdr.elfentry = swal(ehdr.elfentry);
107*da917039SDavid du Colombier 	ehdr.phoff = swal(ehdr.phoff);
108*da917039SDavid du Colombier 	ehdr.shoff = swal(ehdr.shoff);
109*da917039SDavid du Colombier 	ehdr.flags = swal(ehdr.flags);
110*da917039SDavid du Colombier 	ehdr.ehsize = swab(ehdr.ehsize);
111*da917039SDavid du Colombier 	ehdr.phentsize = swab(ehdr.phentsize);
112*da917039SDavid du Colombier 	ehdr.phnum = swab(ehdr.phnum);
113*da917039SDavid du Colombier 	ehdr.shentsize = swab(ehdr.shentsize);
114*da917039SDavid du Colombier 	ehdr.shnum = swab(ehdr.shnum);
115*da917039SDavid du Colombier 	ehdr.shstrndx = swab(ehdr.shstrndx);
116*da917039SDavid du Colombier 	if(ehdr.type != EXEC || ehdr.version != CURRENT)
117*da917039SDavid du Colombier 		return 0;
118*da917039SDavid du Colombier 	if(ehdr.phentsize != sizeof(Phdr))
119*da917039SDavid du Colombier 		return 0;
120*da917039SDavid du Colombier 
121*da917039SDavid du Colombier 	if(debug)
122*da917039SDavid du Colombier 		print("readehdr OK entry 0x%lux\n", ehdr.elfentry);
123*da917039SDavid du Colombier 
124*da917039SDavid du Colombier 	curoff = sizeof(Ehdr);
125*da917039SDavid du Colombier 	i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff;
126*da917039SDavid du Colombier 	b->state = READPHDR;
127*da917039SDavid du Colombier 	b->bp = (char*)malloc(i);
128*da917039SDavid du Colombier 	b->wp = b->bp;
129*da917039SDavid du Colombier 	b->ep = b->wp + i;
130*da917039SDavid du Colombier 	phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr));
131*da917039SDavid du Colombier 	if(debug)
132*da917039SDavid du Colombier 		print("phdr...");
133*da917039SDavid du Colombier 
134*da917039SDavid du Colombier 	return 1;
135*da917039SDavid du Colombier }
136*da917039SDavid du Colombier 
137*da917039SDavid du Colombier static int
nextphdr(Boot * b)138*da917039SDavid du Colombier nextphdr(Boot *b)
139*da917039SDavid du Colombier {
140*da917039SDavid du Colombier 	Phdr *php;
141*da917039SDavid du Colombier 	ulong entry, offset;
142*da917039SDavid du Colombier 	char *paddr;
143*da917039SDavid du Colombier 
144*da917039SDavid du Colombier 	if(debug)
145*da917039SDavid du Colombier 		print("readedata %d\n", curphdr);
146*da917039SDavid du Colombier 
147*da917039SDavid du Colombier 	for(; curphdr < ehdr.phnum; curphdr++){
148*da917039SDavid du Colombier 		php = phdr+curphdr;
149*da917039SDavid du Colombier 		if(php->type != LOAD)
150*da917039SDavid du Colombier 			continue;
151*da917039SDavid du Colombier 		offset = php->offset;
152*da917039SDavid du Colombier 		paddr = (char*)PADDR(php->paddr);
153*da917039SDavid du Colombier 		if(offset < curoff){
154*da917039SDavid du Colombier 			/*
155*da917039SDavid du Colombier 			 * Can't (be bothered to) rewind the
156*da917039SDavid du Colombier 			 * input, it might be from tftp. If we
157*da917039SDavid du Colombier 			 * did then we could boot FreeBSD kernels
158*da917039SDavid du Colombier 			 * too maybe.
159*da917039SDavid du Colombier 			 */
160*da917039SDavid du Colombier 			return 0;
161*da917039SDavid du Colombier 		}
162*da917039SDavid du Colombier 		if(php->offset > curoff){
163*da917039SDavid du Colombier 			b->state = READEPAD;
164*da917039SDavid du Colombier 			b->bp = (char*)malloc(offset - curoff);
165*da917039SDavid du Colombier 			b->wp = b->bp;
166*da917039SDavid du Colombier 			b->ep = b->wp + offset - curoff;
167*da917039SDavid du Colombier 			if(debug)
168*da917039SDavid du Colombier 				print("nextphdr %lud...\n", offset - curoff);
169*da917039SDavid du Colombier 			return 1;
170*da917039SDavid du Colombier 		}
171*da917039SDavid du Colombier 		b->state = READEDATA;
172*da917039SDavid du Colombier 		b->bp = paddr;
173*da917039SDavid du Colombier 		b->wp = b->bp;
174*da917039SDavid du Colombier 		b->ep = b->wp+php->filesz;
175*da917039SDavid du Colombier 		print("%ud+", php->filesz);
176*da917039SDavid du Colombier 		elftotal += php->filesz;
177*da917039SDavid du Colombier 		if(debug)
178*da917039SDavid du Colombier 			print("nextphdr %ud@0x%p\n", php->filesz, paddr);
179*da917039SDavid du Colombier 
180*da917039SDavid du Colombier 		return 1;
181*da917039SDavid du Colombier 	}
182*da917039SDavid du Colombier 
183*da917039SDavid du Colombier 	if(curphdr != 0){
184*da917039SDavid du Colombier 		print("=%lud\n", elftotal);
185*da917039SDavid du Colombier 		b->state = TRYBOOT;
186*da917039SDavid du Colombier 		entry = ehdr.elfentry & ~0xF0000000;
187*da917039SDavid du Colombier 		PLLONG(b->exec.entry, entry);
188*da917039SDavid du Colombier 		return 1;
189*da917039SDavid du Colombier 	}
190*da917039SDavid du Colombier 
191*da917039SDavid du Colombier 	return 0;
192*da917039SDavid du Colombier }
193*da917039SDavid du Colombier 
194*da917039SDavid du Colombier static int
readepad(Boot * b)195*da917039SDavid du Colombier readepad(Boot *b)
196*da917039SDavid du Colombier {
197*da917039SDavid du Colombier 	Phdr *php;
198*da917039SDavid du Colombier 
199*da917039SDavid du Colombier 	php = phdr+curphdr;
200*da917039SDavid du Colombier 	if(debug)
201*da917039SDavid du Colombier 		print("readepad %d\n", curphdr);
202*da917039SDavid du Colombier 	curoff = php->offset;
203*da917039SDavid du Colombier 
204*da917039SDavid du Colombier 	return nextphdr(b);
205*da917039SDavid du Colombier }
206*da917039SDavid du Colombier 
207*da917039SDavid du Colombier static int
readedata(Boot * b)208*da917039SDavid du Colombier readedata(Boot *b)
209*da917039SDavid du Colombier {
210*da917039SDavid du Colombier 	Phdr *php;
211*da917039SDavid du Colombier 
212*da917039SDavid du Colombier 	php = phdr+curphdr;
213*da917039SDavid du Colombier 	if(debug)
214*da917039SDavid du Colombier 		print("readedata %d\n", curphdr);
215*da917039SDavid du Colombier 	if(php->filesz < php->memsz){
216*da917039SDavid du Colombier 		print("%lud",  php->memsz-php->filesz);
217*da917039SDavid du Colombier 		elftotal += php->memsz-php->filesz;
218*da917039SDavid du Colombier 		memset((char*)(PADDR(php->paddr)+php->filesz), 0, php->memsz-php->filesz);
219*da917039SDavid du Colombier 	}
220*da917039SDavid du Colombier 	curoff = php->offset+php->filesz;
221*da917039SDavid du Colombier 	curphdr++;
222*da917039SDavid du Colombier 
223*da917039SDavid du Colombier 	return nextphdr(b);
224*da917039SDavid du Colombier }
225*da917039SDavid du Colombier 
226*da917039SDavid du Colombier static int
readphdr(Boot * b)227*da917039SDavid du Colombier readphdr(Boot *b)
228*da917039SDavid du Colombier {
229*da917039SDavid du Colombier 	Phdr *php;
230*da917039SDavid du Colombier 
231*da917039SDavid du Colombier 	php = phdr;
232*da917039SDavid du Colombier 	hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal);
233*da917039SDavid du Colombier 	if(debug)
234*da917039SDavid du Colombier 		print("phdr curoff %lud vaddr 0x%lux paddr 0x%lux\n",
235*da917039SDavid du Colombier 			curoff, php->vaddr, php->paddr);
236*da917039SDavid du Colombier 
237*da917039SDavid du Colombier 	curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum;
238*da917039SDavid du Colombier 	curphdr = 0;
239*da917039SDavid du Colombier 
240*da917039SDavid du Colombier 	return nextphdr(b);
241*da917039SDavid du Colombier }
242*da917039SDavid du Colombier 
243*da917039SDavid du Colombier static ulong chksum, length;
244*da917039SDavid du Colombier 
245*da917039SDavid du Colombier static void
sum(void * vp,int len)246*da917039SDavid du Colombier sum(void *vp, int len)
247*da917039SDavid du Colombier {
248*da917039SDavid du Colombier 	unsigned long *p;
249*da917039SDavid du Colombier 
250*da917039SDavid du Colombier 	if (len % sizeof(int) != 0) {
251*da917039SDavid du Colombier 		print("sum: len %d not a multiple of word size\n",
252*da917039SDavid du Colombier 			len);
253*da917039SDavid du Colombier 		return;
254*da917039SDavid du Colombier 	}
255*da917039SDavid du Colombier 	p = vp;
256*da917039SDavid du Colombier 	len /= sizeof *p;
257*da917039SDavid du Colombier 	while (len-- > 0)
258*da917039SDavid du Colombier 		chksum += *p++;
259*da917039SDavid du Colombier }
260*da917039SDavid du Colombier 
261*da917039SDavid du Colombier static int
addbytes(char ** dbuf,char * edbuf,char ** sbuf,char * esbuf)262*da917039SDavid du Colombier addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
263*da917039SDavid du Colombier {
264*da917039SDavid du Colombier 	int n;
265*da917039SDavid du Colombier 	static ulong *start;
266*da917039SDavid du Colombier 
267*da917039SDavid du Colombier 	n = edbuf - *dbuf;
268*da917039SDavid du Colombier 	if(n <= 0)
269*da917039SDavid du Colombier 		return 0;
270*da917039SDavid du Colombier 	if(n > esbuf - *sbuf)
271*da917039SDavid du Colombier 		n = esbuf - *sbuf;
272*da917039SDavid du Colombier 	if(n <= 0)
273*da917039SDavid du Colombier 		return -1;
274*da917039SDavid du Colombier 
275*da917039SDavid du Colombier 	memmove(*dbuf, *sbuf, n);
276*da917039SDavid du Colombier 	coherence();
277*da917039SDavid du Colombier 
278*da917039SDavid du Colombier 	/* verify that the copy worked */
279*da917039SDavid du Colombier 	if (memcmp(*dbuf, *sbuf, n) != 0)
280*da917039SDavid du Colombier 		panic("addbytes: memmove copied %d bytes wrong from %#p to %#p",
281*da917039SDavid du Colombier 			n, *sbuf, *dbuf);
282*da917039SDavid du Colombier 	*sbuf += n;
283*da917039SDavid du Colombier 	*dbuf += n;
284*da917039SDavid du Colombier 	return edbuf - *dbuf;
285*da917039SDavid du Colombier }
286*da917039SDavid du Colombier 
287*da917039SDavid du Colombier int
bootpass(Boot * b,void * vbuf,int nbuf)288*da917039SDavid du Colombier bootpass(Boot *b, void *vbuf, int nbuf)
289*da917039SDavid du Colombier {
290*da917039SDavid du Colombier 	char *buf, *ebuf;
291*da917039SDavid du Colombier 	Exec *ep;
292*da917039SDavid du Colombier 	ulong entry, data, text, bss;
293*da917039SDavid du Colombier 
294*da917039SDavid du Colombier 	SET(text, data);
295*da917039SDavid du Colombier 	USED(text, data);
296*da917039SDavid du Colombier 	if(b->state == FAILED)
297*da917039SDavid du Colombier 		return FAIL;
298*da917039SDavid du Colombier 
299*da917039SDavid du Colombier 	if(nbuf == 0)
300*da917039SDavid du Colombier 		goto Endofinput;
301*da917039SDavid du Colombier 
302*da917039SDavid du Colombier 	buf = vbuf;
303*da917039SDavid du Colombier 	ebuf = buf+nbuf;
304*da917039SDavid du Colombier 	while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
305*da917039SDavid du Colombier 		switch(b->state) {
306*da917039SDavid du Colombier 		case INITKERNEL:
307*da917039SDavid du Colombier 			b->state = READEXEC;
308*da917039SDavid du Colombier 			b->bp = (char*)&b->exec;
309*da917039SDavid du Colombier 			b->wp = b->bp;
310*da917039SDavid du Colombier 			b->ep = b->bp+sizeof(Exec);
311*da917039SDavid du Colombier 			break;
312*da917039SDavid du Colombier 		case READEXEC:
313*da917039SDavid du Colombier 			ep = &b->exec;
314*da917039SDavid du Colombier 			if(GLLONG(ep->magic) == Q_MAGIC) {
315*da917039SDavid du Colombier 				b->state = READ9TEXT;
316*da917039SDavid du Colombier 				b->bp = (char*)PADDR(GLLONG(ep->entry));
317*da917039SDavid du Colombier 				b->wp = b->bp;
318*da917039SDavid du Colombier 				b->ep = b->wp+GLLONG(ep->text);
319*da917039SDavid du Colombier 				print("%lud", GLLONG(ep->text));
320*da917039SDavid du Colombier 				break;
321*da917039SDavid du Colombier 			}
322*da917039SDavid du Colombier 
323*da917039SDavid du Colombier 			/*
324*da917039SDavid du Colombier 			 * Check for ELF.
325*da917039SDavid du Colombier 			 */
326*da917039SDavid du Colombier 			if(memcmp(b->bp, elfident, 4) == 0){
327*da917039SDavid du Colombier 				b->state = READEHDR;
328*da917039SDavid du Colombier 				b->bp = (char*)&ehdr;
329*da917039SDavid du Colombier 				b->wp = b->bp;
330*da917039SDavid du Colombier 				b->ep = b->wp + sizeof(Ehdr);
331*da917039SDavid du Colombier 				memmove(b->bp, &b->exec, sizeof(Exec));
332*da917039SDavid du Colombier 				b->wp += sizeof(Exec);
333*da917039SDavid du Colombier 				print("elf...");
334*da917039SDavid du Colombier 				break;
335*da917039SDavid du Colombier 			}
336*da917039SDavid du Colombier 
337*da917039SDavid du Colombier 			print("bad kernel format\n");
338*da917039SDavid du Colombier 			b->state = FAILED;
339*da917039SDavid du Colombier 			return FAIL;
340*da917039SDavid du Colombier 
341*da917039SDavid du Colombier 		case READ9TEXT:
342*da917039SDavid du Colombier 			ep = &b->exec;
343*da917039SDavid du Colombier 			b->state = READ9DATA;
344*da917039SDavid du Colombier 			b->bp = (char*)UTROUND(PADDR(GLLONG(ep->entry)) +
345*da917039SDavid du Colombier 				GLLONG(ep->text));
346*da917039SDavid du Colombier 			b->wp = b->bp;
347*da917039SDavid du Colombier 			b->ep = b->wp + GLLONG(ep->data);
348*da917039SDavid du Colombier 			{
349*da917039SDavid du Colombier 				/*
350*da917039SDavid du Colombier 				 * fill the gap between text and first page
351*da917039SDavid du Colombier 				 * of data.
352*da917039SDavid du Colombier 				 */
353*da917039SDavid du Colombier 				int wds;
354*da917039SDavid du Colombier 				ulong *dst = (ulong *)(PADDR(GLLONG(ep->entry))+
355*da917039SDavid du Colombier 					GLLONG(ep->text));
356*da917039SDavid du Colombier 
357*da917039SDavid du Colombier 				for (wds = (ulong *)b->bp - dst; wds-- > 0;
358*da917039SDavid du Colombier 				    dst++)
359*da917039SDavid du Colombier 					*dst = (uintptr)dst;
360*da917039SDavid du Colombier 			}
361*da917039SDavid du Colombier 			print("+%ld", GLLONG(ep->data));
362*da917039SDavid du Colombier 			length = b->ep - (char *)PADDR(GLLONG(ep->entry));
363*da917039SDavid du Colombier 			break;
364*da917039SDavid du Colombier 
365*da917039SDavid du Colombier 		case READ9DATA:
366*da917039SDavid du Colombier 			ep = &b->exec;
367*da917039SDavid du Colombier 			bss = GLLONG(ep->bss);
368*da917039SDavid du Colombier 			print("+%ld=%ld\n",
369*da917039SDavid du Colombier 				bss, GLLONG(ep->text)+GLLONG(ep->data)+bss);
370*da917039SDavid du Colombier 			b->state = TRYBOOT;
371*da917039SDavid du Colombier 			return ENOUGH;
372*da917039SDavid du Colombier 
373*da917039SDavid du Colombier 		case READEHDR:
374*da917039SDavid du Colombier 			if(!readehdr(b)){
375*da917039SDavid du Colombier 				print("readehdr failed\n");
376*da917039SDavid du Colombier 				b->state = FAILED;
377*da917039SDavid du Colombier 				return FAIL;
378*da917039SDavid du Colombier 			}
379*da917039SDavid du Colombier 			break;
380*da917039SDavid du Colombier 
381*da917039SDavid du Colombier 		case READPHDR:
382*da917039SDavid du Colombier 			if(!readphdr(b)){
383*da917039SDavid du Colombier 				b->state = FAILED;
384*da917039SDavid du Colombier 				return FAIL;
385*da917039SDavid du Colombier 			}
386*da917039SDavid du Colombier 			break;
387*da917039SDavid du Colombier 
388*da917039SDavid du Colombier 		case READEPAD:
389*da917039SDavid du Colombier 			if(!readepad(b)){
390*da917039SDavid du Colombier 				b->state = FAILED;
391*da917039SDavid du Colombier 				return FAIL;
392*da917039SDavid du Colombier 			}
393*da917039SDavid du Colombier 			break;
394*da917039SDavid du Colombier 
395*da917039SDavid du Colombier 		case READEDATA:
396*da917039SDavid du Colombier 			if(!readedata(b)){
397*da917039SDavid du Colombier 				b->state = FAILED;
398*da917039SDavid du Colombier 				return FAIL;
399*da917039SDavid du Colombier 			}
400*da917039SDavid du Colombier 			if(b->state == TRYBOOT)
401*da917039SDavid du Colombier 				return ENOUGH;
402*da917039SDavid du Colombier 			break;
403*da917039SDavid du Colombier 
404*da917039SDavid du Colombier 		case TRYBOOT:
405*da917039SDavid du Colombier 		case READGZIP:
406*da917039SDavid du Colombier 			return ENOUGH;
407*da917039SDavid du Colombier 
408*da917039SDavid du Colombier 		case READ9LOAD:
409*da917039SDavid du Colombier 		case INIT9LOAD:
410*da917039SDavid du Colombier 			panic("9load");
411*da917039SDavid du Colombier 
412*da917039SDavid du Colombier 		default:
413*da917039SDavid du Colombier 			panic("bootstate");
414*da917039SDavid du Colombier 		}
415*da917039SDavid du Colombier 	}
416*da917039SDavid du Colombier 	return MORE;
417*da917039SDavid du Colombier 
418*da917039SDavid du Colombier 
419*da917039SDavid du Colombier Endofinput:
420*da917039SDavid du Colombier 	/* end of input */
421*da917039SDavid du Colombier 	switch(b->state) {
422*da917039SDavid du Colombier 	case INITKERNEL:
423*da917039SDavid du Colombier 	case READEXEC:
424*da917039SDavid du Colombier 	case READ9TEXT:
425*da917039SDavid du Colombier 	case READ9DATA:
426*da917039SDavid du Colombier 	case READEHDR:
427*da917039SDavid du Colombier 	case READPHDR:
428*da917039SDavid du Colombier 	case READEPAD:
429*da917039SDavid du Colombier 	case READEDATA:
430*da917039SDavid du Colombier 		print("premature EOF\n");
431*da917039SDavid du Colombier 		b->state = FAILED;
432*da917039SDavid du Colombier 		return FAIL;
433*da917039SDavid du Colombier 
434*da917039SDavid du Colombier 	case TRYBOOT:
435*da917039SDavid du Colombier 		delay(100);
436*da917039SDavid du Colombier 		syncall();
437*da917039SDavid du Colombier 		entry = GLLONG(b->exec.entry);
438*da917039SDavid du Colombier 		dcflush(PADDR(entry), 4*1024*1024);		/* HACK */
439*da917039SDavid du Colombier 
440*da917039SDavid du Colombier 		sum((void *)PADDR(entry), length);
441*da917039SDavid du Colombier 		print("checksum: %#luX (on length %lud)\n", chksum, length);
442*da917039SDavid du Colombier 
443*da917039SDavid du Colombier 		print("entry: 0x%lux\n", entry);
444*da917039SDavid du Colombier 		delay(20);
445*da917039SDavid du Colombier 
446*da917039SDavid du Colombier 		cpuentry = entry;		/* for second cpu's use */
447*da917039SDavid du Colombier 		coherence();
448*da917039SDavid du Colombier 		dcflush((uintptr)&cpuentry, sizeof cpuentry);
449*da917039SDavid du Colombier 
450*da917039SDavid du Colombier 		warp9(PADDR(entry));
451*da917039SDavid du Colombier 
452*da917039SDavid du Colombier 		b->state = FAILED;
453*da917039SDavid du Colombier 		return FAIL;
454*da917039SDavid du Colombier 
455*da917039SDavid du Colombier 	case INIT9LOAD:
456*da917039SDavid du Colombier 	case READ9LOAD:
457*da917039SDavid du Colombier 		panic("end 9load");
458*da917039SDavid du Colombier 
459*da917039SDavid du Colombier 	default:
460*da917039SDavid du Colombier 		panic("bootdone");
461*da917039SDavid du Colombier 	}
462*da917039SDavid du Colombier 	b->state = FAILED;
463*da917039SDavid du Colombier 	return FAIL;
464*da917039SDavid du Colombier }
465