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