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 if (length < sizeof(hdr)) {
171 fprintf(stderr, "Length read from TRX too low (%zu B)\n", length);
176 buf = malloc(length);
178 fprintf(stderr, "Couldn't alloc %d B buffer\n", length);
183 fseek(trx, trx_offset, SEEK_SET);
184 bytes = fread(buf, 1, length, trx);
185 if (bytes != length) {
186 fprintf(stderr, "Couldn't read %d B of data from %s\n", length, trx_path);
191 crc32 = otrx_crc32(buf + TRX_FLAGS_OFFSET, length - TRX_FLAGS_OFFSET);
192 if (crc32 != le32_to_cpu(hdr.crc32)) {
193 fprintf(stderr, "Invalid data crc32: 0x%08x instead of 0x%08x\n", crc32, le32_to_cpu(hdr.crc32));
198 printf("Found a valid TRX version %d\n", le32_to_cpu(hdr.version));
208 /**************************************************
210 **************************************************/
212 static int otrx_extract_copy(FILE *trx, size_t offset, size_t length, char *out_path) {
218 out = fopen(out_path, "w");
220 fprintf(stderr, "Couldn't open %s\n", out_path);
225 buf = malloc(length);
227 fprintf(stderr, "Couldn't alloc %zu B buffer\n", length);
232 fseek(trx, offset, SEEK_SET);
233 bytes = fread(buf, 1, length, trx);
234 if (bytes != length) {
235 fprintf(stderr, "Couldn't read %zu B of data from %s\n", length, trx_path);
240 bytes = fwrite(buf, 1, length, out);
241 if (bytes != length) {
242 fprintf(stderr, "Couldn't write %zu B to %s\n", length, out_path);
247 printf("Extracted 0x%zx bytes into %s\n", length, out_path);
257 static int otrx_extract() {
259 struct trx_header hdr;
264 trx = fopen(trx_path, "r");
266 fprintf(stderr, "Couldn't open %s\n", trx_path);
271 fseek(trx, trx_offset, SEEK_SET);
272 bytes = fread(&hdr, 1, sizeof(hdr), trx);
273 if (bytes != sizeof(hdr)) {
274 fprintf(stderr, "Couldn't read %s header\n", trx_path);
279 if (le32_to_cpu(hdr.magic) != TRX_MAGIC) {
280 fprintf(stderr, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr.magic));
285 for (i = 0; i < TRX_MAX_PARTS; i++) {
290 if (!hdr.offset[i]) {
291 printf("TRX doesn't contain partition %d, can't extract %s\n", i + 1, partition[i]);
295 if (i + 1 >= TRX_MAX_PARTS || !hdr.offset[i + 1])
296 length = le32_to_cpu(hdr.length) - le32_to_cpu(hdr.offset[i]);
298 length = le32_to_cpu(hdr.offset[i + 1]) - le32_to_cpu(hdr.offset[i]);
300 otrx_extract_copy(trx, trx_offset + le32_to_cpu(hdr.offset[i]), length, partition[i]);
309 /**************************************************
311 **************************************************/
313 static void parse_options(int argc, char **argv) {
316 while ((c = getopt(argc, argv, "c:e:o:1:2:3:")) != -1) {
327 trx_offset = atoi(optarg);
330 partition[0] = optarg;
333 partition[1] = optarg;
336 partition[2] = optarg;
342 static void usage() {
345 printf("Checking TRX file:\n");
346 printf("\t-c file\t\tcheck if file is a valid TRX\n");
347 printf("\t-o offset\toffset of TRX data in file (default: 0)\n");
349 printf("Extracting from TRX file:\n");
350 printf("\t-e file\t\tfile with TRX to extract from\n");
351 printf("\t-o offset\toffset of TRX data in file (default: 0)\n");
352 printf("\t-1 file\t\tfile to extract 1st partition to (optional)\n");
353 printf("\t-2 file\t\tfile to extract 2nd partition to (optional)\n");
354 printf("\t-3 file\t\tfile to extract 3rd partition to (optional)\n");
357 int main(int argc, char **argv) {
358 parse_options(argc, argv);
364 return otrx_extract();