b3cfdfe55bc9b3eda0fa6b67ea13c2d194ef2904
[openwrt/staging/yousong.git] / package / utils / otrx / src / otrx.c
1 /*
2 * otrx
3 *
4 * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
5 *
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)
9 * any later version.
10 */
11
12 #include <errno.h>
13 #include <stdint.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17
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)
24 #else
25 #error "Unsupported endianness"
26 #endif
27
28 #define TRX_MAGIC 0x30524448
29 #define TRX_FLAGS_OFFSET 12
30
31 struct trx_header {
32 uint32_t magic;
33 uint32_t length;
34 uint32_t crc32;
35 uint16_t flags;
36 uint16_t version;
37 uint32_t offset[3];
38 };
39
40 enum mode {
41 MODE_UNKNOWN,
42 MODE_CHECK,
43 };
44
45 enum mode mode = MODE_UNKNOWN;
46
47 char *trx_path;
48 size_t trx_offset = 0;
49
50 /**************************************************
51 * CRC32
52 **************************************************/
53
54 uint32_t otrx_crc32(uint8_t *buf, size_t len) {
55 static const uint32_t t[] = {
56 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
57 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
58 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
59 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
60 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
61 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
62 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
63 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
64 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
65 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
66 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
67 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
68 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
69 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
70 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
71 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
72 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
73 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
74 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
75 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
76 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
77 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
78 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
79 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
80 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
81 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
82 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
83 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
84 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
85 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
86 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
87 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
88 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
89 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
90 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
91 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
92 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
93 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
94 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
95 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
96 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
97 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
98 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
99 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
100 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
101 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
102 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
103 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
104 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
105 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
106 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
107 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
108 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
109 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
110 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
111 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
112 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
113 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
114 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
115 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
116 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
117 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
118 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
119 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
120 };
121 uint32_t crc = 0xffffffff;
122
123 while (len) {
124 crc = t[(crc ^ *buf) & 0xff] ^ (crc >> 8);
125 buf++;
126 len--;
127 }
128
129 return crc;
130 }
131
132 /**************************************************
133 * Check
134 **************************************************/
135
136 static int otrx_check() {
137 FILE *trx;
138 struct trx_header hdr;
139 size_t bytes, length;
140 uint8_t *buf;
141 uint32_t crc32;
142 int err = 0;
143
144 trx = fopen(trx_path, "r");
145 if (!trx) {
146 fprintf(stderr, "Couldn't open %s\n", trx_path);
147 err = -EACCES;
148 goto out;
149 }
150
151 fseek(trx, trx_offset, SEEK_SET);
152 bytes = fread(&hdr, 1, sizeof(hdr), trx);
153 if (bytes != sizeof(hdr)) {
154 fprintf(stderr, "Couldn't read %s header\n", trx_path);
155 err = -EIO;
156 goto err_close;
157 }
158
159 if (le32_to_cpu(hdr.magic) != TRX_MAGIC) {
160 fprintf(stderr, "Invalid TRX magic: 0x%08x\n", le32_to_cpu(hdr.magic));
161 err = -EINVAL;
162 goto err_close;
163 }
164
165 length = le32_to_cpu(hdr.length);
166 buf = malloc(length);
167 if (!buf) {
168 fprintf(stderr, "Couldn't alloc %d B buffer\n", length);
169 err = -ENOMEM;
170 goto err_close;
171 }
172
173 fseek(trx, trx_offset, SEEK_SET);
174 bytes = fread(buf, 1, length, trx);
175 if (bytes != length) {
176 fprintf(stderr, "Couldn't read %d B of data from %s\n", length, trx_path);
177 err = -ENOMEM;
178 goto err_free_buf;
179 }
180
181 crc32 = otrx_crc32(buf + TRX_FLAGS_OFFSET, length - TRX_FLAGS_OFFSET);
182 if (crc32 != le32_to_cpu(hdr.crc32)) {
183 fprintf(stderr, "Invalid data crc32: 0x%08x instead of 0x%08x\n", crc32, le32_to_cpu(hdr.crc32));
184 err = -EINVAL;
185 goto err_free_buf;
186 }
187
188 printf("Found a valid TRX version %d\n", le32_to_cpu(hdr.version));
189
190 err_free_buf:
191 free(buf);
192 err_close:
193 fclose(trx);
194 out:
195 return err;
196 }
197
198 /**************************************************
199 * Start
200 **************************************************/
201
202 static void parse_options(int argc, char **argv) {
203 int c;
204
205 while ((c = getopt(argc, argv, "c:o:")) != -1) {
206 switch (c) {
207 case 'c':
208 mode = MODE_CHECK;
209 trx_path = optarg;
210 break;
211 case 'o':
212 trx_offset = atoi(optarg);
213 break;
214 }
215 }
216 }
217
218 static void usage() {
219 printf("Usage:\n");
220 printf("\n");
221 printf("Checking TRX file:\n");
222 printf("\t-c file\t\tcheck if file is a valid TRX\n");
223 printf("\t-o offset\toffset of TRX data in file (default: 0)\n");
224 }
225
226 int main(int argc, char **argv) {
227 parse_options(argc, argv);
228
229 switch (mode) {
230 case MODE_CHECK:
231 return otrx_check();
232 default:
233 usage();
234 }
235
236 return 0;
237 }