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)
19 #if __BYTE_ORDER == __BIG_ENDIAN
20 #define cpu_to_le32(x) bswap_32(x)
21 #define le32_to_cpu(x) bswap_32(x)
22 #elif __BYTE_ORDER == __LITTLE_ENDIAN
23 #define cpu_to_le32(x) (x)
24 #define le32_to_cpu(x) (x)
26 #error "Unsupported endianness"
29 #define TRX_MAGIC 0x30524448
30 #define TRX_FLAGS_OFFSET 12
31 #define TRX_MAX_PARTS 3
48 enum mode mode
= MODE_UNKNOWN
;
51 size_t trx_offset
= 0;
52 char *partition
[TRX_MAX_PARTS
] = {};
54 /**************************************************
56 **************************************************/
58 uint32_t otrx_crc32(uint8_t *buf
, size_t len
) {
59 static const uint32_t t
[] = {
60 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
61 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
62 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
63 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
64 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
65 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
66 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
67 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
68 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
69 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
70 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
71 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
72 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
73 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
74 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
75 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
76 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
77 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
78 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
79 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
80 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
81 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
82 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
83 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
84 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
85 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
86 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
87 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
88 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
89 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
90 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
91 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
92 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
93 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
94 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
95 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
96 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
97 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
98 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
99 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
100 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
101 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
102 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
103 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
104 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
105 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
106 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
107 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
108 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
109 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
110 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
111 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
112 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
113 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
114 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
115 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
116 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
117 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
118 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
119 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
120 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
121 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
122 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
123 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
125 uint32_t crc
= 0xffffffff;
128 crc
= t
[(crc
^ *buf
) & 0xff] ^ (crc
>> 8);
136 /**************************************************
138 **************************************************/
140 static int otrx_check() {
142 struct trx_header hdr
;
143 size_t bytes
, length
;
148 trx
= fopen(trx_path
, "r");
150 fprintf(stderr
, "Couldn't open %s\n", trx_path
);
155 fseek(trx
, trx_offset
, SEEK_SET
);
156 bytes
= fread(&hdr
, 1, sizeof(hdr
), trx
);
157 if (bytes
!= sizeof(hdr
)) {
158 fprintf(stderr
, "Couldn't read %s header\n", trx_path
);
163 if (le32_to_cpu(hdr
.magic
) != TRX_MAGIC
) {
164 fprintf(stderr
, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr
.magic
));
169 length
= le32_to_cpu(hdr
.length
);
170 buf
= malloc(length
);
172 fprintf(stderr
, "Couldn't alloc %d B buffer\n", length
);
177 fseek(trx
, trx_offset
, SEEK_SET
);
178 bytes
= fread(buf
, 1, length
, trx
);
179 if (bytes
!= length
) {
180 fprintf(stderr
, "Couldn't read %d B of data from %s\n", length
, trx_path
);
185 crc32
= otrx_crc32(buf
+ TRX_FLAGS_OFFSET
, length
- TRX_FLAGS_OFFSET
);
186 if (crc32
!= le32_to_cpu(hdr
.crc32
)) {
187 fprintf(stderr
, "Invalid data crc32: 0x%08x instead of 0x%08x\n", crc32
, le32_to_cpu(hdr
.crc32
));
192 printf("Found a valid TRX version %d\n", le32_to_cpu(hdr
.version
));
202 /**************************************************
204 **************************************************/
206 static int otrx_extract_copy(FILE *trx
, size_t offset
, size_t length
, char *out_path
) {
212 out
= fopen(out_path
, "w");
214 fprintf(stderr
, "Couldn't open %s\n", out_path
);
219 buf
= malloc(length
);
221 fprintf(stderr
, "Couldn't alloc %zu B buffer\n", length
);
226 fseek(trx
, offset
, SEEK_SET
);
227 bytes
= fread(buf
, 1, length
, trx
);
228 if (bytes
!= length
) {
229 fprintf(stderr
, "Couldn't read %zu B of data from %s\n", length
, trx_path
);
234 bytes
= fwrite(buf
, 1, length
, out
);
235 if (bytes
!= length
) {
236 fprintf(stderr
, "Couldn't write %zu B to %s\n", length
, out_path
);
241 printf("Extracted 0x%zx bytes into %s\n", length
, out_path
);
251 static int otrx_extract() {
253 struct trx_header hdr
;
258 trx
= fopen(trx_path
, "r");
260 fprintf(stderr
, "Couldn't open %s\n", trx_path
);
265 fseek(trx
, trx_offset
, SEEK_SET
);
266 bytes
= fread(&hdr
, 1, sizeof(hdr
), trx
);
267 if (bytes
!= sizeof(hdr
)) {
268 fprintf(stderr
, "Couldn't read %s header\n", trx_path
);
273 if (le32_to_cpu(hdr
.magic
) != TRX_MAGIC
) {
274 fprintf(stderr
, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr
.magic
));
279 for (i
= 0; i
< TRX_MAX_PARTS
; i
++) {
284 if (!hdr
.offset
[i
]) {
285 printf("TRX doesn't contain partition %d, can't extract %s\n", i
+ 1, partition
[i
]);
289 if (i
+ 1 >= TRX_MAX_PARTS
|| !hdr
.offset
[i
+ 1])
290 length
= le32_to_cpu(hdr
.length
) - le32_to_cpu(hdr
.offset
[i
]);
292 length
= le32_to_cpu(hdr
.offset
[i
+ 1]) - le32_to_cpu(hdr
.offset
[i
]);
294 otrx_extract_copy(trx
, trx_offset
+ le32_to_cpu(hdr
.offset
[i
]), length
, partition
[i
]);
303 /**************************************************
305 **************************************************/
307 static void parse_options(int argc
, char **argv
) {
310 while ((c
= getopt(argc
, argv
, "c:e:o:1:2:3:")) != -1) {
321 trx_offset
= atoi(optarg
);
324 partition
[0] = optarg
;
327 partition
[1] = optarg
;
330 partition
[2] = optarg
;
336 static void usage() {
339 printf("Checking TRX file:\n");
340 printf("\t-c file\t\tcheck if file is a valid TRX\n");
341 printf("\t-o offset\toffset of TRX data in file (default: 0)\n");
343 printf("Extracting from TRX file:\n");
344 printf("\t-e file\t\tfile with TRX to extract from\n");
345 printf("\t-o offset\toffset of TRX data in file (default: 0)\n");
346 printf("\t-1 file\t\tfile to extract 1st partition to (optional)\n");
347 printf("\t-2 file\t\tfile to extract 2nd partition to (optional)\n");
348 printf("\t-3 file\t\tfile to extract 3rd partition to (optional)\n");
351 int main(int argc
, char **argv
) {
352 parse_options(argc
, argv
);
358 return otrx_extract();