151 lines
3.2 KiB
C
151 lines
3.2 KiB
C
|
#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;
|
||
|
}
|