spw303v.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * spw303v.c - partially based on OpenWrt's imagetag.c and addpattern.c
  3. *
  4. * Copyright (C) 2011 Jonas Gorski <jonas.gorski@gmail.com>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <stdint.h>
  24. #include <time.h>
  25. #include <unistd.h>
  26. #include <sys/stat.h>
  27. #define IMAGE_LEN 10 /* Length of Length Field */
  28. #define ADDRESS_LEN 12 /* Length of Address field */
  29. #define TAGID_LEN 6 /* Length of tag ID */
  30. #define TAGINFO_LEN 20 /* Length of vendor information field in tag */
  31. #define TAGVER_LEN 4 /* Length of Tag Version */
  32. #define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
  33. struct spw303v_tag
  34. {
  35. unsigned char tagVersion[4]; // tag version. Will be 2 here.
  36. unsigned char signiture_1[20]; // text line for company info
  37. unsigned char signiture_2[14]; // additional info (can be version number)
  38. unsigned char chipId[6]; // chip id
  39. unsigned char boardId[16]; // board id
  40. unsigned char bigEndian[2]; // if = 1 - big, = 0 - little endia of the host
  41. unsigned char totalImageLen[IMAGE_LEN]; // the sum of all the following length
  42. unsigned char cfeAddress[ADDRESS_LEN]; // if non zero, cfe starting address
  43. unsigned char cfeLen[IMAGE_LEN]; // if non zero, cfe size in clear ASCII text.
  44. unsigned char rootfsAddress[ADDRESS_LEN]; // if non zero, filesystem starting address
  45. unsigned char rootfsLen[IMAGE_LEN]; // if non zero, filesystem size in clear ASCII text.
  46. unsigned char kernelAddress[ADDRESS_LEN]; // if non zero, kernel starting address
  47. unsigned char kernelLen[IMAGE_LEN]; // if non zero, kernel size in clear ASCII text.
  48. unsigned char certf1Address[ADDRESS_LEN];
  49. unsigned char certf1Len[6];
  50. unsigned char certf2Address[ADDRESS_LEN];
  51. unsigned char certf2Len[6];
  52. unsigned char certf3Address[ADDRESS_LEN];
  53. unsigned char certf3Len[6];
  54. unsigned char httpsFileSize[4];
  55. unsigned char tr64FileSize[4];
  56. unsigned char tr69FileSize[4];
  57. unsigned char filesmap[4];
  58. unsigned char imageSequence[4]; // incrments everytime an image is flashed
  59. unsigned char reserved[4]; // reserved for later use
  60. unsigned char imageCRC[4]; // 216-219: CRC32 of images
  61. unsigned char reserved2[16]; // 220-235: Unused at present
  62. unsigned char headerCRC[4]; // 236-239: CRC32 of header excluding tagVersion
  63. unsigned char reserved3[16]; // 240-255: Unused at present
  64. };
  65. static uint32_t crc32tab[256] = {
  66. 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
  67. 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
  68. 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
  69. 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
  70. 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
  71. 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
  72. 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
  73. 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
  74. 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
  75. 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
  76. 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
  77. 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
  78. 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
  79. 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
  80. 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
  81. 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
  82. 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
  83. 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
  84. 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
  85. 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
  86. 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
  87. 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
  88. 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
  89. 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
  90. 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
  91. 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
  92. 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
  93. 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
  94. 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
  95. 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
  96. 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
  97. 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
  98. };
  99. #define IMAGETAG_CRC_START 0xFFFFFFFF
  100. #define IMAGETAG_MAGIC1_TCOM "AAAAAAAA Corporatio"
  101. static char fake_data[] = {
  102. 0x18, 0x21, 0x21, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 ,0x18,
  103. 0x21, 0x24, 0x21, 0x1b, 0x18, 0x18, 0x24, 0x24, 0x18, 0x21, 0x21, 0x21,
  104. 0x21, 0x21, 0x21, 0x21, 0x1b, 0x18, 0x18, 0x24, 0x24, 0x21, 0x21, 0x21,
  105. 0x21, 0x21, 0x21, 0x21, 0x18, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x18,
  106. 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x18, 0x21, 0x21,
  107. 0x21, 0x21, 0x21, 0x21,
  108. };
  109. uint32_t crc32(uint32_t crc, uint8_t *data, size_t len)
  110. {
  111. while (len--)
  112. crc = (crc >> 8) ^ crc32tab[(crc ^ *data++) & 0xFF];
  113. return crc;
  114. }
  115. void fix_header(void *buf)
  116. {
  117. struct spw303v_tag *tag = buf;
  118. uint32_t crc;
  119. /* Replace signature with custom t-com one */
  120. memset(tag->signiture_1, 0, 20);
  121. memcpy(tag->signiture_1, IMAGETAG_MAGIC1_TCOM, strlen(IMAGETAG_MAGIC1_TCOM));
  122. /* Clear cert fields to remove information_* data */
  123. memset(tag->certf1Address, 0, 74);
  124. /* replace image crc with modified one */
  125. crc = ntohl(*((uint32_t *)&tag->imageCRC));
  126. crc = htonl(crc32(crc, fake_data, 64));
  127. memcpy(tag->imageCRC, &crc, 4);
  128. /* Update tag crc */
  129. crc = htonl(crc32(IMAGETAG_CRC_START, buf, 236));
  130. memcpy(tag->headerCRC, &crc, 4);
  131. }
  132. void usage(void) __attribute__ (( __noreturn__ ));
  133. void usage(void)
  134. {
  135. fprintf(stderr, "Usage: spw303v [-i <inputfile>] [-o <outputfile>]\n");
  136. exit(EXIT_FAILURE);
  137. }
  138. int main(int argc, char **argv)
  139. {
  140. char buf[1024]; /* keep this at 1k or adjust garbage calc below */
  141. FILE *in = stdin;
  142. FILE *out = stdout;
  143. char *ifn = NULL;
  144. char *ofn = NULL;
  145. int c;
  146. int v0, v1, v2;
  147. size_t n;
  148. int first_block = 1;
  149. uint32_t image_crc = IMAGETAG_CRC_START;
  150. while ((c = getopt(argc, argv, "i:o:h")) != -1) {
  151. switch (c) {
  152. case 'i':
  153. ifn = optarg;
  154. break;
  155. case 'o':
  156. ofn = optarg;
  157. break;
  158. case 'h':
  159. default:
  160. usage();
  161. }
  162. }
  163. if (optind != argc || optind == 1) {
  164. fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]);
  165. usage();
  166. }
  167. if (ifn && !(in = fopen(ifn, "r"))) {
  168. fprintf(stderr, "can not open \"%s\" for reading\n", ifn);
  169. usage();
  170. }
  171. if (ofn && !(out = fopen(ofn, "w"))) {
  172. fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
  173. usage();
  174. }
  175. while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
  176. if (n < sizeof(buf)) {
  177. if (ferror(in)) {
  178. FREAD_ERROR:
  179. fprintf(stderr, "fread error\n");
  180. return EXIT_FAILURE;
  181. }
  182. }
  183. if (first_block && n >= 256) {
  184. fix_header(buf);
  185. first_block = 0;
  186. }
  187. image_crc = crc32(image_crc, buf, n);
  188. if (!fwrite(buf, n, 1, out)) {
  189. FWRITE_ERROR:
  190. fprintf(stderr, "fwrite error\n");
  191. return EXIT_FAILURE;
  192. }
  193. }
  194. if (ferror(in)) {
  195. goto FREAD_ERROR;
  196. }
  197. if (fflush(out)) {
  198. goto FWRITE_ERROR;
  199. }
  200. fclose(in);
  201. fclose(out);
  202. return EXIT_SUCCESS;
  203. }