• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/firmware-utils/src/otrx.c

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * otrx
  4  *
  5  * Copyright (C) 2015-2017 Rafał Miłecki <zajec5@gmail.com>
  6  */
  7 
  8 #include <byteswap.h>
  9 #include <endian.h>
 10 #include <errno.h>
 11 #include <stdint.h>
 12 #include <stdio.h>
 13 #include <stdlib.h>
 14 #include <string.h>
 15 #include <sys/stat.h>
 16 #include <unistd.h>
 17 
 18 #if !defined(__BYTE_ORDER)
 19 #error "Unknown byte order"
 20 #endif
 21 
 22 #if __BYTE_ORDER == __BIG_ENDIAN
 23 #define cpu_to_le32(x)  bswap_32(x)
 24 #define le32_to_cpu(x)  bswap_32(x)
 25 #elif __BYTE_ORDER == __LITTLE_ENDIAN
 26 #define cpu_to_le32(x)  (x)
 27 #define le32_to_cpu(x)  (x)
 28 #else
 29 #error "Unsupported endianness"
 30 #endif
 31 
 32 #define TRX_MAGIC                       0x30524448
 33 #define TRX_FLAGS_OFFSET                12
 34 #define TRX_MAX_PARTS                   3
 35 
 36 struct trx_header {
 37         uint32_t magic;
 38         uint32_t length;
 39         uint32_t crc32;
 40         uint16_t flags;
 41         uint16_t version;
 42         uint32_t offset[3];
 43 };
 44 
 45 struct otrx_part {
 46         int idx;
 47         size_t offset;
 48         size_t length;
 49 };
 50 
 51 struct otrx_ctx {
 52         FILE *fp;
 53         struct trx_header hdr;
 54         struct otrx_part parts[TRX_MAX_PARTS];          /* Sorted partitions */
 55 };
 56 
 57 char *trx_path;
 58 size_t trx_offset = 0;
 59 char *partition[TRX_MAX_PARTS] = {};
 60 
 61 static inline size_t otrx_min(size_t x, size_t y) {
 62         return x < y ? x : y;
 63 }
 64 
 65 /**************************************************
 66  * CRC32
 67  **************************************************/
 68 
 69 static const uint32_t crc32_tbl[] = {
 70         0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
 71         0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
 72         0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
 73         0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
 74         0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
 75         0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
 76         0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
 77         0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
 78         0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
 79         0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
 80         0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
 81         0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
 82         0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
 83         0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
 84         0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
 85         0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
 86         0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
 87         0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
 88         0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
 89         0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
 90         0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
 91         0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
 92         0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
 93         0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
 94         0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
 95         0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
 96         0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
 97         0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
 98         0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
 99         0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
100         0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
101         0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
102         0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
103         0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
104         0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
105         0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
106         0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
107         0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
108         0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
109         0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
110         0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
111         0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
112         0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
113         0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
114         0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
115         0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
116         0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
117         0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
118         0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
119         0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
120         0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
121         0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
122         0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
123         0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
124         0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
125         0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
126         0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
127         0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
128         0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
129         0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
130         0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
131         0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
132         0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
133         0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
134 };
135 
136 uint32_t otrx_crc32(uint32_t crc, uint8_t *buf, size_t len) {
137         while (len) {
138                 crc = crc32_tbl[(crc ^ *buf) & 0xff] ^ (crc >> 8);
139                 buf++;
140                 len--;
141         }
142 
143         return crc;
144 }
145 
146 /**************************************************
147  * Helpers
148  **************************************************/
149 
150 static FILE *otrx_open(const char *pathname, const char *mode) {
151         if (strcmp(pathname, "-"))
152                 return fopen(pathname, mode);
153 
154         if (isatty(fileno(stdin))) {
155                 fprintf(stderr, "Reading from TTY stdin is unsupported\n");
156                 return NULL;
157         }
158 
159         return stdin;
160 }
161 
162 static int otrx_skip(FILE *fp, size_t length)
163 {
164         if (fseek(fp, length, SEEK_CUR)) {
165                 uint8_t buf[1024];
166                 size_t bytes;
167 
168                 do {
169                         bytes = fread(buf, 1, otrx_min(sizeof(buf), length), fp);
170                         if (bytes <= 0)
171                                 return -EIO;
172                         length -= bytes;
173                 } while (length);
174         }
175 
176         return 0;
177 }
178 
179 static void otrx_close(FILE *fp) {
180         if (fp != stdin)
181                 fclose(fp);
182 }
183 
184 static int otrx_part_compar(const void *a, const void *b)
185 {
186         const struct otrx_part *partA = a;
187         const struct otrx_part *partB = b;
188 
189         if (!partA->offset)
190                 return 1;
191         if (!partB->offset)
192                 return -1;
193 
194         return partA->offset - partB->offset;
195 }
196 
197 static int otrx_open_parse(const char *pathname, const char *mode,
198                            struct otrx_ctx *otrx)
199 {
200         size_t length;
201         size_t bytes;
202         int err;
203         int i;
204 
205         otrx->fp = otrx_open(pathname, mode);
206         if (!otrx->fp) {
207                 fprintf(stderr, "Couldn't open %s\n", pathname);
208                 err = -EACCES;
209                 goto err_out;
210         }
211 
212         if (trx_offset && otrx_skip(otrx->fp, trx_offset)) {
213                 fprintf(stderr, "Couldn't skip first %zd B\n", trx_offset);
214                 err = -EIO;
215                 goto err_close;
216         }
217 
218         bytes = fread(&otrx->hdr, 1, sizeof(otrx->hdr), otrx->fp);
219         if (bytes != sizeof(otrx->hdr)) {
220                 fprintf(stderr, "Couldn't read %s header\n", pathname);
221                 err = -EIO;
222                 goto err_close;
223         }
224 
225         if (le32_to_cpu(otrx->hdr.magic) != TRX_MAGIC) {
226                 fprintf(stderr, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(otrx->hdr.magic));
227                 err =  -EINVAL;
228                 goto err_close;
229         }
230 
231         length = le32_to_cpu(otrx->hdr.length);
232         if (length < sizeof(otrx->hdr)) {
233                 fprintf(stderr, "Length read from TRX too low (%zu B)\n", length);
234                 err = -EINVAL;
235                 goto err_close;
236         }
237 
238         for (i = 0; i < TRX_MAX_PARTS; i++) {
239                 otrx->parts[i].idx = i;
240                 otrx->parts[i].offset = le32_to_cpu(otrx->hdr.offset[i]);
241         }
242         qsort(otrx->parts, TRX_MAX_PARTS, sizeof(otrx->parts[0]), otrx_part_compar);
243 
244         /* Calculate length of every partition */
245         for (i = 0; i < TRX_MAX_PARTS; i++) {
246                 if (otrx->parts[i].offset) {
247                         if (i + 1 >= TRX_MAX_PARTS || !otrx->parts[i + 1].offset)
248                                 otrx->parts[i].length = le32_to_cpu(otrx->hdr.length) - otrx->parts[i].offset;
249                         else
250                                 otrx->parts[i].length = otrx->parts[i + 1].offset - otrx->parts[i].offset;
251                 }
252         }
253 
254         return 0;
255 
256 err_close:
257         otrx_close(otrx->fp);
258 err_out:
259         return err;
260 }
261 
262 /**************************************************
263  * Check
264  **************************************************/
265 
266 static void otrx_check_parse_options(int argc, char **argv) {
267         int c;
268 
269         while ((c = getopt(argc, argv, "o:")) != -1) {
270                 switch (c) {
271                 case 'o':
272                         trx_offset = atoi(optarg);
273                         break;
274                 }
275         }
276 }
277 
278 static int otrx_check(int argc, char **argv) {
279         struct otrx_ctx otrx = { };
280         size_t bytes, length;
281         uint8_t buf[1024];
282         uint32_t crc32;
283         int err = 0;
284 
285         if (argc < 3) {
286                 fprintf(stderr, "No TRX file passed\n");
287                 err = -EINVAL;
288                 goto out;
289         }
290         trx_path = argv[2];
291 
292         optind = 3;
293         otrx_check_parse_options(argc, argv);
294 
295         err = otrx_open_parse(trx_path, "r", &otrx);
296         if (err) {
297                 fprintf(stderr, "Couldn't open & parse %s: %d\n", trx_path, err);
298                 err = -EACCES;
299                 goto out;
300         }
301 
302         crc32 = 0xffffffff;
303         crc32 = otrx_crc32(crc32, (uint8_t *)&otrx.hdr + TRX_FLAGS_OFFSET, sizeof(otrx.hdr) - TRX_FLAGS_OFFSET);
304         length = le32_to_cpu(otrx.hdr.length) - sizeof(otrx.hdr);
305         while ((bytes = fread(buf, 1, otrx_min(sizeof(buf), length), otrx.fp)) > 0) {
306                 crc32 = otrx_crc32(crc32, buf, bytes);
307                 length -= bytes;
308         }
309 
310         if (length) {
311                 fprintf(stderr, "Couldn't read last %zd B of data from %s\n", length, trx_path);
312                 err = -EIO;
313                 goto err_close;
314         }
315 
316         if (crc32 != le32_to_cpu(otrx.hdr.crc32)) {
317                 fprintf(stderr, "Invalid data crc32: 0x%08x instead of 0x%08x\n", crc32, le32_to_cpu(otrx.hdr.crc32));
318                 err =  -EINVAL;
319                 goto err_close;
320         }
321 
322         printf("Found a valid TRX version %d\n", le32_to_cpu(otrx.hdr.version));
323 
324 err_close:
325         otrx_close(otrx.fp);
326 out:
327         return err;
328 }
329 
330 /**************************************************
331  * Create
332  **************************************************/
333 
334 static ssize_t otrx_create_append_file(FILE *trx, const char *in_path) {
335         FILE *in;
336         size_t bytes;
337         ssize_t length = 0;
338         uint8_t buf[1024];
339 
340         in = fopen(in_path, "r");
341         if (!in) {
342                 fprintf(stderr, "Couldn't open %s\n", in_path);
343                 return -EACCES;
344         }
345 
346         while ((bytes = fread(buf, 1, sizeof(buf), in)) > 0) {
347                 if (fwrite(buf, 1, bytes, trx) != bytes) {
348                         fprintf(stderr, "Couldn't write %zu B to %s\n", bytes, trx_path);
349                         length = -EIO;
350                         break;
351                 }
352                 length += bytes;
353         }
354 
355         fclose(in);
356 
357         return length;
358 }
359 
360 static ssize_t otrx_create_append_zeros(FILE *trx, size_t length) {
361         uint8_t *buf;
362 
363         buf = malloc(length);
364         if (!buf)
365                 return -ENOMEM;
366         memset(buf, 0, length);
367 
368         if (fwrite(buf, 1, length, trx) != length) {
369                 fprintf(stderr, "Couldn't write %zu B to %s\n", length, trx_path);
370                 free(buf);
371                 return -EIO;
372         }
373 
374         free(buf);
375 
376         return length;
377 }
378 
379 static ssize_t otrx_create_align(FILE *trx, size_t curr_offset, size_t alignment) {
380         if (curr_offset & (alignment - 1)) {
381                 size_t length = alignment - (curr_offset % alignment);
382                 return otrx_create_append_zeros(trx, length);
383         }
384 
385         return 0;
386 }
387 
388 static int otrx_create_write_hdr(FILE *trx, struct trx_header *hdr) {
389         size_t bytes, length;
390         uint8_t buf[1024];
391         uint32_t crc32;
392 
393         hdr->version = 1;
394 
395         fseek(trx, 0, SEEK_SET);
396         bytes = fwrite(hdr, 1, sizeof(struct trx_header), trx);
397         if (bytes != sizeof(struct trx_header)) {
398                 fprintf(stderr, "Couldn't write TRX header to %s\n", trx_path);
399                 return -EIO;
400         }
401 
402         length = le32_to_cpu(hdr->length);
403 
404         crc32 = 0xffffffff;
405         fseek(trx, TRX_FLAGS_OFFSET, SEEK_SET);
406         length -= TRX_FLAGS_OFFSET;
407         while ((bytes = fread(buf, 1, otrx_min(sizeof(buf), length), trx)) > 0) {
408                 crc32 = otrx_crc32(crc32, buf, bytes);
409                 length -= bytes;
410         }
411         hdr->crc32 = cpu_to_le32(crc32);
412 
413         fseek(trx, 0, SEEK_SET);
414         bytes = fwrite(hdr, 1, sizeof(struct trx_header), trx);
415         if (bytes != sizeof(struct trx_header)) {
416                 fprintf(stderr, "Couldn't write TRX header to %s\n", trx_path);
417                 return -EIO;
418         }
419 
420         return 0;
421 }
422 
423 static int otrx_create(int argc, char **argv) {
424         FILE *trx;
425         struct trx_header hdr = {};
426         ssize_t sbytes;
427         size_t curr_idx = 0;
428         size_t curr_offset = sizeof(hdr);
429         char *e;
430         uint32_t magic;
431         int c;
432         int err = 0;
433 
434         hdr.magic = cpu_to_le32(TRX_MAGIC);
435 
436         if (argc < 3) {
437                 fprintf(stderr, "No TRX file passed\n");
438                 err = -EINVAL;
439                 goto out;
440         }
441         trx_path = argv[2];
442 
443         trx = fopen(trx_path, "w+");
444         if (!trx) {
445                 fprintf(stderr, "Couldn't open %s\n", trx_path);
446                 err = -EACCES;
447                 goto out;
448         }
449         fseek(trx, curr_offset, SEEK_SET);
450 
451         optind = 3;
452         while ((c = getopt(argc, argv, "f:A:a:b:M:")) != -1) {
453                 switch (c) {
454                 case 'f':
455                         if (curr_idx >= TRX_MAX_PARTS) {
456                                 err = -ENOSPC;
457                                 fprintf(stderr, "Reached TRX partitions limit, no place for %s\n", optarg);
458                                 goto err_close;
459                         }
460 
461                         sbytes = otrx_create_append_file(trx, optarg);
462                         if (sbytes < 0) {
463                                 fprintf(stderr, "Failed to append file %s\n", optarg);
464                         } else {
465                                 hdr.offset[curr_idx++] = curr_offset;
466                                 curr_offset += sbytes;
467                         }
468 
469                         sbytes = otrx_create_align(trx, curr_offset, 4);
470                         if (sbytes < 0)
471                                 fprintf(stderr, "Failed to append zeros\n");
472                         else
473                                 curr_offset += sbytes;
474 
475                         break;
476                 case 'A':
477                         sbytes = otrx_create_append_file(trx, optarg);
478                         if (sbytes < 0) {
479                                 fprintf(stderr, "Failed to append file %s\n", optarg);
480                         } else {
481                                 curr_offset += sbytes;
482                         }
483 
484                         sbytes = otrx_create_align(trx, curr_offset, 4);
485                         if (sbytes < 0)
486                                 fprintf(stderr, "Failed to append zeros\n");
487                         else
488                                 curr_offset += sbytes;
489                         break;
490                 case 'a':
491                         sbytes = otrx_create_align(trx, curr_offset, strtol(optarg, NULL, 0));
492                         if (sbytes < 0)
493                                 fprintf(stderr, "Failed to append zeros\n");
494                         else
495                                 curr_offset += sbytes;
496                         break;
497                 case 'b':
498                         sbytes = strtol(optarg, NULL, 0) - curr_offset;
499                         if (sbytes < 0) {
500                                 fprintf(stderr, "Current TRX length is 0x%zx, can't pad it with zeros to 0x%lx\n", curr_offset, strtol(optarg, NULL, 0));
501                         } else {
502                                 sbytes = otrx_create_append_zeros(trx, sbytes);
503                                 if (sbytes < 0)
504                                         fprintf(stderr, "Failed to append zeros\n");
505                                 else
506                                         curr_offset += sbytes;
507                         }
508                         break;
509                 case 'M':
510                         errno = 0;
511                         magic = strtoul(optarg, &e, 0);
512                         if (errno || (e == optarg) || *e)
513                                 fprintf(stderr, "illegal magic string %s\n", optarg);
514                         else
515                                 hdr.magic = cpu_to_le32(magic);
516                         break;
517                 }
518                 if (err)
519                         break;
520         }
521 
522         sbytes = otrx_create_align(trx, curr_offset, 0x1000);
523         if (sbytes < 0)
524                 fprintf(stderr, "Failed to append zeros\n");
525         else
526                 curr_offset += sbytes;
527 
528         hdr.length = curr_offset;
529         otrx_create_write_hdr(trx, &hdr);
530 err_close:
531         fclose(trx);
532 out:
533         return err;
534 }
535 
536 /**************************************************
537  * Extract
538  **************************************************/
539 
540 static void otrx_extract_parse_options(int argc, char **argv) {
541         int c;
542 
543         while ((c = getopt(argc, argv, "c:e:o:1:2:3:")) != -1) {
544                 switch (c) {
545                 case 'o':
546                         trx_offset = atoi(optarg);
547                         break;
548                 case '1':
549                         partition[0] = optarg;
550                         break;
551                 case '2':
552                         partition[1] = optarg;
553                         break;
554                 case '3':
555                         partition[2] = optarg;
556                         break;
557                 }
558         }
559 }
560 
561 static int otrx_extract_copy(struct otrx_ctx *otrx, size_t length, char *out_path) {
562         FILE *out;
563         size_t bytes;
564         uint8_t *buf;
565         int err = 0;
566 
567         out = fopen(out_path, "w");
568         if (!out) {
569                 fprintf(stderr, "Couldn't open %s\n", out_path);
570                 err = -EACCES;
571                 goto out;
572         }
573 
574         buf = malloc(length);
575         if (!buf) {
576                 fprintf(stderr, "Couldn't alloc %zu B buffer\n", length);
577                 err =  -ENOMEM;
578                 goto err_close;
579         }
580 
581         bytes = fread(buf, 1, length, otrx->fp);
582         if (bytes != length) {
583                 fprintf(stderr, "Couldn't read %zu B of data from %s\n", length, trx_path);
584                 err =  -ENOMEM;
585                 goto err_free_buf;
586         };
587 
588         bytes = fwrite(buf, 1, length, out);
589         if (bytes != length) {
590                 fprintf(stderr, "Couldn't write %zu B to %s\n", length, out_path);
591                 err =  -ENOMEM;
592                 goto err_free_buf;
593         }
594 
595         printf("Extracted 0x%zx bytes into %s\n", length, out_path);
596 
597 err_free_buf:
598         free(buf);
599 err_close:
600         fclose(out);
601 out:
602         return err;
603 }
604 
605 static int otrx_extract(int argc, char **argv) {
606         struct otrx_ctx otrx = { };
607         int i;
608         int err = 0;
609 
610         if (argc < 3) {
611                 fprintf(stderr, "No TRX file passed\n");
612                 err = -EINVAL;
613                 goto err_out;
614         }
615         trx_path = argv[2];
616 
617         optind = 3;
618         otrx_extract_parse_options(argc, argv);
619 
620         err = otrx_open_parse(trx_path, "r", &otrx);
621         if (err) {
622                 fprintf(stderr, "Couldn't open & parse %s: %d\n", trx_path, err);
623                 err = -EACCES;
624                 goto err_out;
625         }
626 
627         for (i = 0; i < TRX_MAX_PARTS; i++) {
628                 struct otrx_part *part = &otrx.parts[i];
629 
630                 if (!part->offset && partition[part->idx])
631                         printf("TRX doesn't contain partition %d, can't extract %s\n", part->idx + 1, partition[part->idx]);
632                 if (!part->offset || !partition[part->idx])
633                         otrx_skip(otrx.fp, part->length);
634                 else
635                         otrx_extract_copy(&otrx, part->length, partition[part->idx]);
636         }
637 
638         otrx_close(otrx.fp);
639 err_out:
640         return err;
641 }
642 
643 /**************************************************
644  * Start
645  **************************************************/
646 
647 static void usage() {
648         printf("Usage:\n");
649         printf("\n");
650         printf("Checking TRX file:\n");
651         printf("\totrx check <file> [options]\tcheck if file is a valid TRX\n");
652         printf("\t-o offset\t\t\toffset of TRX data in file (default: 0)\n");
653         printf("\n");
654         printf("Creating new TRX file:\n");
655         printf("\totrx create <file> [options] [partitions]\n");
656         printf("\t-f file\t\t\t\t[partition] start new partition with content copied from file\n");
657         printf("\t-A file\t\t\t\t[partition] append current partition with content copied from file\n");
658         printf("\t-a alignment\t\t\t[partition] align current partition\n");
659         printf("\t-b offset\t\t\t[partition] append zeros to partition till reaching absolute offset\n");
660         printf("\n");
661         printf("Extracting from TRX file:\n");
662         printf("\totrx extract <file> [options]\textract partitions from TRX file\n");
663         printf("\t-o offset\t\t\toffset of TRX data in file (default: 0)\n");
664         printf("\t-1 file\t\t\t\tfile to extract 1st partition to (optional)\n");
665         printf("\t-2 file\t\t\t\tfile to extract 2nd partition to (optional)\n");
666         printf("\t-3 file\t\t\t\tfile to extract 3rd partition to (optional)\n");
667 }
668 
669 int main(int argc, char **argv) {
670         if (argc > 1) {
671                 if (!strcmp(argv[1], "check"))
672                         return otrx_check(argc, argv);
673                 else if (!strcmp(argv[1], "create"))
674                         return otrx_create(argc, argv);
675                 else if (!strcmp(argv[1], "extract"))
676                         return otrx_extract(argc, argv);
677         }
678 
679         usage();
680         return 0;
681 }
682 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt