summaryrefslogtreecommitdiff
path: root/sys/src/9/port/rebootcmd.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /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-xsys/src/9/port/rebootcmd.c100
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!");
+}