summaryrefslogtreecommitdiff
path: root/doc_loadbios.c
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>2006-04-11 19:09:16 -0400
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>2006-04-11 19:09:16 -0400
commit72212c137c574b564723327af751c4054c7cfca6 (patch)
tree13be2da9d4be695002d6ea9c396660c986e5fa5c /doc_loadbios.c
Initial commit
Diffstat (limited to 'doc_loadbios.c')
-rw-r--r--doc_loadbios.c149
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;
+}