dgfirmware.c 7.4 KB

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