Browse Source

Plan 9 from Bell Labs 2013-03-09

David du Colombier 11 years ago
parent
commit
9495cb7852
9 changed files with 469 additions and 152 deletions
  1. 5 0
      sys/man/1/8c
  2. 16 0
      sys/man/1/8l
  3. 9 0
      sys/man/1/pcc
  4. 1 1
      sys/man/2/mach
  5. 1 1
      sys/man/8/9boot
  6. 414 144
      sys/src/9/pcboot/bootld.c
  7. 1 2
      sys/src/9/pcboot/bootmkfile
  8. 15 4
      sys/src/9/pcboot/dat.h
  9. 7 0
      sys/src/cmd/pcc.c

+ 5 - 0
sys/man/1/8c

@@ -109,6 +109,11 @@ and append
 .B -w
 Print warning messages about unused variables, etc.
 .TP
+.B -W
+Print all the messages that
+.B -w
+would print as warnings, but make them errors.
+.TP
 .B -B
 Accept functions without a new-style
 ANSI C function prototype.

+ 16 - 0
sys/man/1/8l

@@ -35,6 +35,11 @@ is one of
 .BR 386 ,
 etc. as listed in
 .IR 8c (1).
+If the environment variable
+.B ccroot
+is defined, the library is sought in
+.BR $ccroot/$objtype/lib
+instead.
 The libraries must have tables of contents
 (see
 .IR ar (1)).
@@ -201,6 +206,17 @@ The text segment is rounded to a multiple of
 (if
 .I r
 is nonzero).
+.TP
+.BI -L dir
+For a library reference
+.BI -l ext,
+search
+.I dir
+before looking in the standard library directory.
+If more than one
+.B -L
+option is given,
+directories will be searched in order of appearance.
 .PP
 The numbers in the above options can begin with
 .L 0x

+ 9 - 0
sys/man/1/pcc

@@ -59,6 +59,11 @@ Insert profiling code into the executable output.
 .B -w
 Print compiler warning messages.
 .TP
+.B -W
+Print all the messages that
+.B -w
+would print as warnings, but make them errors.
+.TP
 .BI -l lib
 Include
 .BI / $objtype /lib/ape/lib lib .a
@@ -78,6 +83,10 @@ conversion warnings, as in
 Echo the preprocessing, compiling, and loading commands
 before they are executed.
 .TP
+.BI -x " file"
+Produce an export file in the executable, as described in
+.IR 8l (1).
+.TP
 .BI -D name=def
 .br
 .ns

+ 1 - 1
sys/man/2/mach

@@ -1,7 +1,7 @@
 .TH MACH 2
 .SH NAME
 crackhdr, machbytype, machbyname, newmap, setmap, findseg, unusemap,
-loadmap, attachproc, get1, get2, get4, get8, geta, put1, put2, put4, put8, puta
+loadmap, attachproc, get1, get2, get4, get8, geta, put1, put2, put4, put8, puta,
 beswab, beswal, beswav, leswab, leswal, leswav \- machine-independent access to executable files
 .SH SYNOPSIS
 .B #include <u.h>

+ 1 - 1
sys/man/8/9boot

@@ -188,7 +188,7 @@ the
 may be a Plan 9 boot image compressed with
 .IR gzip (1).
 In all cases,
-the uncompressed kernel must be in Plan 9 boot image or ELF format.
+the uncompressed kernel must be in Plan 9 boot image, ELF or ELF64 format.
 If the
 .B plan9.ini
 file contains multiple

+ 414 - 144
sys/src/9/pcboot/bootld.c

@@ -18,22 +18,27 @@
 
 #undef KADDR
 #undef PADDR
-// #define PADDR(a)	(paddr)((void *)(a))
 
 #define KADDR(a)	((void*)((ulong)(a) | KZERO))
 #define PADDR(a)	((ulong)(a) & ~KSEGM)
 
 extern int debug;
+
 extern void pagingoff(ulong);
 
