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 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 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 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 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