/**[txh]******************************************************************** Copyright (c) 2005 Juan Pablo D. Borgna Copyright (c) 2006-2007 Salvador E. Tropea Copyright (c) 2005-2007 Instituto Nacional de Tecnolog�a Industrial Copyright (c) 2012 Timothy Pearson This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA Description: Commands parser and executor. ***************************************************************************/ /***************************************************************************** Target: Any Language: C Compiler: gcc 3.3.5 (Debian GNU/Linux) Text editor: SETEdit 0.5.5 *****************************************************************************/ #include #include #include #include "global.h" #include "commands.h" #include "bitshandle.h" #define MAX_WIDTH 246 long value_from(char *varname) { if (!strncasecmp("BSIZEB2",varname,7)) return strtol(bsize,NULL,0)/4; if (!strncasecmp("BSIZEB",varname,6)) return strtol(bsize,NULL,0)/8; if (!strncasecmp("BSIZE",varname,5)) return strtol(bsize,NULL,0); if (!strncasecmp("MSIZE",varname,5)) return msize; return strtol(varname,NULL,0); } void fill(FILE *fp, long c, long t, int *col) { char b[4]="ZZ"; sprintf(b,"%02x",(unsigned int)c); int co=*col; for (;t>0;t--) { co+=fprintf(fp,"%s",b); if (co>=MAX_WIDTH) { co=0; fprintf(fp,"\n"); } } *col=co; } /* This function executes a $COMMAND$ */ int do_command(char *cmd, FILE *dfp, FILE *ofp, int *col) { char *temp; char *dbuffer; long nbytes=0l; long readed=0l; long value=0l; long times=0l; int padded=0; char *args_pos_s=NULL; char *args_pos_e=NULL; char *separator=NULL; char args[100]; /* I dont think i need more than 100 bytes for passing args... */ /* DATA and DATA_INV command */ if (strstr(cmd,"DATA")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if( !args_pos_s || !args_pos_e) { fprintf(stderr,"Bad argument specification in $DATA_INV(ndatabytes)$\n"); return 1; } memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te command */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ if ((nbytes=value_from(args))==0) /* Bad specification of number of bytes */ { fprintf(stderr,"Bad specification of ndatabytes in $DATA_INV(ndatabytes)$\n"); return 2; } if ((nbytes=value_from(args))==-1) /* Want to process the whole stream */ { nbytes=s_bytes; } if ((temp=(char *)malloc(nbytes*2+1))==NULL) { fprintf(stderr,"Cannot asign %li bytes in memory needed for $DATA_INV(ndatabytes)$\n",nbytes*2+1); return 3; } if ((dbuffer=(char *)malloc(nbytes))==NULL) { free(temp); fprintf(stderr,"Cannot asign %li bytes in memory needed for $DATA_INV(ndatabytes)$\n",nbytes); return 3; } if ((readed=fread(dbuffer,1,nbytes,dfp))!=nbytes) { if (padded) { free(dbuffer); free(temp); fprintf(stderr,"Cannot read %li databytes for $DATA_INV(ndatabytes)$ from bitfile\n",nbytes); return 3; } padded=1; memset(dbuffer+readed,0xff,nbytes-readed); } if (strstr(cmd,"DATA_INV")) pbi(temp,dbuffer,nbytes); /* Want to inver the bits*/ else pb(temp,dbuffer,nbytes); /* Want to use the bits*/ temp[nbytes*2]='\0'; if (cutputs(temp,ofp,MAX_WIDTH,col)) { fprintf(stderr,"Could not write $DATA to file.\n"); return 4; } free(temp); free(dbuffer); return 0; } /* end DATA and DATA_INV command */ /* ADDRESS command */ if (strstr(cmd,"ADDRESS")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $ADDRESS(DIR)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { /* Want to use the value */ if (msize<=0x10000) *col+=fprintf(ofp,"%04x",(unsigned int)address); else *col+=fprintf(ofp,"%06x",(unsigned int)address); return 0; } /* Want to SET the value */ memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ value=value_from(args); address=value; return 0; } /* end ADDRESS command */ /* SET: CUTLINES command */ if (strstr(cmd,"CUTLINES")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $CUTLINES(ON)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { /* Want to use the value */ *col+=fprintf(ofp,"%04x",(unsigned int)cutlines); return 0; } /* Want to SET the value */ memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ value=value_from(args); cutlines=value; return 0; } /* end CUTLINES command */ /* STEP command */ if (strstr(cmd,"STEP")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $STEP(VAL)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { /* Want to use the value */ *col+=fprintf(ofp,"%04x",(unsigned int)step); return 0; } /* Want to SET the value */ memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ value=value_from(args); step=value; return 0; } /* end STEP command */ /* REWIND command */ if (strstr(cmd,"REWIND")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if(args_pos_s || args_pos_e ) { fprintf(stderr,"No arguments needed by $REWIND$\n"); return 1; } fseek(dfp,stream_s,0); return 0; } /* end REWIND command */ /* SBITS command */ if (strstr(cmd,"SBITS")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $SBITS(VAL)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { /* Want to use the value */ *col+=fprintf(ofp,"%d",(unsigned int)s_bits); return 0; } /* Want to SET the value */ memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ value=value_from(args); s_bits=value; return 0; } /* end SBITS command */ /* SADDBITS command */ if (strstr(cmd,"SADDBITS")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $SADDBITS(VAL)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { fprintf(stderr,"Bad argument specification in $SADDBITS(VAL)$\n"); return 1; } memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy the argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ value=value_from(args); *col+=fprintf(ofp,"%d",(unsigned int)(s_bits+value)); return 0; } /* end SADDBITS command */ /* SBYTES command */ if (strstr(cmd,"SBYTES")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $SBYTES(VAL)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { /* Want to use the value */ *col+=fprintf(ofp,"%d",(unsigned int)s_bytes); return 0; } /* Want to SET the value */ memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy the argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ value=value_from(args); s_bytes=value; return 0; } /* end SBYTES command */ /* FILL command */ if (strstr(cmd,"FILL")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); separator=strchr(cmd,','); if(!args_pos_s || !args_pos_e || !separator) { fprintf(stderr,"Bad argument specification in $FILL(VAL,TIMES)$\n"); return 1; } /* Want to SET the value */ memcpy(args,args_pos_s+1,4); /* Copy the character */ args[4]='\0'; /* Put the null terminator */ value=value_from(args); memcpy(args,separator+1,(size_t)(args_pos_e-separator)); /* Copy the times */ times=value_from(args); if(times==-1) times=s_bytes; fill(ofp,value,times,col); return 0; } /* end FILL command */ /* IDMASK command */ if (strstr(cmd,"IDMASK")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $IDMASK(VAL)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { /* Want to use the value */ *col+=fprintf(ofp,"%s",idmask); return 0; } /* Want to SET the value */ memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ if (id) free(id); if((id=(char *)malloc(strlen(args)))==NULL) { fprintf(stderr,"Cannot asign memory needed for $IDMASK$\n"); return 3; } strcpy(id,args); return 0; } /* end IDMASK command */ /* ID command */ if (strstr(cmd,"ID")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $ID(VAL)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { /* Want to use the value */ *col+=fprintf(ofp,"%s",id); return 0; } /* Want to SET the value */ memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ if (id) free(id); if((id=(char *)malloc(strlen(args)))==NULL) { fprintf(stderr,"Cannot asign memory needed for $ID$\n"); return 3; } strcpy(id,args); return 0; } /* end ID command */ /* BSIZE2 command */ if (strstr(cmd,"BSIZE2")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if (args_pos_s || args_pos_e) { fprintf(stderr,"$BSIZE2$ is read only\n"); return 1; } *col+=fprintf(ofp,"%ld",strtol(bsize,NULL,0)*2); return 0; } /* end BSIZE2 command */ /* BSIZE command */ if (strstr(cmd,"BSIZE")) { /* get the args inside the () */ args_pos_s=strchr(cmd,'('); args_pos_e=strchr(cmd,')'); if((!args_pos_s && args_pos_e )|| (!args_pos_e && args_pos_s)) { fprintf(stderr,"Bad argument specification in $BSIZE(VAL)$\n"); return 1; } if (!args_pos_s && !args_pos_e) { /* Want to use the value */ *col+=fprintf(ofp,"%s",bsize); return 0; } /* Want to SET the value */ memcpy(args,args_pos_s+1,(size_t)(args_pos_e-args_pos_s)); /* Copy te argument */ args[args_pos_e-args_pos_s-1]='\0'; /* Put the null terminator */ if (id) free(id); if((id=(char *)malloc(strlen(args)))==NULL) { fprintf(stderr,"Cannot asign memory needed for $BSIZE$\n"); return 3; } strcpy(bsize,args); return 0; } /* end BSIZE command */ return 0; } int repeat (FILE *ifp, FILE *ofp, FILE *dfp,long limit) { char line[2001]; char *cmd_pos_s=NULL; char *cmd_pos_e=NULL; char cmd[30]; long entry_point; long end_address=limit; /*+step; SET: Why?*/ /* Sanity check */ if (limit>0 && address>=end_address) { /* SET: Not an error, the PROMs have some "fillers", when we use the full memory the fillers must be skipped */ fprintf(stderr,"WARNING: REPEAT UNTIL 0x%lX but current address is 0x%lX\n", limit,address); if (fgets(line,2001,ifp)==NULL) return 1; do { if (!strncasecmp(line,"--END",5)) break; if (fgets(line,2001,ifp)==NULL) return 1; /* get a new line to parse */ } while(1); return 0; } entry_point=ftell(ifp); if (fgets(line,2001,ifp)==NULL) return 1; do { int col=0; cmd_pos_e=NULL; /* Ending position of command, also used as flag for a command found or not */ if (!strncasecmp(line,"--END",5)) { address+=step; /* Repeat condition */ /* SET: XCF02S can produce address>end_address */ if ( (limit==0) || ((limit <0) && feof(dfp)) || ((limit >0) && (address>=end_address))) break; if (ftell(dfp)-stream_s>=s_bytes) { fprintf(stderr,"INFO: Bitstream limit reached\n"); //fprintf(stderr,"limit: %ld address %ld end_address %ld\n",limit,address,end_address); break; } /*Sanity check*/ if ( (0 < limit) && (end_address < address)) { fprintf(stderr,"ERROR: REPEAT UNTIL 0x%lX but current address is 0x%lX (2)\n",limit,address); return 24; } fseek(ifp,entry_point,0); if (fgets(line,2001,ifp)==NULL) return 1; /* get a new line to parse */ continue; } while((cmd_pos_s=strchr(line,'$'))) /* $ character found in line */ { if (cmd_pos_e) { /* There was another command on this line before */ /* Write intermedia bytes */ int size=cmd_pos_s-cmd_pos_e-1; if (fwrite(cmd_pos_e+1,1,size,ofp)!=cmd_pos_s-cmd_pos_e-1) { fprintf(stderr,"There was an error writing to svf file.\n"); return 2; } col+=size; } else { /* write from begining of line to the starting $ char to output file */ size_t size=cmd_pos_s-line; if (fwrite(line,1,size,ofp)!=(size_t)(cmd_pos_s-line)) { fprintf(stderr,"There was an error writing to svf file.\n"); return 2; } col+=size; } /* clear the starting '$' simbol so i can search the next */ *cmd_pos_s='_'; if ((cmd_pos_e=strchr(line,'$'))==NULL) { fprintf(stderr,"Parse error: Cant find ending '$' while parsing command.\n"); return 3; } *cmd_pos_e='_'; /* clear the ending '$' simbol so i can search the next */ memcpy(cmd,cmd_pos_s+1,(size_t)(cmd_pos_e-cmd_pos_s-1)); /* Copy the command */ cmd[cmd_pos_e-cmd_pos_s-1]='\0'; /* Put the null terminator */ if (do_command(cmd,dfp,ofp,&col)) return 3; } /* No more commands */ if (cmd_pos_e) { if (fputs(cmd_pos_e+1,ofp)==EOF) return 2; /* Write remainig bytes */ } else { /* There was no command */ if (fputs(line,ofp)==EOF) return 2; /* Write all the line */ } if (fgets(line,2001,ifp)==NULL) return 1; /* get a new line to parse */ } while (1); return 0; }