19ef1f84bSDavid du Colombier #include "u.h"
29ef1f84bSDavid du Colombier #include "../port/lib.h"
39ef1f84bSDavid du Colombier #include "mem.h"
49ef1f84bSDavid du Colombier #include "dat.h"
59ef1f84bSDavid du Colombier #include "fns.h"
69ef1f84bSDavid du Colombier #include "../port/error.h"
79ef1f84bSDavid du Colombier
89ef1f84bSDavid du Colombier #include <a.out.h>
9*406c76faSDavid du Colombier #include "/sys/src/libmach/elf.h"
109ef1f84bSDavid du Colombier
11*406c76faSDavid du Colombier enum {
12*406c76faSDavid du Colombier Ehdr32sz = 52,
13*406c76faSDavid du Colombier Phdr32sz = 32,
14*406c76faSDavid du Colombier Shdr32sz = 40,
159ef1f84bSDavid du Colombier
16*406c76faSDavid du Colombier Ehdr64sz = 64,
17*406c76faSDavid du Colombier Phdr64sz = 56,
18*406c76faSDavid du Colombier Shdr64sz = 64,
19*406c76faSDavid du Colombier };
209ef1f84bSDavid du Colombier
21*406c76faSDavid du Colombier static uchar elfident[] = {
22*406c76faSDavid du Colombier '\177', 'E', 'L', 'F',
23*406c76faSDavid du Colombier };
249ef1f84bSDavid du Colombier
25*406c76faSDavid du Colombier void
readn(Chan * c,void * vp,long n)269ef1f84bSDavid du Colombier readn(Chan *c, void *vp, long n)
279ef1f84bSDavid du Colombier {
289ef1f84bSDavid du Colombier char *p;
299ef1f84bSDavid du Colombier long nn;
309ef1f84bSDavid du Colombier
319ef1f84bSDavid du Colombier p = vp;
329ef1f84bSDavid du Colombier while(n > 0) {
339ef1f84bSDavid du Colombier nn = c->dev->read(c, p, n, c->offset);
349ef1f84bSDavid du Colombier if(nn == 0)
359ef1f84bSDavid du Colombier error(Eshort);
369ef1f84bSDavid du Colombier c->offset += nn;
379ef1f84bSDavid du Colombier p += nn;
389ef1f84bSDavid du Colombier n -= nn;
399ef1f84bSDavid du Colombier }
409ef1f84bSDavid du Colombier }
419ef1f84bSDavid du Colombier
42*406c76faSDavid du Colombier /* assume the elf header is in the byte order of this machine */
43*406c76faSDavid du Colombier int
readelfhdr(Chan * c,ulong,Execvals * evp)44*406c76faSDavid du Colombier readelfhdr(Chan *c, ulong, Execvals *evp)
45*406c76faSDavid du Colombier {
46*406c76faSDavid du Colombier Ehdr ehdr;
47*406c76faSDavid du Colombier Phdr phdrs[3];
48*406c76faSDavid du Colombier
49*406c76faSDavid du Colombier c->offset = 0; /* back up */
50*406c76faSDavid du Colombier readn(c, &ehdr, sizeof ehdr);
51*406c76faSDavid du Colombier if(memcmp(&ehdr.ident[MAG0], elfident, sizeof elfident) != 0 ||
52*406c76faSDavid du Colombier ehdr.ident[CLASS] != ELFCLASS32)
53*406c76faSDavid du Colombier return -1;
54*406c76faSDavid du Colombier
55*406c76faSDavid du Colombier /* get textsize and datasize from Phdrs */
56*406c76faSDavid du Colombier readn(c, phdrs, sizeof phdrs);
57*406c76faSDavid du Colombier evp->entry = ehdr.elfentry;
58*406c76faSDavid du Colombier evp->textsize = phdrs[0].filesz;
59*406c76faSDavid du Colombier evp->datasize = phdrs[1].filesz;
60*406c76faSDavid du Colombier c->offset = ROUNDUP(Ehdr32sz + 3*Phdr32sz, 16); /* position for text */
61*406c76faSDavid du Colombier return 0;
62*406c76faSDavid du Colombier }
63*406c76faSDavid du Colombier
64*406c76faSDavid du Colombier static int
readelf64hdr(Chan * c,ulong,Execvals * evp)65*406c76faSDavid du Colombier readelf64hdr(Chan *c, ulong, Execvals *evp)
66*406c76faSDavid du Colombier {
67*406c76faSDavid du Colombier E64hdr ehdr;
68*406c76faSDavid du Colombier P64hdr phdrs[3];
69*406c76faSDavid du Colombier
70*406c76faSDavid du Colombier c->offset = 0; /* back up */
71*406c76faSDavid du Colombier readn(c, &ehdr, sizeof ehdr);
72*406c76faSDavid du Colombier if(memcmp(&ehdr.ident[MAG0], elfident, sizeof elfident) != 0 ||
73*406c76faSDavid du Colombier ehdr.ident[CLASS] != ELFCLASS64)
74*406c76faSDavid du Colombier return -1;
75*406c76faSDavid du Colombier
76*406c76faSDavid du Colombier /* get textsize and datasize from Phdrs */
77*406c76faSDavid du Colombier readn(c, phdrs, sizeof phdrs);
78*406c76faSDavid du Colombier evp->entry = ehdr.elfentry;
79*406c76faSDavid du Colombier evp->textsize = phdrs[0].filesz;
80*406c76faSDavid du Colombier evp->datasize = phdrs[1].filesz;
81*406c76faSDavid du Colombier c->offset = ROUNDUP(Ehdr64sz + 3*Phdr64sz, 16); /* position for text */
82*406c76faSDavid du Colombier return 0;
83*406c76faSDavid du Colombier }
84*406c76faSDavid du Colombier
859ef1f84bSDavid du Colombier static void
setbootcmd(int argc,char * argv[])869ef1f84bSDavid du Colombier setbootcmd(int argc, char *argv[])
879ef1f84bSDavid du Colombier {
889ef1f84bSDavid du Colombier char *buf, *p, *ep;
899ef1f84bSDavid du Colombier int i;
909ef1f84bSDavid du Colombier
919ef1f84bSDavid du Colombier buf = malloc(1024);
929ef1f84bSDavid du Colombier if(buf == nil)
939ef1f84bSDavid du Colombier error(Enomem);
949ef1f84bSDavid du Colombier p = buf;
959ef1f84bSDavid du Colombier ep = buf + 1024;
969ef1f84bSDavid du Colombier for(i=0; i<argc; i++)
979ef1f84bSDavid du Colombier p = seprint(p, ep, "%q ", argv[i]);
989ef1f84bSDavid du Colombier *p = 0;
999ef1f84bSDavid du Colombier ksetenv("bootcmd", buf, 1);
1009ef1f84bSDavid du Colombier free(buf);
1019ef1f84bSDavid du Colombier }
1029ef1f84bSDavid du Colombier
1039ef1f84bSDavid du Colombier void
rebootcmd(int argc,char * argv[])1049ef1f84bSDavid du Colombier rebootcmd(int argc, char *argv[])
1059ef1f84bSDavid du Colombier {
1069ef1f84bSDavid du Colombier Chan *c;
1079ef1f84bSDavid du Colombier Exec exec;
108*406c76faSDavid du Colombier Execvals ev;
1099ef1f84bSDavid du Colombier ulong magic, text, rtext, entry, data, size;
1109ef1f84bSDavid du Colombier uchar *p;
1119ef1f84bSDavid du Colombier
1129ef1f84bSDavid du Colombier if(argc == 0)
1139ef1f84bSDavid du Colombier exit(0);
1149ef1f84bSDavid du Colombier
1159ef1f84bSDavid du Colombier c = namec(argv[0], Aopen, OEXEC, 0);
1169ef1f84bSDavid du Colombier if(waserror()){
1179ef1f84bSDavid du Colombier cclose(c);
1189ef1f84bSDavid du Colombier nexterror();
1199ef1f84bSDavid du Colombier }
1209ef1f84bSDavid du Colombier
1219ef1f84bSDavid du Colombier readn(c, &exec, sizeof(Exec));
1229ef1f84bSDavid du Colombier magic = l2be(exec.magic);
123*406c76faSDavid du Colombier /*
124*406c76faSDavid du Colombier * AOUT_MAGIC is sometimes defined like this:
125*406c76faSDavid du Colombier * #define AOUT_MAGIC V_MAGIC || magic==M_MAGIC
126*406c76faSDavid du Colombier * so we can only use it in a fairly stylized manner.
127*406c76faSDavid du Colombier */
128*406c76faSDavid du Colombier if(magic == AOUT_MAGIC) {
1299ef1f84bSDavid du Colombier entry = l2be(exec.entry);
1309ef1f84bSDavid du Colombier text = l2be(exec.text);
1319ef1f84bSDavid du Colombier data = l2be(exec.data);
132*406c76faSDavid du Colombier } else if(parseboothdr && (*parseboothdr)(c, magic, &ev) >= 0 ||
133*406c76faSDavid du Colombier readelfhdr(c, magic, &ev) >= 0 ||
134*406c76faSDavid du Colombier readelf64hdr(c, magic, &ev) >= 0){
135*406c76faSDavid du Colombier entry = ev.entry;
136*406c76faSDavid du Colombier text = ev.textsize;
137*406c76faSDavid du Colombier data = ev.datasize;
138*406c76faSDavid du Colombier } else {
1399ef1f84bSDavid du Colombier error(Ebadexec);
140*406c76faSDavid du Colombier return; /* for the compiler */
141*406c76faSDavid du Colombier }
1429ef1f84bSDavid du Colombier
1439ef1f84bSDavid du Colombier /* round text out to page boundary */
1449ef1f84bSDavid du Colombier rtext = ROUNDUP(entry+text, PGSZ)-entry;
1459ef1f84bSDavid du Colombier size = rtext + data;
1469ef1f84bSDavid du Colombier p = malloc(size);
1479ef1f84bSDavid du Colombier if(p == nil)
1489ef1f84bSDavid du Colombier error(Enomem);
1499ef1f84bSDavid du Colombier
1509ef1f84bSDavid du Colombier if(waserror()){
1519ef1f84bSDavid du Colombier free(p);
1529ef1f84bSDavid du Colombier nexterror();
1539ef1f84bSDavid du Colombier }
1549ef1f84bSDavid du Colombier
1559ef1f84bSDavid du Colombier memset(p, 0, size);
1569ef1f84bSDavid du Colombier readn(c, p, text);
1579ef1f84bSDavid du Colombier readn(c, p + rtext, data);
1589ef1f84bSDavid du Colombier
1599ef1f84bSDavid du Colombier ksetenv("bootfile", argv[0], 1);
1609ef1f84bSDavid du Colombier setbootcmd(argc-1, argv+1);
1619ef1f84bSDavid du Colombier
1629ef1f84bSDavid du Colombier reboot((void*)entry, p, size);
1639ef1f84bSDavid du Colombier
1649ef1f84bSDavid du Colombier panic("return from reboot!");
1659ef1f84bSDavid du Colombier }
166