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
38struct 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
73static 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
111static 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
121uint32_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
129void 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
154void usage(void) __attribute__ (( __noreturn__ ));
155
156void usage(void)
157{
158	fprintf(stderr, "Usage: spw303v [-i <inputfile>] [-o <outputfile>]\n");
159	exit(EXIT_FAILURE);
160}
161
162
163int 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}
244