|
@@ -1,12 +1,14 @@
|
|
|
/*
|
|
|
- * Copyright (C) 2010-2013 Freescale Semiconductor, Inc.
|
|
|
+ * Copyright (C) 2010-2014 Freescale Semiconductor, Inc.
|
|
|
*
|
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
|
*/
|
|
|
|
|
|
#include <common.h>
|
|
|
#include <asm/io.h>
|
|
|
+#include <asm/system.h>
|
|
|
#include <asm/arch/hab.h>
|
|
|
+#include <asm/arch/clock.h>
|
|
|
#include <asm/arch/sys_proto.h>
|
|
|
|
|
|
/* -------- start of HAB API updates ------------*/
|
|
@@ -71,6 +73,44 @@
|
|
|
((hab_rvt_exit_t *)HAB_RVT_EXIT) \
|
|
|
)
|
|
|
|
|
|
+#define IVT_SIZE 0x20
|
|
|
+#define ALIGN_SIZE 0x1000
|
|
|
+#define CSF_PAD_SIZE 0x2000
|
|
|
+#define MX6DQ_PU_IROM_MMU_EN_VAR 0x009024a8
|
|
|
+#define MX6DLS_PU_IROM_MMU_EN_VAR 0x00901dd0
|
|
|
+#define MX6SL_PU_IROM_MMU_EN_VAR 0x00900a18
|
|
|
+
|
|
|
+/*
|
|
|
+ * +------------+ 0x0 (DDR_UIMAGE_START) -
|
|
|
+ * | Header | |
|
|
|
+ * +------------+ 0x40 |
|
|
|
+ * | | |
|
|
|
+ * | | |
|
|
|
+ * | | |
|
|
|
+ * | | |
|
|
|
+ * | Image Data | |
|
|
|
+ * . | |
|
|
|
+ * . | > Stuff to be authenticated ----+
|
|
|
+ * . | | |
|
|
|
+ * | | | |
|
|
|
+ * | | | |
|
|
|
+ * +------------+ | |
|
|
|
+ * | | | |
|
|
|
+ * | Fill Data | | |
|
|
|
+ * | | | |
|
|
|
+ * +------------+ Align to ALIGN_SIZE | |
|
|
|
+ * | IVT | | |
|
|
|
+ * +------------+ + IVT_SIZE - |
|
|
|
+ * | | |
|
|
|
+ * | CSF DATA | <---------------------------------------------------------+
|
|
|
+ * | |
|
|
|
+ * +------------+
|
|
|
+ * | |
|
|
|
+ * | Fill Data |
|
|
|
+ * | |
|
|
|
+ * +------------+ + CSF_PAD_SIZE
|
|
|
+ */
|
|
|
+
|
|
|
bool is_hab_enabled(void)
|
|
|
{
|
|
|
struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
|
|
@@ -144,6 +184,108 @@ int get_hab_status(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
|
|
|
+{
|
|
|
+ uint32_t load_addr = 0;
|
|
|
+ size_t bytes;
|
|
|
+ ptrdiff_t ivt_offset = 0;
|
|
|
+ int result = 0;
|
|
|
+ ulong start;
|
|
|
+ hab_rvt_authenticate_image_t *hab_rvt_authenticate_image;
|
|
|
+ hab_rvt_entry_t *hab_rvt_entry;
|
|
|
+ hab_rvt_exit_t *hab_rvt_exit;
|
|
|
+
|
|
|
+ hab_rvt_authenticate_image = hab_rvt_authenticate_image_p;
|
|
|
+ hab_rvt_entry = hab_rvt_entry_p;
|
|
|
+ hab_rvt_exit = hab_rvt_exit_p;
|
|
|
+
|
|
|
+ if (is_hab_enabled()) {
|
|
|
+ printf("\nAuthenticate image from DDR location 0x%x...\n",
|
|
|
+ ddr_start);
|
|
|
+
|
|
|
+ hab_caam_clock_enable(1);
|
|
|
+
|
|
|
+ if (hab_rvt_entry() == HAB_SUCCESS) {
|
|
|
+ /* If not already aligned, Align to ALIGN_SIZE */
|
|
|
+ ivt_offset = (image_size + ALIGN_SIZE - 1) &
|
|
|
+ ~(ALIGN_SIZE - 1);
|
|
|
+
|
|
|
+ start = ddr_start;
|
|
|
+ bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
|
|
|
+#ifdef DEBUG
|
|
|
+ printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n",
|
|
|
+ ivt_offset, ddr_start + ivt_offset);
|
|
|
+ puts("Dumping IVT\n");
|
|
|
+ print_buffer(ddr_start + ivt_offset,
|
|
|
+ (void *)(ddr_start + ivt_offset),
|
|
|
+ 4, 0x8, 0);
|
|
|
+
|
|
|
+ puts("Dumping CSF Header\n");
|
|
|
+ print_buffer(ddr_start + ivt_offset+IVT_SIZE,
|
|
|
+ (void *)(ddr_start + ivt_offset+IVT_SIZE),
|
|
|
+ 4, 0x10, 0);
|
|
|
+
|
|
|
+ get_hab_status();
|
|
|
+
|
|
|
+ puts("\nCalling authenticate_image in ROM\n");
|
|
|
+ printf("\tivt_offset = 0x%x\n", ivt_offset);
|
|
|
+ printf("\tstart = 0x%08lx\n", start);
|
|
|
+ printf("\tbytes = 0x%x\n", bytes);
|
|
|
+#endif
|
|
|
+ /*
|
|
|
+ * If the MMU is enabled, we have to notify the ROM
|
|
|
+ * code, or it won't flush the caches when needed.
|
|
|
+ * This is done, by setting the "pu_irom_mmu_enabled"
|
|
|
+ * word to 1. You can find its address by looking in
|
|
|
+ * the ROM map. This is critical for
|
|
|
+ * authenticate_image(). If MMU is enabled, without
|
|
|
+ * setting this bit, authentication will fail and may
|
|
|
+ * crash.
|
|
|
+ */
|
|
|
+ /* Check MMU enabled */
|
|
|
+ if (get_cr() & CR_M) {
|
|
|
+ if (is_cpu_type(MXC_CPU_MX6Q) ||
|
|
|
+ is_cpu_type(MXC_CPU_MX6D)) {
|
|
|
+ /*
|
|
|
+ * This won't work on Rev 1.0.0 of
|
|
|
+ * i.MX6Q/D, since their ROM doesn't
|
|
|
+ * do cache flushes. don't think any
|
|
|
+ * exist, so we ignore them.
|
|
|
+ */
|
|
|
+ writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
|
|
|
+ } else if (is_cpu_type(MXC_CPU_MX6DL) ||
|
|
|
+ is_cpu_type(MXC_CPU_MX6SOLO)) {
|
|
|
+ writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
|
|
|
+ } else if (is_cpu_type(MXC_CPU_MX6SL)) {
|
|
|
+ writel(1, MX6SL_PU_IROM_MMU_EN_VAR);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ load_addr = (uint32_t)hab_rvt_authenticate_image(
|
|
|
+ HAB_CID_UBOOT,
|
|
|
+ ivt_offset, (void **)&start,
|
|
|
+ (size_t *)&bytes, NULL);
|
|
|
+ if (hab_rvt_exit() != HAB_SUCCESS) {
|
|
|
+ puts("hab exit function fail\n");
|
|
|
+ load_addr = 0;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ puts("hab entry function fail\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ hab_caam_clock_enable(0);
|
|
|
+
|
|
|
+ get_hab_status();
|
|
|
+ } else {
|
|
|
+ puts("hab fuse not enabled\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((!is_hab_enabled()) || (load_addr != 0))
|
|
|
+ result = 1;
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
|
{
|
|
|
if ((argc != 1)) {
|
|
@@ -156,8 +298,33 @@ int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
|
+ char * const argv[])
|
|
|
+{
|
|
|
+ ulong addr, ivt_offset;
|
|
|
+ int rcode = 0;
|
|
|
+
|
|
|
+ if (argc < 3)
|
|
|
+ return CMD_RET_USAGE;
|
|
|
+
|
|
|
+ addr = simple_strtoul(argv[1], NULL, 16);
|
|
|
+ ivt_offset = simple_strtoul(argv[2], NULL, 16);
|
|
|
+
|
|
|
+ rcode = authenticate_image(addr, ivt_offset);
|
|
|
+
|
|
|
+ return rcode;
|
|
|
+}
|
|
|
+
|
|
|
U_BOOT_CMD(
|
|
|
hab_status, CONFIG_SYS_MAXARGS, 1, do_hab_status,
|
|
|
"display HAB status",
|
|
|
""
|
|
|
);
|
|
|
+
|
|
|
+U_BOOT_CMD(
|
|
|
+ hab_auth_img, 3, 0, do_authenticate_image,
|
|
|
+ "authenticate image via HAB",
|
|
|
+ "addr ivt_offset\n"
|
|
|
+ "addr - image hex address\n"
|
|
|
+ "ivt_offset - hex offset of IVT in the image"
|
|
|
+ );
|