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