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