home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / system / linux_bo / netboot.zoo / hexbin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-21  |  8.6 KB  |  423 lines

  1. /*\
  2.  * INTEL hex <-> binary file Converter.
  3.  * 
  4.  * T.Bohning 
  5.  * 11851 NW 37 Place
  6.  * Sunrise, FL 33323
  7.  * 
  8.  * Compiler: Microsoft C 5.1
  9.  * 2/20/89
  10.  * 
  11.  * Compuserve User ID: [71036,1066]
  12.  * GEnie address: T.BOHNING
  13.  * 
  14. INTEL hex description:
  15. 8 bit codes are split into two nibbles, and each nibble stored as 
  16. a hex ascii digit '0' through 'F'.
  17. Each line of the intel hex file is a record, with the following format:
  18.  
  19.      :NNAAAATTD1D2D3D4....DnCC
  20.  
  21. The colon means start of record, NN is the number of data bytes in the 
  22. record given as two hex digits.  AAAA is the starting load address of
  23. the record.  
  24. *
  25. TT is a record type, 00 for data records.  D1,D2...Dn are the hex ASCII 
  26. representations of the data bytes.  CC is a hex ASCII checksum, chosen
  27. such that the sum of all preceding byte values in the record 
  28. (not just the data bytes) modulo 256 = 0.
  29. *
  30. The end of the hex file is marked by a record with a data length of 0
  31. and a record type of 1.
  32. *
  33. * This description is for "old" INTEL hex, which could only support
  34. * 64K loads.  "Extended" INTEL hex was developed when the 8086 came
  35. * along.
  36. \*/
  37.  
  38. #include <stdio.h>
  39. #include <string.h>
  40. #include <conio.h>
  41. #include <stdlib.h>
  42.  
  43. enum bool { FALSE, TRUE };
  44.  
  45. /*\
  46.  * function prototypes
  47. \*/
  48. void    genbin( FILE *inptr, FILE *outptr);
  49. void    genhex( FILE *inptr, FILE *outptr);
  50. int    getyn( char *msg );
  51. char    get_hexbyte( char *cptr );
  52. int    hexext( char *filename );
  53. void     main( int argc, char *argv[] );
  54. char *    put_hexbyte( char *cptr, char val );
  55. void    read_exit( void );
  56. void     usexit( void );
  57. void     write_exit( void );
  58.  
  59. /* file i/o buffer size (2 allocated)
  60. */
  61. #define    FILE_BUFSIZE    0x6000
  62.  
  63. void
  64. main( argc, argv)
  65. int argc;
  66. char *argv[]; {
  67.     FILE *inptr, *outptr;
  68.     int tohex;        /* TRUE -> binary to HEX */
  69.     char *inbuf, *outbuf;    /* file I/O buffers */
  70.     
  71.     /*\
  72.       * Check args.
  73.     \*/
  74.     if (argc != 3) {
  75.         usexit();
  76.     }    
  77.     
  78.     /*\
  79.      * Open files, check for .HEX extension, establish 
  80.      * conversion direction.
  81.     \*/
  82.     tohex = hexext(argv[2]) ? TRUE : (hexext(argv[1]) ? FALSE : usexit());
  83.  
  84.     /*\
  85.      * Open the files.
  86.     \*/
  87.     if ( (inptr = fopen( argv[1], tohex ? "rb" : "rt" )) == NULL ) {
  88.         printf("can't open %s for reading", argv[1]);
  89.     }
  90.  
  91.     /*\
  92.      * Test for output file existence first.
  93.     \*/
  94.     if ( (outptr = fopen( argv[2], "rb" )) != NULL ) {
  95.  
  96.         if ( getyn("Output file exists, overwrite (Y/N)? ") == 'N' ) {
  97.             usexit();
  98.         } else {
  99.             fclose( outptr );
  100.         }
  101.     }
  102.     if ( (outptr = fopen( argv[2], tohex ? "wt" : "wb" )) == NULL ) {
  103.         printf("can't open %s for writing", argv[1]);
  104.     }
  105.  
  106.     /*\
  107.      * Allocate and set up file I/O buffers
  108.     \*/
  109.     if (     ( (inbuf = malloc( FILE_BUFSIZE)) == NULL) 
  110.         ||
  111.         ( (outbuf = malloc( FILE_BUFSIZE)) == NULL)  ) {
  112.  
  113.         puts("Can't allocate file I/O buffers");
  114.         exit(1);
  115.     }
  116.     if (    setvbuf( inptr, inbuf, _IOFBF, FILE_BUFSIZE )
  117.         ||
  118.         setvbuf( outptr, outbuf, _IOFBF, FILE_BUFSIZE ) ) {
  119.  
  120.         puts("Error setting file buffers");
  121.         exit(1);
  122.     }
  123.  
  124.      printf("Converting: %s -> %s\n", argv[1], argv[2] );
  125.     if (tohex) {
  126.         genhex(inptr, outptr);
  127.     } else {
  128.         genbin(inptr, outptr);
  129.     }
  130. }
  131. /*\
  132.  * Print msg, Get y or n from user.  
  133.  * Return upper case variant.
  134. \*/
  135. int 
  136. getyn( msg )
  137. char *msg; {
  138.     int c;
  139.  
  140.     puts( msg );
  141.  
  142.     while( 1) {
  143.         c = getche();
  144.         puts("");
  145.  
  146.         if ( (c == 'y') || (c == 'Y') ) {
  147.             return( 'Y' );
  148.         }
  149.         if ( (c == 'n') || (c == 'N') ) {
  150.             return( 'N' );
  151.         }
  152.     }
  153. }
  154. /*\
  155.  * Get a byte from hex ascii string, return the value.
  156. \*/
  157. char 
  158. get_hexbyte( cptr ) 
  159. char *cptr; {
  160.     char retval;
  161.     char nbl;
  162.     int shift;
  163.     
  164.     retval = 0;
  165.  
  166.     for( shift = 4; shift >= 0; shift -= 4 ) {
  167.     
  168.         if ((*cptr >= '0') && (*cptr <= '9')) {
  169.             nbl = *cptr - '0';
  170.         } else {
  171.             if ((*cptr >= 'A') && (*cptr <= 'F')) {
  172.                 nbl = *cptr - 'A' + 10;        
  173.             } else {
  174.                 puts("Hex file contains invalid character");
  175.                 exit(1);
  176.             }
  177.         }
  178.         ++cptr;
  179.             
  180.         retval |= (nbl << shift);
  181.     }
  182.     return( retval );
  183. }
  184. /*\
  185.  *   Convert INTEL hex at infile to binary at outfile.
  186. \*/
  187. void
  188. genbin( inptr, outptr) 
  189. FILE *inptr, *outptr; {
  190.     char linebuf[256];    /* input buffer */
  191.     char c;
  192.  
  193.     char *bufptr;
  194.     int numbytes;
  195.     char chksum;
  196.  
  197.     int i;
  198.     
  199.     int linenum = 1;
  200.  
  201.     printf("Processing hex file line number: %5d", linenum );
  202.  
  203.     /*\
  204.      * process input file 1 line at a time.
  205.     \*/
  206.     while( fgets( linebuf, sizeof(linebuf)-1, inptr) != NULL ) {
  207.  
  208.         chksum = 0;
  209.  
  210.         bufptr = linebuf;
  211.  
  212.         if ( *bufptr++ != ':' ) {
  213.             printf("Intel hex format error in line %d\n", linenum);
  214.             exit(1);
  215.         }        
  216.  
  217.         /*\
  218.          * Get number of data bytes and add into checksum.
  219.         \*/
  220.         numbytes = get_hexbyte( bufptr );
  221.         chksum += (char)numbytes;
  222.         bufptr += 2;
  223.  
  224.         /*\
  225.          * Add load address and record type into checksum.
  226.         \*/
  227.         for( i = 0; i < 3; ++i ) {
  228.             chksum += get_hexbyte( bufptr );
  229.             bufptr += 2;
  230.         }
  231.         
  232.         /*\
  233.          * Write the binary data.
  234.         \*/
  235.         for( i = 0; i < numbytes; ++i ) {
  236.             c = get_hexbyte(bufptr);
  237.             bufptr += 2;
  238.  
  239.             putc( c, outptr);
  240.             chksum += c;
  241.         }
  242.  
  243.         if ( ferror( outptr ) ) {
  244.             write_exit();
  245.         }
  246.  
  247.         /*\
  248.          * Sum in checksum byte and check the sum.
  249.         \*/
  250.         chksum += get_hexbyte(bufptr);
  251.         if (chksum != 0) {
  252.             printf("Checksum error in line %d\n", linenum);
  253.             exit(1);
  254.         }
  255.  
  256.         if( numbytes == 0 ) {
  257.             puts("");
  258.             exit(0);    /* end of hex file */
  259.         }                                
  260.  
  261.         ++linenum;
  262.         if ( (linenum & 0x3F) == 0 ) {
  263.             printf("\b\b\b\b\b%5d", linenum);
  264.         }
  265.     }        
  266.  
  267.     if (ferror(inptr)) {
  268.         read_exit();
  269.     }
  270.  
  271.     puts("\nWarning: Terminator record not found, hex file probably truncated.");
  272.     exit(1);
  273. }
  274. /*\
  275.  *   Convert infile to INTEL hex at outfile.
  276. \*/
  277. void
  278. genhex( inptr, outptr) 
  279. FILE *inptr, *outptr; {
  280.  
  281.     #define DATA_BYTES    0x10    /* data bytes per record */
  282.  
  283.     /* hex file line buffer, one space for a NULL, 
  284.     * one space for \n
  285.     *
  286.                        :  len addr 00 cks \n null */
  287.     char     hexline[ DATA_BYTES*2 + 1 + 2 + 4 + 2 + 2 + 1 + 1 ];    
  288.     char     data_buf[ DATA_BYTES ];
  289.  
  290.     unsigned int load_addr = 0;
  291.     int numbytes, i;
  292.  
  293.     unsigned char chksum;
  294.     unsigned char *bufptr;
  295.     
  296.     unsigned int linenum = 1;
  297.  
  298.     hexline[0] = ':';    /* colon always starts a record */
  299.     hexline[7] = '0';    /* type for data records is */
  300.     hexline[8] = '0';    /* ... 00 */
  301.  
  302.     printf("Processing hex file line number: %5d", linenum );
  303.  
  304.     /*\
  305.      * Build a line 
  306.     \*/
  307.     while(
  308.        (numbytes = fread( data_buf, sizeof(char), DATA_BYTES, inptr)) != 0
  309.          )  {
  310.         
  311.         /*\
  312.         *  Write out all the bytes as hex,
  313.         *   updating chechksum as we go.
  314.         \*/
  315.         bufptr = &hexline[1];    /* skip the colon */
  316.  
  317.         chksum = (char)numbytes;
  318.         bufptr = put_hexbyte( bufptr, (char)numbytes );
  319.  
  320.         chksum += (char)(load_addr >> 8);
  321.         chksum += (char)load_addr;
  322.  
  323.         bufptr = put_hexbyte( bufptr, (char)(load_addr >> 8) );
  324.         bufptr = put_hexbyte( bufptr, (char)load_addr );
  325.  
  326.         bufptr += 2;    /* skip over data record type */
  327.  
  328.         /*\
  329.          * Write out actual data bytes.
  330.         \*/
  331.         for(i = 0; i < numbytes; i++) {
  332.             chksum += data_buf[i];
  333.             bufptr = put_hexbyte( bufptr, data_buf[i] );
  334.             }
  335.  
  336.         chksum = ~chksum+1;
  337.         bufptr = put_hexbyte( bufptr, chksum );
  338.  
  339.         *bufptr++ = '\n';
  340.         *bufptr = NULL;
  341.  
  342.         /*\
  343.          * write this line of the hex file
  344.         \*/
  345.         fputs( hexline, outptr );
  346.  
  347.         if ( ferror(outptr) ) {
  348.             write_exit();
  349.         }
  350.  
  351.         load_addr += numbytes;
  352.  
  353.         ++linenum;
  354.         if ( (linenum & 0x3F) == 0 ) {
  355.             printf("\b\b\b\b\b%5d", linenum);
  356.         }
  357.     }
  358.     puts("");
  359.  
  360.     if ( ferror(inptr) ) {
  361.         read_exit();
  362.     }
  363.  
  364.     fputs(":00000001FF", outptr);   /* Standard termination record */
  365. }
  366. /*\
  367.  *  Try to find .HEX extension on a filename.
  368. \*/
  369. hexext( cptr )
  370. char *cptr; {
  371.  
  372.     return( !strcmpi( cptr + strlen(cptr) - 4, ".hex") );
  373. }
  374. /*\
  375.  * Put a byte as hex ascii, return pointer to next location.
  376. \*/
  377. char *
  378. put_hexbyte(cptr, val) 
  379. char *cptr; 
  380. char val; {
  381.     static char hextbl[16] = {
  382.         '0', '1', '2', '3', '4', '5', '6', '7', 
  383.         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  384.     };
  385.     
  386.     *cptr++ = hextbl[ ((val >> 4) & 0x0F) ];
  387.  
  388.     *cptr++ = hextbl[ val & 0x0F ];
  389.  
  390.     return(cptr);    
  391. }
  392. /*\
  393.  * read error on input file
  394. \*/
  395. void
  396. read_exit() {
  397.     puts("Error on input file read");
  398.     exit(1);
  399. }
  400. /*\
  401.  * Show usage and die.
  402. \*/
  403. void
  404. usexit() {
  405.     puts("\nINTEL hex <-> binary file converter");
  406.     puts("\nUsage: HEXBIN infile outfile" );
  407.     puts("\nEither infile or outfile must have .HEX extension");
  408.  
  409. puts("\nIf infile  has .HEX extension, HEX to binary conversion is performed");
  410. puts("If outfile has .HEX extension, binary to HEX conversion is performed");
  411.  
  412.     exit(1);
  413. }
  414. /*\
  415.  * write error on output file
  416. \*/
  417. void
  418. write_exit() {
  419.     puts("Error on output file write");
  420.     exit(1);
  421. }
  422. /************************ EOF *************************/
  423.