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{ 154de34a7eSDavid du Colombier struct { 164de34a7eSDavid du Colombier Exec; /* a.out.h */ 174de34a7eSDavid du Colombier uvlong hdr[1]; 184de34a7eSDavid du Colombier }; 194de34a7eSDavid du Colombier Ehdr; /* elf.h */ 20d3993254SDavid du Colombier E64hdr; 214de34a7eSDavid du Colombier struct mipsexec; /* bootexec.h */ 224de34a7eSDavid du Colombier struct mips4kexec; /* bootexec.h */ 234de34a7eSDavid du Colombier struct sparcexec; /* bootexec.h */ 244de34a7eSDavid du Colombier struct nextexec; /* bootexec.h */ 253e12c5d1SDavid du Colombier } e; 263e12c5d1SDavid du Colombier long dummy; /* padding to ensure extra long */ 273e12c5d1SDavid du Colombier } ExecHdr; 283e12c5d1SDavid du Colombier 297dd7cddfSDavid du Colombier static int nextboot(int, Fhdr*, ExecHdr*); 307dd7cddfSDavid du Colombier static int sparcboot(int, Fhdr*, ExecHdr*); 317dd7cddfSDavid du Colombier static int mipsboot(int, Fhdr*, ExecHdr*); 327dd7cddfSDavid du Colombier static int mips4kboot(int, Fhdr*, ExecHdr*); 337dd7cddfSDavid du Colombier static int common(int, Fhdr*, ExecHdr*); 344de34a7eSDavid du Colombier static int commonllp64(int, Fhdr*, ExecHdr*); 357dd7cddfSDavid du Colombier static int adotout(int, Fhdr*, ExecHdr*); 367dd7cddfSDavid du Colombier static int elfdotout(int, Fhdr*, ExecHdr*); 377dd7cddfSDavid du Colombier static int armdotout(int, Fhdr*, ExecHdr*); 384de34a7eSDavid du Colombier static void setsym(Fhdr*, long, long, long, vlong); 394de34a7eSDavid du Colombier static void setdata(Fhdr*, uvlong, long, vlong, long); 404de34a7eSDavid du Colombier static void settext(Fhdr*, uvlong, uvlong, long, vlong); 414de34a7eSDavid du Colombier static void hswal(void*, int, ulong(*)(ulong)); 424de34a7eSDavid du Colombier static uvlong _round(uvlong, ulong); 433e12c5d1SDavid du Colombier 443e12c5d1SDavid du Colombier /* 453e12c5d1SDavid du Colombier * definition of per-executable file type structures 463e12c5d1SDavid du Colombier */ 473e12c5d1SDavid du Colombier 483e12c5d1SDavid du Colombier typedef struct Exectable{ 493e12c5d1SDavid du Colombier long magic; /* big-endian magic number of file */ 503e12c5d1SDavid du Colombier char *name; /* executable identifier */ 5112fd1c83SDavid du Colombier char *dlmname; /* dynamically loadable module identifier */ 522cca75a1SDavid du Colombier uchar type; /* Internal code */ 532cca75a1SDavid du Colombier uchar _magic; /* _MAGIC() magic */ 543e12c5d1SDavid du Colombier Mach *mach; /* Per-machine data */ 554de34a7eSDavid du Colombier long hsize; /* header size */ 56e887ea33SDavid du Colombier ulong (*swal)(ulong); /* beswal or leswal */ 577dd7cddfSDavid du Colombier int (*hparse)(int, Fhdr*, ExecHdr*); 583e12c5d1SDavid du Colombier } ExecTable; 593e12c5d1SDavid du Colombier 603e12c5d1SDavid du Colombier extern Mach mmips; 617dd7cddfSDavid du Colombier extern Mach mmips2le; 627dd7cddfSDavid du Colombier extern Mach mmips2be; 633e12c5d1SDavid du Colombier extern Mach msparc; 64b0dcc5a8SDavid du Colombier extern Mach msparc64; 653e12c5d1SDavid du Colombier extern Mach m68020; 663e12c5d1SDavid du Colombier extern Mach mi386; 67b0dcc5a8SDavid du Colombier extern Mach mamd64; 687dd7cddfSDavid du Colombier extern Mach marm; 697dd7cddfSDavid du Colombier extern Mach mpower; 7047ad9175SDavid du Colombier extern Mach mpower64; 718a34c8c5SDavid du Colombier extern Mach malpha; 723e12c5d1SDavid du Colombier 733e12c5d1SDavid du Colombier ExecTable exectab[] = 743e12c5d1SDavid du Colombier { 753e12c5d1SDavid du Colombier { V_MAGIC, /* Mips v.out */ 769cd23d14SDavid du Colombier "mips plan 9 executable BE", 779cd23d14SDavid du Colombier "mips plan 9 dlm BE", 783e12c5d1SDavid du Colombier FMIPS, 792cca75a1SDavid du Colombier 1, 803e12c5d1SDavid du Colombier &mmips, 813e12c5d1SDavid du Colombier sizeof(Exec), 823e12c5d1SDavid du Colombier beswal, 833e12c5d1SDavid du Colombier adotout }, 849cd23d14SDavid du Colombier { P_MAGIC, /* Mips 0.out (r3k le) */ 859cd23d14SDavid du Colombier "mips plan 9 executable LE", 869cd23d14SDavid du Colombier "mips plan 9 dlm LE", 879cd23d14SDavid du Colombier FMIPSLE, 889cd23d14SDavid du Colombier 1, 899cd23d14SDavid du Colombier &mmips, 909cd23d14SDavid du Colombier sizeof(Exec), 919cd23d14SDavid du Colombier beswal, 929cd23d14SDavid du Colombier adotout }, 937dd7cddfSDavid du Colombier { M_MAGIC, /* Mips 4.out */ 947dd7cddfSDavid du Colombier "mips 4k plan 9 executable BE", 9512fd1c83SDavid du Colombier "mips 4k plan 9 dlm BE", 967dd7cddfSDavid du Colombier FMIPS2BE, 972cca75a1SDavid du Colombier 1, 987dd7cddfSDavid du Colombier &mmips2be, 997dd7cddfSDavid du Colombier sizeof(Exec), 1007dd7cddfSDavid du Colombier beswal, 1017dd7cddfSDavid du Colombier adotout }, 1027dd7cddfSDavid du Colombier { N_MAGIC, /* Mips 0.out */ 1037dd7cddfSDavid du Colombier "mips 4k plan 9 executable LE", 10412fd1c83SDavid du Colombier "mips 4k plan 9 dlm LE", 1057dd7cddfSDavid du Colombier FMIPS2LE, 1062cca75a1SDavid du Colombier 1, 1077dd7cddfSDavid du Colombier &mmips2le, 1087dd7cddfSDavid du Colombier sizeof(Exec), 1097dd7cddfSDavid du Colombier beswal, 1107dd7cddfSDavid du Colombier adotout }, 1113e12c5d1SDavid du Colombier { 0x160<<16, /* Mips boot image */ 1123e12c5d1SDavid du Colombier "mips plan 9 boot image", 11312fd1c83SDavid du Colombier nil, 1143e12c5d1SDavid du Colombier FMIPSB, 1152cca75a1SDavid du Colombier 0, 1163e12c5d1SDavid du Colombier &mmips, 1173e12c5d1SDavid du Colombier sizeof(struct mipsexec), 1183e12c5d1SDavid du Colombier beswal, 1193e12c5d1SDavid du Colombier mipsboot }, 120219b2ee8SDavid du Colombier { (0x160<<16)|3, /* Mips boot image */ 121219b2ee8SDavid du Colombier "mips 4k plan 9 boot image", 12212fd1c83SDavid du Colombier nil, 123219b2ee8SDavid du Colombier FMIPSB, 1242cca75a1SDavid du Colombier 0, 12580ee5cbfSDavid du Colombier &mmips2be, 126219b2ee8SDavid du Colombier sizeof(struct mips4kexec), 1273e12c5d1SDavid du Colombier beswal, 128219b2ee8SDavid du Colombier mips4kboot }, 1293e12c5d1SDavid du Colombier { K_MAGIC, /* Sparc k.out */ 1303e12c5d1SDavid du Colombier "sparc plan 9 executable", 13112fd1c83SDavid du Colombier "sparc plan 9 dlm", 1323e12c5d1SDavid du Colombier FSPARC, 1332cca75a1SDavid du Colombier 1, 1343e12c5d1SDavid du Colombier &msparc, 1353e12c5d1SDavid du Colombier sizeof(Exec), 1363e12c5d1SDavid du Colombier beswal, 1373e12c5d1SDavid du Colombier adotout }, 1383e12c5d1SDavid du Colombier { 0x01030107, /* Sparc boot image */ 1393e12c5d1SDavid du Colombier "sparc plan 9 boot image", 14012fd1c83SDavid du Colombier nil, 1413e12c5d1SDavid du Colombier FSPARCB, 1422cca75a1SDavid du Colombier 0, 1433e12c5d1SDavid du Colombier &msparc, 1443e12c5d1SDavid du Colombier sizeof(struct sparcexec), 1453e12c5d1SDavid du Colombier beswal, 1463e12c5d1SDavid du Colombier sparcboot }, 147b0dcc5a8SDavid du Colombier { U_MAGIC, /* Sparc64 u.out */ 148b0dcc5a8SDavid du Colombier "sparc64 plan 9 executable", 149b0dcc5a8SDavid du Colombier "sparc64 plan 9 dlm", 150b0dcc5a8SDavid du Colombier FSPARC64, 1512cca75a1SDavid du Colombier 1, 152b0dcc5a8SDavid du Colombier &msparc64, 153b0dcc5a8SDavid du Colombier sizeof(Exec), 154b0dcc5a8SDavid du Colombier beswal, 155b0dcc5a8SDavid du Colombier adotout }, 1563e12c5d1SDavid du Colombier { A_MAGIC, /* 68020 2.out & boot image */ 1573e12c5d1SDavid du Colombier "68020 plan 9 executable", 15812fd1c83SDavid du Colombier "68020 plan 9 dlm", 1593e12c5d1SDavid du Colombier F68020, 1602cca75a1SDavid du Colombier 1, 1613e12c5d1SDavid du Colombier &m68020, 1623e12c5d1SDavid du Colombier sizeof(Exec), 1633e12c5d1SDavid du Colombier beswal, 1643e12c5d1SDavid du Colombier common }, 1653e12c5d1SDavid du Colombier { 0xFEEDFACE, /* Next boot image */ 1663e12c5d1SDavid du Colombier "next plan 9 boot image", 16712fd1c83SDavid du Colombier nil, 1683e12c5d1SDavid du Colombier FNEXTB, 1692cca75a1SDavid du Colombier 0, 1703e12c5d1SDavid du Colombier &m68020, 1713e12c5d1SDavid du Colombier sizeof(struct nextexec), 1723e12c5d1SDavid du Colombier beswal, 1733e12c5d1SDavid du Colombier nextboot }, 1743e12c5d1SDavid du Colombier { I_MAGIC, /* I386 8.out & boot image */ 1753e12c5d1SDavid du Colombier "386 plan 9 executable", 17612fd1c83SDavid du Colombier "386 plan 9 dlm", 1773e12c5d1SDavid du Colombier FI386, 1782cca75a1SDavid du Colombier 1, 1793e12c5d1SDavid du Colombier &mi386, 1803e12c5d1SDavid du Colombier sizeof(Exec), 1813e12c5d1SDavid du Colombier beswal, 1823e12c5d1SDavid du Colombier common }, 183b0dcc5a8SDavid du Colombier { S_MAGIC, /* amd64 6.out & boot image */ 184b0dcc5a8SDavid du Colombier "amd64 plan 9 executable", 185b0dcc5a8SDavid du Colombier "amd64 plan 9 dlm", 186b0dcc5a8SDavid du Colombier FAMD64, 1872cca75a1SDavid du Colombier 1, 188b0dcc5a8SDavid du Colombier &mamd64, 1894de34a7eSDavid du Colombier sizeof(Exec)+8, 190e887ea33SDavid du Colombier nil, 1914de34a7eSDavid du Colombier commonllp64 }, 1929a747e4fSDavid du Colombier { Q_MAGIC, /* PowerPC q.out & boot image */ 1937dd7cddfSDavid du Colombier "power plan 9 executable", 19412fd1c83SDavid du Colombier "power plan 9 dlm", 1957dd7cddfSDavid du Colombier FPOWER, 1962cca75a1SDavid du Colombier 1, 1977dd7cddfSDavid du Colombier &mpower, 1987dd7cddfSDavid du Colombier sizeof(Exec), 1997dd7cddfSDavid du Colombier beswal, 2007dd7cddfSDavid du Colombier common }, 20147ad9175SDavid du Colombier { T_MAGIC, /* power64 9.out & boot image */ 20247ad9175SDavid du Colombier "power64 plan 9 executable", 20347ad9175SDavid du Colombier "power64 plan 9 dlm", 20447ad9175SDavid du Colombier FPOWER64, 20547ad9175SDavid du Colombier 1, 20647ad9175SDavid du Colombier &mpower64, 20747ad9175SDavid du Colombier sizeof(Exec)+8, 208e887ea33SDavid du Colombier nil, 20947ad9175SDavid du Colombier commonllp64 }, 210d3993254SDavid du Colombier { ELF_MAG, /* any ELF */ 211b0dcc5a8SDavid du Colombier "elf executable", 21212fd1c83SDavid du Colombier nil, 21370b8e010SDavid du Colombier FNONE, 2142cca75a1SDavid du Colombier 0, 21570b8e010SDavid du Colombier &mi386, 2167dd7cddfSDavid du Colombier sizeof(Ehdr), 2174de34a7eSDavid du Colombier nil, 2187dd7cddfSDavid du Colombier elfdotout }, 21941fb754aSDavid du Colombier { E_MAGIC, /* Arm 5.out and boot image */ 220b0dcc5a8SDavid du Colombier "arm plan 9 executable", 221b0dcc5a8SDavid du Colombier "arm plan 9 dlm", 2227dd7cddfSDavid du Colombier FARM, 2232cca75a1SDavid du Colombier 1, 2247dd7cddfSDavid du Colombier &marm, 2257dd7cddfSDavid du Colombier sizeof(Exec), 2267dd7cddfSDavid du Colombier beswal, 2277dd7cddfSDavid du Colombier common }, 2287dd7cddfSDavid du Colombier { (143<<16)|0413, /* (Free|Net)BSD Arm */ 229b0dcc5a8SDavid du Colombier "arm *bsd executable", 23012fd1c83SDavid du Colombier nil, 2317dd7cddfSDavid du Colombier FARM, 2322cca75a1SDavid du Colombier 0, 2337dd7cddfSDavid du Colombier &marm, 2347dd7cddfSDavid du Colombier sizeof(Exec), 2357dd7cddfSDavid du Colombier leswal, 2367dd7cddfSDavid du Colombier armdotout }, 2378a34c8c5SDavid du Colombier { L_MAGIC, /* alpha 7.out */ 2388a34c8c5SDavid du Colombier "alpha plan 9 executable", 2398a34c8c5SDavid du Colombier "alpha plan 9 dlm", 2408a34c8c5SDavid du Colombier FALPHA, 2418a34c8c5SDavid du Colombier 1, 2428a34c8c5SDavid du Colombier &malpha, 2438a34c8c5SDavid du Colombier sizeof(Exec), 2448a34c8c5SDavid du Colombier beswal, 2458a34c8c5SDavid du Colombier common }, 2468a34c8c5SDavid du Colombier { 0x0700e0c3, /* alpha boot image */ 2478a34c8c5SDavid du Colombier "alpha plan 9 boot image", 2488a34c8c5SDavid du Colombier nil, 2498a34c8c5SDavid du Colombier FALPHA, 2508a34c8c5SDavid du Colombier 0, 2518a34c8c5SDavid du Colombier &malpha, 2528a34c8c5SDavid du Colombier sizeof(Exec), 2538a34c8c5SDavid du Colombier beswal, 2548a34c8c5SDavid du Colombier common }, 2553e12c5d1SDavid du Colombier { 0 }, 2563e12c5d1SDavid du Colombier }; 2573e12c5d1SDavid du Colombier 2587dd7cddfSDavid du Colombier Mach *mach = &mi386; /* Global current machine table */ 2597dd7cddfSDavid du Colombier 2607dd7cddfSDavid du Colombier static ExecTable* 2617dd7cddfSDavid du Colombier couldbe4k(ExecTable *mp) 2627dd7cddfSDavid du Colombier { 2639a747e4fSDavid du Colombier Dir *d; 2647dd7cddfSDavid du Colombier ExecTable *f; 2657dd7cddfSDavid du Colombier 2669a747e4fSDavid du Colombier if((d=dirstat("/proc/1/regs")) == nil) 2677dd7cddfSDavid du Colombier return mp; 2689a747e4fSDavid du Colombier if(d->length < 32*8){ /* R3000 */ 2699a747e4fSDavid du Colombier free(d); 2707dd7cddfSDavid du Colombier return mp; 2719a747e4fSDavid du Colombier } 2729a747e4fSDavid du Colombier free(d); 2737dd7cddfSDavid du Colombier for (f = exectab; f->magic; f++) 2747dd7cddfSDavid du Colombier if(f->magic == M_MAGIC) { 2757dd7cddfSDavid du Colombier f->name = "mips plan 9 executable on mips2 kernel"; 2767dd7cddfSDavid du Colombier return f; 2777dd7cddfSDavid du Colombier } 2787dd7cddfSDavid du Colombier return mp; 2797dd7cddfSDavid du Colombier } 2807dd7cddfSDavid du Colombier 2813e12c5d1SDavid du Colombier int 2823e12c5d1SDavid du Colombier crackhdr(int fd, Fhdr *fp) 2833e12c5d1SDavid du Colombier { 2843e12c5d1SDavid du Colombier ExecTable *mp; 2853e12c5d1SDavid du Colombier ExecHdr d; 2864de34a7eSDavid du Colombier int nb, ret; 2874de34a7eSDavid du Colombier ulong magic; 2883e12c5d1SDavid du Colombier 2893e12c5d1SDavid du Colombier fp->type = FNONE; 2907dd7cddfSDavid du Colombier nb = read(fd, (char *)&d.e, sizeof(d.e)); 2917dd7cddfSDavid du Colombier if (nb <= 0) 2923e12c5d1SDavid du Colombier return 0; 2937dd7cddfSDavid du Colombier 2947dd7cddfSDavid du Colombier ret = 0; 2952cca75a1SDavid du Colombier magic = beswal(d.e.magic); /* big-endian */ 2963e12c5d1SDavid du Colombier for (mp = exectab; mp->magic; mp++) { 29712fd1c83SDavid du Colombier if (nb < mp->hsize) 29812fd1c83SDavid du Colombier continue; 2992cca75a1SDavid du Colombier 3002cca75a1SDavid du Colombier /* 3012cca75a1SDavid du Colombier * The magic number has morphed into something 3022cca75a1SDavid du Colombier * with fields (the straw was DYN_MAGIC) so now 3032cca75a1SDavid du Colombier * a flag is needed in Fhdr to distinguish _MAGIC() 3042cca75a1SDavid du Colombier * magic numbers from foreign magic numbers. 3052cca75a1SDavid du Colombier * 3062cca75a1SDavid du Colombier * This code is creaking a bit and if it has to 3072cca75a1SDavid du Colombier * be modified/extended much more it's probably 3082cca75a1SDavid du Colombier * time to step back and redo it all. 3092cca75a1SDavid du Colombier */ 3102cca75a1SDavid du Colombier if(mp->_magic){ 3112cca75a1SDavid du Colombier if(mp->magic != (magic & ~DYN_MAGIC)) 3122cca75a1SDavid du Colombier continue; 3132cca75a1SDavid du Colombier 3147dd7cddfSDavid du Colombier if(mp->magic == V_MAGIC) 3157dd7cddfSDavid du Colombier mp = couldbe4k(mp); 3167dd7cddfSDavid du Colombier 31712fd1c83SDavid du Colombier if ((magic & DYN_MAGIC) && mp->dlmname != nil) 31812fd1c83SDavid du Colombier fp->name = mp->dlmname; 31912fd1c83SDavid du Colombier else 3203e12c5d1SDavid du Colombier fp->name = mp->name; 3212cca75a1SDavid du Colombier } 3222cca75a1SDavid du Colombier else{ 3232cca75a1SDavid du Colombier if(mp->magic != magic) 3242cca75a1SDavid du Colombier continue; 3252cca75a1SDavid du Colombier fp->name = mp->name; 3262cca75a1SDavid du Colombier } 3272cca75a1SDavid du Colombier fp->type = mp->type; 3282cca75a1SDavid du Colombier fp->hdrsz = mp->hsize; /* will be zero on bootables */ 3292cca75a1SDavid du Colombier fp->_magic = mp->_magic; 3302cca75a1SDavid du Colombier fp->magic = magic; 3312cca75a1SDavid du Colombier 3323e12c5d1SDavid du Colombier mach = mp->mach; 3334de34a7eSDavid du Colombier if(mp->swal != nil) 3344de34a7eSDavid du Colombier hswal(&d, sizeof(d.e)/sizeof(ulong), mp->swal); 3357dd7cddfSDavid du Colombier ret = mp->hparse(fd, fp, &d); 3363e12c5d1SDavid du Colombier seek(fd, mp->hsize, 0); /* seek to end of header */ 3377dd7cddfSDavid du Colombier break; 3383e12c5d1SDavid du Colombier } 3397dd7cddfSDavid du Colombier if(mp->magic == 0) 3407dd7cddfSDavid du Colombier werrstr("unknown header type"); 3417dd7cddfSDavid du Colombier return ret; 3423e12c5d1SDavid du Colombier } 3434de34a7eSDavid du Colombier 3443e12c5d1SDavid du Colombier /* 3453e12c5d1SDavid du Colombier * Convert header to canonical form 3463e12c5d1SDavid du Colombier */ 3473e12c5d1SDavid du Colombier static void 3484de34a7eSDavid du Colombier hswal(void *v, int n, ulong (*swap)(ulong)) 3493e12c5d1SDavid du Colombier { 3504de34a7eSDavid du Colombier ulong *ulp; 3514de34a7eSDavid du Colombier 3524de34a7eSDavid du Colombier for(ulp = v; n--; ulp++) 3534de34a7eSDavid du Colombier *ulp = (*swap)(*ulp); 3543e12c5d1SDavid du Colombier } 3554de34a7eSDavid du Colombier 35670b8e010SDavid du Colombier /* 3573e12c5d1SDavid du Colombier * Crack a normal a.out-type header 3583e12c5d1SDavid du Colombier */ 3597dd7cddfSDavid du Colombier static int 3607dd7cddfSDavid du Colombier adotout(int fd, Fhdr *fp, ExecHdr *hp) 3613e12c5d1SDavid du Colombier { 3627dd7cddfSDavid du Colombier long pgsize; 3633e12c5d1SDavid du Colombier 3647dd7cddfSDavid du Colombier USED(fd); 3657dd7cddfSDavid du Colombier pgsize = mach->pgsize; 366219b2ee8SDavid du Colombier settext(fp, hp->e.entry, pgsize+sizeof(Exec), 367219b2ee8SDavid du Colombier hp->e.text, sizeof(Exec)); 368219b2ee8SDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz+sizeof(Exec), pgsize), 369219b2ee8SDavid du Colombier hp->e.data, fp->txtsz+sizeof(Exec), hp->e.bss); 3703e12c5d1SDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 3717dd7cddfSDavid du Colombier return 1; 3723e12c5d1SDavid du Colombier } 3733e12c5d1SDavid du Colombier 3744de34a7eSDavid du Colombier static void 3754de34a7eSDavid du Colombier commonboot(Fhdr *fp) 3764de34a7eSDavid du Colombier { 3772cca75a1SDavid du Colombier if (!(fp->entry & mach->ktmask)) 3784de34a7eSDavid du Colombier return; 3794de34a7eSDavid du Colombier 3804de34a7eSDavid du Colombier switch(fp->type) { /* boot image */ 3814de34a7eSDavid du Colombier case F68020: 3824de34a7eSDavid du Colombier fp->type = F68020B; 3834de34a7eSDavid du Colombier fp->name = "68020 plan 9 boot image"; 3844de34a7eSDavid du Colombier break; 3854de34a7eSDavid du Colombier case FI386: 3864de34a7eSDavid du Colombier fp->type = FI386B; 3874de34a7eSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 3884de34a7eSDavid du Colombier fp->name = "386 plan 9 boot image"; 3894de34a7eSDavid du Colombier fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 3904de34a7eSDavid du Colombier break; 3914de34a7eSDavid du Colombier case FARM: 39241fb754aSDavid du Colombier fp->type = FARMB; 39341fb754aSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 3944de34a7eSDavid du Colombier fp->name = "ARM plan 9 boot image"; 39541fb754aSDavid du Colombier fp->dataddr = _round(fp->txtaddr+fp->txtsz, mach->pgsize); 3964de34a7eSDavid du Colombier return; 3978a34c8c5SDavid du Colombier case FALPHA: 3988a34c8c5SDavid du Colombier fp->type = FALPHAB; 3998a34c8c5SDavid du Colombier fp->txtaddr = (u32int)fp->entry; 4008a34c8c5SDavid du Colombier fp->name = "alpha plan 9 boot image"; 4018a34c8c5SDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 4028a34c8c5SDavid du Colombier break; 4034de34a7eSDavid du Colombier case FPOWER: 4044de34a7eSDavid du Colombier fp->type = FPOWERB; 4054de34a7eSDavid du Colombier fp->txtaddr = (u32int)fp->entry; 4064de34a7eSDavid du Colombier fp->name = "power plan 9 boot image"; 4074de34a7eSDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 4084de34a7eSDavid du Colombier break; 4094de34a7eSDavid du Colombier case FAMD64: 4104de34a7eSDavid du Colombier fp->type = FAMD64B; 4114de34a7eSDavid du Colombier fp->txtaddr = fp->entry; 4124de34a7eSDavid du Colombier fp->name = "amd64 plan 9 boot image"; 41355a30970SDavid du Colombier fp->dataddr = _round(fp->txtaddr+fp->txtsz, 4096); 4144de34a7eSDavid du Colombier break; 415d3993254SDavid du Colombier case FPOWER64: 416d3993254SDavid du Colombier fp->type = FPOWER64B; 417d3993254SDavid du Colombier fp->txtaddr = fp->entry; 418d3993254SDavid du Colombier fp->name = "power64 plan 9 boot image"; 419d3993254SDavid du Colombier fp->dataddr = fp->txtaddr+fp->txtsz; 420d3993254SDavid du Colombier break; 4214de34a7eSDavid du Colombier default: 4224de34a7eSDavid du Colombier return; 4234de34a7eSDavid du Colombier } 4244de34a7eSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 4254de34a7eSDavid du Colombier } 4264de34a7eSDavid du Colombier 4273e12c5d1SDavid du Colombier /* 4282cca75a1SDavid du Colombier * _MAGIC() style headers and 4297dd7cddfSDavid du Colombier * alpha plan9-style bootable images for axp "headerless" boot 4303e12c5d1SDavid du Colombier * 4313e12c5d1SDavid du Colombier */ 4327dd7cddfSDavid du Colombier static int 4337dd7cddfSDavid du Colombier common(int fd, Fhdr *fp, ExecHdr *hp) 4343e12c5d1SDavid du Colombier { 4357dd7cddfSDavid du Colombier adotout(fd, fp, hp); 4369a747e4fSDavid du Colombier if(hp->e.magic & DYN_MAGIC) { 4379a747e4fSDavid du Colombier fp->txtaddr = 0; 4389a747e4fSDavid du Colombier fp->dataddr = fp->txtsz; 4399a747e4fSDavid du Colombier return 1; 4409a747e4fSDavid du Colombier } 4414de34a7eSDavid du Colombier commonboot(fp); 4427dd7cddfSDavid du Colombier return 1; 4433e12c5d1SDavid du Colombier } 4444de34a7eSDavid du Colombier 4454de34a7eSDavid du Colombier static int 4464de34a7eSDavid du Colombier commonllp64(int, Fhdr *fp, ExecHdr *hp) 4474de34a7eSDavid du Colombier { 4484de34a7eSDavid du Colombier long pgsize; 4494de34a7eSDavid du Colombier uvlong entry; 4504de34a7eSDavid du Colombier 451e887ea33SDavid du Colombier hswal(&hp->e, sizeof(Exec)/sizeof(long), beswal); 4524de34a7eSDavid du Colombier if(!(hp->e.magic & HDR_MAGIC)) 4534de34a7eSDavid du Colombier return 0; 4544de34a7eSDavid du Colombier 4554de34a7eSDavid du Colombier /* 4564de34a7eSDavid du Colombier * There can be more magic here if the 4574de34a7eSDavid du Colombier * header ever needs more expansion. 4584de34a7eSDavid du Colombier * For now just catch use of any of the 4594de34a7eSDavid du Colombier * unused bits. 4604de34a7eSDavid du Colombier */ 4614de34a7eSDavid du Colombier if((hp->e.magic & ~DYN_MAGIC)>>16) 4624de34a7eSDavid du Colombier return 0; 4634de34a7eSDavid du Colombier entry = beswav(hp->e.hdr[0]); 4644de34a7eSDavid du Colombier 4654de34a7eSDavid du Colombier pgsize = mach->pgsize; 4664de34a7eSDavid du Colombier settext(fp, entry, pgsize+fp->hdrsz, hp->e.text, fp->hdrsz); 4674de34a7eSDavid du Colombier setdata(fp, _round(pgsize+fp->txtsz+fp->hdrsz, pgsize), 4684de34a7eSDavid du Colombier hp->e.data, fp->txtsz+fp->hdrsz, hp->e.bss); 4694de34a7eSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 4704de34a7eSDavid du Colombier 4714de34a7eSDavid du Colombier if(hp->e.magic & DYN_MAGIC) { 4724de34a7eSDavid du Colombier fp->txtaddr = 0; 4734de34a7eSDavid du Colombier fp->dataddr = fp->txtsz; 4744de34a7eSDavid du Colombier return 1; 4753e12c5d1SDavid du Colombier } 4764de34a7eSDavid du Colombier commonboot(fp); 4777dd7cddfSDavid du Colombier return 1; 4783e12c5d1SDavid du Colombier } 4793e12c5d1SDavid du Colombier 4803e12c5d1SDavid du Colombier /* 4813e12c5d1SDavid du Colombier * mips bootable image. 4823e12c5d1SDavid du Colombier */ 4837dd7cddfSDavid du Colombier static int 4847dd7cddfSDavid du Colombier mipsboot(int fd, Fhdr *fp, ExecHdr *hp) 4853e12c5d1SDavid du Colombier { 4867dd7cddfSDavid du Colombier USED(fd); 4872cca75a1SDavid du Colombier fp->type = FMIPSB; 4883e12c5d1SDavid du Colombier switch(hp->e.amagic) { 4893e12c5d1SDavid du Colombier default: 4903e12c5d1SDavid du Colombier case 0407: /* some kind of mips */ 4912cca75a1SDavid du Colombier settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start, 4922cca75a1SDavid du Colombier hp->e.tsize, sizeof(struct mipsexec)+4); 4932cca75a1SDavid du Colombier setdata(fp, (u32int)hp->e.data_start, hp->e.dsize, 4943e12c5d1SDavid du Colombier fp->txtoff+hp->e.tsize, hp->e.bsize); 4953e12c5d1SDavid du Colombier break; 4963e12c5d1SDavid du Colombier case 0413: /* some kind of mips */ 4972cca75a1SDavid du Colombier settext(fp, (u32int)hp->e.mentry, (u32int)hp->e.text_start, 4982cca75a1SDavid du Colombier hp->e.tsize, 0); 4992cca75a1SDavid du Colombier setdata(fp, (u32int)hp->e.data_start, hp->e.dsize, 5002cca75a1SDavid du Colombier hp->e.tsize, hp->e.bsize); 5013e12c5d1SDavid du Colombier break; 5023e12c5d1SDavid du Colombier } 5033e12c5d1SDavid du Colombier setsym(fp, hp->e.nsyms, 0, hp->e.pcsize, hp->e.symptr); 504219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 5057dd7cddfSDavid du Colombier return 1; 5063e12c5d1SDavid du Colombier } 507219b2ee8SDavid du Colombier 5083e12c5d1SDavid du Colombier /* 509219b2ee8SDavid du Colombier * mips4k bootable image. 5103e12c5d1SDavid du Colombier */ 5117dd7cddfSDavid du Colombier static int 5127dd7cddfSDavid du Colombier mips4kboot(int fd, Fhdr *fp, ExecHdr *hp) 5133e12c5d1SDavid du Colombier { 5147dd7cddfSDavid du Colombier USED(fd); 5152cca75a1SDavid du Colombier fp->type = FMIPSB; 516219b2ee8SDavid du Colombier switch(hp->e.h.amagic) { 517219b2ee8SDavid du Colombier default: 518219b2ee8SDavid du Colombier case 0407: /* some kind of mips */ 5192cca75a1SDavid du Colombier settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start, 5202cca75a1SDavid du Colombier hp->e.h.tsize, sizeof(struct mips4kexec)); 5212cca75a1SDavid du Colombier setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize, 522219b2ee8SDavid du Colombier fp->txtoff+hp->e.h.tsize, hp->e.h.bsize); 523219b2ee8SDavid du Colombier break; 524219b2ee8SDavid du Colombier case 0413: /* some kind of mips */ 5252cca75a1SDavid du Colombier settext(fp, (u32int)hp->e.h.mentry, (u32int)hp->e.h.text_start, 5262cca75a1SDavid du Colombier hp->e.h.tsize, 0); 5272cca75a1SDavid du Colombier setdata(fp, (u32int)hp->e.h.data_start, hp->e.h.dsize, 5282cca75a1SDavid du Colombier hp->e.h.tsize, hp->e.h.bsize); 529219b2ee8SDavid du Colombier break; 5303e12c5d1SDavid du Colombier } 531219b2ee8SDavid du Colombier setsym(fp, hp->e.h.nsyms, 0, hp->e.h.pcsize, hp->e.h.symptr); 532219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 5337dd7cddfSDavid du Colombier return 1; 534219b2ee8SDavid du Colombier } 535219b2ee8SDavid du Colombier 5363e12c5d1SDavid du Colombier /* 5373e12c5d1SDavid du Colombier * sparc bootable image 5383e12c5d1SDavid du Colombier */ 5397dd7cddfSDavid du Colombier static int 5407dd7cddfSDavid du Colombier sparcboot(int fd, Fhdr *fp, ExecHdr *hp) 5413e12c5d1SDavid du Colombier { 5427dd7cddfSDavid du Colombier USED(fd); 5433e12c5d1SDavid du Colombier fp->type = FSPARCB; 5443e12c5d1SDavid du Colombier settext(fp, hp->e.sentry, hp->e.sentry, hp->e.stext, 5453e12c5d1SDavid du Colombier sizeof(struct sparcexec)); 5463e12c5d1SDavid du Colombier setdata(fp, hp->e.sentry+hp->e.stext, hp->e.sdata, 5473e12c5d1SDavid du Colombier fp->txtoff+hp->e.stext, hp->e.sbss); 5483e12c5d1SDavid du Colombier setsym(fp, hp->e.ssyms, 0, hp->e.sdrsize, fp->datoff+hp->e.sdata); 549219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 5507dd7cddfSDavid du Colombier return 1; 5513e12c5d1SDavid du Colombier } 5523e12c5d1SDavid du Colombier 5533e12c5d1SDavid du Colombier /* 5543e12c5d1SDavid du Colombier * next bootable image 5553e12c5d1SDavid du Colombier */ 5567dd7cddfSDavid du Colombier static int 5577dd7cddfSDavid du Colombier nextboot(int fd, Fhdr *fp, ExecHdr *hp) 5583e12c5d1SDavid du Colombier { 5597dd7cddfSDavid du Colombier USED(fd); 5603e12c5d1SDavid du Colombier fp->type = FNEXTB; 5613e12c5d1SDavid du Colombier settext(fp, hp->e.textc.vmaddr, hp->e.textc.vmaddr, 5623e12c5d1SDavid du Colombier hp->e.texts.size, hp->e.texts.offset); 5633e12c5d1SDavid du Colombier setdata(fp, hp->e.datac.vmaddr, hp->e.datas.size, 5643e12c5d1SDavid du Colombier hp->e.datas.offset, hp->e.bsss.size); 5653e12c5d1SDavid du Colombier setsym(fp, hp->e.symc.nsyms, hp->e.symc.spoff, hp->e.symc.pcoff, 5663e12c5d1SDavid du Colombier hp->e.symc.symoff); 567219b2ee8SDavid du Colombier fp->hdrsz = 0; /* header stripped */ 5687dd7cddfSDavid du Colombier return 1; 5693e12c5d1SDavid du Colombier } 5703e12c5d1SDavid du Colombier 5717dd7cddfSDavid du Colombier /* 572d3993254SDavid du Colombier * ELF64 binaries. 5737dd7cddfSDavid du Colombier */ 5747dd7cddfSDavid du Colombier static int 575d3993254SDavid du Colombier elf64dotout(int fd, Fhdr *fp, ExecHdr *hp) 5767dd7cddfSDavid du Colombier { 577d3993254SDavid du Colombier E64hdr *ep; 578d3993254SDavid du Colombier P64hdr *ph; 579d3993254SDavid du Colombier ushort (*swab)(ushort); 580d3993254SDavid du Colombier ulong (*swal)(ulong); 581d3993254SDavid du Colombier uvlong (*swav)(uvlong); 582d3993254SDavid du Colombier int i, it, id, is, phsz; 583d3993254SDavid du Colombier uvlong uvl; 5847dd7cddfSDavid du Colombier 585d3993254SDavid du Colombier ep = &hp->e; 586d3993254SDavid du Colombier if(ep->ident[DATA] == ELFDATA2LSB) { 587d3993254SDavid du Colombier swab = leswab; 588d3993254SDavid du Colombier swal = leswal; 589d3993254SDavid du Colombier swav = leswav; 590d3993254SDavid du Colombier } else if(ep->ident[DATA] == ELFDATA2MSB) { 591d3993254SDavid du Colombier swab = beswab; 592d3993254SDavid du Colombier swal = beswal; 593d3993254SDavid du Colombier swav = beswav; 594d3993254SDavid du Colombier } else { 595d3993254SDavid du Colombier werrstr("bad ELF64 encoding - not big or little endian"); 596d3993254SDavid du Colombier return 0; 597d3993254SDavid du Colombier } 598d3993254SDavid du Colombier 599d3993254SDavid du Colombier ep->type = swab(ep->type); 600d3993254SDavid du Colombier ep->machine = swab(ep->machine); 601d3993254SDavid du Colombier ep->version = swal(ep->version); 602d3993254SDavid du Colombier if(ep->type != EXEC || ep->version != CURRENT) 603d3993254SDavid du Colombier return 0; 604d3993254SDavid du Colombier ep->elfentry = swav(ep->elfentry); 605d3993254SDavid du Colombier ep->phoff = swav(ep->phoff); 606d3993254SDavid du Colombier ep->shoff = swav(ep->shoff); 607d3993254SDavid du Colombier ep->flags = swal(ep->flags); 608d3993254SDavid du Colombier ep->ehsize = swab(ep->ehsize); 609d3993254SDavid du Colombier ep->phentsize = swab(ep->phentsize); 610d3993254SDavid du Colombier ep->phnum = swab(ep->phnum); 611d3993254SDavid du Colombier ep->shentsize = swab(ep->shentsize); 612d3993254SDavid du Colombier ep->shnum = swab(ep->shnum); 613d3993254SDavid du Colombier ep->shstrndx = swab(ep->shstrndx); 614d3993254SDavid du Colombier 615d3993254SDavid du Colombier fp->magic = ELF_MAG; 616d3993254SDavid du Colombier fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 617d3993254SDavid du Colombier switch(ep->machine) { 618d3993254SDavid du Colombier default: 619d3993254SDavid du Colombier return 0; 620d3993254SDavid du Colombier case AMD64: 621d3993254SDavid du Colombier mach = &mamd64; 622d3993254SDavid du Colombier fp->type = FAMD64; 623d3993254SDavid du Colombier fp->name = "amd64 ELF64 executable"; 624d3993254SDavid du Colombier break; 625d3993254SDavid du Colombier case POWER64: 626d3993254SDavid du Colombier mach = &mpower64; 627d3993254SDavid du Colombier fp->type = FPOWER64; 628d3993254SDavid du Colombier fp->name = "power64 ELF64 executable"; 629d3993254SDavid du Colombier break; 630d3993254SDavid du Colombier } 631d3993254SDavid du Colombier 632d3993254SDavid du Colombier if(ep->phentsize != sizeof(P64hdr)) { 633d3993254SDavid du Colombier werrstr("bad ELF64 header size"); 634d3993254SDavid du Colombier return 0; 635d3993254SDavid du Colombier } 636d3993254SDavid du Colombier phsz = sizeof(P64hdr)*ep->phnum; 637d3993254SDavid du Colombier ph = malloc(phsz); 638d3993254SDavid du Colombier if(!ph) 639d3993254SDavid du Colombier return 0; 640d3993254SDavid du Colombier seek(fd, ep->phoff, 0); 641d3993254SDavid du Colombier if(read(fd, ph, phsz) < 0) { 642d3993254SDavid du Colombier free(ph); 643d3993254SDavid du Colombier return 0; 644d3993254SDavid du Colombier } 645d3993254SDavid du Colombier for(i = 0; i < ep->phnum; i++) { 646d3993254SDavid du Colombier ph[i].type = swal(ph[i].type); 647d3993254SDavid du Colombier ph[i].flags = swal(ph[i].flags); 648d3993254SDavid du Colombier ph[i].offset = swav(ph[i].offset); 649d3993254SDavid du Colombier ph[i].vaddr = swav(ph[i].vaddr); 650d3993254SDavid du Colombier ph[i].paddr = swav(ph[i].paddr); 651d3993254SDavid du Colombier ph[i].filesz = swav(ph[i].filesz); 652d3993254SDavid du Colombier ph[i].memsz = swav(ph[i].memsz); 653d3993254SDavid du Colombier ph[i].align = swav(ph[i].align); 654d3993254SDavid du Colombier } 655d3993254SDavid du Colombier 656d3993254SDavid du Colombier /* find text, data and symbols and install them */ 657d3993254SDavid du Colombier it = id = is = -1; 658d3993254SDavid du Colombier for(i = 0; i < ep->phnum; i++) { 659d3993254SDavid du Colombier if(ph[i].type == LOAD 660d3993254SDavid du Colombier && (ph[i].flags & (R|X)) == (R|X) && it == -1) 661d3993254SDavid du Colombier it = i; 662d3993254SDavid du Colombier else if(ph[i].type == LOAD 663d3993254SDavid du Colombier && (ph[i].flags & (R|W)) == (R|W) && id == -1) 664d3993254SDavid du Colombier id = i; 665d3993254SDavid du Colombier else if(ph[i].type == NOPTYPE && is == -1) 666d3993254SDavid du Colombier is = i; 667d3993254SDavid du Colombier } 668d3993254SDavid du Colombier if(it == -1 || id == -1) { 669d3993254SDavid du Colombier werrstr("No ELF64 TEXT or DATA sections"); 670d3993254SDavid du Colombier free(ph); 671d3993254SDavid du Colombier return 0; 672d3993254SDavid du Colombier } 673d3993254SDavid du Colombier 674d3993254SDavid du Colombier settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); 675d3993254SDavid du Colombier /* 8c: out of fixed registers */ 676d3993254SDavid du Colombier uvl = ph[id].memsz - ph[id].filesz; 677d3993254SDavid du Colombier setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, uvl); 678d3993254SDavid du Colombier if(is != -1) 679d3993254SDavid du Colombier setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); 680d3993254SDavid du Colombier free(ph); 681d3993254SDavid du Colombier return 1; 682d3993254SDavid du Colombier } 683d3993254SDavid du Colombier 684d3993254SDavid du Colombier /* 685d3993254SDavid du Colombier * ELF32 binaries. 686d3993254SDavid du Colombier */ 687d3993254SDavid du Colombier static int 688d3993254SDavid du Colombier elf32dotout(int fd, Fhdr *fp, ExecHdr *hp) 689d3993254SDavid du Colombier { 6904de34a7eSDavid du Colombier ulong (*swal)(ulong); 69170b8e010SDavid du Colombier ushort (*swab)(ushort); 6927dd7cddfSDavid du Colombier Ehdr *ep; 69370b8e010SDavid du Colombier Phdr *ph; 69470b8e010SDavid du Colombier int i, it, id, is, phsz; 6957dd7cddfSDavid du Colombier 69670b8e010SDavid du Colombier /* bitswap the header according to the DATA format */ 6977dd7cddfSDavid du Colombier ep = &hp->e; 69870b8e010SDavid du Colombier if(ep->ident[DATA] == ELFDATA2LSB) { 69970b8e010SDavid du Colombier swab = leswab; 70070b8e010SDavid du Colombier swal = leswal; 70170b8e010SDavid du Colombier } else if(ep->ident[DATA] == ELFDATA2MSB) { 70270b8e010SDavid du Colombier swab = beswab; 70370b8e010SDavid du Colombier swal = beswal; 70470b8e010SDavid du Colombier } else { 705d3993254SDavid du Colombier werrstr("bad ELF32 encoding - not big or little endian"); 70670b8e010SDavid du Colombier return 0; 70770b8e010SDavid du Colombier } 70870b8e010SDavid du Colombier 70970b8e010SDavid du Colombier ep->type = swab(ep->type); 71070b8e010SDavid du Colombier ep->machine = swab(ep->machine); 71170b8e010SDavid du Colombier ep->version = swal(ep->version); 71270b8e010SDavid du Colombier ep->elfentry = swal(ep->elfentry); 71370b8e010SDavid du Colombier ep->phoff = swal(ep->phoff); 71470b8e010SDavid du Colombier ep->shoff = swal(ep->shoff); 71570b8e010SDavid du Colombier ep->flags = swal(ep->flags); 71670b8e010SDavid du Colombier ep->ehsize = swab(ep->ehsize); 71770b8e010SDavid du Colombier ep->phentsize = swab(ep->phentsize); 71870b8e010SDavid du Colombier ep->phnum = swab(ep->phnum); 71970b8e010SDavid du Colombier ep->shentsize = swab(ep->shentsize); 72070b8e010SDavid du Colombier ep->shnum = swab(ep->shnum); 72170b8e010SDavid du Colombier ep->shstrndx = swab(ep->shstrndx); 72270b8e010SDavid du Colombier if(ep->type != EXEC || ep->version != CURRENT) 7237dd7cddfSDavid du Colombier return 0; 7247dd7cddfSDavid du Colombier 72570b8e010SDavid du Colombier /* we could definitely support a lot more machines here */ 7267dd7cddfSDavid du Colombier fp->magic = ELF_MAG; 7277dd7cddfSDavid du Colombier fp->hdrsz = (ep->ehsize+ep->phnum*ep->phentsize+16)&~15; 72870b8e010SDavid du Colombier switch(ep->machine) { 72970b8e010SDavid du Colombier case I386: 73070b8e010SDavid du Colombier mach = &mi386; 73170b8e010SDavid du Colombier fp->type = FI386; 732d3993254SDavid du Colombier fp->name = "386 ELF32 executable"; 73370b8e010SDavid du Colombier break; 73470b8e010SDavid du Colombier case MIPS: 73570b8e010SDavid du Colombier mach = &mmips; 73670b8e010SDavid du Colombier fp->type = FMIPS; 737d3993254SDavid du Colombier fp->name = "mips ELF32 executable"; 73870b8e010SDavid du Colombier break; 739b0dcc5a8SDavid du Colombier case SPARC64: 740b0dcc5a8SDavid du Colombier mach = &msparc64; 741b0dcc5a8SDavid du Colombier fp->type = FSPARC64; 742d3993254SDavid du Colombier fp->name = "sparc64 ELF32 executable"; 743b0dcc5a8SDavid du Colombier break; 74470b8e010SDavid du Colombier case POWER: 74570b8e010SDavid du Colombier mach = &mpower; 74670b8e010SDavid du Colombier fp->type = FPOWER; 747d3993254SDavid du Colombier fp->name = "power ELF32 executable"; 748d3993254SDavid du Colombier break; 749d3993254SDavid du Colombier case POWER64: 750d3993254SDavid du Colombier mach = &mpower64; 751d3993254SDavid du Colombier fp->type = FPOWER64; 752d3993254SDavid du Colombier fp->name = "power64 ELF32 executable"; 75370b8e010SDavid du Colombier break; 754b0dcc5a8SDavid du Colombier case AMD64: 755b0dcc5a8SDavid du Colombier mach = &mamd64; 756b0dcc5a8SDavid du Colombier fp->type = FAMD64; 757d3993254SDavid du Colombier fp->name = "amd64 ELF32 executable"; 758b0dcc5a8SDavid du Colombier break; 759617c0e1eSDavid du Colombier case ARM: 760617c0e1eSDavid du Colombier mach = &marm; 761617c0e1eSDavid du Colombier fp->type = FARM; 762d3993254SDavid du Colombier fp->name = "arm ELF32 executable"; 763617c0e1eSDavid du Colombier break; 76470b8e010SDavid du Colombier default: 7657dd7cddfSDavid du Colombier return 0; 7667dd7cddfSDavid du Colombier } 7677dd7cddfSDavid du Colombier 76870b8e010SDavid du Colombier if(ep->phentsize != sizeof(Phdr)) { 769d3993254SDavid du Colombier werrstr("bad ELF32 header size"); 77070b8e010SDavid du Colombier return 0; 77170b8e010SDavid du Colombier } 77270b8e010SDavid du Colombier phsz = sizeof(Phdr)*ep->phnum; 77370b8e010SDavid du Colombier ph = malloc(phsz); 77470b8e010SDavid du Colombier if(!ph) 77570b8e010SDavid du Colombier return 0; 77670b8e010SDavid du Colombier seek(fd, ep->phoff, 0); 77770b8e010SDavid du Colombier if(read(fd, ph, phsz) < 0) { 77870b8e010SDavid du Colombier free(ph); 77970b8e010SDavid du Colombier return 0; 78070b8e010SDavid du Colombier } 7814de34a7eSDavid du Colombier hswal(ph, phsz/sizeof(ulong), swal); 7827dd7cddfSDavid du Colombier 78370b8e010SDavid du Colombier /* find text, data and symbols and install them */ 78470b8e010SDavid du Colombier it = id = is = -1; 78570b8e010SDavid du Colombier for(i = 0; i < ep->phnum; i++) { 78670b8e010SDavid du Colombier if(ph[i].type == LOAD 78770b8e010SDavid du Colombier && (ph[i].flags & (R|X)) == (R|X) && it == -1) 78870b8e010SDavid du Colombier it = i; 78970b8e010SDavid du Colombier else if(ph[i].type == LOAD 79070b8e010SDavid du Colombier && (ph[i].flags & (R|W)) == (R|W) && id == -1) 79170b8e010SDavid du Colombier id = i; 79270b8e010SDavid du Colombier else if(ph[i].type == NOPTYPE && is == -1) 79370b8e010SDavid du Colombier is = i; 79470b8e010SDavid du Colombier } 79570b8e010SDavid du Colombier if(it == -1 || id == -1) { 796b0dcc5a8SDavid du Colombier /* 797b0dcc5a8SDavid du Colombier * The SPARC64 boot image is something of an ELF hack. 798b0dcc5a8SDavid du Colombier * Text+Data+BSS are represented by ph[0]. Symbols 799b0dcc5a8SDavid du Colombier * are represented by ph[1]: 800b0dcc5a8SDavid du Colombier * 801b0dcc5a8SDavid du Colombier * filesz, memsz, vaddr, paddr, off 802b0dcc5a8SDavid du Colombier * ph[0] : txtsz+datsz, txtsz+datsz+bsssz, txtaddr-KZERO, datasize, txtoff 803b0dcc5a8SDavid du Colombier * ph[1] : symsz, lcsz, 0, 0, symoff 804b0dcc5a8SDavid du Colombier */ 805b0dcc5a8SDavid du Colombier if(ep->machine == SPARC64 && ep->phnum == 2) { 806b0dcc5a8SDavid du Colombier ulong txtaddr, txtsz, dataddr, bsssz; 807b0dcc5a8SDavid du Colombier 808b0dcc5a8SDavid du Colombier txtaddr = ph[0].vaddr | 0x80000000; 809b0dcc5a8SDavid du Colombier txtsz = ph[0].filesz - ph[0].paddr; 810b0dcc5a8SDavid du Colombier dataddr = txtaddr + txtsz; 811b0dcc5a8SDavid du Colombier bsssz = ph[0].memsz - ph[0].filesz; 812b0dcc5a8SDavid du Colombier settext(fp, ep->elfentry | 0x80000000, txtaddr, txtsz, ph[0].offset); 813b0dcc5a8SDavid du Colombier setdata(fp, dataddr, ph[0].paddr, ph[0].offset + txtsz, bsssz); 814b0dcc5a8SDavid du Colombier setsym(fp, ph[1].filesz, 0, ph[1].memsz, ph[1].offset); 815b0dcc5a8SDavid du Colombier free(ph); 816b0dcc5a8SDavid du Colombier return 1; 817b0dcc5a8SDavid du Colombier } 818b0dcc5a8SDavid du Colombier 819d3993254SDavid du Colombier werrstr("No ELF32 TEXT or DATA sections"); 82070b8e010SDavid du Colombier free(ph); 82170b8e010SDavid du Colombier return 0; 8227dd7cddfSDavid du Colombier } 8237dd7cddfSDavid du Colombier 82470b8e010SDavid du Colombier settext(fp, ep->elfentry, ph[it].vaddr, ph[it].memsz, ph[it].offset); 825603dff34SDavid du Colombier setdata(fp, ph[id].vaddr, ph[id].filesz, ph[id].offset, ph[id].memsz - ph[id].filesz); 82670b8e010SDavid du Colombier if(is != -1) 82770b8e010SDavid du Colombier setsym(fp, ph[is].filesz, 0, ph[is].memsz, ph[is].offset); 82870b8e010SDavid du Colombier free(ph); 8297dd7cddfSDavid du Colombier return 1; 8307dd7cddfSDavid du Colombier } 8317dd7cddfSDavid du Colombier 8327dd7cddfSDavid du Colombier /* 833d3993254SDavid du Colombier * Elf binaries. 834d3993254SDavid du Colombier */ 835d3993254SDavid du Colombier static int 836d3993254SDavid du Colombier elfdotout(int fd, Fhdr *fp, ExecHdr *hp) 837d3993254SDavid du Colombier { 838d3993254SDavid du Colombier Ehdr *ep; 839d3993254SDavid du Colombier 840d3993254SDavid du Colombier /* bitswap the header according to the DATA format */ 841d3993254SDavid du Colombier ep = &hp->e; 842d3993254SDavid du Colombier if(ep->ident[CLASS] == ELFCLASS32) 843d3993254SDavid du Colombier return elf32dotout(fd, fp, hp); 844d3993254SDavid du Colombier else if(ep->ident[CLASS] == ELFCLASS64) 845d3993254SDavid du Colombier return elf64dotout(fd, fp, hp); 846d3993254SDavid du Colombier 847*401db9f5SDavid du Colombier werrstr("bad ELF class - not 32- nor 64-bit"); 848d3993254SDavid du Colombier return 0; 849d3993254SDavid du Colombier } 850d3993254SDavid du Colombier 851d3993254SDavid du Colombier /* 8527dd7cddfSDavid du Colombier * (Free|Net)BSD ARM header. 8537dd7cddfSDavid du Colombier */ 8547dd7cddfSDavid du Colombier static int 8557dd7cddfSDavid du Colombier armdotout(int fd, Fhdr *fp, ExecHdr *hp) 8567dd7cddfSDavid du Colombier { 8574de34a7eSDavid du Colombier uvlong kbase; 8587dd7cddfSDavid du Colombier 8597dd7cddfSDavid du Colombier USED(fd); 8607dd7cddfSDavid du Colombier settext(fp, hp->e.entry, sizeof(Exec), hp->e.text, sizeof(Exec)); 8617dd7cddfSDavid du Colombier setdata(fp, fp->txtsz, hp->e.data, fp->txtsz, hp->e.bss); 8627dd7cddfSDavid du Colombier setsym(fp, hp->e.syms, hp->e.spsz, hp->e.pcsz, fp->datoff+fp->datsz); 8637dd7cddfSDavid du Colombier 8647dd7cddfSDavid du Colombier kbase = 0xF0000000; 8657dd7cddfSDavid du Colombier if ((fp->entry & kbase) == kbase) { /* Boot image */ 8667dd7cddfSDavid du Colombier fp->txtaddr = kbase+sizeof(Exec); 8677dd7cddfSDavid du Colombier fp->name = "ARM *BSD boot image"; 8687dd7cddfSDavid du Colombier fp->hdrsz = 0; /* header stripped */ 8697dd7cddfSDavid du Colombier fp->dataddr = kbase+fp->txtsz; 8707dd7cddfSDavid du Colombier } 8717dd7cddfSDavid du Colombier return 1; 8727dd7cddfSDavid du Colombier } 8733e12c5d1SDavid du Colombier 8743e12c5d1SDavid du Colombier static void 8754de34a7eSDavid du Colombier settext(Fhdr *fp, uvlong e, uvlong a, long s, vlong off) 8763e12c5d1SDavid du Colombier { 8773e12c5d1SDavid du Colombier fp->txtaddr = a; 8783e12c5d1SDavid du Colombier fp->entry = e; 8793e12c5d1SDavid du Colombier fp->txtsz = s; 8803e12c5d1SDavid du Colombier fp->txtoff = off; 8813e12c5d1SDavid du Colombier } 8824de34a7eSDavid du Colombier 8833e12c5d1SDavid du Colombier static void 8844de34a7eSDavid du Colombier setdata(Fhdr *fp, uvlong a, long s, vlong off, long bss) 8853e12c5d1SDavid du Colombier { 8863e12c5d1SDavid du Colombier fp->dataddr = a; 8873e12c5d1SDavid du Colombier fp->datsz = s; 8883e12c5d1SDavid du Colombier fp->datoff = off; 8893e12c5d1SDavid du Colombier fp->bsssz = bss; 8903e12c5d1SDavid du Colombier } 8914de34a7eSDavid du Colombier 8923e12c5d1SDavid du Colombier static void 8934de34a7eSDavid du Colombier setsym(Fhdr *fp, long symsz, long sppcsz, long lnpcsz, vlong symoff) 8943e12c5d1SDavid du Colombier { 8954de34a7eSDavid du Colombier fp->symsz = symsz; 8963e12c5d1SDavid du Colombier fp->symoff = symoff; 8974de34a7eSDavid du Colombier fp->sppcsz = sppcsz; 8983e12c5d1SDavid du Colombier fp->sppcoff = fp->symoff+fp->symsz; 8994de34a7eSDavid du Colombier fp->lnpcsz = lnpcsz; 9003e12c5d1SDavid du Colombier fp->lnpcoff = fp->sppcoff+fp->sppcsz; 9013e12c5d1SDavid du Colombier } 9023e12c5d1SDavid du Colombier 903219b2ee8SDavid du Colombier 9044de34a7eSDavid du Colombier static uvlong 9054de34a7eSDavid du Colombier _round(uvlong a, ulong b) 906219b2ee8SDavid du Colombier { 9074de34a7eSDavid du Colombier uvlong w; 908219b2ee8SDavid du Colombier 909219b2ee8SDavid du Colombier w = (a/b)*b; 910219b2ee8SDavid du Colombier if (a!=w) 911219b2ee8SDavid du Colombier w += b; 912219b2ee8SDavid du Colombier return(w); 913219b2ee8SDavid du Colombier } 914