firmware-utils: allow mkfwimage2 to use - in partition names
[openwrt/staging/mkresin.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 }