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