2 * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
4 * SPDX-License-Identifier: GPL-2.0+
10 #include <asm/system.h>
11 #include <asm/arch/clock.h>
12 #include <asm/arch/sys_proto.h>
13 #include <asm/arch/hab.h>
15 HAB_FUNC(entry, hab_status_t)
16 HAB_FUNC(exit, hab_status_t)
17 HAB_FUNC5(authenticate_image, void *, uint8_t, size_t, void **, size_t *, hab_loader_callback_f_t)
18 HAB_FUNC2(report_status, hab_status_t, hab_config_t *, hab_state_t *)
19 HAB_FUNC4(report_event, hab_status_t, hab_status_t, uint32_t, uint8_t *, size_t *)
20 HAB_FUNC3(check_target, hab_status_t, uint8_t, const void *, size_t)
21 HAB_FUNC3(assert, hab_status_t, uint8_t, const void *, size_t)
28 struct mx53_boot_data *boot_data;
34 struct mx53_boot_data {
41 #define ALIGN_SIZE 0x400
42 #define CSF_PAD_SIZE 0x2000
45 * +------------+ 0x0 (DDR_UIMAGE_START) -
47 * +------------+ 0x40 |
54 * . | > Stuff to be authenticated ----+
62 * +------------+ Align to ALIGN_SIZE | |
64 * +------------+ + IVT_SIZE - |
66 * | CSF DATA | <---------------------------------------------------------+
72 * +------------+ + CSF_PAD_SIZE
75 static inline int read_fuse(unsigned bank, unsigned row)
77 struct iim_regs *iim_regs = (void *)IMX_IIM_BASE;
80 if (bank > ARRAY_SIZE(iim_regs->bank))
82 fuses = iim_regs->bank[bank].fuse_regs;
84 debug("Reading fuse bank %u row %u @ %p\n", bank, row, &fuses[row]);
85 return readl(&fuses[row]);
88 static bool is_hab_enabled(void)
94 debug("rvt_base=%p\n", hab_rvt_base());
95 debug("hab_rvt_entry=%p\n", hab_rvt_entry_p);
96 debug("hab_rvt_exit=%p\n", hab_rvt_exit_p);
97 debug("hab_rvt_check_target=%p\n", hab_rvt_check_target_p);
98 debug("hab_rvt_authenticate_image=%p\n", hab_rvt_authenticate_image_p);
99 debug("hab_rvt_report_event=%p\n", hab_rvt_report_event_p);
100 debug("hab_rvt_report_status=%p\n", hab_rvt_report_status_p);
101 debug("hab_rvt_assert=%p\n", hab_rvt_assert_p);
105 return read_fuse(0, 4) & (1 << 1);
108 static void mx53_hab_display_event(uint8_t *event_data, size_t bytes)
112 if (!(event_data && bytes > 0))
115 for (i = 0; i < bytes; i++) {
117 printf("\t0x%02x", event_data[i]);
118 else if ((i % 8) == 0)
119 printf("\n\t0x%02x", event_data[i]);
121 printf(" 0x%02x", event_data[i]);
125 static inline void mx53_hab_pr_fuse_val(unsigned bank, unsigned row)
127 printf(" %02x", read_fuse(bank, row));
130 static inline void mx53_hab_dump_srk_hash(void)
134 printf("SRK hash:\n\t");
135 mx53_hab_pr_fuse_val(1, 1);
136 for (i = 1; i <= 31; i++) {
139 mx53_hab_pr_fuse_val(3, i);
144 int get_hab_status(void)
146 static uint32_t last_hab_event __attribute__((section(".data")));
147 uint32_t index = last_hab_event; /* Loop index */
148 uint8_t event_data[128]; /* Event data buffer */
149 size_t bytes = sizeof(event_data); /* Event size in bytes */
150 enum hab_config config;
151 enum hab_state state;
153 int hab_debug = getenv_yesno("hab_debug") == 1;
156 if (is_hab_enabled()) {
157 printf("Secure boot enabled\n\t");
159 printf("Secure boot disabled\n");
161 mx53_hab_dump_srk_hash();
164 /* Check HAB status */
165 config = state = 0; /* ROM code assumes short enums! */
166 ret = hab_rvt_report_status(&config, &state);
167 if (hab_debug || ret != HAB_SUCCESS)
168 printf("HAB Configuration: 0x%02x, HAB State: 0x%02x\n",
170 if (ret != HAB_SUCCESS) {
171 /* Display HAB Error events */
172 while (hab_rvt_report_event(HAB_STS_ANY, index, event_data,
173 &bytes) == HAB_SUCCESS) {
175 printf("--------- HAB Event %d -----------------\n",
177 puts("event data:\n");
178 mx53_hab_display_event(event_data, bytes);
180 bytes = sizeof(event_data);
183 ret = index - last_hab_event;
184 last_hab_event = index;
186 /* Display message if no HAB events are found */
188 puts("No HAB Events Found!\n");
194 static inline hab_status_t hab_init(void)
198 ret = hab_rvt_entry();
199 debug("hab_rvt_entry() returned %02x\n", ret);
200 if (ret != HAB_SUCCESS) {
201 printf("hab entry function failed: %02x\n", ret);
207 static inline hab_status_t hab_exit(void)
211 ret = hab_rvt_exit();
212 if (ret != HAB_SUCCESS)
213 printf("hab exit function failed: %02x\n", ret);
218 static hab_status_t hab_check_target(hab_target_t type, uint32_t addr, size_t len)
223 if (ret != HAB_SUCCESS)
226 ret = hab_rvt_check_target(type, (void *)addr, len);
227 if (ret != HAB_SUCCESS) {
228 printf("check_target(0x%08x, 0x%08x) failed: %d\n",
234 if (ret == HAB_SUCCESS && get_hab_status() > 0) {
240 static hab_status_t hab_assert(uint32_t type, uint32_t addr, size_t len)
245 if (ret != HAB_SUCCESS)
248 ret = hab_rvt_assert(type, (void *)addr, len);
249 if (ret != HAB_SUCCESS) {
250 printf("assert(0x%08x, 0x%08x) failed: %d\n",
256 if (ret == HAB_SUCCESS && get_hab_status() > 0) {
262 static int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc,
266 return CMD_RET_USAGE;
270 return CMD_RET_SUCCESS;
273 static int do_hab_check_target(cmd_tbl_t *cmdtp, int flag, int argc,
276 hab_target_t type = HAB_TGT_MEMORY;
281 return CMD_RET_USAGE;
283 addr = simple_strtoul(argv[1], NULL, 16);
284 len = simple_strtoul(argv[2], NULL, 16);
286 switch (argv[3][0]) {
289 type = HAB_TGT_PERIPHERAL;
293 type = HAB_TGT_MEMORY;
296 printf("Invalid type '%s'\n", argv[3]);
297 return CMD_RET_USAGE;
300 if (hab_check_target(type, addr, len) != HAB_SUCCESS)
301 return CMD_RET_FAILURE;
303 return CMD_RET_SUCCESS;
306 static int do_hab_assert(cmd_tbl_t *cmdtp, int flag, int argc,
314 return CMD_RET_USAGE;
316 addr = simple_strtoul(argv[1], NULL, 16);
317 len = simple_strtoul(argv[2], NULL, 16);
319 type = simple_strtoul(argv[3], NULL, 16);
322 if (hab_assert(type, addr, len) != HAB_SUCCESS)
323 return CMD_RET_FAILURE;
325 return CMD_RET_SUCCESS;
329 hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
330 "display HAB status",
335 hab_check_target, 4, 0, do_hab_check_target,
336 "verify an address range via HAB",
338 "\t\taddr -\taddress to verify\n"
339 "\t\tlen -\tlength of addr range to verify\n"
343 hab_assert, 4, 0, do_hab_assert,
344 "Test an assertion against the HAB audit log",
346 "\t\taddr -\taddress to verify\n"
347 "\t\tlen -\tlength of addr range to verify\n"