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