6 // 8 Jan 2001 MJH Added code to write data to Binary file
7 // note: outputfile is name.bin, where name is first part
8 // of input file. ie tmp.rec -> tmp.bin
10 // srec2bin <input SREC file> <Output Binary File> <If Present, Big Endian>
13 // bit32u TAG_BIG = 0xDEADBE42;
14 // bit32u TAG_LITTLE = 0xFEEDFA42;
21 // Data Records Structure
23 // LENGTH : 32 Bits <- Length of DATA, excludes ADDRESS and CHECKSUM
25 // DATA : 8 Bits * LENGTH
26 // CHECKSUM: 32 Bits <- 0 - (Sum of Length --> End of Data)
28 // Note : If Length == 0, Address will be Program Start
39 #define EndianSwitch(x) ((x >> 24) | (x << 24) | ((x << 8) & (0x00FF0000)) | ((x >> 8) & (0x0000FF00)) )
41 typedef unsigned char bit8u;
42 typedef unsigned int bit32u;
54 FILE *OpenOutputFile( char *Name );
58 bit32u AddressCurrent;
60 bit32u gh(char *cp,int nibs);
80 void dumpfTell(char *s, bit32u Value)
83 Length = (int) RecLength;
85 printf("[%s ] ftell()[0x%08lX] Length[0x%4X] Length[%4d] Value[0x%08x]\n",
86 s, ftell(fOut), Length, Length, Value);
89 void DispHex(bit32u Hex)
94 void WaitDisplay(void)
98 char iline[]={"-\\|/"};
104 printf("%c%c",iline[Index++],8);
110 void binOut32 ( bit32u Data )
112 // On UNIX machine all 32bit writes need ENDIAN switched
113 // Data = EndianSwitch(Data);
114 // fwrite( &Data, sizeof(bit32u), 1, fOut);
120 sdat[i]=(char)(Data>>(i*8));
121 fwrite( sdat, 1, 4, fOut);
122 dumpfTell("Out32" , Data);
125 // Only update RecLength on Byte Writes
126 // All 32 bit writes will be for Length etc
128 void binOut8 ( bit8u Data )
131 dumpfTell("B4Data" , (bit32u) (Data & 0xFF) );
132 n = fwrite( &Data, sizeof(bit8u), 1, fOut);
134 printf("Error in writing %X for Address 0x%8X\n", Data, AddressCurrent);
138 // Currently ONLY used for outputting Program Start
140 void binRecStart(bit32u Address)
147 printf("[RecStart] CheckSum[0x%08X] Length[%4d] Address[0x%08X]\n",
148 CheckSum, RecLength, Address);
151 dumpfTell("RecLength", RecLength);
152 binOut32( RecLength );
153 dumpfTell("Address", Address);
161 if (!RecStart) // if no record started, do not end it
169 RecEnd = ftell(fOut); // Save Current position
172 printf("[RecEnd ] CheckSum[0x%08X] Length[%4d] Length[0x%X] RecEnd[0x%08lX]\n",
173 CheckSum, RecLength, RecLength, RecEnd);
175 fseek( fOut, -((long) RecLength), SEEK_CUR); // move back Start Of Data
177 dumpfTell("Data ", -1);
179 fseek( fOut, -4, SEEK_CUR); // move back Start Of Address
181 dumpfTell("Address ", -1);
183 fseek( fOut, -4, SEEK_CUR); // move back Start Of Length
185 dumpfTell("Length ", -1);
187 binOut32( RecLength );
189 fseek( fOut, RecEnd, SEEK_SET); // move to end of Record
191 CheckSum += RecLength;
193 CheckSum = ~CheckSum + 1; // Two's complement
195 binOut32( CheckSum );
198 printf("[Created Record of %d Bytes with CheckSum [0x%8X]\n", RecLength, CheckSum);
201 void binRecOutProgramStart(bit32u Address)
203 if (Address != (AddressCurrent+1))
206 binRecStart(Address);
208 AddressCurrent = Address;
210 void binRecOutByte(bit32u Address, bit8u Data)
212 // If Address is one after Current Address, output Byte
213 // If not, close out last record, update Length, write checksum
214 // Then Start New Record, updating Current Address
216 if (Address != (AddressCurrent+1))
219 binRecStart(Address);
221 AddressCurrent = Address;
226 //=============================================================================
228 //=============================================================================
229 int readline(FILE *fil,char *buf,int len)
234 if (len==0) return(0);
239 cur_len=fread(buffer, 1, sizeof(buffer), fil);
262 if ((len>1)&&(*cur_ptr!='\r'))
285 int SRLerrorout(char *c1,char *c2)
287 printf("\nERROR: %s - '%s'.",c1,c2);
292 int checksum(char *cp,int count)
301 if (!isxdigit(*scp++))
302 return(SRLerrorout("Invalid hex digits",cp));
317 // printf("\nCk:%02x",cksum);
318 return(cksum==0x0ff);
321 bit32u gh(char *cp,int nibs)
331 if ((*cp>='a')&&(*cp<='z')) *cp &= 0x5f;
332 if ((*cp>='0')&&(*cp<='9'))
335 if ((*cp>='A')&&(*cp<='F'))
338 SRLerrorout("Bad Hex char", cp);
345 //=============================================================================
347 //=============================================================================
349 int srecLine(char *pSrecLine)
354 static bit32u RecordCounter=0;
360 return(SRLerrorout("Not an Srecord file",scp));
362 if (strlen(pSrecLine)<4)
363 return(SRLerrorout("Srecord too short",scp));
367 count=gh(pSrecLine,2);
372 // printf("count %d, strlen(pSrecLine) = %d, pSrecLine =[%s]\n", count, strlen(pSrecLine), pSrecLine);
374 DispHex(RecordCounter);
376 if ((count*2) != strlen(pSrecLine)) return(SRLerrorout("Count field larger than record",scp));
378 if (!checksum(pSrecLine, count)) return(SRLerrorout("Bad Checksum",scp));
382 case '0': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
383 itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
384 if (itmp) return(SRLerrorout("Srecord 1 address not zero",scp));
386 case '1': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
387 return(SRLerrorout("Srecord Not valid for MIPS",scp));
389 case '2': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
390 return(SRLerrorout("Srecord Not valid for MIPS",scp));
392 case '3': if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
393 adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
397 dat=gh(pSrecLine,2); pSrecLine+=2; count--;
398 binRecOutByte(adr, (char) (dat & 0xFF));
403 case '4': return(SRLerrorout("Invalid Srecord type",scp));
405 case '5': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
406 itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
407 if (itmp|=s1s2s3_total) return(SRLerrorout("Incorrect number of S3 Record processed",scp));
409 case '6': return(SRLerrorout("Invalid Srecord type",scp));
411 case '7': // PROGRAM START
412 if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
413 adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
414 if (count!=1) return(SRLerrorout("Invalid Srecord count field",scp));
415 binRecOutProgramStart(adr);
417 case '8': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
418 return(SRLerrorout("Srecord Not valid for MIPS",scp));
420 case '9': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
421 return(SRLerrorout("Srecord Not valid for MIPS",scp));
430 //=============================================================================
431 // MAIN LOGIC, READS IN LINE AND OUTPUTS BINARY
432 //=============================================================================
434 int srec2bin(int argc,char *argv[],int verbose)
440 bit32u TAG_BIG = 0xDEADBE42;
441 bit32u TAG_LITTLE = 0xFEEDFA42;
448 printf("\nError: <srec2bin <srec input file> <bin output file>\n\n");
452 if (argc > 3) BigEndian=TRUE; else BigEndian=FALSE;
460 printf("\nEndian: %s, Tag is 0x%8X\n",(BigEndian)?"BIG":"LITTLE", Tag);
462 fp = fopen(argv[1],"rt");
466 printf("\nError: Opening input file, %s.", argv[1]);
470 fOut = fopen( argv[2], "wb");
474 printf("\nError: Opening Output file, %s.", argv[2]);
481 AddressCurrent = 0xFFFFFFFFL;
485 dumpfTell("Tag", Tag);
493 rlen = readline(fp,buff,sizeof buff);
495 while( (sts) && (rlen != -1))
499 sts &= srecLine(buff);
502 rlen = readline(fp,buff,sizeof buff);
506 // printf("PC: 0x%08X, Length 0x%08X, Tag 0x%08X\n", ProgramStart, RecLength, TAG_LITTLE);
511 if(fOut) fclose(fOut);
516 main(int argc, char *argv[])
521 srec2bin(argc,argv,verbose);