mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-24 03:58:35 +02:00
Add srec2bin to firmware-utils
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@6599 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
01d129a6a2
commit
865cfde1ef
@ -25,6 +25,7 @@ define Build/Compile
|
||||
$(call cc,trx2usr)
|
||||
$(call cc,ptgen)
|
||||
$(call cc,airlink)
|
||||
$(call cc,srec2bin)
|
||||
endef
|
||||
|
||||
define Build/Install
|
||||
|
523
tools/firmware-utils/src/srec2bin.c
Normal file
523
tools/firmware-utils/src/srec2bin.c
Normal file
@ -0,0 +1,523 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.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 etc
|
||||
|
||||
void 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 Start
|
||||
|
||||
void 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 i,rlen,sts;
|
||||
FILE *fp;
|
||||
char ac;
|
||||
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);
|
||||
}
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
debug = TRUE;
|
||||
debug = FALSE;
|
||||
verbose = FALSE;
|
||||
srec2bin(argc,argv,verbose);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user