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
;
52 static const uint32_t crc32_tbl
[] = {
53 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
54 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
55 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
56 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
57 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
58 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
59 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
60 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
61 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
62 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
63 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
64 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
65 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
66 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
67 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
68 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
69 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
70 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
71 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
72 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
73 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
74 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
75 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
76 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
77 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
78 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
79 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
80 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
81 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
82 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
83 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
84 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
85 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
86 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
87 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
88 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
89 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
90 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
91 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
92 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
93 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
94 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
95 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
96 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
97 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
98 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
99 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
100 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
101 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
102 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
103 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
104 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
105 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
106 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
107 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
108 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
109 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
110 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
111 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
112 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
113 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
114 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
115 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
116 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
119 static void parse_options(int argc
, char **argv
) {
122 while ((c
= getopt(argc
, argv
, "i:o:p:")) != -1) {
137 static void usage() {
139 printf("\t-i file\t\t\t\tinput TRX file\n");
140 printf("\t-o offset\t\t\toutput Asus TRX file\n");
141 printf("\t-p productid\t\t\tproduct (device) ID\n");
144 int main(int argc
, char **argv
) {
145 struct trx_header hdr
;
146 struct asustrx_tail tail
= { };
151 uint32_t crc32
= 0xffffffff;
155 /* Parse & validate arguments */
156 parse_options(argc
, argv
);
157 if (!in_path
|| !out_path
|| !productid
) {
164 strncpy(tail
.productid
, productid
, sizeof(tail
.productid
));
167 in
= fopen(in_path
, "r");
169 fprintf(stderr
, "Couldn't open %s\n", in_path
);
173 out
= fopen(out_path
, "w+");
175 fprintf(stderr
, "Couldn't open %s\n", out_path
);
180 /* Check is there is empty place for Asus tail */
181 bytes
= sizeof(struct asustrx_tail
);
182 fseek(in
, -bytes
, SEEK_END
);
183 if (fread(buf
, 1, bytes
, in
) != bytes
) {
184 fprintf(stderr
, "Couldn't read %zu B from %s\n", bytes
, in_path
);
188 for (i
= 0; i
< bytes
; i
++) {
190 fprintf(stderr
, "Input TRX doesn't have last 64 B empty %s\n");
198 while ((bytes
= fread(buf
, 1, sizeof(buf
), in
)) > 0) {
199 if (fwrite(buf
, 1, bytes
, out
) != bytes
) {
200 fprintf(stderr
, "Couldn't write %zu B to %s\n", bytes
, out_path
);
206 /* Overwrite last 64 B with Asus tail */
207 bytes
= sizeof(tail
);
208 fseek(out
, -bytes
, SEEK_CUR
);
209 if (fwrite(&tail
, 1, bytes
, out
) != bytes
) {
210 fprintf(stderr
, "Couldn't write %zu B to %s\n", bytes
);
215 /* Calculate crc32 */
216 fseek(out
, TRX_FLAGS_OFFSET
, SEEK_SET
);
217 length
= TRX_FLAGS_OFFSET
;
218 while ((bytes
= fread(buf
, 1, sizeof(buf
), out
)) > 0) {
220 for (i
= 0; i
< bytes
; i
++)
221 crc32
= crc32_tbl
[(crc32
^ buf
[i
]) & 0xff] ^ (crc32
>> 8);
227 if (fread(&hdr
, 1, sizeof(hdr
), out
) != bytes
) {
228 fprintf(stderr
, "Couldn't read %zu B from %s\n", bytes
, in_path
);
232 hdr
.crc32
= cpu_to_le32(crc32
);
234 if (fwrite(&hdr
, 1, bytes
, out
) != bytes
) {
235 fprintf(stderr
, "Couldn't write %zu B to %s\n", bytes
);