• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/asustrx.c

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * asustrx
  4  *
  5  * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
  6  */
  7 
  8 #include <byteswap.h>
  9 #include <errno.h>
 10 #include <stdint.h>
 11 #include <stdio.h>
 12 #include <stdlib.h>
 13 #include <string.h>
 14 #include <unistd.h>
 15 
 16 #if __BYTE_ORDER == __BIG_ENDIAN
 17 #define cpu_to_le32(x)  bswap_32(x)
 18 #define le32_to_cpu(x)  bswap_32(x)
 19 #elif __BYTE_ORDER == __LITTLE_ENDIAN
 20 #define cpu_to_le32(x)  (x)
 21 #define le32_to_cpu(x)  (x)
 22 #else
 23 #error "Unsupported endianness"
 24 #endif
 25 
 26 #define TRX_MAGIC                       0x30524448
 27 #define TRX_FLAGS_OFFSET                12
 28 
 29 struct trx_header {
 30         uint32_t magic;
 31         uint32_t length;
 32         uint32_t crc32;
 33         uint16_t flags;
 34         uint16_t version;
 35         uint32_t offset[3];
 36 };
 37 
 38 struct asustrx_tail {
 39         uint8_t version[4];
 40         char productid[12];
 41         uint8_t unused[48];
 42 };
 43 
 44 char *in_path = NULL;
 45 char *out_path = NULL;
 46 char *productid = NULL;
 47 uint8_t version[4] = { };
 48 
 49 static const uint32_t crc32_tbl[] = {
 50         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
 51         0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
 52         0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
 53         0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
 54         0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
 55         0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
 56         0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
 57         0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
 58         0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
 59         0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
 60         0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
 61         0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
 62         0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
 63         0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
 64         0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
 65         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
 66         0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
 67         0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
 68         0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
 69         0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
 70         0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
 71         0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
 72         0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
 73         0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
 74         0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
 75         0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
 76         0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
 77         0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
 78         0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
 79         0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
 80         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
 81         0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
 82         0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
 83         0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
 84         0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
 85         0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
 86         0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
 87         0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
 88         0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
 89         0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
 90         0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
 91         0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
 92         0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
 93         0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
 94         0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
 95         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
 96         0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
 97         0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
 98         0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
 99         0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
100         0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
101         0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
102         0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
103         0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
104         0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
105         0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
106         0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
107         0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
108         0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
109         0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
110         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
111         0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
112         0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
113         0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
114 };
115 
116 static void parse_options(int argc, char **argv) {
117         int c;
118 
119         while ((c = getopt(argc, argv, "i:o:p:v:")) != -1) {
120                 switch (c) {
121                 case 'i':
122                         in_path = optarg;
123                         break;
124                 case 'o':
125                         out_path = optarg;
126                         break;
127                 case 'p':
128                         productid = optarg;
129                         break;
130                 case 'v':
131                         if (sscanf(optarg, "%hhu.%hhu.%hhu.%hhu", &version[0], &version[1], &version[2], &version[3]) != 4)
132                                 fprintf(stderr, "Version %s doesn't match suppored 4-digits format\n", optarg);
133                         break;
134                 }
135         }
136 }
137 
138 static void usage() {
139         printf("Usage:\n");
140         printf("\t-i file\t\t\t\tinput TRX file\n");
141         printf("\t-o file\t\t\t\toutput Asus TRX file\n");
142         printf("\t-p productid\t\t\tproduct (device) ID\n");
143         printf("\t-v version\t\t\tfirmware version formatted with 4 digits like: 1.2.3.4\n");
144 }
145 
146 int main(int argc, char **argv) {
147         struct trx_header hdr;
148         struct asustrx_tail tail = { };
149         FILE *out = NULL;
150         FILE *in = NULL;
151         uint8_t buf[1024];
152         size_t bytes;
153         size_t length = 0;
154         uint32_t crc32 = 0xffffffff;
155         int i;
156         int err = 0;
157 
158         /* Parse & validate arguments */
159         parse_options(argc, argv);
160         if (!in_path || !out_path || !productid) {
161                 usage();
162                 err = -EINVAL;
163                 goto err;
164         }
165 
166         /* Fill Asus tail */
167         tail.version[0] = version[0];
168         tail.version[1] = version[1];
169         tail.version[2] = version[2];
170         tail.version[3] = version[3];
171         strncpy(tail.productid, productid, sizeof(tail.productid));
172 
173         /* Open files */
174         in = fopen(in_path, "r");
175         if (!in) {
176                 fprintf(stderr, "Couldn't open %s\n", in_path);
177                 err = -EIO;
178                 goto err;
179         }
180         out = fopen(out_path, "w+");
181         if (!out) {
182                 fprintf(stderr, "Couldn't open %s\n", out_path);
183                 err = -EIO;
184                 goto err;
185         }
186 
187         /* Check is there is empty place for Asus tail */
188         bytes = sizeof(struct asustrx_tail);
189         fseek(in, -bytes, SEEK_END);
190         if (fread(buf, 1, bytes, in) != bytes) {
191                 fprintf(stderr, "Couldn't read %zu B from %s\n", bytes, in_path);
192                 err = -EIO;
193                 goto err;
194         }
195         for (i = 0; i < bytes; i++) {
196                 if (buf[i]) {
197                         fprintf(stderr, "Input TRX doesn't have last 64 B empty %s\n", out_path);
198                         err = -ENOSPC;
199                         goto err;
200                 }
201         }
202 
203         /* Copy whole TRX */
204         rewind(in);
205         while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
206                 if (fwrite(buf, 1, bytes, out) != bytes) {
207                         fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
208                         err = -EIO;
209                         goto err;
210                 }
211         }
212 
213         /* Overwrite last 64 B with Asus tail */
214         bytes = sizeof(tail);
215         fseek(out, -bytes, SEEK_CUR);
216         if (fwrite(&tail, 1, bytes, out) != bytes) {
217                 fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
218                 err = -EIO;
219                 goto err;
220         }
221 
222         /* Calculate crc32 */
223         fseek(out, TRX_FLAGS_OFFSET, SEEK_SET);
224         length = TRX_FLAGS_OFFSET;
225         while ((bytes = fread(buf, 1, sizeof(buf), out )) > 0) {
226                 length += bytes;
227                 for (i = 0; i < bytes; i++)
228                         crc32 = crc32_tbl[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8);
229         }
230 
231         /* Update header */
232         bytes = sizeof(hdr);
233         rewind(out);
234         if (fread(&hdr, 1, sizeof(hdr), out) != bytes) {
235                 fprintf(stderr, "Couldn't read %zu B from %s\n", bytes, in_path);
236                 err = -EIO;
237                 goto err;
238         }
239         hdr.crc32 = cpu_to_le32(crc32);
240         rewind(out);
241         if (fwrite(&hdr, 1, bytes, out) != bytes) {
242                 fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
243                 err = -EIO;
244                 goto err;
245         }
246 
247 err:
248         if (out)
249                 fclose(out);
250         if (in)
251                 fclose(in);
252         return err;
253 }
254 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt