]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/rebootcmd.c
kernel: use 64-bit virtual entry point for expanded header, document behaviour in...
[plan9front.git] / sys / src / 9 / port / rebootcmd.c
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 void
10 readn(Chan *c, void *vp, long n)
11 {
12         char *p = vp;
13         long nn;
14
15         while(n > 0) {
16                 nn = devtab[c->type]->read(c, p, n, c->offset);
17                 if(nn == 0)
18                         error(Eshort);
19                 c->offset += nn;
20                 p += nn;
21                 n -= nn;
22         }
23 }
24
25 void
26 rebootcmd(int argc, char *argv[])
27 {
28         struct {
29                 Exec;
30                 uvlong  hdr[1];
31         } ehdr;
32         Chan *c;
33         ulong magic, text, rtext, entry, data, size, align;
34         uchar *p;
35
36         if(argc == 0)
37                 exit(0);
38
39         c = namec(argv[0], Aopen, OEXEC, 0);
40         if(waserror()){
41                 cclose(c);
42                 nexterror();
43         }
44
45         readn(c, &ehdr, sizeof(Exec));
46         magic = beswal(ehdr.magic);
47         entry = beswal(ehdr.entry);
48         text = beswal(ehdr.text);
49         data = beswal(ehdr.data);
50
51         if(!(magic == AOUT_MAGIC)){
52                 switch(magic){
53                 case I_MAGIC:
54                 case S_MAGIC:
55                         if((I_MAGIC == AOUT_MAGIC) || (S_MAGIC == AOUT_MAGIC))
56                                 break;
57                 default:
58                         error(Ebadexec);
59                 }
60         }
61         if(magic & HDR_MAGIC)
62                 readn(c, ehdr.hdr, sizeof(ehdr.hdr));
63
64         switch(magic){
65         case R_MAGIC:
66                 align = 0x10000;        /* 64k segment alignment for arm64 */
67                 break;
68         default:
69                 align = BY2PG;
70                 break;
71         }
72
73         /* round text out to page boundary */
74         rtext = ROUND(entry+text, align)-entry;
75         size = rtext + data;
76         p = malloc(size);
77         if(p == nil)
78                 error(Enomem);
79
80         if(waserror()){
81                 free(p);
82                 nexterror();
83         }
84
85         memset(p, 0, size);
86         readn(c, p, text);
87         readn(c, p + rtext, data);
88
89         ksetenv("bootfile", argv[0], 1);
90
91         reboot((void*)entry, p, size);
92         error(Egreg);
93 }