-static uchar elfident[7] = {
-	'\177', 'E', 'L', 'F', '\1', '\1', '\1'
+static uchar elfident[] = {
+	'\177', 'E', 'L', 'F',
 };
 static Ehdr ehdr, rehdr;
+static E64hdr e64hdr;
 static Phdr *phdr;
+static P64hdr *p64hdr;
+
 static int curphdr;
 static ulong curoff;
 static ulong elftotal;
+
+static uvlong (*swav)(uvlong);
 static long (*swal)(long);
 static ushort (*swab)(ushort);
 
@@ -100,6 +105,21 @@ leswal(long l)
 	return (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
 }
 
+/*
+ * little-endian vlong
+ */
+uvlong
+leswav(uvlong v)
+{
+	uchar *p;
+
+	p = (uchar*)&v;
+	return ((uvlong)p[7]<<56) | ((uvlong)p[6]<<48) | ((uvlong)p[5]<<40)
+				  | ((uvlong)p[4]<<32) | ((uvlong)p[3]<<24)
+				  | ((uvlong)p[2]<<16) | ((uvlong)p[1]<<8)
+				  | (uvlong)p[0];
+}
+
 /*
  * Convert header to canonical form
  */
@@ -112,6 +132,15 @@ hswal(long *lp, int n, long (*swap) (long))
 	}
 }
 
+static void
+hswav(uvlong *lp, int n, uvlong (*swap)(uvlong))
+{
+	while (n--) {
+		*lp = (*swap)(*lp);
+		lp++;
+	}
+}
+
 static int
 readehdr(Boot *b)
 {
@@ -132,7 +161,7 @@ readehdr(Boot *b)
 		print("bad ELF encoding - not big or little endian\n");
 		return 0;
 	}
-	memmove(&rehdr, &ehdr, sizeof(Ehdr));
+	memmove(&rehdr, &ehdr, sizeof(Ehdr));	/* copy; never used */
 
 	ehdr.type = swab(ehdr.type);
 	ehdr.machine = swab(ehdr.machine);
@@ -161,6 +190,7 @@ readehdr(Boot *b)
 	b->bp = (char*)smalloc(i);
 	b->wp = b->bp;
 	b->ep = b->wp + i;
+	elftotal = 0;
 	phdr = (Phdr*)(b->bp + ehdr.phoff-sizeof(Ehdr));
 	if(debug)
 		print("phdr...");
@@ -168,11 +198,70 @@ readehdr(Boot *b)
 	return 1;
 }
 
