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