2 * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0+
9 #include <asm/system.h>
10 #include <asm/arch/hab.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/sys_proto.h>
14 /* -------- start of HAB API updates ------------*/
16 #define hab_rvt_report_event_p \
18 ((is_cpu_type(MXC_CPU_MX6Q) || \
19 is_cpu_type(MXC_CPU_MX6D)) && \
20 (soc_rev() >= CHIP_REV_1_5)) ? \
21 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \
22 (is_cpu_type(MXC_CPU_MX6DL) && \
23 (soc_rev() >= CHIP_REV_1_2)) ? \
24 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \
25 ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT) \
28 #define hab_rvt_report_status_p \
30 ((is_cpu_type(MXC_CPU_MX6Q) || \
31 is_cpu_type(MXC_CPU_MX6D)) && \
32 (soc_rev() >= CHIP_REV_1_5)) ? \
33 ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\
34 (is_cpu_type(MXC_CPU_MX6DL) && \
35 (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) \
40 #define hab_rvt_authenticate_image_p \
42 ((is_cpu_type(MXC_CPU_MX6Q) || \
43 is_cpu_type(MXC_CPU_MX6D)) && \
44 (soc_rev() >= CHIP_REV_1_5)) ? \
45 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \
46 (is_cpu_type(MXC_CPU_MX6DL) && \
47 (soc_rev() >= CHIP_REV_1_2)) ? \
48 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \
49 ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE) \
52 #define hab_rvt_entry_p \
54 ((is_cpu_type(MXC_CPU_MX6Q) || \
55 is_cpu_type(MXC_CPU_MX6D)) && \
56 (soc_rev() >= CHIP_REV_1_5)) ? \
57 ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \
58 (is_cpu_type(MXC_CPU_MX6DL) && \
59 (soc_rev() >= CHIP_REV_1_2)) ? \
60 ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \
61 ((hab_rvt_entry_t *)HAB_RVT_ENTRY) \
64 #define hab_rvt_exit_p \
66 ((is_cpu_type(MXC_CPU_MX6Q) || \
67 is_cpu_type(MXC_CPU_MX6D)) && \
68 (soc_rev() >= CHIP_REV_1_5)) ? \
69 ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \
70 (is_cpu_type(MXC_CPU_MX6DL) && \
71 (soc_rev() >= CHIP_REV_1_2)) ? \
72 ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \
73 ((hab_rvt_exit_t *)HAB_RVT_EXIT) \
77 #define ALIGN_SIZE 0x1000
78 #define CSF_PAD_SIZE 0x2000
79 #define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8
80 #define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0
81 #define MX6SL_PU_IROM_MMU_EN_VAR 0x00900a18
84 * +------------+ 0x0 (DDR_UIMAGE_START) -
86 * +------------+ 0x40 |
93 * . | > Stuff to be authenticated ----+
101 * +------------+ Align to ALIGN_SIZE | |
103 * +------------+ + IVT_SIZE - |
105 * | CSF DATA | <---------------------------------------------------------+
111 * +------------+ + CSF_PAD_SIZE
114 bool is_hab_enabled(void)
116 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
117 struct fuse_bank *bank = &ocotp->bank[0];
118 struct fuse_bank0_regs *fuse =
119 (struct fuse_bank0_regs *)bank->fuse_regs;
120 uint32_t reg = readl(&fuse->cfg5);
122 return (reg & 0x2) == 0x2;
125 void display_event(uint8_t *event_data, size_t bytes)
129 if (!(event_data && bytes > 0))
132 for (i = 0; i < bytes; i++) {
134 printf("\t0x%02x", event_data[i]);
135 else if ((i % 8) == 0)
136 printf("\n\t0x%02x", event_data[i]);
138 printf(" 0x%02x", event_data[i]);
142 int get_hab_status(void)
144 uint32_t index = 0; /* Loop index */
145 uint8_t event_data[128]; /* Event data buffer */
146 size_t bytes = sizeof(event_data); /* Event size in bytes */
147 enum hab_config config = 0;
148 enum hab_state state = 0;
149 hab_rvt_report_event_t *hab_rvt_report_event;
150 hab_rvt_report_status_t *hab_rvt_report_status;
152 hab_rvt_report_event = hab_rvt_report_event_p;
153 hab_rvt_report_status = hab_rvt_report_status_p;
155 if (is_hab_enabled())
156 puts("\nSecure boot enabled\n");
158 puts("\nSecure boot disabled\n");
160 /* Check HAB status */
161 if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) {
162 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
165 /* Display HAB Error events */
166 while (hab_rvt_report_event(HAB_FAILURE, index, event_data,
167 &bytes) == HAB_SUCCESS) {
169 printf("--------- HAB Event %d -----------------\n",
171 puts("event data:\n");
172 display_event(event_data, bytes);
174 bytes = sizeof(event_data);
178 /* Display message if no HAB events are found */
180 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
182 puts("No HAB Events Found!\n\n");
187 uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
189 uint32_t load_addr = 0;
191 ptrdiff_t ivt_offset = 0;
194 hab_rvt_authenticate_image_t *hab_rvt_authenticate_image;
195 hab_rvt_entry_t *hab_rvt_entry;
196 hab_rvt_exit_t *hab_rvt_exit;
198 hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
199 hab_rvt_entry = hab_rvt_entry_p;
200 hab_rvt_exit = hab_rvt_exit_p;
202 if (is_hab_enabled()) {
203 printf("\nAuthenticate image from DDR location 0x%x...\n",
206 hab_caam_clock_enable(1);
208 if (hab_rvt_entry() == HAB_SUCCESS) {
209 /* If not already aligned, Align to ALIGN_SIZE */
210 ivt_offset = (image_size + ALIGN_SIZE - 1) &
214 bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
216 printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n",
217 ivt_offset, ddr_start + ivt_offset);
218 puts("Dumping IVT\n");
219 print_buffer(ddr_start + ivt_offset,
220 (void *)(ddr_start + ivt_offset),
223 puts("Dumping CSF Header\n");
224 print_buffer(ddr_start + ivt_offset+IVT_SIZE,
225 (void *)(ddr_start + ivt_offset+IVT_SIZE),
230 puts("\nCalling authenticate_image in ROM\n");
231 printf("\tivt_offset = 0x%x\n", ivt_offset);
232 printf("\tstart = 0x%08lx\n", start);
233 printf("\tbytes = 0x%x\n", bytes);
236 * If the MMU is enabled, we have to notify the ROM
237 * code, or it won't flush the caches when needed.
238 * This is done, by setting the "pu_irom_mmu_enabled"
239 * word to 1. You can find its address by looking in
240 * the ROM map. This is critical for
241 * authenticate_image(). If MMU is enabled, without
242 * setting this bit, authentication will fail and may
245 /* Check MMU enabled */
246 if (get_cr() & CR_M) {
247 if (is_cpu_type(MXC_CPU_MX6Q) ||
248 is_cpu_type(MXC_CPU_MX6D)) {
250 * This won't work on Rev 1.0.0 of
251 * i.MX6Q/D, since their ROM doesn't
252 * do cache flushes. don't think any
253 * exist, so we ignore them.
255 writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
256 } else if (is_cpu_type(MXC_CPU_MX6DL) ||
257 is_cpu_type(MXC_CPU_MX6SOLO)) {
258 writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
259 } else if (is_cpu_type(MXC_CPU_MX6SL)) {
260 writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
264 load_addr = (uint32_t)hab_rvt_authenticate_image(
266 ivt_offset, (void **)&start,
267 (size_t *)&bytes, NULL);
268 if (hab_rvt_exit() != HAB_SUCCESS) {
269 puts("hab exit function fail\n");
273 puts("hab entry function fail\n");
276 hab_caam_clock_enable(0);
280 puts("hab fuse not enabled\n");
283 if ((!is_hab_enabled()) || (load_addr != 0))
289 int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
301 static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
304 ulong addr, ivt_offset;
308 return CMD_RET_USAGE;
310 addr = simple_strtoul(argv[1], NULL, 16);
311 ivt_offset = simple_strtoul(argv[2], NULL, 16);
313 rcode = authenticate_image(addr, ivt_offset);
319 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
320 "display HAB status",
325 hab_auth_img, 3, 0, do_authenticate_image,
326 "authenticate image via HAB",
328 "addr - image hex address\n"
329 "ivt_offset - hex offset of IVT in the image"