📄 genfrec.c
字号:
/************************************************************* * File: tools/genfrec.c * Purpose: Generate fast-format records from a MIPS COFF file * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970313 Added -e option */#include <stdio.h>#include "mipscoff.h"/* * This program is intended for downloading program binaries to * a specially equipped prom monitor. It uses base 64 encoding, where * three bytes are sent as four characters. There are two record types, * those starting with '/' and those that do not. The records that start * with a '/' are used to perform special operations, all other records * contain 24 bits of data. The function send12 is used to send special * operations, whereas the function send24 is used to send data. * To further improve download performance, contiguous records of zero * are sent as a special record that includes a count value. The bss * section is cleared using these special records. */#define DEBUG 0#define BLKSIZE 500#define swap(x,y) ((y==2)?byte_swap(x,y):word_swap(x,y))/* special record types */#define ZEROS "/Z" /* record contains a count of zeros, actually it's the number of 24-bit records that are all zero */#define BYTE "/B" /* record contains a single byte */#define CHKSUM "/C" /* checksum to date */#define CLRSUM "/K" /* klear (sic) the checksum */#define ADDR "/A" /* double length record containing a 32 bit address */#define END "/E" /* end of download */unsigned long addr;int blksz;int chksum;/* define the other 2 chars needed for base 64 */char exta = ',';char extb = '.';char *usage[] = { "usage: genfrec [-ptdbcs] file", "\tgenerate fast-format records suitable for downloading to PMON.", "\t-p\tprom mode, start addresses at zero", "\t-t\tomit text section", "\t-b\tinclude bss section", "\t-d\tdebug mode", "\t-D\tdriver", "\t-c\tdon't send checksum record", "\t-s\tinclude symbols", "\t-e\tgenerate symbols exclusively", 0};int filecount = 0;int prom = 0;int omit_text = 0;int inc_bss = 0;int cflag = 1;int debug = 0;int driver = 0;int sflag = 0;int eflag = 0;unsigned long entry;int leflag;/*** 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[];{FILE *fp;int i,j;for (i=1;i<argc;i++) { /* first find all the options */ if (argv[i][0] == '-') { /* must be an option */ for (j=1;argv[i][j] != 0;j++) { if (argv[i][j] == 'p') prom = 1; else if (argv[i][j] == 't') omit_text = 1; else if (argv[i][j] == 'b') inc_bss = 1; else if (argv[i][j] == 'c') cflag = 0; else if (argv[i][j] == 'd') debug = 1; else if (argv[i][j] == 'e') eflag = 1; else if (argv[i][j] == 'D') driver = 1; else if (argv[i][j] == 's') sflag = 1; else { fprintf(stderr,"%c: bad option\n",argv[i][j]); for (j=0;usage[j];j++) fprintf(stderr,"%s\n",usage[j]); exit(-1); } } } else /* must be a file */ filecount++; }if (driver) send12("/D",0);if (cflag) send12(CLRSUM,0);if (filecount == 0) dofile(stdin,"stdin");else { for (i=1;i<argc;i++) { /* do the files */ if (argv[i][0] != '-') { /* must be a filename */ fp = fopen(argv[i],"r"); if (! fp) { fprintf(stderr,"can't open %s\n",argv[i]); exit(-1); } dofile(fp,argv[i]); fclose(fp); } } }txeof(entry);exit(0);}/************************************************************** dofile(ifp,fname)*/dofile(ifp,fname)FILE *ifp;char *fname;{struct aouthdr ohdr;unsigned long offset;struct filehdr fhdr;fread(&fhdr,sizeof(fhdr),1,ifp);if (fhdr.f_magic == 060001 || fhdr.f_magic == 061001 || fhdr.f_magic == 063001) { /* reverse endian */ leflag = 1; swap(&fhdr.f_magic,sizeof(fhdr.f_magic)); swap(&fhdr.f_nscns,sizeof(fhdr.f_nscns)); swap(&fhdr.f_opthdr,sizeof(fhdr.f_opthdr)); swap(&fhdr.f_symptr,sizeof(fhdr.f_symptr)); }else leflag = 0;if (debug) printf("magic=0%o nscns=%d ohdrsz=%d\n", fhdr.f_magic,fhdr.f_nscns,fhdr.f_opthdr);if (fhdr.f_magic != 0540 && fhdr.f_magic != 0542 && fhdr.f_magic != 0543 && fhdr.f_magic != 0546) { fprintf(stderr,"genfrec: 0%o Bad magic number\n",fhdr.f_magic); exit(1); }fread(&ohdr,sizeof(ohdr),1,ifp);if (leflag) { swap(&ohdr.entry,sizeof(ohdr.entry)); swap(&ohdr.tsize,sizeof(ohdr.tsize)); swap(&ohdr.text_start,sizeof(ohdr.text_start)); swap(&ohdr.dsize,sizeof(ohdr.dsize)); swap(&ohdr.data_start,sizeof(ohdr.data_start)); swap(&ohdr.bsize,sizeof(ohdr.bsize)); swap(&ohdr.bss_start,sizeof(ohdr.bss_start)); }if (debug) printf("entry=%lx tsize=%lx tbase=%lx dsize=%lx dbase=%lx\n", ohdr.entry,ohdr.tsize,ohdr.text_start,ohdr.dsize,ohdr.data_start);offset = ((fhdr.f_nscns*sizeof(struct scnhdr))+sizeof(fhdr)+ sizeof(ohdr)+15)&~15;if (sflag || eflag) do_syms(ifp,&fhdr);if (eflag) return;if (omit_text) fseek(ifp,offset+ohdr.tsize,0);else { txaddr(ohdr.text_start); fseek(ifp,offset,0); dosect(ifp,ohdr.tsize); }if (!prom) txaddr(ohdr.data_start);dosect(ifp,ohdr.dsize);if (inc_bss) clrbss(ohdr.bss_start,ohdr.bsize);if (!entry) entry = ohdr.entry;}/************************************************************** dosect(infile,scnsize)*/dosect(infile,scnsize)FILE *infile;long scnsize;{int i,n,zcnt,reccnt;unsigned char buf[3];long cnt,bdat;zcnt = 0;reccnt = 0;for (cnt=0;cnt+3<=scnsize;cnt+=3) { fread(buf,sizeof(buf[0]),3,infile); /* read 3 data bytes */ /* convert to single word */ bdat = buf[0]; bdat = (bdat<<8)+buf[1]; bdat = (bdat<<8)+buf[2]; if (bdat == 0) { /* compress if the data is zero */ zcnt++; if (zcnt < 4096) continue; zcnt--; } if (DEBUG) printf("%06lx ",cnt); if (zcnt > 0) { /* send a special record for zeros */ send12(ZEROS,zcnt); if (DEBUG) printf(" %03x\n",zcnt); reccnt++; zcnt = 0; } send24(bdat); /* send the data */ reccnt++; if (DEBUG) printf(" %06lx\n",bdat); }if (zcnt > 0) { /* make sure we didn't end with zeros outstanding */ send12(ZEROS,zcnt); if (DEBUG) printf(" %03x\n",zcnt); zcnt = 0; }if (DEBUG) printf("cnt=%06lx scnsize=%06lx\n",cnt,scnsize);for (i=0;i<scnsize-cnt;i++) { /* if sect size not divisable by 3 */ fread(buf,sizeof(buf[0]),1,infile); send12(BYTE,buf[0]); /* send individual byte */ if (DEBUG) printf(" %02x\n",buf[0]); }if (DEBUG) printf("\n");}/************************************************************** send12(type,val)*/send12(type,val)char *type;int val;{char adat[4];val &= 0xfff;chksum += val;adat[0] = type[0];adat[1] = type[1];adat[2] = b2a(val>>6);adat[3] = b2a(val);send(adat,4);}/************************************************************** send24(val)*/send24(val)unsigned long val;{char adat[4];int i;val &= 0xffffff;chksum += val>>12;chksum += val&0xfff;for (i=3;i>=0;i--) { adat[i] = b2a(val); val>>=6; }send(adat,4);}/************************************************************** send(p,n)*/send(p,n)char *p;int n;{if (blksz+n >= BLKSIZE) { putc('\n',stdout); blksz = 0; }fwrite(p,sizeof(p[0]),n,stdout);blksz += n;}/************************************************************** txchksum()*/txchksum(){send12(CHKSUM,chksum);chksum = 0;}/************************************************************** txeof(addr)*/txeof(addr)unsigned long addr;{if (cflag) txchksum(chksum);txaddr(addr);send12(END,0);putc('\n',stdout);}/************************************************************** txaddr(addr)*/txaddr(addr)unsigned long addr;{if (blksz+8 >= BLKSIZE) { putc('\n',stdout); blksz = 0; }send12(ADDR,addr>>24);send24(addr);if (DEBUG) printf(" %08lx ",addr);}/************************************************************** clrbss(addr,size)*/clrbss(addr,size)long addr,size;{int i,rem;txaddr(addr);if (DEBUG) printf("%08lx ",size);rem = size % 3;size /= 3;while (size>4095) { send12(ZEROS,4095); size -= 4095; }send12(ZEROS,size);for (i=0;i<rem;i++) send12(BYTE,0);}/************************************************************** a2b(c)* not used in this program*/a2b(c)int c;{/* translate base64 (tx form) to binaryA-Z 0..25a-z 26..510-9 52..61exta 62extb 63*/if (c >= 'A' && c <= 'Z') return(c-'A');if (c >= 'a' && c <= 'z') return(c-'a'+26);if (c >= '0' && c <= '9') return(c-'0'+52);if (c == exta) return(62);if (c == extb) return(63);printf("a2a: Bad input value\n");return(0);}/************************************************************** b2a(c)*/b2a(c)int c;{/* translate binary to base64 (tx form) 0..25 A-Z26..51 a-z52..61 0-96263*/c &= 0x3f;if (c <= 25) return('A'+c);if (c <= 51) return('a'+c-26);if (c <= 61) return('0'+c-52); if (c == 62) return(exta);if (c == 63) return(extb);printf("b2a: bad input value\n");return(0);}/************************************************************** 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;EXTR sym;HDRR symh;char buf[100];long p;blksz = 0;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)); } 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("sym=%s\n",buf); } txaddr(sym.asym.value); strcat(buf,","); for (;;) { len = strlen(buf)+2; if ((len&3) == 0) break; strcat(buf,"X"); } if (blksz+len >= BLKSIZE) { putc('\n',stdout); blksz = 0; } printf("/S%s",buf); blksz += len; }putc('\n',stdout);}/************************************************************** 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -