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