+static int
+reade64hdr(Boot *b)
+{
+	int i;
+
+	/* bitswap the header according to the DATA format */
+	if(e64hdr.ident[CLASS] != ELFCLASS64) {
+		print("bad ELF class - not 64 bit\n");
+		return 0;
+	}
+	if(e64hdr.ident[DATA] == ELFDATA2LSB) {
+		swab = leswab;
+		swal = leswal;
+		swav = leswav;
+	} else if(e64hdr.ident[DATA] == ELFDATA2MSB) {
+		swab = beswab;
+		swal = beswal;
+		swav = beswav;
+	} else {
+		print("bad ELF encoding - not big or little endian\n");
+		return 0;
+	}
+//	memmove(&rehdr, &ehdr, sizeof(Ehdr));	/* copy; never used */
+
+	e64hdr.type = swab(e64hdr.type);
+	e64hdr.machine = swab(e64hdr.machine);
+	e64hdr.version = swal(e64hdr.version);
+	e64hdr.elfentry = swav(e64hdr.elfentry);
+	e64hdr.phoff = swav(e64hdr.phoff);
+	e64hdr.shoff = swav(e64hdr.shoff);
+	e64hdr.flags = swal(e64hdr.flags);
+	e64hdr.ehsize = swab(e64hdr.ehsize);
+	e64hdr.phentsize = swab(e64hdr.phentsize);
+	e64hdr.phnum = swab(e64hdr.phnum);
+	e64hdr.shentsize = swab(e64hdr.shentsize);
+	e64hdr.shnum = swab(e64hdr.shnum);
+	e64hdr.shstrndx = swab(e64hdr.shstrndx);
+	if(e64hdr.type != EXEC || e64hdr.version != CURRENT)
+		return 0;
+	if(e64hdr.phentsize != sizeof(P64hdr))
+		return 0;
+
+	if(debug)
+		print("reade64hdr OK entry %#llux\n", e64hdr.elfentry);
+
+	curoff = sizeof(E64hdr);
+	i = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum - curoff;
+	b->state = READ64PHDR;
+	b->bp = (char*)smalloc(i);
+	b->wp = b->bp;
+	b->ep = b->wp + i;
+	elftotal = 0;
+	p64hdr = (P64hdr*)(b->bp + e64hdr.phoff-sizeof(E64hdr));
+	if(debug)
+		print("p64hdr...");
+
+	return 1;
+}
+
 static int
 nextphdr(Boot *b)
 {
 	Phdr *php;
-	ulong entry, offset;
+	ulong offset;
 	char *physaddr;
 
 	if(debug)
@@ -217,8 +306,64 @@ nextphdr(Boot *b)
 	if(curphdr != 0){
 		print("=%lud\n", elftotal);
 		b->state = TRYEBOOT;
-		entry = ehdr.elfentry & ~KSEGM;
-		PLLONG(b->hdr.entry, entry);
+		b->entry = ehdr.elfentry;
+		// PLLONG(b->hdr.entry, b->entry);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int
+nextp64hdr(Boot *b)
+{
+	P64hdr *php;
+	uvlong offset;
+	char *physaddr;
+
+	if(debug)
+		print("reade64data %d\n", curphdr);
+
+	for(; curphdr < e64hdr.phnum; curphdr++){
+		php = p64hdr+curphdr;
+		if(php->type != LOAD)
+			continue;
+		offset = php->offset;
+		physaddr = (char*)KADDR(PADDR(php->paddr));
+		if(offset < curoff){
+			/*
+			 * Can't (be bothered to) rewind the
+			 * input, it might be from tftp. If we
+			 * did then we could boot FreeBSD kernels
+			 * too maybe.
+			 */
+			return 0;
+		}
+		if(php->offset > curoff){
+			b->state = READE64PAD;
+			b->bp = (char*)smalloc(offset - curoff);
+			b->wp = b->bp;
+			b->ep = b->wp + offset - curoff;
+			if(debug)
+				print("nextp64hdr %llud...\n", offset - curoff);
+			return 1;
+		}
+		b->state = READE64DATA;
+		b->bp = physaddr;
+		b->wp = b->bp;
+		b->ep = b->wp+php->filesz;
+		print("%llud+", php->filesz);
+		elftotal += php->filesz;
+		if(debug)
+			print("nextp64hdr %llud@%#p\n", php->filesz, physaddr);
+
+		return 1;
+	}
+
+	if(curphdr != 0){
+		print("=%lud\n", elftotal);
+		b->state = TRYE64BOOT;
+		b->entry = e64hdr.elfentry;
 		return 1;
 	}
 
@@ -238,6 +383,19 @@ readepad(Boot *b)
 	return nextphdr(b);
 }
 
+static int
+reade64pad(Boot *b)
+{
+	P64hdr *php;
+
+	php = p64hdr+curphdr;
+	if(debug)
+		print("reade64pad %d\n", curphdr);
+	curoff = php->offset;
+
+	return nextp64hdr(b);
+}
+
 static int
 readedata(Boot *b)
 {
@@ -258,6 +416,26 @@ readedata(Boot *b)
 	return nextphdr(b);
 }
 
+static int
+reade64data(Boot *b)
+{
+	P64hdr *php;
+
+	php = p64hdr+curphdr;
+	if(debug)
+		print("reade64data %d\n", curphdr);
+	if(php->filesz < php->memsz){
+		print("%llud",  php->memsz - php->filesz);
+		elftotal += php->memsz - php->filesz;
+		memset((char*)KADDR(PADDR(php->paddr) + php->filesz), 0,
+			php->memsz - php->filesz);
+	}
+	curoff = php->offset + php->filesz;
+	curphdr++;
+
+	return nextp64hdr(b);
+}
+
 static int
 readphdr(Boot *b)
 {
@@ -275,6 +453,27 @@ readphdr(Boot *b)
 	return nextphdr(b);
 }
 
+static int
+readp64hdr(Boot *b)
+{
+	int hdr;
+	P64hdr *php, *p;
+
+	php = p = p64hdr;
+	for (hdr = 0; hdr < e64hdr.phnum; hdr++, p++) {
+		hswal((long*)p, 2, swal);
+		hswav((uvlong*)&p->offset, 6, swav);
+	}
+	if(debug)
+		print("p64hdr curoff %lud vaddr %#llux paddr %#llux\n",
+			curoff, php->vaddr, php->paddr);
+
+	curoff = e64hdr.phoff + e64hdr.phentsize*e64hdr.phnum;
+	curphdr = 0;
+
+	return nextp64hdr(b);
+}
+
 static int
 addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
 {
@@ -282,11 +481,11 @@ addbytes(char **dbuf, char *edbuf, char **sbuf, char *esbuf)
 
 	n = edbuf - *dbuf;
 	if(n <= 0)
-		return 0;
+		return 0;			/* dest buffer is full */
 	if(n > esbuf - *sbuf)
 		n = esbuf - *sbuf;
 	if(n <= 0)
-		return -1;
+		return -1;			/* src buffer is empty */
 
 	memmove(*dbuf, *sbuf, n);
 	*sbuf += n;
@@ -338,13 +537,156 @@ warp9(ulong entry)
 	pagingoff(PADDR(entry));
 }
 
+static int
+bootfail(Boot *b)
+{
+	b->state = FAILED;
+	return FAIL;
+}
+
+static int
+isgzipped(uchar *p)
+{
+	return p[0] == 0x1F && p[1] == 0x8B && p[2] == 0x08;
+}
+
+static int
+readexec(Boot *b)
+{
+	Exechdr *hdr;
+	ulong pentry, text, data, magic;
+
+	hdr = &b->hdr;
+	magic = GLLONG(hdr->magic);
+	if(magic == I_MAGIC || magic == S_MAGIC) {
+		pentry = PADDR(GLLONG(hdr->entry));
+		text = GLLONG(hdr->text);
+		data = GLLONG(hdr->data);
+		if (pentry < MB)
+			panic("kernel entry %#p below 1 MB", pentry);
+		if (PGROUND(pentry + text) + data > MB + Kernelmax)
+			panic("kernel larger than %d bytes", Kernelmax);
+		b->state = READ9TEXT;
+		b->bp = (char*)KADDR(pentry);
+		b->wp = b->bp;
+		b->ep = b->wp+text;
+
+		if(magic == I_MAGIC){
+			memmove(b->bp, b->hdr.uvl, sizeof(b->hdr.uvl));
+			b->wp += sizeof(b->hdr.uvl);
+		}
+
+		print("%lud", text);
+	} else if(memcmp(b->bp, elfident, 4) == 0 &&
+	    (uchar)b->bp[4] == ELFCLASS32){
+		b->state = READEHDR;
+		b->bp = (char*)&ehdr;
+		b->wp = b->bp;
+		b->ep = b->wp + sizeof(Ehdr);
+		memmove(b->bp, &b->hdr, sizeof(Exechdr));
+		b->wp += sizeof(Exechdr);
+		print("elf...");
+	} else if(memcmp(b->bp, elfident, 4) == 0 &&
+	    (uchar)b->bp[4] == ELFCLASS64){
+		b->state = READE64HDR;
+		b->bp = (char*)&e64hdr;
+		b->wp = b->bp;
+		b->ep = b->wp + sizeof(E64hdr);
+		memmove(b->bp, &b->hdr, sizeof(Exechdr));
+		b->wp += sizeof(Exechdr);
+		print("elf64...");
+	} else if(isgzipped((uchar *)b->bp)) {
+		b->state = READGZIP;
+		/* could use Unzipbuf instead of smalloc() */
+		b->bp = (char*)smalloc(Kernelmax);
+		b->wp = b->bp;
+		b->ep = b->wp + Kernelmax;
+		memmove(b->bp, &b->hdr, sizeof(Exechdr));
+		b->wp += sizeof(Exechdr);
+		print("gz...");
+	} else {
+		print("bad kernel format (magic %#lux)\n", magic);
+		return bootfail(b);
+	}
+	return MORE;
+}
+
+static void
+boot9(Boot *b, ulong magic, ulong entry)
+{
+	if(magic == I_MAGIC){
+		print("entry: %#lux\n", entry);
+		warp9(PADDR(entry));
+	}
+	else if(magic == S_MAGIC)
+		warp64(beswav(b->hdr.uvl[0]));
+	else
+		print("bad magic %#lux\n", magic);
+}
+
+/* only returns upon failure */
+static void
+readgzip(Boot *b)
+{
+	ulong entry, text, data, bss, magic, all, pentry;
+	uchar *sdata;
+	Exechdr *hdr;
+
+	/* the whole gzipped kernel is now at b->bp */
+	hdr = &b->hdr;
+	if(!isgzipped((uchar *)b->bp)) {
+		print("lost magic\n");
+		return;
+	}
+	print("%ld => ", b->wp - b->bp);
+	/* just fill hdr from gzipped b->bp, to get various sizes */
+	if(gunzip((uchar*)hdr, sizeof *hdr, (uchar*)b->bp, b->wp - b->bp)
+	    < sizeof *hdr) {
+		print("error uncompressing kernel exec header\n");
+		return;
+	}
+
+	/* assume uncompressed kernel is a plan 9 boot image */
+	magic = GLLONG(hdr->magic);
+	entry = GLLONG(hdr->entry);
+	text = GLLONG(hdr->text);
+	data = GLLONG(hdr->data);
+	bss = GLLONG(hdr->bss);
+	print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
+
+	pentry = PADDR(entry);
+	if (pentry < MB)
+		panic("kernel entry %#p below 1 MB", pentry);
+	if (PGROUND(pentry + text) + data > MB + Kernelmax)
+		panic("kernel larger than %d bytes", Kernelmax);
+
+	/* fill entry from gzipped b->bp */
+	all = sizeof(Exec) + text + data;
+	if(gunzip((uchar *)KADDR(PADDR(entry)) - sizeof(Exec), all,
+	    (uchar*)b->bp, b->wp - b->bp) < all) {
+		print("error uncompressing kernel\n");
+		return;
+	}
+
+	/* relocate data to start at page boundary */
+	sdata = KADDR(PADDR(entry+text));
+	memmove((void*)PGROUND((uintptr)sdata), sdata, data);
+
+	boot9(b, magic, entry);
+}
+
+/*
+ * if nbuf is zero, boot.
+ * else add nbuf bytes from vbuf to b->wp (if there is room)
+ * and advance the state machine, which may reset b's pointers
+ * and return to the top.
+ */
 int
 bootpass(Boot *b, void *vbuf, int nbuf)
 {
 	char *buf, *ebuf;
-	uchar *sdata;
 	Exechdr *hdr;
-	ulong entry, pentry, text, data, bss, magic;
+	ulong entry, bss;
 	uvlong entry64;
 
 	if(b->state == FAILED)
@@ -355,7 +697,9 @@ bootpass(Boot *b, void *vbuf, int nbuf)
 
 	buf = vbuf;
 	ebuf = buf+nbuf;
+	/* possibly copy into b->wp from buf (not first time) */
 	while(addbytes(&b->wp, b->ep, &buf, ebuf) == 0) {
+		/* b->bp is full, so advance the state machine */
 		switch(b->state) {
 		case INITKERNEL:
 			b->state = READEXEC;
@@ -364,54 +708,7 @@ bootpass(Boot *b, void *vbuf, int nbuf)
 			b->ep = b->bp+sizeof(Exechdr);
 			break;
 		case READEXEC:
-			hdr = &b->hdr;
-			magic = GLLONG(hdr->magic);
-			if(magic == I_MAGIC || magic == S_MAGIC) {
-				pentry = PADDR(GLLONG(hdr->entry));
-				text = GLLONG(hdr->text);
-				data = GLLONG(hdr->data);
-				if (pentry < MB)
-					panic("kernel entry %#p below 1 MB",
-						pentry);
-				if (PGROUND(pentry + text) + data >
-				    MB + Kernelmax)
-					panic("kernel larger than %d bytes",
-						Kernelmax);
-				b->state = READ9TEXT;
-				b->bp = (char*)KADDR(pentry);
-				b->wp = b->bp;
-				b->ep = b->wp+text;
-
-				if(magic == I_MAGIC){
-					memmove(b->bp, b->hdr.uvl, sizeof(b->hdr.uvl));
-					b->wp += sizeof(b->hdr.uvl);
-				}
-
-				print("%lud", text);
-			} else if(memcmp(b->bp, elfident, 4) == 0){
-				b->state = READEHDR;
-				b->bp = (char*)&ehdr;
-				b->wp = b->bp;
-				b->ep = b->wp + sizeof(Ehdr);
-				memmove(b->bp, &b->hdr, sizeof(Exechdr));
-				b->wp += sizeof(Exechdr);
-				print("elf...");
-			} else if(b->bp[0] == 0x1F && (uchar)b->bp[1] == 0x8B &&
-			    b->bp[2] == 0x08) {
-				b->state = READGZIP;
-				/* could use Unzipbuf instead of smalloc() */
-				b->bp = (char*)smalloc(Kernelmax);
-				b->wp = b->bp;
-				b->ep = b->wp + Kernelmax;
-				memmove(b->bp, &b->hdr, sizeof(Exechdr));
-				b->wp += sizeof(Exechdr);
-				print("gz...");
-			} else {
-				print("bad kernel format (magic %#lux)\n",
-					magic);
-				b->state = FAILED;
-				return FAIL;
-			}
+			readexec(b);
 			break;
 
 		case READ9TEXT:
@@ -434,39 +731,47 @@ bootpass(Boot *b, void *vbuf, int nbuf)
 			b->state = TRYBOOT;
 			return ENOUGH;
 
+		/*
+		 * elf
+		 */
 		case READEHDR:
-			if(!readehdr(b)){
+			if(!readehdr(b))
 				print("readehdr failed\n");
-				b->state = FAILED;
-				return FAIL;
-			}
 			break;
-
 		case READPHDR:
-			if(!readphdr(b)){
-				b->state = FAILED;
-				return FAIL;
-			}
+			readphdr(b);
 			break;
-
 		case READEPAD:
-			if(!readepad(b)){
-				b->state = FAILED;
-				return FAIL;
-			}
+			readepad(b);
 			break;
-
 		case READEDATA:
-			if(!readedata(b)){
-				b->state = FAILED;
-				return FAIL;
-			}
-			if(b->state == TRYBOOT)
+			readedata(b);
+			if(b->state == TRYEBOOT)
+				return ENOUGH;
+			break;
+
+		/*
+		 * elf64
+		 */
+		case READE64HDR:
+			if(!reade64hdr(b))
+				print("reade64hdr failed\n");
+			break;
+		case READ64PHDR:
+			readp64hdr(b);
+			break;
+		case READE64PAD:
+			reade64pad(b);
+			break;
+		case READE64DATA:
+			reade64data(b);
+			if(b->state == TRYE64BOOT)
 				return ENOUGH;
 			break;
 
 		case TRYBOOT:
 		case TRYEBOOT:
+		case TRYE64BOOT:
 		case READGZIP:
 			return ENOUGH;
 
@@ -477,10 +782,11 @@ bootpass(Boot *b, void *vbuf, int nbuf)
 		default:
 			panic("bootstate");
 		}
+		if(b->state == FAILED)
+			return FAIL;
 	}
 	return MORE;
 
-
 Endofinput:
 	/* end of input */
 	switch(b->state) {
@@ -492,80 +798,45 @@ Endofinput:
 	case READPHDR:
 	case READEPAD:
 	case READEDATA:
+	case READE64HDR:
+	case READ64PHDR:
+	case READE64PAD:
+	case READE64DATA:
 		print("premature EOF\n");
-		b->state = FAILED;
-		return FAIL;
+		break;
 
 	case TRYBOOT:
-		entry = GLLONG(b->hdr.entry);
-		magic = GLLONG(b->hdr.magic);
-		if(magic == I_MAGIC){
-			print("entry: %#lux\n", entry);
-			warp9(PADDR(entry));
-		}
-		else if(magic == S_MAGIC){
-			entry64 = beswav(b->hdr.uvl[0]);
-			warp64(entry64);
-		}
-		b->state = FAILED;
-		return FAIL;
+		boot9(b, GLLONG(b->hdr.magic), GLLONG(b->hdr.entry));
+		break;
 
 	case TRYEBOOT:
-		entry = GLLONG(b->hdr.entry);
+		entry = b->entry;
 		if(ehdr.machine == I386){
 			print("entry: %#lux\n", entry);
 			warp9(PADDR(entry));
 		}
-		else if(ehdr.machine == AMD64){
-			print("entry: %#lux\n", entry);
+		else if(ehdr.machine == AMD64)
 			warp64(entry);
-		}	
-		b->state = FAILED;
-		return FAIL;
-
-	case READGZIP:
-		/* apparently the whole gzipped kernel is now at b->bp */
-		hdr = &b->hdr;
-		if(b->bp[0] != 0x1F || (uchar)b->bp[1] != 0x8B || b->bp[2] != 0x08)
-			print("lost magic\n");
-
-		print("%ld => ", b->wp - b->bp);
-		/* fill hdr from gzipped b->bp to get various sizes */
-		if(gunzip((uchar*)hdr, sizeof *hdr, (uchar*)b->bp, b->wp - b->bp)
-		    < sizeof *hdr) {
-			print("badly compressed kernel\n");
-			return FAIL;
-		}
-
-		magic = GLLONG(hdr->magic);
-		entry = GLLONG(hdr->entry);
-		text = GLLONG(hdr->text);
-		data = GLLONG(hdr->data);
-		bss = GLLONG(hdr->bss);
-		print("%lud+%lud+%lud=%lud\n", text, data, bss, text+data+bss);
-
-		/* fill entry from gzipped b->bp */
-		if(gunzip((uchar *)KADDR(PADDR(entry)) - sizeof(Exec),
-		     sizeof(Exec)+text+data, 
-		     (uchar*)b->bp, b->wp-b->bp) < sizeof(Exec)+text+data) {
-			print("error uncompressing kernel\n");
-			return FAIL;
+		else
+			panic("elf boot: ehdr.machine %d unknown", ehdr.machine);
+		break;
+
+	case TRYE64BOOT:
+		entry64 = b->entry;
+		if(e64hdr.machine == I386){
+			print("entry: %#llux\n", entry64);
+			warp9(PADDR(entry64));
 		}
-		/* relocate data to start at page boundary */
-		sdata = KADDR(PADDR(entry+text));
-		memmove((void*)PGROUND((uintptr)sdata), sdata, data);
-
-		if(magic == I_MAGIC){
-			print("entry: %#lux\n", entry);
-			warp9(PADDR(entry));
-		}
-		else if(magic == S_MAGIC){
-			entry64 = beswav(hdr->uvl[0]);
+		else if(e64hdr.machine == AMD64)
 			warp64(entry64);
-		} else
-			print("bad magic %#lux\n", magic);
-		b->state = FAILED;
-		return FAIL;
+		else
+			panic("elf64 boot: e64hdr.machine %d unknown",
+				e64hdr.machine);
+		break;
+
+	case READGZIP:
+		readgzip(b);
+		break;
 
 	case INIT9LOAD:
 	case READ9LOAD:
@@ -574,6 +845,5 @@ Endofinput:
 	default:
 		panic("bootdone");
 	}
-	b->state = FAILED;
-	return FAIL;
+	return bootfail(b);
 }

+ 1 - 2
sys/src/9/pcboot/bootmkfile

@@ -67,10 +67,9 @@ ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
 
 $p$CONF:Q:	$CONF.c $OBJ $LIB
 	$CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
-	echo linking bootstraps
+	echo linking $p$CONF^'*'
 	$LD -o $target -H3 -T$KTZERO -l $OBJ $CONF.$O $LIB	# dos .com
 	$LD -o $target^debug -T$KTZERO -l $OBJ $CONF.$O $LIB
-#	$LD -o $target.exe -H4 -T$KTZERO -l $OBJ $CONF.$O $LIB	# dos .exe
 #	$LD -o $target.elf -H5 -R4096 -T$KTZERO -l $OBJ $CONF.$O $LIB
 	size $target^debug
 

+ 15 - 4
sys/src/9/pcboot/dat.h

@@ -52,11 +52,16 @@ int nconf;
 #define NAMELEN 28
 
 #define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
-#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
 #define	GLSHORT(p)	(((p)[0]<<8)|(p)[1])
+
+#define	GLONG(p)	((GSHORT(p+2)<<16)|GSHORT(p))
 #define	GLLONG(p)	(((ulong)GLSHORT(p)<<16)|GLSHORT(p+2))
 #define	PLLONG(p,v)	(p)[3]=(v);(p)[2]=(v)>>8;(p)[1]=(v)>>16;(p)[0]=(v)>>24
 
+#define	PLVLONG(p,v)	(p)[7]=(v);(p)[6]=(v)>>8;(p)[5]=(v)>>16;(p)[4]=(v)>>24;\
+			(p)[3]=(v)>>32; (p)[2]=(v)>>40;\
+			(p)[1]=(v)>>48; (p)[0]=(v)>>56;
+
 enum {
 	Stkpat =	0,
 };
@@ -477,12 +482,17 @@ enum {
 	READ9TEXT,
 	READ9DATA,
 	READGZIP,
-	READEHDR,
+	READEHDR,		/* elf states ... */
 	READPHDR,
 	READEPAD,
-	READEDATA,
+	READEDATA,		/* through here */
+	READE64HDR,		/* elf64 states ... */
+	READ64PHDR,
+	READE64PAD,
+	READE64DATA,		/* through here */
 	TRYBOOT,
-	TRYEBOOT,
+	TRYEBOOT,		/* another elf state */
+	TRYE64BOOT,		/* another elf state */
 	INIT9LOAD,
 	READ9LOAD,
 	FAILED
@@ -511,6 +521,7 @@ struct Boot {
 	int state;
 
 	Exechdr hdr;
+	uvlong	entry;
 
 	char *bp;	/* base ptr */
 	char *wp;	/* write ptr */

+ 7 - 0
sys/src/cmd/pcc.c

@@ -83,6 +83,7 @@ main(int argc, char *argv[])
 		case 'S':
 		case 'T':
 		case 'V':
+		case 'W':
 			append(&cc, smprint("-%c", ARGC()));
 			break;
 		case 's':
@@ -112,6 +113,12 @@ main(int argc, char *argv[])
 			if(strcmp(ot->name, "arm") == 0)
 				append(&ldargs, "-f");
 			break;
+		case 'x':
+			s = ARGF();
+			if(s == nil || *s == '-')
+				fatal("no -x argument");
+			append(&ldargs, smprint("-x %s", s));
+			break;
 		case 'a':
 			/* hacky look inside ARGBEGIN insides, to see if we have -aa */
 			if(*_args == 'a') {