ms2.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <mach.h>
  5. void record(uchar*, int);
  6. void usage(void);
  7. void segment(long, int);
  8. enum
  9. {
  10. Recordsize = 32,
  11. };
  12. int dsegonly;
  13. int supressend;
  14. int binary;
  15. int halfswap;
  16. int srec = 2;
  17. ulong addr;
  18. ulong psize = 4096;
  19. Biobuf stdout;
  20. Fhdr exech;
  21. Biobuf *bio;
  22. void
  23. main(int argc, char **argv)
  24. {
  25. Dir *dir;
  26. ulong totsz;
  27. ARGBEGIN{
  28. case 'd':
  29. dsegonly++;
  30. break;
  31. case 's':
  32. supressend++;
  33. break;
  34. case 'a':
  35. addr = strtoul(ARGF(), 0, 0);
  36. break;
  37. case 'p':
  38. psize = strtoul(ARGF(), 0, 0);
  39. break;
  40. case 'b':
  41. binary++;
  42. break;
  43. case 'h':
  44. halfswap++;
  45. break;
  46. case '1':
  47. srec = 1;
  48. break;
  49. case '2':
  50. srec = 2;
  51. break;
  52. case '3':
  53. srec = 3;
  54. break;
  55. default:
  56. usage();
  57. }ARGEND
  58. if(argc != 1)
  59. usage();
  60. Binit(&stdout, 1, OWRITE);
  61. bio = Bopen(argv[0], OREAD);
  62. if(bio == 0) {
  63. fprint(2, "ms2: open %s: %r\n", argv[0]);
  64. exits("open");
  65. }
  66. if(binary) {
  67. if((dir = dirfstat(Bfildes(bio))) == nil) {
  68. fprint(2, "ms2: stat failed %r");
  69. exits("dirfstat");
  70. }
  71. segment(0, dir->length);
  72. Bprint(&stdout, "S9030000FC\n");
  73. Bterm(&stdout);
  74. Bterm(bio);
  75. free(dir);
  76. exits(0);
  77. }
  78. if(!crackhdr(Bfildes(bio), &exech)) {
  79. fprint(2, "ms2: can't decode file header\n");
  80. return;
  81. }
  82. totsz = exech.txtsz + exech.datsz + exech.bsssz;
  83. fprint(2, "%s: %lud+%lud+%lud=%lud\n",
  84. exech.name, exech.txtsz, exech.datsz, exech.bsssz, totsz);
  85. if(dsegonly)
  86. segment(exech.datoff, exech.datsz);
  87. else {
  88. segment(exech.txtoff, exech.txtsz);
  89. addr = (addr+(psize-1))&~(psize-1);
  90. segment(exech.datoff, exech.datsz);
  91. }
  92. if(supressend == 0) {
  93. switch(srec) {
  94. case 1:
  95. case 2:
  96. Bprint(&stdout, "S9030000FC\n");
  97. break;
  98. case 3:
  99. Bprint(&stdout, "S705000000FA\n");
  100. break;
  101. }
  102. }
  103. Bterm(&stdout);
  104. Bterm(bio);
  105. exits(0);
  106. }
  107. void
  108. segment(long foff, int len)
  109. {
  110. int l, n, i;
  111. uchar t, buf[2*Recordsize];
  112. Bseek(bio, foff, 0);
  113. for(;;) {
  114. l = len;
  115. if(l > Recordsize)
  116. l = Recordsize;
  117. n = Bread(bio, buf, l);
  118. if(n == 0)
  119. break;
  120. if(n < 0) {
  121. fprint(2, "ms2: read error: %r\n");
  122. exits("read");
  123. }
  124. if(halfswap) {
  125. if(n & 1) {
  126. fprint(2, "ms2: data must be even length\n");
  127. exits("even");
  128. }
  129. for(i = 0; i < n; i += 2) {
  130. t = buf[i];
  131. buf[i] = buf[i+1];
  132. buf[i+1] = t;
  133. }
  134. }
  135. record(buf, l);
  136. len -= l;
  137. }
  138. }
  139. void
  140. record(uchar *s, int l)
  141. {
  142. int i;
  143. ulong cksum = 0;
  144. switch(srec) {
  145. case 1:
  146. cksum = l+3;
  147. Bprint(&stdout, "S1%.2X%.4luX", l+3, addr);
  148. cksum += addr&0xff;
  149. cksum += (addr>>8)&0xff;
  150. break;
  151. case 2:
  152. cksum = l+4;
  153. Bprint(&stdout, "S2%.2X%.6luX", l+4, addr);
  154. cksum += addr&0xff;
  155. cksum += (addr>>8)&0xff;
  156. cksum += (addr>>16)&0xff;
  157. break;
  158. case 3:
  159. cksum = l+5;
  160. Bprint(&stdout, "S3%.2X%.8luX", l+5, addr);
  161. cksum += addr&0xff;
  162. cksum += (addr>>8)&0xff;
  163. cksum += (addr>>16)&0xff;
  164. cksum += (addr>>24)&0xff;
  165. break;
  166. }
  167. for(i = 0; i < l; i++) {
  168. cksum += *s;
  169. Bprint(&stdout, "%.2X", *s++);
  170. }
  171. Bprint(&stdout, "%.2luX\n", (~cksum)&0xff);
  172. addr += l;
  173. }
  174. void
  175. usage(void)
  176. {
  177. fprint(2, "usage: ms2 [-dsbh] [-a address] [-p pagesize] ?.out\n");
  178. exits("usage");
  179. }