motorola-bin.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * motorola-bin.c
  3. *
  4. * Copyright (C) 2005-2006 Mike Baker,
  5. * Imre Kaloz <kaloz@openwrt.org>
  6. * D. Hugh Redelmeier
  7. * OpenWrt.org
  8. *
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. *
  24. */
  25. /*
  26. * Motorola's firmware flashing code requires an extra header.
  27. * The header is eight bytes (see struct motorola below).
  28. * This program will take a firmware file and create a new one
  29. * with this header:
  30. * motorola-bin --wr850g WR850G_V403.stripped.trx WR850G_V403.trx
  31. *
  32. * Note: Motorola's firmware is distributed with this header.
  33. * If you need to flash Motorola firmware on a router running OpenWRT,
  34. * you will to remove this header. Use the --strip flag:
  35. * motorola-bin --strip WR850G_V403.trx WR850G_V403.stripped.trx
  36. */
  37. /*
  38. * February 1, 2006
  39. *
  40. * Add support for for creating WA840G and WE800G images
  41. */
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <stddef.h>
  45. #include <unistd.h>
  46. #include <errno.h>
  47. #include <fcntl.h>
  48. #include <sys/mman.h>
  49. #include <string.h>
  50. #include <netinet/in.h>
  51. #include <inttypes.h>
  52. #define BPB 8 /* bits/byte */
  53. static uint32_t crc32[1<<BPB];
  54. static void init_crc32()
  55. {
  56. const uint32_t poly = ntohl(0x2083b8ed);
  57. int n;
  58. for (n = 0; n < 1<<BPB; n++) {
  59. uint32_t crc = n;
  60. int bit;
  61. for (bit = 0; bit < BPB; bit++)
  62. crc = (crc & 1) ? (poly ^ (crc >> 1)) : (crc >> 1);
  63. crc32[n] = crc;
  64. }
  65. }
  66. static uint32_t crc32buf(unsigned char *buf, size_t len)
  67. {
  68. uint32_t crc = 0xFFFFFFFF;
  69. for (; len; len--, buf++)
  70. crc = crc32[(uint8_t)crc ^ *buf] ^ (crc >> BPB);
  71. return crc;
  72. }
  73. struct motorola {
  74. uint32_t crc; // crc32 of the remainder
  75. uint32_t flags; // unknown, 105770*
  76. };
  77. static const struct model {
  78. char digit; /* a digit signifying model (historical) */
  79. const char *name;
  80. uint32_t flags;
  81. } models[] = {
  82. { '1', "WR850G", 0x10577050LU },
  83. { '2', "WA840G", 0x10577040LU },
  84. { '3', "WE800G", 0x10577000LU },
  85. { '\0', NULL, 0 }
  86. };
  87. static void usage(const char *) __attribute__ (( __noreturn__ ));
  88. static void usage(const char *mess)
  89. {
  90. const struct model *m;
  91. fprintf(stderr, "Error: %s\n", mess);
  92. fprintf(stderr, "Usage: motorola-bin -device|--strip infile outfile\n");
  93. fprintf(stderr, "Known devices: ");
  94. for (m = models; m->digit != '\0'; m++)
  95. fprintf(stderr, " %c - %s", m->digit, m->name);
  96. fprintf(stderr, "\n");
  97. exit(1);
  98. }
  99. int main(int argc, char **argv)
  100. {
  101. off_t len; // of original firmware
  102. int fd;
  103. void *trx; // pointer to original firmware (mmmapped)
  104. struct motorola *firmware; // pionter to prefix + copy of original firmware
  105. uint32_t flags;
  106. // verify parameters
  107. if (argc != 4)
  108. usage("wrong number of arguments");
  109. // mmap trx file
  110. if ((fd = open(argv[2], O_RDONLY)) < 0
  111. || (len = lseek(fd, 0, SEEK_END)) < 0
  112. || (trx = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0)) == (void *) (-1)
  113. || close(fd) < 0)
  114. {
  115. fprintf(stderr, "Error loading file %s: %s\n", argv[2], strerror(errno));
  116. exit(1);
  117. }
  118. init_crc32();
  119. if (strcmp(argv[1], "--strip") == 0)
  120. {
  121. const char *ugh = NULL;
  122. if (len < sizeof(struct motorola)) {
  123. ugh = "input file too short";
  124. } else {
  125. const struct model *m;
  126. firmware = trx;
  127. if (htonl(crc32buf(trx + offsetof(struct motorola, flags), len - offsetof(struct motorola, flags))) != firmware->crc)
  128. ugh = "Invalid CRC";
  129. for (m = models; ; m++) {
  130. if (m->digit == '\0') {
  131. if (ugh == NULL)
  132. ugh = "unrecognized flags field";
  133. break;
  134. }
  135. if (firmware->flags == htonl(m->flags)) {
  136. fprintf(stderr, "Firmware for Motorola %s\n", m->name);
  137. break;
  138. }
  139. }
  140. }
  141. if (ugh != NULL) {
  142. fprintf(stderr, "%s\n", ugh);
  143. exit(3);
  144. } else {
  145. // all is well, write the file without the prefix
  146. if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0
  147. || write(fd, trx + sizeof(struct motorola), len - sizeof(struct motorola)) != len - sizeof(struct motorola)
  148. || close(fd) < 0)
  149. {
  150. fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno));
  151. exit(2);
  152. }
  153. }
  154. } else {
  155. // setup the firmware flags magic number
  156. const struct model *m;
  157. const char *df = argv[1];
  158. if (*df != '-')
  159. usage("first argument must start with -");
  160. if (*++df == '-')
  161. ++df; /* allow but don't require second - */
  162. for (m = models; ; m++) {
  163. if (m->digit == '\0')
  164. usage("unrecognized device specified");
  165. if ((df[0] == m->digit && df[1] == '\0') || strcasecmp(df, m->name) == 0) {
  166. flags = m->flags;
  167. break;
  168. }
  169. }
  170. // create a firmware image in memory
  171. // and copy the trx to it
  172. firmware = malloc(sizeof(struct motorola) + len);
  173. memcpy(&firmware[1], trx, len);
  174. // setup the motorola headers
  175. firmware->flags = htonl(flags);
  176. // CRC of flags + firmware
  177. firmware->crc = htonl(crc32buf((unsigned char *)&firmware->flags, sizeof(firmware->flags) + len));
  178. // write the firmware
  179. if ((fd = open(argv[3], O_CREAT|O_WRONLY|O_TRUNC,0644)) < 0
  180. || write(fd, firmware, sizeof(struct motorola) + len) != sizeof(struct motorola) + len
  181. || close(fd) < 0)
  182. {
  183. fprintf(stderr, "Error storing file %s: %s\n", argv[3], strerror(errno));
  184. exit(2);
  185. }
  186. free(firmware);
  187. }
  188. munmap(trx,len);
  189. return 0;
  190. }