04af9a184a58c24ad8f552716d79799ddebab0f6
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
, "%hhu.%hhu.%hhu.%hhu", &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
= { };
158 uint32_t crc32
= 0xffffffff;
162 /* Parse & validate arguments */
163 parse_options(argc
, argv
);
164 if (!in_path
|| !out_path
|| !productid
) {
171 tail
.version
[0] = version
[0];
172 tail
.version
[1] = version
[1];
173 tail
.version
[2] = version
[2];
174 tail
.version
[3] = version
[3];
175 strncpy(tail
.productid
, productid
, sizeof(tail
.productid
));
178 in
= fopen(in_path
, "r");
180 fprintf(stderr
, "Couldn't open %s\n", in_path
);
184 out
= fopen(out_path
, "w+");
186 fprintf(stderr
, "Couldn't open %s\n", out_path
);
191 /* Check is there is empty place for Asus tail */
192 bytes
= sizeof(struct asustrx_tail
);
193 fseek(in
, -bytes
, SEEK_END
);
194 if (fread(buf
, 1, bytes
, in
) != bytes
) {
195 fprintf(stderr
, "Couldn't read %zu B from %s\n", bytes
, in_path
);
199 for (i
= 0; i
< bytes
; i
++) {
201 fprintf(stderr
, "Input TRX doesn't have last 64 B empty %s\n", out_path
);
209 while ((bytes
= fread(buf
, 1, sizeof(buf
), in
)) > 0) {
210 if (fwrite(buf
, 1, bytes
, out
) != bytes
) {
211 fprintf(stderr
, "Couldn't write %zu B to %s\n", bytes
, out_path
);
217 /* Overwrite last 64 B with Asus tail */
218 bytes
= sizeof(tail
);
219 fseek(out
, -bytes
, SEEK_CUR
);
220 if (fwrite(&tail
, 1, bytes
, out
) != bytes
) {
221 fprintf(stderr
, "Couldn't write %zu B to %s\n", bytes
, out_path
);
226 /* Calculate crc32 */
227 fseek(out
, TRX_FLAGS_OFFSET
, SEEK_SET
);
228 length
= TRX_FLAGS_OFFSET
;
229 while ((bytes
= fread(buf
, 1, sizeof(buf
), out
)) > 0) {
231 for (i
= 0; i
< bytes
; i
++)
232 crc32
= crc32_tbl
[(crc32
^ buf
[i
]) & 0xff] ^ (crc32
>> 8);
238 if (fread(&hdr
, 1, sizeof(hdr
), out
) != bytes
) {
239 fprintf(stderr
, "Couldn't read %zu B from %s\n", bytes
, in_path
);
243 hdr
.crc32
= cpu_to_le32(crc32
);
245 if (fwrite(&hdr
, 1, bytes
, out
) != bytes
) {
246 fprintf(stderr
, "Couldn't write %zu B to %s\n", bytes
, out_path
);