xref: /plan9-contrib/sys/src/9/pcboot/bootld.c (revision 62579e3431b49107da5aa4bf80b65c6650de497d)
125210b06SDavid du Colombier /*
225210b06SDavid du Colombier  * load kernel into memory
325210b06SDavid du Colombier  */
425210b06SDavid du Colombier #include	"u.h"
525210b06SDavid du Colombier #include	"../port/lib.h"
625210b06SDavid du Colombier #include	"mem.h"
725210b06SDavid du Colombier #include	"dat.h"
825210b06SDavid du Colombier #include	"fns.h"
925210b06SDavid du Colombier #include	"io.h"
1025210b06SDavid du Colombier #include	"ureg.h"
1125210b06SDavid du Colombier #include	"pool.h"
1225210b06SDavid du Colombier #include	"../port/netif.h"
1325210b06SDavid du Colombier #include	"../ip/ip.h"
1425210b06SDavid du Colombier #include	"pxe.h"
1525210b06SDavid du Colombier 
1625210b06SDavid du Colombier #include	<a.out.h>
1725210b06SDavid du Colombier #include 	"/sys/src/libmach/elf.h"
1825210b06SDavid du Colombier 
1925210b06SDavid du Colombier #undef KADDR
2025210b06SDavid du Colombier #undef PADDR
2125210b06SDavid du Colombier 
2225210b06SDavid du Colombier #define KADDR(a)	((void*)((ulong)(a) | KZERO))
2325210b06SDavid du Colombier #define PADDR(a)	((ulong)(a) & ~KSEGM)
2425210b06SDavid du Colombier 
2525210b06SDavid du Colombier extern int debug;
26*62579e34SDavid du Colombier 
2725210b06SDavid du Colombier extern void pagingoff(ulong);
2825210b06SDavid du Colombier 
29*62579e34SDavid du Colombier static uchar elfident[] = {
30*62579e34SDavid du Colombier 	'\177', 'E', 'L', 'F',
3125210b06SDavid du Colombier };
3225210b06SDavid du Colombier static Ehdr ehdr, rehdr;
33*62579e34SDavid du Colombier static E64hdr e64hdr;
3425210b06SDavid du Colombier static Phdr *phdr;
35*62579e34SDavid du Colombier static P64hdr *p64hdr;
36*62579e34SDavid du Colombier 
3725210b06SDavid du Colombier static int curphdr;
3825210b06SDavid du Colombier static ulong curoff;
3925210b06SDavid du Colombier static ulong elftotal;
40*62579e34SDavid du Colombier 
41*62579e34SDavid du Colombier static uvlong (*swav)(uvlong);
4225210b06SDavid du Colombier static long (*swal)(long);
4325210b06SDavid du Colombier static ushort (*swab)(ushort);
4425210b06SDavid du Colombier 
4525210b06SDavid du Colombier /*
4625210b06SDavid du Colombier  * big-endian short
4725210b06SDavid du Colombier  */
4825210b06SDavid du Colombier ushort
beswab(ushort s)4925210b06SDavid du Colombier beswab(ushort s)
5025210b06SDavid du Colombier {
5125210b06SDavid du Colombier 	uchar *p;
5225210b06SDavid du Colombier 
5325210b06SDavid du Colombier 	p = (uchar*)&s;
5425210b06SDavid du Colombier 	return (p[0]<<8) | p[1];
5525210b06SDavid du Colombier }
5625210b06SDavid du Colombier 
5725210b06SDavid du Colombier /*
5825210b06SDavid du Colombier  * big-endian long
5925210b06SDavid du Colombier  */
6025210b06SDavid du Colombier long
beswal(long l)6125210b06SDavid du Colombier beswal(long l)
6225210b06SDavid du Colombier {
6325210b06SDavid du Colombier 	uchar *p;
6425210b06SDavid du Colombier 
6525210b06SDavid du Colombier 	p = (uchar*)&l;
6625210b06SDavid du Colombier 	return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
6725210b06SDavid du Colombier }
6825210b06SDavid du Colombier 
6925210b06SDavid du Colombier /*
7025210b06SDavid du Colombier  * big-endian vlong
7125210b06SDavid du Colombier  */
7225210b06SDavid du Colombier uvlong
beswav(uvlong v)7325210b06SDavid du Colombier beswav(uvlong v)
7425210b06SDavid du Colombier {
7525210b06SDavid du Colombier 	uchar *p;
7625210b06SDavid du Colombier 
7725210b06SDavid du Colombier 	p = (uchar*)&v;
7825210b06SDavid du Colombier 	return ((uvlong)p[0]<<56) | ((uvlong)p[1]<<48) | ((uvlong)p[2]<<40)
7925210b06SDavid du Colombier 				  | ((uvlong)p[3]<<32) | ((uvlong)p[4]<<24)
8025210b06SDavid du Colombier 				  | ((uvlong)p[5]<<16) | ((uvlong)p[6]<<8)
8125210b06SDavid du Colombier 				  | (uvlong)p[7];
8225210b06SDavid du Colombier }
8325210b06SDavid du Colombier 
8425210b06SDavid du Colombier /*
8525210b06SDavid du Colombier  * little-endian short
8625210b06SDavid du Colombier  */
8725210b06SDavid du Colombier ushort
leswab(ushort s)8825210b06SDavid du Colombier leswab(ushort s)
8925210b06SDavid du Colombier {
9025210b06SDavid du Colombier 	uchar *p;
9125210b06SDavid du Colombier 
9225210b06SDavid du Colombier 	p = (uchar*)&s;
9325210b06SDavid du Colombier 	return (p[1]<<8) | p[0];
9425210b06SDavid du Colombier }
9525210b06SDavid du Colombier 
9625210b06SDavid du Colombier /*
9725210b06SDavid du Colombier  * little-endian long
9825210b06SDavid du Colombier  */
9925210b06SDavid du Colombier long
leswal(long l)10025210b06SDavid du Colombier leswal(long l)
10125210b06SDavid du Colombier {
10225210b06SDavid du Colombier 	uchar *p;
10325210b06SDavid du Colombier 
10425210b06SDavid du Colombier 	p = (uchar*)&l;
10525210b06SDavid du Colombier 	return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
10625210b06SDavid du Colombier }
10725210b06SDavid du Colombier 
10825210b06SDavid du Colombier /*
109*62579e34SDavid du Colombier  * little-endian vlong
110*62579e34SDavid du Colombier  */
111*62579e34SDavid du Colombier uvlong
leswav(uvlong v)112*62579e34SDavid du Colombier leswav(uvlong v)
113*62579e34SDavid du Colombier {
114*62579e34SDavid du Colombier 	uchar *p;
115*62579e34SDavid du Colombier 
116*62579e34SDavid du Colombier 	p = (uchar*)&v;
117*62579e34SDavid du Colombier 	return ((uvlong)p[7]<<56) | ((uvlong)p[6]<<48) | ((uvlong)p[5]<<40)
118*62579e34SDavid du Colombier 				  | ((uvlong)p[4]<<32) | ((uvlong)p[3]<<24)
119*62579e34SDavid du Colombier 				  | ((uvlong)p[2]<<16) | ((uvlong)p[1]<<8)
120*62579e34SDavid du Colombier 				  | (uvlong)p[0];
121*62579e34SDavid du Colombier }
122*62579e34SDavid du Colombier 
123*62579e34SDavid du Colombier /*
12425210b06SDavid du Colombier  * Convert header to canonical form
12525210b06SDavid du Colombier  */
12625210b06SDavid du Colombier static void
hswal(long * lp,int n,long (* swap)(long))12725210b06SDavid du Colombier hswal(long *lp, int n, long (*swap) (long))
12825210b06SDavid du Colombier {
12925210b06SDavid du Colombier 	while (n--) {
13025210b06SDavid du Colombier 		*lp = (*swap) (*lp);
13125210b06SDavid du Colombier 		lp++;
13225210b06SDavid du Colombier 	}
13325210b06SDavid du Colombier }
13425210b06SDavid du Colombier 
135*62579e34SDavid du Colombier static void
hswav(uvlong * lp,int n,uvlong (* swap)(uvlong))136*62579e34SDavid du Colombier hswav(uvlong *lp, int n, uvlong (*swap)(uvlong))
137*62579e34SDavid du Colombier {
138*62579e34SDavid du Colombier 	while (n--) {
139*62579e34SDavid du Colombier 		*lp = (*swap)(*lp);
140*62579e34SDavid du Colombier 		lp++;
141*62579e34SDavid du Colombier 	}
142*62579e34SDavid du Colombier }
143*62579e34SDavid du Colombier 
14425210b06SDavid du Colombier static int
readehdr(Boot * b)14525210b06SDavid du Colombier readehdr(Boot *b)
14625210b06SDavid du Colombier {
14725210b06SDavid du Colombier 	int i;
14825210b06SDavid du Colombier 
14925210b06SDavid du Colombier 	/* bitswap the header according to the DATA format */
15025210b06SDavid du Colombier 	if(ehdr.ident[CLASS] != ELFCLASS32) {
15125210b06SDavid du Colombier 		print("bad ELF class - not 32 bit\n");
15225210b06SDavid du Colombier 		return 0;
15325210b06SDavid du Colombier 	}
15425210b06SDavid du Colombier 	if(ehdr.ident[DATA] == ELFDATA2LSB) {
15525210b06SDavid du Colombier 		swab = leswab;
15625210b06SDavid du Colombier 		swal = leswal;
15725210b06SDavid du Colombier 	} else if(ehdr.ident[DATA] == ELFDATA2MSB) {
15825210b06SDavid du Colombier 		swab = beswab;
15925210b06SDavid du Colombier 		swal = beswal;
16025210b06SDavid du Colombier 	} else {
16125210b06SDavid du Colombier 		print("bad ELF encoding - not big or little endian\n");
16225210b06SDavid du Colombier 		return 0;
16325210b06SDavid du Colombier 	}
164*62579e34SDavid du Colombier 	memmove(&rehdr, &ehdr, sizeof(Ehdr));	/* copy; never used */
16525210b06SDavid du Colombier 
16625210b06SDavid du Colombier 	ehdr.type = swab(ehdr.type);
16725210b06SDavid du Colombier 	ehdr.machine = swab(ehdr.machine);
16825210b06SDavid du Colombier 	ehdr.version = swal(ehdr.version);
16925210b06SDavid du Colombier 	ehdr.elfentry = swal(ehdr.elfentry);
17025210b06SDavid du Colombier 	ehdr.phoff = swal(ehdr.phoff);
17125210b06SDavid du Colombier 	ehdr.shoff = swal(ehdr.shoff);
17225210b06SDavid du Colombier 	ehdr.flags = swal(ehdr.flags);
17325210b06SDavid du Colombier 	ehdr.ehsize = swab(ehdr.ehsize);
17425210b06SDavid du Colombier 	ehdr.phentsize = swab(ehdr.phentsize);
17525210b06SDavid du Colombier 	ehdr.phnum = swab(ehdr.phnum);
17625210b06SDavid du Colombier 	ehdr.shentsize = swab(ehdr.shentsize);
17725210b06SDavid du Colombier 	ehdr.shnum = swab(ehdr.shnum);
17825210b06SDavid du Colombier 	ehdr.shstrndx = swab(ehdr.shstrndx);
17925210b06SDavid du Colombier 	if(ehdr.type != EXEC || ehdr.version != CURRENT)
18025210b06SDavid du Colombier 		return 0;
18125210b06SDavid du Colombier 	if(ehdr.phentsize != sizeof(Phdr))
18225210b06SDavid du Colombier 		return 0;
18325210b06SDavid du Colombier 
18425210b06SDavid du Colombier 	if(debug)
18525210b06SDavid du Colombier 		print("readehdr OK entry %#lux\n", ehdr.elfentry);
18625210b06SDavid du Colombier 
18725210b06SDavid du Colombier 	curoff = sizeof(Ehdr);
18825210b06SDavid du Colombier 	i = ehdr.phoff+ehdr.phentsize*ehdr.phnum - curoff;
18925210b06SDavid du Colombier 	b->state = READPHDR;
19025210b06SDavid du Colombier 	b->bp = (char*)smalloc(i);
19125210b06SDavid du Colombier 	b->wp = b->bp;
19225210b06SDavid du Colombier 	b->ep = b->wp + i;
193*62579e34SDavid du Colombier 	elftotal = 0;
19425210b06SDavid du Colombier 	phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr));
19525210b06SDavid du Colombier 	if(debug)
19625210b06SDavid du Colombier 		print("phdr...");
19725210b06SDavid du Colombier 
19825210b06SDavid du Colombier 	return 1;
19925210b06SDavid du Colombier }
20025210b06SDavid du Colombier 
20125210b06SDavid du Colombier static int
reade64hdr(Boot * b)202*62579e34SDavid du Colombier reade64hdr(Boot *b)
203*62579e34SDavid du Colombier {
204*62579e34SDavid du Colombier 	int i;
205*62579e34SDavid du Colombier 
206*62579e34SDavid du Colombier 	/* bitswap the header according to the DATA format */
207*62579e34SDavid du Colombier 	if(e64hdr.ident[CLASS] != ELFCLASS64) {
208*62579e34SDavid du Colombier 		print("bad ELF class - not 64 bit\n");
209*62579e34SDavid du Colombier 		return 0;
210*62579e34SDavid du Colombier 	}
211*62579e34SDavid du Colombier 	if(e64hdr.ident[DATA] == ELFDATA2LSB) {
212*62579e34SDavid du Colombier 		swab = leswab;
213*62579e34SDavid du Colombier 		swal = leswal;
214*62579e34SDavid du Colombier 		swav = leswav;
215*62579e34SDavid du Colombier 	} else if(e64hdr.ident[DATA] == ELFDATA2MSB) {
216*62579e34SDavid du Colombier 		swab = beswab;
217*62579e34SDavid du Colombier 		swal = beswal;
218*62579e34SDavid du Colombier 		swav = beswav;
219*62579e34SDavid du Colombier 	} else {
220*62579e34SDavid du Colombier 		print("bad ELF encoding - not big or little endian\n");
221*62579e34SDavid du Colombier 		return 0;
222*62579e34SDavid du Colombier 	}
223*62579e34SDavid du Colombier //	memmove(&rehdr, &ehdr, sizeof(Ehdr));	/* copy; never used */
224*62579e34SDavid du Colombier 
225*62579e34SDavid du Colombier 	e64hdr.type = swab(e64hdr.type);
226*62579e34SDavid du Colombier 	e64hdr.machine = swab(e64hdr.machine);
227*62579e34SDavid du Colombier 	e64hdr.version = swal(e64hdr.version);
228*62579e34SDavid du Colombier 	e64hdr.elfentry = swav(e64hdr.elfentry);
229*62579e34SDavid du Colombier 	e64hdr.phoff = swav(e64hdr.phoff);
230*62579e34SDavid du Colombier 	e64hdr.shoff = swav(e64hdr.shoff);
231*62579e34SDavid du Colombier 	e64hdr.flags = swal(e64hdr.flags);
232*62579e34SDavid du Colombier 	e64hdr.ehsize = swab(e64hdr.ehsize);
233*62579e34SDavid du Colombier 	e64hdr.phentsize = swab(e64hdr.phentsize);
234*62579e34SDavid du Colombier 	e64hdr.phnum = swab(e64hdr.phnum);
235*62579e34SDavid du Colombier 	e64hdr.shentsize = swab(e64hdr.shentsize);
236*62579e34SDavid du Colombier 	e64hdr.shnum = swab(e64hdr.shnum);
237*62579e34SDavid du Colombier 	e64hdr.shstrndx = swab(e64hdr.shstrndx);
238*62579e34SDavid du Colombier 	if(e64hdr.type != EXEC || e64hdr.version != CURRENT)
239*62579e34SDavid du Colombier 		return 0;
240*62579e34SDavid du Colombier 	if(e64hdr.phentsize != sizeof(P64hdr))
241*62579e34SDavid du Colombier 		return 0;
242*62579e34SDavid du Colombier 
243*62579e34SDavid du Colombier 	if(debug)
244*62579e34SDavid du Colombier 		print("reade64hdr OK entry %#llux\n", e64hdr.elfentry);
245*62579e34SDavid du Colombier 
246*62579e34SDavid du Colombier 	curoff = sizeof(E64hdr);
247*62579e34SDavid du Colombier 	i = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum - curoff;
248*62579e34SDavid du Colombier 	b->state = READ64PHDR;
249*62579e34SDavid du Colombier 	b->bp = (char*)smalloc(i);
250*62579e34SDavid du Colombier 	b->wp = b->bp;
251*62579e34SDavid du Colombier 	b->ep = b->wp + i;
252*62579e34SDavid du Colombier 	elftotal = 0;
253*62579e34SDavid du Colombier 	p64hdr = (P64hdr*)(b->bp + e64hdr.phoff-sizeof(E64hdr));
254*62579e34SDavid du Colombier 	if(debug)
255*62579e34SDavid du Colombier 		print("p64hdr...");
256*62579e34SDavid du Colombier 
257*62579e34SDavid du Colombier 	return 1;
258*62579e34SDavid du Colombier }
259*62579e34SDavid du Colombier 
260*62579e34SDavid du Colombier static int
nextphdr(Boot * b)26125210b06SDavid du Colombier nextphdr(Boot *b)
26225210b06SDavid du Colombier {
26325210b06SDavid du Colombier 	Phdr *php;
264*62579e34SDavid du Colombier 	ulong offset;
26525210b06SDavid du Colombier 	char *physaddr;
26625210b06SDavid du Colombier 
26725210b06SDavid du Colombier 	if(debug)
26825210b06SDavid du Colombier 		print("readedata %d\n", curphdr);
26925210b06SDavid du Colombier 
27025210b06SDavid du Colombier 	for(; curphdr < ehdr.phnum; curphdr++){
27125210b06SDavid du Colombier 		php = phdr+curphdr;
27225210b06SDavid du Colombier 		if(php->type != LOAD)
27325210b06SDavid du Colombier 			continue;
27425210b06SDavid du Colombier 		offset = php->offset;
27525210b06SDavid du Colombier 		physaddr = (char*)KADDR(PADDR(php->paddr));
27625210b06SDavid du Colombier 		if(offset < curoff){
27725210b06SDavid du Colombier 			/*
27825210b06SDavid du Colombier 			 * Can't (be bothered to) rewind the
27925210b06SDavid du Colombier 			 * input, it might be from tftp. If we
28025210b06SDavid du Colombier 			 * did then we could boot FreeBSD kernels
28125210b06SDavid du Colombier 			 * too maybe.
28225210b06SDavid du Colombier 			 */
28325210b06SDavid du Colombier 			return 0;
28425210b06SDavid du Colombier 		}
28525210b06SDavid du Colombier 		if(php->offset > curoff){
28625210b06SDavid du Colombier 			b->state = READEPAD;
28725210b06SDavid du Colombier 			b->bp = (char*)smalloc(offset - curoff);
28825210b06SDavid du Colombier 			b->wp = b->bp;
28925210b06SDavid du Colombier 			b->ep = b->wp + offset - curoff;
29025210b06SDavid du Colombier 			if(debug)
29125210b06SDavid du Colombier 				print("nextphdr %lud...\n", offset - curoff);
29225210b06SDavid du Colombier 			return 1;
29325210b06SDavid du Colombier 		}
29425210b06SDavid du Colombier 		b->state = READEDATA;
29525210b06SDavid du Colombier 		b->bp = physaddr;
29625210b06SDavid du Colombier 		b->wp = b->bp;
29725210b06SDavid du Colombier 		b->ep = b->wp+php->filesz;
29825210b06SDavid du Colombier 		print("%ud+", php->filesz);
29925210b06SDavid du Colombier 		elftotal += php->filesz;
30025210b06SDavid du Colombier 		if(debug)
30125210b06SDavid du Colombier 			print("nextphdr %ud@%#p\n", php->filesz, physaddr);
30225210b06SDavid du Colombier 
30325210b06SDavid du Colombier 		return 1;
30425210b06SDavid du Colombier 	}
30525210b06SDavid du Colombier 
30625210b06SDavid du Colombier 	if(curphdr != 0){
30725210b06SDavid du Colombier 		print("=%lud\n", elftotal);
30825210b06SDavid du Colombier 		b->state = TRYEBOOT;
309*62579e34SDavid du Colombier 		b->entry = ehdr.elfentry;
310*62579e34SDavid du Colombier 		// PLLONG(b->hdr.entry, b->entry);
311*62579e34SDavid du Colombier 		return 1;
312*62579e34SDavid du Colombier 	}
313*62579e34SDavid du Colombier 
314*62579e34SDavid du Colombier 	return 0;
315*62579e34SDavid du Colombier }
316*62579e34SDavid du Colombier 
317*62579e34SDavid du Colombier static int
nextp64hdr(Boot * b)318*62579e34SDavid du Colombier nextp64hdr(Boot *b)
319*62579e34SDavid du Colombier {
320*62579e34SDavid du Colombier 	P64hdr *php;
321*62579e34SDavid du Colombier 	uvlong offset;
322*62579e34SDavid du Colombier 	char *physaddr;
323*62579e34SDavid du Colombier 
324*62579e34SDavid du Colombier 	if(debug)
325*62579e34SDavid du Colombier 		print("reade64data %d\n", curphdr);
326*62579e34SDavid du Colombier 
327*62579e34SDavid du Colombier 	for(; curphdr < e64hdr.phnum; curphdr++){
328*62579e34SDavid du Colombier 		php = p64hdr+curphdr;
329*62579e34SDavid du Colombier 		if(php->type != LOAD)
330*62579e34SDavid du Colombier 			continue;
331*62579e34SDavid du Colombier 		offset = php->offset;
332*62579e34SDavid du Colombier 		physaddr = (char*)KADDR(PADDR(php->paddr));
333*62579e34SDavid du Colombier 		if(offset < curoff){
334*62579e34SDavid du Colombier 			/*
335*62579e34SDavid du Colombier 			 * Can't (be bothered to) rewind the
336*62579e34SDavid du Colombier 			 * input, it might be from tftp. If we
337*62579e34SDavid du Colombier 			 * did then we could boot FreeBSD kernels
338*62579e34SDavid du Colombier 			 * too maybe.
339*62579e34SDavid du Colombier 			 */
340*62579e34SDavid du Colombier 			return 0;
341*62579e34SDavid du Colombier 		}
342*62579e34SDavid du Colombier 		if(php->offset > curoff){
343*62579e34SDavid du Colombier 			b->state = READE64PAD;
344*62579e34SDavid du Colombier 			b->bp = (char*)smalloc(offset - curoff);
345*62579e34SDavid du Colombier 			b->wp = b->bp;
346*62579e34SDavid du Colombier 			b->ep = b->wp + offset - curoff;
347*62579e34SDavid du Colombier 			if(debug)
348*62579e34SDavid du Colombier 				print("nextp64hdr %llud...\n", offset - curoff);
349*62579e34SDavid du Colombier 			return 1;
350*62579e34SDavid du Colombier 		}
351*62579e34SDavid du Colombier 		b->state = READE64DATA;
352*62579e34SDavid du Colombier 		b->bp = physaddr;
353*62579e34SDavid du Colombier 		b->wp = b->bp;
354*62579e34SDavid du Colombier 		b->ep = b->wp+php->filesz;
355*62579e34SDavid du Colombier 		print("%llud+", php->filesz);
356*62579e34SDavid du Colombier 		elftotal += php->filesz;
357*62579e34SDavid du Colombier 		if(debug)
358*62579e34SDavid du Colombier 			print("nextp64hdr %llud@%#p\n", php->filesz, physaddr);
359*62579e34SDavid du Colombier 
360*62579e34SDavid du Colombier 		return 1;
361*62579e34SDavid du Colombier 	}
362*62579e34SDavid du Colombier 
363*62579e34SDavid du Colombier 	if(curphdr != 0){
364*62579e34SDavid du Colombier 		print("=%lud\n", elftotal);
365*62579e34SDavid du Colombier 		b->state = TRYE64BOOT;
366*62579e34SDavid du Colombier 		b->entry = e64hdr.elfentry;
36725210b06SDavid du Colombier 		return 1;
36825210b06SDavid du Colombier 	}
36925210b06SDavid du Colombier 
37025210b06SDavid du Colombier 	return 0;
37125210b06SDavid du Colombier }
37225210b06SDavid du Colombier 
37325210b06SDavid du Colombier static int
readepad(Boot * b)37425210b06SDavid du Colombier readepad(Boot *b)
37525210b06SDavid du Colombier {
37625210b06SDavid du Colombier 	Phdr *php;
37725210b06SDavid du Colombier 
37825210b06SDavid du Colombier 	php = phdr+curphdr;
37925210b06SDavid du Colombier 	if(debug)
38025210b06SDavid du Colombier 		print("readepad %d\n", curphdr);
38125210b06SDavid du Colombier 	curoff = php->offset;
38225210b06SDavid du Colombier 
38325210b06SDavid du Colombier 	return nextphdr(b);
38425210b06SDavid du Colombier }
38525210b06SDavid du Colombier 
38625210b06SDavid du Colombier static int
reade64pad(Boot * b)387*62579e34SDavid du Colombier reade64pad(Boot *b)
388*62579e34SDavid du Colombier {
389*62579e34SDavid du Colombier 	P64hdr *php;
390*62579e34SDavid du Colombier 
391*62579e34SDavid du Colombier 	php = p64hdr+curphdr;
392*62579e34SDavid du Colombier 	if(debug)
393*62579e34SDavid du Colombier 		print("reade64pad %d\n", curphdr);
394*62579e34SDavid du Colombier 	curoff = php->offset;
395*62579e34SDavid du Colombier 
396*62579e34SDavid du Colombier 	return nextp64hdr(b);
397*62579e34SDavid du Colombier }
398*62579e34SDavid du Colombier 
399*62579e34SDavid du Colombier static int
readedata(Boot * b)40025210b06SDavid du Colombier readedata(Boot *b)
40125210b06SDavid du Colombier {
40225210b06SDavid du Colombier 	Phdr *php;
40325210b06SDavid du Colombier 
40425210b06SDavid du Colombier 	php = phdr+curphdr;
40525210b06SDavid du Colombier 	if(debug)
40625210b06SDavid du Colombier 		print("readedata %d\n", curphdr);
40725210b06SDavid du Colombier 	if(php->filesz < php->memsz){
40825210b06SDavid du Colombier 		print("%lud",  php->memsz-php->filesz);
40925210b06SDavid du Colombier 		elftotal += php->memsz-php->filesz;
41025210b06SDavid du Colombier 		memset((char*)KADDR(PADDR(php->paddr)+php->filesz), 0,
41125210b06SDavid du Colombier 			php->memsz-php->filesz);
41225210b06SDavid du Colombier 	}
41325210b06SDavid du Colombier 	curoff = php->offset+php->filesz;
41425210b06SDavid du Colombier 	curphdr++;
41525210b06SDavid du Colombier 
41625210b06SDavid du Colombier 	return nextphdr(b);
41725210b06SDavid du Colombier }
41825210b06SDavid du Colombier 
41925210b06SDavid du Colombier static int
reade64data(Boot * b)420*62579e34SDavid du Colombier reade64data(Boot *b)
421*62579e34SDavid du Colombier {
422*62579e34SDavid du Colombier 	P64hdr *php;
423*62579e34SDavid du Colombier 
424*62579e34SDavid du Colombier 	php = p64hdr+curphdr;
425*62579e34SDavid du Colombier 	if(debug)
426*62579e34SDavid du Colombier 		print("reade64data %d\n", curphdr);
427*62579e34SDavid du Colombier 	if(php->filesz < php->memsz){
428*62579e34SDavid du Colombier 		print("%llud",  php->memsz - php->filesz);
429*62579e34SDavid du Colombier 		elftotal += php->memsz - php->filesz;
430*62579e34SDavid du Colombier 		memset((char*)KADDR(PADDR(php->paddr) + php->filesz), 0,
431*62579e34SDavid du Colombier 			php->memsz - php->filesz);
432*62579e34SDavid du Colombier 	}
433*62579e34SDavid du Colombier 	curoff = php->offset + php->filesz;
434*62579e34SDavid du Colombier 	curphdr++;
435*62579e34SDavid du Colombier 
436*62579e34SDavid du Colombier 	return nextp64hdr(b);
437*62579e34SDavid du Colombier }
438*62579e34SDavid du Colombier 
439*62579e34SDavid du Colombier static int
readphdr(Boot * b)44025210b06SDavid du Colombier readphdr(Boot *b)
44125210b06SDavid du Colombier {
44225210b06SDavid du Colombier 	Phdr *php;
44325210b06SDavid du Colombier 
44425210b06SDavid du Colombier 	php = phdr;
44525210b06SDavid du Colombier 	hswal((long*)php, ehdr.phentsize*ehdr.phnum/sizeof(long), swal);
44625210b06SDavid du Colombier 	if(debug)
44725210b06SDavid du Colombier 		print("phdr curoff %lud vaddr %#lux paddr %#lux\n",
44825210b06SDavid du Colombier 			curoff, php->vaddr, php->paddr);
44925210b06SDavid du Colombier 
45025210b06SDavid du Colombier 	curoff = ehdr.phoff+ehdr.phentsize*ehdr.phnum;
45125210b06SDavid du Colombier 	curphdr = 0;
45225210b06SDavid du Colombier 
45325210b06SDavid du Colombier 	return nextphdr(b);
45425210b06SDavid du Colombier }
45525210b06SDavid du Colombier 
45625210b06SDavid du Colombier static int
readp64hdr(Boot * b)457*62579e34SDavid du Colombier readp64hdr(Boot *b)
458*62579e34SDavid du Colombier {
459*62579e34SDavid du Colombier 	int hdr;
460*62579e34SDavid du Colombier 	P64hdr *php, *p;
461*62579e34SDavid du Colombier 
462*62579e34SDavid du Colombier 	php = p = p64hdr;
463*62579e34SDavid du Colombier 	for (hdr = 0; hdr < e64hdr.phnum; hdr++, p++) {
464*62579e34SDavid du Colombier 		hswal((long*)p, 2, swal);
465*62579e34SDavid du Colombier 		hswav((uvlong*)&p->offset, 6, swav);
466*62579e34SDavid du Colombier 	}
467*62579e34SDavid du Colombier 	if(debug)
468*62579e34SDavid du Colombier 		print("p64hdr curoff %lud vaddr %#llux paddr %#llux\n",
469*62579e34SDavid du Colombier 			curoff, php->vaddr, php->paddr);
470*62579e34SDavid du Colombier 
471*62579e34SDavid du Colombier 	curoff = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum;
472*62579e34SDavid du Colombier 	curphdr = 0;
473*62579e34SDavid du Colombier 
474*62579e34SDavid du Colombier 	return nextp64hdr(b);
475*62579e34SDavid du Colombier }
476*62579e34SDavid du Colombier 
477*62579e34SDavid du Colombier static int
addbytes(char ** dbuf,char * edbuf,char ** sbuf,char * esbuf)47825210b06SDavid du Colombier addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
47925210b06SDavid du Colombier {
48025210b06SDavid du Colombier 	int n;
48125210b06SDavid du Colombier 
48225210b06SDavid du Colombier 	n = edbuf - *dbuf;
48325210b06SDavid du Colombier 	if(n <= 0)
484*62579e34SDavid du Colombier 		return 0;			/* dest buffer is full */
48525210b06SDavid du Colombier 	if(n > esbuf - *sbuf)
48625210b06SDavid du Colombier 		n = esbuf - *sbuf;
48725210b06SDavid du Colombier 	if(n <= 0)
488*62579e34SDavid du Colombier 		return -1;			/* src buffer is empty */
48925210b06SDavid du Colombier 
49025210b06SDavid du Colombier 	memmove(*dbuf, *sbuf, n);
49125210b06SDavid du Colombier 	*sbuf += n;
49225210b06SDavid du Colombier 	*dbuf += n;
49325210b06SDavid du Colombier 	return edbuf - *dbuf;
49425210b06SDavid du Colombier }
49525210b06SDavid du Colombier 
49625210b06SDavid du Colombier void
impulse(void)49725210b06SDavid du Colombier impulse(void)
49825210b06SDavid du Colombier {
49925210b06SDavid du Colombier 	delay(500);				/* drain uart */
50025210b06SDavid du Colombier 	splhi();
50125210b06SDavid du Colombier 
50225210b06SDavid du Colombier 	/* turn off buffered serial console */
50325210b06SDavid du Colombier 	serialoq = nil;
50425210b06SDavid du Colombier 
50525210b06SDavid du Colombier 	/* shutdown devices */
50625210b06SDavid du Colombier 	chandevshutdown();
50725210b06SDavid du Colombier 	arch->introff();
50825210b06SDavid du Colombier }
50925210b06SDavid du Colombier 
51025210b06SDavid du Colombier void
prstackuse(int)51125210b06SDavid du Colombier prstackuse(int)
51225210b06SDavid du Colombier {
51325210b06SDavid du Colombier 	char *top, *base;
51425210b06SDavid du Colombier 	ulong *p;
51525210b06SDavid du Colombier 
51625210b06SDavid du Colombier 	base = up->kstack;
51725210b06SDavid du Colombier 	top =  up->kstack + KSTACK - (sizeof(Sargs) + BY2WD);
51825210b06SDavid du Colombier 	for (p = (ulong *)base; (char *)p < top && *p ==
51925210b06SDavid du Colombier 	    (Stkpat<<24 | Stkpat<<16 | Stkpat<<8 | Stkpat); p++)
52025210b06SDavid du Colombier 		;
52125210b06SDavid du Colombier 	print("proc stack: used %ld bytes, %ld left (stack pattern)\n",
52225210b06SDavid du Colombier 		top - (char *)p, (char *)p - base);
52325210b06SDavid du Colombier }
52425210b06SDavid du Colombier 
52525210b06SDavid du Colombier /*
52625210b06SDavid du Colombier  * this code is simplified from reboot().  It doesn't need to relocate
52725210b06SDavid du Colombier  * the new kernel nor deal with other processors.
52825210b06SDavid du Colombier  */
52925210b06SDavid du Colombier void
warp9(ulong entry)53025210b06SDavid du Colombier warp9(ulong entry)
53125210b06SDavid du Colombier {
53225210b06SDavid du Colombier //	prstackuse(0);			/* debugging */
533bca3d52eSDavid du Colombier 	mkmultiboot();
53425210b06SDavid du Colombier 	impulse();
53525210b06SDavid du Colombier 
53625210b06SDavid du Colombier 	/* get out of KZERO space, turn off paging and jump to entry */
53725210b06SDavid du Colombier 	pagingoff(PADDR(entry));
53825210b06SDavid du Colombier }
53925210b06SDavid du Colombier 
540*62579e34SDavid du Colombier static int
bootfail(Boot * b)541*62579e34SDavid du Colombier bootfail(Boot *b)
54225210b06SDavid du Colombier {
543*62579e34SDavid du Colombier 	b->state = FAILED;
54425210b06SDavid du Colombier 	return FAIL;
545*62579e34SDavid du Colombier }
54625210b06SDavid du Colombier 
547*62579e34SDavid du Colombier static int
isgzipped(uchar * p)548*62579e34SDavid du Colombier isgzipped(uchar *p)
549*62579e34SDavid du Colombier {
550*62579e34SDavid du Colombier 	return p[0] == 0x1F && p[1] == 0x8B && p[2] == 0x08;
551*62579e34SDavid du Colombier }
55225210b06SDavid du Colombier 
553*62579e34SDavid du Colombier static int
readexec(Boot * b)554*62579e34SDavid du Colombier readexec(Boot *b)
555*62579e34SDavid du Colombier {
556*62579e34SDavid du Colombier 	Exechdr *hdr;
557*62579e34SDavid du Colombier 	ulong pentry, text, data, magic;
558*62579e34SDavid du Colombier 
55925210b06SDavid du Colombier 	hdr = &b->hdr;
56025210b06SDavid du Colombier 	magic = GLLONG(hdr->magic);
56125210b06SDavid du Colombier 	if(magic == I_MAGIC || magic == S_MAGIC) {
56225210b06SDavid du Colombier 		pentry = PADDR(GLLONG(hdr->entry));
56325210b06SDavid du Colombier 		text = GLLONG(hdr->text);
56425210b06SDavid du Colombier 		data = GLLONG(hdr->data);
56525210b06SDavid du Colombier 		if (pentry < MB)
566*62579e34SDavid du Colombier 			panic("kernel entry %#p below 1 MB", pentry);
567*62579e34SDavid du Colombier 		if (PGROUND(pentry + text) + data > MB + Kernelmax)
568*62579e34SDavid du Colombier 			panic("kernel larger than %d bytes", Kernelmax);
56925210b06SDavid du Colombier 		b->state = READ9TEXT;
57025210b06SDavid du Colombier 		b->bp = (char*)KADDR(pentry);
57125210b06SDavid du Colombier 		b->wp = b->bp;
57225210b06SDavid du Colombier 		b->ep = b->wp+text;
57325210b06SDavid du Colombier 
57425210b06SDavid du Colombier 		if(magic == I_MAGIC){
57525210b06SDavid du Colombier 			memmove(b->bp, b->hdr.uvl, sizeof(b->hdr.uvl));
57625210b06SDavid du Colombier 			b->wp += sizeof(b->hdr.uvl);
57725210b06SDavid du Colombier 		}
57825210b06SDavid du Colombier 
57925210b06SDavid du Colombier 		print("%lud", text);
580*62579e34SDavid du Colombier 	} else if(memcmp(b->bp, elfident, 4) == 0 &&
581*62579e34SDavid du Colombier 	    (uchar)b->bp[4] == ELFCLASS32){
58225210b06SDavid du Colombier 		b->state = READEHDR;
58325210b06SDavid du Colombier 		b->bp = (char*)&ehdr;
58425210b06SDavid du Colombier 		b->wp = b->bp;
58525210b06SDavid du Colombier 		b->ep = b->wp + sizeof(Ehdr);
58625210b06SDavid du Colombier 		memmove(b->bp, &b->hdr, sizeof(Exechdr));
58725210b06SDavid du Colombier 		b->wp += sizeof(Exechdr);
58825210b06SDavid du Colombier 		print("elf...");
589*62579e34SDavid du Colombier 	} else if(memcmp(b->bp, elfident, 4) == 0 &&
590*62579e34SDavid du Colombier 	    (uchar)b->bp[4] == ELFCLASS64){
591*62579e34SDavid du Colombier 		b->state = READE64HDR;
592*62579e34SDavid du Colombier 		b->bp = (char*)&e64hdr;
593*62579e34SDavid du Colombier 		b->wp = b->bp;
594*62579e34SDavid du Colombier 		b->ep = b->wp + sizeof(E64hdr);
595*62579e34SDavid du Colombier 		memmove(b->bp, &b->hdr, sizeof(Exechdr));
596*62579e34SDavid du Colombier 		b->wp += sizeof(Exechdr);
597*62579e34SDavid du Colombier 		print("elf64...");
598*62579e34SDavid du Colombier 	} else if(isgzipped((uchar *)b->bp)) {
59925210b06SDavid du Colombier 		b->state = READGZIP;
60025210b06SDavid du Colombier 		/* could use Unzipbuf instead of smalloc() */
60125210b06SDavid du Colombier 		b->bp = (char*)smalloc(Kernelmax);
60225210b06SDavid du Colombier 		b->wp = b->bp;
60325210b06SDavid du Colombier 		b->ep = b->wp + Kernelmax;
60425210b06SDavid du Colombier 		memmove(b->bp, &b->hdr, sizeof(Exechdr));
60525210b06SDavid du Colombier 		b->wp += sizeof(Exechdr);
60625210b06SDavid du Colombier 		print("gz...");
60725210b06SDavid du Colombier 	} else {
608*62579e34SDavid du Colombier 		print("bad kernel format (magic %#lux)\n", magic);
609*62579e34SDavid du Colombier 		return bootfail(b);
61025210b06SDavid du Colombier 	}
611*62579e34SDavid du Colombier 	return MORE;
612*62579e34SDavid du Colombier }
613*62579e34SDavid du Colombier 
614*62579e34SDavid du Colombier static void
boot9(Boot * b,ulong magic,ulong entry)615*62579e34SDavid du Colombier boot9(Boot *b, ulong magic, ulong entry)
616*62579e34SDavid du Colombier {
617*62579e34SDavid du Colombier 	if(magic == I_MAGIC){
618*62579e34SDavid du Colombier 		print("entry: %#lux\n", entry);
619*62579e34SDavid du Colombier 		warp9(PADDR(entry));
620*62579e34SDavid du Colombier 	}
621*62579e34SDavid du Colombier 	else if(magic == S_MAGIC)
622*62579e34SDavid du Colombier 		warp64(beswav(b->hdr.uvl[0]));
623*62579e34SDavid du Colombier 	else
624*62579e34SDavid du Colombier 		print("bad magic %#lux\n", magic);
625*62579e34SDavid du Colombier }
626*62579e34SDavid du Colombier 
627*62579e34SDavid du Colombier /* only returns upon failure */
628*62579e34SDavid du Colombier static void
readgzip(Boot * b)629*62579e34SDavid du Colombier readgzip(Boot *b)
630*62579e34SDavid du Colombier {
631*62579e34SDavid du Colombier 	ulong entry, text, data, bss, magic, all, pentry;
632*62579e34SDavid du Colombier 	uchar *sdata;
633*62579e34SDavid du Colombier 	Exechdr *hdr;
634*62579e34SDavid du Colombier 
635*62579e34SDavid du Colombier 	/* the whole gzipped kernel is now at b->bp */
636*62579e34SDavid du Colombier 	hdr = &b->hdr;
637*62579e34SDavid du Colombier 	if(!isgzipped((uchar *)b->bp)) {
638*62579e34SDavid du Colombier 		print("lost magic\n");
639*62579e34SDavid du Colombier 		return;
640*62579e34SDavid du Colombier 	}
641*62579e34SDavid du Colombier 	print("%ld => ", b->wp - b->bp);
642*62579e34SDavid du Colombier 	/* just fill hdr from gzipped b->bp, to get various sizes */
643*62579e34SDavid du Colombier 	if(gunzip((uchar*)hdr, sizeof *hdr, (uchar*)b->bp, b->wp - b->bp)
644*62579e34SDavid du Colombier 	    < sizeof *hdr) {
645*62579e34SDavid du Colombier 		print("error uncompressing kernel exec header\n");
646*62579e34SDavid du Colombier 		return;
647*62579e34SDavid du Colombier 	}
648*62579e34SDavid du Colombier 
649*62579e34SDavid du Colombier 	/* assume uncompressed kernel is a plan 9 boot image */
650*62579e34SDavid du Colombier 	magic = GLLONG(hdr->magic);
651*62579e34SDavid du Colombier 	entry = GLLONG(hdr->entry);
652*62579e34SDavid du Colombier 	text = GLLONG(hdr->text);
653*62579e34SDavid du Colombier 	data = GLLONG(hdr->data);
654*62579e34SDavid du Colombier 	bss = GLLONG(hdr->bss);
655*62579e34SDavid du Colombier 	print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
656*62579e34SDavid du Colombier 
657*62579e34SDavid du Colombier 	pentry = PADDR(entry);
658*62579e34SDavid du Colombier 	if (pentry < MB)
659*62579e34SDavid du Colombier 		panic("kernel entry %#p below 1 MB", pentry);
660*62579e34SDavid du Colombier 	if (PGROUND(pentry + text) + data > MB + Kernelmax)
661*62579e34SDavid du Colombier 		panic("kernel larger than %d bytes", Kernelmax);
662*62579e34SDavid du Colombier 
663*62579e34SDavid du Colombier 	/* fill entry from gzipped b->bp */
664*62579e34SDavid du Colombier 	all = sizeof(Exec) + text + data;
665*62579e34SDavid du Colombier 	if(gunzip((uchar *)KADDR(PADDR(entry)) - sizeof(Exec), all,
666*62579e34SDavid du Colombier 	    (uchar*)b->bp, b->wp - b->bp) < all) {
667*62579e34SDavid du Colombier 		print("error uncompressing kernel\n");
668*62579e34SDavid du Colombier 		return;
669*62579e34SDavid du Colombier 	}
670*62579e34SDavid du Colombier 
671*62579e34SDavid du Colombier 	/* relocate data to start at page boundary */
672*62579e34SDavid du Colombier 	sdata = KADDR(PADDR(entry+text));
673*62579e34SDavid du Colombier 	memmove((void*)PGROUND((uintptr)sdata), sdata, data);
674*62579e34SDavid du Colombier 
675*62579e34SDavid du Colombier 	boot9(b, magic, entry);
676*62579e34SDavid du Colombier }
677*62579e34SDavid du Colombier 
678*62579e34SDavid du Colombier /*
679*62579e34SDavid du Colombier  * if nbuf is zero, boot.
680*62579e34SDavid du Colombier  * else add nbuf bytes from vbuf to b->wp (if there is room)
681*62579e34SDavid du Colombier  * and advance the state machine, which may reset b's pointers
682*62579e34SDavid du Colombier  * and return to the top.
683*62579e34SDavid du Colombier  */
684*62579e34SDavid du Colombier int
bootpass(Boot * b,void * vbuf,int nbuf)685*62579e34SDavid du Colombier bootpass(Boot *b, void *vbuf, int nbuf)
686*62579e34SDavid du Colombier {
687*62579e34SDavid du Colombier 	char *buf, *ebuf;
688*62579e34SDavid du Colombier 	Exechdr *hdr;
689*62579e34SDavid du Colombier 	ulong entry, bss;
690*62579e34SDavid du Colombier 	uvlong entry64;
691*62579e34SDavid du Colombier 
692*62579e34SDavid du Colombier 	if(b->state == FAILED)
693*62579e34SDavid du Colombier 		return FAIL;
694*62579e34SDavid du Colombier 
695*62579e34SDavid du Colombier 	if(nbuf == 0)
696*62579e34SDavid du Colombier 		goto Endofinput;
697*62579e34SDavid du Colombier 
698*62579e34SDavid du Colombier 	buf = vbuf;
699*62579e34SDavid du Colombier 	ebuf = buf+nbuf;
700*62579e34SDavid du Colombier 	/* possibly copy into b->wp from buf (not first time) */
701*62579e34SDavid du Colombier 	while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
702*62579e34SDavid du Colombier 		/* b->bp is full, so advance the state machine */
703*62579e34SDavid du Colombier 		switch(b->state) {
704*62579e34SDavid du Colombier 		case INITKERNEL:
705*62579e34SDavid du Colombier 			b->state = READEXEC;
706*62579e34SDavid du Colombier 			b->bp = (char*)&b->hdr;
707*62579e34SDavid du Colombier 			b->wp = b->bp;
708*62579e34SDavid du Colombier 			b->ep = b->bp+sizeof(Exechdr);
709*62579e34SDavid du Colombier 			break;
710*62579e34SDavid du Colombier 		case READEXEC:
711*62579e34SDavid du Colombier 			readexec(b);
71225210b06SDavid du Colombier 			break;
71325210b06SDavid du Colombier 
71425210b06SDavid du Colombier 		case READ9TEXT:
71525210b06SDavid du Colombier 			hdr = &b->hdr;
71625210b06SDavid du Colombier 			b->state = READ9DATA;
71725210b06SDavid du Colombier 			b->bp = (char*)PGROUND((uintptr)
71825210b06SDavid du Colombier 				KADDR(PADDR(GLLONG(hdr->entry))) +
71925210b06SDavid du Colombier 				GLLONG(hdr->text));
72025210b06SDavid du Colombier 			b->wp = b->bp;
72125210b06SDavid du Colombier 			b->ep = b->wp + GLLONG(hdr->data);
72225210b06SDavid du Colombier 			print("+%ld", GLLONG(hdr->data));
72325210b06SDavid du Colombier 			break;
72425210b06SDavid du Colombier 
72525210b06SDavid du Colombier 		case READ9DATA:
72625210b06SDavid du Colombier 			hdr = &b->hdr;
72725210b06SDavid du Colombier 			bss = GLLONG(hdr->bss);
72825210b06SDavid du Colombier 			memset(b->ep, 0, bss);
72925210b06SDavid du Colombier 			print("+%ld=%ld\n",
73025210b06SDavid du Colombier 				bss, GLLONG(hdr->text)+GLLONG(hdr->data)+bss);
73125210b06SDavid du Colombier 			b->state = TRYBOOT;
73225210b06SDavid du Colombier 			return ENOUGH;
73325210b06SDavid du Colombier 
734*62579e34SDavid du Colombier 		/*
735*62579e34SDavid du Colombier 		 * elf
736*62579e34SDavid du Colombier 		 */
73725210b06SDavid du Colombier 		case READEHDR:
738*62579e34SDavid du Colombier 			if(!readehdr(b))
73925210b06SDavid du Colombier 				print("readehdr failed\n");
74025210b06SDavid du Colombier 			break;
74125210b06SDavid du Colombier 		case READPHDR:
742*62579e34SDavid du Colombier 			readphdr(b);
74325210b06SDavid du Colombier 			break;
74425210b06SDavid du Colombier 		case READEPAD:
745*62579e34SDavid du Colombier 			readepad(b);
746*62579e34SDavid du Colombier 			break;
747*62579e34SDavid du Colombier 		case READEDATA:
748*62579e34SDavid du Colombier 			readedata(b);
749*62579e34SDavid du Colombier 			if(b->state == TRYEBOOT)
750*62579e34SDavid du Colombier 				return ENOUGH;
75125210b06SDavid du Colombier 			break;
75225210b06SDavid du Colombier 
753*62579e34SDavid du Colombier 		/*
754*62579e34SDavid du Colombier 		 * elf64
755*62579e34SDavid du Colombier 		 */
756*62579e34SDavid du Colombier 		case READE64HDR:
757*62579e34SDavid du Colombier 			if(!reade64hdr(b))
758*62579e34SDavid du Colombier 				print("reade64hdr failed\n");
759*62579e34SDavid du Colombier 			break;
760*62579e34SDavid du Colombier 		case READ64PHDR:
761*62579e34SDavid du Colombier 			readp64hdr(b);
762*62579e34SDavid du Colombier 			break;
763*62579e34SDavid du Colombier 		case READE64PAD:
764*62579e34SDavid du Colombier 			reade64pad(b);
765*62579e34SDavid du Colombier 			break;
766*62579e34SDavid du Colombier 		case READE64DATA:
767*62579e34SDavid du Colombier 			reade64data(b);
768*62579e34SDavid du Colombier 			if(b->state == TRYE64BOOT)
76925210b06SDavid du Colombier 				return ENOUGH;
77025210b06SDavid du Colombier 			break;
77125210b06SDavid du Colombier 
77225210b06SDavid du Colombier 		case TRYBOOT:
77325210b06SDavid du Colombier 		case TRYEBOOT:
774*62579e34SDavid du Colombier 		case TRYE64BOOT:
77525210b06SDavid du Colombier 		case READGZIP:
77625210b06SDavid du Colombier 			return ENOUGH;
77725210b06SDavid du Colombier 
77825210b06SDavid du Colombier 		case READ9LOAD:
77925210b06SDavid du Colombier 		case INIT9LOAD:
78025210b06SDavid du Colombier 			panic("9load");
78125210b06SDavid du Colombier 
78225210b06SDavid du Colombier 		default:
78325210b06SDavid du Colombier 			panic("bootstate");
78425210b06SDavid du Colombier 		}
785*62579e34SDavid du Colombier 		if(b->state == FAILED)
786*62579e34SDavid du Colombier 			return FAIL;
78725210b06SDavid du Colombier 	}
78825210b06SDavid du Colombier 	return MORE;
78925210b06SDavid du Colombier 
79025210b06SDavid du Colombier Endofinput:
79125210b06SDavid du Colombier 	/* end of input */
79225210b06SDavid du Colombier 	switch(b->state) {
79325210b06SDavid du Colombier 	case INITKERNEL:
79425210b06SDavid du Colombier 	case READEXEC:
79525210b06SDavid du Colombier 	case READ9TEXT:
79625210b06SDavid du Colombier 	case READ9DATA:
79725210b06SDavid du Colombier 	case READEHDR:
79825210b06SDavid du Colombier 	case READPHDR:
79925210b06SDavid du Colombier 	case READEPAD:
80025210b06SDavid du Colombier 	case READEDATA:
801*62579e34SDavid du Colombier 	case READE64HDR:
802*62579e34SDavid du Colombier 	case READ64PHDR:
803*62579e34SDavid du Colombier 	case READE64PAD:
804*62579e34SDavid du Colombier 	case READE64DATA:
80525210b06SDavid du Colombier 		print("premature EOF\n");
806*62579e34SDavid du Colombier 		break;
80725210b06SDavid du Colombier 
80825210b06SDavid du Colombier 	case TRYBOOT:
809*62579e34SDavid du Colombier 		boot9(b, GLLONG(b->hdr.magic), GLLONG(b->hdr.entry));
810*62579e34SDavid du Colombier 		break;
81125210b06SDavid du Colombier 
81225210b06SDavid du Colombier 	case TRYEBOOT:
813*62579e34SDavid du Colombier 		entry = b->entry;
81425210b06SDavid du Colombier 		if(ehdr.machine == I386){
81525210b06SDavid du Colombier 			print("entry: %#lux\n", entry);
81625210b06SDavid du Colombier 			warp9(PADDR(entry));
81725210b06SDavid du Colombier 		}
818*62579e34SDavid du Colombier 		else if(ehdr.machine == AMD64)
81925210b06SDavid du Colombier 			warp64(entry);
820*62579e34SDavid du Colombier 		else
821*62579e34SDavid du Colombier 			panic("elf boot: ehdr.machine %d unknown", ehdr.machine);
822*62579e34SDavid du Colombier 		break;
823*62579e34SDavid du Colombier 
824*62579e34SDavid du Colombier 	case TRYE64BOOT:
825*62579e34SDavid du Colombier 		entry64 = b->entry;
826*62579e34SDavid du Colombier 		if(e64hdr.machine == I386){
827*62579e34SDavid du Colombier 			print("entry: %#llux\n", entry64);
828*62579e34SDavid du Colombier 			warp9(PADDR(entry64));
82925210b06SDavid du Colombier 		}
830*62579e34SDavid du Colombier 		else if(e64hdr.machine == AMD64)
831*62579e34SDavid du Colombier 			warp64(entry64);
832*62579e34SDavid du Colombier 		else
833*62579e34SDavid du Colombier 			panic("elf64 boot: e64hdr.machine %d unknown",
834*62579e34SDavid du Colombier 				e64hdr.machine);
835*62579e34SDavid du Colombier 		break;
83625210b06SDavid du Colombier 
83725210b06SDavid du Colombier 	case READGZIP:
838*62579e34SDavid du Colombier 		readgzip(b);
839*62579e34SDavid du Colombier 		break;
84025210b06SDavid du Colombier 
84125210b06SDavid du Colombier 	case INIT9LOAD:
84225210b06SDavid du Colombier 	case READ9LOAD:
84325210b06SDavid du Colombier 		panic("end 9load");
84425210b06SDavid du Colombier 
84525210b06SDavid du Colombier 	default:
84625210b06SDavid du Colombier 		panic("bootdone");
84725210b06SDavid du Colombier 	}
848*62579e34SDavid du Colombier 	return bootfail(b);
84925210b06SDavid du Colombier }
850