srec2bin.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <string.h>
  4. //Rev 0.1 Original
  5. // 8 Jan 2001 MJH Added code to write data to Binary file
  6. // note: outputfile is name.bin, where name is first part
  7. // of input file. ie tmp.rec -> tmp.bin
  8. //
  9. // srec2bin <input SREC file> <Output Binary File> <If Present, Big Endian>
  10. //
  11. // TAG
  12. // bit32u TAG_BIG = 0xDEADBE42;
  13. // bit32u TAG_LITTLE = 0xFEEDFA42;
  14. //
  15. // File Structure
  16. //
  17. // TAG : 32 Bits
  18. // [DATA RECORDS]
  19. //
  20. // Data Records Structure
  21. //
  22. // LENGTH : 32 Bits <- Length of DATA, excludes ADDRESS and CHECKSUM
  23. // ADDRESS : 32 Bits
  24. // DATA : 8 Bits * LENGTH
  25. // CHECKSUM: 32 Bits <- 0 - (Sum of Length --> End of Data)
  26. //
  27. // Note : If Length == 0, Address will be Program Start
  28. //
  29. //
  30. //
  31. //
  32. //
  33. #define MajRevNum 0
  34. #define MinRevNum 2
  35. #define EndianSwitch(x) ((x >> 24) | (x << 24) | ((x << 8) & (0x00FF0000)) | ((x >> 8) & (0x0000FF00)) )
  36. typedef unsigned char bit8u;
  37. typedef unsigned int bit32u;
  38. typedef int bit32;
  39. #define FALSE 0
  40. #define TRUE (!FALSE)
  41. bit32u CheckSum;
  42. int RecStart;
  43. int debug;
  44. int verbose;
  45. FILE *OpenOutputFile( char *Name );
  46. FILE *fOut;
  47. bit32u RecLength=0;
  48. bit32u AddressCurrent;
  49. bit32u gh(char *cp,int nibs);
  50. int BigEndian;
  51. int inputline;
  52. // char buf[16*1024];
  53. char buffer[2048];
  54. char *cur_ptr;
  55. int cur_line=0;
  56. int cur_len=0;
  57. int s1s2s3_total=0;
  58. bit32u PBVal;
  59. int PBValid;
  60. bit32u PBAdr;
  61. void dumpfTell(char *s, bit32u Value)
  62. {
  63. int Length;
  64. Length = (int) RecLength;
  65. if (debug)
  66. printf("[%s ] ftell()[0x%08lX] Length[0x%4X] Length[%4d] Value[0x%08x]\n",
  67. s, ftell(fOut), Length, Length, Value);
  68. }
  69. void DispHex(bit32u Hex)
  70. {
  71. // printf("%X", Hex);
  72. }
  73. void WaitDisplay(void)
  74. {
  75. static int Count=0;
  76. static int Index=0;
  77. char iline[]={"-\\|/"};
  78. Count++;
  79. if ((Count % 32)==0)
  80. {
  81. if (verbose)
  82. printf("%c%c",iline[Index++],8);
  83. Index &= 3;
  84. }
  85. }
  86. void binOut32 ( bit32u Data )
  87. {
  88. // On UNIX machine all 32bit writes need ENDIAN switched
  89. // Data = EndianSwitch(Data);
  90. // fwrite( &Data, sizeof(bit32u), 1, fOut);
  91. char sdat[4];
  92. int i;
  93. for(i=0;i<4;i++)
  94. sdat[i]=(char)(Data>>(i*8));
  95. fwrite( sdat, 1, 4, fOut);
  96. dumpfTell("Out32" , Data);
  97. }
  98. // Only update RecLength on Byte Writes
  99. // All 32 bit writes will be for Length etc
  100. void binOut8 ( bit8u Data )
  101. {
  102. int n;
  103. dumpfTell("B4Data" , (bit32u) (Data & 0xFF) );
  104. n = fwrite( &Data, sizeof(bit8u), 1, fOut);
  105. if (n != 1)
  106. printf("Error in writing %X for Address 0x%8X\n", Data, AddressCurrent);
  107. RecLength += 1;
  108. }
  109. // Currently ONLY used for outputting Program Start
  110. void binRecStart(bit32u Address)
  111. {
  112. RecLength = 0;
  113. CheckSum = Address;
  114. RecStart = TRUE;
  115. if (debug)
  116. printf("[RecStart] CheckSum[0x%08X] Length[%4d] Address[0x%08X]\n",
  117. CheckSum, RecLength, Address);
  118. dumpfTell("RecLength", RecLength);
  119. binOut32( RecLength );
  120. dumpfTell("Address", Address);
  121. binOut32( Address );
  122. }
  123. void binRecEnd(void)
  124. {
  125. long RecEnd;
  126. if (!RecStart) // if no record started, do not end it
  127. {
  128. return;
  129. }
  130. RecStart = FALSE;
  131. RecEnd = ftell(fOut); // Save Current position
  132. if (debug)
  133. printf("[RecEnd ] CheckSum[0x%08X] Length[%4d] Length[0x%X] RecEnd[0x%08lX]\n",
  134. CheckSum, RecLength, RecLength, RecEnd);
  135. fseek( fOut, -((long) RecLength), SEEK_CUR); // move back Start Of Data
  136. dumpfTell("Data ", -1);
  137. fseek( fOut, -4, SEEK_CUR); // move back Start Of Address
  138. dumpfTell("Address ", -1);
  139. fseek( fOut, -4, SEEK_CUR); // move back Start Of Length
  140. dumpfTell("Length ", -1);
  141. binOut32( RecLength );
  142. fseek( fOut, RecEnd, SEEK_SET); // move to end of Record
  143. CheckSum += RecLength;
  144. CheckSum = ~CheckSum + 1; // Two's complement
  145. binOut32( CheckSum );
  146. if (verbose)
  147. printf("[Created Record of %d Bytes with CheckSum [0x%8X]\n", RecLength, CheckSum);
  148. }
  149. void binRecOutProgramStart(bit32u Address)
  150. {
  151. if (Address != (AddressCurrent+1))
  152. {
  153. binRecEnd();
  154. binRecStart(Address);
  155. }
  156. AddressCurrent = Address;
  157. }
  158. void binRecOutByte(bit32u Address, bit8u Data)
  159. {
  160. // If Address is one after Current Address, output Byte
  161. // If not, close out last record, update Length, write checksum
  162. // Then Start New Record, updating Current Address
  163. if (Address != (AddressCurrent+1))
  164. {
  165. binRecEnd();
  166. binRecStart(Address);
  167. }
  168. AddressCurrent = Address;
  169. CheckSum += Data;
  170. binOut8( Data );
  171. }
  172. //=============================================================================
  173. // SUPPORT FUNCTIONS
  174. //=============================================================================
  175. int readline(FILE *fil,char *buf,int len)
  176. {
  177. int rlen;
  178. rlen=0;
  179. if (len==0) return(0);
  180. while(1)
  181. {
  182. if (cur_len==0)
  183. {
  184. cur_len=fread(buffer, 1, sizeof(buffer), fil);
  185. if (cur_len==0)
  186. {
  187. if (rlen)
  188. {
  189. *buf=0;
  190. return(rlen);
  191. }
  192. return(-1);
  193. }
  194. cur_ptr=buffer;
  195. }
  196. if (cur_len)
  197. {
  198. if (*cur_ptr=='\n')
  199. {
  200. *buf=0;
  201. cur_ptr++;
  202. cur_len--;
  203. return(rlen);
  204. }
  205. else
  206. {
  207. if ((len>1)&&(*cur_ptr!='\r'))
  208. {
  209. *buf++=*cur_ptr++;
  210. len--;
  211. }
  212. else
  213. cur_ptr++;
  214. rlen++;
  215. cur_len--;
  216. }
  217. }
  218. else
  219. {
  220. *buf=0;
  221. cur_ptr++;
  222. cur_len--;
  223. return(rlen);
  224. }
  225. }
  226. }
  227. int SRLerrorout(char *c1,char *c2)
  228. {
  229. printf("\nERROR: %s - '%s'.",c1,c2);
  230. return(FALSE);
  231. }
  232. int checksum(char *cp,int count)
  233. {
  234. char *scp;
  235. int cksum;
  236. int dum;
  237. scp=cp;
  238. while(*scp)
  239. {
  240. if (!isxdigit(*scp++))
  241. return(SRLerrorout("Invalid hex digits",cp));
  242. }
  243. scp=cp;
  244. cksum=count;
  245. while(count)
  246. {
  247. cksum += gh(scp,2);
  248. if (count == 2)
  249. dum = ~cksum;
  250. scp += 2;
  251. count--;
  252. }
  253. cksum&=0x0ff;
  254. // printf("\nCk:%02x",cksum);
  255. return(cksum==0x0ff);
  256. }
  257. bit32u gh(char *cp,int nibs)
  258. {
  259. int i;
  260. bit32u j;
  261. j=0;
  262. for(i=0;i<nibs;i++)
  263. {
  264. j<<=4;
  265. if ((*cp>='a')&&(*cp<='z')) *cp &= 0x5f;
  266. if ((*cp>='0')&&(*cp<='9'))
  267. j += (*cp-0x30);
  268. else
  269. if ((*cp>='A')&&(*cp<='F'))
  270. j += (*cp-0x37);
  271. else
  272. SRLerrorout("Bad Hex char", cp);
  273. cp++;
  274. }
  275. return(j);
  276. }
  277. //=============================================================================
  278. // PROCESS SREC LINE
  279. //=============================================================================
  280. int srecLine(char *pSrecLine)
  281. {
  282. char *scp,ch;
  283. int itmp,count,dat;
  284. bit32u adr;
  285. static bit32u RecordCounter=0;
  286. cur_line++;
  287. scp=pSrecLine;
  288. if (*pSrecLine!='S')
  289. return(SRLerrorout("Not an Srecord file",scp));
  290. pSrecLine++;
  291. if (strlen(pSrecLine)<4)
  292. return(SRLerrorout("Srecord too short",scp));
  293. ch=*pSrecLine++;
  294. count=gh(pSrecLine,2);
  295. pSrecLine += 2;
  296. // if(debug)
  297. // printf("count %d, strlen(pSrecLine) = %d, pSrecLine =[%s]\n", count, strlen(pSrecLine), pSrecLine);
  298. RecordCounter++;
  299. DispHex(RecordCounter);
  300. if ((count*2) != strlen(pSrecLine)) return(SRLerrorout("Count field larger than record",scp));
  301. if (!checksum(pSrecLine, count)) return(SRLerrorout("Bad Checksum",scp));
  302. switch(ch)
  303. {
  304. case '0': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
  305. itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
  306. if (itmp) return(SRLerrorout("Srecord 1 address not zero",scp));
  307. break;
  308. case '1': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
  309. return(SRLerrorout("Srecord Not valid for MIPS",scp));
  310. break;
  311. case '2': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
  312. return(SRLerrorout("Srecord Not valid for MIPS",scp));
  313. break;
  314. case '3': if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
  315. adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
  316. count--;
  317. while(count)
  318. {
  319. dat=gh(pSrecLine,2); pSrecLine+=2; count--;
  320. binRecOutByte(adr, (char) (dat & 0xFF));
  321. adr++;
  322. }
  323. s1s2s3_total++;
  324. break;
  325. case '4': return(SRLerrorout("Invalid Srecord type",scp));
  326. break;
  327. case '5': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
  328. itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
  329. if (itmp|=s1s2s3_total) return(SRLerrorout("Incorrect number of S3 Record processed",scp));
  330. break;
  331. case '6': return(SRLerrorout("Invalid Srecord type",scp));
  332. break;
  333. case '7': // PROGRAM START
  334. if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
  335. adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
  336. if (count!=1) return(SRLerrorout("Invalid Srecord count field",scp));
  337. binRecOutProgramStart(adr);
  338. break;
  339. case '8': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
  340. return(SRLerrorout("Srecord Not valid for MIPS",scp));
  341. break;
  342. case '9': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
  343. return(SRLerrorout("Srecord Not valid for MIPS",scp));
  344. break;
  345. default:
  346. break;
  347. }
  348. return(TRUE);
  349. }
  350. //=============================================================================
  351. // MAIN LOGIC, READS IN LINE AND OUTPUTS BINARY
  352. //=============================================================================
  353. int srec2bin(int argc,char *argv[],int verbose)
  354. {
  355. int rlen,sts;
  356. FILE *fp;
  357. char buff[256];
  358. bit32u TAG_BIG = 0xDEADBE42;
  359. bit32u TAG_LITTLE = 0xFEEDFA42;
  360. bit32u Tag;
  361. if(argc < 3)
  362. {
  363. printf("\nError: <srec2bin <srec input file> <bin output file>\n\n");
  364. return(0);
  365. }
  366. if (argc > 3) BigEndian=TRUE; else BigEndian=FALSE;
  367. if (BigEndian)
  368. Tag = TAG_BIG;
  369. else
  370. Tag = TAG_LITTLE;
  371. if (verbose)
  372. printf("\nEndian: %s, Tag is 0x%8X\n",(BigEndian)?"BIG":"LITTLE", Tag);
  373. fp = fopen(argv[1],"rt");
  374. if (fp==NULL)
  375. {
  376. printf("\nError: Opening input file, %s.", argv[1]);
  377. return(0);
  378. }
  379. fOut = fopen( argv[2], "wb");
  380. if (fOut==NULL)
  381. {
  382. printf("\nError: Opening Output file, %s.", argv[2]);
  383. if(fp) fclose(fp);
  384. return(0);
  385. }
  386. RecStart = FALSE;
  387. AddressCurrent = 0xFFFFFFFFL;
  388. // Setup Tag
  389. dumpfTell("Tag", Tag);
  390. binOut32(Tag);
  391. inputline=0;
  392. sts=TRUE;
  393. rlen = readline(fp,buff,sizeof buff);
  394. while( (sts) && (rlen != -1))
  395. {
  396. if (strlen(buff))
  397. {
  398. sts &= srecLine(buff);
  399. WaitDisplay();
  400. }
  401. rlen = readline(fp,buff,sizeof buff);
  402. }
  403. // printf("PC: 0x%08X, Length 0x%08X, Tag 0x%08X\n", ProgramStart, RecLength, TAG_LITTLE);
  404. binRecEnd();
  405. if(fp) fclose(fp);
  406. if(fOut) fclose(fOut);
  407. return(1);
  408. }
  409. int main(int argc, char *argv[])
  410. {
  411. debug = FALSE;
  412. verbose = FALSE;
  413. srec2bin(argc,argv,verbose);
  414. return 0;
  415. }