1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
4 */
5
6 #include <errno.h>
7 #include <memory.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <stdbool.h>
12 #include <sys/stat.h>
13 #include <time.h>
14
15 /**
16 * \brief SHA-1 context structure
17 */
18 typedef struct
19 {
20 unsigned long total[2]; /*!< number of bytes processed */
21 unsigned long state[5]; /*!< intermediate digest state */
22 unsigned char buffer[64]; /*!< data block being processed */
23 }
24 sha1_context;
25
26 /*
27 * 32-bit integer manipulation macros (big endian)
28 */
29 #ifndef GET_UINT32_BE
30 #define GET_UINT32_BE(n,b,i) { \
31 (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
32 | ( (unsigned long) (b)[(i) + 1] << 16 ) \
33 | ( (unsigned long) (b)[(i) + 2] << 8 ) \
34 | ( (unsigned long) (b)[(i) + 3] ); \
35 }
36 #endif
37 #ifndef PUT_UINT32_BE
38 #define PUT_UINT32_BE(n,b,i) { \
39 (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
40 (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
41 (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
42 (b)[(i) + 3] = (unsigned char) ( (n) ); \
43 }
44 #endif
45
46 /*
47 * SHA-1 context setup
48 */
49 static
sha1_starts(sha1_context * ctx)50 void sha1_starts (sha1_context * ctx)
51 {
52 ctx->total[0] = 0;
53 ctx->total[1] = 0;
54
55 ctx->state[0] = 0x67452301;
56 ctx->state[1] = 0xEFCDAB89;
57 ctx->state[2] = 0x98BADCFE;
58 ctx->state[3] = 0x10325476;
59 ctx->state[4] = 0xC3D2E1F0;
60 }
61
sha1_process(sha1_context *ctx, const unsigned char data[64])62 static void sha1_process(sha1_context *ctx, const unsigned char data[64])
63 {
64 unsigned long temp, W[16], A, B, C, D, E;
65
66 GET_UINT32_BE (W[0], data, 0);
67 GET_UINT32_BE (W[1], data, 4);
68 GET_UINT32_BE (W[2], data, 8);
69 GET_UINT32_BE (W[3], data, 12);
70 GET_UINT32_BE (W[4], data, 16);
71 GET_UINT32_BE (W[5], data, 20);
72 GET_UINT32_BE (W[6], data, 24);
73 GET_UINT32_BE (W[7], data, 28);
74 GET_UINT32_BE (W[8], data, 32);
75 GET_UINT32_BE (W[9], data, 36);
76 GET_UINT32_BE (W[10], data, 40);
77 GET_UINT32_BE (W[11], data, 44);
78 GET_UINT32_BE (W[12], data, 48);
79 GET_UINT32_BE (W[13], data, 52);
80 GET_UINT32_BE (W[14], data, 56);
81 GET_UINT32_BE (W[15], data, 60);
82
83 #define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
84
85 #define R(t) ( \
86 temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
87 W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
88 ( W[t & 0x0F] = S(temp,1) ) \
89 )
90
91 #define P(a,b,c,d,e,x) { \
92 e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
93 }
94
95 A = ctx->state[0];
96 B = ctx->state[1];
97 C = ctx->state[2];
98 D = ctx->state[3];
99 E = ctx->state[4];
100
101 #define F(x,y,z) (z ^ (x & (y ^ z)))
102 #define K 0x5A827999
103
104 P (A, B, C, D, E, W[0]);
105 P (E, A, B, C, D, W[1]);
106 P (D, E, A, B, C, W[2]);
107 P (C, D, E, A, B, W[3]);
108 P (B, C, D, E, A, W[4]);
109 P (A, B, C, D, E, W[5]);
110 P (E, A, B, C, D, W[6]);
111 P (D, E, A, B, C, W[7]);
112 P (C, D, E, A, B, W[8]);
113 P (B, C, D, E, A, W[9]);
114 P (A, B, C, D, E, W[10]);
115 P (E, A, B, C, D, W[11]);
116 P (D, E, A, B, C, W[12]);
117 P (C, D, E, A, B, W[13]);
118 P (B, C, D, E, A, W[14]);
119 P (A, B, C, D, E, W[15]);
120 P (E, A, B, C, D, R (16));
121 P (D, E, A, B, C, R (17));
122 P (C, D, E, A, B, R (18));
123 P (B, C, D, E, A, R (19));
124
125 #undef K
126 #undef F
127
128 #define F(x,y,z) (x ^ y ^ z)
129 #define K 0x6ED9EBA1
130
131 P (A, B, C, D, E, R (20));
132 P (E, A, B, C, D, R (21));
133 P (D, E, A, B, C, R (22));
134 P (C, D, E, A, B, R (23));
135 P (B, C, D, E, A, R (24));
136 P (A, B, C, D, E, R (25));
137 P (E, A, B, C, D, R (26));
138 P (D, E, A, B, C, R (27));
139 P (C, D, E, A, B, R (28));
140 P (B, C, D, E, A, R (29));
141 P (A, B, C, D, E, R (30));
142 P (E, A, B, C, D, R (31));
143 P (D, E, A, B, C, R (32));
144 P (C, D, E, A, B, R (33));
145 P (B, C, D, E, A, R (34));
146 P (A, B, C, D, E, R (35));
147 P (E, A, B, C, D, R (36));
148 P (D, E, A, B, C, R (37));
149 P (C, D, E, A, B, R (38));
150 P (B, C, D, E, A, R (39));
151
152 #undef K
153 #undef F
154
155 #define F(x,y,z) ((x & y) | (z & (x | y)))
156 #define K 0x8F1BBCDC
157
158 P (A, B, C, D, E, R (40));
159 P (E, A, B, C, D, R (41));
160 P (D, E, A, B, C, R (42));
161 P (C, D, E, A, B, R (43));
162 P (B, C, D, E, A, R (44));
163 P (A, B, C, D, E, R (45));
164 P (E, A, B, C, D, R (46));
165 P (D, E, A, B, C, R (47));
166 P (C, D, E, A, B, R (48));
167 P (B, C, D, E, A, R (49));
168 P (A, B, C, D, E, R (50));
169 P (E, A, B, C, D, R (51));
170 P (D, E, A, B, C, R (52));
171 P (C, D, E, A, B, R (53));
172 P (B, C, D, E, A, R (54));
173 P (A, B, C, D, E, R (55));
174 P (E, A, B, C, D, R (56));
175 P (D, E, A, B, C, R (57));
176 P (C, D, E, A, B, R (58));
177 P (B, C, D, E, A, R (59));
178
179 #undef K
180 #undef F
181
182 #define F(x,y,z) (x ^ y ^ z)
183 #define K 0xCA62C1D6
184
185 P (A, B, C, D, E, R (60));
186 P (E, A, B, C, D, R (61));
187 P (D, E, A, B, C, R (62));
188 P (C, D, E, A, B, R (63));
189 P (B, C, D, E, A, R (64));
190 P (A, B, C, D, E, R (65));
191 P (E, A, B, C, D, R (66));
192 P (D, E, A, B, C, R (67));
193 P (C, D, E, A, B, R (68));
194 P (B, C, D, E, A, R (69));
195 P (A, B, C, D, E, R (70));
196 P (E, A, B, C, D, R (71));
197 P (D, E, A, B, C, R (72));
198 P (C, D, E, A, B, R (73));
199 P (B, C, D, E, A, R (74));
200 P (A, B, C, D, E, R (75));
201 P (E, A, B, C, D, R (76));
202 P (D, E, A, B, C, R (77));
203 P (C, D, E, A, B, R (78));
204 P (B, C, D, E, A, R (79));
205
206 #undef K
207 #undef F
208
209 ctx->state[0] += A;
210 ctx->state[1] += B;
211 ctx->state[2] += C;
212 ctx->state[3] += D;
213 ctx->state[4] += E;
214 }
215
216 #undef P
217 #undef R
218 #undef S
219
220 /*
221 * SHA-1 process buffer
222 */
223 static
sha1_update(sha1_context *ctx, const unsigned char *input, unsigned int ilen)224 void sha1_update(sha1_context *ctx, const unsigned char *input,
225 unsigned int ilen)
226 {
227 int fill;
228 unsigned long left;
229
230 if (ilen <= 0)
231 return;
232
233 left = ctx->total[0] & 0x3F;
234 fill = 64 - left;
235
236 ctx->total[0] += ilen;
237 ctx->total[0] &= 0xFFFFFFFF;
238
239 if (ctx->total[0] < (unsigned long) ilen)
240 ctx->total[1]++;
241
242 if (left && ilen >= fill) {
243 memcpy ((void *) (ctx->buffer + left), (void *) input, fill);
244 sha1_process (ctx, ctx->buffer);
245 input += fill;
246 ilen -= fill;
247 left = 0;
248 }
249
250 while (ilen >= 64) {
251 sha1_process (ctx, input);
252 input += 64;
253 ilen -= 64;
254 }
255
256 if (ilen > 0) {
257 memcpy ((void *) (ctx->buffer + left), (void *) input, ilen);
258 }
259 }
260
261 static const unsigned char sha1_padding[64] = {
262 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
263 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
264 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
265 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
266 };
267
268 /*
269 * SHA-1 final digest
270 */
271 static
sha1_finish(sha1_context * ctx, unsigned char output[20])272 void sha1_finish (sha1_context * ctx, unsigned char output[20])
273 {
274 unsigned long last, padn;
275 unsigned long high, low;
276 unsigned char msglen[8];
277
278 high = (ctx->total[0] >> 29)
279 | (ctx->total[1] << 3);
280 low = (ctx->total[0] << 3);
281
282 PUT_UINT32_BE (high, msglen, 0);
283 PUT_UINT32_BE (low, msglen, 4);
284
285 last = ctx->total[0] & 0x3F;
286 padn = (last < 56) ? (56 - last) : (120 - last);
287
288 sha1_update (ctx, (unsigned char *) sha1_padding, padn);
289 sha1_update (ctx, msglen, 8);
290
291 PUT_UINT32_BE (ctx->state[0], output, 0);
292 PUT_UINT32_BE (ctx->state[1], output, 4);
293 PUT_UINT32_BE (ctx->state[2], output, 8);
294 PUT_UINT32_BE (ctx->state[3], output, 12);
295 PUT_UINT32_BE (ctx->state[4], output, 16);
296 }
297
298 /*
299 * Output = SHA-1( input buffer )
300 */
301 static
sha1_csum(const unsigned char *input, unsigned int ilen, unsigned char *output)302 void sha1_csum(const unsigned char *input, unsigned int ilen,
303 unsigned char *output)
304 {
305 sha1_context ctx;
306
307 sha1_starts (&ctx);
308 sha1_update (&ctx, input, ilen);
309 sha1_finish (&ctx, output);
310 }
311
312 typedef struct {
313 uint32_t total[2];
314 uint32_t state[8];
315 uint8_t buffer[64];
316 } sha256_context;
317
318 static
sha256_starts(sha256_context * ctx)319 void sha256_starts(sha256_context * ctx)
320 {
321 ctx->total[0] = 0;
322 ctx->total[1] = 0;
323
324 ctx->state[0] = 0x6A09E667;
325 ctx->state[1] = 0xBB67AE85;
326 ctx->state[2] = 0x3C6EF372;
327 ctx->state[3] = 0xA54FF53A;
328 ctx->state[4] = 0x510E527F;
329 ctx->state[5] = 0x9B05688C;
330 ctx->state[6] = 0x1F83D9AB;
331 ctx->state[7] = 0x5BE0CD19;
332 }
333
sha256_process(sha256_context *ctx, const uint8_t data[64])334 static void sha256_process(sha256_context *ctx, const uint8_t data[64])
335 {
336 uint32_t temp1, temp2;
337 uint32_t W[64];
338 uint32_t A, B, C, D, E, F, G, H;
339
340 GET_UINT32_BE(W[0], data, 0);
341 GET_UINT32_BE(W[1], data, 4);
342 GET_UINT32_BE(W[2], data, 8);
343 GET_UINT32_BE(W[3], data, 12);
344 GET_UINT32_BE(W[4], data, 16);
345 GET_UINT32_BE(W[5], data, 20);
346 GET_UINT32_BE(W[6], data, 24);
347 GET_UINT32_BE(W[7], data, 28);
348 GET_UINT32_BE(W[8], data, 32);
349 GET_UINT32_BE(W[9], data, 36);
350 GET_UINT32_BE(W[10], data, 40);
351 GET_UINT32_BE(W[11], data, 44);
352 GET_UINT32_BE(W[12], data, 48);
353 GET_UINT32_BE(W[13], data, 52);
354 GET_UINT32_BE(W[14], data, 56);
355 GET_UINT32_BE(W[15], data, 60);
356
357 #define SHR(x,n) ((x & 0xFFFFFFFF) >> n)
358 #define ROTR(x,n) (SHR(x,n) | (x << (32 - n)))
359
360 #define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3))
361 #define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10))
362
363 #define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22))
364 #define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25))
365
366 #define F0(x,y,z) ((x & y) | (z & (x | y)))
367 #define F1(x,y,z) (z ^ (x & (y ^ z)))
368
369 #define R(t) \
370 ( \
371 W[t] = S1(W[t - 2]) + W[t - 7] + \
372 S0(W[t - 15]) + W[t - 16] \
373 )
374
375 #define P(a,b,c,d,e,f,g,h,x,K) { \
376 temp1 = h + S3(e) + F1(e,f,g) + K + x; \
377 temp2 = S2(a) + F0(a,b,c); \
378 d += temp1; h = temp1 + temp2; \
379 }
380
381 A = ctx->state[0];
382 B = ctx->state[1];
383 C = ctx->state[2];
384 D = ctx->state[3];
385 E = ctx->state[4];
386 F = ctx->state[5];
387 G = ctx->state[6];
388 H = ctx->state[7];
389
390 P(A, B, C, D, E, F, G, H, W[0], 0x428A2F98);
391 P(H, A, B, C, D, E, F, G, W[1], 0x71374491);
392 P(G, H, A, B, C, D, E, F, W[2], 0xB5C0FBCF);
393 P(F, G, H, A, B, C, D, E, W[3], 0xE9B5DBA5);
394 P(E, F, G, H, A, B, C, D, W[4], 0x3956C25B);
395 P(D, E, F, G, H, A, B, C, W[5], 0x59F111F1);
396 P(C, D, E, F, G, H, A, B, W[6], 0x923F82A4);
397 P(B, C, D, E, F, G, H, A, W[7], 0xAB1C5ED5);
398 P(A, B, C, D, E, F, G, H, W[8], 0xD807AA98);
399 P(H, A, B, C, D, E, F, G, W[9], 0x12835B01);
400 P(G, H, A, B, C, D, E, F, W[10], 0x243185BE);
401 P(F, G, H, A, B, C, D, E, W[11], 0x550C7DC3);
402 P(E, F, G, H, A, B, C, D, W[12], 0x72BE5D74);
403 P(D, E, F, G, H, A, B, C, W[13], 0x80DEB1FE);
404 P(C, D, E, F, G, H, A, B, W[14], 0x9BDC06A7);
405 P(B, C, D, E, F, G, H, A, W[15], 0xC19BF174);
406 P(A, B, C, D, E, F, G, H, R(16), 0xE49B69C1);
407 P(H, A, B, C, D, E, F, G, R(17), 0xEFBE4786);
408 P(G, H, A, B, C, D, E, F, R(18), 0x0FC19DC6);
409 P(F, G, H, A, B, C, D, E, R(19), 0x240CA1CC);
410 P(E, F, G, H, A, B, C, D, R(20), 0x2DE92C6F);
411 P(D, E, F, G, H, A, B, C, R(21), 0x4A7484AA);
412 P(C, D, E, F, G, H, A, B, R(22), 0x5CB0A9DC);
413 P(B, C, D, E, F, G, H, A, R(23), 0x76F988DA);
414 P(A, B, C, D, E, F, G, H, R(24), 0x983E5152);
415 P(H, A, B, C, D, E, F, G, R(25), 0xA831C66D);
416 P(G, H, A, B, C, D, E, F, R(26), 0xB00327C8);
417 P(F, G, H, A, B, C, D, E, R(27), 0xBF597FC7);
418 P(E, F, G, H, A, B, C, D, R(28), 0xC6E00BF3);
419 P(D, E, F, G, H, A, B, C, R(29), 0xD5A79147);
420 P(C, D, E, F, G, H, A, B, R(30), 0x06CA6351);
421 P(B, C, D, E, F, G, H, A, R(31), 0x14292967);
422 P(A, B, C, D, E, F, G, H, R(32), 0x27B70A85);
423 P(H, A, B, C, D, E, F, G, R(33), 0x2E1B2138);
424 P(G, H, A, B, C, D, E, F, R(34), 0x4D2C6DFC);
425 P(F, G, H, A, B, C, D, E, R(35), 0x53380D13);
426 P(E, F, G, H, A, B, C, D, R(36), 0x650A7354);
427 P(D, E, F, G, H, A, B, C, R(37), 0x766A0ABB);
428 P(C, D, E, F, G, H, A, B, R(38), 0x81C2C92E);
429 P(B, C, D, E, F, G, H, A, R(39), 0x92722C85);
430 P(A, B, C, D, E, F, G, H, R(40), 0xA2BFE8A1);
431 P(H, A, B, C, D, E, F, G, R(41), 0xA81A664B);
432 P(G, H, A, B, C, D, E, F, R(42), 0xC24B8B70);
433 P(F, G, H, A, B, C, D, E, R(43), 0xC76C51A3);
434 P(E, F, G, H, A, B, C, D, R(44), 0xD192E819);
435 P(D, E, F, G, H, A, B, C, R(45), 0xD6990624);
436 P(C, D, E, F, G, H, A, B, R(46), 0xF40E3585);
437 P(B, C, D, E, F, G, H, A, R(47), 0x106AA070);
438 P(A, B, C, D, E, F, G, H, R(48), 0x19A4C116);
439 P(H, A, B, C, D, E, F, G, R(49), 0x1E376C08);
440 P(G, H, A, B, C, D, E, F, R(50), 0x2748774C);
441 P(F, G, H, A, B, C, D, E, R(51), 0x34B0BCB5);
442 P(E, F, G, H, A, B, C, D, R(52), 0x391C0CB3);
443 P(D, E, F, G, H, A, B, C, R(53), 0x4ED8AA4A);
444 P(C, D, E, F, G, H, A, B, R(54), 0x5B9CCA4F);
445 P(B, C, D, E, F, G, H, A, R(55), 0x682E6FF3);
446 P(A, B, C, D, E, F, G, H, R(56), 0x748F82EE);
447 P(H, A, B, C, D, E, F, G, R(57), 0x78A5636F);
448 P(G, H, A, B, C, D, E, F, R(58), 0x84C87814);
449 P(F, G, H, A, B, C, D, E, R(59), 0x8CC70208);
450 P(E, F, G, H, A, B, C, D, R(60), 0x90BEFFFA);
451 P(D, E, F, G, H, A, B, C, R(61), 0xA4506CEB);
452 P(C, D, E, F, G, H, A, B, R(62), 0xBEF9A3F7);
453 P(B, C, D, E, F, G, H, A, R(63), 0xC67178F2);
454
455 ctx->state[0] += A;
456 ctx->state[1] += B;
457 ctx->state[2] += C;
458 ctx->state[3] += D;
459 ctx->state[4] += E;
460 ctx->state[5] += F;
461 ctx->state[6] += G;
462 ctx->state[7] += H;
463 }
464
465 #undef P
466 #undef R
467 #undef F1
468 #undef F0
469 #undef S3
470 #undef S2
471 #undef S1
472 #undef S0
473 #undef ROTR
474 #undef SHR
475
476 static
sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)477 void sha256_update(sha256_context *ctx, const uint8_t *input, uint32_t length)
478 {
479 uint32_t left, fill;
480
481 if (!length)
482 return;
483
484 left = ctx->total[0] & 0x3F;
485 fill = 64 - left;
486
487 ctx->total[0] += length;
488 ctx->total[0] &= 0xFFFFFFFF;
489
490 if (ctx->total[0] < length)
491 ctx->total[1]++;
492
493 if (left && length >= fill) {
494 memcpy((void *) (ctx->buffer + left), (void *) input, fill);
495 sha256_process(ctx, ctx->buffer);
496 length -= fill;
497 input += fill;
498 left = 0;
499 }
500
501 while (length >= 64) {
502 sha256_process(ctx, input);
503 length -= 64;
504 input += 64;
505 }
506
507 if (length)
508 memcpy((void *) (ctx->buffer + left), (void *) input, length);
509 }
510
511 static uint8_t sha256_padding[64] = {
512 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
513 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
514 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
515 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
516 };
517
518 static
sha256_finish(sha256_context * ctx, uint8_t digest[32])519 void sha256_finish(sha256_context * ctx, uint8_t digest[32])
520 {
521 uint32_t last, padn;
522 uint32_t high, low;
523 uint8_t msglen[8];
524
525 high = ((ctx->total[0] >> 29)
526 | (ctx->total[1] << 3));
527 low = (ctx->total[0] << 3);
528
529 PUT_UINT32_BE(high, msglen, 0);
530 PUT_UINT32_BE(low, msglen, 4);
531
532 last = ctx->total[0] & 0x3F;
533 padn = (last < 56) ? (56 - last) : (120 - last);
534
535 sha256_update(ctx, sha256_padding, padn);
536 sha256_update(ctx, msglen, 8);
537
538 PUT_UINT32_BE(ctx->state[0], digest, 0);
539 PUT_UINT32_BE(ctx->state[1], digest, 4);
540 PUT_UINT32_BE(ctx->state[2], digest, 8);
541 PUT_UINT32_BE(ctx->state[3], digest, 12);
542 PUT_UINT32_BE(ctx->state[4], digest, 16);
543 PUT_UINT32_BE(ctx->state[5], digest, 20);
544 PUT_UINT32_BE(ctx->state[6], digest, 24);
545 PUT_UINT32_BE(ctx->state[7], digest, 28);
546 }
547
548 /*
549 * Output = SHA-256( input buffer ).
550 */
551 static
sha256_csum(const unsigned char *input, unsigned int ilen, unsigned char *output)552 void sha256_csum(const unsigned char *input, unsigned int ilen,
553 unsigned char *output)
554 {
555 sha256_context ctx;
556
557 sha256_starts(&ctx);
558 sha256_update(&ctx, input, ilen);
559 sha256_finish(&ctx, output);
560 }
561
562 /* #define DEBUG */
563
564 static bool g_debug =
565 #ifdef DEBUG
566 true;
567 #else
568 false;
569 #endif /* DEBUG */
570
571 #define LOGE(fmt, args...) \
572 fprintf(stderr, "E/%s(%d): " fmt "\n", __func__, __LINE__, ##args)
573 #define LOGD(fmt, args...) \
574 do { \
575 if (g_debug) \
576 fprintf(stderr, "D/%s(%d): " fmt "\n", __func__, __LINE__, ##args); \
577 } while (0)
578
579 /* sync with ./board/rockchip/rk30xx/rkloader.c #define FDT_PATH */
580 #define FDT_PATH "rk-kernel.dtb"
581 #define DTD_SUBFIX ".dtb"
582
583 #define DEFAULT_IMAGE_PATH "resource.img"
584 #define DEFAULT_UNPACK_DIR "out"
585 #define BLOCK_SIZE 512
586
587 #define RESOURCE_PTN_HDR_SIZE 1
588 #define INDEX_TBL_ENTR_SIZE 1
589
590 #define RESOURCE_PTN_VERSION 0
591 #define INDEX_TBL_VERSION 0
592
593 #define RESOURCE_PTN_HDR_MAGIC "RSCE"
594 typedef struct {
595 char magic[4]; /* tag, "RSCE" */
596 uint16_t resource_ptn_version;
597 uint16_t index_tbl_version;
598 uint8_t header_size; /* blocks, size of ptn header. */
599 uint8_t tbl_offset; /* blocks, offset of index table. */
600 uint8_t tbl_entry_size; /* blocks, size of index table's entry. */
601 uint32_t tbl_entry_num; /* numbers of index table's entry. */
602 } resource_ptn_header;
603
604 #define INDEX_TBL_ENTR_TAG "ENTR"
605 #define MAX_INDEX_ENTRY_PATH_LEN 220
606 #define MAX_HASH_LEN 32
607
608 typedef struct {
609 char tag[4]; /* tag, "ENTR" */
610 char path[MAX_INDEX_ENTRY_PATH_LEN];
611 char hash[MAX_HASH_LEN]; /* hash data */
612 uint32_t hash_size; /* 20 or 32 */
613 uint32_t content_offset; /* blocks, offset of resource content. */
614 uint32_t content_size; /* bytes, size of resource content. */
615 } index_tbl_entry;
616
617 #define OPT_VERBOSE "--verbose"
618 #define OPT_HELP "--help"
619 #define OPT_VERSION "--version"
620 #define OPT_PRINT "--print"
621 #define OPT_PACK "--pack"
622 #define OPT_UNPACK "--unpack"
623 #define OPT_TEST_LOAD "--test_load"
624 #define OPT_TEST_CHARGE "--test_charge"
625 #define OPT_IMAGE "--image="
626 #define OPT_ROOT "--root="
627
628 #define VERSION "2014-5-31 14:43:42"
629
630 typedef struct {
631 char path[MAX_INDEX_ENTRY_PATH_LEN];
632 uint32_t content_offset; /* blocks, offset of resource content. */
633 uint32_t content_size; /* bytes, size of resource content. */
634 void *load_addr;
635 } resource_content;
636
637 typedef struct {
638 int max_level;
639 int num;
640 int delay;
641 char prefix[MAX_INDEX_ENTRY_PATH_LEN];
642 } anim_level_conf;
643
644 #define DEF_CHARGE_DESC_PATH "charge_anim_desc.txt"
645
646 #define OPT_CHARGE_ANIM_DELAY "delay="
647 #define OPT_CHARGE_ANIM_LOOP_CUR "only_current_level="
648 #define OPT_CHARGE_ANIM_LEVELS "levels="
649 #define OPT_CHARGE_ANIM_LEVEL_CONF "max_level="
650 #define OPT_CHARGE_ANIM_LEVEL_NUM "num="
651 #define OPT_CHARGE_ANIM_LEVEL_PFX "prefix="
652
653 static char image_path[MAX_INDEX_ENTRY_PATH_LEN] = "\0";
654
fix_blocks(size_t size)655 static int fix_blocks(size_t size)
656 {
657 return (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
658 }
659
fix_path(const char *path)660 static const char *fix_path(const char *path)
661 {
662 if (!memcmp(path, "./", 2)) {
663 return path + 2;
664 }
665 return path;
666 }
667
switch_short(uint16_t x)668 static uint16_t switch_short(uint16_t x)
669 {
670 uint16_t val;
671 uint8_t *p = (uint8_t *)(&x);
672
673 val = (*p++ & 0xff) << 0;
674 val |= (*p & 0xff) << 8;
675
676 return val;
677 }
678
switch_int(uint32_t x)679 static uint32_t switch_int(uint32_t x)
680 {
681 uint32_t val;
682 uint8_t *p = (uint8_t *)(&x);
683
684 val = (*p++ & 0xff) << 0;
685 val |= (*p++ & 0xff) << 8;
686 val |= (*p++ & 0xff) << 16;
687 val |= (*p & 0xff) << 24;
688
689 return val;
690 }
691
fix_header(resource_ptn_header *header)692 static void fix_header(resource_ptn_header *header)
693 {
694 /* switch for be. */
695 header->resource_ptn_version = switch_short(header->resource_ptn_version);
696 header->index_tbl_version = switch_short(header->index_tbl_version);
697 header->tbl_entry_num = switch_int(header->tbl_entry_num);
698 }
699
fix_entry(index_tbl_entry *entry)700 static void fix_entry(index_tbl_entry *entry)
701 {
702 /* switch for be. */
703 entry->content_offset = switch_int(entry->content_offset);
704 entry->content_size = switch_int(entry->content_size);
705 }
706
get_ptn_offset(void)707 static int inline get_ptn_offset(void)
708 {
709 return 0;
710 }
711
StorageWriteLba(int offset_block, void *data, int blocks)712 static bool StorageWriteLba(int offset_block, void *data, int blocks)
713 {
714 bool ret = false;
715 FILE *file = fopen(image_path, "rb+");
716 if (!file)
717 goto end;
718 int offset = offset_block * BLOCK_SIZE;
719 fseek(file, offset, SEEK_SET);
720 if (offset != ftell(file)) {
721 LOGE("Failed to seek %s to %d!", image_path, offset);
722 goto end;
723 }
724 if (!fwrite(data, blocks * BLOCK_SIZE, 1, file)) {
725 LOGE("Failed to write %s!", image_path);
726 goto end;
727 }
728 ret = true;
729 end:
730 if (file)
731 fclose(file);
732 return ret;
733 }
734
StorageReadLba(int offset_block, void *data, int blocks)735 static bool StorageReadLba(int offset_block, void *data, int blocks)
736 {
737 bool ret = false;
738 FILE *file = fopen(image_path, "rb");
739 if (!file)
740 goto end;
741 int offset = offset_block * BLOCK_SIZE;
742 fseek(file, offset, SEEK_SET);
743 if (offset != ftell(file)) {
744 goto end;
745 }
746 if (!fread(data, blocks * BLOCK_SIZE, 1, file)) {
747 goto end;
748 }
749 ret = true;
750 end:
751 if (file)
752 fclose(file);
753 return ret;
754 }
755
write_data(int offset_block, void *data, size_t len)756 static bool write_data(int offset_block, void *data, size_t len)
757 {
758 bool ret = false;
759 if (!data)
760 goto end;
761 int blocks = len / BLOCK_SIZE;
762 if (blocks && !StorageWriteLba(offset_block, data, blocks)) {
763 goto end;
764 }
765 int left = len % BLOCK_SIZE;
766 if (left) {
767 char buf[BLOCK_SIZE] = "\0";
768 memcpy(buf, data + blocks * BLOCK_SIZE, left);
769 if (!StorageWriteLba(offset_block + blocks, buf, 1))
770 goto end;
771 }
772 ret = true;
773 end:
774 return ret;
775 }
776
777 /**********************load test************************/
778 static int load_file(const char *file_path, int offset_block, int blocks);
779
test_load(int argc, char **argv)780 static int test_load(int argc, char **argv)
781 {
782 if (argc < 1) {
783 LOGE("Nothing to load!");
784 return -1;
785 }
786 const char *file_path;
787 int offset_block = 0;
788 int blocks = 0;
789 if (argc > 0) {
790 file_path = (const char *)fix_path(argv[0]);
791 argc--, argv++;
792 }
793 if (argc > 0) {
794 offset_block = atoi(argv[0]);
795 argc--, argv++;
796 }
797 if (argc > 0) {
798 blocks = atoi(argv[0]);
799 }
800 return load_file(file_path, offset_block, blocks);
801 }
802
free_content(resource_content *content)803 static void free_content(resource_content *content)
804 {
805 if (content->load_addr) {
806 free(content->load_addr);
807 content->load_addr = 0;
808 }
809 }
810
tests_dump_file(const char *path, void *data, int len)811 static void tests_dump_file(const char *path, void *data, int len)
812 {
813 FILE *file = fopen(path, "wb");
814 if (!file)
815 return;
816 fwrite(data, len, 1, file);
817 fclose(file);
818 }
819
load_content(resource_content *content)820 static bool load_content(resource_content *content)
821 {
822 if (content->load_addr)
823 return true;
824 int blocks = fix_blocks(content->content_size);
825 content->load_addr = malloc(blocks * BLOCK_SIZE);
826 if (!content->load_addr)
827 return false;
828 if (!StorageReadLba(get_ptn_offset() + content->content_offset,
829 content->load_addr, blocks)) {
830 free_content(content);
831 return false;
832 }
833
834 tests_dump_file(content->path, content->load_addr, content->content_size);
835 return true;
836 }
837
load_content_data(resource_content *content, int offset_block, void *data, int blocks)838 static bool load_content_data(resource_content *content, int offset_block,
839 void *data, int blocks)
840 {
841 if (!StorageReadLba(get_ptn_offset() + content->content_offset + offset_block,
842 data, blocks)) {
843 return false;
844 }
845 tests_dump_file(content->path, data, blocks * BLOCK_SIZE);
846 return true;
847 }
848
get_entry(const char *file_path, index_tbl_entry *entry)849 static bool get_entry(const char *file_path, index_tbl_entry *entry)
850 {
851 bool ret = false;
852 char buf[BLOCK_SIZE];
853 resource_ptn_header header;
854 if (!StorageReadLba(get_ptn_offset(), buf, 1)) {
855 LOGE("Failed to read header!");
856 goto end;
857 }
858 memcpy(&header, buf, sizeof(header));
859
860 if (memcmp(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic))) {
861 LOGE("Not a resource image(%s)!", image_path);
862 goto end;
863 }
864 /* test on pc, switch for be. */
865 fix_header(&header);
866
867 /* TODO: support header_size & tbl_entry_size */
868 if (header.resource_ptn_version != RESOURCE_PTN_VERSION ||
869 header.header_size != RESOURCE_PTN_HDR_SIZE ||
870 header.index_tbl_version != INDEX_TBL_VERSION ||
871 header.tbl_entry_size != INDEX_TBL_ENTR_SIZE) {
872 LOGE("Not supported in this version!");
873 goto end;
874 }
875
876 int i;
877 for (i = 0; i < header.tbl_entry_num; i++) {
878 /* TODO: support tbl_entry_size */
879 if (!StorageReadLba(
880 get_ptn_offset() + header.header_size + i * header.tbl_entry_size,
881 buf, 1)) {
882 LOGE("Failed to read index entry:%d!", i);
883 goto end;
884 }
885 memcpy(entry, buf, sizeof(*entry));
886
887 if (memcmp(entry->tag, INDEX_TBL_ENTR_TAG, sizeof(entry->tag))) {
888 LOGE("Something wrong with index entry:%d!", i);
889 goto end;
890 }
891
892 if (!strncmp(entry->path, file_path, sizeof(entry->path)))
893 break;
894 }
895 if (i == header.tbl_entry_num) {
896 LOGE("Cannot find %s!", file_path);
897 goto end;
898 }
899 /* test on pc, switch for be. */
900 fix_entry(entry);
901
902 printf("Found entry:\n\tpath:%s\n\toffset:%d\tsize:%d\n", entry->path,
903 entry->content_offset, entry->content_size);
904
905 ret = true;
906 end:
907 return ret;
908 }
909
get_content(resource_content *content)910 static bool get_content(resource_content *content)
911 {
912 bool ret = false;
913 index_tbl_entry entry;
914 if (!get_entry(content->path, &entry))
915 goto end;
916 content->content_offset = entry.content_offset;
917 content->content_size = entry.content_size;
918 ret = true;
919 end:
920 return ret;
921 }
922
load_file(const char *file_path, int offset_block, int blocks)923 static int load_file(const char *file_path, int offset_block, int blocks)
924 {
925 printf("Try to load:%s", file_path);
926 if (blocks) {
927 printf(", offset block:%d, blocks:%d\n", offset_block, blocks);
928 } else {
929 printf("\n");
930 }
931 bool ret = false;
932 resource_content content;
933 snprintf(content.path, sizeof(content.path), "%s", file_path);
934 content.load_addr = 0;
935 if (!get_content(&content)) {
936 goto end;
937 }
938 if (!blocks) {
939 if (!load_content(&content)) {
940 goto end;
941 }
942 } else {
943 void *data = malloc(blocks * BLOCK_SIZE);
944 if (!data)
945 goto end;
946 if (!load_content_data(&content, offset_block, data, blocks)) {
947 goto end;
948 }
949 }
950 ret = true;
951 end:
952 free_content(&content);
953 return ret;
954 }
955
956 /**********************load test end************************/
957 /**********************anim test************************/
958
parse_level_conf(const char *arg, anim_level_conf *level_conf)959 static bool parse_level_conf(const char *arg, anim_level_conf *level_conf)
960 {
961 memset(level_conf, 0, sizeof(anim_level_conf));
962 char *buf = NULL;
963 buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_CONF);
964 if (buf) {
965 level_conf->max_level = atoi(buf + strlen(OPT_CHARGE_ANIM_LEVEL_CONF));
966 } else {
967 LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_CONF);
968 return false;
969 }
970 buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_NUM);
971 if (buf) {
972 level_conf->num = atoi(buf + strlen(OPT_CHARGE_ANIM_LEVEL_NUM));
973 if (level_conf->num <= 0) {
974 return false;
975 }
976 } else {
977 LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_NUM);
978 return false;
979 }
980 buf = strstr(arg, OPT_CHARGE_ANIM_DELAY);
981 if (buf) {
982 level_conf->delay = atoi(buf + strlen(OPT_CHARGE_ANIM_DELAY));
983 }
984 buf = strstr(arg, OPT_CHARGE_ANIM_LEVEL_PFX);
985 if (buf) {
986 snprintf(level_conf->prefix, sizeof(level_conf->prefix), "%s",
987 buf + strlen(OPT_CHARGE_ANIM_LEVEL_PFX));
988 } else {
989 LOGE("Not found:%s", OPT_CHARGE_ANIM_LEVEL_PFX);
990 return false;
991 }
992
993 LOGD("Found conf:\nmax_level:%d, num:%d, delay:%d, prefix:%s",
994 level_conf->max_level, level_conf->num, level_conf->delay,
995 level_conf->prefix);
996 return true;
997 }
998
test_charge(int argc, char **argv)999 static int test_charge(int argc, char **argv)
1000 {
1001 const char *desc;
1002 if (argc > 0) {
1003 desc = argv[0];
1004 } else {
1005 desc = DEF_CHARGE_DESC_PATH;
1006 }
1007
1008 resource_content content;
1009 snprintf(content.path, sizeof(content.path), "%s", desc);
1010 content.load_addr = 0;
1011 if (!get_content(&content)) {
1012 goto end;
1013 }
1014 if (!load_content(&content)) {
1015 goto end;
1016 }
1017
1018 char *buf = (char *)content.load_addr;
1019 char *end = buf + content.content_size - 1;
1020 *end = '\0';
1021 LOGD("desc:\n%s", buf);
1022
1023 int pos = 0;
1024 while (1) {
1025 char *line = (char *)memchr(buf + pos, '\n', strlen(buf + pos));
1026 if (!line)
1027 break;
1028 *line = '\0';
1029 LOGD("splite:%s", buf + pos);
1030 pos += (strlen(buf + pos) + 1);
1031 }
1032
1033 int delay = 900;
1034 int only_current_level = false;
1035 anim_level_conf *level_confs = NULL;
1036 int level_conf_pos = 0;
1037 int level_conf_num = 0;
1038
1039 while (true) {
1040 if (buf >= end)
1041 break;
1042 const char *arg = buf;
1043 buf += (strlen(buf) + 1);
1044
1045 LOGD("parse arg:%s", arg);
1046 if (!memcmp(arg, OPT_CHARGE_ANIM_LEVEL_CONF,
1047 strlen(OPT_CHARGE_ANIM_LEVEL_CONF))) {
1048 if (!level_confs) {
1049 LOGE("Found level conf before levels!");
1050 goto end;
1051 }
1052 if (level_conf_pos >= level_conf_num) {
1053 LOGE("Too many level confs!(%d >= %d)", level_conf_pos, level_conf_num);
1054 goto end;
1055 }
1056 if (!parse_level_conf(arg, level_confs + level_conf_pos)) {
1057 LOGE("Failed to parse level conf:%s", arg);
1058 goto end;
1059 }
1060 level_conf_pos++;
1061 } else if (!memcmp(arg, OPT_CHARGE_ANIM_DELAY,
1062 strlen(OPT_CHARGE_ANIM_DELAY))) {
1063 delay = atoi(arg + strlen(OPT_CHARGE_ANIM_DELAY));
1064 LOGD("Found delay:%d", delay);
1065 } else if (!memcmp(arg, OPT_CHARGE_ANIM_LOOP_CUR,
1066 strlen(OPT_CHARGE_ANIM_LOOP_CUR))) {
1067 only_current_level =
1068 !memcmp(arg + strlen(OPT_CHARGE_ANIM_LOOP_CUR), "true", 4);
1069 LOGD("Found only_current_level:%d", only_current_level);
1070 } else if (!memcmp(arg, OPT_CHARGE_ANIM_LEVELS,
1071 strlen(OPT_CHARGE_ANIM_LEVELS))) {
1072 if (level_conf_num) {
1073 goto end;
1074 }
1075 level_conf_num = atoi(arg + strlen(OPT_CHARGE_ANIM_LEVELS));
1076 if (!level_conf_num) {
1077 goto end;
1078 }
1079 level_confs =
1080 (anim_level_conf *)malloc(level_conf_num * sizeof(anim_level_conf));
1081 LOGD("Found levels:%d", level_conf_num);
1082 } else {
1083 LOGE("Unknown arg:%s", arg);
1084 goto end;
1085 }
1086 }
1087
1088 if (level_conf_pos != level_conf_num || !level_conf_num) {
1089 LOGE("Something wrong with level confs!");
1090 goto end;
1091 }
1092
1093 int i = 0, j = 0;
1094 for (i = 0; i < level_conf_num; i++) {
1095 if (!level_confs[i].delay) {
1096 level_confs[i].delay = delay;
1097 }
1098 if (!level_confs[i].delay) {
1099 LOGE("Missing delay in level conf:%d", i);
1100 goto end;
1101 }
1102 for (j = 0; j < i; j++) {
1103 if (level_confs[j].max_level == level_confs[i].max_level) {
1104 LOGE("Dup level conf:%d", i);
1105 goto end;
1106 }
1107 if (level_confs[j].max_level > level_confs[i].max_level) {
1108 anim_level_conf conf = level_confs[i];
1109 memmove(level_confs + j + 1, level_confs + j,
1110 (i - j) * sizeof(anim_level_conf));
1111 level_confs[j] = conf;
1112 }
1113 }
1114 }
1115
1116 printf("Parse anim desc(%s):\n", desc);
1117 printf("only_current_level=%d\n", only_current_level);
1118 printf("level conf:\n");
1119 for (i = 0; i < level_conf_num; i++) {
1120 printf("\tmax=%d, delay=%d, num=%d, prefix=%s\n", level_confs[i].max_level,
1121 level_confs[i].delay, level_confs[i].num, level_confs[i].prefix);
1122 }
1123
1124 end:
1125 free_content(&content);
1126 return 0;
1127 }
1128
1129 /**********************anim test end************************/
1130 /**********************append file************************/
1131
1132 static const char *PROG = NULL;
1133 static resource_ptn_header header;
1134 static bool just_print = false;
1135 static char root_path[MAX_INDEX_ENTRY_PATH_LEN] = "\0";
1136
version(void)1137 static void version(void)
1138 {
1139 printf("%s (cjf@rock-chips.com)\t" VERSION "\n", PROG);
1140 }
1141
usage(void)1142 static void usage(void)
1143 {
1144 printf("Usage: %s [options] [FILES]\n", PROG);
1145 printf("Tools for Rockchip's resource image.\n");
1146 version();
1147 printf("Options:\n");
1148 printf("\t" OPT_PACK "\t\t\tPack image from given files.\n");
1149 printf("\t" OPT_UNPACK "\t\tUnpack given image to current dir.\n");
1150 printf("\t" OPT_IMAGE "path"
1151 "\t\tSpecify input/output image path.\n");
1152 printf("\t" OPT_PRINT "\t\t\tJust print informations.\n");
1153 printf("\t" OPT_VERBOSE "\t\tDisplay more runtime informations.\n");
1154 printf("\t" OPT_HELP "\t\t\tDisplay this information.\n");
1155 printf("\t" OPT_VERSION "\t\tDisplay version information.\n");
1156 printf("\t" OPT_ROOT "path"
1157 "\t\tSpecify resources' root dir.\n");
1158 }
1159
1160 static int pack_image(int file_num, const char **files);
1161 static int unpack_image(const char *unpack_dir);
1162
1163 enum ACTION {
1164 ACTION_PACK,
1165 ACTION_UNPACK,
1166 ACTION_TEST_LOAD,
1167 ACTION_TEST_CHARGE,
1168 };
1169
main(int argc, char **argv)1170 int main(int argc, char **argv)
1171 {
1172 PROG = fix_path(argv[0]);
1173
1174 enum ACTION action = ACTION_PACK;
1175
1176 argc--, argv++;
1177 while (argc > 0 && argv[0][0] == '-') {
1178 /* it's a opt arg. */
1179 const char *arg = argv[0];
1180 argc--, argv++;
1181 if (!strcmp(OPT_VERBOSE, arg)) {
1182 g_debug = true;
1183 } else if (!strcmp(OPT_HELP, arg)) {
1184 usage();
1185 return 0;
1186 } else if (!strcmp(OPT_VERSION, arg)) {
1187 version();
1188 return 0;
1189 } else if (!strcmp(OPT_PRINT, arg)) {
1190 just_print = true;
1191 } else if (!strcmp(OPT_PACK, arg)) {
1192 action = ACTION_PACK;
1193 } else if (!strcmp(OPT_UNPACK, arg)) {
1194 action = ACTION_UNPACK;
1195 } else if (!strcmp(OPT_TEST_LOAD, arg)) {
1196 action = ACTION_TEST_LOAD;
1197 } else if (!strcmp(OPT_TEST_CHARGE, arg)) {
1198 action = ACTION_TEST_CHARGE;
1199 } else if (!memcmp(OPT_IMAGE, arg, strlen(OPT_IMAGE))) {
1200 snprintf(image_path, sizeof(image_path), "%s", arg + strlen(OPT_IMAGE));
1201 } else if (!memcmp(OPT_ROOT, arg, strlen(OPT_ROOT))) {
1202 snprintf(root_path, sizeof(root_path), "%s", arg + strlen(OPT_ROOT));
1203 } else {
1204 LOGE("Unknown opt:%s", arg);
1205 usage();
1206 return -1;
1207 }
1208 }
1209
1210 if (!image_path[0]) {
1211 snprintf(image_path, sizeof(image_path), "%s", DEFAULT_IMAGE_PATH);
1212 }
1213
1214 switch (action) {
1215 case ACTION_PACK: {
1216 int file_num = argc;
1217 const char **files = (const char **)argv;
1218 if (!file_num) {
1219 LOGE("No file to pack!");
1220 return 0;
1221 }
1222 LOGD("try to pack %d files.", file_num);
1223 return pack_image(file_num, files);
1224 }
1225 case ACTION_UNPACK: {
1226 return unpack_image(argc > 0 ? argv[0] : DEFAULT_UNPACK_DIR);
1227 }
1228 case ACTION_TEST_LOAD: {
1229 return test_load(argc, argv);
1230 }
1231 case ACTION_TEST_CHARGE: {
1232 return test_charge(argc, argv);
1233 }
1234 }
1235 /* not reach here. */
1236 return -1;
1237 }
1238
1239 /************unpack code****************/
mkdirs(char *path)1240 static bool mkdirs(char *path)
1241 {
1242 char *tmp = path;
1243 char *pos = NULL;
1244 char buf[MAX_INDEX_ENTRY_PATH_LEN];
1245 bool ret = true;
1246 while ((pos = memchr(tmp, '/', strlen(tmp)))) {
1247 strcpy(buf, path);
1248 buf[pos - path] = '\0';
1249 tmp = pos + 1;
1250 LOGD("mkdir:%s", buf);
1251 if (!mkdir(buf, 0755)) {
1252 ret = false;
1253 }
1254 }
1255 if (!ret)
1256 LOGD("Failed to mkdir(%s)!", path);
1257 return ret;
1258 }
1259
dump_file(FILE *file, const char *unpack_dir, index_tbl_entry entry)1260 static bool dump_file(FILE *file, const char *unpack_dir,
1261 index_tbl_entry entry)
1262 {
1263 LOGD("try to dump entry:%s", entry.path);
1264 bool ret = false;
1265 FILE *out_file = NULL;
1266 long int pos = 0;
1267 char path[MAX_INDEX_ENTRY_PATH_LEN * 2 + 1];
1268 if (just_print) {
1269 ret = true;
1270 goto done;
1271 }
1272
1273 pos = ftell(file);
1274 snprintf(path, sizeof(path), "%s/%s", unpack_dir, entry.path);
1275 mkdirs(path);
1276 out_file = fopen(path, "wb");
1277 if (!out_file) {
1278 LOGE("Failed to create:%s", path);
1279 goto end;
1280 }
1281 long int offset = entry.content_offset * BLOCK_SIZE;
1282 fseek(file, offset, SEEK_SET);
1283 if (offset != ftell(file)) {
1284 LOGE("Failed to read content:%s", entry.path);
1285 goto end;
1286 }
1287 char buf[BLOCK_SIZE];
1288 int n;
1289 int len = entry.content_size;
1290 while (len > 0) {
1291 n = len > BLOCK_SIZE ? BLOCK_SIZE : len;
1292 if (!fread(buf, n, 1, file)) {
1293 LOGE("Failed to read content:%s", entry.path);
1294 goto end;
1295 }
1296 if (!fwrite(buf, n, 1, out_file)) {
1297 LOGE("Failed to write:%s", entry.path);
1298 goto end;
1299 }
1300 len -= n;
1301 }
1302 done:
1303 ret = true;
1304 end:
1305 if (out_file)
1306 fclose(out_file);
1307 if (pos)
1308 fseek(file, pos, SEEK_SET);
1309 return ret;
1310 }
1311
unpack_image(const char *dir)1312 static int unpack_image(const char *dir)
1313 {
1314 FILE *image_file = NULL;
1315 bool ret = false;
1316 char unpack_dir[MAX_INDEX_ENTRY_PATH_LEN];
1317 if (just_print)
1318 dir = ".";
1319 snprintf(unpack_dir, sizeof(unpack_dir), "%s", dir);
1320 if (!strlen(unpack_dir)) {
1321 goto end;
1322 } else if (unpack_dir[strlen(unpack_dir) - 1] == '/') {
1323 unpack_dir[strlen(unpack_dir) - 1] = '\0';
1324 }
1325
1326 mkdir(unpack_dir, 0755);
1327 image_file = fopen(image_path, "rb");
1328 char buf[BLOCK_SIZE];
1329 if (!image_file) {
1330 LOGE("Failed to open:%s", image_path);
1331 goto end;
1332 }
1333 if (!fread(buf, BLOCK_SIZE, 1, image_file)) {
1334 LOGE("Failed to read header!");
1335 goto end;
1336 }
1337 memcpy(&header, buf, sizeof(header));
1338
1339 if (memcmp(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic))) {
1340 LOGE("Not a resource image(%s)!", image_path);
1341 goto end;
1342 }
1343 /* switch for be. */
1344 fix_header(&header);
1345
1346 printf("Dump header:\n");
1347 printf("partition version:%d.%d\n", header.resource_ptn_version,
1348 header.index_tbl_version);
1349 printf("header size:%d\n", header.header_size);
1350 printf("index tbl:\n\toffset:%d\tentry size:%d\tentry num:%d\n",
1351 header.tbl_offset, header.tbl_entry_size, header.tbl_entry_num);
1352
1353 /* TODO: support header_size & tbl_entry_size */
1354 if (header.resource_ptn_version != RESOURCE_PTN_VERSION ||
1355 header.header_size != RESOURCE_PTN_HDR_SIZE ||
1356 header.index_tbl_version != INDEX_TBL_VERSION ||
1357 header.tbl_entry_size != INDEX_TBL_ENTR_SIZE) {
1358 LOGE("Not supported in this version!");
1359 goto end;
1360 }
1361
1362 printf("Dump Index table:\n");
1363 index_tbl_entry entry;
1364 int i;
1365 for (i = 0; i < header.tbl_entry_num; i++) {
1366 /* TODO: support tbl_entry_size */
1367 if (!fread(buf, BLOCK_SIZE, 1, image_file)) {
1368 LOGE("Failed to read index entry:%d!", i);
1369 goto end;
1370 }
1371 memcpy(&entry, buf, sizeof(entry));
1372
1373 if (memcmp(entry.tag, INDEX_TBL_ENTR_TAG, sizeof(entry.tag))) {
1374 LOGE("Something wrong with index entry:%d!", i);
1375 goto end;
1376 }
1377 /* switch for be. */
1378 fix_entry(&entry);
1379
1380 printf("entry(%d):\n\tpath:%s\n\toffset:%d\tsize:%d\n", i, entry.path,
1381 entry.content_offset, entry.content_size);
1382 if (!dump_file(image_file, unpack_dir, entry)) {
1383 goto end;
1384 }
1385 }
1386 printf("Unack %s to %s successed!\n", image_path, unpack_dir);
1387 ret = true;
1388 end:
1389 if (image_file)
1390 fclose(image_file);
1391 return ret ? 0 : -1;
1392 }
1393
1394 /************unpack code end****************/
1395 /************pack code****************/
1396
get_file_size(const char *path)1397 static inline size_t get_file_size(const char *path)
1398 {
1399 LOGD("try to get size(%s)...", path);
1400 struct stat st;
1401 if (stat(path, &st) < 0) {
1402 LOGE("Failed to get size:%s", path);
1403 return -1;
1404 }
1405 LOGD("path:%s, size:%ld", path, st.st_size);
1406 return st.st_size;
1407 }
1408
write_file(int offset_block, const char *src_path, char hash[], int hash_size)1409 static int write_file(int offset_block, const char *src_path,
1410 char hash[], int hash_size)
1411 {
1412 LOGD("try to write file(%s) to offset:%d...", src_path, offset_block);
1413 char *buf = NULL;
1414 int ret = -1;
1415 size_t file_size;
1416 LOGE("#### [zhq] src_path: %s", src_path);
1417 FILE *src_file = fopen(src_path, "rb");
1418 if (!src_file) {
1419 LOGE("Failed to open:%s", src_path);
1420 goto end;
1421 }
1422
1423 file_size = get_file_size(src_path);
1424 if (file_size < 0) {
1425 goto end;
1426 }
1427
1428 buf = calloc(file_size, 1);
1429 if (!buf)
1430 goto end;
1431
1432 if (!fread(buf, file_size, 1, src_file))
1433 goto end;
1434
1435 if (!write_data(offset_block, buf, file_size))
1436 goto end;
1437
1438 if (hash_size == 20)
1439 sha1_csum((const unsigned char *)buf, file_size,
1440 (unsigned char *)hash);
1441 else if (hash_size == 32)
1442 sha256_csum((const unsigned char *)buf, file_size,
1443 (unsigned char *)hash);
1444 else
1445 goto end;
1446
1447 ret = file_size;
1448 end:
1449 if (src_file)
1450 fclose(src_file);
1451 if (buf)
1452 free(buf);
1453
1454 return ret;
1455 }
1456
write_header(const int file_num)1457 static bool write_header(const int file_num)
1458 {
1459 LOGD("try to write header...");
1460 memcpy(header.magic, RESOURCE_PTN_HDR_MAGIC, sizeof(header.magic));
1461 header.resource_ptn_version = RESOURCE_PTN_VERSION;
1462 header.index_tbl_version = INDEX_TBL_VERSION;
1463 header.header_size = RESOURCE_PTN_HDR_SIZE;
1464 header.tbl_offset = header.header_size;
1465 header.tbl_entry_size = INDEX_TBL_ENTR_SIZE;
1466 header.tbl_entry_num = file_num;
1467
1468 /* switch for le. */
1469 resource_ptn_header hdr = header;
1470 fix_header(&hdr);
1471 return write_data(0, &hdr, sizeof(hdr));
1472 }
1473
write_index_tbl(const int file_num, const char **files)1474 static bool write_index_tbl(const int file_num, const char **files)
1475 {
1476 LOGD("try to write index table...");
1477 bool ret = false;
1478 bool foundFdt = false;
1479 int offset =
1480 header.header_size + header.tbl_entry_size * header.tbl_entry_num;
1481 index_tbl_entry entry;
1482 char hash[20]; /* sha1 */
1483 int i;
1484
1485 memcpy(entry.tag, INDEX_TBL_ENTR_TAG, sizeof(entry.tag));
1486 for (i = 0; i < file_num; i++) {
1487 size_t file_size = get_file_size(files[i]);
1488 if (file_size < 0)
1489 goto end;
1490 entry.content_size = file_size;
1491 entry.content_offset = offset;
1492
1493 if (write_file(offset, files[i], hash, sizeof(hash)) < 0)
1494 goto end;
1495
1496 memcpy(entry.hash, hash, sizeof(hash));
1497 entry.hash_size = sizeof(hash);
1498
1499 LOGD("try to write index entry(%s)...", files[i]);
1500
1501 /* switch for le. */
1502 fix_entry(&entry);
1503 memset(entry.path, 0, sizeof(entry.path));
1504 const char *path = files[i];
1505 if (root_path[0]) {
1506 if (!strncmp(path, root_path, strlen(root_path))) {
1507 path += strlen(root_path);
1508 if (path[0] == '/')
1509 path++;
1510 }
1511 }
1512 path = fix_path(path);
1513 if (!strcmp(files[i] + strlen(files[i]) - strlen(DTD_SUBFIX), DTD_SUBFIX)) {
1514 if (!foundFdt) {
1515 /* use default path. */
1516 LOGD("mod fdt path:%s -> %s...", files[i], FDT_PATH);
1517 path = FDT_PATH;
1518 foundFdt = true;
1519 }
1520 }
1521 snprintf(entry.path, sizeof(entry.path), "%s", path);
1522 offset += fix_blocks(file_size);
1523 if (!write_data(header.header_size + i * header.tbl_entry_size, &entry,
1524 sizeof(entry)))
1525 goto end;
1526 }
1527 ret = true;
1528 end:
1529 return ret;
1530 }
1531
pack_image(int file_num, const char **files)1532 static int pack_image(int file_num, const char **files)
1533 {
1534 bool ret = false;
1535 FILE *image_file = fopen(image_path, "wb");
1536 if (!image_file) {
1537 LOGE("Failed to create:%s", image_path);
1538 goto end;
1539 }
1540 fclose(image_file);
1541
1542 /* prepare files */
1543 int i = 0;
1544 int pos = 0;
1545 const char *tmp;
1546 for (i = 0; i < file_num; i++) {
1547 if (!strcmp(files[i] + strlen(files[i]) - strlen(DTD_SUBFIX), DTD_SUBFIX)) {
1548 /* dtb files for kernel. */
1549 tmp = files[pos];
1550 files[pos] = files[i];
1551 files[i] = tmp;
1552 pos++;
1553 } else if (!strcmp(fix_path(image_path), fix_path(files[i]))) {
1554 /* not to pack image itself! */
1555 tmp = files[file_num - 1];
1556 files[file_num - 1] = files[i];
1557 files[i] = tmp;
1558 file_num--;
1559 }
1560 }
1561
1562 if (!write_header(file_num)) {
1563 LOGE("Failed to write header!");
1564 goto end;
1565 }
1566 if (!write_index_tbl(file_num, files)) {
1567 LOGE("Failed to write index table!");
1568 goto end;
1569 }
1570 printf("Pack to %s successed!\n", image_path);
1571 ret = true;
1572 end:
1573 return ret ? 0 : -1;
1574 }
1575
1576 /************pack code end****************/
1577