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