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