makeamitbin.c 6.8 KB

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