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> 67dd7cddfSDavid 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 */ 167dd7cddfSDavid du Colombier Ehdr; /* in elf.h */ 177dd7cddfSDavid 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 267dd7cddfSDavid du Colombier static int i960boot(int, Fhdr*, ExecHdr*); 277dd7cddfSDavid du Colombier static int nextboot(int, Fhdr*, ExecHdr*); 287dd7cddfSDavid du Colombier static int sparcboot(int, Fhdr*, ExecHdr*); 297dd7cddfSDavid du Colombier static int mipsboot(int, Fhdr*, ExecHdr*); 307dd7cddfSDavid du Colombier static int mips4kboot(int, Fhdr*, ExecHdr*); 317dd7cddfSDavid du Colombier static int common(int, Fhdr*, ExecHdr*); 327dd7cddfSDavid du Colombier static int adotout(int, Fhdr*, ExecHdr*); 337dd7cddfSDavid du Colombier static int elfdotout(int, Fhdr*, ExecHdr*); 347dd7cddfSDavid du Colombier static int armdotout(int, Fhdr*, ExecHdr*); 357dd7cddfSDavid 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 */ 537dd7cddfSDavid du Colombier int (*hparse)(int, Fhdr*, ExecHdr*); 543e12c5d1SDavid du Colombier } ExecTable; 553e12c5d1SDavid du Colombier 563e12c5d1SDavid du Colombier extern Mach mmips; 577dd7cddfSDavid du Colombier extern Mach mmips2le; 587dd7cddfSDavid 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; 647dd7cddfSDavid du Colombier extern Mach m29000; 657dd7cddfSDavid du Colombier extern Mach marm; 667dd7cddfSDavid du Colombier extern Mach mpower; 677dd7cddfSDavid 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 }, 787dd7cddfSDavid du Colombier { M_MAGIC, /* Mips 4.out */ 797dd7cddfSDavid du Colombier "mips 4k plan 9 executable BE", 807dd7cddfSDavid du Colombier FMIPS2BE, 817dd7cddfSDavid du Colombier &mmips2be, 827dd7cddfSDavid du Colombier sizeof(Exec), 837dd7cddfSDavid du Colombier beswal, 847dd7cddfSDavid du Colombier adotout }, 857dd7cddfSDavid du Colombier { N_MAGIC, /* Mips 0.out */ 867dd7cddfSDavid du Colombier "mips 4k plan 9 executable LE", 877dd7cddfSDavid du Colombier FMIPS2LE, 887dd7cddfSDavid du Colombier &mmips2le, 897dd7cddfSDavid du Colombier sizeof(Exec), 907dd7cddfSDavid du Colombier beswal, 917dd7cddfSDavid 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, 102*80ee5cbfSDavid du Colombier &mmips2be, 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 }, 1627dd7cddfSDavid du Colombier { D_MAGIC, /* 29000 9.out */ 1637dd7cddfSDavid du Colombier "29000 plan 9 executable", 1647dd7cddfSDavid du Colombier F29000, 1657dd7cddfSDavid du Colombier &m29000, 1667dd7cddfSDavid du Colombier sizeof(Exec), 1677dd7cddfSDavid du Colombier beswal, 1687dd7cddfSDavid du Colombier adotout }, 1697dd7cddfSDavid du Colombier { Q_MAGIC, /* PowerPC q.out */ 1707dd7cddfSDavid du Colombier "power plan 9 executable", 1717dd7cddfSDavid du Colombier FPOWER, 1727dd7cddfSDavid du Colombier &mpower, 1737dd7cddfSDavid du Colombier sizeof(Exec), 1747dd7cddfSDavid du Colombier beswal, 1757dd7cddfSDavid du Colombier common }, 1767dd7cddfSDavid du Colombier { ELF_MAG, 1777dd7cddfSDavid du Colombier "Irix 5.X Elf executable", 1787dd7cddfSDavid du Colombier FMIPS, 1797dd7cddfSDavid du Colombier &mmips, 1807dd7cddfSDavid du Colombier sizeof(Ehdr), 1817dd7cddfSDavid du Colombier beswal, 1827dd7cddfSDavid du Colombier elfdotout }, 1837dd7cddfSDavid du Colombier { E_MAGIC, /* Arm 5.out */ 1847dd7cddfSDavid du Colombier "Arm plan 9 executable", 1857dd7cddfSDavid du Colombier FARM, 1867dd7cddfSDavid du Colombier &marm, 1877dd7cddfSDavid du Colombier sizeof(Exec), 1887dd7cddfSDavid du Colombier beswal, 1897dd7cddfSDavid du Colombier common }, 1907dd7cddfSDavid du Colombier { (143<<16)|0413, /* (Free|Net)BSD Arm */ 1917dd7cddfSDavid du Colombier "Arm *BSD executable", 1927dd7cddfSDavid du Colombier FARM, 1937dd7cddfSDavid du Colombier &marm, 1947dd7cddfSDavid du Colombier sizeof(Exec), 1957dd7cddfSDavid du Colombier leswal, 1967dd7cddfSDavid du Colombier armdotout }, 1977dd7cddfSDavid du Colombier { L_MAGIC, /* alpha 7.out */ 1987dd7cddfSDavid du Colombier "alpha plan 9 executable", 1997dd7cddfSDavid du Colombier FALPHA, 2007dd7cddfSDavid du Colombier &malpha, 2017dd7cddfSDavid du Colombier sizeof(Exec), 2027dd7cddfSDavid du Colombier beswal, 2037dd7cddfSDavid du Colombier common }, 2047dd7cddfSDavid du Colombier { 0x0700e0c3, /* alpha boot image */ 2057dd7cddfSDavid du Colombier "alpha plan 9 boot image", 2067dd7cddfSDavid du Colombier FALPHAB, 2077dd7cddfSDavid du Colombier &malpha, 2087dd7cddfSDavid du Colombier sizeof(Exec), 2097dd7cddfSDavid du Colombier beswal, 2107dd7cddfSDavid du Colombier alphadotout }, 2113e12c5d1SDavid du Colombier { 0 }, 2123e12c5d1SDavid du Colombier }; 2133e12c5d1SDavid du Colombier 2147dd7cddfSDavid du Colombier Mach *mach = &mi386; /* Global current machine table */ 2157dd7cddfSDavid du Colombier 2167dd7cddfSDavid du Colombier static ExecTable* 2177dd7cddfSDavid du Colombier couldbe4k(ExecTable *mp) 2187dd7cddfSDavid du Colombier { 2197dd7cddfSDavid du Colombier Dir d; 2207dd7cddfSDavid du Colombier ExecTable *f; 2217dd7cddfSDavid du Colombier 2227dd7cddfSDavid du Colombier if(dirstat("/proc/1/regs", &d) < 0) 2237dd7cddfSDavid du Colombier return mp; 2247dd7cddfSDavid du Colombier if(d.length < 32*8) /* R3000 */ 2257dd7cddfSDavid du Colombier return mp; 2267dd7cddfSDavid du Colombier for (f = exectab; f->magic; f++) 2277dd7cddfSDavid du Colombier if(f->magic == M_MAGIC) { 2287dd7cddfSDavid du Colombier f->name = "mips plan 9 executable on mips2 kernel"; 2297dd7cddfSDavid du Colombier return f; 2307dd7cddfSDavid du Colombier } 2317dd7cddfSDavid du Colombier return mp; 2327dd7cddfSDavid du Colombier } 2337dd7cddfSDavid 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; 2407dd7cddfSDavid du Colombier int nb, magic, ret; 2413e12c5d1SDavid du Colombier 2423e12c5d1SDavid du Colombier fp->type = FNONE; 2437dd7cddfSDavid du Colombier nb = read(fd, (char *)&d.e, sizeof(d.e)); 2447dd7cddfSDavid du Colombier if (nb <= 0) 2453e12c5d1SDavid du Colombier return 0; 2467dd7cddfSDavid du Colombier 2477dd7cddfSDavid 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) { 2517dd7cddfSDavid du Colombier if(mp->magic == V_MAGIC) 2527dd7cddfSDavid du Colombier mp = couldbe4k(mp); 2537dd7cddfSDavid 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; 2597dd7cddfSDavid du Colombier ret = mp->hparse(fd, fp, &d); 2603e12c5d1SDavid du Colombier seek(fd, mp->hsize, 0); /* seek to end of header */ 2617dd7cddfSDavid du Colombier break; 2623e12c5d1SDavid du Colombier } 2633e12c5d1SDavid du Colombier } 2647dd7cddfSDavid du Colombier if(mp->magic == 0) 2657dd7cddfSDavid du Colombier werrstr("unknown header type"); 2667dd7cddfSDavid 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 */ 2827dd7cddfSDavid du Colombier static int 2837dd7cddfSDavid du Colombier adotout(int fd, Fhdr *fp, ExecHdr *hp) 2843e12c5d1SDavid du Colombier { 2857dd7cddfSDavid du Colombier long pgsize; 2863e12c5d1SDavid du Colombier 2877dd7cddfSDavid du Colombier USED(fd); 2887dd7cddfSDavid 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); 2947dd7cddfSDavid 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 3007dd7cddfSDavid du Colombier * alpha plan9-style bootable images for axp "headerless" boot 3013e12c5d1SDavid du Colombier * 3023e12c5d1SDavid du Colombier */ 3037dd7cddfSDavid du Colombier static int 3047dd7cddfSDavid du Colombier common(int fd, Fhdr *fp, ExecHdr *hp) 3053e12c5d1SDavid du Colombier { 3067dd7cddfSDavid du Colombier long kbase; 3073e12c5d1SDavid du Colombier 3087dd7cddfSDavid du Colombier adotout(fd, fp, hp); 3097dd7cddfSDavid du Colombier kbase = mach->kbase; 3107dd7cddfSDavid 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; 3247dd7cddfSDavid du Colombier case FARM: 325*80ee5cbfSDavid du Colombier fp->txtaddr = kbase+0x8010; 3267dd7cddfSDavid du Colombier fp->name = "ARM plan 9 boot image"; 3277dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 3287dd7cddfSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 3297dd7cddfSDavid du Colombier return 1; 3307dd7cddfSDavid du Colombier case FALPHA: 3317dd7cddfSDavid du Colombier fp->type = FALPHAB; 3327dd7cddfSDavid du Colombier fp->txtaddr = fp->entry; 3337dd7cddfSDavid du Colombier fp->name = "Alpha plan 9 boot image?"; 3347dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 3357dd7cddfSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 3367dd7cddfSDavid du Colombier break; 3377dd7cddfSDavid du Colombier case FALPHAB: 3387dd7cddfSDavid du Colombier fp->txtaddr = 0x20000000+sizeof(Exec); 3397dd7cddfSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 3407dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 3417dd7cddfSDavid 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 } 3497dd7cddfSDavid du Colombier return 1; 3503e12c5d1SDavid du Colombier } 3513e12c5d1SDavid du Colombier 3523e12c5d1SDavid du Colombier /* 3533e12c5d1SDavid du Colombier * mips bootable image. 3543e12c5d1SDavid du Colombier */ 3557dd7cddfSDavid du Colombier static int 3567dd7cddfSDavid du Colombier mipsboot(int fd, Fhdr *fp, ExecHdr *hp) 3573e12c5d1SDavid du Colombier { 3587dd7cddfSDavid 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 */ 3777dd7cddfSDavid du Colombier return 1; 3783e12c5d1SDavid du Colombier } 379219b2ee8SDavid du Colombier 3803e12c5d1SDavid du Colombier /* 381219b2ee8SDavid du Colombier * mips4k bootable image. 3823e12c5d1SDavid du Colombier */ 3837dd7cddfSDavid du Colombier static int 3847dd7cddfSDavid du Colombier mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) 3853e12c5d1SDavid du Colombier { 3867dd7cddfSDavid 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 */ 4057dd7cddfSDavid du Colombier return 1; 406219b2ee8SDavid du Colombier } 407219b2ee8SDavid du Colombier 4083e12c5d1SDavid du Colombier /* 4093e12c5d1SDavid du Colombier * sparc bootable image 4103e12c5d1SDavid du Colombier */ 4117dd7cddfSDavid du Colombier static int 4127dd7cddfSDavid du Colombier sparcboot(int fd, Fhdr *fp, ExecHdr *hp) 4133e12c5d1SDavid du Colombier { 4147dd7cddfSDavid 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 */ 4227dd7cddfSDavid du Colombier return 1; 4233e12c5d1SDavid du Colombier } 4243e12c5d1SDavid du Colombier 4253e12c5d1SDavid du Colombier /* 4263e12c5d1SDavid du Colombier * next bootable image 4273e12c5d1SDavid du Colombier */ 4287dd7cddfSDavid du Colombier static int 4297dd7cddfSDavid du Colombier nextboot(int fd, Fhdr *fp, ExecHdr *hp) 4303e12c5d1SDavid du Colombier { 4317dd7cddfSDavid 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 */ 4407dd7cddfSDavid du Colombier return 1; 4413e12c5d1SDavid du Colombier } 4423e12c5d1SDavid du Colombier 4433e12c5d1SDavid du Colombier /* 4443e12c5d1SDavid du Colombier * I960 bootable image 4453e12c5d1SDavid du Colombier */ 4467dd7cddfSDavid du Colombier static int 4477dd7cddfSDavid 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 4517dd7cddfSDavid 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 */ 4597dd7cddfSDavid du Colombier return 1; 4603e12c5d1SDavid du Colombier } 4613e12c5d1SDavid du Colombier 4627dd7cddfSDavid du Colombier static Shdr* 4637dd7cddfSDavid du Colombier elfsectbyname(int fd, Ehdr *hp, Shdr *sp, char *name) 4647dd7cddfSDavid du Colombier { 4657dd7cddfSDavid du Colombier int i, offset, n; 4667dd7cddfSDavid du Colombier char s[64]; 4677dd7cddfSDavid du Colombier 4687dd7cddfSDavid du Colombier offset = sp[hp->shstrndx].offset; 4697dd7cddfSDavid du Colombier for(i = 1; i < hp->shnum; i++) { 4707dd7cddfSDavid du Colombier seek(fd, offset+sp[i].name, 0); 4717dd7cddfSDavid du Colombier n = read(fd, s, sizeof(s)-1); 4727dd7cddfSDavid du Colombier if(n < 0) 4737dd7cddfSDavid du Colombier continue; 4747dd7cddfSDavid du Colombier s[n] = 0; 4757dd7cddfSDavid du Colombier if(strcmp(s, name) == 0) 4767dd7cddfSDavid du Colombier return &sp[i]; 4777dd7cddfSDavid du Colombier } 4787dd7cddfSDavid du Colombier return 0; 4797dd7cddfSDavid du Colombier } 4807dd7cddfSDavid du Colombier /* 4817dd7cddfSDavid du Colombier * Decode an Irix 5.x ELF header 4827dd7cddfSDavid du Colombier */ 4837dd7cddfSDavid du Colombier static int 4847dd7cddfSDavid du Colombier elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 4857dd7cddfSDavid du Colombier { 4867dd7cddfSDavid du Colombier 4877dd7cddfSDavid du Colombier Ehdr *ep; 4887dd7cddfSDavid du Colombier Shdr *es, *txt, *init, *s; 4897dd7cddfSDavid du Colombier long addr, size, offset, bsize; 4907dd7cddfSDavid du Colombier 4917dd7cddfSDavid du Colombier ep = &hp->e; 4927dd7cddfSDavid du Colombier if(ep->type != 8 || ep->machine != 2 || ep->version != 1) 4937dd7cddfSDavid du Colombier return 0; 4947dd7cddfSDavid du Colombier 4957dd7cddfSDavid du Colombier fp->magic = ELF_MAG; 4967dd7cddfSDavid du Colombier fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 4977dd7cddfSDavid du Colombier 4987dd7cddfSDavid du Colombier if(ep->shnum <= 0) { 4997dd7cddfSDavid du Colombier werrstr("no ELF header sections"); 5007dd7cddfSDavid du Colombier return 0; 5017dd7cddfSDavid du Colombier } 5027dd7cddfSDavid du Colombier es = malloc(sizeof(Shdr)*ep->shnum); 5037dd7cddfSDavid du Colombier if(es == 0) 5047dd7cddfSDavid du Colombier return 0; 5057dd7cddfSDavid du Colombier 5067dd7cddfSDavid du Colombier seek(fd, ep->shoff, 0); 5077dd7cddfSDavid du Colombier if(read(fd, es, sizeof(Shdr)*ep->shnum) < 0){ 5087dd7cddfSDavid du Colombier free(es); 5097dd7cddfSDavid du Colombier return 0; 5107dd7cddfSDavid du Colombier } 5117dd7cddfSDavid du Colombier 5127dd7cddfSDavid du Colombier txt = elfsectbyname(fd, ep, es, ".text"); 5137dd7cddfSDavid du Colombier init = elfsectbyname(fd, ep, es, ".init"); 5147dd7cddfSDavid du Colombier if(txt == 0 || init == 0 || init != txt+1) 5157dd7cddfSDavid du Colombier goto bad; 5167dd7cddfSDavid du Colombier if(txt->addr+txt->size != init->addr) 5177dd7cddfSDavid du Colombier goto bad; 5187dd7cddfSDavid du Colombier settext(fp, ep->elfentry, txt->addr, txt->size+init->size, txt->offset); 5197dd7cddfSDavid du Colombier 5207dd7cddfSDavid du Colombier addr = 0; 5217dd7cddfSDavid du Colombier offset = 0; 5227dd7cddfSDavid du Colombier size = 0; 5237dd7cddfSDavid du Colombier s = elfsectbyname(fd, ep, es, ".data"); 5247dd7cddfSDavid du Colombier if(s) { 5257dd7cddfSDavid du Colombier addr = s->addr; 5267dd7cddfSDavid du Colombier size = s->size; 5277dd7cddfSDavid du Colombier offset = s->offset; 5287dd7cddfSDavid du Colombier } 5297dd7cddfSDavid du Colombier 5307dd7cddfSDavid du Colombier s = elfsectbyname(fd, ep, es, ".rodata"); 5317dd7cddfSDavid du Colombier if(s) { 5327dd7cddfSDavid du Colombier if(addr){ 5337dd7cddfSDavid du Colombier if(addr+size != s->addr) 5347dd7cddfSDavid du Colombier goto bad; 5357dd7cddfSDavid du Colombier } else { 5367dd7cddfSDavid du Colombier addr = s->addr; 5377dd7cddfSDavid du Colombier offset = s->offset; 5387dd7cddfSDavid du Colombier } 5397dd7cddfSDavid du Colombier size += s->size; 5407dd7cddfSDavid du Colombier } 5417dd7cddfSDavid du Colombier 5427dd7cddfSDavid du Colombier s = elfsectbyname(fd, ep, es, ".got"); 5437dd7cddfSDavid du Colombier if(s) { 5447dd7cddfSDavid du Colombier if(addr){ 5457dd7cddfSDavid du Colombier if(addr+size != s->addr) 5467dd7cddfSDavid du Colombier goto bad; 5477dd7cddfSDavid du Colombier } else { 5487dd7cddfSDavid du Colombier addr = s->addr; 5497dd7cddfSDavid du Colombier offset = s->offset; 5507dd7cddfSDavid du Colombier } 5517dd7cddfSDavid du Colombier size += s->size; 5527dd7cddfSDavid du Colombier } 5537dd7cddfSDavid du Colombier 5547dd7cddfSDavid du Colombier bsize = 0; 5557dd7cddfSDavid du Colombier s = elfsectbyname(fd, ep, es, ".bss"); 5567dd7cddfSDavid du Colombier if(s) { 5577dd7cddfSDavid du Colombier if(addr){ 5587dd7cddfSDavid du Colombier if(addr+size != s->addr) 5597dd7cddfSDavid du Colombier goto bad; 5607dd7cddfSDavid du Colombier } else { 5617dd7cddfSDavid du Colombier addr = s->addr; 5627dd7cddfSDavid du Colombier offset = s->offset; 5637dd7cddfSDavid du Colombier } 5647dd7cddfSDavid du Colombier bsize = s->size; 5657dd7cddfSDavid du Colombier } 5667dd7cddfSDavid du Colombier 5677dd7cddfSDavid du Colombier if(addr == 0) 5687dd7cddfSDavid du Colombier goto bad; 5697dd7cddfSDavid du Colombier 5707dd7cddfSDavid du Colombier setdata(fp, addr, size, offset, bsize); 5717dd7cddfSDavid du Colombier fp->name = "IRIX Elf a.out executable"; 5727dd7cddfSDavid du Colombier free(es); 5737dd7cddfSDavid du Colombier return 1; 5747dd7cddfSDavid du Colombier bad: 5757dd7cddfSDavid du Colombier free(es); 5767dd7cddfSDavid du Colombier werrstr("ELF sections scrambled"); 5777dd7cddfSDavid du Colombier return 0; 5787dd7cddfSDavid du Colombier } 5797dd7cddfSDavid du Colombier 5807dd7cddfSDavid du Colombier /* 5817dd7cddfSDavid du Colombier * alpha bootable 5827dd7cddfSDavid du Colombier */ 5837dd7cddfSDavid du Colombier static int 5847dd7cddfSDavid du Colombier alphadotout(int fd, Fhdr *fp, ExecHdr *hp) 5857dd7cddfSDavid du Colombier { 5867dd7cddfSDavid du Colombier long kbase; 5877dd7cddfSDavid du Colombier 5887dd7cddfSDavid du Colombier USED(fd); 5897dd7cddfSDavid du Colombier settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 5907dd7cddfSDavid du Colombier setdata(fp, fp->txtsz+sizeof(Exec), hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 5917dd7cddfSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 5927dd7cddfSDavid du Colombier 5937dd7cddfSDavid du Colombier /* 5947dd7cddfSDavid du Colombier * Boot images have some of bits <31:28> set: 5957dd7cddfSDavid du Colombier * 0x80400000 kernel 5967dd7cddfSDavid du Colombier * 0x20000000 secondary bootstrap 5977dd7cddfSDavid du Colombier */ 5987dd7cddfSDavid du Colombier kbase = 0xF0000000; 5997dd7cddfSDavid du Colombier if (fp->entry & kbase) { 6007dd7cddfSDavid du Colombier fp->txtaddr = fp->entry; 6017dd7cddfSDavid du Colombier fp->name = "alpha plan 9 boot image"; 6027dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 6037dd7cddfSDavid du Colombier fp->dataddr = fp->entry+fp->txtsz; 6047dd7cddfSDavid du Colombier } 6057dd7cddfSDavid du Colombier return 1; 6067dd7cddfSDavid du Colombier } 6077dd7cddfSDavid du Colombier 6087dd7cddfSDavid du Colombier /* 6097dd7cddfSDavid du Colombier * (Free|Net)BSD ARM header. 6107dd7cddfSDavid du Colombier */ 6117dd7cddfSDavid du Colombier static int 6127dd7cddfSDavid du Colombier armdotout(int fd, Fhdr *fp, ExecHdr *hp) 6137dd7cddfSDavid du Colombier { 6147dd7cddfSDavid du Colombier long kbase; 6157dd7cddfSDavid du Colombier 6167dd7cddfSDavid du Colombier USED(fd); 6177dd7cddfSDavid du Colombier settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 6187dd7cddfSDavid du Colombier setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss); 6197dd7cddfSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 6207dd7cddfSDavid du Colombier 6217dd7cddfSDavid du Colombier kbase = 0xF0000000; 6227dd7cddfSDavid du Colombier if ((fp->entry & kbase) == kbase) { /* Boot image */ 6237dd7cddfSDavid du Colombier fp->txtaddr = kbase+sizeof(Exec); 6247dd7cddfSDavid du Colombier fp->name = "ARM *BSD boot image"; 6257dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 6267dd7cddfSDavid du Colombier fp->dataddr = kbase+fp->txtsz; 6277dd7cddfSDavid du Colombier } 6287dd7cddfSDavid du Colombier return 1; 6297dd7cddfSDavid 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