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