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