123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- #include <stdio.h>
- #include <ctype.h>
- #include <string.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 rlen,sts;
- FILE *fp;
- 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);
- }
- int main(int argc, char *argv[])
- {
- debug = FALSE;
- verbose = FALSE;
- srec2bin(argc,argv,verbose);
- return 0;
- }
|