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