diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/9/port/rebootcmd.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/9/port/rebootcmd.c')
-rwxr-xr-x | sys/src/9/port/rebootcmd.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/sys/src/9/port/rebootcmd.c b/sys/src/9/port/rebootcmd.c new file mode 100755 index 000000000..591864903 --- /dev/null +++ b/sys/src/9/port/rebootcmd.c @@ -0,0 +1,100 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#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]; +} + + +static void +readn(Chan *c, void *vp, long n) +{ + char *p = vp; + long nn; + + while(n > 0) { + nn = devtab[c->type]->read(c, p, n, c->offset); + if(nn == 0) + error(Eshort); + c->offset += nn; + p += nn; + n -= nn; + } +} + +static void +setbootcmd(int argc, char *argv[]) +{ + char *buf, *p, *ep; + int i; + + buf = malloc(1024); + if(buf == nil) + error(Enomem); + p = buf; + ep = buf + 1024; + for(i=0; i<argc; i++) + p = seprint(p, ep, "%q ", argv[i]); + *p = 0; + ksetenv("bootcmd", buf, 1); + free(buf); +} + +void +rebootcmd(int argc, char *argv[]) +{ + Chan *c; + Exec exec; + ulong magic, text, rtext, entry, data, size; + uchar *p; + + if(argc == 0) + exit(0); + + c = namec(argv[0], Aopen, OEXEC, 0); + if(waserror()){ + cclose(c); + nexterror(); + } + + 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) + error(Ebadexec); + + /* round text out to page boundary */ + rtext = PGROUND(entry+text)-entry; + size = rtext + data; + p = malloc(size); + if(p == nil) + error(Enomem); + + if(waserror()){ + free(p); + nexterror(); + } + + memset(p, 0, size); + readn(c, p, text); + readn(c, p + rtext, data); + + ksetenv("bootfile", argv[0], 1); + setbootcmd(argc-1, argv+1); + + reboot((void*)entry, p, size); + + panic("return from reboot!"); +} |