123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- #include <lib9.h>
- #include <bio.h>
- #include <mach.h>
- char *Cmd;
- int Hdrtype;
- int Strip;
- long Txtaddr = -1;
- int Ofd;
- int Ifd;
- Fhdr Ihdr;
- int Debug;
- static void get_file(char *);
- static void put_file(char *);
- static void Usage(char *);
- static long strxtol(char *);
- char *fail = "error";
- void
- main(int argc, char *argv[])
- {
- char *ifile, *ofile;
- Cmd = argv[0];
- Hdrtype = 2;
- ARGBEGIN {
- /*
- * Options without args
- */
- case 's':
- Strip = 1;
- break;
- /*
- * Options with args
- */
- case 'T':
- Txtaddr = strxtol(ARGF());
- break;
- case 'H':
- Hdrtype = strxtol(ARGF());
- break;
- case 'D':
- Debug |= strxtol(ARGF());
- break;
- default:
- Usage("Invalid option");
- } ARGEND
- if (argc != 2)
- Usage("Wrong number of arguments");
- ifile = argv[0];
- ofile = argv[1];
- get_file(ifile);
- put_file(ofile);
- exits(0);
- }
- char usagemsg[] =
- "Usage: %s options infile outfile\n\t options (for outfile): -H[123456] -s -T<text> \n";
- static void
- Usage(char *msg)
- {
- fprint(2, "***Error: %s\n", msg);
- fprint(2, usagemsg, Cmd);
- exits("usage");
- }
- static long
- strxtol(char *s)
- {
- char *es;
- int base = 0;
- long r;
- if (*s == '0')
- if (*++s == 'x'){
- base = 16;
- s++;
- }
- else
- base = 8;
- r = strtol(s, &es, base);
- if (*es)
- Usage("bad number");
- return(r);
- }
- static void
- get_file(char *ifile)
- {
- int h;
- int d;
- Ifd = open(ifile, OREAD);
- if (Ifd < 0) {
- fprint(2, "5cv: open %s: %r\n", ifile);
- exits("open");
- }
- h = crackhdr(Ifd, &Ihdr);
- if (!h || Debug){
- fprint(2, "Crackhdr: %d, type: %d, name: %s\n", h, Ihdr.type, Ihdr.name);
- fprint(2, "txt %llux, ent %llux, txtsz %lux, dataddr %llux\n",
- Ihdr.txtaddr, Ihdr.entry, Ihdr.txtsz, Ihdr.dataddr);
- }
- if (!h)
- Usage("File type not recognized");
- machbytype(Ihdr.type);
- if (Debug)
- fprint(2, "name: <%s> pgsize:%ux\n", mach->name, mach->pgsize);
- if (Txtaddr != -1){
- d = Txtaddr - Ihdr.txtaddr;
- Ihdr.txtaddr += d;
- Ihdr.dataddr = Ihdr.txtaddr + Ihdr.txtsz;
- }
- }
- char Wbuf[128];
- char *wp = Wbuf;
- void
- lput(long l)
- {
- wp[0] = l>>24;
- wp[1] = l>>16;
- wp[2] = l>>8;
- wp[3] = l;
- wp += 4;
- }
- void
- lputl(long l)
- {
- wp[3] = l>>24;
- wp[2] = l>>16;
- wp[1] = l>>8;
- wp[0] = l;
- wp += 4;
- }
- static void
- copyseg(long sz)
- {
- char buf[1024];
- while (sz > 0){
- long n;
- long r;
- n = sz;
- if (n > sizeof buf)
- n = sizeof buf;
- sz -= n;
- if ((r = read(Ifd, buf, n)) != n){
- fprint(2, "%ld = read(...%ld) at %ld\n", r, n, (long)seek(Ifd, 0, 1));
- perror("Premature eof");
- exits(fail);
- }
- if ((r = write(Ofd, buf, n)) != n){
- fprint(2, "%ld = write(...%ld)\n", r, n);
- perror("Write error!");
- exits(fail);
- }
- }
- }
- static void
- zero(long sz)
- {
- char buf[1024];
- memset(buf, 0, sizeof buf);
- while (sz > 0){
- long n;
- long r;
- n = sz;
- if (n > sizeof buf)
- n = sizeof buf;
- sz -= n;
- if ((r = write(Ofd, buf, n)) != n){
- fprint(2, "%ld = write(...%ld)\n", r, n);
- perror("Write error!");
- exits(fail);
- }
- }
- }
- static long
- rnd(long v, long r)
- {
- long c;
- if(r <= 0)
- return v;
- v += r - 1;
- c = v % r;
- if(c < 0)
- c += r;
- v -= c;
- return v;
- }
- static void
- put_file(char *ofile)
- {
- int ii;
- long doff;
- long dsize;
- long hlen;
- long pad;
- Ofd = create(ofile, OWRITE, 0666);
- if (Ofd < 0) {
- fprint(2, "5cv: create %s: %r\n", ofile);
- exits("create");
- }
- pad = 0;
- switch(Hdrtype) {
- case 1: /* aif for risc os */
- Strip = 1;
- hlen = 128;
- lputl(0xe1a00000); /* NOP - decompress code */
- lputl(0xe1a00000); /* NOP - relocation code */
- lputl(0xeb000000 + 12); /* BL - zero init code */
- lputl(0xeb000000 +
- (Ihdr.entry
- - Ihdr.txtaddr
- + hlen
- - 12
- - 8) / 4); /* BL - entry code */
- lputl(0xef000011); /* SWI - exit code */
- doff = Ihdr.txtsz+hlen;
- lputl(doff); /* text size */
- dsize = Ihdr.datsz;
- lputl(dsize); /* data size */
- lputl(0); /* sym size */
- lputl(Ihdr.bsssz); /* bss size */
- lputl(0); /* sym type */
- lputl(Ihdr.txtaddr-hlen); /* text addr */
- lputl(0); /* workspace - ignored */
- lputl(32); /* addr mode / data addr flag */
- lputl(0); /* data addr */
- for(ii=0; ii<2; ii++)
- lputl(0); /* reserved */
- for(ii=0; ii<15; ii++)
- lputl(0xe1a00000); /* NOP - zero init code */
- lputl(0xe1a0f00e); /* B (R14) - zero init return */
- break;
- case 2: /* plan 9 */
- hlen = 32;
- doff = hlen + Ihdr.txtsz;
- dsize = Ihdr.datsz;
- lput(0x647); /* magic */
- lput(Ihdr.txtsz); /* sizes */
- lput(Ihdr.datsz);
- lput(Ihdr.bsssz);
- if (Strip) /* nsyms */
- lput(0);
- else
- lput(Ihdr.symsz);
- lput(Ihdr.entry); /* va of entry */
- lput(0L);
- lput(Ihdr.lnpcsz);
- break;
- case 3: /* boot for NetBSD */
- hlen = 32;
- doff = rnd(hlen+Ihdr.txtsz, 4096);
- dsize = rnd(Ihdr.datsz, 4096);
- lput((143<<16)|0413); /* magic */
- lputl(doff);
- lputl(dsize);
- lputl(Ihdr.bsssz);
- if (Strip) /* nsyms */
- lputl(0);
- else
- lputl(Ihdr.symsz);
- lputl(Ihdr.entry); /* va of entry */
- lputl(0L);
- lputl(0L);
- break;
- case 4: /* no header, stripped, padded to 2K, for serial bootstrap */
- hlen = 0;
- Strip = 1;
- doff = hlen + Ihdr.txtsz;
- dsize = Ihdr.datsz;
- pad = 2048;
- break;
- case 5: /* no header, stripped, for all sorts */
- hlen = 0;
- Strip = 1;
- doff = hlen + Ihdr.txtsz;
- dsize = Ihdr.datsz;
- break;
- case 6: /* fake EPOC IMG format header */
- hlen = 256;
- *wp++ = 'E';
- *wp++ = 'P';
- Strip = 1;
- doff = hlen + Ihdr.txtsz;
- dsize = Ihdr.datsz;
- break;
- default:
- Usage("Bad -Htype");
- return;
- }
- write(Ofd, Wbuf, hlen);
- seek(Ifd, Ihdr.txtoff, 0);
- copyseg(Ihdr.txtsz);
- seek(Ifd, Ihdr.datoff, 0);
- seek(Ofd, doff, 0);
- copyseg(Ihdr.datsz);
- if (!Strip) {
- /* Write symbols */
- seek(Ofd, doff + dsize, 0);
- if (Ihdr.symsz){
- seek(Ifd, Ihdr.symoff, 0);
- copyseg(Ihdr.symsz);
- }
- if (Hdrtype == 2)
- copyseg(Ihdr.lnpcsz);
- }
- if (pad) {
- if (doff + Ihdr.datsz > pad) {
- perror("Too big!");
- exits(fail);
- }
- else if (doff + Ihdr.datsz < pad)
- zero(pad - (doff + Ihdr.datsz));
- }
- }
|