dgfirmware.c 7.3 KB

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