1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
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)
23 #error "Unsupported endianness"
26 #define TRX_MAGIC 0x30524448
27 #define TRX_FLAGS_OFFSET 12
45 char *out_path
= NULL
;
46 char *productid
= NULL
;
47 uint8_t version
[4] = { };
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,
116 static void parse_options(int argc
, char **argv
) {
119 while ((c
= getopt(argc
, argv
, "i:o:p:v:")) != -1) {
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
);
138 static void usage() {
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");
146 int main(int argc
, char **argv
) {
147 struct trx_header hdr
;
148 struct asustrx_tail tail
= { };
154 uint32_t crc32
= 0xffffffff;
158 /* Parse & validate arguments */
159 parse_options(argc
, argv
);
160 if (!in_path
|| !out_path
|| !productid
) {
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
));
174 in
= fopen(in_path
, "r");
176 fprintf(stderr
, "Couldn't open %s\n", in_path
);
180 out
= fopen(out_path
, "w+");
182 fprintf(stderr
, "Couldn't open %s\n", out_path
);
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
);
195 for (i
= 0; i
< bytes
; i
++) {
197 fprintf(stderr
, "Input TRX doesn't have last 64 B empty %s\n", out_path
);
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
);
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
);
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) {
227 for (i
= 0; i
< bytes
; i
++)
228 crc32
= crc32_tbl
[(crc32
^ buf
[i
]) & 0xff] ^ (crc32
>> 8);
234 if (fread(&hdr
, 1, sizeof(hdr
), out
) != bytes
) {
235 fprintf(stderr
, "Couldn't read %zu B from %s\n", bytes
, in_path
);
239 hdr
.crc32
= cpu_to_le32(crc32
);
241 if (fwrite(&hdr
, 1, bytes
, out
) != bytes
) {
242 fprintf(stderr
, "Couldn't write %zu B to %s\n", bytes
, out_path
);