1bd389b36SDavid du Colombier #include <u.h> 2bd389b36SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier #include <bio.h> 4bd389b36SDavid du Colombier #include <bootexec.h> 5bd389b36SDavid du Colombier #include <mach.h> 6*7dd7cddfSDavid du Colombier #include "elf.h" 73e12c5d1SDavid du Colombier 83e12c5d1SDavid du Colombier /* 93e12c5d1SDavid du Colombier * All a.out header types. The dummy entry allows canonical 103e12c5d1SDavid du Colombier * processing of the union as a sequence of longs 113e12c5d1SDavid du Colombier */ 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier typedef struct { 143e12c5d1SDavid du Colombier union{ 153e12c5d1SDavid du Colombier Exec; /* in a.out.h */ 16*7dd7cddfSDavid du Colombier Ehdr; /* in elf.h */ 17*7dd7cddfSDavid du Colombier struct mipsexec; 18219b2ee8SDavid du Colombier struct mips4kexec; 193e12c5d1SDavid du Colombier struct sparcexec; 203e12c5d1SDavid du Colombier struct nextexec; 213e12c5d1SDavid du Colombier struct i960exec; 223e12c5d1SDavid du Colombier } e; 233e12c5d1SDavid du Colombier long dummy; /* padding to ensure extra long */ 243e12c5d1SDavid du Colombier } ExecHdr; 253e12c5d1SDavid du Colombier 26*7dd7cddfSDavid du Colombier static int i960boot(int, Fhdr*, ExecHdr*); 27*7dd7cddfSDavid du Colombier static int nextboot(int, Fhdr*, ExecHdr*); 28*7dd7cddfSDavid du Colombier static int sparcboot(int, Fhdr*, ExecHdr*); 29*7dd7cddfSDavid du Colombier static int mipsboot(int, Fhdr*, ExecHdr*); 30*7dd7cddfSDavid du Colombier static int mips4kboot(int, Fhdr*, ExecHdr*); 31*7dd7cddfSDavid du Colombier static int common(int, Fhdr*, ExecHdr*); 32*7dd7cddfSDavid du Colombier static int adotout(int, Fhdr*, ExecHdr*); 33*7dd7cddfSDavid du Colombier static int elfdotout(int, Fhdr*, ExecHdr*); 34*7dd7cddfSDavid du Colombier static int armdotout(int, Fhdr*, ExecHdr*); 35*7dd7cddfSDavid du Colombier static int alphadotout(int, Fhdr*, ExecHdr*); 363e12c5d1SDavid du Colombier static void setsym(Fhdr*, long, long, long, long); 373e12c5d1SDavid du Colombier static void setdata(Fhdr*, long, long, long, long); 383e12c5d1SDavid du Colombier static void settext(Fhdr*, long, long, long, long); 393e12c5d1SDavid du Colombier static void hswal(long*, int, long(*)(long)); 40219b2ee8SDavid du Colombier static long _round(long, long); 413e12c5d1SDavid du Colombier 423e12c5d1SDavid du Colombier /* 433e12c5d1SDavid du Colombier * definition of per-executable file type structures 443e12c5d1SDavid du Colombier */ 453e12c5d1SDavid du Colombier 463e12c5d1SDavid du Colombier typedef struct Exectable{ 473e12c5d1SDavid du Colombier long magic; /* big-endian magic number of file */ 483e12c5d1SDavid du Colombier char *name; /* executable identifier */ 493e12c5d1SDavid du Colombier int type; /* Internal code */ 503e12c5d1SDavid du Colombier Mach *mach; /* Per-machine data */ 513e12c5d1SDavid du Colombier ulong hsize; /* header size */ 523e12c5d1SDavid du Colombier long (*swal)(long); /* beswal or leswal */ 53*7dd7cddfSDavid du Colombier int (*hparse)(int, Fhdr*, ExecHdr*); 543e12c5d1SDavid du Colombier } ExecTable; 553e12c5d1SDavid du Colombier 563e12c5d1SDavid du Colombier extern Mach mmips; 57*7dd7cddfSDavid du Colombier extern Mach mmips2le; 58*7dd7cddfSDavid du Colombier extern Mach mmips2be; 593e12c5d1SDavid du Colombier extern Mach msparc; 603e12c5d1SDavid du Colombier extern Mach m68020; 613e12c5d1SDavid du Colombier extern Mach mi386; 623e12c5d1SDavid du Colombier extern Mach mi960; 63219b2ee8SDavid du Colombier extern Mach m3210; 64*7dd7cddfSDavid du Colombier extern Mach m29000; 65*7dd7cddfSDavid du Colombier extern Mach marm; 66*7dd7cddfSDavid du Colombier extern Mach mpower; 67*7dd7cddfSDavid du Colombier extern Mach malpha; 683e12c5d1SDavid du Colombier 693e12c5d1SDavid du Colombier ExecTable exectab[] = 703e12c5d1SDavid du Colombier { 713e12c5d1SDavid du Colombier { V_MAGIC, /* Mips v.out */ 723e12c5d1SDavid du Colombier "mips plan 9 executable", 733e12c5d1SDavid du Colombier FMIPS, 743e12c5d1SDavid du Colombier &mmips, 753e12c5d1SDavid du Colombier sizeof(Exec), 763e12c5d1SDavid du Colombier beswal, 773e12c5d1SDavid du Colombier adotout }, 78*7dd7cddfSDavid du Colombier { M_MAGIC, /* Mips 4.out */ 79*7dd7cddfSDavid du Colombier "mips 4k plan 9 executable BE", 80*7dd7cddfSDavid du Colombier FMIPS2BE, 81*7dd7cddfSDavid du Colombier &mmips2be, 82*7dd7cddfSDavid du Colombier sizeof(Exec), 83*7dd7cddfSDavid du Colombier beswal, 84*7dd7cddfSDavid du Colombier adotout }, 85*7dd7cddfSDavid du Colombier { N_MAGIC, /* Mips 0.out */ 86*7dd7cddfSDavid du Colombier "mips 4k plan 9 executable LE", 87*7dd7cddfSDavid du Colombier FMIPS2LE, 88*7dd7cddfSDavid du Colombier &mmips2le, 89*7dd7cddfSDavid du Colombier sizeof(Exec), 90*7dd7cddfSDavid du Colombier beswal, 91*7dd7cddfSDavid du Colombier adotout }, 923e12c5d1SDavid du Colombier { 0x160<<16, /* Mips boot image */ 933e12c5d1SDavid du Colombier "mips plan 9 boot image", 943e12c5d1SDavid du Colombier FMIPSB, 953e12c5d1SDavid du Colombier &mmips, 963e12c5d1SDavid du Colombier sizeof(struct mipsexec), 973e12c5d1SDavid du Colombier beswal, 983e12c5d1SDavid du Colombier mipsboot }, 99219b2ee8SDavid du Colombier { (0x160<<16)|3, /* Mips boot image */ 100219b2ee8SDavid du Colombier "mips 4k plan 9 boot image", 101219b2ee8SDavid du Colombier FMIPSB, 102219b2ee8SDavid du Colombier &mmips, 103219b2ee8SDavid du Colombier sizeof(struct mips4kexec), 1043e12c5d1SDavid du Colombier beswal, 105219b2ee8SDavid du Colombier mips4kboot }, 1063e12c5d1SDavid du Colombier { K_MAGIC, /* Sparc k.out */ 1073e12c5d1SDavid du Colombier "sparc plan 9 executable", 1083e12c5d1SDavid du Colombier FSPARC, 1093e12c5d1SDavid du Colombier &msparc, 1103e12c5d1SDavid du Colombier sizeof(Exec), 1113e12c5d1SDavid du Colombier beswal, 1123e12c5d1SDavid du Colombier adotout }, 1133e12c5d1SDavid du Colombier { 0x01030107, /* Sparc boot image */ 1143e12c5d1SDavid du Colombier "sparc plan 9 boot image", 1153e12c5d1SDavid du Colombier FSPARCB, 1163e12c5d1SDavid du Colombier &msparc, 1173e12c5d1SDavid du Colombier sizeof(struct sparcexec), 1183e12c5d1SDavid du Colombier beswal, 1193e12c5d1SDavid du Colombier sparcboot }, 1203e12c5d1SDavid du Colombier { A_MAGIC, /* 68020 2.out & boot image */ 1213e12c5d1SDavid du Colombier "68020 plan 9 executable", 1223e12c5d1SDavid du Colombier F68020, 1233e12c5d1SDavid du Colombier &m68020, 1243e12c5d1SDavid du Colombier sizeof(Exec), 1253e12c5d1SDavid du Colombier beswal, 1263e12c5d1SDavid du Colombier common }, 1273e12c5d1SDavid du Colombier { 0xFEEDFACE, /* Next boot image */ 1283e12c5d1SDavid du Colombier "next plan 9 boot image", 1293e12c5d1SDavid du Colombier FNEXTB, 1303e12c5d1SDavid du Colombier &m68020, 1313e12c5d1SDavid du Colombier sizeof(struct nextexec), 1323e12c5d1SDavid du Colombier beswal, 1333e12c5d1SDavid du Colombier nextboot }, 1343e12c5d1SDavid du Colombier { I_MAGIC, /* I386 8.out & boot image */ 1353e12c5d1SDavid du Colombier "386 plan 9 executable", 1363e12c5d1SDavid du Colombier FI386, 1373e12c5d1SDavid du Colombier &mi386, 1383e12c5d1SDavid du Colombier sizeof(Exec), 1393e12c5d1SDavid du Colombier beswal, 1403e12c5d1SDavid du Colombier common }, 1413e12c5d1SDavid du Colombier { J_MAGIC, /* I960 6.out (big-endian) */ 1423e12c5d1SDavid du Colombier "960 plan 9 executable", 1433e12c5d1SDavid du Colombier FI960, 1443e12c5d1SDavid du Colombier &mi960, 1453e12c5d1SDavid du Colombier sizeof(Exec), 1463e12c5d1SDavid du Colombier beswal, 1473e12c5d1SDavid du Colombier adotout }, 1483e12c5d1SDavid du Colombier { 0x61010200, /* I960 boot image (little endian) */ 1493e12c5d1SDavid du Colombier "960 plan 9 boot image", 1503e12c5d1SDavid du Colombier FI960B, 1513e12c5d1SDavid du Colombier &mi960, 1523e12c5d1SDavid du Colombier sizeof(struct i960exec), 1533e12c5d1SDavid du Colombier leswal, 1543e12c5d1SDavid du Colombier i960boot }, 155219b2ee8SDavid du Colombier { X_MAGIC, /* 3210 x.out */ 156219b2ee8SDavid du Colombier "3210 plan 9 executable", 157219b2ee8SDavid du Colombier F3210, 158219b2ee8SDavid du Colombier &m3210, 1593e12c5d1SDavid du Colombier sizeof(Exec), 1603e12c5d1SDavid du Colombier beswal, 1613e12c5d1SDavid du Colombier adotout }, 162*7dd7cddfSDavid du Colombier { D_MAGIC, /* 29000 9.out */ 163*7dd7cddfSDavid du Colombier "29000 plan 9 executable", 164*7dd7cddfSDavid du Colombier F29000, 165*7dd7cddfSDavid du Colombier &m29000, 166*7dd7cddfSDavid du Colombier sizeof(Exec), 167*7dd7cddfSDavid du Colombier beswal, 168*7dd7cddfSDavid du Colombier adotout }, 169*7dd7cddfSDavid du Colombier { Q_MAGIC, /* PowerPC q.out */ 170*7dd7cddfSDavid du Colombier "power plan 9 executable", 171*7dd7cddfSDavid du Colombier FPOWER, 172*7dd7cddfSDavid du Colombier &mpower, 173*7dd7cddfSDavid du Colombier sizeof(Exec), 174*7dd7cddfSDavid du Colombier beswal, 175*7dd7cddfSDavid du Colombier common }, 176*7dd7cddfSDavid du Colombier { ELF_MAG, 177*7dd7cddfSDavid du Colombier "Irix 5.X Elf executable", 178*7dd7cddfSDavid du Colombier FMIPS, 179*7dd7cddfSDavid du Colombier &mmips, 180*7dd7cddfSDavid du Colombier sizeof(Ehdr), 181*7dd7cddfSDavid du Colombier beswal, 182*7dd7cddfSDavid du Colombier elfdotout }, 183*7dd7cddfSDavid du Colombier { E_MAGIC, /* Arm 5.out */ 184*7dd7cddfSDavid du Colombier "Arm plan 9 executable", 185*7dd7cddfSDavid du Colombier FARM, 186*7dd7cddfSDavid du Colombier &marm, 187*7dd7cddfSDavid du Colombier sizeof(Exec), 188*7dd7cddfSDavid du Colombier beswal, 189*7dd7cddfSDavid du Colombier common }, 190*7dd7cddfSDavid du Colombier { (143<<16)|0413, /* (Free|Net)BSD Arm */ 191*7dd7cddfSDavid du Colombier "Arm *BSD executable", 192*7dd7cddfSDavid du Colombier FARM, 193*7dd7cddfSDavid du Colombier &marm, 194*7dd7cddfSDavid du Colombier sizeof(Exec), 195*7dd7cddfSDavid du Colombier leswal, 196*7dd7cddfSDavid du Colombier armdotout }, 197*7dd7cddfSDavid du Colombier { L_MAGIC, /* alpha 7.out */ 198*7dd7cddfSDavid du Colombier "alpha plan 9 executable", 199*7dd7cddfSDavid du Colombier FALPHA, 200*7dd7cddfSDavid du Colombier &malpha, 201*7dd7cddfSDavid du Colombier sizeof(Exec), 202*7dd7cddfSDavid du Colombier beswal, 203*7dd7cddfSDavid du Colombier common }, 204*7dd7cddfSDavid du Colombier { 0x0700e0c3, /* alpha boot image */ 205*7dd7cddfSDavid du Colombier "alpha plan 9 boot image", 206*7dd7cddfSDavid du Colombier FALPHAB, 207*7dd7cddfSDavid du Colombier &malpha, 208*7dd7cddfSDavid du Colombier sizeof(Exec), 209*7dd7cddfSDavid du Colombier beswal, 210*7dd7cddfSDavid du Colombier alphadotout }, 2113e12c5d1SDavid du Colombier { 0 }, 2123e12c5d1SDavid du Colombier }; 2133e12c5d1SDavid du Colombier 214*7dd7cddfSDavid du Colombier Mach *mach = &mi386; /* Global current machine table */ 215*7dd7cddfSDavid du Colombier 216*7dd7cddfSDavid du Colombier static ExecTable* 217*7dd7cddfSDavid du Colombier couldbe4k(ExecTable *mp) 218*7dd7cddfSDavid du Colombier { 219*7dd7cddfSDavid du Colombier Dir d; 220*7dd7cddfSDavid du Colombier ExecTable *f; 221*7dd7cddfSDavid du Colombier 222*7dd7cddfSDavid du Colombier if(dirstat("/proc/1/regs", &d) < 0) 223*7dd7cddfSDavid du Colombier return mp; 224*7dd7cddfSDavid du Colombier if(d.length < 32*8) /* R3000 */ 225*7dd7cddfSDavid du Colombier return mp; 226*7dd7cddfSDavid du Colombier for (f = exectab; f->magic; f++) 227*7dd7cddfSDavid du Colombier if(f->magic == M_MAGIC) { 228*7dd7cddfSDavid du Colombier f->name = "mips plan 9 executable on mips2 kernel"; 229*7dd7cddfSDavid du Colombier return f; 230*7dd7cddfSDavid du Colombier } 231*7dd7cddfSDavid du Colombier return mp; 232*7dd7cddfSDavid du Colombier } 233*7dd7cddfSDavid du Colombier 2343e12c5d1SDavid du Colombier 2353e12c5d1SDavid du Colombier int 2363e12c5d1SDavid du Colombier crackhdr(int fd, Fhdr *fp) 2373e12c5d1SDavid du Colombier { 2383e12c5d1SDavid du Colombier ExecTable *mp; 2393e12c5d1SDavid du Colombier ExecHdr d; 240*7dd7cddfSDavid du Colombier int nb, magic, ret; 2413e12c5d1SDavid du Colombier 2423e12c5d1SDavid du Colombier fp->type = FNONE; 243*7dd7cddfSDavid du Colombier nb = read(fd, (char *)&d.e, sizeof(d.e)); 244*7dd7cddfSDavid du Colombier if (nb <= 0) 2453e12c5d1SDavid du Colombier return 0; 246*7dd7cddfSDavid du Colombier 247*7dd7cddfSDavid du Colombier ret = 0; 2483e12c5d1SDavid du Colombier fp->magic = magic = beswal(d.e.magic); /* big-endian */ 2493e12c5d1SDavid du Colombier for (mp = exectab; mp->magic; mp++) { 2503e12c5d1SDavid du Colombier if (mp->magic == magic && nb >= mp->hsize) { 251*7dd7cddfSDavid du Colombier if(mp->magic == V_MAGIC) 252*7dd7cddfSDavid du Colombier mp = couldbe4k(mp); 253*7dd7cddfSDavid du Colombier 2543e12c5d1SDavid du Colombier hswal((long *) &d, sizeof(d.e)/sizeof(long), mp->swal); 2553e12c5d1SDavid du Colombier fp->type = mp->type; 2563e12c5d1SDavid du Colombier fp->name = mp->name; 257219b2ee8SDavid du Colombier fp->hdrsz = mp->hsize; /* zero on bootables */ 2583e12c5d1SDavid du Colombier mach = mp->mach; 259*7dd7cddfSDavid du Colombier ret = mp->hparse(fd, fp, &d); 2603e12c5d1SDavid du Colombier seek(fd, mp->hsize, 0); /* seek to end of header */ 261*7dd7cddfSDavid du Colombier break; 2623e12c5d1SDavid du Colombier } 2633e12c5d1SDavid du Colombier } 264*7dd7cddfSDavid du Colombier if(mp->magic == 0) 265*7dd7cddfSDavid du Colombier werrstr("unknown header type"); 266*7dd7cddfSDavid du Colombier return ret; 2673e12c5d1SDavid du Colombier } 2683e12c5d1SDavid du Colombier /* 2693e12c5d1SDavid du Colombier * Convert header to canonical form 2703e12c5d1SDavid du Colombier */ 2713e12c5d1SDavid du Colombier static void 2723e12c5d1SDavid du Colombier hswal(long *lp, int n, long (*swap) (long)) 2733e12c5d1SDavid du Colombier { 2743e12c5d1SDavid du Colombier while (n--) { 2753e12c5d1SDavid du Colombier *lp = (*swap) (*lp); 2763e12c5d1SDavid du Colombier lp++; 2773e12c5d1SDavid du Colombier } 2783e12c5d1SDavid du Colombier } 2793e12c5d1SDavid du Colombier /* 2803e12c5d1SDavid du Colombier * Crack a normal a.out-type header 2813e12c5d1SDavid du Colombier */ 282*7dd7cddfSDavid du Colombier static int 283*7dd7cddfSDavid du Colombier adotout(int fd, Fhdr *fp, ExecHdr *hp) 2843e12c5d1SDavid du Colombier { 285*7dd7cddfSDavid du Colombier long pgsize; 2863e12c5d1SDavid du Colombier 287*7dd7cddfSDavid du Colombier USED(fd); 288*7dd7cddfSDavid du Colombier pgsize = mach->pgsize; 289219b2ee8SDavid du Colombier settext(fp, hp->e.entry, pgsize+sizeof(Exec), 290219b2ee8SDavid du Colombier hp->e.text, sizeof(Exec)); 291219b2ee8SDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), 292219b2ee8SDavid du Colombier hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 2933e12c5d1SDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 294*7dd7cddfSDavid du Colombier return 1; 2953e12c5d1SDavid du Colombier } 2963e12c5d1SDavid du Colombier 2973e12c5d1SDavid du Colombier /* 2983e12c5d1SDavid du Colombier * 68020 2.out and 68020 bootable images 2993e12c5d1SDavid du Colombier * 386I 8.out and 386I bootable images 300*7dd7cddfSDavid du Colombier * alpha plan9-style bootable images for axp "headerless" boot 3013e12c5d1SDavid du Colombier * 3023e12c5d1SDavid du Colombier */ 303*7dd7cddfSDavid du Colombier static int 304*7dd7cddfSDavid du Colombier common(int fd, Fhdr *fp, ExecHdr *hp) 3053e12c5d1SDavid du Colombier { 306*7dd7cddfSDavid du Colombier long kbase; 3073e12c5d1SDavid du Colombier 308*7dd7cddfSDavid du Colombier adotout(fd, fp, hp); 309*7dd7cddfSDavid du Colombier kbase = mach->kbase; 310*7dd7cddfSDavid du Colombier if ((fp->entry & kbase) == kbase) { /* Boot image */ 3113e12c5d1SDavid du Colombier switch(fp->type) { 3123e12c5d1SDavid du Colombier case F68020: 3133e12c5d1SDavid du Colombier fp->type = F68020B; 3143e12c5d1SDavid du Colombier fp->name = "68020 plan 9 boot image"; 315219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 3163e12c5d1SDavid du Colombier break; 3173e12c5d1SDavid du Colombier case FI386: 3183e12c5d1SDavid du Colombier fp->type = FI386B; 319219b2ee8SDavid du Colombier fp->txtaddr = sizeof(Exec); 3203e12c5d1SDavid du Colombier fp->name = "386 plan 9 boot image"; 321219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 322219b2ee8SDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 3233e12c5d1SDavid du Colombier break; 324*7dd7cddfSDavid du Colombier case FARM: 325*7dd7cddfSDavid du Colombier fp->txtaddr = kbase+0xC000+sizeof(Exec); 326*7dd7cddfSDavid du Colombier fp->name = "ARM plan 9 boot image"; 327*7dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 328*7dd7cddfSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 329*7dd7cddfSDavid du Colombier return 1; 330*7dd7cddfSDavid du Colombier case FALPHA: 331*7dd7cddfSDavid du Colombier fp->type = FALPHAB; 332*7dd7cddfSDavid du Colombier fp->txtaddr = fp->entry; 333*7dd7cddfSDavid du Colombier fp->name = "Alpha plan 9 boot image?"; 334*7dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 335*7dd7cddfSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 336*7dd7cddfSDavid du Colombier break; 337*7dd7cddfSDavid du Colombier case FALPHAB: 338*7dd7cddfSDavid du Colombier fp->txtaddr = 0x20000000+sizeof(Exec); 339*7dd7cddfSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 340*7dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 341*7dd7cddfSDavid du Colombier return 1; 3423e12c5d1SDavid du Colombier default: 3433e12c5d1SDavid du Colombier break; 3443e12c5d1SDavid du Colombier } 3453e12c5d1SDavid du Colombier fp->txtaddr |= kbase; 3463e12c5d1SDavid du Colombier fp->entry |= kbase; 3473e12c5d1SDavid du Colombier fp->dataddr |= kbase; 3483e12c5d1SDavid du Colombier } 349*7dd7cddfSDavid du Colombier return 1; 3503e12c5d1SDavid du Colombier } 3513e12c5d1SDavid du Colombier 3523e12c5d1SDavid du Colombier /* 3533e12c5d1SDavid du Colombier * mips bootable image. 3543e12c5d1SDavid du Colombier */ 355*7dd7cddfSDavid du Colombier static int 356*7dd7cddfSDavid du Colombier mipsboot(int fd, Fhdr *fp, ExecHdr *hp) 3573e12c5d1SDavid du Colombier { 358*7dd7cddfSDavid du Colombier USED(fd); 3593e12c5d1SDavid du Colombier switch(hp->e.amagic) { 3603e12c5d1SDavid du Colombier default: 3613e12c5d1SDavid du Colombier case 0407: /* some kind of mips */ 3623e12c5d1SDavid du Colombier fp->type = FMIPSB; 3633e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 3643e12c5d1SDavid du Colombier sizeof(struct mipsexec)+4); 3653e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, 3663e12c5d1SDavid du Colombier fp->txtoff+hp->e.tsize, hp->e.bsize); 3673e12c5d1SDavid du Colombier break; 3683e12c5d1SDavid du Colombier case 0413: /* some kind of mips */ 3693e12c5d1SDavid du Colombier fp->type = FMIPSB; 3703e12c5d1SDavid du Colombier settext(fp, hp->e.mentry, hp->e.text_start, hp->e.tsize, 0); 3713e12c5d1SDavid du Colombier setdata(fp, hp->e.data_start, hp->e.dsize, hp->e.tsize, 3723e12c5d1SDavid du Colombier hp->e.bsize); 3733e12c5d1SDavid du Colombier break; 3743e12c5d1SDavid du Colombier } 3753e12c5d1SDavid du Colombier setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 376219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 377*7dd7cddfSDavid du Colombier return 1; 3783e12c5d1SDavid du Colombier } 379219b2ee8SDavid du Colombier 3803e12c5d1SDavid du Colombier /* 381219b2ee8SDavid du Colombier * mips4k bootable image. 3823e12c5d1SDavid du Colombier */ 383*7dd7cddfSDavid du Colombier static int 384*7dd7cddfSDavid du Colombier mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) 3853e12c5d1SDavid du Colombier { 386*7dd7cddfSDavid du Colombier USED(fd); 387219b2ee8SDavid du Colombier switch(hp->e.h.amagic) { 388219b2ee8SDavid du Colombier default: 389219b2ee8SDavid du Colombier case 0407: /* some kind of mips */ 390219b2ee8SDavid du Colombier fp->type = FMIPSB; 391219b2ee8SDavid du Colombier settext(fp, hp->e.h.mentry, hp->e.h.text_start, hp->e.h.tsize, 392219b2ee8SDavid du Colombier sizeof(struct mips4kexec)); 393219b2ee8SDavid du Colombier setdata(fp, hp->e.h.data_start, hp->e.h.dsize, 394219b2ee8SDavid du Colombier fp->txtoff+hp->e.h.tsize, hp->e.h.bsize); 395219b2ee8SDavid du Colombier break; 396219b2ee8SDavid du Colombier case 0413: /* some kind of mips */ 397219b2ee8SDavid du Colombier fp->type = FMIPSB; 398219b2ee8SDavid du Colombier settext(fp, hp->e.h.mentry, hp->e.h.text_start, hp->e.h.tsize, 0); 399219b2ee8SDavid du Colombier setdata(fp, hp->e.h.data_start, hp->e.h.dsize, hp->e.h.tsize, 400219b2ee8SDavid du Colombier hp->e.h.bsize); 401219b2ee8SDavid du Colombier break; 4023e12c5d1SDavid du Colombier } 403219b2ee8SDavid du Colombier setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr); 404219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 405*7dd7cddfSDavid du Colombier return 1; 406219b2ee8SDavid du Colombier } 407219b2ee8SDavid du Colombier 4083e12c5d1SDavid du Colombier /* 4093e12c5d1SDavid du Colombier * sparc bootable image 4103e12c5d1SDavid du Colombier */ 411*7dd7cddfSDavid du Colombier static int 412*7dd7cddfSDavid du Colombier sparcboot(int fd, Fhdr *fp, ExecHdr *hp) 4133e12c5d1SDavid du Colombier { 414*7dd7cddfSDavid du Colombier USED(fd); 4153e12c5d1SDavid du Colombier fp->type = FSPARCB; 4163e12c5d1SDavid du Colombier settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, 4173e12c5d1SDavid du Colombier sizeof(struct sparcexec)); 4183e12c5d1SDavid du Colombier setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, 4193e12c5d1SDavid du Colombier fp->txtoff+hp->e.stext, hp->e.sbss); 4203e12c5d1SDavid du Colombier setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); 421219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 422*7dd7cddfSDavid du Colombier return 1; 4233e12c5d1SDavid du Colombier } 4243e12c5d1SDavid du Colombier 4253e12c5d1SDavid du Colombier /* 4263e12c5d1SDavid du Colombier * next bootable image 4273e12c5d1SDavid du Colombier */ 428*7dd7cddfSDavid du Colombier static int 429*7dd7cddfSDavid du Colombier nextboot(int fd, Fhdr *fp, ExecHdr *hp) 4303e12c5d1SDavid du Colombier { 431*7dd7cddfSDavid du Colombier USED(fd); 4323e12c5d1SDavid du Colombier fp->type = FNEXTB; 4333e12c5d1SDavid du Colombier settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, 4343e12c5d1SDavid du Colombier hp->e.texts.size, hp->e.texts.offset); 4353e12c5d1SDavid du Colombier setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, 4363e12c5d1SDavid du Colombier hp->e.datas.offset, hp->e.bsss.size); 4373e12c5d1SDavid du Colombier setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, 4383e12c5d1SDavid du Colombier hp->e.symc.symoff); 439219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 440*7dd7cddfSDavid du Colombier return 1; 4413e12c5d1SDavid du Colombier } 4423e12c5d1SDavid du Colombier 4433e12c5d1SDavid du Colombier /* 4443e12c5d1SDavid du Colombier * I960 bootable image 4453e12c5d1SDavid du Colombier */ 446*7dd7cddfSDavid du Colombier static int 447*7dd7cddfSDavid du Colombier i960boot(int fd, Fhdr *fp, ExecHdr *hp) 4483e12c5d1SDavid du Colombier { 4493e12c5d1SDavid du Colombier /* long n = hp->e.i6comments.fptrlineno-hp->e.i6comments.fptrreloc; */ 4503e12c5d1SDavid du Colombier 451*7dd7cddfSDavid du Colombier USED(fd); 4523e12c5d1SDavid du Colombier settext(fp, hp->e.i6entry, hp->e.i6texts.virt, hp->e.i6texts.size, 4533e12c5d1SDavid du Colombier hp->e.i6texts.fptr); 4543e12c5d1SDavid du Colombier setdata(fp, hp->e.i6datas.virt, hp->e.i6datas.size, 4553e12c5d1SDavid du Colombier hp->e.i6datas.fptr, hp->e.i6bsssize); 4563e12c5d1SDavid du Colombier setsym(fp, 0, 0, 0, 0); 4573e12c5d1SDavid du Colombier /*setsym(fp, n, 0, hp->e.i6comments.size-n, hp->e.i6comments.fptr); */ 458219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 459*7dd7cddfSDavid du Colombier return 1; 4603e12c5d1SDavid du Colombier } 4613e12c5d1SDavid du Colombier 462*7dd7cddfSDavid du Colombier static Shdr* 463*7dd7cddfSDavid du Colombier elfsectbyname(int fd, Ehdr *hp, Shdr *sp, char *name) 464*7dd7cddfSDavid du Colombier { 465*7dd7cddfSDavid du Colombier int i, offset, n; 466*7dd7cddfSDavid du Colombier char s[64]; 467*7dd7cddfSDavid du Colombier 468*7dd7cddfSDavid du Colombier offset = sp[hp->shstrndx].offset; 469*7dd7cddfSDavid du Colombier for(i = 1; i < hp->shnum; i++) { 470*7dd7cddfSDavid du Colombier seek(fd, offset+sp[i].name, 0); 471*7dd7cddfSDavid du Colombier n = read(fd, s, sizeof(s)-1); 472*7dd7cddfSDavid du Colombier if(n < 0) 473*7dd7cddfSDavid du Colombier continue; 474*7dd7cddfSDavid du Colombier s[n] = 0; 475*7dd7cddfSDavid du Colombier if(strcmp(s, name) == 0) 476*7dd7cddfSDavid du Colombier return &sp[i]; 477*7dd7cddfSDavid du Colombier } 478*7dd7cddfSDavid du Colombier return 0; 479*7dd7cddfSDavid du Colombier } 480*7dd7cddfSDavid du Colombier /* 481*7dd7cddfSDavid du Colombier * Decode an Irix 5.x ELF header 482*7dd7cddfSDavid du Colombier */ 483*7dd7cddfSDavid du Colombier static int 484*7dd7cddfSDavid du Colombier elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 485*7dd7cddfSDavid du Colombier { 486*7dd7cddfSDavid du Colombier 487*7dd7cddfSDavid du Colombier Ehdr *ep; 488*7dd7cddfSDavid du Colombier Shdr *es, *txt, *init, *s; 489*7dd7cddfSDavid du Colombier long addr, size, offset, bsize; 490*7dd7cddfSDavid du Colombier 491*7dd7cddfSDavid du Colombier ep = &hp->e; 492*7dd7cddfSDavid du Colombier if(ep->type != 8 || ep->machine != 2 || ep->version != 1) 493*7dd7cddfSDavid du Colombier return 0; 494*7dd7cddfSDavid du Colombier 495*7dd7cddfSDavid du Colombier fp->magic = ELF_MAG; 496*7dd7cddfSDavid du Colombier fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 497*7dd7cddfSDavid du Colombier 498*7dd7cddfSDavid du Colombier if(ep->shnum <= 0) { 499*7dd7cddfSDavid du Colombier werrstr("no ELF header sections"); 500*7dd7cddfSDavid du Colombier return 0; 501*7dd7cddfSDavid du Colombier } 502*7dd7cddfSDavid du Colombier es = malloc(sizeof(Shdr)*ep->shnum); 503*7dd7cddfSDavid du Colombier if(es == 0) 504*7dd7cddfSDavid du Colombier return 0; 505*7dd7cddfSDavid du Colombier 506*7dd7cddfSDavid du Colombier seek(fd, ep->shoff, 0); 507*7dd7cddfSDavid du Colombier if(read(fd, es, sizeof(Shdr)*ep->shnum) < 0){ 508*7dd7cddfSDavid du Colombier free(es); 509*7dd7cddfSDavid du Colombier return 0; 510*7dd7cddfSDavid du Colombier } 511*7dd7cddfSDavid du Colombier 512*7dd7cddfSDavid du Colombier txt = elfsectbyname(fd, ep, es, ".text"); 513*7dd7cddfSDavid du Colombier init = elfsectbyname(fd, ep, es, ".init"); 514*7dd7cddfSDavid du Colombier if(txt == 0 || init == 0 || init != txt+1) 515*7dd7cddfSDavid du Colombier goto bad; 516*7dd7cddfSDavid du Colombier if(txt->addr+txt->size != init->addr) 517*7dd7cddfSDavid du Colombier goto bad; 518*7dd7cddfSDavid du Colombier settext(fp, ep->elfentry, txt->addr, txt->size+init->size, txt->offset); 519*7dd7cddfSDavid du Colombier 520*7dd7cddfSDavid du Colombier addr = 0; 521*7dd7cddfSDavid du Colombier offset = 0; 522*7dd7cddfSDavid du Colombier size = 0; 523*7dd7cddfSDavid du Colombier s = elfsectbyname(fd, ep, es, ".data"); 524*7dd7cddfSDavid du Colombier if(s) { 525*7dd7cddfSDavid du Colombier addr = s->addr; 526*7dd7cddfSDavid du Colombier size = s->size; 527*7dd7cddfSDavid du Colombier offset = s->offset; 528*7dd7cddfSDavid du Colombier } 529*7dd7cddfSDavid du Colombier 530*7dd7cddfSDavid du Colombier s = elfsectbyname(fd, ep, es, ".rodata"); 531*7dd7cddfSDavid du Colombier if(s) { 532*7dd7cddfSDavid du Colombier if(addr){ 533*7dd7cddfSDavid du Colombier if(addr+size != s->addr) 534*7dd7cddfSDavid du Colombier goto bad; 535*7dd7cddfSDavid du Colombier } else { 536*7dd7cddfSDavid du Colombier addr = s->addr; 537*7dd7cddfSDavid du Colombier offset = s->offset; 538*7dd7cddfSDavid du Colombier } 539*7dd7cddfSDavid du Colombier size += s->size; 540*7dd7cddfSDavid du Colombier } 541*7dd7cddfSDavid du Colombier 542*7dd7cddfSDavid du Colombier s = elfsectbyname(fd, ep, es, ".got"); 543*7dd7cddfSDavid du Colombier if(s) { 544*7dd7cddfSDavid du Colombier if(addr){ 545*7dd7cddfSDavid du Colombier if(addr+size != s->addr) 546*7dd7cddfSDavid du Colombier goto bad; 547*7dd7cddfSDavid du Colombier } else { 548*7dd7cddfSDavid du Colombier addr = s->addr; 549*7dd7cddfSDavid du Colombier offset = s->offset; 550*7dd7cddfSDavid du Colombier } 551*7dd7cddfSDavid du Colombier size += s->size; 552*7dd7cddfSDavid du Colombier } 553*7dd7cddfSDavid du Colombier 554*7dd7cddfSDavid du Colombier bsize = 0; 555*7dd7cddfSDavid du Colombier s = elfsectbyname(fd, ep, es, ".bss"); 556*7dd7cddfSDavid du Colombier if(s) { 557*7dd7cddfSDavid du Colombier if(addr){ 558*7dd7cddfSDavid du Colombier if(addr+size != s->addr) 559*7dd7cddfSDavid du Colombier goto bad; 560*7dd7cddfSDavid du Colombier } else { 561*7dd7cddfSDavid du Colombier addr = s->addr; 562*7dd7cddfSDavid du Colombier offset = s->offset; 563*7dd7cddfSDavid du Colombier } 564*7dd7cddfSDavid du Colombier bsize = s->size; 565*7dd7cddfSDavid du Colombier } 566*7dd7cddfSDavid du Colombier 567*7dd7cddfSDavid du Colombier if(addr == 0) 568*7dd7cddfSDavid du Colombier goto bad; 569*7dd7cddfSDavid du Colombier 570*7dd7cddfSDavid du Colombier setdata(fp, addr, size, offset, bsize); 571*7dd7cddfSDavid du Colombier fp->name = "IRIX Elf a.out executable"; 572*7dd7cddfSDavid du Colombier free(es); 573*7dd7cddfSDavid du Colombier return 1; 574*7dd7cddfSDavid du Colombier bad: 575*7dd7cddfSDavid du Colombier free(es); 576*7dd7cddfSDavid du Colombier werrstr("ELF sections scrambled"); 577*7dd7cddfSDavid du Colombier return 0; 578*7dd7cddfSDavid du Colombier } 579*7dd7cddfSDavid du Colombier 580*7dd7cddfSDavid du Colombier /* 581*7dd7cddfSDavid du Colombier * alpha bootable 582*7dd7cddfSDavid du Colombier */ 583*7dd7cddfSDavid du Colombier static int 584*7dd7cddfSDavid du Colombier alphadotout(int fd, Fhdr *fp, ExecHdr *hp) 585*7dd7cddfSDavid du Colombier { 586*7dd7cddfSDavid du Colombier long kbase; 587*7dd7cddfSDavid du Colombier 588*7dd7cddfSDavid du Colombier USED(fd); 589*7dd7cddfSDavid du Colombier settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 590*7dd7cddfSDavid du Colombier setdata(fp, fp->txtsz+sizeof(Exec), hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 591*7dd7cddfSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 592*7dd7cddfSDavid du Colombier 593*7dd7cddfSDavid du Colombier /* 594*7dd7cddfSDavid du Colombier * Boot images have some of bits <31:28> set: 595*7dd7cddfSDavid du Colombier * 0x80400000 kernel 596*7dd7cddfSDavid du Colombier * 0x20000000 secondary bootstrap 597*7dd7cddfSDavid du Colombier */ 598*7dd7cddfSDavid du Colombier kbase = 0xF0000000; 599*7dd7cddfSDavid du Colombier if (fp->entry & kbase) { 600*7dd7cddfSDavid du Colombier fp->txtaddr = fp->entry; 601*7dd7cddfSDavid du Colombier fp->name = "alpha plan 9 boot image"; 602*7dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 603*7dd7cddfSDavid du Colombier fp->dataddr = fp->entry+fp->txtsz; 604*7dd7cddfSDavid du Colombier } 605*7dd7cddfSDavid du Colombier return 1; 606*7dd7cddfSDavid du Colombier } 607*7dd7cddfSDavid du Colombier 608*7dd7cddfSDavid du Colombier /* 609*7dd7cddfSDavid du Colombier * (Free|Net)BSD ARM header. 610*7dd7cddfSDavid du Colombier */ 611*7dd7cddfSDavid du Colombier static int 612*7dd7cddfSDavid du Colombier armdotout(int fd, Fhdr *fp, ExecHdr *hp) 613*7dd7cddfSDavid du Colombier { 614*7dd7cddfSDavid du Colombier long kbase; 615*7dd7cddfSDavid du Colombier 616*7dd7cddfSDavid du Colombier USED(fd); 617*7dd7cddfSDavid du Colombier settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 618*7dd7cddfSDavid du Colombier setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss); 619*7dd7cddfSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 620*7dd7cddfSDavid du Colombier 621*7dd7cddfSDavid du Colombier kbase = 0xF0000000; 622*7dd7cddfSDavid du Colombier if ((fp->entry & kbase) == kbase) { /* Boot image */ 623*7dd7cddfSDavid du Colombier fp->txtaddr = kbase+sizeof(Exec); 624*7dd7cddfSDavid du Colombier fp->name = "ARM *BSD boot image"; 625*7dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 626*7dd7cddfSDavid du Colombier fp->dataddr = kbase+fp->txtsz; 627*7dd7cddfSDavid du Colombier } 628*7dd7cddfSDavid du Colombier return 1; 629*7dd7cddfSDavid du Colombier } 6303e12c5d1SDavid du Colombier 6313e12c5d1SDavid du Colombier static void 6323e12c5d1SDavid du Colombier settext(Fhdr *fp, long e, long a, long s, long off) 6333e12c5d1SDavid du Colombier { 6343e12c5d1SDavid du Colombier fp->txtaddr = a; 6353e12c5d1SDavid du Colombier fp->entry = e; 6363e12c5d1SDavid du Colombier fp->txtsz = s; 6373e12c5d1SDavid du Colombier fp->txtoff = off; 6383e12c5d1SDavid du Colombier } 6393e12c5d1SDavid du Colombier static void 6403e12c5d1SDavid du Colombier setdata(Fhdr *fp, long a, long s, long off, long bss) 6413e12c5d1SDavid du Colombier { 6423e12c5d1SDavid du Colombier fp->dataddr = a; 6433e12c5d1SDavid du Colombier fp->datsz = s; 6443e12c5d1SDavid du Colombier fp->datoff = off; 6453e12c5d1SDavid du Colombier fp->bsssz = bss; 6463e12c5d1SDavid du Colombier } 6473e12c5d1SDavid du Colombier static void 6483e12c5d1SDavid du Colombier setsym(Fhdr *fp, long sy, long sppc, long lnpc, long symoff) 6493e12c5d1SDavid du Colombier { 6503e12c5d1SDavid du Colombier fp->symsz = sy; 6513e12c5d1SDavid du Colombier fp->symoff = symoff; 6523e12c5d1SDavid du Colombier fp->sppcsz = sppc; 6533e12c5d1SDavid du Colombier fp->sppcoff = fp->symoff+fp->symsz; 6543e12c5d1SDavid du Colombier fp->lnpcsz = lnpc; 6553e12c5d1SDavid du Colombier fp->lnpcoff = fp->sppcoff+fp->sppcsz; 6563e12c5d1SDavid du Colombier } 6573e12c5d1SDavid du Colombier 658219b2ee8SDavid du Colombier 659219b2ee8SDavid du Colombier static long 660219b2ee8SDavid du Colombier _round(long a, long b) 661219b2ee8SDavid du Colombier { 662219b2ee8SDavid du Colombier long w; 663219b2ee8SDavid du Colombier 664219b2ee8SDavid du Colombier w = (a/b)*b; 665219b2ee8SDavid du Colombier if (a!=w) 666219b2ee8SDavid du Colombier w += b; 667219b2ee8SDavid du Colombier return(w); 668219b2ee8SDavid du Colombier } 669