xref: /rk3399_rockchip-uboot/tools/rockchip/loaderimage.c (revision 52243bce1370e760206595b1222fa0bf7757f0a1)
123ba6841SJoseph Chen /*
223ba6841SJoseph Chen  * (C) Copyright 2008-2015 Fuzhou Rockchip Electronics Co., Ltd
323ba6841SJoseph Chen  *
423ba6841SJoseph Chen  * SPDX-License-Identifier:	GPL-2.0+
523ba6841SJoseph Chen  */
623ba6841SJoseph Chen #include "compiler.h"
723ba6841SJoseph Chen #include <version.h>
823ba6841SJoseph Chen #include "sha.h"
923ba6841SJoseph Chen #include <u-boot/sha256.h>
1023ba6841SJoseph Chen #include <u-boot/crc.h>
1123ba6841SJoseph Chen #include <linux/sizes.h>
1223ba6841SJoseph Chen #include <linux/kconfig.h>
1323ba6841SJoseph Chen #include <config.h>
1423ba6841SJoseph Chen 
1523ba6841SJoseph Chen extern uint32_t crc32_rk(uint32_t, const unsigned char *, uint32_t);
1623ba6841SJoseph Chen 
1723ba6841SJoseph Chen #define OPT_PACK "--pack"
1823ba6841SJoseph Chen #define OPT_UNPACK "--unpack"
1923ba6841SJoseph Chen #define OPT_UBOOT "--uboot"
2023ba6841SJoseph Chen #define OPT_TRUSTOS "--trustos"
2123ba6841SJoseph Chen #define OPT_SIZE "--size"
2223ba6841SJoseph Chen #define OPT_VERSION "--version"
2323ba6841SJoseph Chen #define OPT_INFO "--info"
24*52243bceSJoseph Chen #define OPT_PREPATH             "--prepath"
2523ba6841SJoseph Chen 
2623ba6841SJoseph Chen /* pack or unpack */
2723ba6841SJoseph Chen #define MODE_PACK 0
2823ba6841SJoseph Chen #define MODE_UNPACK 1
2923ba6841SJoseph Chen #define MODE_INFO 2
3023ba6841SJoseph Chen #define CONFIG_SECUREBOOT_SHA256
3123ba6841SJoseph Chen 
3223ba6841SJoseph Chen /* image type */
3323ba6841SJoseph Chen #define IMAGE_UBOOT 0
3423ba6841SJoseph Chen #define IMAGE_TRUST 1
3523ba6841SJoseph Chen 
3623ba6841SJoseph Chen /* magic and hash size */
3723ba6841SJoseph Chen #define LOADER_MAGIC_SIZE 8
3823ba6841SJoseph Chen #define LOADER_HASH_SIZE 32
3923ba6841SJoseph Chen 
4023ba6841SJoseph Chen /* uboot image config */
4123ba6841SJoseph Chen #define UBOOT_NAME "uboot"
4223ba6841SJoseph Chen #ifdef CONFIG_RK_NVME_BOOT_EN
4323ba6841SJoseph Chen #define UBOOT_NUM 2
4423ba6841SJoseph Chen #define UBOOT_MAX_SIZE 512 * 1024
4523ba6841SJoseph Chen #else
4623ba6841SJoseph Chen #define UBOOT_NUM 4
4723ba6841SJoseph Chen #define UBOOT_MAX_SIZE 1024 * 1024
4823ba6841SJoseph Chen #endif
4923ba6841SJoseph Chen 
5023ba6841SJoseph Chen #define UBOOT_VERSION_STRING                                                   \
5123ba6841SJoseph Chen   U_BOOT_VERSION " (" U_BOOT_DATE " - " U_BOOT_TIME ")" CONFIG_IDENT_STRING
5223ba6841SJoseph Chen 
5323ba6841SJoseph Chen #define RK_UBOOT_MAGIC "LOADER  "
5423ba6841SJoseph Chen #define RK_UBOOT_RUNNING_ADDR CONFIG_SYS_TEXT_BASE
5523ba6841SJoseph Chen 
5623ba6841SJoseph Chen /* trust image config */
5723ba6841SJoseph Chen #define TRUST_NAME "trustos"
5823ba6841SJoseph Chen #define TRUST_NUM 4
5923ba6841SJoseph Chen #define TRUST_MAX_SIZE 1024 * 1024
6023ba6841SJoseph Chen #define TRUST_VERSION_STRING "Trust os"
6123ba6841SJoseph Chen 
6223ba6841SJoseph Chen #define RK_TRUST_MAGIC "TOS     "
6323ba6841SJoseph Chen #define RK_TRUST_RUNNING_ADDR (CONFIG_SYS_TEXT_BASE + SZ_128M + SZ_4M)
6423ba6841SJoseph Chen 
6523ba6841SJoseph Chen typedef struct tag_second_loader_hdr {
6623ba6841SJoseph Chen 	uint8_t magic[LOADER_MAGIC_SIZE]; /* magic */
6723ba6841SJoseph Chen 	uint32_t version;
6823ba6841SJoseph Chen 	uint32_t reserved0;
6923ba6841SJoseph Chen 	uint32_t loader_load_addr;      /* physical load addr */
7023ba6841SJoseph Chen 	uint32_t loader_load_size;      /* size in bytes */
7123ba6841SJoseph Chen 	uint32_t crc32;                 /* crc32 */
7223ba6841SJoseph Chen 	uint32_t hash_len;              /* 20 or 32 , 0 is no hash */
7323ba6841SJoseph Chen 	uint8_t hash[LOADER_HASH_SIZE]; /* sha */
7423ba6841SJoseph Chen 
7523ba6841SJoseph Chen 	uint8_t reserved[1024 - 32 - 32];
7623ba6841SJoseph Chen 	uint32_t signTag;     /* 0x4E474953 */
7723ba6841SJoseph Chen 	uint32_t signlen;     /* maybe 128 or 256 */
7823ba6841SJoseph Chen 	uint8_t rsaHash[256]; /* maybe 128 or 256, using max size 256 */
7923ba6841SJoseph Chen 	uint8_t reserved2[2048 - 1024 - 256 - 8];
8023ba6841SJoseph Chen } second_loader_hdr;
8123ba6841SJoseph Chen 
8223ba6841SJoseph Chen void usage(const char *prog)
8323ba6841SJoseph Chen {
8423ba6841SJoseph Chen 	fprintf(stderr, "Usage: %s [--pack|--unpack] [--uboot|--trustos]\
8523ba6841SJoseph Chen 		file_in "
8623ba6841SJoseph Chen 	        "file_out [load_addr]  [--size] [size number]\
8723ba6841SJoseph Chen 		[--version] "
8823ba6841SJoseph Chen 	        "[version] | [--info] [file]\n",
8923ba6841SJoseph Chen 	        prog);
9023ba6841SJoseph Chen }
9123ba6841SJoseph Chen 
9223ba6841SJoseph Chen unsigned int str2hex(char *str)
9323ba6841SJoseph Chen {
9423ba6841SJoseph Chen 	int i = 0;
9523ba6841SJoseph Chen 	unsigned int value = 0;
9623ba6841SJoseph Chen 
9723ba6841SJoseph Chen 	if (*str == '0' && (*(str + 1) == 'x' || *(str + 1) == 'X'))
9823ba6841SJoseph Chen 		str += 2;
9923ba6841SJoseph Chen 	if (*str == 'x' || *str == 'X')
10023ba6841SJoseph Chen 		str += 1;
10123ba6841SJoseph Chen 
10223ba6841SJoseph Chen 	for (i = 0; *str != '\0'; i++, ++str) {
10323ba6841SJoseph Chen 		if (*str >= '0' && *str <= '9')
10423ba6841SJoseph Chen 			value = value * 16 + *str - '0';
10523ba6841SJoseph Chen 		else if (*str >= 'a' && *str <= 'f')
10623ba6841SJoseph Chen 			value = value * 16 + *str - 'a' + 10;
10723ba6841SJoseph Chen 		else if (*str >= 'A' && *str <= 'F')
10823ba6841SJoseph Chen 			value = value * 16 + *str - 'A' + 10;
10923ba6841SJoseph Chen 		else
11023ba6841SJoseph Chen 			break;
11123ba6841SJoseph Chen 	}
11223ba6841SJoseph Chen 	return value;
11323ba6841SJoseph Chen }
11423ba6841SJoseph Chen 
11523ba6841SJoseph Chen int main(int argc, char *argv[])
11623ba6841SJoseph Chen {
11723ba6841SJoseph Chen 	int mode = -1, image = -1;
11823ba6841SJoseph Chen 	int max_size, max_num;
11923ba6841SJoseph Chen 	int size, i;
12023ba6841SJoseph Chen 	uint32_t loader_addr, in_loader_addr = -1;
12123ba6841SJoseph Chen 	char *magic, *version, *name;
12223ba6841SJoseph Chen 	FILE *fi, *fo;
12323ba6841SJoseph Chen 	second_loader_hdr hdr;
12423ba6841SJoseph Chen 	char *buf = 0;
12523ba6841SJoseph Chen 	uint32_t in_size = 0, in_num = 0;
12623ba6841SJoseph Chen 	char *file_in = NULL, *file_out = NULL;
127*52243bceSJoseph Chen 	char			*prepath = NULL;
128*52243bceSJoseph Chen 	char			file_name[1024];
12923ba6841SJoseph Chen 	uint32_t curr_version = 0;
13023ba6841SJoseph Chen 
13123ba6841SJoseph Chen 	if (argc < 3) {
13223ba6841SJoseph Chen 		usage(argv[0]);
13323ba6841SJoseph Chen 		exit(EXIT_FAILURE);
13423ba6841SJoseph Chen 	}
13523ba6841SJoseph Chen 
13623ba6841SJoseph Chen 	for (i = 1; i < argc; i++) {
13723ba6841SJoseph Chen 		if (!strcmp(argv[i], OPT_PACK)) {
13823ba6841SJoseph Chen 			mode = MODE_PACK;
13923ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_UNPACK)) {
14023ba6841SJoseph Chen 			mode = MODE_UNPACK;
14123ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_UBOOT)) {
14223ba6841SJoseph Chen 			image = IMAGE_UBOOT;
14323ba6841SJoseph Chen 			file_in = argv[++i];
14423ba6841SJoseph Chen 			file_out = argv[++i];
14523ba6841SJoseph Chen 			/* detect whether loader address is delivered */
14623ba6841SJoseph Chen 			if ((argv[i + 1]) && (strncmp(argv[i + 1], "--", 2)))
14723ba6841SJoseph Chen 				in_loader_addr = str2hex(argv[++i]);
14823ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_TRUSTOS)) {
14923ba6841SJoseph Chen 			image = IMAGE_TRUST;
15023ba6841SJoseph Chen 			file_in = argv[++i];
15123ba6841SJoseph Chen 			file_out = argv[++i];
15223ba6841SJoseph Chen 			/* detect whether loader address is delivered */
15323ba6841SJoseph Chen 			if ((argv[i + 1]) && (strncmp(argv[i + 1], "--", 2)))
15423ba6841SJoseph Chen 				in_loader_addr = str2hex(argv[++i]);
15523ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_SIZE)) {
15623ba6841SJoseph Chen 			in_size = strtoul(argv[++i], NULL, 10);
15723ba6841SJoseph Chen 			/*
15823ba6841SJoseph Chen 			 * Usually, it must be at 512kb align due to preloader
15923ba6841SJoseph Chen 			 * detects every 512kb. But some product has critial
16023ba6841SJoseph Chen 			 * flash size requirement, we have to make it small than
16123ba6841SJoseph Chen 			 * 512KB.
16223ba6841SJoseph Chen 			 */
16323ba6841SJoseph Chen 			if (in_size % 64) {
16423ba6841SJoseph Chen 				usage(argv[0]);
16523ba6841SJoseph Chen 				exit(EXIT_FAILURE);
16623ba6841SJoseph Chen 			}
16723ba6841SJoseph Chen 			in_size *= 1024;
16823ba6841SJoseph Chen 
16923ba6841SJoseph Chen 			in_num = strtoul(argv[++i], NULL, 10);
17023ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_VERSION)) {
17123ba6841SJoseph Chen 			curr_version = strtoul(argv[++i], NULL, 10);
17223ba6841SJoseph Chen 			printf("curr_version = 0x%x\n", curr_version);
17323ba6841SJoseph Chen 		} else if (!strcmp(argv[i], OPT_INFO)) {
17423ba6841SJoseph Chen 			mode = MODE_INFO;
17523ba6841SJoseph Chen 			file_in = argv[++i];
176*52243bceSJoseph Chen 		} else if (!strcmp(argv[i], OPT_PREPATH)) {
177*52243bceSJoseph Chen 			prepath = argv[++i];
17823ba6841SJoseph Chen 		} else {
17923ba6841SJoseph Chen 			usage(argv[0]);
18023ba6841SJoseph Chen 			exit(EXIT_FAILURE);
18123ba6841SJoseph Chen 		}
18223ba6841SJoseph Chen 	}
18323ba6841SJoseph Chen 
18423ba6841SJoseph Chen 	/* config image information */
18523ba6841SJoseph Chen 	if (image == IMAGE_UBOOT) {
18623ba6841SJoseph Chen 		name = UBOOT_NAME;
18723ba6841SJoseph Chen 		magic = RK_UBOOT_MAGIC;
18823ba6841SJoseph Chen 		version = UBOOT_VERSION_STRING;
18923ba6841SJoseph Chen 		max_size = in_size ? in_size : UBOOT_MAX_SIZE;
19023ba6841SJoseph Chen 		max_num = in_num ? in_num : UBOOT_NUM;
19123ba6841SJoseph Chen 		loader_addr =
19223ba6841SJoseph Chen 		        (in_loader_addr == -1) ? RK_UBOOT_RUNNING_ADDR : in_loader_addr;
19323ba6841SJoseph Chen 	} else if (image == IMAGE_TRUST) {
19423ba6841SJoseph Chen 		name = TRUST_NAME;
19523ba6841SJoseph Chen 		magic = RK_TRUST_MAGIC;
19623ba6841SJoseph Chen 		version = TRUST_VERSION_STRING;
19723ba6841SJoseph Chen 		max_size = in_size ? in_size : TRUST_MAX_SIZE;
19823ba6841SJoseph Chen 		max_num = in_num ? in_num : TRUST_NUM;
19923ba6841SJoseph Chen 		loader_addr =
20023ba6841SJoseph Chen 		        (in_loader_addr == -1) ? RK_TRUST_RUNNING_ADDR : in_loader_addr;
20123ba6841SJoseph Chen 	} else if (mode == MODE_INFO) {
20223ba6841SJoseph Chen 
20323ba6841SJoseph Chen 	} else {
20423ba6841SJoseph Chen 		exit(EXIT_FAILURE);
20523ba6841SJoseph Chen 	}
20623ba6841SJoseph Chen 
20723ba6841SJoseph Chen 	if (mode == MODE_PACK) {
20823ba6841SJoseph Chen 		buf = calloc(max_size, max_num);
20923ba6841SJoseph Chen 		if (!buf) {
21023ba6841SJoseph Chen 			perror(file_out);
21123ba6841SJoseph Chen 			exit(EXIT_FAILURE);
21223ba6841SJoseph Chen 		}
21323ba6841SJoseph Chen 		printf("\n load addr is 0x%x!\n", loader_addr);
214*52243bceSJoseph Chen 
215*52243bceSJoseph Chen 		/* Add prepath for file_in name */
216*52243bceSJoseph Chen 		if (prepath && strncmp(prepath, file_in, strlen(prepath))) {
217*52243bceSJoseph Chen 			strcpy(file_name, prepath);
218*52243bceSJoseph Chen 			strcat(file_name, file_in);
219*52243bceSJoseph Chen 			file_in = file_name;
220*52243bceSJoseph Chen 		}
221*52243bceSJoseph Chen 
22223ba6841SJoseph Chen 		if (!file_in || !file_out) {
22323ba6841SJoseph Chen 			usage(argv[0]);
22423ba6841SJoseph Chen 			exit(EXIT_FAILURE);
22523ba6841SJoseph Chen 		}
22623ba6841SJoseph Chen 
22723ba6841SJoseph Chen 		/* file in */
22823ba6841SJoseph Chen 		fi = fopen(file_in, "rb");
22923ba6841SJoseph Chen 		if (!fi) {
23023ba6841SJoseph Chen 			perror(file_in);
23123ba6841SJoseph Chen 			exit(EXIT_FAILURE);
23223ba6841SJoseph Chen 		}
23323ba6841SJoseph Chen 
23423ba6841SJoseph Chen 		/* file out */
23523ba6841SJoseph Chen 		fo = fopen(file_out, "wb");
23623ba6841SJoseph Chen 		if (!fo) {
23723ba6841SJoseph Chen 			perror(file_out);
23823ba6841SJoseph Chen 			exit(EXIT_FAILURE);
23923ba6841SJoseph Chen 		}
24023ba6841SJoseph Chen 
24123ba6841SJoseph Chen 		printf("pack input %s \n", file_in);
24223ba6841SJoseph Chen 		fseek(fi, 0, SEEK_END);
24323ba6841SJoseph Chen 		size = ftell(fi);
24423ba6841SJoseph Chen 		fseek(fi, 0, SEEK_SET);
2452bbbd780SJoseph Chen 		printf("pack file size: %d(%d KB)\n", size, size / 1024);
24623ba6841SJoseph Chen 		if (size > max_size - sizeof(second_loader_hdr)) {
24723ba6841SJoseph Chen 			perror(file_out);
24823ba6841SJoseph Chen 			exit(EXIT_FAILURE);
24923ba6841SJoseph Chen 		}
25023ba6841SJoseph Chen 		memset(&hdr, 0, sizeof(second_loader_hdr));
25123ba6841SJoseph Chen 		memcpy((char *)hdr.magic, magic, LOADER_MAGIC_SIZE);
25223ba6841SJoseph Chen 		hdr.version = curr_version;
25323ba6841SJoseph Chen 		hdr.loader_load_addr = loader_addr;
25423ba6841SJoseph Chen 		if (!fread(buf + sizeof(second_loader_hdr), size, 1, fi))
25523ba6841SJoseph Chen 			exit(EXIT_FAILURE);
25623ba6841SJoseph Chen 
25723ba6841SJoseph Chen 		/* Aligned size to 4-byte, Rockchip HW Crypto need 4-byte align */
25823ba6841SJoseph Chen 		size = (((size + 3) >> 2) << 2);
25923ba6841SJoseph Chen 		hdr.loader_load_size = size;
26023ba6841SJoseph Chen 
26123ba6841SJoseph Chen 		hdr.crc32 = crc32_rk(
26223ba6841SJoseph Chen 		                    0, (const unsigned char *)buf + sizeof(second_loader_hdr), size);
26323ba6841SJoseph Chen 		printf("crc = 0x%08x\n", hdr.crc32);
26423ba6841SJoseph Chen 
26523ba6841SJoseph Chen #ifndef CONFIG_SECUREBOOT_SHA256
26623ba6841SJoseph Chen 		SHA_CTX ctx;
26723ba6841SJoseph Chen 		uint8_t *sha;
26823ba6841SJoseph Chen 		hdr.hash_len = (SHA_DIGEST_SIZE > LOADER_HASH_SIZE) ? LOADER_HASH_SIZE
26923ba6841SJoseph Chen 		               : SHA_DIGEST_SIZE;
27023ba6841SJoseph Chen 		SHA_init(&ctx);
27123ba6841SJoseph Chen 		SHA_update(&ctx, buf + sizeof(second_loader_hdr), size);
27223ba6841SJoseph Chen 		if (hdr.version > 0)
27323ba6841SJoseph Chen 			SHA_update(&ctx, (void *)&hdr.version, 8);
27423ba6841SJoseph Chen 
27523ba6841SJoseph Chen 		SHA_update(&ctx, &hdr.loader_load_addr, sizeof(hdr.loader_load_addr));
27623ba6841SJoseph Chen 		SHA_update(&ctx, &hdr.loader_load_size, sizeof(hdr.loader_load_size));
27723ba6841SJoseph Chen 		SHA_update(&ctx, &hdr.hash_len, sizeof(hdr.hash_len));
27823ba6841SJoseph Chen 		sha = (uint8_t *)SHA_final(&ctx);
27923ba6841SJoseph Chen 		memcpy(hdr.hash, sha, hdr.hash_len);
28023ba6841SJoseph Chen #else
28123ba6841SJoseph Chen 		sha256_context ctx;
28223ba6841SJoseph Chen 		uint8_t hash[LOADER_HASH_SIZE];
28323ba6841SJoseph Chen 
28423ba6841SJoseph Chen 		memset(hash, 0, LOADER_HASH_SIZE);
28523ba6841SJoseph Chen 
28623ba6841SJoseph Chen 		hdr.hash_len = 32; /* sha256 */
28723ba6841SJoseph Chen 		sha256_starts(&ctx);
28823ba6841SJoseph Chen 		sha256_update(&ctx, (void *)buf + sizeof(second_loader_hdr), size);
28923ba6841SJoseph Chen 		if (hdr.version > 0)
29023ba6841SJoseph Chen 			sha256_update(&ctx, (void *)&hdr.version, 8);
29123ba6841SJoseph Chen 
29223ba6841SJoseph Chen 		sha256_update(&ctx, (void *)&hdr.loader_load_addr,
29323ba6841SJoseph Chen 		              sizeof(hdr.loader_load_addr));
29423ba6841SJoseph Chen 		sha256_update(&ctx, (void *)&hdr.loader_load_size,
29523ba6841SJoseph Chen 		              sizeof(hdr.loader_load_size));
29623ba6841SJoseph Chen 		sha256_update(&ctx, (void *)&hdr.hash_len, sizeof(hdr.hash_len));
29723ba6841SJoseph Chen 		sha256_finish(&ctx, hash);
29823ba6841SJoseph Chen 		memcpy(hdr.hash, hash, hdr.hash_len);
29923ba6841SJoseph Chen #endif /* CONFIG_SECUREBOOT_SHA256 */
30023ba6841SJoseph Chen 
30123ba6841SJoseph Chen 		printf("%s version: %s\n", name, version);
30223ba6841SJoseph Chen 		memcpy(buf, &hdr, sizeof(second_loader_hdr));
30323ba6841SJoseph Chen 		for (i = 0; i < max_num; i++)
30423ba6841SJoseph Chen 			fwrite(buf, max_size, 1, fo);
30523ba6841SJoseph Chen 
30623ba6841SJoseph Chen 		printf("pack %s success! \n", file_out);
30723ba6841SJoseph Chen 		fclose(fi);
30823ba6841SJoseph Chen 		fclose(fo);
30923ba6841SJoseph Chen 	} else if (mode == MODE_UNPACK) {
31023ba6841SJoseph Chen 		buf = calloc(max_size, max_num);
31123ba6841SJoseph Chen 		if (!buf) {
31223ba6841SJoseph Chen 			perror(file_out);
31323ba6841SJoseph Chen 			exit(EXIT_FAILURE);
31423ba6841SJoseph Chen 		}
31523ba6841SJoseph Chen 		if (!file_in || !file_out) {
31623ba6841SJoseph Chen 			usage(argv[0]);
31723ba6841SJoseph Chen 			exit(EXIT_FAILURE);
31823ba6841SJoseph Chen 		}
31923ba6841SJoseph Chen 
32023ba6841SJoseph Chen 		/* file in */
32123ba6841SJoseph Chen 		fi = fopen(file_in, "rb");
32223ba6841SJoseph Chen 		if (!fi) {
32323ba6841SJoseph Chen 			perror(file_in);
32423ba6841SJoseph Chen 			exit(EXIT_FAILURE);
32523ba6841SJoseph Chen 		}
32623ba6841SJoseph Chen 
32723ba6841SJoseph Chen 		/* file out */
32823ba6841SJoseph Chen 		fo = fopen(file_out, "wb");
32923ba6841SJoseph Chen 		if (!fo) {
33023ba6841SJoseph Chen 			perror(file_out);
33123ba6841SJoseph Chen 			exit(EXIT_FAILURE);
33223ba6841SJoseph Chen 		}
33323ba6841SJoseph Chen 
33423ba6841SJoseph Chen 		printf("unpack input %s \n", file_in);
33523ba6841SJoseph Chen 		memset(&hdr, 0, sizeof(second_loader_hdr));
33623ba6841SJoseph Chen 		if (!fread(&hdr, sizeof(second_loader_hdr), 1, fi))
33723ba6841SJoseph Chen 			exit(EXIT_FAILURE);
33823ba6841SJoseph Chen 
33923ba6841SJoseph Chen 		if (!fread(buf, hdr.loader_load_size, 1, fi))
34023ba6841SJoseph Chen 			exit(EXIT_FAILURE);
34123ba6841SJoseph Chen 
34223ba6841SJoseph Chen 		fwrite(buf, hdr.loader_load_size, 1, fo);
34323ba6841SJoseph Chen 		printf("unpack %s success! \n", file_out);
34423ba6841SJoseph Chen 		fclose(fi);
34523ba6841SJoseph Chen 		fclose(fo);
34623ba6841SJoseph Chen 	} else if (mode == MODE_INFO) {
34723ba6841SJoseph Chen 		second_loader_hdr *hdr;
34823ba6841SJoseph Chen 
34923ba6841SJoseph Chen 		hdr = malloc(sizeof(struct tag_second_loader_hdr));
35023ba6841SJoseph Chen 		if (hdr == NULL) {
35123ba6841SJoseph Chen 			printf("Memory error!\n");
35223ba6841SJoseph Chen 			exit(EXIT_FAILURE);
35323ba6841SJoseph Chen 		}
35423ba6841SJoseph Chen 		/* file in */
35523ba6841SJoseph Chen 		fi = fopen(file_in, "rb");
35623ba6841SJoseph Chen 		if (!fi) {
35723ba6841SJoseph Chen 			perror(file_in);
35823ba6841SJoseph Chen 			exit(EXIT_FAILURE);
35923ba6841SJoseph Chen 		}
36023ba6841SJoseph Chen 
36123ba6841SJoseph Chen 		if (!fread(hdr, sizeof(struct tag_second_loader_hdr), 1, fi))
36223ba6841SJoseph Chen 			exit(EXIT_FAILURE);
36323ba6841SJoseph Chen 
36423ba6841SJoseph Chen 		if (!(memcmp(RK_UBOOT_MAGIC, hdr->magic, 5)) ||
36523ba6841SJoseph Chen 		    !(memcmp(RK_TRUST_MAGIC, hdr->magic, 3))) {
36623ba6841SJoseph Chen 			printf("The image info:\n");
36723ba6841SJoseph Chen 			printf("Rollback index is %d\n", hdr->version);
36823ba6841SJoseph Chen 			printf("Load Addr is 0x%x\n", hdr->loader_load_addr);
36923ba6841SJoseph Chen 		} else {
37023ba6841SJoseph Chen 			printf("Please input the correct file.\n");
37123ba6841SJoseph Chen 		}
37223ba6841SJoseph Chen 
37323ba6841SJoseph Chen 		fclose(fi);
37423ba6841SJoseph Chen 		free(hdr);
37523ba6841SJoseph Chen 	}
37623ba6841SJoseph Chen 	free(buf);
37723ba6841SJoseph Chen 
37823ba6841SJoseph Chen 	return 0;
37923ba6841SJoseph Chen }
380