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