19a747e4fSDavid du Colombier #include "u.h"
29a747e4fSDavid du Colombier #include "../port/lib.h"
39a747e4fSDavid du Colombier #include "mem.h"
49a747e4fSDavid du Colombier #include "dat.h"
59a747e4fSDavid du Colombier #include "fns.h"
69a747e4fSDavid du Colombier #include "../port/error.h"
75482313dSDavid du Colombier #include <a.out.h>
8*15bfe97dSDavid du Colombier #include "/sys/src/libmach/elf.h"
9*15bfe97dSDavid du Colombier
10*15bfe97dSDavid du Colombier enum {
11*15bfe97dSDavid du Colombier Ehdr32sz = 52,
12*15bfe97dSDavid du Colombier Phdr32sz = 32,
13*15bfe97dSDavid du Colombier Shdr32sz = 40,
14*15bfe97dSDavid du Colombier
15*15bfe97dSDavid du Colombier Ehdr64sz = 64,
16*15bfe97dSDavid du Colombier Phdr64sz = 56,
17*15bfe97dSDavid du Colombier Shdr64sz = 64,
18*15bfe97dSDavid du Colombier };
19*15bfe97dSDavid du Colombier
20*15bfe97dSDavid du Colombier static uchar elfident[] = {
21*15bfe97dSDavid du Colombier '\177', 'E', 'L', 'F',
22*15bfe97dSDavid du Colombier };
239a747e4fSDavid du Colombier
245482313dSDavid du Colombier void
readn(Chan * c,void * vp,long n)259a747e4fSDavid du Colombier readn(Chan *c, void *vp, long n)
269a747e4fSDavid du Colombier {
279a747e4fSDavid du Colombier char *p = vp;
289a747e4fSDavid du Colombier long nn;
299a747e4fSDavid du Colombier
309a747e4fSDavid du Colombier while(n > 0) {
319a747e4fSDavid du Colombier nn = devtab[c->type]->read(c, p, n, c->offset);
329a747e4fSDavid du Colombier if(nn == 0)
339a747e4fSDavid du Colombier error(Eshort);
349a747e4fSDavid du Colombier c->offset += nn;
359a747e4fSDavid du Colombier p += nn;
369a747e4fSDavid du Colombier n -= nn;
379a747e4fSDavid du Colombier }
389a747e4fSDavid du Colombier }
399a747e4fSDavid du Colombier
40*15bfe97dSDavid du Colombier /* assume the elf header is in the byte order of this machine */
41*15bfe97dSDavid du Colombier int
readelfhdr(Chan * c,ulong,Execvals * evp)42*15bfe97dSDavid du Colombier readelfhdr(Chan *c, ulong, Execvals *evp)
43*15bfe97dSDavid du Colombier {
44*15bfe97dSDavid du Colombier Ehdr ehdr;
45*15bfe97dSDavid du Colombier Phdr phdrs[3];
46*15bfe97dSDavid du Colombier
47*15bfe97dSDavid du Colombier c->offset = 0; /* back up */
48*15bfe97dSDavid du Colombier readn(c, &ehdr, sizeof ehdr);
49*15bfe97dSDavid du Colombier if(memcmp(&ehdr.ident[MAG0], elfident, sizeof elfident) != 0 ||
50*15bfe97dSDavid du Colombier ehdr.ident[CLASS] != ELFCLASS32)
51*15bfe97dSDavid du Colombier return -1;
52*15bfe97dSDavid du Colombier
53*15bfe97dSDavid du Colombier /* get textsize and datasize from Phdrs */
54*15bfe97dSDavid du Colombier readn(c, phdrs, sizeof phdrs);
55*15bfe97dSDavid du Colombier evp->entry = ehdr.elfentry;
56*15bfe97dSDavid du Colombier evp->textsize = phdrs[0].filesz;
57*15bfe97dSDavid du Colombier evp->datasize = phdrs[1].filesz;
58*15bfe97dSDavid du Colombier c->offset = ROUNDUP(Ehdr32sz + 3*Phdr32sz, 16); /* position for text */
59*15bfe97dSDavid du Colombier return 0;
60*15bfe97dSDavid du Colombier }
61*15bfe97dSDavid du Colombier
62*15bfe97dSDavid du Colombier static int
readelf64hdr(Chan * c,ulong,Execvals * evp)63*15bfe97dSDavid du Colombier readelf64hdr(Chan *c, ulong, Execvals *evp)
64*15bfe97dSDavid du Colombier {
65*15bfe97dSDavid du Colombier E64hdr ehdr;
66*15bfe97dSDavid du Colombier P64hdr phdrs[3];
67*15bfe97dSDavid du Colombier
68*15bfe97dSDavid du Colombier c->offset = 0; /* back up */
69*15bfe97dSDavid du Colombier readn(c, &ehdr, sizeof ehdr);
70*15bfe97dSDavid du Colombier if(memcmp(&ehdr.ident[MAG0], elfident, sizeof elfident) != 0 ||
71*15bfe97dSDavid du Colombier ehdr.ident[CLASS] != ELFCLASS64)
72*15bfe97dSDavid du Colombier return -1;
73*15bfe97dSDavid du Colombier
74*15bfe97dSDavid du Colombier /* get textsize and datasize from Phdrs */
75*15bfe97dSDavid du Colombier readn(c, phdrs, sizeof phdrs);
76*15bfe97dSDavid du Colombier evp->entry = ehdr.elfentry;
77*15bfe97dSDavid du Colombier evp->textsize = phdrs[0].filesz;
78*15bfe97dSDavid du Colombier evp->datasize = phdrs[1].filesz;
79*15bfe97dSDavid du Colombier c->offset = ROUNDUP(Ehdr64sz + 3*Phdr64sz, 16); /* position for text */
80*15bfe97dSDavid du Colombier return 0;
81*15bfe97dSDavid du Colombier }
82*15bfe97dSDavid du Colombier
839a747e4fSDavid du Colombier static void
setbootcmd(int argc,char * argv[])849a747e4fSDavid du Colombier setbootcmd(int argc, char *argv[])
859a747e4fSDavid du Colombier {
869a747e4fSDavid du Colombier char *buf, *p, *ep;
879a747e4fSDavid du Colombier int i;
889a747e4fSDavid du Colombier
899a747e4fSDavid du Colombier buf = malloc(1024);
909a747e4fSDavid du Colombier if(buf == nil)
919a747e4fSDavid du Colombier error(Enomem);
929a747e4fSDavid du Colombier p = buf;
939a747e4fSDavid du Colombier ep = buf + 1024;
949a747e4fSDavid du Colombier for(i=0; i<argc; i++)
959a747e4fSDavid du Colombier p = seprint(p, ep, "%q ", argv[i]);
969a747e4fSDavid du Colombier *p = 0;
979a747e4fSDavid du Colombier ksetenv("bootcmd", buf, 1);
989a747e4fSDavid du Colombier free(buf);
999a747e4fSDavid du Colombier }
1009a747e4fSDavid du Colombier
1019a747e4fSDavid du Colombier void
rebootcmd(int argc,char * argv[])1029a747e4fSDavid du Colombier rebootcmd(int argc, char *argv[])
1039a747e4fSDavid du Colombier {
1049a747e4fSDavid du Colombier Chan *c;
1059a747e4fSDavid du Colombier Exec exec;
106*15bfe97dSDavid du Colombier Execvals ev;
1079a747e4fSDavid du Colombier ulong magic, text, rtext, entry, data, size;
1089a747e4fSDavid du Colombier uchar *p;
1099a747e4fSDavid du Colombier
1109a747e4fSDavid du Colombier if(argc == 0)
1119a747e4fSDavid du Colombier exit(0);
1129a747e4fSDavid du Colombier
1139a747e4fSDavid du Colombier c = namec(argv[0], Aopen, OEXEC, 0);
1149a747e4fSDavid du Colombier if(waserror()){
1159a747e4fSDavid du Colombier cclose(c);
1169a747e4fSDavid du Colombier nexterror();
1179a747e4fSDavid du Colombier }
1189a747e4fSDavid du Colombier
1199a747e4fSDavid du Colombier readn(c, &exec, sizeof(Exec));
1209a747e4fSDavid du Colombier magic = l2be(exec.magic);
1214e3613abSDavid du Colombier /*
1224e3613abSDavid du Colombier * AOUT_MAGIC is sometimes defined like this:
1234e3613abSDavid du Colombier * #define AOUT_MAGIC V_MAGIC || magic==M_MAGIC
1244e3613abSDavid du Colombier * so we can only use it in a fairly stylized manner.
1254e3613abSDavid du Colombier */
1264e3613abSDavid du Colombier if(magic == AOUT_MAGIC) {
1275482313dSDavid du Colombier entry = l2be(exec.entry);
1285482313dSDavid du Colombier text = l2be(exec.text);
1295482313dSDavid du Colombier data = l2be(exec.data);
130*15bfe97dSDavid du Colombier } else if(parseboothdr && (*parseboothdr)(c, magic, &ev) >= 0 ||
131*15bfe97dSDavid du Colombier readelfhdr(c, magic, &ev) >= 0 ||
132*15bfe97dSDavid du Colombier readelf64hdr(c, magic, &ev) >= 0){
133*15bfe97dSDavid du Colombier entry = ev.entry;
134*15bfe97dSDavid du Colombier text = ev.textsize;
135*15bfe97dSDavid du Colombier data = ev.datasize;
1365482313dSDavid du Colombier } else {
1379a747e4fSDavid du Colombier error(Ebadexec);
1385482313dSDavid du Colombier return; /* for the compiler */
1395482313dSDavid du Colombier }
1409a747e4fSDavid du Colombier
1419a747e4fSDavid du Colombier /* round text out to page boundary */
142a826b788SDavid du Colombier rtext = ROUNDUP(entry+text, BY2PG) - entry;
1439a747e4fSDavid du Colombier size = rtext + data;
1449a747e4fSDavid du Colombier p = malloc(size);
1459a747e4fSDavid du Colombier if(p == nil)
1469a747e4fSDavid du Colombier error(Enomem);
1479a747e4fSDavid du Colombier
1489a747e4fSDavid du Colombier if(waserror()){
1499a747e4fSDavid du Colombier free(p);
1509a747e4fSDavid du Colombier nexterror();
1519a747e4fSDavid du Colombier }
1529a747e4fSDavid du Colombier
1539a747e4fSDavid du Colombier memset(p, 0, size);
1549a747e4fSDavid du Colombier readn(c, p, text);
1559a747e4fSDavid du Colombier readn(c, p + rtext, data);
1569a747e4fSDavid du Colombier
1579a747e4fSDavid du Colombier ksetenv("bootfile", argv[0], 1);
1589a747e4fSDavid du Colombier setbootcmd(argc-1, argv+1);
1599a747e4fSDavid du Colombier
1609a747e4fSDavid du Colombier reboot((void*)entry, p, size);
1619a747e4fSDavid du Colombier
1629a747e4fSDavid du Colombier panic("return from reboot!");
1639a747e4fSDavid du Colombier }
164