• 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   int dum;
298 
299   scp=cp;
300   while(*scp)
301   {
302     if (!isxdigit(*scp++))
303       return(SRLerrorout("Invalid hex digits",cp));
304   }
305   scp=cp;
306 
307   cksum=count;
308 
309   while(count)
310   {
311     cksum += gh(scp,2);
312     if (count == 2)
313         dum = ~cksum;
314     scp += 2;
315     count--;
316   }
317   cksum&=0x0ff; 
318   //  printf("\nCk:%02x",cksum);
319   return(cksum==0x0ff);
320 }
321 
322 bit32u gh(char *cp,int nibs)
323 {
324   int i;
325   bit32u j;
326 
327   j=0;
328 
329   for(i=0;i<nibs;i++)
330   {
331     j<<=4;
332     if ((*cp>='a')&&(*cp<='z')) *cp &= 0x5f;
333     if ((*cp>='')&&(*cp<='9')) 
334       j += (*cp-0x30);
335      else
336       if ((*cp>='A')&&(*cp<='F'))
337         j += (*cp-0x37);
338        else
339         SRLerrorout("Bad Hex char", cp);
340     cp++;
341   }
342   return(j);
343 }
344 
345 
346 //=============================================================================
347 //       PROCESS SREC LINE
348 //=============================================================================
349 
350 int srecLine(char *pSrecLine)
351 {
352     char *scp,ch;
353     int  itmp,count,dat;
354     bit32u adr;
355     static bit32u RecordCounter=0;
356 
357     cur_line++;
358     scp=pSrecLine;
359   
360     if (*pSrecLine!='S')
361       return(SRLerrorout("Not an Srecord file",scp));
362     pSrecLine++;
363     if (strlen(pSrecLine)<4)
364       return(SRLerrorout("Srecord too short",scp));
365   
366     ch=*pSrecLine++;
367   
368     count=gh(pSrecLine,2);
369   
370     pSrecLine += 2;
371   
372   //  if(debug)
373   //        printf("count %d, strlen(pSrecLine) = %d, pSrecLine =[%s]\n", count, strlen(pSrecLine), pSrecLine);
374      RecordCounter++;
375      DispHex(RecordCounter);
376   
377     if ((count*2) != strlen(pSrecLine)) return(SRLerrorout("Count field larger than record",scp));
378   
379     if (!checksum(pSrecLine, count)) return(SRLerrorout("Bad Checksum",scp));
380   
381     switch(ch)
382     {
383         case '': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
384                   itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
385                   if (itmp) return(SRLerrorout("Srecord 1 address not zero",scp));
386         break;
387         case '1': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
388                   return(SRLerrorout("Srecord Not valid for MIPS",scp));
389         break;
390         case '2': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
391                   return(SRLerrorout("Srecord Not valid for MIPS",scp));
392         break;
393         case '3': if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
394                   adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
395                   count--;
396                   while(count)
397                   {
398                     dat=gh(pSrecLine,2); pSrecLine+=2; count--;
399                     binRecOutByte(adr, (char) (dat & 0xFF));
400                     adr++;
401                   }
402                   s1s2s3_total++;
403         break;
404         case '4': return(SRLerrorout("Invalid Srecord type",scp));
405         break;
406         case '5': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
407                   itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2;
408                   if (itmp|=s1s2s3_total) return(SRLerrorout("Incorrect number of S3 Record processed",scp));
409         break;
410         case '6': return(SRLerrorout("Invalid Srecord type",scp));
411         break;
412         case '7': // PROGRAM START
413                   if (count<5) return(SRLerrorout("Invalid Srecord count field",scp));
414                   adr=gh(pSrecLine,8); pSrecLine+=8; count-=4;
415                   if (count!=1) return(SRLerrorout("Invalid Srecord count field",scp));
416                   binRecOutProgramStart(adr);
417         break;
418         case '8': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp));
419                   return(SRLerrorout("Srecord Not valid for MIPS",scp));
420         break;
421         case '9': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp));
422                   return(SRLerrorout("Srecord Not valid for MIPS",scp));
423         break;
424         default:
425         break;
426     }
427     return(TRUE);
428 }
429  
430 
431 //=============================================================================
432 //       MAIN LOGIC, READS IN LINE AND OUTPUTS BINARY
433 //=============================================================================
434 
435 int srec2bin(int argc,char *argv[],int verbose)
436 {
437     int rlen,sts;
438     FILE *fp;
439     char buff[256];
440     bit32u TAG_BIG     = 0xDEADBE42;
441     bit32u TAG_LITTLE  = 0xFEEDFA42;
442 
443     bit32u Tag;
444 
445   
446     if(argc < 3)
447     {
448       printf("\nError: <srec2bin <srec input file> <bin output file>\n\n");
449       return(0);
450     }
451   
452     if (argc > 3) BigEndian=TRUE; else BigEndian=FALSE;
453 
454     if (BigEndian)
455         Tag = TAG_BIG;
456     else
457         Tag = TAG_LITTLE;
458 
459     if (verbose)
460        printf("\nEndian: %s, Tag is 0x%8X\n",(BigEndian)?"BIG":"LITTLE", Tag);
461 
462     fp = fopen(argv[1],"rt");
463 
464     if (fp==NULL)
465     {
466       printf("\nError: Opening input file, %s.", argv[1]);
467       return(0);
468     }
469   
470     fOut = fopen( argv[2], "wb");
471     
472     if (fOut==NULL)
473     {
474       printf("\nError: Opening Output file, %s.", argv[2]);
475       if(fp) fclose(fp);
476       return(0);
477     }
478  
479     RecStart = FALSE;
480 
481     AddressCurrent = 0xFFFFFFFFL;
482 
483     // Setup Tag 
484   
485     dumpfTell("Tag", Tag);
486 
487     binOut32(Tag);
488 
489   
490     inputline=0;
491     sts=TRUE;
492 
493     rlen = readline(fp,buff,sizeof buff);
494 
495     while( (sts) && (rlen != -1))
496     {
497         if (strlen(buff))
498         {
499             sts &= srecLine(buff);
500             WaitDisplay();
501         }
502        rlen = readline(fp,buff,sizeof buff);
503     }
504 
505   
506   //  printf("PC: 0x%08X, Length 0x%08X, Tag 0x%08X\n", ProgramStart, RecLength, TAG_LITTLE);
507   
508     binRecEnd();
509 
510     if(fp) fclose(fp);
511     if(fOut) fclose(fOut);
512 
513     return(1);
514 }
515 
516 int main(int argc, char *argv[])
517 {
518     debug = TRUE;
519     debug = FALSE;
520     verbose = FALSE;
521     srec2bin(argc,argv,verbose);
522     return 0;
523 }
524 
525 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt