allow /dev/reboot to handle elf executables, from sources. i'm guessing that this is motivated by the boot loader on the mikrotek routerboard. Reference: /n/atom/patch/applied2013/rebootelf Date: Wed Jul 31 20:55:39 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/port/portdat.h Wed Jul 31 20:54:13 2013 +++ /sys/src/9/port/portdat.h Wed Jul 31 20:54:14 2013 @@ -9,6 +9,7 @@ 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; @@ -761,6 +762,12 @@ 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; @@ -774,6 +781,7 @@ extern Ref noteidalloc; extern int nsyscall; extern Palloc palloc; + int (*parseboothdr)(Chan *, ulong, Execvals *); extern Queue* serialoq; extern char* statename[]; extern Image swapimage; --- /sys/src/9/port/rebootcmd.c Wed Jul 31 20:54:15 2013 +++ /sys/src/9/port/rebootcmd.c Wed Jul 31 20:54:15 2013 @@ -4,19 +4,24 @@ #include "dat.h" #include "fns.h" #include "../port/error.h" -#include "a.out.h" - -static ulong -l2be(long l) -{ - uchar *cp; - - cp = (uchar*)&l; - return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3]; -} +#include +#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', +}; -static void +void readn(Chan *c, void *vp, long n) { char *p = vp; @@ -32,6 +37,49 @@ } } +/* assume the elf header is in the byte order of this machine */ +static 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[]) { @@ -55,6 +103,7 @@ { Chan *c; Exec exec; + Execvals ev; ulong magic, text, rtext, entry, data, size; uchar *p; @@ -69,11 +118,25 @@ readn(c, &exec, sizeof(Exec)); magic = l2be(exec.magic); - entry = l2be(exec.entry); - text = l2be(exec.text); - data = l2be(exec.data); - if(magic != AOUT_MAGIC) + /* + * AOUT_MAGIC is sometimes defined like this: + * #define AOUT_MAGIC V_MAGIC || magic==M_MAGIC + * so we can only use it in a fairly stylized manner. + */ + if(magic == AOUT_MAGIC) { + entry = l2be(exec.entry); + text = l2be(exec.text); + data = l2be(exec.data); + } 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 */ + } /* round text out to page boundary */ rtext = PGROUND(entry+text)-entry; --- /sys/src/9/port/sysproc.c Wed Jul 31 20:54:17 2013 +++ /sys/src/9/port/sysproc.c Wed Jul 31 20:54:18 2013 @@ -205,7 +205,7 @@ return pid; } -static ulong +ulong l2be(long l) { uchar *cp; --- /sys/src/9/port/portfns.h Wed Jul 31 20:54:19 2013 +++ /sys/src/9/port/portfns.h Wed Jul 31 20:54:20 2013 @@ -154,6 +154,7 @@ void ksetenv(char*, char*, int); void kstrcpy(char*, char*, int); void kstrdup(char**, char*); +ulong l2be(long); long latin1(Rune*, int); int lock(Lock*); void logopen(Log*); @@ -298,6 +299,7 @@ void randominit(void); ulong randomread(void*, ulong); void rdb(void); +void readn(Chan *, void *, long); int readnum(ulong, char*, ulong, ulong, int); int readstr(ulong, char*, ulong, char*); void ready(Proc*);