1*3e12c5d1SDavid du Colombier #include "u.h" 2*3e12c5d1SDavid du Colombier #include "libc.h" 3*3e12c5d1SDavid du Colombier #include "bootexec.h" 4*3e12c5d1SDavid du Colombier 5*3e12c5d1SDavid du Colombier #include "mach.h" 6*3e12c5d1SDavid du Colombier 7*3e12c5d1SDavid du Colombier /* 8*3e12c5d1SDavid du Colombier * All a.out header types. The dummy entry allows canonical 9*3e12c5d1SDavid du Colombier * processing of the union as a sequence of longs 10*3e12c5d1SDavid du Colombier */ 11*3e12c5d1SDavid du Colombier 12*3e12c5d1SDavid du Colombier typedef struct { 13*3e12c5d1SDavid du Colombier union{ 14*3e12c5d1SDavid du Colombier Exec; /* in a.out.h */ 15*3e12c5d1SDavid du Colombier struct mipsexec; /* Hobbit uses this header too */ 16*3e12c5d1SDavid du Colombier struct sparcexec; 17*3e12c5d1SDavid du Colombier struct nextexec; 18*3e12c5d1SDavid du Colombier struct i960exec; 19*3e12c5d1SDavid du Colombier } e; 20*3e12c5d1SDavid du Colombier long dummy; /* padding to ensure extra long */ 21*3e12c5d1SDavid du Colombier } ExecHdr; 22*3e12c5d1SDavid du Colombier 23*3e12c5d1SDavid du Colombier static void i960boot(Fhdr *, ExecHdr *); 24*3e12c5d1SDavid du Colombier static void nextboot(Fhdr *, ExecHdr *); 25*3e12c5d1SDavid du Colombier static void sparcboot(Fhdr *, ExecHdr *); 26*3e12c5d1SDavid du Colombier static void mipsboot(Fhdr *, ExecHdr *); 27*3e12c5d1SDavid du Colombier static void hobbitboot(Fhdr *, ExecHdr *); 28*3e12c5d1SDavid du Colombier static void common(Fhdr *, ExecHdr *); 29*3e12c5d1SDavid du Colombier static void adotout(Fhdr *, ExecHdr *); 30*3e12c5d1SDavid du Colombier static void setsym(Fhdr *, long, long, long, long); 31*3e12c5d1SDavid du Colombier static void setdata(Fhdr *, long, long, long, long); 32*3e12c5d1SDavid du Colombier static void settext(Fhdr *, long, long, long, long); 33*3e12c5d1SDavid du Colombier static void hswal(long *, int, long (*) (long)); 34*3e12c5d1SDavid du Colombier 35*3e12c5d1SDavid du Colombier /* 36*3e12c5d1SDavid du Colombier * definition of per-executable file type structures 37*3e12c5d1SDavid du Colombier */ 38*3e12c5d1SDavid du Colombier 39*3e12c5d1SDavid du Colombier typedef struct Exectable{ 40*3e12c5d1SDavid du Colombier long magic; /* big-endian magic number of file */ 41*3e12c5d1SDavid du Colombier char *name; /* executable identifier */ 42*3e12c5d1SDavid du Colombier int type; /* Internal code */ 43*3e12c5d1SDavid du Colombier Mach *mach; /* Per-machine data */ 44*3e12c5d1SDavid du Colombier ulong hsize; /* header size */ 45*3e12c5d1SDavid du Colombier long (*swal)(long); /* beswal or leswal */ 46*3e12c5d1SDavid du Colombier void (*hparse)(Fhdr *, ExecHdr *); 47*3e12c5d1SDavid du Colombier } ExecTable; 48*3e12c5d1SDavid du Colombier 49*3e12c5d1SDavid du Colombier extern Mach mmips; 50*3e12c5d1SDavid du Colombier extern Mach msparc; 51*3e12c5d1SDavid du Colombier extern Mach m68020; 52*3e12c5d1SDavid du Colombier extern Mach mi386; 53*3e12c5d1SDavid du Colombier extern Mach mi960; 54*3e12c5d1SDavid du Colombier extern Mach mhobbit; 55*3e12c5d1SDavid du Colombier 56*3e12c5d1SDavid du Colombier ExecTable exectab[] = 57*3e12c5d1SDavid du Colombier { 58*3e12c5d1SDavid du Colombier { V_MAGIC, /* Mips v.out */ 59*3e12c5d1SDavid du Colombier "mips plan 9 executable", 60*3e12c5d1SDavid du Colombier FMIPS, 61*3e12c5d1SDavid du Colombier &mmips, 62*3e12c5d1SDavid du Colombier sizeof(Exec), 63*3e12c5d1SDavid du Colombier beswal, 64*3e12c5d1SDavid du Colombier adotout }, 65*3e12c5d1SDavid du Colombier { 0x160<<16, /* Mips boot image */ 66*3e12c5d1SDavid du Colombier "mips plan 9 boot image", 67*3e12c5d1SDavid du Colombier FMIPSB, 68*3e12c5d1SDavid du Colombier &mmips, 69*3e12c5d1SDavid du Colombier sizeof(struct mipsexec), 70*3e12c5d1SDavid du Colombier beswal, 71*3e12c5d1SDavid du Colombier mipsboot }, 72*3e12c5d1SDavid du Colombier { 0x161<<16, /* hobbit boot image */ 73*3e12c5d1SDavid du Colombier "hobbit plan 9 boot image", 74*3e12c5d1SDavid du Colombier FHOBBITB, 75*3e12c5d1SDavid du Colombier &mhobbit, 76*3e12c5d1SDavid du Colombier sizeof(struct mipsexec), 77*3e12c5d1SDavid du Colombier beswal, 78*3e12c5d1SDavid du Colombier hobbitboot }, 79*3e12c5d1SDavid du Colombier { K_MAGIC, /* Sparc k.out */ 80*3e12c5d1SDavid du Colombier "sparc plan 9 executable", 81*3e12c5d1SDavid du Colombier FSPARC, 82*3e12c5d1SDavid du Colombier &msparc, 83*3e12c5d1SDavid du Colombier sizeof(Exec), 84*3e12c5d1SDavid du Colombier beswal, 85*3e12c5d1SDavid du Colombier adotout }, 86*3e12c5d1SDavid du Colombier { 0x01030107, /* Sparc boot image */ 87*3e12c5d1SDavid du Colombier "sparc plan 9 boot image", 88*3e12c5d1SDavid du Colombier FSPARCB, 89*3e12c5d1SDavid du Colombier &msparc, 90*3e12c5d1SDavid du Colombier sizeof(struct sparcexec), 91*3e12c5d1SDavid du Colombier beswal, 92*3e12c5d1SDavid du Colombier sparcboot }, 93*3e12c5d1SDavid du Colombier { A_MAGIC, /* 68020 2.out & boot image */ 94*3e12c5d1SDavid du Colombier "68020 plan 9 executable", 95*3e12c5d1SDavid du Colombier F68020, 96*3e12c5d1SDavid du Colombier &m68020, 97*3e12c5d1SDavid du Colombier sizeof(Exec), 98*3e12c5d1SDavid du Colombier beswal, 99*3e12c5d1SDavid du Colombier common }, 100*3e12c5d1SDavid du Colombier { 0xFEEDFACE, /* Next boot image */ 101*3e12c5d1SDavid du Colombier "next plan 9 boot image", 102*3e12c5d1SDavid du Colombier FNEXTB, 103*3e12c5d1SDavid du Colombier &m68020, 104*3e12c5d1SDavid du Colombier sizeof(struct nextexec), 105*3e12c5d1SDavid du Colombier beswal, 106*3e12c5d1SDavid du Colombier nextboot }, 107*3e12c5d1SDavid du Colombier { I_MAGIC, /* I386 8.out & boot image */ 108*3e12c5d1SDavid du Colombier "386 plan 9 executable", 109*3e12c5d1SDavid du Colombier FI386, 110*3e12c5d1SDavid du Colombier &mi386, 111*3e12c5d1SDavid du Colombier sizeof(Exec), 112*3e12c5d1SDavid du Colombier beswal, 113*3e12c5d1SDavid du Colombier common }, 114*3e12c5d1SDavid du Colombier { J_MAGIC, /* I960 6.out (big-endian) */ 115*3e12c5d1SDavid du Colombier "960 plan 9 executable", 116*3e12c5d1SDavid du Colombier FI960, 117*3e12c5d1SDavid du Colombier &mi960, 118*3e12c5d1SDavid du Colombier sizeof(Exec), 119*3e12c5d1SDavid du Colombier beswal, 120*3e12c5d1SDavid du Colombier adotout }, 121*3e12c5d1SDavid du Colombier { 0x61010200, /* I960 boot image (little endian) */ 122*3e12c5d1SDavid du Colombier "960 plan 9 boot image", 123*3e12c5d1SDavid du Colombier FI960B, 124*3e12c5d1SDavid du Colombier &mi960, 125*3e12c5d1SDavid du Colombier sizeof(struct i960exec), 126*3e12c5d1SDavid du Colombier leswal, 127*3e12c5d1SDavid du Colombier i960boot }, 128*3e12c5d1SDavid du Colombier { Z_MAGIC, /* Hobbit z.out */ 129*3e12c5d1SDavid du Colombier "hobbit plan 9 executable", 130*3e12c5d1SDavid du Colombier FHOBBIT, 131*3e12c5d1SDavid du Colombier &mhobbit, 132*3e12c5d1SDavid du Colombier sizeof(Exec), 133*3e12c5d1SDavid du Colombier beswal, 134*3e12c5d1SDavid du Colombier adotout }, 135*3e12c5d1SDavid du Colombier { 0 }, 136*3e12c5d1SDavid du Colombier }; 137*3e12c5d1SDavid du Colombier 138*3e12c5d1SDavid du Colombier Mach *mach = &mmips; /* Global current machine table */ 139*3e12c5d1SDavid du Colombier 140*3e12c5d1SDavid du Colombier int 141*3e12c5d1SDavid du Colombier crackhdr(int fd, Fhdr *fp) 142*3e12c5d1SDavid du Colombier { 143*3e12c5d1SDavid du Colombier ExecTable *mp; 144*3e12c5d1SDavid du Colombier ExecHdr d; 145*3e12c5d1SDavid du Colombier int nb, magic; 146*3e12c5d1SDavid du Colombier 147*3e12c5d1SDavid du Colombier fp->type = FNONE; 148*3e12c5d1SDavid du Colombier if ((nb = read(fd, (char *)&d.e, sizeof(d.e))) <= 0) 149*3e12c5d1SDavid du Colombier return 0; 150*3e12c5d1SDavid du Colombier fp->magic = magic = beswal(d.e.magic); /* big-endian */ 151*3e12c5d1SDavid du Colombier for (mp = exectab; mp->magic; mp++) { 152*3e12c5d1SDavid du Colombier if (mp->magic == magic && nb >= mp->hsize) { 153*3e12c5d1SDavid du Colombier hswal((long *) &d, sizeof(d.e)/sizeof(long), mp->swal); 154*3e12c5d1SDavid du Colombier fp->type = mp->type; 155*3e12c5d1SDavid du Colombier fp->name = mp->name; 156*3e12c5d1SDavid du Colombier fp->hdrsz = mp->hsize; 157*3e12c5d1SDavid du Colombier mach = mp->mach; 158*3e12c5d1SDavid du Colombier mp->hparse(fp, &d); 159*3e12c5d1SDavid du Colombier seek(fd, mp->hsize, 0); /* seek to end of header */ 160*3e12c5d1SDavid du Colombier return 1; 161*3e12c5d1SDavid du Colombier } 162*3e12c5d1SDavid du Colombier } 163*3e12c5d1SDavid du Colombier return 0; 164*3e12c5d1SDavid du Colombier } 165*3e12c5d1SDavid du Colombier /* 166*3e12c5d1SDavid du Colombier * Convert header to canonical form 167*3e12c5d1SDavid du Colombier */ 168*3e12c5d1SDavid du Colombier static void 169*3e12c5d1SDavid du Colombier hswal(long *lp, int n, long (*swap) (long)) 170*3e12c5d1SDavid du Colombier { 171*3e12c5d1SDavid du Colombier while (n--) { 172*3e12c5d1SDavid du Colombier *lp = (*swap) (*lp); 173*3e12c5d1SDavid du Colombier lp++; 174*3e12c5d1SDavid du Colombier } 175*3e12c5d1SDavid du Colombier } 176*3e12c5d1SDavid du Colombier /* 177*3e12c5d1SDavid du Colombier * Crack a normal a.out-type header 178*3e12c5d1SDavid du Colombier */ 179*3e12c5d1SDavid du Colombier static void 180*3e12c5d1SDavid du Colombier adotout(Fhdr *fp, ExecHdr *hp) 181*3e12c5d1SDavid du Colombier { 182*3e12c5d1SDavid du Colombier long pgsize = mach->pgsize; 183*3e12c5d1SDavid du Colombier 184*3e12c5d1SDavid du Colombier settext(fp, hp->e.entry, pgsize, hp->e.text+sizeof(Exec), 0); 185*3e12c5d1SDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz, pgsize), hp->e.data, fp->txtsz, 186*3e12c5d1SDavid du Colombier hp->e.bss); 187*3e12c5d1SDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 188*3e12c5d1SDavid du Colombier } 189*3e12c5d1SDavid du Colombier 190*3e12c5d1SDavid du Colombier /* 191*3e12c5d1SDavid du Colombier * 68020 2.out and 68020 bootable images 192*3e12c5d1SDavid du Colombier * 386I 8.out and 386I bootable images 193*3e12c5d1SDavid du Colombier * 194*3e12c5d1SDavid du Colombier */ 195*3e12c5d1SDavid du Colombier static void 196*3e12c5d1SDavid du Colombier common(Fhdr *fp, ExecHdr *hp) 197*3e12c5d1SDavid du Colombier { 198*3e12c5d1SDavid du Colombier long kbase = mach->kbase; 199*3e12c5d1SDavid du Colombier 200*3e12c5d1SDavid du Colombier adotout(fp, hp); 201*3e12c5d1SDavid du Colombier if (fp->entry & kbase) { /* Boot image */ 202*3e12c5d1SDavid du Colombier switch(fp->type) { 203*3e12c5d1SDavid du Colombier case F68020: 204*3e12c5d1SDavid du Colombier fp->type = F68020B; 205*3e12c5d1SDavid du Colombier fp->name = "68020 plan 9 boot image"; 206*3e12c5d1SDavid du Colombier break; 207*3e12c5d1SDavid du Colombier case FI386: 208*3e12c5d1SDavid du Colombier fp->type = FI386B; 209*3e12c5d1SDavid du Colombier fp->name = "386 plan 9 boot image"; 210*3e12c5d1SDavid du Colombier break; 211*3e12c5d1SDavid du Colombier default: 212*3e12c5d1SDavid du Colombier break; 213*3e12c5d1SDavid du Colombier } 214*3e12c5d1SDavid du Colombier fp->txtaddr |= kbase; 215*3e12c5d1SDavid du Colombier fp->entry |= kbase; 216*3e12c5d1SDavid du Colombier fp->dataddr |= kbase; 217*3e12c5d1SDavid du Colombier } 218*3e12c5d1SDavid du Colombier } 219*3e12c5d1SDavid du Colombier 220*3e12c5d1SDavid du Colombier /* 221*3e12c5d1SDavid du Colombier * mips bootable image. 222*3e12c5d1SDavid du Colombier */ 223*3e12c5d1SDavid du Colombier static void 224*3e12c5d1SDavid du Colombier mipsboot(Fhdr *fp, ExecHdr *hp) 225*3e12c5d1SDavid du Colombier { 226*3e12c5d1SDavid du Colombier switch(hp->e.amagic) { 227*3e12c5d1SDavid du Colombier default: 228*3e12c5d1SDavid du Colombier case 0407: /* some kind of mips */ 229*3e12c5d1SDavid du Colombier fp->type = FMIPSB; 230*3e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 231*3e12c5d1SDavid du Colombier sizeof(struct mipsexec)+4); 232*3e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, 233*3e12c5d1SDavid du Colombier fp->txtoff+hp->e.tsize, hp->e.bsize); 234*3e12c5d1SDavid du Colombier break; 235*3e12c5d1SDavid du Colombier case 0413: /* some kind of mips */ 236*3e12c5d1SDavid du Colombier fp->type = FMIPSB; 237*3e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 0); 238*3e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, hp->e.tsize, 239*3e12c5d1SDavid du Colombier hp->e.bsize); 240*3e12c5d1SDavid du Colombier break; 241*3e12c5d1SDavid du Colombier } 242*3e12c5d1SDavid du Colombier setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 243*3e12c5d1SDavid du Colombier } 244*3e12c5d1SDavid du Colombier /* 245*3e12c5d1SDavid du Colombier * hobbit bootable image. 246*3e12c5d1SDavid du Colombier */ 247*3e12c5d1SDavid du Colombier static void 248*3e12c5d1SDavid du Colombier hobbitboot(Fhdr *fp, ExecHdr *hp) 249*3e12c5d1SDavid du Colombier { 250*3e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 251*3e12c5d1SDavid du Colombier sizeof(struct mipsexec)+4); 252*3e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, 253*3e12c5d1SDavid du Colombier fp->txtoff+hp->e.tsize, hp->e.bsize); 254*3e12c5d1SDavid du Colombier setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 255*3e12c5d1SDavid du Colombier } 256*3e12c5d1SDavid du Colombier /* 257*3e12c5d1SDavid du Colombier * sparc bootable image 258*3e12c5d1SDavid du Colombier */ 259*3e12c5d1SDavid du Colombier static void 260*3e12c5d1SDavid du Colombier sparcboot(Fhdr *fp, ExecHdr *hp) 261*3e12c5d1SDavid du Colombier { 262*3e12c5d1SDavid du Colombier fp->type = FSPARCB; 263*3e12c5d1SDavid du Colombier settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, 264*3e12c5d1SDavid du Colombier sizeof(struct sparcexec)); 265*3e12c5d1SDavid du Colombier setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, 266*3e12c5d1SDavid du Colombier fp->txtoff+hp->e.stext, hp->e.sbss); 267*3e12c5d1SDavid du Colombier setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); 268*3e12c5d1SDavid du Colombier } 269*3e12c5d1SDavid du Colombier 270*3e12c5d1SDavid du Colombier /* 271*3e12c5d1SDavid du Colombier * next bootable image 272*3e12c5d1SDavid du Colombier */ 273*3e12c5d1SDavid du Colombier static void 274*3e12c5d1SDavid du Colombier nextboot(Fhdr *fp, ExecHdr *hp) 275*3e12c5d1SDavid du Colombier { 276*3e12c5d1SDavid du Colombier fp->type = FNEXTB; 277*3e12c5d1SDavid du Colombier settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, 278*3e12c5d1SDavid du Colombier hp->e.texts.size, hp->e.texts.offset); 279*3e12c5d1SDavid du Colombier setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, 280*3e12c5d1SDavid du Colombier hp->e.datas.offset, hp->e.bsss.size); 281*3e12c5d1SDavid du Colombier setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, 282*3e12c5d1SDavid du Colombier hp->e.symc.symoff); 283*3e12c5d1SDavid du Colombier } 284*3e12c5d1SDavid du Colombier 285*3e12c5d1SDavid du Colombier /* 286*3e12c5d1SDavid du Colombier * I960 bootable image 287*3e12c5d1SDavid du Colombier */ 288*3e12c5d1SDavid du Colombier static void 289*3e12c5d1SDavid du Colombier i960boot(Fhdr *fp, ExecHdr *hp) 290*3e12c5d1SDavid du Colombier { 291*3e12c5d1SDavid du Colombier /* long n = hp->e.i6comments.fptrlineno-hp->e.i6comments.fptrreloc; */ 292*3e12c5d1SDavid du Colombier 293*3e12c5d1SDavid du Colombier settext(fp, hp->e.i6entry, hp->e.i6texts.virt, hp->e.i6texts.size, 294*3e12c5d1SDavid du Colombier hp->e.i6texts.fptr); 295*3e12c5d1SDavid du Colombier setdata(fp, hp->e.i6datas.virt, hp->e.i6datas.size, 296*3e12c5d1SDavid du Colombier hp->e.i6datas.fptr, hp->e.i6bsssize); 297*3e12c5d1SDavid du Colombier setsym(fp, 0, 0, 0, 0); 298*3e12c5d1SDavid du Colombier /*setsym(fp, n, 0, hp->e.i6comments.size-n, hp->e.i6comments.fptr); */ 299*3e12c5d1SDavid du Colombier } 300*3e12c5d1SDavid du Colombier 301*3e12c5d1SDavid du Colombier 302*3e12c5d1SDavid du Colombier static void 303*3e12c5d1SDavid du Colombier settext(Fhdr *fp, long e, long a, long s, long off) 304*3e12c5d1SDavid du Colombier { 305*3e12c5d1SDavid du Colombier fp->txtaddr = a; 306*3e12c5d1SDavid du Colombier fp->entry = e; 307*3e12c5d1SDavid du Colombier fp->txtsz = s; 308*3e12c5d1SDavid du Colombier fp->txtoff = off; 309*3e12c5d1SDavid du Colombier } 310*3e12c5d1SDavid du Colombier static void 311*3e12c5d1SDavid du Colombier setdata(Fhdr *fp, long a, long s, long off, long bss) 312*3e12c5d1SDavid du Colombier { 313*3e12c5d1SDavid du Colombier fp->dataddr = a; 314*3e12c5d1SDavid du Colombier fp->datsz = s; 315*3e12c5d1SDavid du Colombier fp->datoff = off; 316*3e12c5d1SDavid du Colombier fp->bsssz = bss; 317*3e12c5d1SDavid du Colombier } 318*3e12c5d1SDavid du Colombier static void 319*3e12c5d1SDavid du Colombier setsym(Fhdr *fp, long sy, long sppc, long lnpc, long symoff) 320*3e12c5d1SDavid du Colombier { 321*3e12c5d1SDavid du Colombier fp->symsz = sy; 322*3e12c5d1SDavid du Colombier fp->symoff = symoff; 323*3e12c5d1SDavid du Colombier fp->sppcsz = sppc; 324*3e12c5d1SDavid du Colombier fp->sppcoff = fp->symoff+fp->symsz; 325*3e12c5d1SDavid du Colombier fp->lnpcsz = lnpc; 326*3e12c5d1SDavid du Colombier fp->lnpcoff = fp->sppcoff+fp->sppcsz; 327*3e12c5d1SDavid du Colombier } 328*3e12c5d1SDavid du Colombier 329