summaryrefslogtreecommitdiff
path: root/os/boot/rpcg/plan9boot.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/boot/rpcg/plan9boot.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/boot/rpcg/plan9boot.c')
-rw-r--r--os/boot/rpcg/plan9boot.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/os/boot/rpcg/plan9boot.c b/os/boot/rpcg/plan9boot.c
new file mode 100644
index 00000000..047474e3
--- /dev/null
+++ b/os/boot/rpcg/plan9boot.c
@@ -0,0 +1,96 @@
+#include "u.h"
+#include "lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+
+char *premature = "premature EOF\n";
+
+/*
+ * read in a segment
+ */
+static long
+readseg(int dev, long (*read)(int, void*, long), long len, long addr)
+{
+ char *a;
+ long n, sofar;
+
+ a = (char *)addr;
+ for(sofar = 0; sofar < len; sofar += n){
+ n = 8*1024;
+ if(len - sofar < n)
+ n = len - sofar;
+ n = (*read)(dev, a + sofar, n);
+ if(n <= 0)
+ break;
+ print(".");
+ }
+ return sofar;
+}
+
+/*
+ * boot
+ */
+int
+plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
+{
+ long n;
+ long addr;
+ void (*b)(void);
+ Exec *ep;
+
+ if((*seek)(dev, 0) < 0)
+ return -1;
+
+ /*
+ * read header
+ */
+ ep = (Exec *) ialloc(sizeof(Exec), 0);
+ n = sizeof(Exec);
+ if(readseg(dev, read, n, (long) ep) != n){
+ print(premature);
+ return -1;
+ }
+ if(GLLONG(ep->magic) != Q_MAGIC){
+ print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
+ return -1;
+ }
+
+ /*
+ * read text
+ */
+ addr = PADDR(GLLONG(ep->entry));
+ n = GLLONG(ep->text);
+ print("%d", n);
+ if(readseg(dev, read, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * read data (starts at first page after kernel)
+ */
+ addr = PGROUND(addr+n);
+ n = GLLONG(ep->data);
+ print("+%d@%8.8lux", n, addr);
+ if(readseg(dev, read, n, addr) != n){
+ print(premature);
+ return -1;
+ }
+
+ /*
+ * bss and entry point
+ */
+ print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
+ uartwait();
+ scc2stop();
+ splhi();
+
+ /*
+ * Go to new code. It's up to the program to get its PC relocated to
+ * the right place.
+ */
+ b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
+ (*b)();
+ return 0;
+}