xref: /inferno-os/os/boot/rpcg/plan9boot.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
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