Browse Source

Plan 9 from Bell Labs 2013-07-20

David du Colombier 10 years ago
parent
commit
f1da97ef0f
5 changed files with 83 additions and 10 deletions
  1. 2 2
      rc/bin/fshalt
  2. 6 0
      sys/man/3/cons
  3. 2 2
      sys/man/8/booting
  4. 8 1
      sys/src/9/port/portdat.h
  5. 65 5
      sys/src/9/port/rebootcmd.c

+ 2 - 2
rc/bin/fshalt

@@ -44,8 +44,8 @@ if (test -e '#v/vgactl' && test -e '#P/realmode') {
 }
 
 fn isbootable {
-	# on mips (for example), kernels are now a.out format
-	test -e $1 && ~ `{file $1} *' plan 9 boot image' *' plan 9 executable'*
+	test -e $1 && ~ `{file $1} *' plan 9 boot image' \
+		*' plan 9 executable'* *ELF*' executable'
 }
 fn usekernel {
 	kerncopy=kern

+ 6 - 0
sys/man/3/cons

@@ -207,6 +207,12 @@ variable is set to
 .IR kernelpath .
 Only the host
 owner has the ability to open this file.
+The named kernel may be a Plan 9 executable or
+a 32-bit or 64-bit ELF executable.
+On some architectures
+(e.g.,
+.BR mips ),
+it may also be a Plan 9 boot image.
 .PP
 .B Bintime
 is a binary interface that provides

+ 2 - 2
sys/man/8/booting

@@ -70,8 +70,8 @@ or
 .
 .SS MIPS Routerboard CPU Server
 Configure RouterBOOT via the serial port (115200 baud)
-to always boot from Ethernet, and arrange to load
-.B /mips/9rb.elf
+to always boot from Ethernet, and arrange to load the ELF executable
+.B /mips/9rb
 in
 .IR ndb (6).
 .

+ 8 - 1
sys/src/9/port/portdat.h

@@ -9,6 +9,7 @@ typedef struct Dirtab	Dirtab;
 typedef struct Edf	Edf;
 typedef struct Egrp	Egrp;
 typedef struct Evalue	Evalue;
+typedef struct Execvals	Execvals;
 typedef struct Fgrp	Fgrp;
 typedef struct DevConf	DevConf;
 typedef struct Image	Image;
@@ -797,6 +798,12 @@ enum
 	READSTR =	4000,		/* temporary buffer size for device reads */
 };
 
+struct Execvals {
+	uvlong	entry;
+	ulong	textsize;
+	ulong	datasize;
+};
+
 extern	Conf	conf;
 extern	char*	conffile;
 extern	int	cpuserver;
@@ -810,7 +817,7 @@ extern	Queue*	kprintoq;
 extern 	Ref	noteidalloc;
 extern	int	nsyscall;
 extern	Palloc	palloc;
-	int	(*parseboothdr)(Chan *, ulong, ulong [3]);
+	int	(*parseboothdr)(Chan *, ulong, Execvals *);
 extern	Queue*	serialoq;
 extern	char*	statename[];
 extern	Image	swapimage;

+ 65 - 5
sys/src/9/port/rebootcmd.c

@@ -5,6 +5,21 @@
 #include	"fns.h"
 #include	"../port/error.h"
 #include	<a.out.h>
+#include 	"/sys/src/libmach/elf.h"
+
+enum {
+	Ehdr32sz	= 52,
+	Phdr32sz	= 32,
+	Shdr32sz	= 40,
+
+	Ehdr64sz	= 64,
+	Phdr64sz	= 56,
+	Shdr64sz	= 64,
+};
+
+static uchar elfident[] = {
+	'\177', 'E', 'L', 'F',
+};
 
 void
 readn(Chan *c, void *vp, long n)
@@ -22,6 +37,49 @@ readn(Chan *c, void *vp, long n)
 	}
 }
 
+/* assume the elf header is in the byte order of this machine */
+int
+readelfhdr(Chan *c, ulong, Execvals *evp)
+{
+	Ehdr ehdr;
+	Phdr phdrs[3];
+
+	c->offset = 0;			/* back up */
+	readn(c, &ehdr, sizeof ehdr);
+	if(memcmp(&ehdr.ident[MAG0], elfident, sizeof elfident) != 0 ||
+	    ehdr.ident[CLASS] != ELFCLASS32)
+		return -1;
+
+	/* get textsize and datasize from Phdrs */
+	readn(c, phdrs, sizeof phdrs);
+	evp->entry = ehdr.elfentry;
+	evp->textsize = phdrs[0].filesz;
+	evp->datasize = phdrs[1].filesz;
+	c->offset = ROUNDUP(Ehdr32sz + 3*Phdr32sz, 16);	/* position for text */
+	return 0;
+}
+
+static int
+readelf64hdr(Chan *c, ulong, Execvals *evp)
+{
+	E64hdr ehdr;
+	P64hdr phdrs[3];
+
+	c->offset = 0;			/* back up */
+	readn(c, &ehdr, sizeof ehdr);
+	if(memcmp(&ehdr.ident[MAG0], elfident, sizeof elfident) != 0 ||
+	    ehdr.ident[CLASS] != ELFCLASS64)
+		return -1;
+
+	/* get textsize and datasize from Phdrs */
+	readn(c, phdrs, sizeof phdrs);
+	evp->entry = ehdr.elfentry;
+	evp->textsize = phdrs[0].filesz;
+	evp->datasize = phdrs[1].filesz;
+	c->offset = ROUNDUP(Ehdr64sz + 3*Phdr64sz, 16);	/* position for text */
+	return 0;
+}
+
 static void
 setbootcmd(int argc, char *argv[])
 {
@@ -45,8 +103,8 @@ rebootcmd(int argc, char *argv[])
 {
 	Chan *c;
 	Exec exec;
+	Execvals ev;
 	ulong magic, text, rtext, entry, data, size;
-	ulong sizes[3];
 	uchar *p;
 
 	if(argc == 0)
@@ -69,10 +127,12 @@ rebootcmd(int argc, char *argv[])
 		entry = l2be(exec.entry);
 		text = l2be(exec.text);
 		data = l2be(exec.data);
-	} else if(parseboothdr && (*parseboothdr)(c, magic, sizes) >= 0){
-		entry = sizes[0];
-		text = sizes[1];
-		data = sizes[2];
+	} else if(parseboothdr && (*parseboothdr)(c, magic, &ev) >= 0 ||
+	    readelfhdr(c, magic, &ev) >= 0 ||
+	    readelf64hdr(c, magic, &ev) >= 0){
+		entry = ev.entry;
+		text = ev.textsize;
+		data = ev.datasize;
 	} else {
 		error(Ebadexec);
 		return;				/* for the compiler */