|
|
@@ -0,0 +1,523 @@
|
|
|
+#include <stdio.h>
|
|
|
+#include <ctype.h>
|
|
|
+
|
|
|
+//Rev 0.1 Original
|
|
|
+// 8 Jan 2001 MJH Added code to write data to Binary file
|
|
|
+// note: outputfile is name.bin, where name is first part
|
|
|
+// of input file. ie tmp.rec -> tmp.bin
|
|
|
+//
|
|
|
+// srec2bin <input SREC file> <Output Binary File> <If Present, Big Endian>
|
|
|
+//
|
|
|
+// TAG
|
|
|
+// bit32u TAG_BIG = 0xDEADBE42;
|
|
|
+// bit32u TAG_LITTLE = 0xFEEDFA42;
|
|
|
+//
|
|
|
+// File Structure
|
|
|
+//
|
|
|
+// TAG : 32 Bits
|
|
|
+// [DATA RECORDS]
|
|
|
+//
|
|
|
+// Data Records Structure
|
|
|
+//
|
|
|
+// LENGTH : 32 Bits <- Length of DATA, excludes ADDRESS and CHECKSUM
|
|
|
+// ADDRESS : 32 Bits
|
|
|
+// DATA : 8 Bits * LENGTH
|
|
|
+// CHECKSUM: 32 Bits <- 0 - (Sum of Length --> End of Data)
|
|
|
+//
|
|
|
+// Note : If Length == 0, Address will be Program Start
|
|
|
+//
|
|
|
+//
|
|
|
+//
|
|
|
+//
|
|
|
+//
|
|
|
+
|
|
|
+#define MajRevNum 0
|
|
|
+#define MinRevNum 2
|
|
|
+
|
|
|
+
|
|
|
+#define EndianSwitch(x) ((x >> 24) | (x << 24) | ((x << 8) & (0x00FF0000)) | ((x >> 8) & (0x0000FF00)) )
|
|
|
+
|
|
|
+typedef unsigned char bit8u;
|
|
|
+typedef unsigned int bit32u;
|
|
|
+typedef int bit32;
|
|
|
+
|
|
|
+#define FALSE 0
|
|
|
+#define TRUE (!FALSE)
|
|
|
+
|
|
|
+
|
|
|
+bit32u CheckSum;
|
|
|
+int RecStart;
|
|
|
+int debug;
|
|
|
+int verbose;
|
|
|
+
|
|
|
+FILE *OpenOutputFile( char *Name );
|
|
|
+FILE *fOut;
|
|
|
+bit32u RecLength=0;
|
|
|
+
|
|
|
+bit32u AddressCurrent;
|
|
|
+
|
|
|
+bit32u gh(char *cp,int nibs);
|
|
|
+
|
|
|
+int BigEndian;
|
|
|
+
|
|
|
+int inputline;
|
|
|
+
|
|
|
+// char buf[16*1024];
|
|
|
+
|
|
|
+char buffer[2048];
|
|
|
+char *cur_ptr;
|
|
|
+int cur_line=0;
|
|
|
+int cur_len=0;
|
|
|
+
|
|
|
+int s1s2s3_total=0;
|
|
|
+
|
|
|
+bit32u PBVal;
|
|
|
+int PBValid;
|
|
|
+bit32u PBAdr;
|
|
|
+
|
|
|
+
|
|
|
+void dumpfTell(char *s, bit32u Value)
|
|
|
+{
|
|
|
+ int Length;
|
|
|
+ Length = (int) RecLength;
|
|
|
+ if (debug)
|
|
|
+ printf("[%s ] ftell()[0x%08lX] Length[0x%4X] Length[%4d] Value[0x%08x]\n",
|
|
|
+ s, ftell(fOut), Length, Length, Value);
|
|
|
+}
|
|
|
+
|
|
|
+void DispHex(bit32u Hex)
|
|
|
+{
|
|
|
+// printf("%X", Hex);
|
|
|
+}
|
|
|
+
|
|
|
+void WaitDisplay(void)
|
|
|
+{
|
|
|
+ static int Count=0;
|
|
|
+ static int Index=0;
|
|
|
+ char iline[]={"-\\|/"};
|
|
|
+
|
|
|
+ Count++;
|
|
|
+ if ((Count % 32)==0)
|
|
|
+ {
|
|
|
+ if (verbose)
|
|
|
+ printf("%c%c",iline[Index++],8);
|
|
|
+ Index &= 3;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void binOut32 ( bit32u Data )
|
|
|
+{
|
|
|
+// On UNIX machine all 32bit writes need ENDIAN switched
|
|
|
+// Data = EndianSwitch(Data);
|
|
|
+// fwrite( &Data, sizeof(bit32u), 1, fOut);
|
|
|
+
|
|
|
+ char sdat[4];
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for(i=0;i<4;i++)
|
|
|
+ sdat[i]=(char)(Data>>(i*8));
|
|
|
+ fwrite( sdat, 1, 4, fOut);
|
|
|
+ dumpfTell("Out32" , Data);
|
|
|
+}
|
|
|
+
|
|
|
+// Only update RecLength on Byte Writes
|
|
|
+// All 32 bit writes will be for Length etc
|
|
|
+
|
|
|
+void binOut8 ( bit8u Data )
|
|
|
+{
|
|
|
+ int n;
|
|
|
+ dumpfTell("B4Data" , (bit32u) (Data & 0xFF) );
|
|
|
+ n = fwrite( &Data, sizeof(bit8u), 1, fOut);
|
|
|
+ if (n != 1)
|
|
|
+ printf("Error in writing %X for Address 0x%8X\n", Data, AddressCurrent);
|
|
|
+ RecLength += 1;
|
|
|
+}
|
|
|
+
|
|
|
+// Currently ONLY used for outputting Program Start
|
|
|
+
|
|
|
+void binRecStart(bit32u Address)
|
|
|
+{
|
|
|
+ RecLength = 0;
|
|
|
+ CheckSum = Address;
|
|
|
+ RecStart = TRUE;
|
|
|
+
|
|
|
+ if (debug)
|
|
|
+ printf("[RecStart] CheckSum[0x%08X] Length[%4d] Address[0x%08X]\n",
|
|
|
+ CheckSum, RecLength, Address);
|
|
|
+
|
|
|
+
|
|
|
+ dumpfTell("RecLength", RecLength);
|
|
|
+ binOut32( RecLength );
|
|
|
+ dumpfTell("Address", Address);
|
|
|
+ binOut32( Address );
|
|
|
+}
|
|
|
+
|
|
|
+void binRecEnd(void)
|
|
|
+{
|
|
|
+ long RecEnd;
|
|
|
+
|
|
|
+ if (!RecStart) // if no record started, do not end it
|
|
|
+ {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ RecStart = FALSE;
|
|
|
+
|
|
|
+
|
|
|
+ RecEnd = ftell(fOut); // Save Current position
|
|
|
+
|
|
|
+ if (debug)
|
|
|
+ printf("[RecEnd ] CheckSum[0x%08X] Length[%4d] Length[0x%X] RecEnd[0x%08lX]\n",
|
|
|
+ CheckSum, RecLength, RecLength, RecEnd);
|
|
|
+
|
|
|
+ fseek( fOut, -((long) RecLength), SEEK_CUR); // move back Start Of Data
|
|
|
+
|
|
|
+ dumpfTell("Data ", -1);
|
|
|
+
|
|
|
+ fseek( fOut, -4, SEEK_CUR); // move back Start Of Address
|
|
|
+
|
|
|
+ dumpfTell("Address ", -1);
|
|
|
+
|
|
|
+ fseek( fOut, -4, SEEK_CUR); // move back Start Of Length
|
|
|
+
|
|
|
+ dumpfTell("Length ", -1);
|
|
|
+
|
|
|
+ binOut32( RecLength );
|
|
|
+
|
|
|
+ fseek( fOut, RecEnd, SEEK_SET); // move to end of Record
|
|
|
+
|
|
|
+ CheckSum += RecLength;
|
|
|
+
|
|
|
+ CheckSum = ~CheckSum + 1; // Two's complement
|
|
|
+
|
|
|
+ binOut32( CheckSum );
|
|
|
+
|
|
|
+ if (verbose)
|
|
|
+ printf("[Created Record of %d Bytes with CheckSum [0x%8X]\n", RecLength, CheckSum);
|
|
|
+}
|
|
|
+
|
|
|
+void binRecOutProgramStart(bit32u Address)
|
|
|
+{
|
|
|
+ if (Address != (AddressCurrent+1))
|
|
|
+ {
|
|
|
+ binRecEnd();
|
|
|
+ binRecStart(Address);
|
|
|
+ }
|
|
|
+ AddressCurrent = Address;
|
|
|
+}
|
|
|
+void binRecOutByte(bit32u Address, bit8u Data)
|
|
|
+{
|
|
|
+ // If Address is one after Current Address, output Byte
|
|
|
+ // If not, close out last record, update Length, write checksum
|
|
|
+ // Then Start New Record, updating Current Address
|
|
|
+
|
|
|
+ if (Address != (AddressCurrent+1))
|
|
|
+ {
|
|
|
+ binRecEnd();
|
|
|
+ binRecStart(Address);
|
|
|
+ }
|
|
|
+ AddressCurrent = Address;
|
|
|
+ CheckSum += Data;
|
|
|
+ binOut8( Data );
|
|
|
+}
|
|
|
+
|
|
|
+//=============================================================================
|
|
|
+// SUPPORT FUNCTIONS
|
|
|
+//=============================================================================
|
|
|
+int readline(FILE *fil,char *buf,int len)
|
|
|
+{
|
|
|
+ int rlen;
|
|
|
+
|
|
|
+ rlen=0;
|
|
|
+ if (len==0) return(0);
|
|
|
+ while(1)
|
|
|
+ {
|
|
|
+ if (cur_len==0)
|
|
|
+ {
|
|
|
+ cur_len=fread(buffer, 1, sizeof(buffer), fil);
|
|
|
+ if (cur_len==0)
|
|
|
+ {
|
|
|
+ if (rlen)
|
|
|
+ {
|
|
|
+ *buf=0;
|
|
|
+ return(rlen);
|
|
|
+ }
|
|
|
+ return(-1);
|
|
|
+ }
|
|
|
+ cur_ptr=buffer;
|
|
|
+ }
|
|
|
+ if (cur_len)
|
|
|
+ {
|
|
|
+ if (*cur_ptr=='\n')
|
|
|
+ {
|
|
|
+ *buf=0;
|
|
|
+ cur_ptr++;
|
|
|
+ cur_len--;
|
|
|
+ return(rlen);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if ((len>1)&&(*cur_ptr!='\r'))
|
|
|
+ {
|
|
|
+ *buf++=*cur_ptr++;
|
|
|
+ len--;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ cur_ptr++;
|
|
|
+
|
|
|
+ rlen++;
|
|
|
+ cur_len--;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ *buf=0;
|
|
|
+ cur_ptr++;
|
|
|
+ cur_len--;
|
|
|
+ return(rlen);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+int SRLerrorout(char *c1,char *c2)
|
|
|
+{
|
|
|
+ printf("\nERROR: %s - '%s'.",c1,c2);
|
|
|
+ return(FALSE);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+int checksum(char *cp,int count)
|
|
|
+{
|
|
|
+ char *scp;
|
|
|
+ int cksum;
|
|
|
+ int dum;
|
|
|
+
|
|
|
+ scp=cp;
|
|
|
+ while(*scp)
|
|
|
+ {
|
|
|
+ if (!isxdigit(*scp++))
|
|
|
+ return(SRLerrorout("Invalid hex digits",cp));
|
|
|
+ }
|
|
|
+ scp=cp;
|
|
|
+
|
|
|
+ cksum=count;
|
|
|
+
|
|
|
+ while(count)
|
|
|
+ {
|
|
|
+ cksum += gh(scp,2);
|
|
|
+ if (count == 2)
|
|
|
+ dum = ~cksum;
|
|
|
+ scp += 2;
|
|
|
+ count--;
|
|
|
+ }
|
|
|
+ cksum&=0x0ff;
|
|
|
+ // printf("\nCk:%02x",cksum);
|
|
|
+ return(cksum==0x0ff);
|
|
|
+}
|
|
|
+
|
|
|
+bit32u gh(char *cp,int nibs)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ bit32u j;
|
|
|
+
|
|
|
+ j=0;
|
|
|
+
|
|
|
+ for(i=0;i<nibs;i++)
|
|
|
+ {
|
|
|
+ j<<=4;
|
|
|
+ if ((*cp>='a')&&(*cp<='z')) *cp &= 0x5f;
|
|
|
+ if ((*cp>='0')&&(*cp<='9'))
|
|
|
+ j += (*cp-0x30);
|
|
|
+ else
|
|
|
+ if ((*cp>='A')&&(*cp<='F'))
|
|
|
+ j += (*cp-0x37);
|
|
|
+ else
|
|
|
+ SRLerrorout("Bad Hex char", cp);
|
|
|
+ cp++;
|
|
|
+ }
|
|
|
+ return(j);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//=============================================================================
|
|
|
+// PROCESS SREC LINE
|
|
|
+//=============================================================================
|
|
|
+
|
|
|
+int srecLine(char *pSrecLine)
|
|
|
+{
|
|
|
+ char *scp,ch;
|
|
|
+ int itmp,count,dat;
|
|
|
+ bit32u adr;
|
|
|
+ static bit32u RecordCounter=0;
|
|
|
+
|
|
|
+ cur_line++;
|
|
|
+ scp=pSrecLine;
|
|
|
+
|
|
|
+ if (*pSrecLine!='S')
|
|
|
+ return(SRLerrorout("Not an Srecord file",scp));
|
|
|
+ pSrecLine++;
|
|
|
+ if (strlen(pSrecLine)<4)
|
|
|
+ return(SRLerrorout("Srecord too short",scp));
|
|
|
+
|
|
|
+ ch=*pSrecLine++;
|
|
|
+
|
|
|
+ count=gh(pSrecLine,2);
|
|
|
+
|
|
|
+ pSrecLine += 2;
|
|
|
+
|
|
|
+ // if(debug)
|
|
|
+ // printf("count %d, strlen(pSrecLine) = %d, pSrecLine =[%s]\n", count, strlen(pSrecLine), pSrecLine);
|
|
|
+ RecordCounter++;
|
|
|
+ DispHex(RecordCounter);
|
|
|
+
|
|
|
+ if ((count*2) != strlen(pSrecLine)) return(SRLerrorout("Count field larger than record",scp));
|
|
|
+
|
|
|
+ if (!checksum(pSrecLine, count)) return(SRLerrorout("Bad Checksum",scp));
|
|
|
+
|
|
|
+ switch(ch)
|
|
|
+ {
|
|
|
+ case '0': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
|
|
|
+ if (itmp) return(SRLerrorout("Srecord 1 address not zero",scp));
|
|
|
+ break;
|
|
|
+ case '1': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
|
|
|
+ break;
|
|
|
+ case '2': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
|
|
|
+ break;
|
|
|
+ case '3': if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
|
|
|
+ count--;
|
|
|
+ while(count)
|
|
|
+ {
|
|
|
+ dat=gh(pSrecLine,2); pSrecLine+=2; count--;
|
|
|
+ binRecOutByte(adr, (char) (dat & 0xFF));
|
|
|
+ adr++;
|
|
|
+ }
|
|
|
+ s1s2s3_total++;
|
|
|
+ break;
|
|
|
+ case '4': return(SRLerrorout("Invalid Srecord type",scp));
|
|
|
+ break;
|
|
|
+ case '5': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
|
|
|
+ if (itmp|=s1s2s3_total) return(SRLerrorout("Incorrect number of S3 Record processed",scp));
|
|
|
+ break;
|
|
|
+ case '6': return(SRLerrorout("Invalid Srecord type",scp));
|
|
|
+ break;
|
|
|
+ case '7': // PROGRAM START
|
|
|
+ if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
|
|
|
+ if (count!=1) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ binRecOutProgramStart(adr);
|
|
|
+ break;
|
|
|
+ case '8': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
|
|
|
+ break;
|
|
|
+ case '9': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
|
|
|
+ return(SRLerrorout("Srecord Not valid for MIPS",scp));
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return(TRUE);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//=============================================================================
|
|
|
+// MAIN LOGIC, READS IN LINE AND OUTPUTS BINARY
|
|
|
+//=============================================================================
|
|
|
+
|
|
|
+int srec2bin(int argc,char *argv[],int verbose)
|
|
|
+{
|
|
|
+ int i,rlen,sts;
|
|
|
+ FILE *fp;
|
|
|
+ char ac;
|
|
|
+ char buff[256];
|
|
|
+ bit32u TAG_BIG = 0xDEADBE42;
|
|
|
+ bit32u TAG_LITTLE = 0xFEEDFA42;
|
|
|
+
|
|
|
+ bit32u Tag;
|
|
|
+
|
|
|
+
|
|
|
+ if(argc < 3)
|
|
|
+ {
|
|
|
+ printf("\nError: <srec2bin <srec input file> <bin output file>\n\n");
|
|
|
+ return(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (argc > 3) BigEndian=TRUE; else BigEndian=FALSE;
|
|
|
+
|
|
|
+ if (BigEndian)
|
|
|
+ Tag = TAG_BIG;
|
|
|
+ else
|
|
|
+ Tag = TAG_LITTLE;
|
|
|
+
|
|
|
+ if (verbose)
|
|
|
+ printf("\nEndian: %s, Tag is 0x%8X\n",(BigEndian)?"BIG":"LITTLE", Tag);
|
|
|
+
|
|
|
+ fp = fopen(argv[1],"rt");
|
|
|
+
|
|
|
+ if (fp==NULL)
|
|
|
+ {
|
|
|
+ printf("\nError: Opening input file, %s.", argv[1]);
|
|
|
+ return(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ fOut = fopen( argv[2], "wb");
|
|
|
+
|
|
|
+ if (fOut==NULL)
|
|
|
+ {
|
|
|
+ printf("\nError: Opening Output file, %s.", argv[2]);
|
|
|
+ if(fp) fclose(fp);
|
|
|
+ return(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ RecStart = FALSE;
|
|
|
+
|
|
|
+ AddressCurrent = 0xFFFFFFFFL;
|
|
|
+
|
|
|
+ // Setup Tag
|
|
|
+
|
|
|
+ dumpfTell("Tag", Tag);
|
|
|
+
|
|
|
+ binOut32(Tag);
|
|
|
+
|
|
|
+
|
|
|
+ inputline=0;
|
|
|
+ sts=TRUE;
|
|
|
+
|
|
|
+ rlen = readline(fp,buff,sizeof buff);
|
|
|
+
|
|
|
+ while( (sts) && (rlen != -1))
|
|
|
+ {
|
|
|
+ if (strlen(buff))
|
|
|
+ {
|
|
|
+ sts &= srecLine(buff);
|
|
|
+ WaitDisplay();
|
|
|
+ }
|
|
|
+ rlen = readline(fp,buff,sizeof buff);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // printf("PC: 0x%08X, Length 0x%08X, Tag 0x%08X\n", ProgramStart, RecLength, TAG_LITTLE);
|
|
|
+
|
|
|
+ binRecEnd();
|
|
|
+
|
|
|
+ if(fp) fclose(fp);
|
|
|
+ if(fOut) fclose(fOut);
|
|
|
+
|
|
|
+ return(1);
|
|
|
+}
|
|
|
+
|
|
|
+main(int argc, char *argv[])
|
|
|
+{
|
|
|
+ debug = TRUE;
|
|
|
+ debug = FALSE;
|
|
|
+ verbose = FALSE;
|
|
|
+ srec2bin(argc,argv,verbose);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|