1 /* 2 * Copyright (C) 2010-2015 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <config.h> 9 #include <fuse.h> 10 #include <asm/io.h> 11 #include <asm/system.h> 12 #include <asm/arch/clock.h> 13 #include <asm/arch/sys_proto.h> 14 #include <asm/mach-imx/hab.h> 15 16 /* -------- start of HAB API updates ------------*/ 17 18 #define hab_rvt_report_event_p \ 19 ( \ 20 (is_mx6dqp()) ? \ 21 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \ 22 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 23 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \ 24 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 25 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \ 26 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT) \ 27 ) 28 29 #define hab_rvt_report_status_p \ 30 ( \ 31 (is_mx6dqp()) ? \ 32 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\ 33 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 34 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\ 35 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 36 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\ 37 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS) \ 38 ) 39 40 #define hab_rvt_authenticate_image_p \ 41 ( \ 42 (is_mx6dqp()) ? \ 43 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \ 44 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 45 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \ 46 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 47 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \ 48 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE) \ 49 ) 50 51 #define hab_rvt_entry_p \ 52 ( \ 53 (is_mx6dqp()) ? \ 54 ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \ 55 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 56 ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \ 57 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 58 ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \ 59 ((hab_rvt_entry_t *)HAB_RVT_ENTRY) \ 60 ) 61 62 #define hab_rvt_exit_p \ 63 ( \ 64 (is_mx6dqp()) ? \ 65 ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \ 66 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 67 ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \ 68 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 69 ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \ 70 ((hab_rvt_exit_t *)HAB_RVT_EXIT) \ 71 ) 72 73 static inline void hab_rvt_failsafe_new(void) 74 { 75 } 76 77 #define hab_rvt_failsafe_p \ 78 ( \ 79 (is_mx6dqp()) ? \ 80 ((hab_rvt_failsafe_t *)hab_rvt_failsafe_new) : \ 81 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 82 ((hab_rvt_failsafe_t *)hab_rvt_failsafe_new) : \ 83 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 84 ((hab_rvt_failsafe_t *)hab_rvt_failsafe_new) : \ 85 ((hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE) \ 86 ) 87 88 static inline enum hab_status hab_rvt_check_target_new(enum hab_target target, 89 const void *start, 90 size_t bytes) 91 { 92 return HAB_SUCCESS; 93 } 94 95 #define hab_rvt_check_target_p \ 96 ( \ 97 (is_mx6dqp()) ? \ 98 ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \ 99 (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \ 100 ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \ 101 (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \ 102 ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \ 103 ((hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET) \ 104 ) 105 106 #define ALIGN_SIZE 0x1000 107 #define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8 108 #define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0 109 #define MX6SL_PU_IROM_MMU_EN_VAR 0x00900a18 110 #define IS_HAB_ENABLED_BIT \ 111 (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \ 112 (is_soc_type(MXC_SOC_MX7) ? 0x2000000 : 0x2)) 113 114 static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr) 115 { 116 printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str, 117 ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version); 118 119 return 1; 120 } 121 122 static int verify_ivt_header(struct ivt_header *ivt_hdr) 123 { 124 int result = 0; 125 126 if (ivt_hdr->magic != IVT_HEADER_MAGIC) 127 result = ivt_header_error("bad magic", ivt_hdr); 128 129 if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH) 130 result = ivt_header_error("bad length", ivt_hdr); 131 132 if (ivt_hdr->version != IVT_HEADER_V1 && 133 ivt_hdr->version != IVT_HEADER_V2) 134 result = ivt_header_error("bad version", ivt_hdr); 135 136 return result; 137 } 138 139 #if !defined(CONFIG_SPL_BUILD) 140 141 #define MAX_RECORD_BYTES (8*1024) /* 4 kbytes */ 142 143 struct record { 144 uint8_t tag; /* Tag */ 145 uint8_t len[2]; /* Length */ 146 uint8_t par; /* Version */ 147 uint8_t contents[MAX_RECORD_BYTES];/* Record Data */ 148 bool any_rec_flag; 149 }; 150 151 static char *rsn_str[] = { 152 "RSN = HAB_RSN_ANY (0x00)\n", 153 "RSN = HAB_ENG_FAIL (0x30)\n", 154 "RSN = HAB_INV_ADDRESS (0x22)\n", 155 "RSN = HAB_INV_ASSERTION (0x0C)\n", 156 "RSN = HAB_INV_CALL (0x28)\n", 157 "RSN = HAB_INV_CERTIFICATE (0x21)\n", 158 "RSN = HAB_INV_COMMAND (0x06)\n", 159 "RSN = HAB_INV_CSF (0x11)\n", 160 "RSN = HAB_INV_DCD (0x27)\n", 161 "RSN = HAB_INV_INDEX (0x0F)\n", 162 "RSN = HAB_INV_IVT (0x05)\n", 163 "RSN = HAB_INV_KEY (0x1D)\n", 164 "RSN = HAB_INV_RETURN (0x1E)\n", 165 "RSN = HAB_INV_SIGNATURE (0x18)\n", 166 "RSN = HAB_INV_SIZE (0x17)\n", 167 "RSN = HAB_MEM_FAIL (0x2E)\n", 168 "RSN = HAB_OVR_COUNT (0x2B)\n", 169 "RSN = HAB_OVR_STORAGE (0x2D)\n", 170 "RSN = HAB_UNS_ALGORITHM (0x12)\n", 171 "RSN = HAB_UNS_COMMAND (0x03)\n", 172 "RSN = HAB_UNS_ENGINE (0x0A)\n", 173 "RSN = HAB_UNS_ITEM (0x24)\n", 174 "RSN = HAB_UNS_KEY (0x1B)\n", 175 "RSN = HAB_UNS_PROTOCOL (0x14)\n", 176 "RSN = HAB_UNS_STATE (0x09)\n", 177 "RSN = INVALID\n", 178 NULL 179 }; 180 181 static char *sts_str[] = { 182 "STS = HAB_SUCCESS (0xF0)\n", 183 "STS = HAB_FAILURE (0x33)\n", 184 "STS = HAB_WARNING (0x69)\n", 185 "STS = INVALID\n", 186 NULL 187 }; 188 189 static char *eng_str[] = { 190 "ENG = HAB_ENG_ANY (0x00)\n", 191 "ENG = HAB_ENG_SCC (0x03)\n", 192 "ENG = HAB_ENG_RTIC (0x05)\n", 193 "ENG = HAB_ENG_SAHARA (0x06)\n", 194 "ENG = HAB_ENG_CSU (0x0A)\n", 195 "ENG = HAB_ENG_SRTC (0x0C)\n", 196 "ENG = HAB_ENG_DCP (0x1B)\n", 197 "ENG = HAB_ENG_CAAM (0x1D)\n", 198 "ENG = HAB_ENG_SNVS (0x1E)\n", 199 "ENG = HAB_ENG_OCOTP (0x21)\n", 200 "ENG = HAB_ENG_DTCP (0x22)\n", 201 "ENG = HAB_ENG_ROM (0x36)\n", 202 "ENG = HAB_ENG_HDCP (0x24)\n", 203 "ENG = HAB_ENG_RTL (0x77)\n", 204 "ENG = HAB_ENG_SW (0xFF)\n", 205 "ENG = INVALID\n", 206 NULL 207 }; 208 209 static char *ctx_str[] = { 210 "CTX = HAB_CTX_ANY(0x00)\n", 211 "CTX = HAB_CTX_FAB (0xFF)\n", 212 "CTX = HAB_CTX_ENTRY (0xE1)\n", 213 "CTX = HAB_CTX_TARGET (0x33)\n", 214 "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n", 215 "CTX = HAB_CTX_DCD (0xDD)\n", 216 "CTX = HAB_CTX_CSF (0xCF)\n", 217 "CTX = HAB_CTX_COMMAND (0xC0)\n", 218 "CTX = HAB_CTX_AUT_DAT (0xDB)\n", 219 "CTX = HAB_CTX_ASSERT (0xA0)\n", 220 "CTX = HAB_CTX_EXIT (0xEE)\n", 221 "CTX = INVALID\n", 222 NULL 223 }; 224 225 static uint8_t hab_statuses[5] = { 226 HAB_STS_ANY, 227 HAB_FAILURE, 228 HAB_WARNING, 229 HAB_SUCCESS, 230 -1 231 }; 232 233 static uint8_t hab_reasons[26] = { 234 HAB_RSN_ANY, 235 HAB_ENG_FAIL, 236 HAB_INV_ADDRESS, 237 HAB_INV_ASSERTION, 238 HAB_INV_CALL, 239 HAB_INV_CERTIFICATE, 240 HAB_INV_COMMAND, 241 HAB_INV_CSF, 242 HAB_INV_DCD, 243 HAB_INV_INDEX, 244 HAB_INV_IVT, 245 HAB_INV_KEY, 246 HAB_INV_RETURN, 247 HAB_INV_SIGNATURE, 248 HAB_INV_SIZE, 249 HAB_MEM_FAIL, 250 HAB_OVR_COUNT, 251 HAB_OVR_STORAGE, 252 HAB_UNS_ALGORITHM, 253 HAB_UNS_COMMAND, 254 HAB_UNS_ENGINE, 255 HAB_UNS_ITEM, 256 HAB_UNS_KEY, 257 HAB_UNS_PROTOCOL, 258 HAB_UNS_STATE, 259 -1 260 }; 261 262 static uint8_t hab_contexts[12] = { 263 HAB_CTX_ANY, 264 HAB_CTX_FAB, 265 HAB_CTX_ENTRY, 266 HAB_CTX_TARGET, 267 HAB_CTX_AUTHENTICATE, 268 HAB_CTX_DCD, 269 HAB_CTX_CSF, 270 HAB_CTX_COMMAND, 271 HAB_CTX_AUT_DAT, 272 HAB_CTX_ASSERT, 273 HAB_CTX_EXIT, 274 -1 275 }; 276 277 static uint8_t hab_engines[16] = { 278 HAB_ENG_ANY, 279 HAB_ENG_SCC, 280 HAB_ENG_RTIC, 281 HAB_ENG_SAHARA, 282 HAB_ENG_CSU, 283 HAB_ENG_SRTC, 284 HAB_ENG_DCP, 285 HAB_ENG_CAAM, 286 HAB_ENG_SNVS, 287 HAB_ENG_OCOTP, 288 HAB_ENG_DTCP, 289 HAB_ENG_ROM, 290 HAB_ENG_HDCP, 291 HAB_ENG_RTL, 292 HAB_ENG_SW, 293 -1 294 }; 295 296 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt) 297 { 298 uint8_t idx = 0; 299 uint8_t element = list[idx]; 300 while (element != -1) { 301 if (element == tgt) 302 return idx; 303 element = list[++idx]; 304 } 305 return -1; 306 } 307 308 static void process_event_record(uint8_t *event_data, size_t bytes) 309 { 310 struct record *rec = (struct record *)event_data; 311 312 printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]); 313 printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]); 314 printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]); 315 printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]); 316 } 317 318 static void display_event(uint8_t *event_data, size_t bytes) 319 { 320 uint32_t i; 321 322 if (!(event_data && bytes > 0)) 323 return; 324 325 for (i = 0; i < bytes; i++) { 326 if (i == 0) 327 printf("\t0x%02x", event_data[i]); 328 else if ((i % 8) == 0) 329 printf("\n\t0x%02x", event_data[i]); 330 else 331 printf(" 0x%02x", event_data[i]); 332 } 333 334 process_event_record(event_data, bytes); 335 } 336 337 static int get_hab_status(void) 338 { 339 uint32_t index = 0; /* Loop index */ 340 uint8_t event_data[128]; /* Event data buffer */ 341 size_t bytes = sizeof(event_data); /* Event size in bytes */ 342 enum hab_config config = 0; 343 enum hab_state state = 0; 344 hab_rvt_report_event_t *hab_rvt_report_event; 345 hab_rvt_report_status_t *hab_rvt_report_status; 346 347 hab_rvt_report_event = hab_rvt_report_event_p; 348 hab_rvt_report_status = hab_rvt_report_status_p; 349 350 if (imx_hab_is_enabled()) 351 puts("\nSecure boot enabled\n"); 352 else 353 puts("\nSecure boot disabled\n"); 354 355 /* Check HAB status */ 356 if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) { 357 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", 358 config, state); 359 360 /* Display HAB Error events */ 361 while (hab_rvt_report_event(HAB_FAILURE, index, event_data, 362 &bytes) == HAB_SUCCESS) { 363 puts("\n"); 364 printf("--------- HAB Event %d -----------------\n", 365 index + 1); 366 puts("event data:\n"); 367 display_event(event_data, bytes); 368 puts("\n"); 369 bytes = sizeof(event_data); 370 index++; 371 } 372 } 373 /* Display message if no HAB events are found */ 374 else { 375 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n", 376 config, state); 377 puts("No HAB Events Found!\n\n"); 378 } 379 return 0; 380 } 381 382 static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, 383 char * const argv[]) 384 { 385 if ((argc != 1)) { 386 cmd_usage(cmdtp); 387 return 1; 388 } 389 390 get_hab_status(); 391 392 return 0; 393 } 394 395 static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc, 396 char * const argv[]) 397 { 398 ulong addr, length, ivt_offset; 399 int rcode = 0; 400 401 if (argc < 4) 402 return CMD_RET_USAGE; 403 404 addr = simple_strtoul(argv[1], NULL, 16); 405 length = simple_strtoul(argv[2], NULL, 16); 406 ivt_offset = simple_strtoul(argv[3], NULL, 16); 407 408 rcode = imx_hab_authenticate_image(addr, length, ivt_offset); 409 if (rcode == 0) 410 rcode = CMD_RET_SUCCESS; 411 else 412 rcode = CMD_RET_FAILURE; 413 414 return rcode; 415 } 416 417 static int do_hab_failsafe(cmd_tbl_t *cmdtp, int flag, int argc, 418 char * const argv[]) 419 { 420 hab_rvt_failsafe_t *hab_rvt_failsafe; 421 422 if (argc != 1) { 423 cmd_usage(cmdtp); 424 return 1; 425 } 426 427 hab_rvt_failsafe = hab_rvt_failsafe_p; 428 hab_rvt_failsafe(); 429 430 return 0; 431 } 432 433 U_BOOT_CMD( 434 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status, 435 "display HAB status", 436 "" 437 ); 438 439 U_BOOT_CMD( 440 hab_auth_img, 4, 0, do_authenticate_image, 441 "authenticate image via HAB", 442 "addr length ivt_offset\n" 443 "addr - image hex address\n" 444 "length - image hex length\n" 445 "ivt_offset - hex offset of IVT in the image" 446 ); 447 448 U_BOOT_CMD( 449 hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe, 450 "run BootROM failsafe routine", 451 "" 452 ); 453 454 #endif /* !defined(CONFIG_SPL_BUILD) */ 455 456 bool imx_hab_is_enabled(void) 457 { 458 struct imx_sec_config_fuse_t *fuse = 459 (struct imx_sec_config_fuse_t *)&imx_sec_config_fuse; 460 uint32_t reg; 461 int ret; 462 463 ret = fuse_read(fuse->bank, fuse->word, ®); 464 if (ret) { 465 puts("\nSecure boot fuse read error\n"); 466 return ret; 467 } 468 469 return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT; 470 } 471 472 int imx_hab_authenticate_image(uint32_t ddr_start, uint32_t image_size, 473 uint32_t ivt_offset) 474 { 475 uint32_t load_addr = 0; 476 size_t bytes; 477 uint32_t ivt_addr = 0; 478 int result = 1; 479 ulong start; 480 hab_rvt_authenticate_image_t *hab_rvt_authenticate_image; 481 hab_rvt_entry_t *hab_rvt_entry; 482 hab_rvt_exit_t *hab_rvt_exit; 483 hab_rvt_check_target_t *hab_rvt_check_target; 484 struct ivt *ivt; 485 struct ivt_header *ivt_hdr; 486 enum hab_status status; 487 488 hab_rvt_authenticate_image = hab_rvt_authenticate_image_p; 489 hab_rvt_entry = hab_rvt_entry_p; 490 hab_rvt_exit = hab_rvt_exit_p; 491 hab_rvt_check_target = hab_rvt_check_target_p; 492 493 if (!imx_hab_is_enabled()) { 494 puts("hab fuse not enabled\n"); 495 return 0; 496 } 497 498 printf("\nAuthenticate image from DDR location 0x%x...\n", 499 ddr_start); 500 501 hab_caam_clock_enable(1); 502 503 /* Calculate IVT address header */ 504 ivt_addr = ddr_start + ivt_offset; 505 ivt = (struct ivt *)ivt_addr; 506 ivt_hdr = &ivt->hdr; 507 508 /* Verify IVT header bugging out on error */ 509 if (verify_ivt_header(ivt_hdr)) 510 goto hab_caam_clock_disable; 511 512 /* Verify IVT body */ 513 if (ivt->self != ivt_addr) { 514 printf("ivt->self 0x%08x pointer is 0x%08x\n", 515 ivt->self, ivt_addr); 516 goto hab_caam_clock_disable; 517 } 518 519 start = ddr_start; 520 bytes = image_size; 521 522 if (hab_rvt_entry() != HAB_SUCCESS) { 523 puts("hab entry function fail\n"); 524 goto hab_exit_failure_print_status; 525 } 526 527 status = hab_rvt_check_target(HAB_TGT_MEMORY, (void *)ddr_start, bytes); 528 if (status != HAB_SUCCESS) { 529 printf("HAB check target 0x%08x-0x%08x fail\n", 530 ddr_start, ddr_start + bytes); 531 goto hab_exit_failure_print_status; 532 } 533 #ifdef DEBUG 534 printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", ivt_offset, ivt_addr); 535 printf("ivt entry = 0x%08x, dcd = 0x%08x, csf = 0x%08x\n", ivt->entry, 536 ivt->dcd, ivt->csf); 537 puts("Dumping IVT\n"); 538 print_buffer(ivt_addr, (void *)(ivt_addr), 4, 0x8, 0); 539 540 puts("Dumping CSF Header\n"); 541 print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0); 542 543 #if !defined(CONFIG_SPL_BUILD) 544 get_hab_status(); 545 #endif 546 547 puts("\nCalling authenticate_image in ROM\n"); 548 printf("\tivt_offset = 0x%x\n", ivt_offset); 549 printf("\tstart = 0x%08lx\n", start); 550 printf("\tbytes = 0x%x\n", bytes); 551 #endif 552 /* 553 * If the MMU is enabled, we have to notify the ROM 554 * code, or it won't flush the caches when needed. 555 * This is done, by setting the "pu_irom_mmu_enabled" 556 * word to 1. You can find its address by looking in 557 * the ROM map. This is critical for 558 * authenticate_image(). If MMU is enabled, without 559 * setting this bit, authentication will fail and may 560 * crash. 561 */ 562 /* Check MMU enabled */ 563 if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) { 564 if (is_mx6dq()) { 565 /* 566 * This won't work on Rev 1.0.0 of 567 * i.MX6Q/D, since their ROM doesn't 568 * do cache flushes. don't think any 569 * exist, so we ignore them. 570 */ 571 if (!is_mx6dqp()) 572 writel(1, MX6DQ_PU_IROM_MMU_EN_VAR); 573 } else if (is_mx6sdl()) { 574 writel(1, MX6DLS_PU_IROM_MMU_EN_VAR); 575 } else if (is_mx6sl()) { 576 writel(1, MX6SL_PU_IROM_MMU_EN_VAR); 577 } 578 } 579 580 load_addr = (uint32_t)hab_rvt_authenticate_image( 581 HAB_CID_UBOOT, 582 ivt_offset, (void **)&start, 583 (size_t *)&bytes, NULL); 584 if (hab_rvt_exit() != HAB_SUCCESS) { 585 puts("hab exit function fail\n"); 586 load_addr = 0; 587 } 588 589 hab_exit_failure_print_status: 590 #if !defined(CONFIG_SPL_BUILD) 591 get_hab_status(); 592 #endif 593 594 hab_caam_clock_disable: 595 hab_caam_clock_enable(0); 596 597 if (load_addr != 0) 598 result = 0; 599 600 return result; 601 } 602