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