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
32 #define TRX_MAX_PARTS 3
44 size_t trx_offset
= 0;
45 char *partition
[TRX_MAX_PARTS
] = {};
47 /**************************************************
49 **************************************************/
51 uint32_t otrx_crc32(uint8_t *buf
, size_t len
) {
52 static const uint32_t t
[] = {
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,
118 uint32_t crc
= 0xffffffff;
121 crc
= t
[(crc
^ *buf
) & 0xff] ^ (crc
>> 8);
129 /**************************************************
131 **************************************************/
133 static void otrx_check_parse_options(int argc
, char **argv
) {
136 while ((c
= getopt(argc
, argv
, "o:")) != -1) {
139 trx_offset
= atoi(optarg
);
145 static int otrx_check(int argc
, char **argv
) {
147 struct trx_header hdr
;
148 size_t bytes
, length
;
154 fprintf(stderr
, "No TRX file passed\n");
161 otrx_check_parse_options(argc
, argv
);
163 trx
= fopen(trx_path
, "r");
165 fprintf(stderr
, "Couldn't open %s\n", trx_path
);
170 fseek(trx
, trx_offset
, SEEK_SET
);
171 bytes
= fread(&hdr
, 1, sizeof(hdr
), trx
);
172 if (bytes
!= sizeof(hdr
)) {
173 fprintf(stderr
, "Couldn't read %s header\n", trx_path
);
178 if (le32_to_cpu(hdr
.magic
) != TRX_MAGIC
) {
179 fprintf(stderr
, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr
.magic
));
184 length
= le32_to_cpu(hdr
.length
);
185 if (length
< sizeof(hdr
)) {
186 fprintf(stderr
, "Length read from TRX too low (%zu B)\n", length
);
191 buf
= malloc(length
);
193 fprintf(stderr
, "Couldn't alloc %zd B buffer\n", length
);
198 fseek(trx
, trx_offset
, SEEK_SET
);
199 bytes
= fread(buf
, 1, length
, trx
);
200 if (bytes
!= length
) {
201 fprintf(stderr
, "Couldn't read %zd B of data from %s\n", length
, trx_path
);
206 crc32
= otrx_crc32(buf
+ TRX_FLAGS_OFFSET
, length
- TRX_FLAGS_OFFSET
);
207 if (crc32
!= le32_to_cpu(hdr
.crc32
)) {
208 fprintf(stderr
, "Invalid data crc32: 0x%08x instead of 0x%08x\n", crc32
, le32_to_cpu(hdr
.crc32
));
213 printf("Found a valid TRX version %d\n", le32_to_cpu(hdr
.version
));
223 /**************************************************
225 **************************************************/
227 static void otrx_extract_parse_options(int argc
, char **argv
) {
230 while ((c
= getopt(argc
, argv
, "c:e:o:1:2:3:")) != -1) {
233 trx_offset
= atoi(optarg
);
236 partition
[0] = optarg
;
239 partition
[1] = optarg
;
242 partition
[2] = optarg
;
248 static int otrx_extract_copy(FILE *trx
, size_t offset
, size_t length
, char *out_path
) {
254 out
= fopen(out_path
, "w");
256 fprintf(stderr
, "Couldn't open %s\n", out_path
);
261 buf
= malloc(length
);
263 fprintf(stderr
, "Couldn't alloc %zu B buffer\n", length
);
268 fseek(trx
, offset
, SEEK_SET
);
269 bytes
= fread(buf
, 1, length
, trx
);
270 if (bytes
!= length
) {
271 fprintf(stderr
, "Couldn't read %zu B of data from %s\n", length
, trx_path
);
276 bytes
= fwrite(buf
, 1, length
, out
);
277 if (bytes
!= length
) {
278 fprintf(stderr
, "Couldn't write %zu B to %s\n", length
, out_path
);
283 printf("Extracted 0x%zx bytes into %s\n", length
, out_path
);
293 static int otrx_extract(int argc
, char **argv
) {
295 struct trx_header hdr
;
301 fprintf(stderr
, "No TRX file passed\n");
308 otrx_extract_parse_options(argc
, argv
);
310 trx
= fopen(trx_path
, "r");
312 fprintf(stderr
, "Couldn't open %s\n", trx_path
);
317 fseek(trx
, trx_offset
, SEEK_SET
);
318 bytes
= fread(&hdr
, 1, sizeof(hdr
), trx
);
319 if (bytes
!= sizeof(hdr
)) {
320 fprintf(stderr
, "Couldn't read %s header\n", trx_path
);
325 if (le32_to_cpu(hdr
.magic
) != TRX_MAGIC
) {
326 fprintf(stderr
, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr
.magic
));
331 for (i
= 0; i
< TRX_MAX_PARTS
; i
++) {
336 if (!hdr
.offset
[i
]) {
337 printf("TRX doesn't contain partition %d, can't extract %s\n", i
+ 1, partition
[i
]);
341 if (i
+ 1 >= TRX_MAX_PARTS
|| !hdr
.offset
[i
+ 1])
342 length
= le32_to_cpu(hdr
.length
) - le32_to_cpu(hdr
.offset
[i
]);
344 length
= le32_to_cpu(hdr
.offset
[i
+ 1]) - le32_to_cpu(hdr
.offset
[i
]);
346 otrx_extract_copy(trx
, trx_offset
+ le32_to_cpu(hdr
.offset
[i
]), length
, partition
[i
]);
355 /**************************************************
357 **************************************************/
359 static void usage() {
362 printf("Checking TRX file:\n");
363 printf("\totrx check <file> [options]\tcheck if file is a valid TRX\n");
364 printf("\t-o offset\t\t\toffset of TRX data in file (default: 0)\n");
366 printf("Extracting from TRX file:\n");
367 printf("\totrx extract <file> [options]\textract partitions from TRX file\n");
368 printf("\t-o offset\t\t\toffset of TRX data in file (default: 0)\n");
369 printf("\t-1 file\t\t\t\tfile to extract 1st partition to (optional)\n");
370 printf("\t-2 file\t\t\t\tfile to extract 2nd partition to (optional)\n");
371 printf("\t-3 file\t\t\t\tfile to extract 3rd partition to (optional)\n");
374 int main(int argc
, char **argv
) {
376 if (!strcmp(argv
[1], "check"))
377 return otrx_check(argc
, argv
);
378 else if (!strcmp(argv
[1], "extract"))
379 return otrx_extract(argc
, argv
);