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, ®);
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