home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / hardware / eprommer / source.lha / src / intelhex.c < prev    next >
C/C++ Source or Header  |  1993-06-26  |  7KB  |  285 lines

  1. #define _INTELHEX
  2. #define MIN(a,b) (((a>b)?b:a))
  3. #define MAX(a,b) (((a<b)?b:a))
  4. #include "intelhex.h"
  5.  
  6. /*#define DEBUG*/
  7.  
  8. #ifdef DEBUG
  9. extern FILE *fpdebug;
  10. #endif
  11.  
  12. void mystrncpy(char *dest,char *src,int n)
  13. {
  14.     /* Like the normal 'strncpy()' but appends a '\0' at end */
  15.  
  16.     while(n--)
  17.         *dest++=*src++;
  18.     *dest='\0';
  19. }
  20.  
  21. char *readintelhex(FILE *fp,unsigned char *buffer,int maxbuffer,long *plength,int flag,long *p_epromstart)
  22. {
  23.     /* Read a file in 'intelhex'-Format. Decode the data, check the 
  24.      * Checksum, fill the buffer with data.
  25.      * IF 'flag'==CONTINOUS no fragmented data is allowed,
  26.      *                        plength is set to real read number of bytes
  27.      * IF 'flag'==FRAGMENTED plength is set to size of part of used buffer
  28.      *
  29.      * RC: NULL if all went fine, else
  30.      *     Pointer to an error Message
  31.      */
  32.  
  33.     char line[BUFSIZ],    /* ASCII Buffer for reading line */
  34.          tmpbuf[5],        /* Buffer to extract and convert hex numbers */
  35.          *dummy;        /* like the name */
  36.     static char errormsg[256];    /* buffer for Error Message */
  37.     int ndata,            /* number of Databytes */
  38.         data,            /* one databyte */
  39.         address,        /* address for data */
  40.         status,            /* status of intelhex line */
  41.         chksum,            /* checksum of intelhex line */
  42.         sum,            /* own calculated checksum */
  43.         lnr=0,            /* linenumber */
  44.         totalbytes=0,    /* total bytes written to buffer */
  45.         highaddr,        /* determine the highest used buffer address */
  46.         lowaddr,        /* determine the lowest used buffer address */
  47.         
  48.         i;
  49.  
  50.         /* temp. Pointer to Binary Databuffer */
  51.     unsigned char *pbuf=(unsigned char *)-1;
  52.  
  53. #ifdef DEBUG
  54. fprintf(fpdebug,"readintelhex()\n");
  55. #endif
  56.  
  57.         /* set to ERROR */
  58.     *plength=0;
  59.  
  60.     while(fgets(line,BUFSIZ,fp))
  61.     {
  62.         lnr++;
  63. #ifdef DEBUG
  64. fprintf(fpdebug,"readih: line:%d\n",lnr);
  65. #endif
  66.  
  67.         if(line[IH_COLON]!=':')
  68.         {
  69.             if(lnr==1) /* First line ? */
  70.                 sprintf(errormsg,"No IntelHex Format");
  71.             else
  72.                 sprintf(errormsg,"Line:%d  Expected ':' at first character, get '%c'\nIs the File in IntelHex Format ?\n",lnr,line[IH_COLON]);
  73.             return(errormsg);
  74.         }
  75.  
  76.         /* get number of databytes */
  77.         mystrncpy(tmpbuf,&line[IH_NRDATA],2);
  78.         ndata = strtol(tmpbuf,&dummy,16);
  79.  
  80.         /* get address */
  81.         mystrncpy(tmpbuf,&line[IH_ADDRESS],4);
  82.         address = strtol(tmpbuf,&dummy,16);
  83.  
  84.         /* note used buffer range */
  85.         if(lnr==1)
  86.         {    /* Initialize */ 
  87.             highaddr=address+ndata-1;
  88.             lowaddr=address;
  89.         }
  90.         else
  91.         {
  92.             lowaddr = MIN(lowaddr,address);
  93.             highaddr= MAX(highaddr,address+ndata-1);
  94.         }
  95.  
  96. /*printf("lnr:%d, addr:%x low:%x high:%x ndata=%d\n",lnr,address,lowaddr,highaddr,ndata);*/
  97.  
  98.         /* get status */
  99.         mystrncpy(tmpbuf,&line[IH_STATUS],2);
  100.         status = strtol(tmpbuf,&dummy,16);
  101.         
  102.         /* get chksum */
  103.         mystrncpy(tmpbuf,&line[IH_FIRSTDATA+2*ndata],2);
  104.         chksum = strtol(tmpbuf,&dummy,16);
  105.         
  106.         /* build first part of own checksum */
  107.         sum = ndata + (0xFF&(address>>8)) + (0xFF&address) + status;
  108.  
  109.         /* check if last intelhex line */
  110.         if(ndata==0)
  111.         {
  112. #ifdef DEBUG
  113. printf("ndata=%d status=%d chksum=%d totalbytes=%d\n",ndata,status,chksum,totalbytes);
  114. #endif
  115.  
  116.             if( (status!=1) || (chksum!=0xFF))
  117.             {
  118.                 sprintf(errormsg,"Line:%d  ndata=0 but status=%d\n",lnr,status);
  119.                 return(errormsg);
  120.             }
  121.             else
  122.             {
  123.                 /* set total written bytes */
  124.  
  125. /*printf("end: total:%d calc:%d\n",totalbytes,highaddr-lowaddr+1);*/
  126.                 *plength = (flag==CONTINOUS) ? totalbytes : highaddr-lowaddr+1 ;
  127.                 *p_epromstart = lowaddr;
  128.                 return(NULL);
  129.             }
  130.         }
  131.         
  132.         /* check if is status correct */
  133.         if(status!=0)
  134.         {
  135.             sprintf(errormsg,"Line:%d  Wrong status, expected 0 not %d",lnr,status);
  136.             return(errormsg);
  137.         }
  138.         
  139.         /* check if is internal buffer big enough */
  140.         if(address+ndata>maxbuffer)
  141.         {
  142.             sprintf(errormsg,"Line:%d  Too much data, internal Buffer max:%d\n",lnr,maxbuffer);
  143.             return(errormsg);
  144.         }
  145.  
  146.         if(pbuf!=(unsigned char *)-1)
  147.         {
  148.             if( (flag==CONTINOUS) && (pbuf!=buffer + address) )
  149.             {
  150.                 sprintf(errormsg,"Line:%d  Data not continous",lnr);
  151.                 return(errormsg);
  152.             }
  153.         }
  154.         i=IH_FIRSTDATA;                /* first databyte in intelhex line */
  155.         pbuf = buffer + address;    /* first buffer position */
  156.         while(ndata--)
  157.         {    
  158.             mystrncpy(tmpbuf,&line[i],2);
  159.             data = strtol(tmpbuf,&dummy,16);
  160.             *pbuf++=(unsigned char)data;
  161.             i+=2;
  162.             sum+=data;
  163.             totalbytes++;
  164.         }
  165.  
  166.             /* make chksum complete */
  167.         sum = 0xFF & ( 0x100 - sum );
  168.  
  169.         /* compare checksum's */
  170.         if(chksum != sum)
  171.         {
  172.             sprintf(errormsg,"Line:%d  Checksum differs, read:%d calculate:%d\n",lnr,chksum,sum);
  173.             return(errormsg);
  174.         }
  175.         
  176.     }
  177.  
  178.     if(feof(fp))
  179.     {
  180.         sprintf(errormsg,"Line:%d No END Status found",lnr);
  181.         return(errormsg);
  182.     }
  183.  
  184.     sprintf(errormsg,"Line:%d  Error reading File",lnr);
  185.     return(errormsg);
  186. }
  187.  
  188. char *itoh(unsigned char byte,char *pbuf)
  189. {
  190.     /* Convert 'byte' in ASCII Hex Notation.
  191.      * 
  192.      * Write ASCII Hex Code (2 Chars) at '*pbuf'.
  193.      *
  194.      * RC: pbuf+2    (points to next free char 
  195.      */  
  196.  
  197.     unsigned char     low,    /* low 4 Bits of 'byte' */
  198.             high;    /* high 4 Bits of 'byte' (normalized) */
  199.  
  200.     low = 0x0F&byte;
  201. /*    high = (unsigned char)(((int)(0xF0&byte))>>4);*/
  202.     high = (unsigned char)(0xF0&byte)>>4;
  203.  
  204.     /* convert Integer to ASCII Hex */
  205.     *pbuf++= (high<=9) ? high+'0' : (high-0x0A)+'A';
  206.     *pbuf++= (low<=9) ? low+'0' : (low-0x0A)+'A';
  207.  
  208.     return(pbuf);
  209. }
  210.  
  211. char *writeintelhex(FILE *fp,unsigned char *buffer,int offset,int length)
  212. {
  213.     /* Write a file in 'intelhex'-Format. 
  214.      * Code the binary data:
  215.      *  Determine Address, calculate checksum, write intelhex line.
  216.      *
  217.      * RC: NULL if all went fine, else
  218.      *     Pointer to an error Message
  219.      */
  220.  
  221.     char line[BUFSIZ],    /* ASCII Buffer for writing line */
  222.          *pos;            /* used for filling intelhex line */
  223.     static char errormsg[256];    /* buffer for Error Message */
  224.     int ndata,            /* number of Databytes */
  225.         data,            /* one databyte */
  226.         address,        /* address for data */
  227.         status,            /* status of intelhex line */
  228.         chksum,            /* checksum of intelhex line */
  229.         lnr=0;            /* linenumber */
  230.  
  231.  
  232.     address=offset;        /* set logically startaddress */
  233.     status=0;            /* set status */
  234.     line[IH_COLON]=':'; /* set Start Marker */
  235.     
  236.     
  237.     while(length)
  238.     {
  239.         lnr++;        /* linenumber counting */
  240.  
  241.             /* write maximal IH_MAXDATA to one intelhex line */
  242.         ndata=MIN(IH_MAXDATA,length);
  243.  
  244.             /* remaining data */
  245.         length-=ndata;
  246.  
  247.             /* build first part of checksum */
  248.         chksum = ndata + (0xFF&(address>>8)) + (0xFF&address) + status;
  249.         
  250.         pos = &line[1]; /* points to second byte of line */
  251.  
  252.         pos = itoh((unsigned char)ndata,pos);                     /* Write data counter */
  253.         pos = itoh((unsigned char)(address>>8),pos);  /* Write High Byte Address */
  254.         pos = itoh((unsigned char)(0xFF&address),pos); /* Write Low Byte Address */
  255.         pos = itoh((unsigned char)status,pos);                 /* Write status */
  256.  
  257.             /* calculate address for next line */
  258.         address+=ndata;
  259.  
  260.         while(ndata--)
  261.         {
  262.             data=*buffer;        
  263.             buffer++;        
  264.             chksum+=data;                        /* adding for chksum */
  265.  
  266.             pos = itoh((unsigned char)data,pos);            /* Write databyte */
  267.         }
  268.  
  269.         chksum=0xFF&(0x100-(0xFF&chksum));
  270.         pos = itoh(chksum,pos);                    /* Write chksum */
  271.         *pos++ = '\n';                            /* Close String */
  272.         *pos = '\0';                            /* Close String */
  273.  
  274.         if(fputs(line,fp)<0)
  275.         {
  276.             sprintf(errormsg,"Line:%d Can't write line",lnr);
  277.             return(errormsg);
  278.         }
  279.     }
  280.     fputs(":00000001FF\n",fp);
  281.  
  282.     return(NULL);
  283.  
  284. }
  285.