makeamitbin.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*
  2. * makeamitbin - create firmware binaries for MGB100
  3. *
  4. * Copyright (C) 2007 Volker Weiss <dev@tintuc.de>
  5. * Christian Welzel <dev@welzel-online.ch>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. *
  21. */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. /* defaults: Level One WAP-0007 */
  26. static char *ascii1 = "DDC_RUS001";
  27. static char *ascii2 = "Queen";
  28. static struct hdrinfo {
  29. char *name;
  30. unsigned long unknown; /* can probably be any number, maybe version number */
  31. int topalign;
  32. unsigned int addr;
  33. unsigned int size;
  34. } hdrinfo[] = {
  35. { "bios", 0xc76be111, 1, 0x3fa000, 0x006000 }, /* BIOS */
  36. { "recovery", 0xc76be222, 0, 0x3f0000, 0x004000 }, /* Recovery Loader */
  37. { "linux", 0xc76bee9d, 0, 0x000000, 0x100000 }, /* Linux */
  38. { "ramdisk", 0xc76bee9d, 0, 0x100000, 0x280000 }, /* ramdisk */
  39. { "amitconfig", 0xc76bee8b, 0, 0x380000, 0x060000 }, /* AMIT config */
  40. { "redboot", 0x00000000, 1, 0x3d0000, 0x030000 }, /* Redboot 128kB image */
  41. { "redbootlow", 0, 0, 0x3e0000, 0x18000 }, /* Redboot 1. part */
  42. { "redboothigh", 0, 0, 0x3fa000, 0x6000 }, /* Redboot 2. part */
  43. { "linux3g", 0xcb5f06b5, 0, 0x000000, 0x100000 }, /* Linux */
  44. { "ramdisk3g", 0xcb5f06b5, 0, 0x100000, 0x280000 }, /* ramdisk */
  45. { NULL }
  46. };
  47. /*
  48. CHD2WLANU_R400b7
  49. 11e1 6bc7
  50. 22e2 6bc7
  51. 5dc3 47c8
  52. 5cc3 47c8
  53. 21c3 47c8
  54. */
  55. /*
  56. 20060106_DDC_WAP-0007_R400b4
  57. 11e1 6bc7
  58. 22e2 6bc7
  59. 9dee 6bc7
  60. 9dee 6bc7
  61. 8bee 6bc7
  62. */
  63. /*
  64. WMU-6000FS_R400b6
  65. 11e1 6bc7
  66. 22e2 6bc7
  67. 6d2d 0fc8
  68. 6c2d 0fc8
  69. 542d 0fc8
  70. */
  71. /*
  72. WAP-0007(R4.00b8)_2006-10-02
  73. 9979 5fc8
  74. 22e2 6bc7
  75. c46e cec8
  76. c36e cec8
  77. a76e cec8
  78. */
  79. #define HDRSIZE 80
  80. #define COPY_SHORT(d, o, v) d[o+0] = (unsigned char)((v) & 0xff); \
  81. d[o+1] = (unsigned char)(((v) >> 8) & 0xff)
  82. #define COPY_LONG(d, o, v) d[o+0] = (unsigned char)((v) & 0xff); \
  83. d[o+1] = (unsigned char)(((v) >> 8) & 0xff); \
  84. d[o+2] = (unsigned char)(((v) >> 16) & 0xff); \
  85. d[o+3] = (unsigned char)(((v) >> 24) & 0xff)
  86. #define READ_SHORT(d, o) ((unsigned short)(d[o+0]) + \
  87. (((unsigned short)(d[o+1])) << 8))
  88. /*
  89. 00..0d ASCII product ID
  90. 0e..0f checksum of payload
  91. 10..1b ASCII Queen
  92. 1c..1f AMIT BIOS: 11e1 6bc7, Recovery Tool: 22e2 6bc7
  93. Linux: 5dc3 47c8, ramdisk: 5cc3 47c8
  94. AMIT FS: 21c3 47c8 VERSION NUMBER??????
  95. 20..23 offset in flash aligned to segment boundary
  96. 24..27 length in flash aligned to segment boundary
  97. 28..2b offset in flash (payload)
  98. 2c..2f length (payload)
  99. 30..3f always 0
  100. 40..47 always 4248 0101 5000 0001 (last maybe .....0501)
  101. 48..4b same as 20..23
  102. 4c..4d always 0b00
  103. 4e..4f inverted checksum of header
  104. */
  105. unsigned short checksum(unsigned char *data, long size)
  106. {
  107. long n;
  108. unsigned short d, cs = 0;
  109. for (n = 0; n < size; n += 2)
  110. {
  111. d = READ_SHORT(data, n);
  112. cs += d;
  113. if (cs < d)
  114. cs++;
  115. }
  116. if (size & 1)
  117. {
  118. d = data[n];
  119. cs += d;
  120. if (cs < d)
  121. cs++;
  122. }
  123. return cs;
  124. }
  125. void showhdr(unsigned char *hdr)
  126. {
  127. int i, j;
  128. for (j = 0; j < 5; j++)
  129. {
  130. for (i = 0; i < 16; i++)
  131. {
  132. printf("%02x ", (unsigned int)(hdr[j * 16 + i]));
  133. }
  134. printf(" ");
  135. for (i = 0; i < 16; i++)
  136. {
  137. unsigned char d = hdr[j * 16 + i];
  138. printf("%c", (d >= ' ' && d < 127) ? d : '.');
  139. }
  140. printf("\n");
  141. }
  142. }
  143. void makehdr(unsigned char *hdr, struct hdrinfo *info,
  144. unsigned char *data, long size, int last)
  145. {
  146. unsigned int offset = info->addr + 0x10;
  147. memset(hdr, 0, HDRSIZE);
  148. if (info->topalign)
  149. offset = info->addr + info->size - size; /* top align */
  150. strncpy((char *)hdr + 0x00, ascii1, 14);
  151. strncpy((char *)hdr + 0x10, ascii2, 12);
  152. COPY_LONG(hdr, 0x1c, info->unknown);
  153. COPY_LONG(hdr, 0x20, info->addr);
  154. COPY_LONG(hdr, 0x24, info->size);
  155. COPY_LONG(hdr, 0x28, offset);
  156. COPY_LONG(hdr, 0x2c, size);
  157. COPY_LONG(hdr, 0x40, 0x01014842);
  158. COPY_LONG(hdr, 0x44, last ? 0x01050050 : 0x01000050);
  159. COPY_LONG(hdr, 0x48, info->addr);
  160. COPY_SHORT(hdr, 0x4c, info->unknown == 0xcb5f06b5 ? 0x0016 : 0x000b);
  161. COPY_SHORT(hdr, 0x0e, checksum(data, size));
  162. COPY_SHORT(hdr, 0x4e, ~checksum(hdr, HDRSIZE));
  163. }
  164. unsigned char *read_file(const char *name, long *size)
  165. {
  166. FILE *f;
  167. unsigned char *data = NULL;
  168. *size = 0;
  169. f = fopen(name, "r");
  170. if (f != NULL)
  171. {
  172. if (fseek(f, 0, SEEK_END) == 0)
  173. {
  174. *size = ftell(f);
  175. if (*size != -1)
  176. {
  177. if (fseek(f, 0, SEEK_SET) == 0)
  178. {
  179. data = (unsigned char *)malloc(*size);
  180. if (data != NULL)
  181. {
  182. if (fread(data, sizeof(char), *size, f) != *size)
  183. {
  184. free(data);
  185. data = NULL;
  186. }
  187. }
  188. }
  189. }
  190. }
  191. fclose(f);
  192. }
  193. return data;
  194. }
  195. struct hdrinfo *find_hdrinfo(const char *name)
  196. {
  197. int n;
  198. for (n = 0; hdrinfo[n].name != NULL; n++)
  199. {
  200. if (strcmp(name, hdrinfo[n].name) == 0)
  201. return &hdrinfo[n];
  202. }
  203. return NULL;
  204. }
  205. void oferror(FILE *f)
  206. {
  207. printf("file error\n");
  208. exit(2);
  209. }
  210. void showhelp(void)
  211. {
  212. printf("Syntax: makeamitbin [options]\n");
  213. printf("Options:\n");
  214. printf(" -1 ID1\tFirmware identifier 1, e.g. 'DDC_RUS001' for manufacturer LevelOne\n");
  215. printf(" -2 ID2\tFirmware identifier 2, 'Queen' in all known cases\n");
  216. printf(" -o FILE\tOutput file\n");
  217. printf(" -ids\t\tShow a list of known firmware identifiers.\n");
  218. exit(1);
  219. }
  220. void show_fwids(void)
  221. {
  222. printf("List of known firmware identifiers:\n");
  223. printf("Manufacturer\t\tProduct\t\tIdentifier\n");
  224. printf("=====================================================\n");
  225. printf("Conceptronic\t\tCHD2WLANU\tLLM_RUS001\n");
  226. printf("Pearl\t\t\tPE6643\t\tQueen\n");
  227. printf("Micronica\t\tMGB100\t\tQueen\n");
  228. printf("LevelOne\t\tWAP-0007\tDDC_RUS001\n");
  229. printf("SMC\t\t\tWAPS-G\t\tSMC_RUS001\n");
  230. printf("OvisLink (AirLive)\tWMU-6\t\tOVS_RUS001\n");
  231. printf("SafeCom SWSAPUR-5\tFMW\t\tSafeco_RPS001\n");
  232. exit(1);
  233. }
  234. int main(int argc, char *argv[])
  235. {
  236. unsigned char hdr[HDRSIZE];
  237. unsigned char *data;
  238. FILE *of;
  239. char *outfile = NULL;
  240. char *type;
  241. struct hdrinfo *info;
  242. long size;
  243. int last = 0;
  244. int n;
  245. for (n = 1; n < argc; n++)
  246. {
  247. if (strcmp(argv[n], "-1") == 0)
  248. ascii1 = argv[n+1];
  249. if (strcmp(argv[n], "-2") == 0)
  250. ascii2 = argv[n+1];
  251. if (strcmp(argv[n], "-o") == 0)
  252. outfile = argv[n+1];
  253. if (strcmp(argv[n], "-ids") == 0)
  254. show_fwids();
  255. }
  256. if (ascii1 == NULL || ascii2 == NULL || outfile == NULL)
  257. showhelp();
  258. of = fopen(outfile, "w");
  259. if (of == NULL)
  260. oferror(of);
  261. for (n = 1; n < argc; n++)
  262. {
  263. if (strncmp(argv[n], "-", 1) != 0)
  264. {
  265. type = argv[n++];
  266. if (n >= argc)
  267. showhelp();
  268. last = ((n + 1) >= argc); /* dirty, options first! */
  269. info = find_hdrinfo(type);
  270. if (info == NULL)
  271. showhelp();
  272. data = read_file(argv[n], &size);
  273. if (data == NULL)
  274. showhelp();
  275. makehdr(hdr, info, data, size, last);
  276. /* showhdr(hdr); */
  277. if (fwrite(hdr, HDRSIZE, 1, of) != 1)
  278. oferror(of);
  279. if (fwrite(data, size, 1, of) != 1)
  280. oferror(of);
  281. free(data);
  282. }
  283. else
  284. n++;
  285. }
  286. if (fclose(of) != 0)
  287. oferror(NULL);
  288. return 0;
  289. }