xref: /plan9/sys/src/9/port/rebootcmd.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1 #include	"u.h"
2 #include	"../port/lib.h"
3 #include	"mem.h"
4 #include	"dat.h"
5 #include	"fns.h"
6 #include	"../port/error.h"
7 #include	"a.out.h"
8 
9 static ulong
10 l2be(long l)
11 {
12 	uchar *cp;
13 
14 	cp = (uchar*)&l;
15 	return (cp[0]<<24) | (cp[1]<<16) | (cp[2]<<8) | cp[3];
16 }
17 
18 
19 static void
20 readn(Chan *c, void *vp, long n)
21 {
22 	char *p = vp;
23 	long nn;
24 
25 	while(n > 0) {
26 		nn = devtab[c->type]->read(c, p, n, c->offset);
27 		if(nn == 0)
28 			error(Eshort);
29 		c->offset += nn;
30 		p += nn;
31 		n -= nn;
32 	}
33 }
34 
35 static void
36 setbootcmd(int argc, char *argv[])
37 {
38 	char *buf, *p, *ep;
39 	int i;
40 
41 	buf = malloc(1024);
42 	if(buf == nil)
43 		error(Enomem);
44 	p = buf;
45 	ep = buf + 1024;
46 	for(i=0; i<argc; i++)
47 		p = seprint(p, ep, "%q ", argv[i]);
48 	*p = 0;
49 	ksetenv("bootcmd", buf, 1);
50 	free(buf);
51 }
52 
53 void
54 rebootcmd(int argc, char *argv[])
55 {
56 	Chan *c;
57 	Exec exec;
58 	ulong magic, text, rtext, entry, data, size;
59 	uchar *p;
60 
61 	if(argc == 0)
62 		exit(0);
63 
64 	c = namec(argv[0], Aopen, OEXEC, 0);
65 	if(waserror()){
66 		cclose(c);
67 		nexterror();
68 	}
69 
70 	readn(c, &exec, sizeof(Exec));
71 	magic = l2be(exec.magic);
72 	entry = l2be(exec.entry);
73 	text = l2be(exec.text);
74 	data = l2be(exec.data);
75 	if(magic != AOUT_MAGIC)
76 		error(Ebadexec);
77 
78 	/* round text out to page boundary */
79 	rtext = PGROUND(entry+text)-entry;
80 	size = rtext + data;
81 	p = malloc(size);
82 	if(p == nil)
83 		error(Enomem);
84 
85 	if(waserror()){
86 		free(p);
87 		nexterror();
88 	}
89 
90 	memset(p, 0, size);
91 	readn(c, p, text);
92 	readn(c, p + rtext, data);
93 
94 	ksetenv("bootfile", argv[0], 1);
95 	setbootcmd(argc-1, argv+1);
96 
97 	reboot((void*)entry, p, size);
98 
99 	panic("return from reboot!");
100 }
101