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