| 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 etcvoid 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 Startvoid 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;}
 |