5cv.c 5.8 KB

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