4 * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
20 #if __BYTE_ORDER == __BIG_ENDIAN
21 #define cpu_to_le32(x) bswap_32(x)
22 #define le32_to_cpu(x) bswap_32(x)
23 #elif __BYTE_ORDER == __LITTLE_ENDIAN
24 #define cpu_to_le32(x) (x)
25 #define le32_to_cpu(x) (x)
27 #error "Unsupported endianness"
30 #define TRX_MAGIC 0x30524448
31 #define TRX_FLAGS_OFFSET 12
49 char *out_path = NULL;
50 char *productid = NULL;
51 uint8_t version[4] = { };
53 static const uint32_t crc32_tbl[] = {
54 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
55 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
56 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
57 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
58 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
59 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
60 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
61 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
62 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
63 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
64 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
65 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
66 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
67 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
68 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
69 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
70 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
71 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
72 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
73 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
74 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
75 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
76 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
77 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
78 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
79 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
80 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
81 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
82 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
83 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
84 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
85 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
86 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
87 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
88 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
89 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
90 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
91 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
92 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
93 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
94 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
95 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
96 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
97 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
98 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
99 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
100 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
101 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
102 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
103 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
104 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
105 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
106 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
107 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
108 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
109 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
110 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
111 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
112 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
113 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
114 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
115 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
116 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
117 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
120 static void parse_options(int argc, char **argv) {
123 while ((c = getopt(argc, argv, "i:o:p:v:")) != -1) {
135 if (sscanf(optarg, "%hu.%hu.%hu.%hu", &version[0], &version[1], &version[2], &version[3]) != 4)
136 fprintf(stderr, "Version %s doesn't match suppored 4-digits format\n", optarg);
142 static void usage() {
144 printf("\t-i file\t\t\t\tinput TRX file\n");
145 printf("\t-o file\t\t\t\toutput Asus TRX file\n");
146 printf("\t-p productid\t\t\tproduct (device) ID\n");
147 printf("\t-v version\t\t\tfirmware version formatted with 4 digits like: 1.2.3.4\n");
150 int main(int argc, char **argv) {
151 struct trx_header hdr;
152 struct asustrx_tail tail = { };
157 uint32_t crc32 = 0xffffffff;
161 /* Parse & validate arguments */
162 parse_options(argc, argv);
163 if (!in_path || !out_path || !productid) {
170 tail.version[0] = version[0];
171 tail.version[1] = version[1];
172 tail.version[2] = version[2];
173 tail.version[3] = version[3];
174 strncpy(tail.productid, productid, sizeof(tail.productid));
177 in = fopen(in_path, "r");
179 fprintf(stderr, "Couldn't open %s\n", in_path);
183 out = fopen(out_path, "w+");
185 fprintf(stderr, "Couldn't open %s\n", out_path);
190 /* Check is there is empty place for Asus tail */
191 bytes = sizeof(struct asustrx_tail);
192 fseek(in, -bytes, SEEK_END);
193 if (fread(buf, 1, bytes, in) != bytes) {
194 fprintf(stderr, "Couldn't read %zu B from %s\n", bytes, in_path);
198 for (i = 0; i < bytes; i++) {
200 fprintf(stderr, "Input TRX doesn't have last 64 B empty %s\n");
208 while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
209 if (fwrite(buf, 1, bytes, out) != bytes) {
210 fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, out_path);
216 /* Overwrite last 64 B with Asus tail */
217 bytes = sizeof(tail);
218 fseek(out, -bytes, SEEK_CUR);
219 if (fwrite(&tail, 1, bytes, out) != bytes) {
220 fprintf(stderr, "Couldn't write %zu B to %s\n", bytes);
225 /* Calculate crc32 */
226 fseek(out, TRX_FLAGS_OFFSET, SEEK_SET);
227 length = TRX_FLAGS_OFFSET;
228 while ((bytes = fread(buf, 1, sizeof(buf), out )) > 0) {
230 for (i = 0; i < bytes; i++)
231 crc32 = crc32_tbl[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8);
237 if (fread(&hdr, 1, sizeof(hdr), out) != bytes) {
238 fprintf(stderr, "Couldn't read %zu B from %s\n", bytes, in_path);
242 hdr.crc32 = cpu_to_le32(crc32);
244 if (fwrite(&hdr, 1, bytes, out) != bytes) {
245 fprintf(stderr, "Couldn't write %zu B to %s\n", bytes);