#include <asm/arch/sys_proto.h>
#include <asm/mach-imx/hab.h>
-/* -------- start of HAB API updates ------------*/
-
-#define hab_rvt_report_event_p \
-( \
- (is_mx6dqp()) ? \
- ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \
- (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \
- ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \
- (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \
- ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT_NEW) : \
- ((hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT) \
-)
-
-#define hab_rvt_report_status_p \
-( \
- (is_mx6dqp()) ? \
- ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\
- (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \
- ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\
- (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \
- ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS_NEW) :\
- ((hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS) \
-)
-
-#define hab_rvt_authenticate_image_p \
-( \
- (is_mx6dqp()) ? \
- ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \
- (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \
- ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \
- (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \
- ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE_NEW) : \
- ((hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE) \
-)
-
-#define hab_rvt_entry_p \
-( \
- (is_mx6dqp()) ? \
- ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \
- (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \
- ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \
- (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \
- ((hab_rvt_entry_t *)HAB_RVT_ENTRY_NEW) : \
- ((hab_rvt_entry_t *)HAB_RVT_ENTRY) \
-)
-
-#define hab_rvt_exit_p \
-( \
- (is_mx6dqp()) ? \
- ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \
- (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \
- ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \
- (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \
- ((hab_rvt_exit_t *)HAB_RVT_EXIT_NEW) : \
- ((hab_rvt_exit_t *)HAB_RVT_EXIT) \
-)
-
-static inline enum hab_status hab_rvt_check_target_new(enum hab_target target,
- const void *start,
- size_t bytes)
-{
- return HAB_SUCCESS;
-}
-
-#define hab_rvt_check_target_p \
-( \
- (is_mx6dqp()) ? \
- ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \
- (is_mx6dq() && (soc_rev() >= CHIP_REV_1_5)) ? \
- ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \
- (is_mx6sdl() && (soc_rev() >= CHIP_REV_1_2)) ? \
- ((hab_rvt_check_target_t *)hab_rvt_check_target_new) : \
- ((hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET) \
-)
-
#define ALIGN_SIZE 0x1000
#define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8
#define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0
(is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 : \
(is_soc_type(MXC_SOC_MX7) ? 0x2000000 : 0x2))
-static bool is_hab_enabled(void);
-
static int ivt_header_error(const char *err_str, struct ivt_header *ivt_hdr)
{
printf("%s magic=0x%x length=0x%02x version=0x%x\n", err_str,
hab_rvt_report_event_t *hab_rvt_report_event;
hab_rvt_report_status_t *hab_rvt_report_status;
- hab_rvt_report_event = hab_rvt_report_event_p;
- hab_rvt_report_status = hab_rvt_report_status_p;
+ hab_rvt_report_event = (hab_rvt_report_event_t *)HAB_RVT_REPORT_EVENT;
+ hab_rvt_report_status =
+ (hab_rvt_report_status_t *)HAB_RVT_REPORT_STATUS;
- if (is_hab_enabled())
+ if (imx_hab_is_enabled())
puts("\nSecure boot enabled\n");
else
puts("\nSecure boot disabled\n");
return rcode;
}
+static int do_hab_failsafe(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ hab_rvt_failsafe_t *hab_rvt_failsafe;
+
+ if (argc != 1) {
+ cmd_usage(cmdtp);
+ return 1;
+ }
+
+ hab_rvt_failsafe = (hab_rvt_failsafe_t *)HAB_RVT_FAILSAFE;
+ hab_rvt_failsafe();
+
+ return 0;
+}
+
+static int do_authenticate_image_or_failover(cmd_tbl_t *cmdtp, int flag,
+ int argc, char * const argv[])
+{
+ int ret = CMD_RET_FAILURE;
+
+ if (argc != 4) {
+ ret = CMD_RET_USAGE;
+ goto error;
+ }
+
+ if (!imx_hab_is_enabled()) {
+ printf("error: secure boot disabled\n");
+ goto error;
+ }
+
+ if (do_authenticate_image(NULL, flag, argc, argv) != CMD_RET_SUCCESS) {
+ fprintf(stderr, "authentication fail -> %s %s %s %s\n",
+ argv[0], argv[1], argv[2], argv[3]);
+ do_hab_failsafe(0, 0, 1, NULL);
+ };
+ ret = CMD_RET_SUCCESS;
+error:
+ return ret;
+}
+
U_BOOT_CMD(
hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
"display HAB status",
"ivt_offset - hex offset of IVT in the image"
);
+U_BOOT_CMD(
+ hab_failsafe, CONFIG_SYS_MAXARGS, 1, do_hab_failsafe,
+ "run BootROM failsafe routine",
+ ""
+ );
+
+U_BOOT_CMD(
+ hab_auth_img_or_fail, 4, 0,
+ do_authenticate_image_or_failover,
+ "authenticate image via HAB on failure drop to USB BootROM mode",
+ "addr length ivt_offset\n"
+ "addr - image hex address\n"
+ "length - image hex length\n"
+ "ivt_offset - hex offset of IVT in the image"
+ );
#endif /* !defined(CONFIG_SPL_BUILD) */
-static bool is_hab_enabled(void)
+/* Get CSF Header length */
+static int get_hab_hdr_len(struct hab_hdr *hdr)
+{
+ return (size_t)((hdr->len[0] << 8) + (hdr->len[1]));
+}
+
+/* Check whether addr lies between start and
+ * end and is within the length of the image
+ */
+static int chk_bounds(u8 *addr, size_t bytes, u8 *start, u8 *end)
+{
+ size_t csf_size = (size_t)((end + 1) - addr);
+
+ return (addr && (addr >= start) && (addr <= end) &&
+ (csf_size >= bytes));
+}
+
+/* Get Length of each command in CSF */
+static int get_csf_cmd_hdr_len(u8 *csf_hdr)
+{
+ if (*csf_hdr == HAB_CMD_HDR)
+ return sizeof(struct hab_hdr);
+
+ return get_hab_hdr_len((struct hab_hdr *)csf_hdr);
+}
+
+/* Check if CSF is valid */
+static bool csf_is_valid(struct ivt *ivt, ulong start_addr, size_t bytes)
+{
+ u8 *start = (u8 *)start_addr;
+ u8 *csf_hdr;
+ u8 *end;
+
+ size_t csf_hdr_len;
+ size_t cmd_hdr_len;
+ size_t offset = 0;
+
+ if (bytes != 0)
+ end = start + bytes - 1;
+ else
+ end = start;
+
+ /* Verify if CSF pointer content is zero */
+ if (!ivt->csf) {
+ puts("Error: CSF pointer is NULL\n");
+ return false;
+ }
+
+ csf_hdr = (u8 *)ivt->csf;
+
+ /* Verify if CSF Header exist */
+ if (*csf_hdr != HAB_CMD_HDR) {
+ puts("Error: CSF header command not found\n");
+ return false;
+ }
+
+ csf_hdr_len = get_hab_hdr_len((struct hab_hdr *)csf_hdr);
+
+ /* Check if the CSF lies within the image bounds */
+ if (!chk_bounds(csf_hdr, csf_hdr_len, start, end)) {
+ puts("Error: CSF lies outside the image bounds\n");
+ return false;
+ }
+
+ do {
+ struct hab_hdr *cmd;
+
+ cmd = (struct hab_hdr *)&csf_hdr[offset];
+
+ switch (cmd->tag) {
+ case (HAB_CMD_WRT_DAT):
+ puts("Error: Deprecated write command found\n");
+ return false;
+ case (HAB_CMD_CHK_DAT):
+ puts("Error: Deprecated check command found\n");
+ return false;
+ case (HAB_CMD_SET):
+ if (cmd->par == HAB_PAR_MID) {
+ puts("Error: Deprecated Set MID command found\n");
+ return false;
+ }
+ default:
+ break;
+ }
+
+ cmd_hdr_len = get_csf_cmd_hdr_len(&csf_hdr[offset]);
+ if (!cmd_hdr_len) {
+ puts("Error: Invalid command length\n");
+ return false;
+ }
+ offset += cmd_hdr_len;
+
+ } while (offset < csf_hdr_len);
+
+ return true;
+}
+
+bool imx_hab_is_enabled(void)
{
struct imx_sec_config_fuse_t *fuse =
(struct imx_sec_config_fuse_t *)&imx_sec_config_fuse;
struct ivt_header *ivt_hdr;
enum hab_status status;
- hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
- hab_rvt_entry = hab_rvt_entry_p;
- hab_rvt_exit = hab_rvt_exit_p;
- hab_rvt_check_target = hab_rvt_check_target_p;
+ hab_rvt_authenticate_image =
+ (hab_rvt_authenticate_image_t *)HAB_RVT_AUTHENTICATE_IMAGE;
+ hab_rvt_entry = (hab_rvt_entry_t *)HAB_RVT_ENTRY;
+ hab_rvt_exit = (hab_rvt_exit_t *)HAB_RVT_EXIT;
+ hab_rvt_check_target = (hab_rvt_check_target_t *)HAB_RVT_CHECK_TARGET;
- if (!is_hab_enabled()) {
+ if (!imx_hab_is_enabled()) {
puts("hab fuse not enabled\n");
- return result;
+ return 0;
}
printf("\nAuthenticate image from DDR location 0x%x...\n",
/* Verify IVT header bugging out on error */
if (verify_ivt_header(ivt_hdr))
- goto hab_caam_clock_disable;
+ goto hab_authentication_exit;
/* Verify IVT body */
if (ivt->self != ivt_addr) {
printf("ivt->self 0x%08x pointer is 0x%08x\n",
ivt->self, ivt_addr);
- goto hab_caam_clock_disable;
+ goto hab_authentication_exit;
+ }
+
+ /* Verify if IVT DCD pointer is NULL */
+ if (ivt->dcd) {
+ puts("Error: DCD pointer must be NULL\n");
+ goto hab_authentication_exit;
}
start = ddr_start;
bytes = image_size;
+ /* Verify CSF */
+ if (!csf_is_valid(ivt, start, bytes))
+ goto hab_authentication_exit;
+
if (hab_rvt_entry() != HAB_SUCCESS) {
puts("hab entry function fail\n");
goto hab_exit_failure_print_status;
get_hab_status();
#endif
-hab_caam_clock_disable:
- hab_caam_clock_enable(0);
+hab_authentication_exit:
if (load_addr != 0)
result = 0;