blob: 0a11fd203f6753ee7804e603f79a4f97bd13ba37 [file] [log] [blame]
#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;
}