Interfacing to Files on the Host

In embedded systems programming, you frequently need to perform various file format conversions. For example, you might need a binary to S-record converter ( bin2srec on the CD); you may need a tool that converts a binary file into a C-array so that the array can be included in a C file ( bin2array on the CD).

Not too long ago I was booting a board with a 64-bit CPU. There were two boot devices, and the target was configured such that the CPU would fetch four bytes from the first device, then four bytes from the second device. This requirement meant that I had to take the binary image that I created from the ELF-formatted output of the linker and chop it into two separate files, where each file contained alternating 4-byte chunks of the original binary. To automate this partitioning, I wrote a host-based tool I call chunker . I might never use this tool again, but it sure did the trick when I needed it. The chunker tool was very simple to write, but, if I hadnt had the ability to develop for the host as well as the target (or had an equivalent tool), I would have been in trouble! Listing A.1 and Listing A.2 show the bulk of the chunker code, demonstrating the interface to a binary file.

Listing A.1: Chunker.
image from book
 main(int argc,char *argv[]) {     char    *ofile, *buf1, *buf2, *bp1, *bp2, *fname, ofilename[128];     struct  stat    stat;     int     ifd, ofd, i, j, opt, size1, size2;     debug = 0;     ofile = "chunk";     while((opt=getopt(argc,argv,"do:V")) != EOF) {         switch(opt) {         case 'd':             debug = 1;             break;         case 'o':             ofile = optarg;             break;         case 'V':             showVersion();             break;         default:             exit(1);         }     }     if (argc != optind +1)         usage(0);     fname = argv[optind];     /* Open a binary file, determine its size and      * allocate two buffers of that size to contain the "chunks".      * This is an over allocation, but who cares!      */     ifd = open(fname,O_RDONLY  O_BINARY);     if (ifd == -1) {         perror(fname);         exit(1);     }     fstat(ifd,&stat);     if (stat.st_size % 4) {         fprintf(stderr,"Input file must be mod 4\n");         exit(1);     }     buf1 = bp1 = malloc(stat.st_size);     buf2 = bp2 = malloc(stat.st_size);     if ((!buf1)  (!buf2)) {         perror("malloc");         exit(1);     } 
image from book
 

The chunker program begins with some command line processing using getopt() and the incoming argument list. The filename of the file to be processed is the first argument after the list of options processed by getopt() . The code stores the filename locally and then opens the file after determining the size of the file (by calling fstat ). The code allocates two buffers where it will collect the chunks of data from the input file (see Listing A.2).

Listing A.2: Filling the Buffers.
image from book
 /* Now read in 4 bytes at a time from the binary file and      * feed 4 bytes to one buffer then 4 bytes to the other buffer.      * Keep this up till the input file is exhausted...      */     size1 = size2 = 0;     while(1) {         if (read(ifd,bp1,4) != 4)             break;         bp1 += 4;         size1 += 4;         if (read(ifd,bp2,4) != 4)             break;         bp2 += 4;         size2 += 4;     }     /* Create 2 new files that represent the two "chunks" of the       * original file:      */     sprintf(ofilename,"%s1.bin",ofile);     ofd = open(ofilename,O_WRONLYO_BINARYO_CREATO_TRUNC,0777);     if (ofd < 0) {         fprintf(stderr,"Can't open %s\n",ofilename);         exit(1);     }     if (write(ofd,buf1,size1) != size1) {         fprintf(stderr,"Can't write file %s\n",ofilename);         exit(1);     }     close (ofd);     sprintf(ofilename,"%s2.bin",ofile);     ofd = open(ofilename,O_WRONLYO_BINARYO_CREATO_TRUNC,0777);     if (ofd < 0) {         fprintf(stderr,"Can't open %s\n",ofilename);         exit(1);     }     if (write(ofd,buf2,size2) != size2) {         fprintf(stderr,"Can't write file %s\n",ofilename);         exit(1);     }     /* Close, free and exit.      */     close (ofd);     close (ifd);     free(buf1);     free(buf2);     printf("Files %s1.bin (%d) & %s2.bin (%d) created\n",ofile,size1,size2);     exit(0); } 
image from book
 

The main loop in Listing A.2 uses read() to retrieve four bytes at a time, placing each 4-byte chunk alternately into the two different buffers. After the buffers have been loaded, two new files are created, and the data from the buffers is stored into those files. Finally, the files and buffers are released, and a status message is printed, indicating that the two chunk files have been created from the single input file.



Embedded Systems Firmware Demystified
Embedded Systems Firmware Demystified (With CD-ROM)
ISBN: 1578200997
EAN: 2147483647
Year: 2002
Pages: 118
Authors: Ed Sutter

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net