• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/srec2bin.c

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

This page was automatically generated by LXR 0.3.1.  •  OpenWrt