📄 rdsrec.c
字号:
/************************************************************* * File: tools/rdsrec.c * Purpose: S-record reader * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970327 Changed RMON to IMON in help. * 970818 Fixed prob caused by srecs that have odd# of bytes * 970823 Fixed prob w disasm mip16 code * 970927 Fixed prob w -A caused by 970823 * 970927 Added checksum to -A mode * 970930 Large change. Sort srecs into linked list before processing. * This was necessary for bso. Also added bytefill. Necessary * for Cygnus. * 970930 Removed the vertcut feature. * 971001 Fixed wrong addresses in -n * 971003 Fixed -C. Don't emit .byte. * 980309 Added -m option for generating .ocm files. * 981205 The -b option fails if address appears more than once. * 990115 Added -Bnn option to set length of srecord. */#include <stdio.h>#include <string.h>#include <ctype.h>#include <malloc.h>#ifdef MSDOS#include <fcntl.h>#include <io.h>#endiftypedef unsigned char Uchar;typedef unsigned long Ulong;#define DEBUG 0#define loop for (;;)#define RECSIZE 100#define strNcpy(x,y,z) strncpy(x,y,z),x[z]=0#define LINESZ 100#define BLKSIZE 500#define ADDRSIZE 4 /* address size specified in bytes 2 = S1recs, 3 = S2recs, 4 = S3 recs *//* special fast-format 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 *//* define the other 2 chars needed for base 64 */char exta = ',';char extb = '.';typedef struct SymRec { struct SymRec *next; char *name; unsigned long value; } SymRec;typedef struct DataRec { struct DataRec *next; Ulong addr; int len; Uchar *data; } DataRec;int filecount;char *filelist[10];int debug;int nodisasm;char prnbuf[100];SymRec *symchn; /* symbols in reverse value order (highest 1st) */int fastmode;Ulong nextaddr;Ulong addr;int zcnt;int blksz;int chksum;int cflag = 1;int datasize = 32;int Dflag;int mflag;int gensrecs;unsigned long bdat;unsigned long bdat_cnt;char bytebuf[256];int bytecnt,vertnn;Ulong bytebufadr;DataRec *datachn;int bytefill;/* output file pointer and name */FILE *ofp;char *oname;char *usage[] = { "usage: rdsrec [-bln] file [-o name]", "Read a Motorola S-record file. By default it disassembles the file.", "\t-A name\tgenerate assembly data declarations", "\t-b\tsend binary image to stdout.", "\t-Bnn\tnumber of databytes per record (for -s option)", "\t-C name\tgenerate C data declarations", "\t-D\tmark the output as a TDD for IMON", "\t-f\tgenerate fast-format records", "\t-l\tlittle endian, swap each word", "\t-m\tgenerate ocm info file", "\t-n\tno disassembly", "\t-o name\tsend output to file", "\t-s\tgenerate S-records", "\t-Txxxxxxxx\tadd offset to record address",#if 0 /* 970930 feature removed */ "\t-vm.n\tvertical cut",#endif 0};int binary,little;Ulong Toffs;#if 0 /* feature removed 970930 */int vertm = 1;int vertn = 0;#endifchar *cname;char *aname;FILE *ifp;char linebuf[RECSIZE]; /* buffer the ascii data from the file */Uchar databuf[RECSIZE]; /* buffer the data bytes */int bufinx,buflen; /* indexes into the databuf[] */long disasm();char *strccat();int getbyte();/************************************************************** 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] == 'd') debug = 1; else if (argv[i][j] == 'b') { binary = 1; bytefill = 1; } else if (argv[i][j] == 'B') { sscanf(&argv[i][j],"B%d",&datasize); break; } else if (argv[i][j] == 'T') { sscanf(&argv[i][j],"T%lx",&Toffs); break; } else if (argv[i][j] == 'l') little = 1; else if (argv[i][j] == 'o') { if (i+1 >= argc) { printf("bad arg count\n"); exit(1); } oname = argv[++i]; break; } else if (argv[i][j] == 'A') { if (i+1 >= argc) { printf("bad arg count\n"); exit(1); } aname = argv[++i]; bytefill = 1; break; } else if (argv[i][j] == 'C') { if (i+1 >= argc) { printf("bad arg count\n"); exit(1); } cname = argv[++i]; bytefill = 1; break; } else if (argv[i][j] == 'n') nodisasm = 1; else if (argv[i][j] == 'D') Dflag = 1; else if (argv[i][j] == 'f') fastmode = 1; else if (argv[i][j] == 's') gensrecs = 1; else if (argv[i][j] == 'c') cflag = 0; else if (argv[i][j] == 'm') mflag = 1;#if 0 /* feature removed 970930 */ else if (argv[i][j] == 'v') { sscanf(&argv[i][j],"v%d.%d",&vertm,&vertn); break; }#endif 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 */ filelist[filecount++] = argv[i]; }#if 0 /* feature removed 970930 */if (vertn+1 > vertm) { fprintf(stderr,"incompatible -vm.n options\n"); exit(1); }#endifif (oname) { ofp = fopen(oname,"w"); if (!ofp) { fprintf(stderr,"can't open %s\n",oname); exit(1); } }else ofp = stdout;#ifdef MSDOS/* MSDOS converts 0x0a to 0x0d0a, so... */if (binary) _setmode(fileno(ofp),_O_BINARY);#endifif (filecount == 0) dofile(stdin,"stdin");else { for (i=0;i<filecount;i++) { /* do the files */ fp = fopen(filelist[i],"r"); if (! fp) { fprintf(stderr,"can't open %s\n",filelist[i]); exit(-1); } dofile(fp,filelist[i]); fclose(fp); } }exit(0);}/************************************************************** dofile(fp,fname)* do a file*/dofile(fp,fname)FILE *fp;char *fname;{int len,x,totbytes;int i,mips16,v;Ulong val,na,csum,addr;mips16 = 0;ifp = fp;if (Dflag && fastmode) send12("/D",0);if (cflag && fastmode) send12(CLRSUM,0);if (cname) fprintf(ofp,"unsigned char %s[] = {\n",cname);if (aname) fprintf(ofp,"\t.data\n\t.globl %s\n%s:\n\t.byte ",aname,aname);totbytes = 0;csum = 0;for (i=0;;i++) { v = getbyte(&addr); if (v == EOF) break; val <<= 8; val |= v; if (fastmode && addr != nextaddr) txaddr(addr); else if (gensrecs) srecSend(addr,v); else if (fastmode) fastSend(v); else if (cname || aname) { if (i>=12) { if (aname) fprintf(ofp,"\n\t.byte "); else fprintf(ofp,"\n\t"); /* 971003 */ i = 0; } if (i != 0) fprintf(ofp,","); fprintf(ofp,"0x%02x",v); totbytes++; csum += v; } else if((i+1)%4 == 0) { if (little) word_swap(&val); if (binary) putw(&val,ofp); else if (nodisasm) fprintf(ofp,"%08lx: %08lx\n",addr-3,val); else { setTiny(addr-3,&mips16); if (mips16) { na = disasm(prnbuf,addr-2, val); fprintf(ofp,"%s\n",prnbuf); if (na-(addr-2) == 2) i -= 2; } else { disasm(prnbuf,addr-3, val); if (mflag) col2only(prnbuf); fprintf(ofp,"%s\n",prnbuf); } } } }if (fastmode) txeof(addr);if (gensrecs) do_erec(addr);if (cname) { fprintf(ofp,"};\nint %s_size = %d;\n",cname,totbytes); fprintf(ofp,"unsigned long %s_csum = 0x%08lx;\n",cname,csum); }if (aname) { fprintf(ofp,"\n\t.sdata\n\t.globl %s_size\n%s_size: .word %d\n", aname,aname,totbytes); fprintf(ofp,"\t.globl %s_csum\n%s_csum: .word 0x%08lx\n", aname,aname,csum); }}/************************************************************** int getbyte(paddr)* get the next data byte from the input file*/int getbyte(paddr)Ulong *paddr;{int x;int len;DataRec *p;if (!datachn) { for (;;) { if (!fgets(linebuf,RECSIZE,ifp)) break; if (linebuf[strlen(linebuf)-1] == '\n') linebuf[strlen(linebuf)-1] = 0; if (linebuf[strlen(linebuf)-1] == '\r') linebuf[strlen(linebuf)-1] = 0; if (linebuf[0] != 'S') continue; if (linebuf[1] >= '1' && linebuf[1] <= '3') { if (x=datarec(linebuf,&addr,&len)) fprintf(stderr,"err %ld\n",x); addDataRec(addr,databuf,len); } else if (linebuf[1] >= '7' && linebuf[1] <= '9') entrec(linebuf,&addr); else if (linebuf[1] == '4') symrec(linebuf); } bufinx = 0; nextaddr = datachn->addr+1; *paddr = datachn->addr+Toffs; return datachn->data[bufinx++]; }if (bufinx >= datachn->len) { free(datachn->data); p = datachn; datachn = p->next; free(p); bufinx = 0; if (datachn == 0) return(EOF); *paddr = datachn->addr+Toffs; }if (bytefill && datachn->addr > nextaddr) { nextaddr++; *paddr = nextaddr+Toffs; return(0); }*paddr = datachn->addr+bufinx+Toffs;nextaddr = datachn->addr+bufinx+1;return datachn->data[bufinx++];}/************************************************************** addDataRec(addr,data,len)*/addDataRec(addr,data,len)Ulong addr;Uchar *data;int len;{DataRec *new,*p,*pr;new = (DataRec *)malloc(sizeof(DataRec));new->data = (Uchar *)malloc(len);memcpy(new->data,data,len);new->addr = addr;new->len = len;new->next = 0;/* empty chain */if (!datachn) { datachn = new; return; }/* insert before first item? */if (datachn->addr > new->addr) { new->next = datachn; datachn = new; return; }/* one item on chain */if (datachn->next == 0) { datachn->next = new; return; } /* n items on chain */for (p=datachn->next,pr=datachn;p;p=p->next) { if (p->addr > new->addr) break; pr = p; }new->next = pr->next;pr->next = new;return;}/************************************************************** entrec(p)* process an entry-point record*/entrec(p,paddr)char *p;Ulong *paddr;{int len,i,chksum;unsigned long addr,v;chksum = 0;if (!gethex(&len,&p[2],2)) return(-1);chksum += len;if (len*2 != strlen(p)-4) return(-2);i = 4; addr = 0;switch (p[1]) { case '7' : if (!gethex(&v,&p[i],2)) return(-1); addr = (addr<<8)+v; chksum += v; i += 2; case '8' : if (!gethex(&v,&p[i],2)) return(-1); addr = (addr<<8)+v; chksum += v; i += 2; case '9' : if (!gethex(&v,&p[i],2)) return(-1); addr = (addr<<8)+v; chksum += v; if (!gethex(&v,&p[i+2],2)) return(-1); addr = (addr<<8)+v; chksum += v; break; default : return(-3); }if (!fastmode && !aname) fprintf(stderr,"Entry point %08lx\n",addr);*paddr = addr;return(0);}/************************************************************** datarec(p,paddr,plen)* process a data record*/datarec(p,paddr,plen)char *p;Ulong *paddr;int *plen;{int len,i,chksum,cs;Ulong v,val;*plen = 0;chksum = 0;if (!gethex(&len,&p[2],2)) return(-1);chksum += len;if (len*2 != strlen(p)-4) return(-2);i = 4; addr = 0;switch (p[1]) { case '3' : if (!gethex(&v,&p[i],2)) return(-1); addr = (addr<<8)+v; chksum += v; i += 2; case '2' : if (!gethex(&v,&p[i],2)) return(-1); addr = (addr<<8)+v; chksum += v; i += 2; case '1' : if (!gethex(&v,&p[i],2)) return(-1); addr = (addr<<8)+v; chksum += v; if (!gethex(&v,&p[i+2],2)) return(-1); addr = (addr<<8)+v; chksum += v; break; default : return(-3); }*paddr = addr;p = &p[i+4];len -= (i/2)+1;val = 0;for (i=0;i<len;i++,p+=2) { if (!gethex(&v,p,2)) return(-1); databuf[i] = v; chksum += v; }if (!gethex(&cs,p,2)) return(-1);if (cs != ((~chksum)&0xff)) return(-4);*plen = i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -