1 #include <lib9.h> 2 #include <bio.h> 3 #include <mach.h> 4 5 char *Cmd; 6 int Hdrtype; 7 int Strip; 8 long Txtaddr = -1; 9 10 int Ofd; 11 int Ifd; 12 Fhdr Ihdr; 13 14 int Debug; 15 16 static void get_file(char *); 17 static void put_file(char *); 18 static void Usage(char *); 19 static long strxtol(char *); 20 21 char *fail = "error"; 22 23 void 24 main(int argc, char *argv[]) 25 { 26 char *ifile, *ofile; 27 28 Cmd = argv[0]; 29 Hdrtype = 2; 30 31 ARGBEGIN { 32 /* 33 * Options without args 34 */ 35 case 's': 36 Strip = 1; 37 break; 38 /* 39 * Options with args 40 */ 41 case 'T': 42 Txtaddr = strxtol(ARGF()); 43 break; 44 case 'H': 45 Hdrtype = strxtol(ARGF()); 46 break; 47 case 'D': 48 Debug |= strxtol(ARGF()); 49 break; 50 default: 51 Usage("Invalid option"); 52 } ARGEND 53 54 if (argc != 2) 55 Usage("Wrong number of arguments"); 56 57 ifile = argv[0]; 58 ofile = argv[1]; 59 60 get_file(ifile); 61 put_file(ofile); 62 exits(0); 63 } 64 65 char usagemsg[] = 66 "Usage: %s options infile outfile\n\t options (for outfile): -H[123456] -s -T<text> \n"; 67 68 static void 69 Usage(char *msg) 70 { 71 fprint(2, "***Error: %s\n", msg); 72 fprint(2, usagemsg, Cmd); 73 exits("usage"); 74 } 75 76 static long 77 strxtol(char *s) 78 { 79 char *es; 80 int base = 0; 81 long r; 82 83 if (*s == '0') 84 if (*++s == 'x'){ 85 base = 16; 86 s++; 87 } 88 else 89 base = 8; 90 r = strtol(s, &es, base); 91 if (*es) 92 Usage("bad number"); 93 return(r); 94 } 95 96 static void 97 get_file(char *ifile) 98 { 99 int h; 100 int d; 101 102 Ifd = open(ifile, OREAD); 103 if (Ifd < 0) { 104 fprint(2, "5cv: open %s: %r\n", ifile); 105 exits("open"); 106 } 107 h = crackhdr(Ifd, &Ihdr); 108 if (!h || Debug){ 109 fprint(2, "Crackhdr: %d, type: %d, name: %s\n", h, Ihdr.type, Ihdr.name); 110 fprint(2, "txt %llux, ent %llux, txtsz %lux, dataddr %llux\n", 111 Ihdr.txtaddr, Ihdr.entry, Ihdr.txtsz, Ihdr.dataddr); 112 } 113 if (!h) 114 Usage("File type not recognized"); 115 machbytype(Ihdr.type); 116 if (Debug) 117 fprint(2, "name: <%s> pgsize:%ux\n", mach->name, mach->pgsize); 118 119 if (Txtaddr != -1){ 120 d = Txtaddr - Ihdr.txtaddr; 121 Ihdr.txtaddr += d; 122 Ihdr.dataddr = Ihdr.txtaddr + Ihdr.txtsz; 123 } 124 } 125 126 char Wbuf[128]; 127 char *wp = Wbuf; 128 129 void 130 lput(long l) 131 { 132 wp[0] = l>>24; 133 wp[1] = l>>16; 134 wp[2] = l>>8; 135 wp[3] = l; 136 wp += 4; 137 } 138 139 void 140 lputl(long l) 141 { 142 wp[3] = l>>24; 143 wp[2] = l>>16; 144 wp[1] = l>>8; 145 wp[0] = l; 146 wp += 4; 147 } 148 149 static void 150 copyseg(long sz) 151 { 152 char buf[1024]; 153 154 while (sz > 0){ 155 long n; 156 long r; 157 158 n = sz; 159 if (n > sizeof buf) 160 n = sizeof buf; 161 sz -= n; 162 163 if ((r = read(Ifd, buf, n)) != n){ 164 fprint(2, "%ld = read(...%ld) at %ld\n", r, n, (long)seek(Ifd, 0, 1)); 165 perror("Premature eof"); 166 exits(fail); 167 } 168 if ((r = write(Ofd, buf, n)) != n){ 169 fprint(2, "%ld = write(...%ld)\n", r, n); 170 perror("Write error!"); 171 exits(fail); 172 } 173 } 174 } 175 176 static void 177 zero(long sz) 178 { 179 char buf[1024]; 180 181 memset(buf, 0, sizeof buf); 182 while (sz > 0){ 183 long n; 184 long r; 185 186 n = sz; 187 if (n > sizeof buf) 188 n = sizeof buf; 189 sz -= n; 190 191 if ((r = write(Ofd, buf, n)) != n){ 192 fprint(2, "%ld = write(...%ld)\n", r, n); 193 perror("Write error!"); 194 exits(fail); 195 } 196 } 197 } 198 199 static long 200 rnd(long v, long r) 201 { 202 long c; 203 204 if(r <= 0) 205 return v; 206 v += r - 1; 207 c = v % r; 208 if(c < 0) 209 c += r; 210 v -= c; 211 return v; 212 } 213 214 static void 215 put_file(char *ofile) 216 { 217 int ii; 218 long doff; 219 long dsize; 220 long hlen; 221 long pad; 222 223 Ofd = create(ofile, OWRITE, 0666); 224 if (Ofd < 0) { 225 fprint(2, "5cv: create %s: %r\n", ofile); 226 exits("create"); 227 } 228 229 pad = 0; 230 231 switch(Hdrtype) { 232 case 1: /* aif for risc os */ 233 Strip = 1; 234 hlen = 128; 235 lputl(0xe1a00000); /* NOP - decompress code */ 236 lputl(0xe1a00000); /* NOP - relocation code */ 237 lputl(0xeb000000 + 12); /* BL - zero init code */ 238 lputl(0xeb000000 + 239 (Ihdr.entry 240 - Ihdr.txtaddr 241 + hlen 242 - 12 243 - 8) / 4); /* BL - entry code */ 244 245 lputl(0xef000011); /* SWI - exit code */ 246 doff = Ihdr.txtsz+hlen; 247 lputl(doff); /* text size */ 248 dsize = Ihdr.datsz; 249 lputl(dsize); /* data size */ 250 lputl(0); /* sym size */ 251 252 lputl(Ihdr.bsssz); /* bss size */ 253 lputl(0); /* sym type */ 254 lputl(Ihdr.txtaddr-hlen); /* text addr */ 255 lputl(0); /* workspace - ignored */ 256 257 lputl(32); /* addr mode / data addr flag */ 258 lputl(0); /* data addr */ 259 for(ii=0; ii<2; ii++) 260 lputl(0); /* reserved */ 261 262 for(ii=0; ii<15; ii++) 263 lputl(0xe1a00000); /* NOP - zero init code */ 264 lputl(0xe1a0f00e); /* B (R14) - zero init return */ 265 break; 266 267 case 2: /* plan 9 */ 268 hlen = 32; 269 doff = hlen + Ihdr.txtsz; 270 dsize = Ihdr.datsz; 271 lput(0x647); /* magic */ 272 lput(Ihdr.txtsz); /* sizes */ 273 lput(Ihdr.datsz); 274 lput(Ihdr.bsssz); 275 if (Strip) /* nsyms */ 276 lput(0); 277 else 278 lput(Ihdr.symsz); 279 lput(Ihdr.entry); /* va of entry */ 280 lput(0L); 281 lput(Ihdr.lnpcsz); 282 break; 283 284 case 3: /* boot for NetBSD */ 285 hlen = 32; 286 doff = rnd(hlen+Ihdr.txtsz, 4096); 287 dsize = rnd(Ihdr.datsz, 4096); 288 lput((143<<16)|0413); /* magic */ 289 lputl(doff); 290 lputl(dsize); 291 lputl(Ihdr.bsssz); 292 if (Strip) /* nsyms */ 293 lputl(0); 294 else 295 lputl(Ihdr.symsz); 296 lputl(Ihdr.entry); /* va of entry */ 297 lputl(0L); 298 lputl(0L); 299 break; 300 case 4: /* no header, stripped, padded to 2K, for serial bootstrap */ 301 hlen = 0; 302 Strip = 1; 303 doff = hlen + Ihdr.txtsz; 304 dsize = Ihdr.datsz; 305 pad = 2048; 306 break; 307 case 5: /* no header, stripped, for all sorts */ 308 hlen = 0; 309 Strip = 1; 310 doff = hlen + Ihdr.txtsz; 311 dsize = Ihdr.datsz; 312 break; 313 case 6: /* fake EPOC IMG format header */ 314 hlen = 256; 315 *wp++ = 'E'; 316 *wp++ = 'P'; 317 Strip = 1; 318 doff = hlen + Ihdr.txtsz; 319 dsize = Ihdr.datsz; 320 break; 321 default: 322 Usage("Bad -Htype"); 323 return; 324 } 325 write(Ofd, Wbuf, hlen); 326 327 seek(Ifd, Ihdr.txtoff, 0); 328 copyseg(Ihdr.txtsz); 329 330 seek(Ifd, Ihdr.datoff, 0); 331 seek(Ofd, doff, 0); 332 copyseg(Ihdr.datsz); 333 334 if (!Strip) { 335 /* Write symbols */ 336 seek(Ofd, doff + dsize, 0); 337 if (Ihdr.symsz){ 338 seek(Ifd, Ihdr.symoff, 0); 339 copyseg(Ihdr.symsz); 340 } 341 if (Hdrtype == 2) 342 copyseg(Ihdr.lnpcsz); 343 } 344 345 if (pad) { 346 if (doff + Ihdr.datsz > pad) { 347 perror("Too big!"); 348 exits(fail); 349 } 350 else if (doff + Ihdr.datsz < pad) 351 zero(pad - (doff + Ihdr.datsz)); 352 } 353 } 354