ms2.c 3.5 KB

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