diff options
author | David Woodhouse <dwmw2@shinybook.infradead.org> | 2006-04-11 19:09:16 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@shinybook.infradead.org> | 2006-04-11 19:09:16 -0400 |
commit | 72212c137c574b564723327af751c4054c7cfca6 (patch) | |
tree | 13be2da9d4be695002d6ea9c396660c986e5fa5c /doc_loadbios.c |
Initial commit
Diffstat (limited to 'doc_loadbios.c')
-rw-r--r-- | doc_loadbios.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/doc_loadbios.c b/doc_loadbios.c new file mode 100644 index 0000000..f7ba8fa --- /dev/null +++ b/doc_loadbios.c @@ -0,0 +1,149 @@ +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <time.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <sys/mount.h> + +/* $Id: doc_loadbios.c,v 1.9 2005/11/07 11:15:10 gleixner Exp $ */ +#include <mtd/mtd-user.h> + +unsigned char databuf[512]; + +int main(int argc,char **argv) +{ + mtd_info_t meminfo; + int ifd,ofd; + struct stat statbuf; + erase_info_t erase; + unsigned long retlen, ofs, iplsize, ipltailsize; + unsigned char *iplbuf; + iplbuf = NULL; + + if (argc < 3) { + fprintf(stderr,"You must specify a device," + " the source firmware file and the offset\n"); + return 1; + } + + // Open and size the device + if ((ofd = open(argv[1],O_RDWR)) < 0) { + perror("Open flash device"); + return 1; + } + + if ((ifd = open(argv[2], O_RDONLY)) < 0) { + perror("Open firmware file\n"); + close(ofd); + return 1; + } + + if (fstat(ifd, &statbuf) != 0) { + perror("Stat firmware file"); + goto error; + } + +#if 0 + if (statbuf.st_size > 65536) { + printf("Firmware too large (%ld bytes)\n",statbuf.st_size); + goto error; + } +#endif + + if (ioctl(ofd,MEMGETINFO,&meminfo) != 0) { + perror("ioctl(MEMGETINFO)"); + goto error; + } + + iplsize = (ipltailsize = 0); + if (argc >= 4) { + /* DoC Millennium has IPL in the first 1K of flash memory */ + /* You may want to specify the offset 1024 to store + the firmware next to IPL. */ + iplsize = strtoul(argv[3], NULL, 0); + ipltailsize = iplsize % meminfo.erasesize; + } + + if (lseek(ofd, iplsize - ipltailsize, SEEK_SET) < 0) { + perror("lseek"); + goto error; + } + + if (ipltailsize) { + iplbuf = malloc(ipltailsize); + if (iplbuf == NULL) { + fprintf(stderr, "Not enough memory for IPL tail buffer of" + " %lu bytes\n", (unsigned long) ipltailsize); + goto error; + } + printf("Reading IPL%s area of length %lu at offset %lu\n", + (iplsize - ipltailsize) ? " tail" : "", + (long unsigned) ipltailsize, + (long unsigned) (iplsize - ipltailsize)); + if (read(ofd, iplbuf, ipltailsize) != ipltailsize) { + perror("read"); + goto error; + } + } + + erase.length = meminfo.erasesize; + + for (ofs = iplsize - ipltailsize ; + ofs < iplsize + statbuf.st_size ; + ofs += meminfo.erasesize) { + erase.start = ofs; + printf("Performing Flash Erase of length %lu at offset %lu\n", + (long unsigned) erase.length, (long unsigned) erase.start); + + if (ioctl(ofd,MEMERASE,&erase) != 0) { + perror("ioctl(MEMERASE)"); + goto error; + } + } + + if (lseek(ofd, iplsize - ipltailsize, SEEK_SET) < 0) { + perror("lseek"); + goto error; + } + + if (ipltailsize) { + printf("Writing IPL%s area of length %lu at offset %lu\n", + (iplsize - ipltailsize) ? " tail" : "", + (long unsigned) ipltailsize, + (long unsigned) (iplsize - ipltailsize)); + if (write(ofd, iplbuf, ipltailsize) != ipltailsize) { + perror("write"); + goto error; + } + } + + printf("Writing the firmware of length %lu at %lu... ", + (unsigned long) statbuf.st_size, + (unsigned long) iplsize); + do { + retlen = read(ifd, databuf, 512); + if (retlen < 512) + memset(databuf+retlen, 0xff, 512-retlen); + if (write(ofd, databuf, 512) != 512) { + perror("write"); + goto error; + } + } while (retlen == 512); + printf("Done.\n"); + + if (iplbuf != NULL) + free(iplbuf); + close(ifd); + close(ofd); + return 0; + +error: + if (iplbuf != NULL) + free(iplbuf); + close(ifd); + close(ofd); + return 1; +} |