tools/firmware-utils: remove obsolete firmware utility for airlink 525w
[openwrt/staging/mkresin.git] / tools / firmware-utils / src / zyxbcm.c
1 /*
2 * zyxbcm.c - based on Jonas Gorski's spw303v.c
3 *
4 * Copyright (C) 2014 Álvaro Fernández Rojas <noltari@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 TAGVER_LEN 4 /* Length of Tag Version */
31 #define SIG1_LEN 20 /* Company Signature 1 Length */
32 #define SIG2_LEN 14 /* Company Signature 2 Lenght */
33 #define BOARDID_LEN 16 /* Length of BoardId */
34 #define ENDIANFLAG_LEN 2 /* Endian Flag Length */
35 #define CHIPID_LEN 6 /* Chip Id Length */
36 #define IMAGE_LEN 10 /* Length of Length Field */
37 #define ADDRESS_LEN 12 /* Length of Address field */
38 #define DUALFLAG_LEN 2 /* Dual Image flag Length */
39 #define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
40 #define RSASIG_LEN 20 /* Length of RSA Signature in tag */
41 #define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
42 #define ZYX_TAGINFO1_LEN 20 /* Length of vendor information field1 in tag */
43 #define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
44 #define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
45 #define CRC_LEN 4 /* Length of CRC in bytes */
46
47 #define IMAGETAG_CRC_START 0xFFFFFFFF
48
49 struct bcm_tag {
50 char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag
51 char sig_1[SIG1_LEN]; // 4-23: Company Line 1
52 char sig_2[SIG2_LEN]; // 24-37: Company Line 2
53 char chipid[CHIPID_LEN]; // 38-43: Chip this image is for
54 char boardid[BOARDID_LEN]; // 44-59: Board name
55 char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE
56 char totalLength[IMAGE_LEN]; // 62-71: Total length of image
57 char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
58 char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
59 char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware)
60 char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs for flashing
61 char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
62 char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
63 char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present
64 char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present
65 char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this)
66 char information1[TAGINFO1_LEN]; // 162-191: Compilation and related information (not generated/used by OpenWRT)
67 char flashLayoutVer[FLASHLAYOUTVER_LEN]; // 192-195: Version flash layout
68 char fskernelCRC[CRC_LEN]; // 196-199: kernel+rootfs CRC32
69 char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information
70 char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate)
71 char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition
72 char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition
73 char imageSequence[4]; // 228-231: Image sequence number
74 char rootLength[4]; // 232-235: steal from reserved1 to keep the real root length so we can use in the flash map even after we have change the rootLength to 0 to satisfy devices that check CRC on every boot
75 char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion
76 char reserved2[16]; // 240-255: Unused at present
77 };
78
79 struct zyxbcm_tag {
80 char tagVersion[TAGVER_LEN]; // 0-3: Version of the image tag
81 char sig_1[SIG1_LEN]; // 4-23: Company Line 1
82 char sig_2[SIG2_LEN]; // 24-37: Company Line 2
83 char chipid[CHIPID_LEN]; // 38-43: Chip this image is for
84 char boardid[BOARDID_LEN]; // 44-59: Board name
85 char big_endian[ENDIANFLAG_LEN]; // 60-61: Map endianness -- 1 BE 0 LE
86 char totalLength[IMAGE_LEN]; // 62-71: Total length of image
87 char cfeAddress[ADDRESS_LEN]; // 72-83: Address in memory of CFE
88 char cfeLength[IMAGE_LEN]; // 84-93: Size of CFE
89 char flashImageStart[ADDRESS_LEN]; // 94-105: Address in memory of image start (kernel for OpenWRT, rootfs for stock firmware)
90 char flashRootLength[IMAGE_LEN]; // 106-115: Size of rootfs for flashing
91 char kernelAddress[ADDRESS_LEN]; // 116-127: Address in memory of kernel
92 char kernelLength[IMAGE_LEN]; // 128-137: Size of kernel
93 char dualImage[DUALFLAG_LEN]; // 138-139: Unused at present
94 char inactiveFlag[INACTIVEFLAG_LEN]; // 140-141: Unused at present
95 char rsa_signature[RSASIG_LEN]; // 142-161: RSA Signature (unused at present; some vendors may use this)
96 char information1[ZYX_TAGINFO1_LEN]; // 162-181: Compilation and related information (not generated/used by OpenWRT)
97 char flashImageEnd[ADDRESS_LEN]; // 182-193: Address in memory of image end
98 char fskernelCRC[CRC_LEN]; // 194-197: kernel+rootfs CRC32
99 char reserved1[2]; // 198-199: Unused at present
100 char information2[TAGINFO2_LEN]; // 200-215: Unused at present except Alice Gate where is is information
101 char imageCRC[CRC_LEN]; // 216-219: CRC32 of image less imagetag (kernel for Alice Gate)
102 char rootfsCRC[CRC_LEN]; // 220-223: CRC32 of rootfs partition
103 char kernelCRC[CRC_LEN]; // 224-227: CRC32 of kernel partition
104 char imageSequence[4]; // 228-231: Image sequence number
105 char rootLength[4]; // 232-235: steal from reserved1 to keep the real root length so we can use in the flash map even after we have change the rootLength to 0 to satisfy devices that check CRC on every boot
106 char headerCRC[CRC_LEN]; // 236-239: CRC32 of header excluding tagVersion
107 char reserved2[16]; // 240-255: Unused at present
108 };
109
110 static uint32_t crc32tab[256] = {
111 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
112 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
113 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
114 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
115 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
116 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
117 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
118 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
119 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
120 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
121 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
122 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
123 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
124 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
125 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
126 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
127 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
128 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
129 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
130 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
131 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
132 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
133 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
134 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
135 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
136 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
137 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
138 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
139 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
140 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
141 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
142 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
143 };
144
145 uint32_t crc32(uint32_t crc, uint8_t *data, size_t len)
146 {
147 while (len--)
148 crc = (crc >> 8) ^ crc32tab[(crc ^ *data++) & 0xFF];
149
150 return crc;
151 }
152
153 void fix_header(void *buf)
154 {
155 struct bcm_tag *bcmtag = buf;
156 struct zyxbcm_tag *zyxtag = buf;
157 uint8_t fskernel_crc[CRC_LEN];
158 uint32_t crc;
159 uint64_t flash_start, rootfs_len, kernel_len;
160
161 /* Backup values */
162 flash_start = strtoul(bcmtag->flashImageStart, NULL, 10);
163 rootfs_len = strtoul(bcmtag->flashRootLength, NULL, 10);
164 kernel_len = strtoul(bcmtag->kernelLength, NULL, 10);
165 memcpy(fskernel_crc, bcmtag->fskernelCRC, CRC_LEN);
166
167 /* Clear values */
168 zyxtag->information1[ZYX_TAGINFO1_LEN - 1] = 0;
169 memset(zyxtag->flashImageEnd, 0, ADDRESS_LEN);
170 memset(zyxtag->fskernelCRC, 0, CRC_LEN);
171 memset(zyxtag->reserved1, 0, 2);
172
173 /* Replace values */
174 sprintf(zyxtag->flashImageEnd, "%lu", flash_start + rootfs_len + kernel_len);
175 memcpy(zyxtag->fskernelCRC, fskernel_crc, CRC_LEN);
176
177 /* Update tag crc */
178 crc = htonl(crc32(IMAGETAG_CRC_START, buf, 236));
179 memcpy(zyxtag->headerCRC, &crc, 4);
180 }
181
182 void usage(void) __attribute__ (( __noreturn__ ));
183
184 void usage(void)
185 {
186 fprintf(stderr, "Usage: zyxbcm [-i <inputfile>] [-o <outputfile>]\n");
187 exit(EXIT_FAILURE);
188 }
189
190 int main(int argc, char **argv)
191 {
192 char buf[1024]; /* keep this at 1k or adjust garbage calc below */
193 FILE *in = stdin, *out = stdout;
194 char *ifn = NULL, *ofn = NULL;
195 size_t n;
196 int c, first_block = 1;
197
198 while ((c = getopt(argc, argv, "i:o:h")) != -1) {
199 switch (c) {
200 case 'i':
201 ifn = optarg;
202 break;
203 case 'o':
204 ofn = optarg;
205 break;
206 case 'h':
207 default:
208 usage();
209 }
210 }
211
212 if (optind != argc || optind == 1) {
213 fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]);
214 usage();
215 }
216
217 if (ifn && !(in = fopen(ifn, "r"))) {
218 fprintf(stderr, "can not open \"%s\" for reading\n", ifn);
219 usage();
220 }
221
222 if (ofn && !(out = fopen(ofn, "w"))) {
223 fprintf(stderr, "can not open \"%s\" for writing\n", ofn);
224 usage();
225 }
226
227 while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
228 if (n < sizeof(buf)) {
229 if (ferror(in)) {
230 FREAD_ERROR:
231 fprintf(stderr, "fread error\n");
232 return EXIT_FAILURE;
233 }
234 }
235
236 if (first_block && n >= 256) {
237 fix_header(buf);
238 first_block = 0;
239 }
240
241 if (!fwrite(buf, n, 1, out)) {
242 FWRITE_ERROR:
243 fprintf(stderr, "fwrite error\n");
244 return EXIT_FAILURE;
245 }
246 }
247
248 if (ferror(in)) {
249 goto FREAD_ERROR;
250 }
251
252 if (fflush(out)) {
253 goto FWRITE_ERROR;
254 }
255
256 fclose(in);
257 fclose(out);
258
259 return EXIT_SUCCESS;
260 }