/************************************************************* * File: tools/gensrec.c * Purpose: Generate Motorola S-records from a MIPS COFF file * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970313 Added -e option * 970327 Changed RMON to IMON in help */ #include #include "mipscoff.h" #define ALIGN 16 /* alignment for start of section data */ #define DATASIZE 32 /* data size specified in bytes */ #define ADDRSIZE 4 /* address size specified in bytes 2 = S1recs, 3 = S2recs, 4 = S3 recs */ #define swap(x,y) ((y==2)?byte_swap(x,y):word_swap(x,y)) #define RECSIZE (DATASIZE + ADDRSIZE + 1) unsigned long addr; int sflag = 0; int bflag = 0; /* generate binary memory image */ int Bflag = 0; int Sflag = 0; int Dflag = 0; int eflag = 0; int debug = 0; /* debug switch */ int prom = 0; /* prom version */ int omit_text = 0; int leflag; char *usage[] = { "usage: gensrec [-opts] file", "\t-p\tprom mode, start addresses at zero", "\t-t\tomit text section", "\t-d\tdebug mode", "\t-b\tgenerate binary memory image file", "\t-B\temulate nm -B", "\t-s\tinclude symbols", "\t-S\tprint ROM/RAM sizes", "\t-D\tmark the file as a TDD for IMON", "\t-e\tgenerate symbols exclusively", 0}; #if 0 /*PERL*/ #endif char *sckey[] = {"0x00","T","D","B","0x04","A","0x06","0x07", "0x08","0x09","0x0a","0x0b","0x0c","G","S","0x0f", "0x10","0x11","0x12","0x13","0x14","0x15","I","0x17", "0x18","0x19","0x1a","0x1b","0x1c","0x1d","0x1e","0x1f", }; /* ** MIPS magic numbers: ** fread(&fhdr,sizeof(fhdr),1,fp) ** fhdr.f_magic HOST TARGET ** 0540 BE BE ** 061001 BE LE (swap req'd) ** 0542 LE LE ** 060001 LE BE (swap req'd) ** 0543 BE BE (mips2) ** 063001 BE LE (mips2, swap req'd) */ /************************************************************* * main(argc,argv) */ main(argc,argv) int argc; char *argv[]; { int i,j,num_files; FILE *fp; for (i=1;i= DATASIZE) n = fread(buf,1,DATASIZE,infile); else n = fread(buf,1,scnsize-cnt,infile); if (n == 0) break; /* hack for MSDOS */ printf("S%1d%02X",ADDRSIZE-1,n+ADDRSIZE+1); chksum += n+ADDRSIZE+1; for (j=ADDRSIZE-1;j>=0;j--) { byte = (addr>>(j*8)) & 0xff; printf("%02X",byte); chksum += byte; } for (j=0;j=0;j--) { byte = (entry>>(j*8)) & 0xff; printf("%02X",byte); chksum += byte; } printf("%02X\n",(~chksum)&0xff); } /************************************************************* * word_swap(vp) */ word_swap(vp) unsigned long *vp; { unsigned short v1,v2; v1 = (*vp)>>16; byte_swap(&v1); v2 = (*vp)&0xffff; byte_swap(&v2); *vp = (((unsigned long)v2)<<16)+v1; } /************************************************************* * byte_swap(vp) */ byte_swap(vp) unsigned short *vp; { *vp = ((*vp)<<8)+((*vp)>>8); } /************************************************************* * do_syms(fp,fhdr) */ do_syms(fp,fhdr) FILE *fp; struct filehdr *fhdr; { int i,size,len,csum; EXTR sym; HDRR symh; char buf[100]; long p; fseek(fp,fhdr->f_symptr,0); fread(&symh,sizeof(HDRR),1,fp); if (leflag) { swap(&symh.cbExtOffset,sizeof(symh.cbExtOffset)); swap(&symh.cbSsExtOffset,sizeof(symh.cbSsExtOffset)); swap(&symh.iextMax,sizeof(symh.iextMax)); } if (debug) { printf("HDRR offset=%08lx size=0x%02x\n",fhdr->f_symptr,sizeof(HDRR)); printf("cbSsExtOffset=%08lx iextMax=%d cbExtOffset=%08lx\n", symh.cbSsExtOffset,symh.iextMax,symh.cbExtOffset); printf("EXTR size=0x%02x\n",sizeof(EXTR)); printf("%5s %10s %10s %10s %2s %5s %10s\n", "#","adr","iss", "value","st","sc","index"); } p = symh.cbExtOffset; for (i=0;i<=symh.iextMax;i++) { fseek(fp,p,0); if (fread(&sym,sizeof(EXTR),1,fp) != 1) break; if (leflag) { swap(&sym.asym.iss,sizeof(sym.asym.iss)); swap(&sym.asym.value,sizeof(sym.asym.value)); sym.asym.sc = getsc(*((&sym.asym.value)+1)); } p = ftell(fp); fseek(fp,sym.asym.iss+symh.cbSsExtOffset,0); getsym(buf,fp); if (debug) { printf("[%3d] ",i); printf("0x%08lx ",sym.asym.iss); printf("0x%08lx ",sym.asym.value); printf("%02x[%s] ",sym.asym.sc,sckey[sym.asym.sc]); printf("sym=%s\n",buf); } if (Bflag) printf("%08lx %s %s\n",sym.asym.value,sckey[sym.asym.sc],buf); else { csum = 0; /* no checksum generated for symbols */ len = strlen(buf)+8+2; printf("S4%02X%08X%s,%02x\n",len,sym.asym.value,buf,csum); } } } /************************************************************* * getsc(w) * A somewhat ad-hoc solution for the sc bit field */ getsc(w) unsigned long w; { return(((w>>16)<<2)|(w>>30)); } /************************************************************* * getsym(p,fp) */ getsym(p,fp) char *p; FILE *fp; { int c; for (;;) { c = getc(fp); if (c == EOF) break; if (c == 0) break; *p++ = c; } *p = 0; }