]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - arch/arm/mach-imx/hab.c
arm: imx: hab: Verify IVT self matches calculated address
[people/ms/u-boot.git] / arch / arm / mach-imx / hab.c
index 02c7ae4e7251d017ca2b0f88d1e2b59e52c3c697..39f8f2de59107ed70ed1fe2d0cf1f3f06732e2b1 100644 (file)
@@ -70,9 +70,7 @@
        ((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
        (is_soc_type(MXC_SOC_MX7ULP) ? 0x80000000 :     \
         (is_soc_type(MXC_SOC_MX7) ? 0x2000000 : 0x2))
 
-/*
- * +------------+  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
- */
-
 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,
+              ivt_hdr->magic, ivt_hdr->length, ivt_hdr->version);
+
+       return 1;
+}
+
+static int verify_ivt_header(struct ivt_header *ivt_hdr)
+{
+       int result = 0;
+
+       if (ivt_hdr->magic != IVT_HEADER_MAGIC)
+               result = ivt_header_error("bad magic", ivt_hdr);
+
+       if (be16_to_cpu(ivt_hdr->length) != IVT_TOTAL_LENGTH)
+               result = ivt_header_error("bad length", ivt_hdr);
+
+       if (ivt_hdr->version != IVT_HEADER_V1 &&
+           ivt_hdr->version != IVT_HEADER_V2)
+               result = ivt_header_error("bad version", ivt_hdr);
+
+       return result;
+}
+
 #if !defined(CONFIG_SPL_BUILD)
 
 #define MAX_RECORD_BYTES     (8*1024) /* 4 kbytes */
@@ -363,16 +355,21 @@ int do_hab_status(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 static int do_authenticate_image(cmd_tbl_t *cmdtp, int flag, int argc,
                                char * const argv[])
 {
-       ulong   addr, ivt_offset;
+       ulong   addr, length, ivt_offset;
        int     rcode = 0;
 
-       if (argc < 3)
+       if (argc < 4)
                return CMD_RET_USAGE;
 
        addr = simple_strtoul(argv[1], NULL, 16);
-       ivt_offset = simple_strtoul(argv[2], NULL, 16);
+       length = simple_strtoul(argv[2], NULL, 16);
+       ivt_offset = simple_strtoul(argv[3], NULL, 16);
 
-       rcode = authenticate_image(addr, ivt_offset);
+       rcode = authenticate_image(addr, length, ivt_offset);
+       if (rcode == 0)
+               rcode = CMD_RET_SUCCESS;
+       else
+               rcode = CMD_RET_FAILURE;
 
        return rcode;
 }
@@ -384,10 +381,11 @@ U_BOOT_CMD(
          );
 
 U_BOOT_CMD(
-               hab_auth_img, 3, 0, do_authenticate_image,
+               hab_auth_img, 4, 0, do_authenticate_image,
                "authenticate image via HAB",
-               "addr ivt_offset\n"
+               "addr length ivt_offset\n"
                "addr - image hex address\n"
+               "length - image hex length\n"
                "ivt_offset - hex offset of IVT in the image"
          );
 
@@ -410,107 +408,120 @@ static bool is_hab_enabled(void)
        return (reg & IS_HAB_ENABLED_BIT) == IS_HAB_ENABLED_BIT;
 }
 
-uint32_t authenticate_image(uint32_t ddr_start, uint32_t image_size)
+int authenticate_image(uint32_t ddr_start, uint32_t image_size,
+                      uint32_t ivt_offset)
 {
        uint32_t load_addr = 0;
        size_t bytes;
-       ptrdiff_t ivt_offset = 0;
-       int result = 0;
+       uint32_t ivt_addr = 0;
+       int result = 1;
        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;
+       struct ivt *ivt;
+       struct ivt_header *ivt_hdr;
 
        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);
+       if (!is_hab_enabled()) {
+               puts("hab fuse not enabled\n");
+               return result;
+       }
+
+       printf("\nAuthenticate image from DDR location 0x%x...\n",
+              ddr_start);
 
-               hab_caam_clock_enable(1);
+       hab_caam_clock_enable(1);
+
+       if (hab_rvt_entry() != HAB_SUCCESS) {
+               puts("hab entry function fail\n");
+               goto hab_caam_clock_disable;
+       }
 
-               if (hab_rvt_entry() == HAB_SUCCESS) {
-                       /* If not already aligned, Align to ALIGN_SIZE */
-                       ivt_offset = (image_size + ALIGN_SIZE - 1) &
-                                       ~(ALIGN_SIZE - 1);
+       /* Calculate IVT address header */
+       ivt_addr = ddr_start + ivt_offset;
+       ivt = (struct ivt *)ivt_addr;
+       ivt_hdr = &ivt->hdr;
 
-                       start = ddr_start;
-                       bytes = ivt_offset + IVT_SIZE + CSF_PAD_SIZE;
+       /* Verify IVT header bugging out on error */
+       if (verify_ivt_header(ivt_hdr))
+               goto hab_caam_clock_disable;
+
+       /* 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;
+       }
+
+       start = ddr_start;
+       bytes = image_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);
+       printf("\nivt_offset = 0x%x, ivt addr = 0x%x\n", ivt_offset, ivt_addr);
+       puts("Dumping IVT\n");
+       print_buffer(ivt_addr, (void *)(ivt_addr), 4, 0x8, 0);
+
+       puts("Dumping CSF Header\n");
+       print_buffer(ivt_addr + IVT_SIZE, (void *)(ivt_addr + IVT_SIZE), 4,
+                    0x10, 0);
 
 #if  !defined(CONFIG_SPL_BUILD)
-                       get_hab_status();
+       get_hab_status();
 #endif
 
-                       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);
+       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 (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) {
+               if (is_mx6dq()) {
                        /*
-                        * 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.
+                        * 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.
                         */
-                       /* Check MMU enabled */
-                       if (is_soc_type(MXC_SOC_MX6) && get_cr() & CR_M) {
-                               if (is_mx6dq()) {
-                                       /*
-                                        * 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.
-                                        */
-                                       if (!is_mx6dqp())
-                                               writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
-                               } else if (is_mx6sdl()) {
-                                       writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
-                               } else if (is_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");
+                       if (!is_mx6dqp())
+                               writel(1, MX6DQ_PU_IROM_MMU_EN_VAR);
+               } else if (is_mx6sdl()) {
+                       writel(1, MX6DLS_PU_IROM_MMU_EN_VAR);
+               } else if (is_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;
+       }
 
-               hab_caam_clock_enable(0);
+hab_caam_clock_disable:
+       hab_caam_clock_enable(0);
 
 #if !defined(CONFIG_SPL_BUILD)
-               get_hab_status();
+       get_hab_status();
 #endif
-       } else {
-               puts("hab fuse not enabled\n");
-       }
-
-       if ((!is_hab_enabled()) || (load_addr != 0))
-               result = 1;
+       if (load_addr != 0)
+               result = 0;
 
        return result;
 }