xref: /rk3399_rockchip-uboot/tools/rockchip/loaderimage.c (revision 23ba6841ccdaeb51290dc49d4e32f175bd3baa34)
1*23ba6841SJoseph Chen /*
2*23ba6841SJoseph Chen  * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
3*23ba6841SJoseph Chen  *
4*23ba6841SJoseph Chen  * SPDX-License-Identifier:	GPL-2.0+
5*23ba6841SJoseph Chen  */
6*23ba6841SJoseph Chen #include "compiler.h"
7*23ba6841SJoseph Chen #include <version.h>
8*23ba6841SJoseph Chen #include "sha.h"
9*23ba6841SJoseph Chen #include <u-boot/sha256.h>
10*23ba6841SJoseph Chen #include <u-boot/crc.h>
11*23ba6841SJoseph Chen #include <linux/sizes.h>
12*23ba6841SJoseph Chen #include <linux/kconfig.h>
13*23ba6841SJoseph Chen #include <config.h>
14*23ba6841SJoseph Chen 
15*23ba6841SJoseph Chen extern uint32_t crc32_rk(uint32_t, const unsigned char *, uint32_t);
16*23ba6841SJoseph Chen 
17*23ba6841SJoseph Chen #define OPT_PACK "--pack"
18*23ba6841SJoseph Chen #define OPT_UNPACK "--unpack"
19*23ba6841SJoseph Chen #define OPT_UBOOT "--uboot"
20*23ba6841SJoseph Chen #define OPT_TRUSTOS "--trustos"
21*23ba6841SJoseph Chen #define OPT_SIZE "--size"
22*23ba6841SJoseph Chen #define OPT_VERSION "--version"
23*23ba6841SJoseph Chen #define OPT_INFO "--info"
24*23ba6841SJoseph Chen 
25*23ba6841SJoseph Chen /* pack or unpack */
26*23ba6841SJoseph Chen #define MODE_PACK 0
27*23ba6841SJoseph Chen #define MODE_UNPACK 1
28*23ba6841SJoseph Chen #define MODE_INFO 2
29*23ba6841SJoseph Chen #define CONFIG_SECUREBOOT_SHA256
30*23ba6841SJoseph Chen 
31*23ba6841SJoseph Chen /* image type */
32*23ba6841SJoseph Chen #define IMAGE_UBOOT 0
33*23ba6841SJoseph Chen #define IMAGE_TRUST 1
34*23ba6841SJoseph Chen 
35*23ba6841SJoseph Chen /* magic and hash size */
36*23ba6841SJoseph Chen #define LOADER_MAGIC_SIZE 8
37*23ba6841SJoseph Chen #define LOADER_HASH_SIZE 32
38*23ba6841SJoseph Chen 
39*23ba6841SJoseph Chen /* uboot image config */
40*23ba6841SJoseph Chen #define UBOOT_NAME "uboot"
41*23ba6841SJoseph Chen #ifdef CONFIG_RK_NVME_BOOT_EN
42*23ba6841SJoseph Chen #define UBOOT_NUM 2
43*23ba6841SJoseph Chen #define UBOOT_MAX_SIZE 512 * 1024
44*23ba6841SJoseph Chen #else
45*23ba6841SJoseph Chen #define UBOOT_NUM 4
46*23ba6841SJoseph Chen #define UBOOT_MAX_SIZE 1024 * 1024
47*23ba6841SJoseph Chen #endif
48*23ba6841SJoseph Chen 
49*23ba6841SJoseph Chen #define UBOOT_VERSION_STRING                                                   \
50*23ba6841SJoseph Chen   U_BOOT_VERSION " (" U_BOOT_DATE " - " U_BOOT_TIME ")" CONFIG_IDENT_STRING
51*23ba6841SJoseph Chen 
52*23ba6841SJoseph Chen #define RK_UBOOT_MAGIC "LOADER  "
53*23ba6841SJoseph Chen #define RK_UBOOT_RUNNING_ADDR CONFIG_SYS_TEXT_BASE
54*23ba6841SJoseph Chen 
55*23ba6841SJoseph Chen /* trust image config */
56*23ba6841SJoseph Chen #define TRUST_NAME "trustos"
57*23ba6841SJoseph Chen #define TRUST_NUM 4
58*23ba6841SJoseph Chen #define TRUST_MAX_SIZE 1024 * 1024
59*23ba6841SJoseph Chen #define TRUST_VERSION_STRING "Trust os"
60*23ba6841SJoseph Chen 
61*23ba6841SJoseph Chen #define RK_TRUST_MAGIC "TOS     "
62*23ba6841SJoseph Chen #define RK_TRUST_RUNNING_ADDR (CONFIG_SYS_TEXT_BASE + SZ_128M + SZ_4M)
63*23ba6841SJoseph Chen 
64*23ba6841SJoseph Chen typedef struct tag_second_loader_hdr {
65*23ba6841SJoseph Chen 	uint8_t magic[LOADER_MAGIC_SIZE]; /* magic */
66*23ba6841SJoseph Chen 	uint32_t version;
67*23ba6841SJoseph Chen 	uint32_t reserved0;
68*23ba6841SJoseph Chen 	uint32_t loader_load_addr;      /* physical load addr */
69*23ba6841SJoseph Chen 	uint32_t loader_load_size;      /* size in bytes */
70*23ba6841SJoseph Chen 	uint32_t crc32;                 /* crc32 */
71*23ba6841SJoseph Chen 	uint32_t hash_len;              /* 20 or 32 , 0 is no hash */
72*23ba6841SJoseph Chen 	uint8_t hash[LOADER_HASH_SIZE]; /* sha */
73*23ba6841SJoseph Chen 
74*23ba6841SJoseph Chen 	uint8_t reserved[1024 - 32 - 32];
75*23ba6841SJoseph Chen 	uint32_t signTag;     /* 0x4E474953 */
76*23ba6841SJoseph Chen 	uint32_t signlen;     /* maybe 128 or 256 */
77*23ba6841SJoseph Chen 	uint8_t rsaHash[256]; /* maybe 128 or 256, using max size 256 */
78*23ba6841SJoseph Chen 	uint8_t reserved2[2048 - 1024 - 256 - 8];
79*23ba6841SJoseph Chen } second_loader_hdr;
80*23ba6841SJoseph Chen 
81*23ba6841SJoseph Chen void usage(const char *prog)
82*23ba6841SJoseph Chen {
83*23ba6841SJoseph Chen 	fprintf(stderr, "Usage: %s [--pack|--unpack] [--uboot|--trustos]\
84*23ba6841SJoseph Chen 		file_in "
85*23ba6841SJoseph Chen 	        "file_out [load_addr]  [--size] [size number]\
86*23ba6841SJoseph Chen 		[--version] "
87*23ba6841SJoseph Chen 	        "[version] | [--info] [file]\n",
88*23ba6841SJoseph Chen 	        prog);
89*23ba6841SJoseph Chen }
90*23ba6841SJoseph Chen 
91*23ba6841SJoseph Chen unsigned int str2hex(char *str)
92*23ba6841SJoseph Chen {
93*23ba6841SJoseph Chen 	int i = 0;
94*23ba6841SJoseph Chen 	unsigned int value = 0;
95*23ba6841SJoseph Chen 
96*23ba6841SJoseph Chen 	if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X'))
97*23ba6841SJoseph Chen 		str += 2;
98*23ba6841SJoseph Chen 	if (*str == 'x' || *str == 'X')
99*23ba6841SJoseph Chen 		str += 1;
100*23ba6841SJoseph Chen 
101*23ba6841SJoseph Chen 	for (i = 0; *str != '\0'; i++, ++str) {
102*23ba6841SJoseph Chen 		if (*str >= '0' && *str <= '9')
103*23ba6841SJoseph Chen 			value = value * 16 + *str - '0';
104*23ba6841SJoseph Chen 		else if (*str >= 'a' && *str <= 'f')
105*23ba6841SJoseph Chen 			value = value * 16 + *str - 'a' + 10;
106*23ba6841SJoseph Chen 		else if (*str >= 'A' && *str <= 'F')
107*23ba6841SJoseph Chen 			value = value * 16 + *str - 'A' + 10;
108*23ba6841SJoseph Chen 		else
109*23ba6841SJoseph Chen 			break;
110*23ba6841SJoseph Chen 	}
111*23ba6841SJoseph Chen 	return value;
112*23ba6841SJoseph Chen }
113*23ba6841SJoseph Chen 
114*23ba6841SJoseph Chen int main(int argc, char *argv[])
115*23ba6841SJoseph Chen {
116*23ba6841SJoseph Chen 	int mode = -1, image = -1;
117*23ba6841SJoseph Chen 	int max_size, max_num;
118*23ba6841SJoseph Chen 	int size, i;
119*23ba6841SJoseph Chen 	uint32_t loader_addr, in_loader_addr = -1;
120*23ba6841SJoseph Chen 	char *magic, *version, *name;
121*23ba6841SJoseph Chen 	FILE *fi, *fo;
122*23ba6841SJoseph Chen 	second_loader_hdr hdr;
123*23ba6841SJoseph Chen 	char *buf = 0;
124*23ba6841SJoseph Chen 	uint32_t in_size = 0, in_num = 0;
125*23ba6841SJoseph Chen 	char *file_in = NULL, *file_out = NULL;
126*23ba6841SJoseph Chen 	uint32_t curr_version = 0;
127*23ba6841SJoseph Chen 
128*23ba6841SJoseph Chen 	if (argc < 3) {
129*23ba6841SJoseph Chen 		usage(argv[0]);
130*23ba6841SJoseph Chen 		exit(EXIT_FAILURE);
131*23ba6841SJoseph Chen 	}
132*23ba6841SJoseph Chen 
133*23ba6841SJoseph Chen 	for (i = 1; i < argc; i++) {
134*23ba6841SJoseph Chen 		if (!strcmp(argv[i], OPT_PACK)) {
135*23ba6841SJoseph Chen 			mode = MODE_PACK;
136*23ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_UNPACK)) {
137*23ba6841SJoseph Chen 			mode = MODE_UNPACK;
138*23ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_UBOOT)) {
139*23ba6841SJoseph Chen 			image = IMAGE_UBOOT;
140*23ba6841SJoseph Chen 			file_in = argv[++i];
141*23ba6841SJoseph Chen 			file_out = argv[++i];
142*23ba6841SJoseph Chen 			/* detect whether loader address is delivered */
143*23ba6841SJoseph Chen 			if ((argv[i + 1]) && (strncmp(argv[i + 1], "--", 2)))
144*23ba6841SJoseph Chen 				in_loader_addr = str2hex(argv[++i]);
145*23ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_TRUSTOS)) {
146*23ba6841SJoseph Chen 			image = IMAGE_TRUST;
147*23ba6841SJoseph Chen 			file_in = argv[++i];
148*23ba6841SJoseph Chen 			file_out = argv[++i];
149*23ba6841SJoseph Chen 			/* detect whether loader address is delivered */
150*23ba6841SJoseph Chen 			if ((argv[i + 1]) && (strncmp(argv[i + 1], "--", 2)))
151*23ba6841SJoseph Chen 				in_loader_addr = str2hex(argv[++i]);
152*23ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_SIZE)) {
153*23ba6841SJoseph Chen 			in_size = strtoul(argv[++i], NULL, 10);
154*23ba6841SJoseph Chen 			/*
155*23ba6841SJoseph Chen 			 * Usually, it must be at 512kb align due to preloader
156*23ba6841SJoseph Chen 			 * detects every 512kb. But some product has critial
157*23ba6841SJoseph Chen 			 * flash size requirement, we have to make it small than
158*23ba6841SJoseph Chen 			 * 512KB.
159*23ba6841SJoseph Chen 			 */
160*23ba6841SJoseph Chen 			if (in_size % 64) {
161*23ba6841SJoseph Chen 				usage(argv[0]);
162*23ba6841SJoseph Chen 				exit(EXIT_FAILURE);
163*23ba6841SJoseph Chen 			}
164*23ba6841SJoseph Chen 			in_size *= 1024;
165*23ba6841SJoseph Chen 
166*23ba6841SJoseph Chen 			in_num = strtoul(argv[++i], NULL, 10);
167*23ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_VERSION)) {
168*23ba6841SJoseph Chen 			curr_version = strtoul(argv[++i], NULL, 10);
169*23ba6841SJoseph Chen 			printf("curr_version = 0x%x\n", curr_version);
170*23ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_INFO)) {
171*23ba6841SJoseph Chen 			mode = MODE_INFO;
172*23ba6841SJoseph Chen 			file_in = argv[++i];
173*23ba6841SJoseph Chen 		} else {
174*23ba6841SJoseph Chen 			usage(argv[0]);
175*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
176*23ba6841SJoseph Chen 		}
177*23ba6841SJoseph Chen 	}
178*23ba6841SJoseph Chen 
179*23ba6841SJoseph Chen 	/* config image information */
180*23ba6841SJoseph Chen 	if (image == IMAGE_UBOOT) {
181*23ba6841SJoseph Chen 		name = UBOOT_NAME;
182*23ba6841SJoseph Chen 		magic = RK_UBOOT_MAGIC;
183*23ba6841SJoseph Chen 		version = UBOOT_VERSION_STRING;
184*23ba6841SJoseph Chen 		max_size = in_size ? in_size : UBOOT_MAX_SIZE;
185*23ba6841SJoseph Chen 		max_num = in_num ? in_num : UBOOT_NUM;
186*23ba6841SJoseph Chen 		loader_addr =
187*23ba6841SJoseph Chen 		        (in_loader_addr == -1) ? RK_UBOOT_RUNNING_ADDR : in_loader_addr;
188*23ba6841SJoseph Chen 	} else if (image == IMAGE_TRUST) {
189*23ba6841SJoseph Chen 		name = TRUST_NAME;
190*23ba6841SJoseph Chen 		magic = RK_TRUST_MAGIC;
191*23ba6841SJoseph Chen 		version = TRUST_VERSION_STRING;
192*23ba6841SJoseph Chen 		max_size = in_size ? in_size : TRUST_MAX_SIZE;
193*23ba6841SJoseph Chen 		max_num = in_num ? in_num : TRUST_NUM;
194*23ba6841SJoseph Chen 		loader_addr =
195*23ba6841SJoseph Chen 		        (in_loader_addr == -1) ? RK_TRUST_RUNNING_ADDR : in_loader_addr;
196*23ba6841SJoseph Chen 	} else if (mode == MODE_INFO) {
197*23ba6841SJoseph Chen 
198*23ba6841SJoseph Chen 	} else {
199*23ba6841SJoseph Chen 		exit(EXIT_FAILURE);
200*23ba6841SJoseph Chen 	}
201*23ba6841SJoseph Chen 
202*23ba6841SJoseph Chen 	if (mode == MODE_PACK) {
203*23ba6841SJoseph Chen 		buf = calloc(max_size, max_num);
204*23ba6841SJoseph Chen 		if (!buf) {
205*23ba6841SJoseph Chen 			perror(file_out);
206*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
207*23ba6841SJoseph Chen 		}
208*23ba6841SJoseph Chen 		printf("\n load addr is 0x%x!\n", loader_addr);
209*23ba6841SJoseph Chen 		if (!file_in || !file_out) {
210*23ba6841SJoseph Chen 			usage(argv[0]);
211*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
212*23ba6841SJoseph Chen 		}
213*23ba6841SJoseph Chen 
214*23ba6841SJoseph Chen 		/* file in */
215*23ba6841SJoseph Chen 		fi = fopen(file_in, "rb");
216*23ba6841SJoseph Chen 		if (!fi) {
217*23ba6841SJoseph Chen 			perror(file_in);
218*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
219*23ba6841SJoseph Chen 		}
220*23ba6841SJoseph Chen 
221*23ba6841SJoseph Chen 		/* file out */
222*23ba6841SJoseph Chen 		fo = fopen(file_out, "wb");
223*23ba6841SJoseph Chen 		if (!fo) {
224*23ba6841SJoseph Chen 			perror(file_out);
225*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
226*23ba6841SJoseph Chen 		}
227*23ba6841SJoseph Chen 
228*23ba6841SJoseph Chen 		printf("pack input %s \n", file_in);
229*23ba6841SJoseph Chen 		fseek(fi, 0, SEEK_END);
230*23ba6841SJoseph Chen 		size = ftell(fi);
231*23ba6841SJoseph Chen 		fseek(fi, 0, SEEK_SET);
232*23ba6841SJoseph Chen 		printf("pack file size: %d \n", size);
233*23ba6841SJoseph Chen 		if (size > max_size - sizeof(second_loader_hdr)) {
234*23ba6841SJoseph Chen 			perror(file_out);
235*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
236*23ba6841SJoseph Chen 		}
237*23ba6841SJoseph Chen 		memset(&hdr, 0, sizeof(second_loader_hdr));
238*23ba6841SJoseph Chen 		memcpy((char *)hdr.magic, magic, LOADER_MAGIC_SIZE);
239*23ba6841SJoseph Chen 		hdr.version = curr_version;
240*23ba6841SJoseph Chen 		hdr.loader_load_addr = loader_addr;
241*23ba6841SJoseph Chen 		if (!fread(buf + sizeof(second_loader_hdr), size, 1, fi))
242*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
243*23ba6841SJoseph Chen 
244*23ba6841SJoseph Chen 		/* Aligned size to 4-byte, Rockchip HW Crypto need 4-byte align */
245*23ba6841SJoseph Chen 		size = (((size + 3) >> 2) << 2);
246*23ba6841SJoseph Chen 		hdr.loader_load_size = size;
247*23ba6841SJoseph Chen 
248*23ba6841SJoseph Chen 		hdr.crc32 = crc32_rk(
249*23ba6841SJoseph Chen 		                    0, (const unsigned char *)buf + sizeof(second_loader_hdr), size);
250*23ba6841SJoseph Chen 		printf("crc = 0x%08x\n", hdr.crc32);
251*23ba6841SJoseph Chen 
252*23ba6841SJoseph Chen #ifndef CONFIG_SECUREBOOT_SHA256
253*23ba6841SJoseph Chen 		SHA_CTX ctx;
254*23ba6841SJoseph Chen 		uint8_t *sha;
255*23ba6841SJoseph Chen 		hdr.hash_len = (SHA_DIGEST_SIZE > LOADER_HASH_SIZE) ? LOADER_HASH_SIZE
256*23ba6841SJoseph Chen 		               : SHA_DIGEST_SIZE;
257*23ba6841SJoseph Chen 		SHA_init(&ctx);
258*23ba6841SJoseph Chen 		SHA_update(&ctx, buf + sizeof(second_loader_hdr), size);
259*23ba6841SJoseph Chen 		if (hdr.version > 0)
260*23ba6841SJoseph Chen 			SHA_update(&ctx, (void *)&hdr.version, 8);
261*23ba6841SJoseph Chen 
262*23ba6841SJoseph Chen 		SHA_update(&ctx, &hdr.loader_load_addr, sizeof(hdr.loader_load_addr));
263*23ba6841SJoseph Chen 		SHA_update(&ctx, &hdr.loader_load_size, sizeof(hdr.loader_load_size));
264*23ba6841SJoseph Chen 		SHA_update(&ctx, &hdr.hash_len, sizeof(hdr.hash_len));
265*23ba6841SJoseph Chen 		sha = (uint8_t *)SHA_final(&ctx);
266*23ba6841SJoseph Chen 		memcpy(hdr.hash, sha, hdr.hash_len);
267*23ba6841SJoseph Chen #else
268*23ba6841SJoseph Chen 		sha256_context ctx;
269*23ba6841SJoseph Chen 		uint8_t hash[LOADER_HASH_SIZE];
270*23ba6841SJoseph Chen 
271*23ba6841SJoseph Chen 		memset(hash, 0, LOADER_HASH_SIZE);
272*23ba6841SJoseph Chen 
273*23ba6841SJoseph Chen 		hdr.hash_len = 32; /* sha256 */
274*23ba6841SJoseph Chen 		sha256_starts(&ctx);
275*23ba6841SJoseph Chen 		sha256_update(&ctx, (void *)buf + sizeof(second_loader_hdr), size);
276*23ba6841SJoseph Chen 		if (hdr.version > 0)
277*23ba6841SJoseph Chen 			sha256_update(&ctx, (void *)&hdr.version, 8);
278*23ba6841SJoseph Chen 
279*23ba6841SJoseph Chen 		sha256_update(&ctx, (void *)&hdr.loader_load_addr,
280*23ba6841SJoseph Chen 		              sizeof(hdr.loader_load_addr));
281*23ba6841SJoseph Chen 		sha256_update(&ctx, (void *)&hdr.loader_load_size,
282*23ba6841SJoseph Chen 		              sizeof(hdr.loader_load_size));
283*23ba6841SJoseph Chen 		sha256_update(&ctx, (void *)&hdr.hash_len, sizeof(hdr.hash_len));
284*23ba6841SJoseph Chen 		sha256_finish(&ctx, hash);
285*23ba6841SJoseph Chen 		memcpy(hdr.hash, hash, hdr.hash_len);
286*23ba6841SJoseph Chen #endif /* CONFIG_SECUREBOOT_SHA256 */
287*23ba6841SJoseph Chen 
288*23ba6841SJoseph Chen 		printf("%s version: %s\n", name, version);
289*23ba6841SJoseph Chen 		memcpy(buf, &hdr, sizeof(second_loader_hdr));
290*23ba6841SJoseph Chen 		for (i = 0; i < max_num; i++)
291*23ba6841SJoseph Chen 			fwrite(buf, max_size, 1, fo);
292*23ba6841SJoseph Chen 
293*23ba6841SJoseph Chen 		printf("pack %s success! \n", file_out);
294*23ba6841SJoseph Chen 		fclose(fi);
295*23ba6841SJoseph Chen 		fclose(fo);
296*23ba6841SJoseph Chen 	} else if (mode == MODE_UNPACK) {
297*23ba6841SJoseph Chen 		buf = calloc(max_size, max_num);
298*23ba6841SJoseph Chen 		if (!buf) {
299*23ba6841SJoseph Chen 			perror(file_out);
300*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
301*23ba6841SJoseph Chen 		}
302*23ba6841SJoseph Chen 		if (!file_in || !file_out) {
303*23ba6841SJoseph Chen 			usage(argv[0]);
304*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
305*23ba6841SJoseph Chen 		}
306*23ba6841SJoseph Chen 
307*23ba6841SJoseph Chen 		/* file in */
308*23ba6841SJoseph Chen 		fi = fopen(file_in, "rb");
309*23ba6841SJoseph Chen 		if (!fi) {
310*23ba6841SJoseph Chen 			perror(file_in);
311*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
312*23ba6841SJoseph Chen 		}
313*23ba6841SJoseph Chen 
314*23ba6841SJoseph Chen 		/* file out */
315*23ba6841SJoseph Chen 		fo = fopen(file_out, "wb");
316*23ba6841SJoseph Chen 		if (!fo) {
317*23ba6841SJoseph Chen 			perror(file_out);
318*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
319*23ba6841SJoseph Chen 		}
320*23ba6841SJoseph Chen 
321*23ba6841SJoseph Chen 		printf("unpack input %s \n", file_in);
322*23ba6841SJoseph Chen 		memset(&hdr, 0, sizeof(second_loader_hdr));
323*23ba6841SJoseph Chen 		if (!fread(&hdr, sizeof(second_loader_hdr), 1, fi))
324*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
325*23ba6841SJoseph Chen 
326*23ba6841SJoseph Chen 		if (!fread(buf, hdr.loader_load_size, 1, fi))
327*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
328*23ba6841SJoseph Chen 
329*23ba6841SJoseph Chen 		fwrite(buf, hdr.loader_load_size, 1, fo);
330*23ba6841SJoseph Chen 		printf("unpack %s success! \n", file_out);
331*23ba6841SJoseph Chen 		fclose(fi);
332*23ba6841SJoseph Chen 		fclose(fo);
333*23ba6841SJoseph Chen 	} else if (mode == MODE_INFO) {
334*23ba6841SJoseph Chen 		second_loader_hdr *hdr;
335*23ba6841SJoseph Chen 
336*23ba6841SJoseph Chen 		hdr = malloc(sizeof(struct tag_second_loader_hdr));
337*23ba6841SJoseph Chen 		if (hdr == NULL) {
338*23ba6841SJoseph Chen 			printf("Memory error!\n");
339*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
340*23ba6841SJoseph Chen 		}
341*23ba6841SJoseph Chen 		/* file in */
342*23ba6841SJoseph Chen 		fi = fopen(file_in, "rb");
343*23ba6841SJoseph Chen 		if (!fi) {
344*23ba6841SJoseph Chen 			perror(file_in);
345*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
346*23ba6841SJoseph Chen 		}
347*23ba6841SJoseph Chen 
348*23ba6841SJoseph Chen 		if (!fread(hdr, sizeof(struct tag_second_loader_hdr), 1, fi))
349*23ba6841SJoseph Chen 			exit(EXIT_FAILURE);
350*23ba6841SJoseph Chen 
351*23ba6841SJoseph Chen 		if (!(memcmp(RK_UBOOT_MAGIC, hdr->magic, 5)) ||
352*23ba6841SJoseph Chen 		    !(memcmp(RK_TRUST_MAGIC, hdr->magic, 3))) {
353*23ba6841SJoseph Chen 			printf("The image info:\n");
354*23ba6841SJoseph Chen 			printf("Rollback index is %d\n", hdr->version);
355*23ba6841SJoseph Chen 			printf("Load Addr is 0x%x\n", hdr->loader_load_addr);
356*23ba6841SJoseph Chen 		} else {
357*23ba6841SJoseph Chen 			printf("Please input the correct file.\n");
358*23ba6841SJoseph Chen 		}
359*23ba6841SJoseph Chen 
360*23ba6841SJoseph Chen 		fclose(fi);
361*23ba6841SJoseph Chen 		free(hdr);
362*23ba6841SJoseph Chen 	}
363*23ba6841SJoseph Chen 	free(buf);
364*23ba6841SJoseph Chen 
365*23ba6841SJoseph Chen 	return 0;
366*23ba6841SJoseph Chen }
367