1#include <stdlib.h> 2#include <stdio.h> 3 4 5#define IMG_SIZE 0x3e0000 6 7#define KERNEL_START 0x020000 8#define KERNEL_SIZE 0x0b0000 9 10#define ROOTFS_START 0x0d0000 11#define ROOTFS_SIZE 0x30ffb2 12 13char* app_name; 14 15 16 17 18void print_usage(void) 19{ 20 fprintf(stderr, "usage: dgfirmware [<opts>] <img>\n"); 21 fprintf(stderr, " <img> firmware image filename\n"); 22 fprintf(stderr, " <opts> -h print this message\n"); 23 fprintf(stderr, " -f fix the checksum\n"); 24 fprintf(stderr, " -x <file> extract the rootfs file to <file>\n"); 25 fprintf(stderr, " -xk <file> extract the kernel to <file>\n"); 26 fprintf(stderr, " -m <file> merge in rootfs fil\e from <file>\n"); 27 fprintf(stderr, " -k <file> merge in kernel from <file>\n"); 28 fprintf(stderr, " -w <file> write back the modified firmware\n"); 29} 30 31 32unsigned char* read_img(const char *fname) 33{ 34 FILE *fp; 35 int size; 36 unsigned char *img; 37 38 fp = fopen(fname, "rb"); 39 if (fp == NULL) { 40 perror(app_name); 41 exit(-1); 42 } 43 44 fseek(fp, 0, SEEK_END); 45 size = ftell(fp); 46 47 if (size != IMG_SIZE) { 48 fprintf(stderr, "%s: image file has wrong size\n", app_name); 49 fclose(fp); 50 exit(-1); 51 } 52 53 rewind(fp); 54 55 img = malloc(IMG_SIZE); 56 if (img == NULL) { 57 perror(app_name); 58 fclose(fp); 59 exit(-1); 60 } 61 62 if (fread(img, 1, IMG_SIZE, fp) != IMG_SIZE) { 63 fprintf(stderr, "%s: can't read image file\n", app_name); 64 fclose(fp); 65 exit(-1); 66 } 67 68 fclose(fp); 69 return img; 70} 71 72 73void write_img(unsigned char* img, const char *fname) 74{ 75 FILE *fp; 76 77 fp = fopen(fname, "wb"); 78 if (fp == NULL) { 79 perror(app_name); 80 exit(-1); 81 } 82 83 if (fwrite(img, 1, IMG_SIZE, fp) != IMG_SIZE) { 84 fprintf(stderr, "%s: can't write image file\n", app_name); 85 fclose(fp); 86 exit(-1); 87 } 88} 89 90 91void write_rootfs(unsigned char* img, const char *fname) 92{ 93 FILE *fp; 94 95 fp = fopen(fname, "wb"); 96 if (fp == NULL) { 97 perror(app_name); 98 exit(-1); 99 } 100 101 if (fwrite(img+ROOTFS_START, 1, ROOTFS_SIZE, fp) != ROOTFS_SIZE) { 102 fprintf(stderr, "%s: can't write image file\n", app_name); 103 fclose(fp); 104 exit(-1); 105 } 106} 107 108 109void write_kernel(unsigned char* img, const char *fname) 110{ 111 FILE *fp; 112 113 fp = fopen(fname, "wb"); 114 if (fp == NULL) { 115 perror(app_name); 116 exit(-1); 117 } 118 119 if (fwrite(img+KERNEL_START, 1, KERNEL_SIZE, fp) != KERNEL_SIZE) { 120 fprintf(stderr, "%s: can't write kernel file\n", app_name); 121 fclose(fp); 122 exit(-1); 123 } 124} 125 126 127unsigned char* read_rootfs(unsigned char* img, const char *fname) 128{ 129 FILE *fp; 130 int size; 131 int i; 132 133 for (i=ROOTFS_START; i<ROOTFS_START+ROOTFS_SIZE; i++) 134 img[i] = 0xff; 135 136 fp = fopen(fname, "rb"); 137 if (fp == NULL) { 138 perror(app_name); 139 exit(-1); 140 } 141 142 fseek(fp, 0, SEEK_END); 143 size = ftell(fp); 144 145 if (size > ROOTFS_SIZE) { 146 fprintf(stderr, "%s: rootfs image file is too big\n", app_name); 147 fclose(fp); 148 exit(-1); 149 } 150 151 rewind(fp); 152 153 if (fread(img+ROOTFS_START, 1, size, fp) != size) { 154 fprintf(stderr, "%s: can't read rootfs image file\n", app_name); 155 fclose(fp); 156 exit(-1); 157 } 158 159 fclose(fp); 160 return img; 161} 162 163 164unsigned char* read_kernel(unsigned char* img, const char *fname) 165{ 166 FILE *fp; 167 int size; 168 int i; 169 170 for (i=KERNEL_START; i<KERNEL_START+KERNEL_SIZE; i++) 171 img[i] = 0xff; 172 173 fp = fopen(fname, "rb"); 174 if (fp == NULL) { 175 perror(app_name); 176 exit(-1); 177 } 178 179 fseek(fp, 0, SEEK_END); 180 size = ftell(fp); 181 182 if (size > KERNEL_SIZE) { 183 fprintf(stderr, "%s: kernel binary file is too big\n", app_name); 184 fclose(fp); 185 exit(-1); 186 } 187 188 rewind(fp); 189 190 if (fread(img+KERNEL_START, 1, size, fp) != size) { 191 fprintf(stderr, "%s: can't read kernel file\n", app_name); 192 fclose(fp); 193 exit(-1); 194 } 195 196 fclose(fp); 197 return img; 198} 199 200 201int get_checksum(unsigned char* img) 202{ 203 short unsigned s; 204 205 s = img[0x3dfffc] + (img[0x3dfffd]<<8); 206 207 return s; 208} 209 210 211void set_checksum(unsigned char*img, unsigned short sum) 212{ 213 img[0x3dfffc] = sum & 0xff; 214 img[0x3dfffd] = (sum>>8) & 0xff; 215} 216 217 218int compute_checksum(unsigned char* img) 219{ 220 int i; 221 short s=0; 222 223 for (i=0; i<0x3dfffc; i++) 224 s += img[i]; 225 226 return s; 227} 228 229 230int main(int argc, char* argv[]) 231{ 232 char *img_fname = NULL; 233 char *rootfs_fname = NULL; 234 char *kernel_fname = NULL; 235 char *new_img_fname = NULL; 236 237 int do_fix_checksum = 0; 238 int do_write = 0; 239 int do_write_rootfs = 0; 240 int do_read_rootfs = 0; 241 int do_write_kernel = 0; 242 int do_read_kernel = 0; 243 244 int i; 245 unsigned char *img; 246 unsigned short img_checksum; 247 unsigned short real_checksum; 248 249 app_name = argv[0]; 250 251 for (i=1; i<argc; i++) { 252 if (!strcmp(argv[i], "-h")) { 253 print_usage(); 254 return 0; 255 } 256 else if (!strcmp(argv[i], "-f")) { 257 do_fix_checksum = 1; 258 } 259 else if (!strcmp(argv[i], "-x")) { 260 if (i+1 >= argc) { 261 fprintf(stderr, "%s: missing argument\n", app_name); 262 return -1; 263 } 264 do_write_rootfs = 1; 265 rootfs_fname = argv[i+1]; 266 i++; 267 } 268 else if (!strcmp(argv[i], "-xk")) { 269 if (i+1 >= argc) { 270 fprintf(stderr, "%s: missing argument\n", app_name); 271 return -1; 272 } 273 do_write_kernel = 1; 274 kernel_fname = argv[i+1]; 275 i++; 276 } 277 else if (!strcmp(argv[i], "-m")) { 278 if (i+1 >= argc) { 279 fprintf(stderr, "%s: missing argument\n", app_name); 280 return -1; 281 } 282 do_read_rootfs = 1; 283 rootfs_fname = argv[i+1]; 284 i++; 285 } 286 else if (!strcmp(argv[i], "-k")) { 287 if (i+1 >= argc) { 288 fprintf(stderr, "%s: missing argument\n", app_name); 289 return -1; 290 } 291 do_read_kernel = 1; 292 kernel_fname = argv[i+1]; 293 i++; 294 } 295 else if (!strcmp(argv[i], "-w")) { 296 if (i+1 >= argc) { 297 fprintf(stderr, "%s: missing argument\n", app_name); 298 return -1; 299 } 300 do_write = 1; 301 new_img_fname = argv[i+1]; 302 i++; 303 } 304 else if (img_fname != 0) { 305 fprintf(stderr, "%s: too many arguments\n", app_name); 306 return -1; 307 } 308 else { 309 img_fname = argv[i]; 310 } 311 } 312 313 if (img_fname == NULL) { 314 fprintf(stderr, "%s: missing argument\n", app_name); 315 return -1; 316 } 317 318 if ((do_read_rootfs && do_write_rootfs) || 319 (do_read_kernel && do_write_kernel)) { 320 fprintf(stderr, "%s: conflictuous options\n", app_name); 321 return -1; 322 } 323 324 printf ("** Read firmware file\n"); 325 img = read_img(img_fname); 326 327 printf ("Firmware product: %s\n", img+0x3dffbd); 328 printf ("Firmware version: 1.%02d.%02d\n", (img[0x3dffeb] & 0x7f), img[0x3dffec]); 329 330 if (do_write_rootfs) { 331 printf ("** Write rootfs file\n"); 332 write_rootfs(img, rootfs_fname); 333 } 334 335 if (do_write_kernel) { 336 printf ("** Write kernel file\n"); 337 write_kernel(img, kernel_fname); 338 } 339 340 if (do_read_rootfs) { 341 printf ("** Read rootfs file\n"); 342 read_rootfs(img, rootfs_fname); 343 do_fix_checksum = 1; 344 } 345 346 if (do_read_kernel) { 347 printf ("** Read kernel file\n"); 348 read_kernel(img, kernel_fname); 349 do_fix_checksum = 1; 350 } 351 352 img_checksum = get_checksum(img); 353 real_checksum = compute_checksum(img); 354 355 printf ("image checksum = %04x\n", img_checksum); 356 printf ("real checksum = %04x\n", real_checksum); 357 358 if (do_fix_checksum) { 359 if (img_checksum != real_checksum) { 360 printf ("** Bad Checksum, fix it\n"); 361 set_checksum(img, real_checksum); 362 } 363 else { 364 printf ("** Checksum is correct, good\n"); 365 } 366 } 367 368 if (do_write) { 369 printf ("** Write image file\n"); 370 write_img(img, new_img_fname); 371 } 372 373 free(img); 374 return 0; 375} 376 377