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