xref: /inferno-os/os/boot/rpcg/plan9boot.c (revision 4eb166cf184c1f102fb79e31b1465ea3e2021c39)
1 #include	"u.h"
2 #include	"lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 
7 char *premature = "premature EOF\n";
8 
9 /*
10  *  read in a segment
11  */
12 static long
13 readseg(int dev, long (*read)(int, void*, long), long len, long addr)
14 {
15 	char *a;
16 	long n, sofar;
17 
18 	a = (char *)addr;
19 	for(sofar = 0; sofar < len; sofar += n){
20 		n = 8*1024;
21 		if(len - sofar < n)
22 			n = len - sofar;
23 		n = (*read)(dev, a + sofar, n);
24 		if(n <= 0)
25 			break;
26 		print(".");
27 	}
28 	return sofar;
29 }
30 
31 /*
32  *  boot
33  */
34 int
35 plan9boot(int dev, long (*seek)(int, long), long (*read)(int, void*, long))
36 {
37 	long n;
38 	long addr;
39 	void (*b)(void);
40 	Exec *ep;
41 
42 	if((*seek)(dev, 0) < 0)
43 		return -1;
44 
45 	/*
46 	 *  read header
47 	 */
48 	ep = (Exec *) ialloc(sizeof(Exec), 0);
49 	n = sizeof(Exec);
50 	if(readseg(dev, read, n, (long) ep) != n){
51 		print(premature);
52 		return -1;
53 	}
54 	if(GLLONG(ep->magic) != Q_MAGIC){
55 		print("bad magic 0x%lux not a plan 9 executable!\n", GLLONG(ep->magic));
56 		return -1;
57 	}
58 
59 	/*
60 	 *  read text
61 	 */
62 	addr = PADDR(GLLONG(ep->entry));
63 	n = GLLONG(ep->text);
64 	print("%d", n);
65 	if(readseg(dev, read, n, addr) != n){
66 		print(premature);
67 		return -1;
68 	}
69 
70 	/*
71 	 *  read data (starts at first page after kernel)
72 	 */
73 	addr = PGROUND(addr+n);
74 	n = GLLONG(ep->data);
75 	print("+%d@%8.8lux", n, addr);
76 	if(readseg(dev, read, n, addr) != n){
77 		print(premature);
78 		return -1;
79 	}
80 
81 	/*
82 	 *  bss and entry point
83 	 */
84 	print("+%d\nstart at 0x%lux\n", GLLONG(ep->bss), GLLONG(ep->entry));
85 	uartwait();
86 	scc2stop();
87 	splhi();
88 
89 	/*
90 	 *  Go to new code. It's up to the program to get its PC relocated to
91 	 *  the right place.
92 	 */
93 	b = (void (*)(void))(PADDR(GLLONG(ep->entry)));
94 	(*b)();
95 	return 0;
96 }
97