123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #define IMG_SIZE 0x3e0000
- #define KERNEL_START 0x020000
- #define KERNEL_SIZE 0x0b0000
- #define ROOTFS_START 0x0d0000
- #define ROOTFS_SIZE 0x30ffb2
- char* app_name;
- void print_usage(void)
- {
- fprintf(stderr, "usage: dgfirmware [<opts>] <img>\n");
- fprintf(stderr, " <img> firmware image filename\n");
- fprintf(stderr, " <opts> -h print this message\n");
- fprintf(stderr, " -f fix the checksum\n");
- fprintf(stderr, " -x <file> extract the rootfs file to <file>\n");
- fprintf(stderr, " -xk <file> extract the kernel to <file>\n");
- fprintf(stderr, " -m <file> merge in rootfs fil\e from <file>\n");
- fprintf(stderr, " -k <file> merge in kernel from <file>\n");
- fprintf(stderr, " -w <file> write back the modified firmware\n");
- }
- unsigned char* read_img(const char *fname)
- {
- FILE *fp;
- int size;
- unsigned char *img;
- fp = fopen(fname, "rb");
- if (fp == NULL) {
- perror(app_name);
- exit(-1);
- }
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
-
- if (size != IMG_SIZE) {
- fprintf(stderr, "%s: image file has wrong size\n", app_name);
- fclose(fp);
- exit(-1);
- }
- rewind(fp);
- img = malloc(IMG_SIZE);
- if (img == NULL) {
- perror(app_name);
- fclose(fp);
- exit(-1);
- }
- if (fread(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
- fprintf(stderr, "%s: can't read image file\n", app_name);
- fclose(fp);
- exit(-1);
- }
- fclose(fp);
- return img;
- }
- void write_img(unsigned char* img, const char *fname)
- {
- FILE *fp;
- fp = fopen(fname, "wb");
- if (fp == NULL) {
- perror(app_name);
- exit(-1);
- }
- if (fwrite(img, 1, IMG_SIZE, fp) != IMG_SIZE) {
- fprintf(stderr, "%s: can't write image file\n", app_name);
- fclose(fp);
- exit(-1);
- }
- }
- void write_rootfs(unsigned char* img, const char *fname)
- {
- FILE *fp;
- fp = fopen(fname, "wb");
- if (fp == NULL) {
- perror(app_name);
- exit(-1);
- }
-
- if (fwrite(img+ROOTFS_START, 1, ROOTFS_SIZE, fp) != ROOTFS_SIZE) {
- fprintf(stderr, "%s: can't write image file\n", app_name);
- fclose(fp);
- exit(-1);
- }
- }
- void write_kernel(unsigned char* img, const char *fname)
- {
- FILE *fp;
- fp = fopen(fname, "wb");
- if (fp == NULL) {
- perror(app_name);
- exit(-1);
- }
-
- if (fwrite(img+KERNEL_START, 1, KERNEL_SIZE, fp) != KERNEL_SIZE) {
- fprintf(stderr, "%s: can't write kernel file\n", app_name);
- fclose(fp);
- exit(-1);
- }
- }
- unsigned char* read_rootfs(unsigned char* img, const char *fname)
- {
- FILE *fp;
- int size;
- int i;
- for (i=ROOTFS_START; i<ROOTFS_START+ROOTFS_SIZE; i++)
- img[i] = 0xff;
- fp = fopen(fname, "rb");
- if (fp == NULL) {
- perror(app_name);
- exit(-1);
- }
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
-
- if (size > ROOTFS_SIZE) {
- fprintf(stderr, "%s: rootfs image file is too big\n", app_name);
- fclose(fp);
- exit(-1);
- }
- rewind(fp);
- if (fread(img+ROOTFS_START, 1, size, fp) != size) {
- fprintf(stderr, "%s: can't read rootfs image file\n", app_name);
- fclose(fp);
- exit(-1);
- }
- fclose(fp);
- return img;
- }
- unsigned char* read_kernel(unsigned char* img, const char *fname)
- {
- FILE *fp;
- int size;
- int i;
- for (i=KERNEL_START; i<KERNEL_START+KERNEL_SIZE; i++)
- img[i] = 0xff;
- fp = fopen(fname, "rb");
- if (fp == NULL) {
- perror(app_name);
- exit(-1);
- }
- fseek(fp, 0, SEEK_END);
- size = ftell(fp);
-
- if (size > KERNEL_SIZE) {
- fprintf(stderr, "%s: kernel binary file is too big\n", app_name);
- fclose(fp);
- exit(-1);
- }
- rewind(fp);
- if (fread(img+KERNEL_START, 1, size, fp) != size) {
- fprintf(stderr, "%s: can't read kernel file\n", app_name);
- fclose(fp);
- exit(-1);
- }
- fclose(fp);
- return img;
- }
- int get_checksum(unsigned char* img)
- {
- short unsigned s;
- s = img[0x3dfffc] + (img[0x3dfffd]<<8);
- return s;
- }
- void set_checksum(unsigned char*img, unsigned short sum)
- {
- img[0x3dfffc] = sum & 0xff;
- img[0x3dfffd] = (sum>>8) & 0xff;
- }
- int compute_checksum(unsigned char* img)
- {
- int i;
- short s=0;
- for (i=0; i<0x3dfffc; i++)
- s += img[i];
- return s;
- }
- int main(int argc, char* argv[])
- {
- char *img_fname = NULL;
- char *rootfs_fname = NULL;
- char *kernel_fname = NULL;
- char *new_img_fname = NULL;
- int do_fix_checksum = 0;
- int do_write = 0;
- int do_write_rootfs = 0;
- int do_read_rootfs = 0;
- int do_write_kernel = 0;
- int do_read_kernel = 0;
- int i;
- unsigned char *img;
- unsigned short img_checksum;
- unsigned short real_checksum;
- app_name = argv[0];
- for (i=1; i<argc; i++) {
- if (!strcmp(argv[i], "-h")) {
- print_usage();
- return 0;
- }
- else if (!strcmp(argv[i], "-f")) {
- do_fix_checksum = 1;
- }
- else if (!strcmp(argv[i], "-x")) {
- if (i+1 >= argc) {
- fprintf(stderr, "%s: missing argument\n", app_name);
- return -1;
- }
- do_write_rootfs = 1;
- rootfs_fname = argv[i+1];
- i++;
- }
- else if (!strcmp(argv[i], "-xk")) {
- if (i+1 >= argc) {
- fprintf(stderr, "%s: missing argument\n", app_name);
- return -1;
- }
- do_write_kernel = 1;
- kernel_fname = argv[i+1];
- i++;
- }
- else if (!strcmp(argv[i], "-m")) {
- if (i+1 >= argc) {
- fprintf(stderr, "%s: missing argument\n", app_name);
- return -1;
- }
- do_read_rootfs = 1;
- rootfs_fname = argv[i+1];
- i++;
- }
- else if (!strcmp(argv[i], "-k")) {
- if (i+1 >= argc) {
- fprintf(stderr, "%s: missing argument\n", app_name);
- return -1;
- }
- do_read_kernel = 1;
- kernel_fname = argv[i+1];
- i++;
- }
- else if (!strcmp(argv[i], "-w")) {
- if (i+1 >= argc) {
- fprintf(stderr, "%s: missing argument\n", app_name);
- return -1;
- }
- do_write = 1;
- new_img_fname = argv[i+1];
- i++;
- }
- else if (img_fname != 0) {
- fprintf(stderr, "%s: too many arguments\n", app_name);
- return -1;
- }
- else {
- img_fname = argv[i];
- }
- }
- if (img_fname == NULL) {
- fprintf(stderr, "%s: missing argument\n", app_name);
- return -1;
- }
- if ((do_read_rootfs && do_write_rootfs) ||
- (do_read_kernel && do_write_kernel)) {
- fprintf(stderr, "%s: conflictuous options\n", app_name);
- return -1;
- }
- printf ("** Read firmware file\n");
- img = read_img(img_fname);
- printf ("Firmware product: %s\n", img+0x3dffbd);
- printf ("Firmware version: 1.%02d.%02d\n", (img[0x3dffeb] & 0x7f), img[0x3dffec]);
- if (do_write_rootfs) {
- printf ("** Write rootfs file\n");
- write_rootfs(img, rootfs_fname);
- }
- if (do_write_kernel) {
- printf ("** Write kernel file\n");
- write_kernel(img, kernel_fname);
- }
- if (do_read_rootfs) {
- printf ("** Read rootfs file\n");
- read_rootfs(img, rootfs_fname);
- do_fix_checksum = 1;
- }
- if (do_read_kernel) {
- printf ("** Read kernel file\n");
- read_kernel(img, kernel_fname);
- do_fix_checksum = 1;
- }
- img_checksum = get_checksum(img);
- real_checksum = compute_checksum(img);
-
- printf ("image checksum = %04x\n", img_checksum);
- printf ("real checksum = %04x\n", real_checksum);
- if (do_fix_checksum) {
- if (img_checksum != real_checksum) {
- printf ("** Bad Checksum, fix it\n");
- set_checksum(img, real_checksum);
- }
- else {
- printf ("** Checksum is correct, good\n");
- }
- }
- if (do_write) {
- printf ("** Write image file\n");
- write_img(img, new_img_fname);
- }
- free(img);
- return 0;
- }
|