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