#define PROGRAM_NAME "doc_loadbios" #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> #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; }