blob: 8dee595eaf85359bcf6a128fba2b088cc77cbbee [file] [log] [blame]
Stefano Babicb83c7092013-06-28 00:20:21 +02001/*
Nitin Garg36c1ca42014-09-16 13:33:25 -05002 * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
Stefano Babicb83c7092013-06-28 00:20:21 +02003 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#include <common.h>
8#include <asm/io.h>
Nitin Garg36c1ca42014-09-16 13:33:25 -05009#include <asm/system.h>
Stefano Babicb83c7092013-06-28 00:20:21 +020010#include <asm/arch/hab.h>
Nitin Garg36c1ca42014-09-16 13:33:25 -050011#include <asm/arch/clock.h>
Stefano Babicf2f07e82014-06-10 10:26:22 +020012#include <asm/arch/sys_proto.h>
Stefano Babicb83c7092013-06-28 00:20:21 +020013
14/* -------- start of HAB API updates ------------*/
Stefano Babicf2f07e82014-06-10 10:26:22 +020015
16#define hab_rvt_report_event_p \
17( \
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) \
26)
27
28#define hab_rvt_report_status_p \
29( \
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) \
38)
39
40#define hab_rvt_authenticate_image_p \
41( \
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) \
50)
51
52#define hab_rvt_entry_p \
53( \
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) \
62)
63
64#define hab_rvt_exit_p \
65( \
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) \
74)
Stefano Babicb83c7092013-06-28 00:20:21 +020075
Nitin Garg36c1ca42014-09-16 13:33:25 -050076#define IVT_SIZE 0x20
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
82
83/*
84 * +------------+ 0x0 (DDR_UIMAGE_START) -
85 * | Header | |
86 * +------------+ 0x40 |
87 * | | |
88 * | | |
89 * | | |
90 * | | |
91 * | Image Data | |
92 * . | |
93 * . | > Stuff to be authenticated ----+
94 * . | | |
95 * | | | |
96 * | | | |
97 * +------------+ | |
98 * | | | |
99 * | Fill Data | | |
100 * | | | |
101 * +------------+ Align to ALIGN_SIZE | |
102 * | IVT | | |
103 * +------------+ + IVT_SIZE - |
104 * | | |
105 * | CSF DATA | <---------------------------------------------------------+
106 * | |
107 * +------------+
108 * | |
109 * | Fill Data |
110 * | |
111 * +------------+ + CSF_PAD_SIZE
112 */
113
Stefano Babicb83c7092013-06-28 00:20:21 +0200114bool is_hab_enabled(void)
115{
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);
121
122 return (reg & 0x2) == 0x2;
123}
124
125void display_event(uint8_t *event_data, size_t bytes)
126{
127 uint32_t i;
128
129 if (!(event_data && bytes > 0))
130 return;
131
132 for (i = 0; i < bytes; i++) {
133 if (i == 0)
134 printf("\t0x%02x", event_data[i]);
135 else if ((i % 8) == 0)
136 printf("\n\t0x%02x", event_data[i]);
137 else
138 printf(" 0x%02x", event_data[i]);
139 }
140}
141
142int get_hab_status(void)
143{
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;
Stefano Babicf2f07e82014-06-10 10:26:22 +0200149 hab_rvt_report_event_t *hab_rvt_report_event;
150 hab_rvt_report_status_t *hab_rvt_report_status;
151
152 hab_rvt_report_event = hab_rvt_report_event_p;
153 hab_rvt_report_status = hab_rvt_report_status_p;
Stefano Babicb83c7092013-06-28 00:20:21 +0200154
155 if (is_hab_enabled())
156 puts("\nSecure boot enabled\n");
157 else
158 puts("\nSecure boot disabled\n");
159
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",
163 config, state);
164
165 /* Display HAB Error events */
166 while (hab_rvt_report_event(HAB_FAILURE, index, event_data,
167 &bytes) == HAB_SUCCESS) {
168 puts("\n");
169 printf("--------- HAB Event %d -----------------\n",
170 index + 1);
171 puts("event data:\n");
172 display_event(event_data, bytes);
173 puts("\n");
174 bytes = sizeof(event_data);
175 index++;
176 }
177 }
178 /* Display message if no HAB events are found */
179 else {
180 printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
181 config, state);
182 puts("No HAB Events Found!\n\n");
183 }
184 return 0;
185}
186
Nitin Garg36c1ca42014-09-16 13:33:25 -0500187uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
188{
189 uint32_t load_addr = 0;
190 size_t bytes;
191 ptrdiff_t ivt_offset = 0;
192 int result = 0;
193 ulong start;
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;
197
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;
201
202 if (is_hab_enabled()) {
203 printf("\nAuthenticate image from DDR location 0x%x...\n",
204 ddr_start);
205
206 hab_caam_clock_enable(1);
207
208 if (hab_rvt_entry() == HAB_SUCCESS) {
209 /* If not already aligned, Align to ALIGN_SIZE */
210 ivt_offset = (image_size + ALIGN_SIZE - 1) &
211 ~(ALIGN_SIZE - 1);
212
213 start = ddr_start;
214 bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
215#ifdef DEBUG
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),
221 4, 0x8, 0);
222
223 puts("Dumping CSF Header\n");
224 print_buffer(ddr_start + ivt_offset+IVT_SIZE,
225 (void *)(ddr_start + ivt_offset+IVT_SIZE),
226 4, 0x10, 0);
227
228 get_hab_status();
229
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);
234#endif
235 /*
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
243 * crash.
244 */
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)) {
249 /*
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.
254 */
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);
261 }
262 }
263
264 load_addr = (uint32_t)hab_rvt_authenticate_image(
265 HAB_CID_UBOOT,
266 ivt_offset, (void **)&start,
267 (size_t *)&bytes, NULL);
268 if (hab_rvt_exit() != HAB_SUCCESS) {
269 puts("hab exit function fail\n");
270 load_addr = 0;
271 }
272 } else {
273 puts("hab entry function fail\n");
274 }
275
276 hab_caam_clock_enable(0);
277
278 get_hab_status();
279 } else {
280 puts("hab fuse not enabled\n");
281 }
282
283 if ((!is_hab_enabled()) || (load_addr != 0))
284 result = 1;
285
286 return result;
287}
288
Stefano Babicb83c7092013-06-28 00:20:21 +0200289int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
290{
291 if ((argc != 1)) {
292 cmd_usage(cmdtp);
293 return 1;
294 }
295
296 get_hab_status();
297
298 return 0;
299}
300
Nitin Garg36c1ca42014-09-16 13:33:25 -0500301static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
302 char * const argv[])
303{
304 ulong addr, ivt_offset;
305 int rcode = 0;
306
307 if (argc < 3)
308 return CMD_RET_USAGE;
309
310 addr = simple_strtoul(argv[1], NULL, 16);
311 ivt_offset = simple_strtoul(argv[2], NULL, 16);
312
313 rcode = authenticate_image(addr, ivt_offset);
314
315 return rcode;
316}
317
Stefano Babicb83c7092013-06-28 00:20:21 +0200318U_BOOT_CMD(
319 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
320 "display HAB status",
321 ""
322 );
Nitin Garg36c1ca42014-09-16 13:33:25 -0500323
324U_BOOT_CMD(
325 hab_auth_img, 3, 0, do_authenticate_image,
326 "authenticate image via HAB",
327 "addr ivt_offset\n"
328 "addr - image hex address\n"
329 "ivt_offset - hex offset of IVT in the image"
330 );