2 * Copyright (C) 2010-2015 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0+
10 #include <asm/system.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/sys_proto.h>
13 #include <asm/arch/hab.h>
15 HAB_FUNC(entry, enum hab_status)
16 HAB_FUNC(exit, enum hab_status)
17 HAB_FUNC5(authenticate_image, void *, uint8_t, size_t, void **, size_t *, hab_loader_callback_f_t)
18 //HAB_FUNC1(run_dcd, enum hab_status, const uint8_t *)
19 HAB_FUNC2(run_csf, enum hab_status, const uint8_t *, uint8_t)
20 HAB_FUNC2(report_status, enum hab_status, enum hab_config *, enum hab_state *)
21 HAB_FUNC4(report_event, enum hab_status, enum hab_status, uint32_t, uint8_t *, size_t *)
22 HAB_FUNC3(check_target, enum hab_status, uint8_t, const void *, size_t)
23 HAB_FUNC3(assert, enum hab_status, uint8_t, const void *, size_t)
25 #define MAX_RECORD_BYTES (8 * 1024)
27 #define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8
28 #define MX6SDL_PU_IROM_MMU_EN_VAR 0x00901dd0
29 #define MX6SL_PU_IROM_MMU_EN_VAR 0x00900a18
32 uint8_t tag; /* Tag */
33 uint8_t len[2]; /* Length */
34 uint8_t par; /* Version */
35 uint8_t contents[MAX_RECORD_BYTES]; /* Record Data */
40 "RSN = HAB_RSN_ANY (0x00)\n",
41 "RSN = HAB_ENG_FAIL (0x30)\n",
42 "RSN = HAB_INV_ADDRESS (0x22)\n",
43 "RSN = HAB_INV_ASSERTION (0x0C)\n",
44 "RSN = HAB_INV_CALL (0x28)\n",
45 "RSN = HAB_INV_CERTIFICATE (0x21)\n",
46 "RSN = HAB_INV_COMMAND (0x06)\n",
47 "RSN = HAB_INV_CSF (0x11)\n",
48 "RSN = HAB_INV_DCD (0x27)\n",
49 "RSN = HAB_INV_INDEX (0x0F)\n",
50 "RSN = HAB_INV_IVT (0x05)\n",
51 "RSN = HAB_INV_KEY (0x1D)\n",
52 "RSN = HAB_INV_RETURN (0x1E)\n",
53 "RSN = HAB_INV_SIGNATURE (0x18)\n",
54 "RSN = HAB_INV_SIZE (0x17)\n",
55 "RSN = HAB_MEM_FAIL (0x2E)\n",
56 "RSN = HAB_OVR_COUNT (0x2B)\n",
57 "RSN = HAB_OVR_STORAGE (0x2D)\n",
58 "RSN = HAB_UNS_ALGORITHM (0x12)\n",
59 "RSN = HAB_UNS_COMMAND (0x03)\n",
60 "RSN = HAB_UNS_ENGINE (0x0A)\n",
61 "RSN = HAB_UNS_ITEM (0x24)\n",
62 "RSN = HAB_UNS_KEY (0x1B)\n",
63 "RSN = HAB_UNS_PROTOCOL (0x14)\n",
64 "RSN = HAB_UNS_STATE (0x09)\n",
69 "STS = HAB_STS_ANY (0x00)\n",
70 "STS = HAB_FAILURE (0x33)\n",
71 "STS = HAB_WARNING (0x69)\n",
72 "STS = HAB_SUCCESS (0xF0)\n",
77 "ENG = HAB_ENG_ANY (0x00)\n",
78 "ENG = HAB_ENG_SCC (0x03)\n",
79 "ENG = HAB_ENG_RTIC (0x05)\n",
80 "ENG = HAB_ENG_SAHARA (0x06)\n",
81 "ENG = HAB_ENG_CSU (0x0A)\n",
82 "ENG = HAB_ENG_SRTC (0x0C)\n",
83 "ENG = HAB_ENG_DCP (0x1B)\n",
84 "ENG = HAB_ENG_CAAM (0x1D)\n",
85 "ENG = HAB_ENG_SNVS (0x1E)\n",
86 "ENG = HAB_ENG_OCOTP (0x21)\n",
87 "ENG = HAB_ENG_DTCP (0x22)\n",
88 "ENG = HAB_ENG_ROM (0x36)\n",
89 "ENG = HAB_ENG_HDCP (0x24)\n",
90 "ENG = HAB_ENG_RTL (0x77)\n",
91 "ENG = HAB_ENG_SW (0xFF)\n",
96 "CTX = HAB_CTX_ANY(0x00)\n",
97 "CTX = HAB_CTX_FAB (0xFF)\n",
98 "CTX = HAB_CTX_ENTRY (0xE1)\n",
99 "CTX = HAB_CTX_TARGET (0x33)\n",
100 "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
101 "CTX = HAB_CTX_DCD (0xDD)\n",
102 "CTX = HAB_CTX_CSF (0xCF)\n",
103 "CTX = HAB_CTX_COMMAND (0xC0)\n",
104 "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
105 "CTX = HAB_CTX_ASSERT (0xA0)\n",
106 "CTX = HAB_CTX_EXIT (0xEE)\n",
110 uint8_t hab_statuses[ARRAY_SIZE(sts_str)] = {
118 uint8_t hab_reasons[ARRAY_SIZE(rsn_str)] = {
147 uint8_t hab_contexts[ARRAY_SIZE(ctx_str)] = {
152 HAB_CTX_AUTHENTICATE,
162 uint8_t hab_engines[ARRAY_SIZE(eng_str)] = {
181 bool is_hab_enabled(void)
184 static int first = 1;
186 if (fuse_read(0, 6, ®)) {
187 printf("Failed to read SECURE_BOOT fuse\n");
192 debug("rvt_base=%p\n", hab_rvt_base());
193 debug("hab_rvt_entry=%p\n", hab_rvt_entry_p);
194 debug("hab_rvt_exit=%p\n", hab_rvt_exit_p);
195 debug("hab_rvt_check_target=%p\n", hab_rvt_check_target_p);
196 debug("hab_rvt_authenticate_image=%p\n", hab_rvt_authenticate_image_p);
197 debug("hab_rvt_report_event=%p\n", hab_rvt_report_event_p);
198 debug("hab_rvt_report_status=%p\n", hab_rvt_report_status_p);
199 debug("hab_rvt_assert=%p\n", hab_rvt_assert_p);
202 return (reg & 0x2) == 0x2;
205 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
208 uint8_t element = list[idx];
209 while (element != -1) {
212 element = list[++idx];
217 void process_event_record(uint8_t *event_data, size_t bytes)
219 struct record *rec = (struct record *)event_data;
221 printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]);
222 printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]);
223 printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]);
224 printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
227 void display_event(uint8_t *event_data, size_t bytes)
231 if (!(event_data && bytes > 0))
234 for (i = 0; i < bytes; i++) {
236 printf("\t0x%02x", event_data[i]);
237 else if ((i % 8) == 0)
238 printf("\n\t0x%02x", event_data[i]);
240 printf(" 0x%02x", event_data[i]);
243 process_event_record(event_data, bytes);
246 static uint32_t last_hab_event __attribute__((section(".data")));
248 int get_hab_status(void)
250 uint32_t index = last_hab_event; /* Loop index */
251 uint8_t event_data[128]; /* Event data buffer */
252 size_t bytes = sizeof(event_data); /* Event size in bytes */
253 enum hab_config config = 0;
254 enum hab_state state = 0;
255 static int first = 1;
259 printf("Secure boot %sabled\n",
260 is_hab_enabled() ? "en" : "dis");
263 /* Check HAB status */
265 ret = hab_rvt_report_status(&config, &state);
268 printf("HAB Configuration: 0x%02x, HAB State: 0x%02x\n",
270 if (ret != HAB_SUCCESS) {
271 /* Display HAB Error events */
272 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
273 &bytes) == HAB_SUCCESS) {
275 printf("--------- HAB Event %d -----------------\n",
277 puts("event data:\n");
278 display_event(event_data, bytes);
280 bytes = sizeof(event_data);
283 ret = index - last_hab_event;
284 last_hab_event = index;
286 /* Display message if no HAB events are found */
287 puts("No HAB Events Found!\n");
294 static inline void hab_clear_events(void)
296 uint32_t index = last_hab_event; /* Loop index */
297 uint8_t event_data[128]; /* Event data buffer */
298 size_t bytes = sizeof(event_data); /* Event size in bytes */
299 enum hab_config config = 0;
300 enum hab_state state = 0;
303 /* Check HAB status */
305 ret = hab_rvt_report_status(&config, &state);
307 if (ret != HAB_SUCCESS) {
308 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
309 &bytes) == HAB_SUCCESS) {
312 last_hab_event = index;
316 static inline enum hab_status hab_init(void)
322 hab_caam_clock_enable(1);
324 ret = hab_rvt_entry();
325 debug("hab_rvt_entry() returned %02x\n", ret);
326 if (ret != HAB_SUCCESS) {
327 printf("hab entry function failed: %02x\n", ret);
328 hab_caam_clock_enable(0);
334 static inline enum hab_status hab_exit(void)
338 ret = hab_rvt_exit();
339 if (ret != HAB_SUCCESS)
340 printf("hab exit function failed: %02x\n", ret);
342 hab_caam_clock_enable(0);
348 static enum hab_status hab_check_target(enum hab_target type, uint32_t addr, size_t len)
353 if (ret != HAB_SUCCESS)
356 ret = hab_rvt_check_target(type, (void *)addr, len);
357 if (ret != HAB_SUCCESS) {
358 printf("check_target(0x%08x, 0x%08x) failed: %d\n",
364 if (ret == HAB_SUCCESS && get_hab_status() > 0) {
370 static enum hab_status hab_assert(uint32_t type, uint32_t addr, size_t len)
375 if (ret != HAB_SUCCESS)
378 ret = hab_rvt_assert(type, (void *)addr, len);
379 if (ret != HAB_SUCCESS) {
380 printf("assert(0x%08x, 0x%08x) failed: %d\n",
386 if (ret == HAB_SUCCESS && get_hab_status() > 0) {
392 static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc,
396 return CMD_RET_USAGE;
400 return CMD_RET_SUCCESS;
403 static int do_hab_check_target(cmd_tbl_t *cmdtp, int flag, int argc,
406 enum hab_target type = HAB_TGT_ANY;
411 return CMD_RET_USAGE;
413 addr = simple_strtoul(argv[1], NULL, 16);
414 len = simple_strtoul(argv[2], NULL, 16);
416 switch (argv[3][0]) {
419 type = HAB_TGT_PERIPHERAL;
423 type = HAB_TGT_MEMORY;
429 printf("Invalid type '%s'\n", argv[3]);
430 return CMD_RET_USAGE;
433 if (hab_check_target(type, addr, len) != HAB_SUCCESS)
434 return CMD_RET_FAILURE;
436 return CMD_RET_SUCCESS;
439 static int do_hab_assert(cmd_tbl_t *cmdtp, int flag, int argc,
447 return CMD_RET_USAGE;
449 addr = simple_strtoul(argv[1], NULL, 16);
450 len = simple_strtoul(argv[2], NULL, 16);
452 type = simple_strtoul(argv[3], NULL, 16);
455 if (hab_assert(type, addr, len) != HAB_SUCCESS)
456 return CMD_RET_FAILURE;
458 return CMD_RET_SUCCESS;
461 /* Get CSF Header length */
462 static int get_hab_hdr_len(struct hab_hdr *hdr)
464 return (size_t)((hdr->len[0] << 8) + (hdr->len[1]));
467 /* Check whether addr lies between start and
468 * end and is within the length of the image
470 static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end)
472 size_t csf_size = (size_t)((end + 1) - addr);
474 return addr && (addr >= start) && (addr <= end) &&
478 /* Get Length of each command in CSF */
479 static int get_csf_cmd_hdr_len(u8 *csf_hdr)
481 if (*csf_hdr == HAB_CMD_HDR)
482 return sizeof(struct hab_hdr);
484 return get_hab_hdr_len((struct hab_hdr *)csf_hdr);
487 /* Check if CSF is valid */
488 static inline bool csf_is_valid(struct ivt *ivt, void *addr, size_t bytes)
499 end = start + bytes - 1;
503 /* Verify if CSF pointer content is zero */
505 puts("Error: CSF pointer is NULL\n");
509 csf_hdr = (u8 *)(uintptr_t)ivt->csf;
511 /* Verify if CSF Header exist */
512 if (*csf_hdr != HAB_CMD_HDR) {
513 puts("Error: CSF header command not found\n");
517 csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr);
519 /* Check if the CSF lies within the image bounds */
520 if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) {
521 puts("Error: CSF lies outside the image bounds\n");
528 cmd = (struct hab_hdr *)&csf_hdr[offset];
531 case (HAB_CMD_WRT_DAT):
532 puts("Error: Deprecated write command found\n");
534 case (HAB_CMD_CHK_DAT):
535 puts("Error: Deprecated check command found\n");
538 if (cmd->par == HAB_PAR_MID) {
539 puts("Error: Deprecated Set MID command found\n");
546 cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]);
548 puts("Error: Invalid command length\n");
551 offset += cmd_hdr_len;
553 } while (offset < csf_hdr_len);
558 static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
560 printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str,
561 ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version);
566 static int verify_ivt_header(struct ivt_header *ivt_hdr)
568 if (ivt_hdr->magic != IVT_HEADER_MAGIC)
569 return ivt_header_error("bad IVT magic", ivt_hdr);
571 if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH)
572 return ivt_header_error("bad IVT length", ivt_hdr);
574 if (ivt_hdr->version != IVT_HEADER_V1 &&
575 ivt_hdr->version != IVT_HEADER_V2)
576 return ivt_header_error("bad IVT version", ivt_hdr);
582 * Validate IVT structure of the image being authenticated
584 static int validate_ivt(struct ivt *ivt)
586 struct ivt_header *ivt_hdr = &ivt->hdr;
588 if ((uintptr_t)ivt & 0x3) {
589 puts("Error: IVT address is not 4 byte aligned\n");
593 /* Check IVT fields before allowing authentication */
594 if ((!verify_ivt_header(ivt_hdr)) &&
595 (ivt->entry != 0x0) &&
596 (ivt->reserved1 == 0x0) &&
597 (ivt->self == (uint32_t)ivt) &&
599 (ivt->reserved2 == 0x0) &&
604 puts("Error: Invalid IVT structure\n");
605 if (ivt->entry == 0x0)
606 printf("entry address must not be NULL\n");
607 if (ivt->reserved1 != 0x0)
608 printf("reserved word at offset 0x%02x should be NULL\n",
609 offsetof(struct ivt, reserved1));
611 puts("Error: DCD pointer must be 0\n");
612 if (ivt->self != (uint32_t)ivt)
613 printf("SELF pointer does not point to IVT\n");
615 printf("CSF address must not be NULL\n");
616 if (ivt->reserved2 != 0x0)
617 printf("reserved word at offset 0x%02x should be NULL\n",
618 offsetof(struct ivt, reserved2));
619 puts("\nAllowed IVT structure:\n");
620 printf("IVT HDR = 0x4X2000D1 (0x%08x)\n", *((u32 *)&ivt->hdr));
621 printf("IVT ENTRY = 0xXXXXXXXX (0x%08x)\n", ivt->entry);
622 printf("IVT RSV1 = 0x00000000 (0x%08x)\n", ivt->reserved1);
623 printf("IVT DCD = 0x00000000 (0x%08x)\n", ivt->dcd);
624 printf("IVT BOOT_DATA = 0xXXXXXXXX (0x%08x)\n", ivt->boot);
625 printf("IVT SELF = 0xXXXXXXXX (0x%08x)\n", ivt->self);
626 printf("IVT CSF = 0xXXXXXXXX (0x%08x)\n", ivt->csf);
627 printf("IVT RSV2 = 0x00000000 (0x%08x)\n", ivt->reserved2);
629 /* Invalid IVT structure */
633 bool imx_hab_authenticate_image(void *addr, size_t len, size_t ivt_offset)
636 enum hab_status status;
638 if (len <= sizeof(ivt)) {
639 printf("Invalid image size %08x\n", len);
642 if (ivt_offset >= len - sizeof(*ivt)) {
643 printf("IVT offset must be smaller than image size - %u\n",
648 ivt = addr + ivt_offset;
649 /* Verify IVT header bugging out on error */
650 if (!validate_ivt(ivt)) {
651 print_buffer((ulong)ivt, ivt, 4, 0x8, 0);
655 if (!csf_is_valid(ivt, addr, len)) {
656 print_buffer(ivt->csf, (void *)(ivt->csf), 4, 0x10, 0);
661 if (status != HAB_SUCCESS)
666 status = hab_rvt_check_target(HAB_TGT_MEMORY, addr, len);
667 if (status != HAB_SUCCESS) {
668 printf("HAB check target 0x%p-0x%p failed\n",
675 * If the MMU is enabled, we have to notify the ROM
676 * code, or it won't flush the caches when needed.
677 * This is done, by setting the "pu_irom_mmu_enabled"
678 * word to 1. You can find its address by looking in
679 * the ROM map. This is critical for
680 * authenticate_image(). If MMU is enabled, without
681 * setting this bit, authentication will fail and may
684 /* Check MMU enabled */
685 if (get_cr() & CR_M) {
686 if (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D)) {
688 * This won't work on Rev 1.0.0 of
689 * i.MX6Q/D, since their ROM doesn't
690 * do cache flushes. don't think any
691 * exist, so we ignore them.
694 writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
695 } else if (is_cpu_type(MXC_CPU_MX6SOLO) ||
696 is_cpu_type(MXC_CPU_MX6DL)) {
697 writel(1, MX6SDL_PU_IROM_MMU_EN_VAR);
698 } else if (is_cpu_type(MXC_CPU_MX6SL)) {
699 writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
703 hab_rvt_authenticate_image(HAB_CID_UBOOT, ivt_offset, &addr,
706 if (status != HAB_SUCCESS)
709 if (get_hab_status() != 0) {
710 printf("ERROR: hab_authenticate_image failed\n");
713 printf("HAB authentication of image at %p..%p successful\n",
718 printf("ERROR: HAB authentication failure: %02x\n", status);
723 static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
727 size_t ivt_offset, len;
730 return CMD_RET_USAGE;
732 addr = (void *)simple_strtoul(argv[1], NULL, 16);
733 len = simple_strtoul(argv[2], NULL, 16);
734 ivt_offset = simple_strtoul(argv[3], NULL, 16);
736 if (imx_hab_authenticate_image(addr, len, ivt_offset))
737 return CMD_RET_SUCCESS;
741 return CMD_RET_FAILURE;
745 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
746 "display HAB status",
751 hab_check_target, 4, 0, do_hab_check_target,
752 "verify an address range via HAB",
754 "\t\taddr -\taddress to verify\n"
755 "\t\tlen -\tlength of addr range to verify\n"
759 hab_assert, 4, 0, do_hab_assert,
760 "Test an assertion against the HAB audit log",
762 "\t\taddr -\taddress to verify\n"
763 "\t\tlen -\tlength of addr range to verify\n"
767 hab_auth_img, 4, 0, do_authenticate_image,
768 "authenticate image via HAB",
769 "addr len ivt_offset\n"
770 "addr - image hex address\n"
771 "len - image size (hex)\n"
772 "ivt_offset - hex offset of IVT in the image"