xref: /openbmc/u-boot/arch/arm/mach-imx/hab.c (revision 8502f9f6)
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 #define IVT_SIZE		0x20
74 #define ALIGN_SIZE		0x1000
75 #define CSF_PAD_SIZE		0x2000
76 #define MX6DQ_PU_IROM_MMU_EN_VAR	0x009024a8
77 #define MX6DLS_PU_IROM_MMU_EN_VAR	0x00901dd0
78 #define MX6SL_PU_IROM_MMU_EN_VAR	0x00900a18
79 #define IS_HAB_ENABLED_BIT \
80 	(is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 :	\
81 	 (is_soc_type(MXC_SOC_MX7) ? 0x2000000 : 0x2))
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 
114 static bool is_hab_enabled(void);
115 
116 #if !defined(CONFIG_SPL_BUILD)
117 
118 #define MAX_RECORD_BYTES     (8*1024) /* 4 kbytes */
119 
120 struct record {
121 	uint8_t  tag;						/* Tag */
122 	uint8_t  len[2];					/* Length */
123 	uint8_t  par;						/* Version */
124 	uint8_t  contents[MAX_RECORD_BYTES];/* Record Data */
125 	bool	 any_rec_flag;
126 };
127 
128 char *rsn_str[] = {"RSN = HAB_RSN_ANY (0x00)\n",
129 				   "RSN = HAB_ENG_FAIL (0x30)\n",
130 				   "RSN = HAB_INV_ADDRESS (0x22)\n",
131 				   "RSN = HAB_INV_ASSERTION (0x0C)\n",
132 				   "RSN = HAB_INV_CALL (0x28)\n",
133 				   "RSN = HAB_INV_CERTIFICATE (0x21)\n",
134 				   "RSN = HAB_INV_COMMAND (0x06)\n",
135 				   "RSN = HAB_INV_CSF (0x11)\n",
136 				   "RSN = HAB_INV_DCD (0x27)\n",
137 				   "RSN = HAB_INV_INDEX (0x0F)\n",
138 				   "RSN = HAB_INV_IVT (0x05)\n",
139 				   "RSN = HAB_INV_KEY (0x1D)\n",
140 				   "RSN = HAB_INV_RETURN (0x1E)\n",
141 				   "RSN = HAB_INV_SIGNATURE (0x18)\n",
142 				   "RSN = HAB_INV_SIZE (0x17)\n",
143 				   "RSN = HAB_MEM_FAIL (0x2E)\n",
144 				   "RSN = HAB_OVR_COUNT (0x2B)\n",
145 				   "RSN = HAB_OVR_STORAGE (0x2D)\n",
146 				   "RSN = HAB_UNS_ALGORITHM (0x12)\n",
147 				   "RSN = HAB_UNS_COMMAND (0x03)\n",
148 				   "RSN = HAB_UNS_ENGINE (0x0A)\n",
149 				   "RSN = HAB_UNS_ITEM (0x24)\n",
150 				   "RSN = HAB_UNS_KEY (0x1B)\n",
151 				   "RSN = HAB_UNS_PROTOCOL (0x14)\n",
152 				   "RSN = HAB_UNS_STATE (0x09)\n",
153 				   "RSN = INVALID\n",
154 				   NULL};
155 
156 char *sts_str[] = {"STS = HAB_SUCCESS (0xF0)\n",
157 				   "STS = HAB_FAILURE (0x33)\n",
158 				   "STS = HAB_WARNING (0x69)\n",
159 				   "STS = INVALID\n",
160 				   NULL};
161 
162 char *eng_str[] = {"ENG = HAB_ENG_ANY (0x00)\n",
163 				   "ENG = HAB_ENG_SCC (0x03)\n",
164 				   "ENG = HAB_ENG_RTIC (0x05)\n",
165 				   "ENG = HAB_ENG_SAHARA (0x06)\n",
166 				   "ENG = HAB_ENG_CSU (0x0A)\n",
167 				   "ENG = HAB_ENG_SRTC (0x0C)\n",
168 				   "ENG = HAB_ENG_DCP (0x1B)\n",
169 				   "ENG = HAB_ENG_CAAM (0x1D)\n",
170 				   "ENG = HAB_ENG_SNVS (0x1E)\n",
171 				   "ENG = HAB_ENG_OCOTP (0x21)\n",
172 				   "ENG = HAB_ENG_DTCP (0x22)\n",
173 				   "ENG = HAB_ENG_ROM (0x36)\n",
174 				   "ENG = HAB_ENG_HDCP (0x24)\n",
175 				   "ENG = HAB_ENG_RTL (0x77)\n",
176 				   "ENG = HAB_ENG_SW (0xFF)\n",
177 				   "ENG = INVALID\n",
178 				   NULL};
179 
180 char *ctx_str[] = {"CTX = HAB_CTX_ANY(0x00)\n",
181 				   "CTX = HAB_CTX_FAB (0xFF)\n",
182 				   "CTX = HAB_CTX_ENTRY (0xE1)\n",
183 				   "CTX = HAB_CTX_TARGET (0x33)\n",
184 				   "CTX = HAB_CTX_AUTHENTICATE (0x0A)\n",
185 				   "CTX = HAB_CTX_DCD (0xDD)\n",
186 				   "CTX = HAB_CTX_CSF (0xCF)\n",
187 				   "CTX = HAB_CTX_COMMAND (0xC0)\n",
188 				   "CTX = HAB_CTX_AUT_DAT (0xDB)\n",
189 				   "CTX = HAB_CTX_ASSERT (0xA0)\n",
190 				   "CTX = HAB_CTX_EXIT (0xEE)\n",
191 				   "CTX = INVALID\n",
192 				   NULL};
193 
194 uint8_t hab_statuses[5] = {
195 	HAB_STS_ANY,
196 	HAB_FAILURE,
197 	HAB_WARNING,
198 	HAB_SUCCESS,
199 	-1
200 };
201 
202 uint8_t hab_reasons[26] = {
203 	HAB_RSN_ANY,
204 	HAB_ENG_FAIL,
205 	HAB_INV_ADDRESS,
206 	HAB_INV_ASSERTION,
207 	HAB_INV_CALL,
208 	HAB_INV_CERTIFICATE,
209 	HAB_INV_COMMAND,
210 	HAB_INV_CSF,
211 	HAB_INV_DCD,
212 	HAB_INV_INDEX,
213 	HAB_INV_IVT,
214 	HAB_INV_KEY,
215 	HAB_INV_RETURN,
216 	HAB_INV_SIGNATURE,
217 	HAB_INV_SIZE,
218 	HAB_MEM_FAIL,
219 	HAB_OVR_COUNT,
220 	HAB_OVR_STORAGE,
221 	HAB_UNS_ALGORITHM,
222 	HAB_UNS_COMMAND,
223 	HAB_UNS_ENGINE,
224 	HAB_UNS_ITEM,
225 	HAB_UNS_KEY,
226 	HAB_UNS_PROTOCOL,
227 	HAB_UNS_STATE,
228 	-1
229 };
230 
231 uint8_t hab_contexts[12] = {
232 	HAB_CTX_ANY,
233 	HAB_CTX_FAB,
234 	HAB_CTX_ENTRY,
235 	HAB_CTX_TARGET,
236 	HAB_CTX_AUTHENTICATE,
237 	HAB_CTX_DCD,
238 	HAB_CTX_CSF,
239 	HAB_CTX_COMMAND,
240 	HAB_CTX_AUT_DAT,
241 	HAB_CTX_ASSERT,
242 	HAB_CTX_EXIT,
243 	-1
244 };
245 
246 uint8_t hab_engines[16] = {
247 	HAB_ENG_ANY,
248 	HAB_ENG_SCC,
249 	HAB_ENG_RTIC,
250 	HAB_ENG_SAHARA,
251 	HAB_ENG_CSU,
252 	HAB_ENG_SRTC,
253 	HAB_ENG_DCP,
254 	HAB_ENG_CAAM,
255 	HAB_ENG_SNVS,
256 	HAB_ENG_OCOTP,
257 	HAB_ENG_DTCP,
258 	HAB_ENG_ROM,
259 	HAB_ENG_HDCP,
260 	HAB_ENG_RTL,
261 	HAB_ENG_SW,
262 	-1
263 };
264 
265 static inline uint8_t get_idx(uint8_t *list, uint8_t tgt)
266 {
267 	uint8_t idx = 0;
268 	uint8_t element = list[idx];
269 	while (element != -1) {
270 		if (element == tgt)
271 			return idx;
272 		element = list[++idx];
273 	}
274 	return -1;
275 }
276 
277 void process_event_record(uint8_t *event_data, size_t bytes)
278 {
279 	struct record *rec = (struct record *)event_data;
280 
281 	printf("\n\n%s", sts_str[get_idx(hab_statuses, rec->contents[0])]);
282 	printf("%s", rsn_str[get_idx(hab_reasons, rec->contents[1])]);
283 	printf("%s", ctx_str[get_idx(hab_contexts, rec->contents[2])]);
284 	printf("%s", eng_str[get_idx(hab_engines, rec->contents[3])]);
285 }
286 
287 void display_event(uint8_t *event_data, size_t bytes)
288 {
289 	uint32_t i;
290 
291 	if (!(event_data && bytes > 0))
292 		return;
293 
294 	for (i = 0; i < bytes; i++) {
295 		if (i == 0)
296 			printf("\t0x%02x", event_data[i]);
297 		else if ((i % 8) == 0)
298 			printf("\n\t0x%02x", event_data[i]);
299 		else
300 			printf(" 0x%02x", event_data[i]);
301 	}
302 
303 	process_event_record(event_data, bytes);
304 }
305 
306 int get_hab_status(void)
307 {
308 	uint32_t index = 0; /* Loop index */
309 	uint8_t event_data[128]; /* Event data buffer */
310 	size_t bytes = sizeof(event_data); /* Event size in bytes */
311 	enum hab_config config = 0;
312 	enum hab_state state = 0;
313 	hab_rvt_report_event_t *hab_rvt_report_event;
314 	hab_rvt_report_status_t *hab_rvt_report_status;
315 
316 	hab_rvt_report_event = hab_rvt_report_event_p;
317 	hab_rvt_report_status = hab_rvt_report_status_p;
318 
319 	if (is_hab_enabled())
320 		puts("\nSecure boot enabled\n");
321 	else
322 		puts("\nSecure boot disabled\n");
323 
324 	/* Check HAB status */
325 	if (hab_rvt_report_status(&config, &state) != HAB_SUCCESS) {
326 		printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
327 		       config, state);
328 
329 		/* Display HAB Error events */
330 		while (hab_rvt_report_event(HAB_FAILURE, index, event_data,
331 					&bytes) == HAB_SUCCESS) {
332 			puts("\n");
333 			printf("--------- HAB Event %d -----------------\n",
334 			       index + 1);
335 			puts("event data:\n");
336 			display_event(event_data, bytes);
337 			puts("\n");
338 			bytes = sizeof(event_data);
339 			index++;
340 		}
341 	}
342 	/* Display message if no HAB events are found */
343 	else {
344 		printf("\nHAB Configuration: 0x%02x, HAB State: 0x%02x\n",
345 		       config, state);
346 		puts("No HAB Events Found!\n\n");
347 	}
348 	return 0;
349 }
350 
351 int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
352 {
353 	if ((argc != 1)) {
354 		cmd_usage(cmdtp);
355 		return 1;
356 	}
357 
358 	get_hab_status();
359 
360 	return 0;
361 }
362 
363 static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
364 				char * const argv[])
365 {
366 	ulong	addr, ivt_offset;
367 	int	rcode = 0;
368 
369 	if (argc < 3)
370 		return CMD_RET_USAGE;
371 
372 	addr = simple_strtoul(argv[1], NULL, 16);
373 	ivt_offset = simple_strtoul(argv[2], NULL, 16);
374 
375 	rcode = authenticate_image(addr, ivt_offset);
376 
377 	return rcode;
378 }
379 
380 U_BOOT_CMD(
381 		hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
382 		"display HAB status",
383 		""
384 	  );
385 
386 U_BOOT_CMD(
387 		hab_auth_img, 3, 0, do_authenticate_image,
388 		"authenticate image via HAB",
389 		"addr ivt_offset\n"
390 		"addr - image hex address\n"
391 		"ivt_offset - hex offset of IVT in the image"
392 	  );
393 
394 
395 #endif /* !defined(CONFIG_SPL_BUILD) */
396 
397 static bool is_hab_enabled(void)
398 {
399 	struct imx_sec_config_fuse_t *fuse =
400 		(struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
401 	uint32_t reg;
402 	int ret;
403 
404 	ret = fuse_read(fuse->bank, fuse->word, &reg);
405 	if (ret) {
406 		puts("\nSecure boot fuse read error\n");
407 		return ret;
408 	}
409 
410 	return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT;
411 }
412 
413 uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
414 {
415 	uint32_t load_addr = 0;
416 	size_t bytes;
417 	ptrdiff_t ivt_offset = 0;
418 	int result = 0;
419 	ulong start;
420 	hab_rvt_authenticate_image_t *hab_rvt_authenticate_image;
421 	hab_rvt_entry_t *hab_rvt_entry;
422 	hab_rvt_exit_t *hab_rvt_exit;
423 
424 	hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
425 	hab_rvt_entry = hab_rvt_entry_p;
426 	hab_rvt_exit = hab_rvt_exit_p;
427 
428 	if (is_hab_enabled()) {
429 		printf("\nAuthenticate image from DDR location 0x%x...\n",
430 		       ddr_start);
431 
432 		hab_caam_clock_enable(1);
433 
434 		if (hab_rvt_entry() == HAB_SUCCESS) {
435 			/* If not already aligned, Align to ALIGN_SIZE */
436 			ivt_offset = (image_size + ALIGN_SIZE - 1) &
437 					~(ALIGN_SIZE - 1);
438 
439 			start = ddr_start;
440 			bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
441 #ifdef DEBUG
442 			printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n",
443 			       ivt_offset, ddr_start + ivt_offset);
444 			puts("Dumping IVT\n");
445 			print_buffer(ddr_start + ivt_offset,
446 				     (void *)(ddr_start + ivt_offset),
447 				     4, 0x8, 0);
448 
449 			puts("Dumping CSF Header\n");
450 			print_buffer(ddr_start + ivt_offset+IVT_SIZE,
451 				     (void *)(ddr_start + ivt_offset+IVT_SIZE),
452 				     4, 0x10, 0);
453 
454 #if  !defined(CONFIG_SPL_BUILD)
455 			get_hab_status();
456 #endif
457 
458 			puts("\nCalling authenticate_image in ROM\n");
459 			printf("\tivt_offset = 0x%x\n", ivt_offset);
460 			printf("\tstart = 0x%08lx\n", start);
461 			printf("\tbytes = 0x%x\n", bytes);
462 #endif
463 			/*
464 			 * If the MMU is enabled, we have to notify the ROM
465 			 * code, or it won't flush the caches when needed.
466 			 * This is done, by setting the "pu_irom_mmu_enabled"
467 			 * word to 1. You can find its address by looking in
468 			 * the ROM map. This is critical for
469 			 * authenticate_image(). If MMU is enabled, without
470 			 * setting this bit, authentication will fail and may
471 			 * crash.
472 			 */
473 			/* Check MMU enabled */
474 			if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) {
475 				if (is_mx6dq()) {
476 					/*
477 					 * This won't work on Rev 1.0.0 of
478 					 * i.MX6Q/D, since their ROM doesn't
479 					 * do cache flushes. don't think any
480 					 * exist, so we ignore them.
481 					 */
482 					if (!is_mx6dqp())
483 						writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
484 				} else if (is_mx6sdl()) {
485 					writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
486 				} else if (is_mx6sl()) {
487 					writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
488 				}
489 			}
490 
491 			load_addr = (uint32_t)hab_rvt_authenticate_image(
492 					HAB_CID_UBOOT,
493 					ivt_offset, (void **)&start,
494 					(size_t *)&bytes, NULL);
495 			if (hab_rvt_exit() != HAB_SUCCESS) {
496 				puts("hab exit function fail\n");
497 				load_addr = 0;
498 			}
499 		} else {
500 			puts("hab entry function fail\n");
501 		}
502 
503 		hab_caam_clock_enable(0);
504 
505 #if !defined(CONFIG_SPL_BUILD)
506 		get_hab_status();
507 #endif
508 	} else {
509 		puts("hab fuse not enabled\n");
510 	}
511 
512 	if ((!is_hab_enabled()) || (load_addr != 0))
513 		result = 1;
514 
515 	return result;
516 }
517