1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. 4 */ 5 6#include <common.h> 7#include <command.h> 8#include <config.h> 9#include <display_options.h> 10#include <fuse.h> 11#include <mapmem.h> 12#include <image.h> 13#include <asm/io.h> 14#include <asm/global_data.h> 15#include <asm/system.h> 16#include <asm/arch/clock.h> 17#include <asm/arch/sys_proto.h> 18#include <asm/mach-imx/hab.h> 19#include <linux/arm-smccc.h> 20 21DECLARE_GLOBAL_DATA_PTR; 22 23#define ALIGN_SIZE 0x1000 24#define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8 25#define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0 26#define MX6SL_PU_IROM_MMU_EN_VAR 0x00901c60 27#define IS_HAB_ENABLED_BIT \ 28 (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \ 29 ((is_soc_type(MXC_SOC_MX7) || is_soc_type(MXC_SOC_IMX8M)) ? 0x2000000 : 0x2)) 30 31#ifdef CONFIG_MX7ULP 32#define HAB_M4_PERSISTENT_START ((soc_rev() >= CHIP_REV_2_0) ? 0x20008040 : \ 33 0x20008180) 34#define HAB_M4_PERSISTENT_BYTES 0xB80 35#endif 36 37static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr) 38{ 39 printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str, 40 ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version); 41 42 return 1; 43} 44 45static int verify_ivt_header(struct ivt_header *ivt_hdr) 46{ 47 int result = 0; 48 49 if (ivt_hdr->magic != IVT_HEADER_MAGIC) 50 result = ivt_header_error("bad magic", ivt_hdr); 51 52 if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH) 53 result = ivt_header_error("bad length", ivt_hdr); 54 55 if ((ivt_hdr->version & HAB_MAJ_MASK) != HAB_MAJ_VER) 56 result = ivt_header_error("bad version", ivt_hdr); 57 58 return result; 59} 60 61#ifdef CONFIG_ARM64 62#define FSL_SIP_HAB 0xC2000007 63#define FSL_SIP_HAB_AUTHENTICATE 0x00 64#define FSL_SIP_HAB_ENTRY 0x01 65#define FSL_SIP_HAB_EXIT 0x02 66#define FSL_SIP_HAB_REPORT_EVENT 0x03 67#define FSL_SIP_HAB_REPORT_STATUS 0x04 68#define FSL_SIP_HAB_FAILSAFE 0x05 69#define FSL_SIP_HAB_CHECK_TARGET 0x06 70static volatile gd_t *gd_save; 71#endif 72 73static inline void save_gd(void) 74{ 75#ifdef CONFIG_ARM64 76 gd_save = gd; 77#endif 78} 79 80static inline void restore_gd(void) 81{ 82#ifdef CONFIG_ARM64 83 /* 84 * Make will already error that reserving x18 is not supported at the 85 * time of writing, clang: error: unknown argument: '-ffixed-x18' 86 */ 87 __asm__ volatile("mov x18, %0\n" : : "r" (gd_save)); 88#endif 89} 90 91enum hab_status hab_rvt_report_event(enum hab_status status, u32 index, 92 u8 *event, size_t *bytes) 93{ 94 enum hab_status ret; 95 hab_rvt_report_event_t *hab_rvt_report_event_func; 96 struct arm_smccc_res res __maybe_unused; 97 98 hab_rvt_report_event_func = (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT; 99#if defined(CONFIG_ARM64) 100 if (current_el() != 3) { 101 /* call sip */ 102 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_EVENT, (unsigned long)index, 103 (unsigned long)event, (unsigned long)bytes, 0, 0, 0, &res); 104 return (enum hab_status)res.a0; 105 } 106#endif 107 108 save_gd(); 109 ret = hab_rvt_report_event_func(status, index, event, bytes); 110 restore_gd(); 111 112 return ret; 113 114} 115 116enum hab_status hab_rvt_report_status(enum hab_config *config, enum hab_state *state) 117{ 118 enum hab_status ret; 119 hab_rvt_report_status_t *hab_rvt_report_status_func; 120 struct arm_smccc_res res __maybe_unused; 121 122 hab_rvt_report_status_func = (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS; 123#if defined(CONFIG_ARM64) 124 if (current_el() != 3) { 125 /* call sip */ 126 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_REPORT_STATUS, (unsigned long)config, 127 (unsigned long)state, 0, 0, 0, 0, &res); 128 return (enum hab_status)res.a0; 129 } 130#endif 131 132 save_gd(); 133 ret = hab_rvt_report_status_func(config, state); 134 restore_gd(); 135 136 return ret; 137} 138 139enum hab_status hab_rvt_entry(void) 140{ 141 enum hab_status ret; 142 hab_rvt_entry_t *hab_rvt_entry_func; 143 struct arm_smccc_res res __maybe_unused; 144 145 hab_rvt_entry_func = (hab_rvt_entry_t *)HAB_RVT_ENTRY; 146#if defined(CONFIG_ARM64) 147 if (current_el() != 3) { 148 /* call sip */ 149 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_ENTRY, 0, 0, 0, 0, 0, 0, &res); 150 return (enum hab_status)res.a0; 151 } 152#endif 153 154 save_gd(); 155 ret = hab_rvt_entry_func(); 156 restore_gd(); 157 158 return ret; 159} 160 161enum hab_status hab_rvt_exit(void) 162{ 163 enum hab_status ret; 164 hab_rvt_exit_t *hab_rvt_exit_func; 165 struct arm_smccc_res res __maybe_unused; 166 167 hab_rvt_exit_func = (hab_rvt_exit_t *)HAB_RVT_EXIT; 168#if defined(CONFIG_ARM64) 169 if (current_el() != 3) { 170 /* call sip */ 171 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_EXIT, 0, 0, 0, 0, 0, 0, &res); 172 return (enum hab_status)res.a0; 173 } 174#endif 175 176 save_gd(); 177 ret = hab_rvt_exit_func(); 178 restore_gd(); 179 180 return ret; 181} 182 183void hab_rvt_failsafe(void) 184{ 185 hab_rvt_failsafe_t *hab_rvt_failsafe_func; 186 187 hab_rvt_failsafe_func = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE; 188#if defined(CONFIG_ARM64) 189 if (current_el() != 3) { 190 /* call sip */ 191 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_FAILSAFE, 0, 0, 0, 0, 0, 0, NULL); 192 return; 193 } 194#endif 195 196 save_gd(); 197 hab_rvt_failsafe_func(); 198 restore_gd(); 199} 200 201enum hab_status hab_rvt_check_target(enum hab_target type, const void *start, 202 size_t bytes) 203{ 204 enum hab_status ret; 205 hab_rvt_check_target_t *hab_rvt_check_target_func; 206 struct arm_smccc_res res __maybe_unused; 207 208 hab_rvt_check_target_func = (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET; 209#if defined(CONFIG_ARM64) 210 if (current_el() != 3) { 211 /* call sip */ 212 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_CHECK_TARGET, (unsigned long)type, 213 (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res); 214 return (enum hab_status)res.a0; 215 } 216#endif 217 218 save_gd(); 219 ret = hab_rvt_check_target_func(type, start, bytes); 220 restore_gd(); 221 222 return ret; 223} 224 225void *hab_rvt_authenticate_image(uint8_t cid, ptrdiff_t ivt_offset, 226 void **start, size_t *bytes, hab_loader_callback_f_t loader) 227{ 228 void *ret; 229 hab_rvt_authenticate_image_t *hab_rvt_authenticate_image_func; 230 struct arm_smccc_res res __maybe_unused; 231 232 hab_rvt_authenticate_image_func = (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE; 233#if defined(CONFIG_ARM64) 234 if (current_el() != 3) { 235 /* call sip */ 236 arm_smccc_smc(FSL_SIP_HAB, FSL_SIP_HAB_AUTHENTICATE, (unsigned long)ivt_offset, 237 (unsigned long)start, (unsigned long)bytes, 0, 0, 0, &res); 238 return (void *)res.a0; 239 } 240#endif 241 242 save_gd(); 243 ret = hab_rvt_authenticate_image_func(cid, ivt_offset, start, bytes, loader); 244 restore_gd(); 245 246 return ret; 247} 248 249#if !defined(CONFIG_SPL_BUILD) 250 251#define MAX_RECORD_BYTES (8*1024) /* 4 kbytes */ 252 253struct record { 254 uint8_t tag; /* Tag */ 255 uint8_t len[2]; /* Length */ 256 uint8_t par; /* Version */ 257 uint8_t contents[MAX_RECORD_BYTES];/* Record Data */ 258 bool any_rec_flag; 259}; 260 261static char *rsn_str[] = { 262 "RSN = HAB_RSN_ANY (0x00)\n", 263 "RSN = HAB_ENG_FAIL (0x30)\n", 264 "RSN = HAB_INV_ADDRESS (0x22)\n", 265 "RSN = HAB_INV_ASSERTION (0x0C)\n", 266 "RSN = HAB_INV_CALL (0x28)\n", 267 "RSN = HAB_INV_CERTIFICATE (0x21)\n", 268 "RSN = HAB_INV_COMMAND (0x06)\n", 269 "RSN = HAB_INV_CSF (0x11)\n", 270 "RSN = HAB_INV_DCD (0x27)\n", 271 "RSN = HAB_INV_INDEX (0x0F)\n", 272 "RSN = HAB_INV_IVT (0x05)\n", 273 "RSN = HAB_INV_KEY (0x1D)\n", 274 "RSN = HAB_INV_RETURN (0x1E)\n", 275 "RSN = HAB_INV_SIGNATURE (0x18)\n", 276 "RSN = HAB_INV_SIZE (0x17)\n", 277 "RSN = HAB_MEM_FAIL (0x2E)\n", 278 "RSN = HAB_OVR_COUNT (0x2B)\n", 279 "RSN = HAB_OVR_STORAGE (0x2D)\n", 280 "RSN = HAB_UNS_ALGORITHM (0x12)\n", 281 "RSN = HAB_UNS_COMMAND (0x03)\n", 282 "RSN = HAB_UNS_ENGINE (0x0A)\n", 283 "RSN = HAB_UNS_ITEM (0x24)\n", 284 "RSN = HAB_UNS_KEY (0x1B)\n", 285 "RSN = HAB_UNS_PROTOCOL (0x14)\n", 286 "RSN = HAB_UNS_STATE (0x09)\n", 287 "RSN = INVALID\n", 288 NULL 289}; 290 291static char *sts_str[] = { 292 "STS = HAB_STS_ANY (0x00)\n", 293 "STS = HAB_FAILURE (0x33)\n", 294 "STS = HAB_WARNING (0x69)\n", 295 "STS = HAB_SUCCESS (0xF0)\n", 296 "STS = INVALID\n", 297 NULL 298}; 299 300static char *eng_str[] = { 301 "ENG = HAB_ENG_ANY (0x00)\n", 302 "ENG = HAB_ENG_SCC (0x03)\n", 303 "ENG = HAB_ENG_RTIC (0x05)\n", 304 "ENG = HAB_ENG_SAHARA (0x06)\n", 305 "ENG = HAB_ENG_CSU (0x0A)\n", 306 "ENG = HAB_ENG_SRTC (0x0C)\n", 307 "ENG = HAB_ENG_DCP (0x1B)\n", 308 "ENG = HAB_ENG_CAAM (0x1D)\n", 309 "ENG = HAB_ENG_SNVS (0x1E)\n", 310 "ENG = HAB_ENG_OCOTP (0x21)\n", 311 "ENG = HAB_ENG_DTCP (0x22)\n", 312 "ENG = HAB_ENG_ROM (0x36)\n", 313 "ENG = HAB_ENG_HDCP (0x24)\n", 314 "ENG = HAB_ENG_RTL (0x77)\n", 315 "ENG = HAB_ENG_SW (0xFF)\n", 316 "ENG = INVALID\n", 317 NULL 318}; 319 320static char *ctx_str[] = { 321 "CTX = HAB_CTX_ANY(0x00)\n", 322 "CTX = HAB_CTX_FAB (0xFF)\n", 323 "CTX = HAB_CTX_ENTRY (0xE1)\n", 324 "CTX = HAB_CTX_TARGET (0x33)\n", 325 "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n", 326 "CTX = HAB_CTX_DCD (0xDD)\n", 327 "CTX = HAB_CTX_CSF (0xCF)\n", 328 "CTX = HAB_CTX_COMMAND (0xC0)\n", 329 "CTX = HAB_CTX_AUT_DAT (0xDB)\n", 330 "CTX = HAB_CTX_ASSERT (0xA0)\n", 331 "CTX = HAB_CTX_EXIT (0xEE)\n", 332 "CTX = INVALID\n", 333 NULL 334}; 335 336static uint8_t hab_statuses[5] = { 337 HAB_STS_ANY, 338 HAB_FAILURE, 339 HAB_WARNING, 340 HAB_SUCCESS 341}; 342 343static uint8_t hab_reasons[26] = { 344 HAB_RSN_ANY, 345 HAB_ENG_FAIL, 346 HAB_INV_ADDRESS, 347 HAB_INV_ASSERTION, 348 HAB_INV_CALL, 349 HAB_INV_CERTIFICATE, 350 HAB_INV_COMMAND, 351 HAB_INV_CSF, 352 HAB_INV_DCD, 353 HAB_INV_INDEX, 354 HAB_INV_IVT, 355 HAB_INV_KEY, 356 HAB_INV_RETURN, 357 HAB_INV_SIGNATURE, 358 HAB_INV_SIZE, 359 HAB_MEM_FAIL, 360 HAB_OVR_COUNT, 361 HAB_OVR_STORAGE, 362 HAB_UNS_ALGORITHM, 363 HAB_UNS_COMMAND, 364 HAB_UNS_ENGINE, 365 HAB_UNS_ITEM, 366 HAB_UNS_KEY, 367 HAB_UNS_PROTOCOL, 368 HAB_UNS_STATE 369}; 370 371static uint8_t hab_contexts[12] = { 372 HAB_CTX_ANY, 373 HAB_CTX_FAB, 374 HAB_CTX_ENTRY, 375 HAB_CTX_TARGET, 376 HAB_CTX_AUTHENTICATE, 377 HAB_CTX_DCD, 378 HAB_CTX_CSF, 379 HAB_CTX_COMMAND, 380 HAB_CTX_AUT_DAT, 381 HAB_CTX_ASSERT, 382 HAB_CTX_EXIT 383}; 384 385static uint8_t hab_engines[16] = { 386 HAB_ENG_ANY, 387 HAB_ENG_SCC, 388 HAB_ENG_RTIC, 389 HAB_ENG_SAHARA, 390 HAB_ENG_CSU, 391 HAB_ENG_SRTC, 392 HAB_ENG_DCP, 393 HAB_ENG_CAAM, 394 HAB_ENG_SNVS, 395 HAB_ENG_OCOTP, 396 HAB_ENG_DTCP, 397 HAB_ENG_ROM, 398 HAB_ENG_HDCP, 399 HAB_ENG_RTL, 400 HAB_ENG_SW 401}; 402 403static inline u32 get_idx(u8 *list, u8 tgt, u32 size) 404{ 405 u32 idx = 0; 406 u8 element; 407 408 while (idx < size) { 409 element = list[idx]; 410 if (element == tgt) 411 return idx; 412 ++idx; 413 } 414 return idx; 415} 416 417static void process_event_record(uint8_t *event_data, size_t bytes) 418{ 419 struct record *rec = (struct record *)event_data; 420 421 printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0], 422 ARRAY_SIZE(hab_statuses))]); 423 printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1], 424 ARRAY_SIZE(hab_reasons))]); 425 printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2], 426 ARRAY_SIZE(hab_contexts))]); 427 printf("%s", eng_str[get_idx(hab_engines, rec->contents[3], 428 ARRAY_SIZE(hab_engines))]); 429} 430 431static void display_event(uint8_t *event_data, size_t bytes) 432{ 433 uint32_t i; 434 435 if (!(event_data && bytes > 0)) 436 return; 437 438 for (i = 0; i < bytes; i++) { 439 if (i == 0) 440 printf("\t0x%02x", event_data[i]); 441 else if ((i % 8) == 0) 442 printf("\n\t0x%02x", event_data[i]); 443 else 444 printf(" 0x%02x", event_data[i]); 445 } 446 447 process_event_record(event_data, bytes); 448} 449 450static int get_hab_status(void) 451{ 452 uint32_t index = 0; /* Loop index */ 453 uint8_t event_data[128]; /* Event data buffer */ 454 size_t bytes = sizeof(event_data); /* Event size in bytes */ 455 enum hab_config config = 0; 456 enum hab_state state = 0; 457 458 if (imx_hab_is_enabled()) 459 puts("\nSecure boot enabled\n"); 460 else 461 puts("\nSecure boot disabled\n"); 462 463 /* Check HAB status */ 464 if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) { 465 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", 466 config, state); 467 468 /* Display HAB events */ 469 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data, 470 &bytes) == HAB_SUCCESS) { 471 puts("\n"); 472 printf("--------- HAB Event %d -----------------\n", 473 index + 1); 474 puts("event data:\n"); 475 display_event(event_data, bytes); 476 puts("\n"); 477 bytes = sizeof(event_data); 478 index++; 479 } 480 } 481 /* Display message if no HAB events are found */ 482 else { 483 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", 484 config, state); 485 puts("No HAB Events Found!\n\n"); 486 } 487 return 0; 488} 489 490#ifdef CONFIG_MX7ULP 491 492static int get_record_len(struct record *rec) 493{ 494 return (size_t)((rec->len[0] << 8) + (rec->len[1])); 495} 496 497static int get_hab_status_m4(void) 498{ 499 unsigned int index = 0; 500 uint8_t event_data[128]; 501 size_t record_len, offset = 0; 502 enum hab_config config = 0; 503 enum hab_state state = 0; 504 505 if (imx_hab_is_enabled()) 506 puts("\nSecure boot enabled\n"); 507 else 508 puts("\nSecure boot disabled\n"); 509 510 /* 511 * HAB in both A7 and M4 gather the security state 512 * and configuration of the chip from 513 * shared SNVS module 514 */ 515 hab_rvt_report_status(&config, &state); 516 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", 517 config, state); 518 519 struct record *rec = (struct record *)(HAB_M4_PERSISTENT_START); 520 521 record_len = get_record_len(rec); 522 523 /* Check if HAB persistent memory is valid */ 524 if (rec->tag != HAB_TAG_EVT_DEF || 525 record_len != sizeof(struct evt_def) || 526 (rec->par & HAB_MAJ_MASK) != HAB_MAJ_VER) { 527 puts("\nERROR: Invalid HAB persistent memory\n"); 528 return 1; 529 } 530 531 /* Parse events in HAB M4 persistent memory region */ 532 while (offset < HAB_M4_PERSISTENT_BYTES) { 533 rec = (struct record *)(HAB_M4_PERSISTENT_START + offset); 534 535 record_len = get_record_len(rec); 536 537 if (rec->tag == HAB_TAG_EVT) { 538 memcpy(&event_data, rec, record_len); 539 puts("\n"); 540 printf("--------- HAB Event %d -----------------\n", 541 index + 1); 542 puts("event data:\n"); 543 display_event(event_data, record_len); 544 puts("\n"); 545 index++; 546 } 547 548 offset += record_len; 549 550 /* Ensure all records start on a word boundary */ 551 if ((offset % 4) != 0) 552 offset = offset + (4 - (offset % 4)); 553 } 554 555 if (!index) 556 puts("No HAB Events Found!\n\n"); 557 558 return 0; 559} 560#endif 561 562static int do_hab_status(struct cmd_tbl *cmdtp, int flag, int argc, 563 char *const argv[]) 564{ 565#ifdef CONFIG_MX7ULP 566 if ((argc > 2)) { 567 cmd_usage(cmdtp); 568 return 1; 569 } 570 571 if (strcmp("m4", argv[1]) == 0) 572 get_hab_status_m4(); 573 else 574 get_hab_status(); 575#else 576 if ((argc != 1)) { 577 cmd_usage(cmdtp); 578 return 1; 579 } 580 581 get_hab_status(); 582#endif 583 584 return 0; 585} 586 587static ulong get_image_ivt_offset(ulong img_addr) 588{ 589 const void *buf; 590 591 buf = map_sysmem(img_addr, 0); 592 switch (genimg_get_format(buf)) { 593#if CONFIG_IS_ENABLED(LEGACY_IMAGE_FORMAT) 594 case IMAGE_FORMAT_LEGACY: 595 return (image_get_image_size((struct legacy_img_hdr *)img_addr) 596 + 0x1000 - 1) & ~(0x1000 - 1); 597#endif 598#if CONFIG_IS_ENABLED(FIT) 599 case IMAGE_FORMAT_FIT: 600 return (fit_get_size(buf) + 0x1000 - 1) & ~(0x1000 - 1); 601#endif 602 default: 603 return 0; 604 } 605} 606 607static int do_authenticate_image(struct cmd_tbl *cmdtp, int flag, int argc, 608 char *const argv[]) 609{ 610 ulong addr, length, ivt_offset; 611 int rcode = 0; 612 613 if (argc < 3) 614 return CMD_RET_USAGE; 615 616 addr = hextoul(argv[1], NULL); 617 length = hextoul(argv[2], NULL); 618 if (argc == 3) 619 ivt_offset = get_image_ivt_offset(addr); 620 else 621 ivt_offset = hextoul(argv[3], NULL); 622 623 rcode = imx_hab_authenticate_image(addr, length, ivt_offset); 624 if (rcode == 0) 625 rcode = CMD_RET_SUCCESS; 626 else 627 rcode = CMD_RET_FAILURE; 628 629 return rcode; 630} 631 632static int do_hab_failsafe(struct cmd_tbl *cmdtp, int flag, int argc, 633 char *const argv[]) 634{ 635 if (argc != 1) { 636 cmd_usage(cmdtp); 637 return 1; 638 } 639 640 hab_rvt_failsafe(); 641 642 return 0; 643} 644 645static int do_hab_version(struct cmd_tbl *cmdtp, int flag, int argc, 646 char *const argv[]) 647{ 648 struct hab_hdr *hdr = (struct hab_hdr *)HAB_RVT_BASE; 649 650 if (hdr->tag != HAB_TAG_RVT) { 651 printf("Unexpected header tag: %x\n", hdr->tag); 652 return CMD_RET_FAILURE; 653 } 654 655 printf("HAB version: %d.%d\n", hdr->par >> 4, hdr->par & 0xf); 656 657 return 0; 658} 659 660static int do_authenticate_image_or_failover(struct cmd_tbl *cmdtp, int flag, 661 int argc, char *const argv[]) 662{ 663 int ret = CMD_RET_FAILURE; 664 665 if (argc < 3) { 666 ret = CMD_RET_USAGE; 667 goto error; 668 } 669 670 if (!imx_hab_is_enabled()) { 671 printf("error: secure boot disabled\n"); 672 goto error; 673 } 674 675 if (do_authenticate_image(NULL, flag, argc, argv) != CMD_RET_SUCCESS) { 676 fprintf(stderr, "authentication fail -> %s %s %s %s\n", 677 argv[0], argv[1], argv[2], argv[3]); 678 do_hab_failsafe(0, 0, 1, NULL); 679 }; 680 ret = CMD_RET_SUCCESS; 681error: 682 return ret; 683} 684 685#ifdef CONFIG_MX7ULP 686U_BOOT_CMD( 687 hab_status, CONFIG_SYS_MAXARGS, 2, do_hab_status, 688 "display HAB status and events", 689 "hab_status - A7 HAB event and status\n" 690 "hab_status m4 - M4 HAB event and status" 691 ); 692#else 693U_BOOT_CMD( 694 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status, 695 "display HAB status", 696 "" 697 ); 698#endif 699 700U_BOOT_CMD( 701 hab_auth_img, 4, 0, do_authenticate_image, 702 "authenticate image via HAB", 703 "addr length ivt_offset\n" 704 "addr - image hex address\n" 705 "length - image hex length\n" 706 "ivt_offset - hex offset of IVT in the image (optional)" 707 ); 708 709U_BOOT_CMD( 710 hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe, 711 "run BootROM failsafe routine", 712 "" 713 ); 714 715U_BOOT_CMD( 716 hab_auth_img_or_fail, 4, 0, 717 do_authenticate_image_or_failover, 718 "authenticate image via HAB. Switch to USB BootROM mode on failure", 719 "addr length ivt_offset\n" 720 "addr - image hex address\n" 721 "length - image hex length\n" 722 "ivt_offset - hex offset of IVT in the image (optional)" 723 ); 724 725U_BOOT_CMD( 726 hab_version, 1, 0, do_hab_version, 727 "print HAB major/minor version", 728 "" 729 ); 730 731#endif /* !defined(CONFIG_SPL_BUILD) */ 732 733/* Get CSF Header length */ 734static int get_hab_hdr_len(struct hab_hdr *hdr) 735{ 736 return (size_t)((hdr->len[0] << 8) + (hdr->len[1])); 737} 738 739/* Check whether addr lies between start and 740 * end and is within the length of the image 741 */ 742static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end) 743{ 744 size_t csf_size = (size_t)((end + 1) - addr); 745 746 return (addr && (addr >= start) && (addr <= end) && 747 (csf_size >= bytes)); 748} 749 750/* Get Length of each command in CSF */ 751static int get_csf_cmd_hdr_len(u8 *csf_hdr) 752{ 753 if (*csf_hdr == HAB_CMD_HDR) 754 return sizeof(struct hab_hdr); 755 756 return get_hab_hdr_len((struct hab_hdr *)csf_hdr); 757} 758 759/* Check if CSF is valid */ 760static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes) 761{ 762 u8 *start = (u8 *)start_addr; 763 u8 *csf_hdr; 764 u8 *end; 765 766 size_t csf_hdr_len; 767 size_t cmd_hdr_len; 768 size_t offset = 0; 769 770 if (bytes != 0) 771 end = start + bytes - 1; 772 else 773 end = start; 774 775 /* Verify if CSF pointer content is zero */ 776 if (!ivt->csf) { 777 puts("Error: CSF pointer is NULL\n"); 778 return false; 779 } 780 781 csf_hdr = (u8 *)(ulong)ivt->csf; 782 783 /* Verify if CSF Header exist */ 784 if (*csf_hdr != HAB_CMD_HDR) { 785 puts("Error: CSF header command not found\n"); 786 return false; 787 } 788 789 csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr); 790 791 /* Check if the CSF lies within the image bounds */ 792 if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) { 793 puts("Error: CSF lies outside the image bounds\n"); 794 return false; 795 } 796 797 do { 798 struct hab_hdr *cmd; 799 800 cmd = (struct hab_hdr *)&csf_hdr[offset]; 801 802 switch (cmd->tag) { 803 case (HAB_CMD_WRT_DAT): 804 puts("Error: Deprecated write command found\n"); 805 return false; 806 case (HAB_CMD_CHK_DAT): 807 puts("Error: Deprecated check command found\n"); 808 return false; 809 case (HAB_CMD_SET): 810 if (cmd->par == HAB_PAR_MID) { 811 puts("Error: Deprecated Set MID command found\n"); 812 return false; 813 } 814 default: 815 break; 816 } 817 818 cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]); 819 if (!cmd_hdr_len) { 820 puts("Error: Invalid command length\n"); 821 return false; 822 } 823 offset += cmd_hdr_len; 824 825 } while (offset < csf_hdr_len); 826 827 return true; 828} 829 830/* 831 * Validate IVT structure of the image being authenticated 832 */ 833static int validate_ivt(struct ivt *ivt_initial) 834{ 835 struct ivt_header *ivt_hdr = &ivt_initial->hdr; 836 837 if ((ulong)ivt_initial & 0x3) { 838 puts("Error: Image's start address is not 4 byte aligned\n"); 839 return 0; 840 } 841 842 /* Check IVT fields before allowing authentication */ 843 if ((!verify_ivt_header(ivt_hdr)) && \ 844 (ivt_initial->entry != 0x0) && \ 845 (ivt_initial->reserved1 == 0x0) && \ 846 (ivt_initial->self == \ 847 (uint32_t)((ulong)ivt_initial & 0xffffffff)) && \ 848 (ivt_initial->csf != 0x0) && \ 849 (ivt_initial->reserved2 == 0x0)) { 850 /* Report boot failure if DCD pointer is found in IVT */ 851 if (ivt_initial->dcd != 0x0) 852 puts("Error: DCD pointer must be 0\n"); 853 else 854 return 1; 855 } 856 857 puts("Error: Invalid IVT structure\n"); 858 debug("\nAllowed IVT structure:\n"); 859 debug("IVT HDR = 0x4X2000D1\n"); 860 debug("IVT ENTRY = 0xXXXXXXXX\n"); 861 debug("IVT RSV1 = 0x0\n"); 862 debug("IVT DCD = 0x0\n"); /* Recommended */ 863 debug("IVT BOOT_DATA = 0xXXXXXXXX\n"); /* Commonly 0x0 */ 864 debug("IVT SELF = 0xXXXXXXXX\n"); /* = ddr_start + ivt_offset */ 865 debug("IVT CSF = 0xXXXXXXXX\n"); 866 debug("IVT RSV2 = 0x0\n"); 867 868 /* Invalid IVT structure */ 869 return 0; 870} 871 872bool imx_hab_is_enabled(void) 873{ 874 struct imx_sec_config_fuse_t *fuse = 875 (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; 876 uint32_t reg; 877 int ret; 878 879 ret = fuse_read(fuse->bank, fuse->word, ®); 880 if (ret) { 881 puts("\nSecure boot fuse read error\n"); 882 return ret; 883 } 884 885 return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT; 886} 887 888int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size, 889 uint32_t ivt_offset) 890{ 891 ulong load_addr = 0; 892 size_t bytes; 893 ulong ivt_addr = 0; 894 int result = 1; 895 ulong start; 896 struct ivt *ivt; 897 enum hab_status status; 898 899 if (!imx_hab_is_enabled()) 900 puts("hab fuse not enabled\n"); 901 902 printf("\nAuthenticate image from DDR location 0x%x...\n", 903 ddr_start); 904 905 hab_caam_clock_enable(1); 906 907 /* Calculate IVT address header */ 908 ivt_addr = (ulong) (ddr_start + ivt_offset); 909 ivt = (struct ivt *)ivt_addr; 910 911 /* Verify IVT header bugging out on error */ 912 if (!validate_ivt(ivt)) 913 goto hab_authentication_exit; 914 915 start = ddr_start; 916 bytes = image_size; 917 918 /* Verify CSF */ 919 if (!csf_is_valid(ivt, start, bytes)) 920 goto hab_authentication_exit; 921 922 if (hab_rvt_entry() != HAB_SUCCESS) { 923 puts("hab entry function fail\n"); 924 goto hab_exit_failure_print_status; 925 } 926 927 status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)(ulong)ddr_start, bytes); 928 if (status != HAB_SUCCESS) { 929 printf("HAB check target 0x%08x-0x%08lx fail\n", 930 ddr_start, ddr_start + (ulong)bytes); 931 goto hab_exit_failure_print_status; 932 } 933#ifdef DEBUG 934 printf("\nivt_offset = 0x%x, ivt addr = 0x%lx\n", ivt_offset, ivt_addr); 935 printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry, 936 ivt->dcd, ivt->csf); 937 puts("Dumping IVT\n"); 938 print_buffer(ivt_addr, (void *)(uintptr_t)(ivt_addr), 4, 0x8, 0); 939 940 puts("Dumping CSF Header\n"); 941 print_buffer(ivt->csf, (void *)(uintptr_t)(ivt->csf), 4, 0x10, 0); 942 943#if !defined(CONFIG_SPL_BUILD) 944 get_hab_status(); 945#endif 946 947 puts("\nCalling authenticate_image in ROM\n"); 948 printf("\tivt_offset = 0x%x\n", ivt_offset); 949 printf("\tstart = 0x%08lx\n", start); 950 printf("\tbytes = 0x%lx\n", (ulong)bytes); 951#endif 952 953#ifndef CONFIG_ARM64 954 /* 955 * If the MMU is enabled, we have to notify the ROM 956 * code, or it won't flush the caches when needed. 957 * This is done, by setting the "pu_irom_mmu_enabled" 958 * word to 1. You can find its address by looking in 959 * the ROM map. This is critical for 960 * authenticate_image(). If MMU is enabled, without 961 * setting this bit, authentication will fail and may 962 * crash. 963 */ 964 /* Check MMU enabled */ 965 if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) { 966 if (is_mx6dq()) { 967 /* 968 * This won't work on Rev 1.0.0 of 969 * i.MX6Q/D, since their ROM doesn't 970 * do cache flushes. don't think any 971 * exist, so we ignore them. 972 */ 973 if (!is_mx6dqp()) 974 writel(1, MX6DQ_PU_IROM_MMU_EN_VAR); 975 } else if (is_mx6sdl()) { 976 writel(1, MX6DLS_PU_IROM_MMU_EN_VAR); 977 } else if (is_mx6sl()) { 978 writel(1, MX6SL_PU_IROM_MMU_EN_VAR); 979 } 980 } 981#endif 982 983 load_addr = (ulong)hab_rvt_authenticate_image( 984 HAB_CID_UBOOT, 985 ivt_offset, (void **)&start, 986 (size_t *)&bytes, NULL); 987 if (hab_rvt_exit() != HAB_SUCCESS) { 988 puts("hab exit function fail\n"); 989 load_addr = 0; 990 } 991 992hab_exit_failure_print_status: 993#if !defined(CONFIG_SPL_BUILD) 994 get_hab_status(); 995#endif 996 997hab_authentication_exit: 998 999 if (load_addr != 0 || !imx_hab_is_enabled()) 1000 result = 0; 1001 1002 return result; 1003} 1004 1005int authenticate_image(u32 ddr_start, u32 raw_image_size) 1006{ 1007 u32 ivt_offset; 1008 size_t bytes; 1009 1010 ivt_offset = (raw_image_size + ALIGN_SIZE - 1) & 1011 ~(ALIGN_SIZE - 1); 1012 bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE; 1013 1014 return imx_hab_authenticate_image(ddr_start, bytes, ivt_offset); 1015} 1016