imx: hab: Simplify the mechanism
authorMarek Vasut <marex@denx.de>
Sun, 28 May 2023 21:00:30 +0000 (23:00 +0200)
committerTom Rini <trini@konsulko.com>
Sat, 24 Jun 2023 17:47:02 +0000 (13:47 -0400)
The current mechanism is unnecessarily complex. Simplify the whole mechanism
such that the entire fitImage is signed, IVT is placed at the end, followed
by CSF, and this entire bundle is also authenticated. This makes the signing
scripting far simpler.

Signed-off-by: Marek Vasut <marex@denx.de>
arch/arm/dts/imx8mm-u-boot.dtsi
arch/arm/dts/imx8mn-u-boot.dtsi
arch/arm/dts/imx8mp-u-boot.dtsi
arch/arm/dts/imx8mq-u-boot.dtsi
arch/arm/mach-imx/spl.c
common/spl/spl_fit.c
doc/imx/habv4/csf_examples/mx8m/csf.sh
doc/imx/habv4/csf_examples/mx8m/csf_fit.txt
doc/imx/habv4/guides/mx8m_spl_secure_boot.txt
include/spl.h

index 7fd5a05..035282b 100644 (file)
@@ -81,7 +81,9 @@
 
                fit {
                        description = "Configuration to load ATF before U-Boot";
+#ifndef CONFIG_IMX_HAB
                        fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+#endif
                        fit,fdt-list = "of-list";
                        #address-cells = <1>;
 
index cef20da..5046b38 100644 (file)
 
                fit {
                        description = "Configuration to load ATF before U-Boot";
+#ifndef CONFIG_IMX_HAB
                        fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+#endif
                        fit,fdt-list = "of-list";
                        #address-cells = <1>;
 
index 18d1728..68cd0e1 100644 (file)
 
                fit {
                        description = "Configuration to load ATF before U-Boot";
+#ifndef CONFIG_IMX_HAB
                        fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+#endif
                        fit,fdt-list = "of-list";
                        #address-cells = <1>;
 
index b3fef86..90b2274 100644 (file)
@@ -97,7 +97,9 @@
 
                fit {
                        description = "Configuration to load ATF before U-Boot";
+#ifndef CONFIG_IMX_HAB
                        fit,external-offset = <CONFIG_FIT_EXTERNAL_OFFSET>;
+#endif
                        #address-cells = <1>;
 
                        images {
index cb9801b..6c13b00 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/mach-imx/boot_mode.h>
 #include <g_dnl.h>
 #include <linux/libfdt.h>
+#include <memalign.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -315,47 +316,21 @@ ulong board_spl_fit_size_align(ulong size)
        size = ALIGN(size, 0x1000);
        size += CONFIG_CSF_SIZE;
 
-       return size;
-}
+       if (size > CONFIG_SYS_BOOTM_LEN)
+               panic("spl: ERROR: image too big\n");
 
-void board_spl_fit_post_load(const void *fit)
-{
-       u32 offset = ALIGN(fdt_totalsize(fit), 0x1000);
-
-       if (imx_hab_authenticate_image((uintptr_t)fit,
-                                      offset + IVT_SIZE + CSF_PAD_SIZE,
-                                      offset)) {
-               panic("spl: ERROR:  image authentication unsuccessful\n");
-       }
+       return size;
 }
 #endif
 
 void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
 {
-       int align_len = ARCH_DMA_MINALIGN - 1;
-
-       /* Some devices like SDP, NOR, NAND, SPI are using bl_len =1, so their fit address
-        * is different with SD/MMC, this cause mismatch with signed address. Thus, adjust
-        * the bl_len to align with SD/MMC.
-        */
-       if (bl_len < 512)
-               bl_len = 512;
-
-       return  (void *)((CONFIG_TEXT_BASE - fit_size - bl_len -
-                       align_len) & ~align_len);
-}
+#if defined(CONFIG_SPL_LOAD_FIT_ADDRESS)
+       return (void *)CONFIG_SPL_LOAD_FIT_ADDRESS;
+#else
+       return (void *)(CONFIG_TEXT_BASE + CONFIG_SYS_BOOTM_LEN);
 #endif
-
-#if defined(CONFIG_MX6) && defined(CONFIG_SPL_OS_BOOT)
-int dram_init_banksize(void)
-{
-       gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
-       gd->bd->bi_dram[0].size = imx_ddr_size();
-
-       return 0;
 }
-#endif
-
 /*
  * read the address where the IVT header must sit
  * from IVT image header, loaded from SPL into
@@ -365,7 +340,6 @@ int dram_init_banksize(void)
 void *spl_load_simple_fit_fix_load(const void *fit)
 {
        struct ivt *ivt;
-       unsigned long new;
        unsigned long offset;
        unsigned long size;
        u8 *tmp = (u8 *)fit;
@@ -375,16 +349,23 @@ void *spl_load_simple_fit_fix_load(const void *fit)
        size = board_spl_fit_size_align(size);
        tmp += offset;
        ivt = (struct ivt *)tmp;
-       if (ivt->hdr.magic != IVT_HEADER_MAGIC) {
-               debug("no IVT header found\n");
-               return (void *)fit;
-       }
+
        debug("%s: ivt: %p offset: %lx size: %lx\n", __func__, ivt, offset, size);
        debug("%s: ivt self: %x\n", __func__, ivt->self);
-       new = ivt->self;
-       new -= offset;
-       debug("%s: new %lx\n", __func__, new);
-       memcpy((void *)new, fit, size);
 
-       return (void *)new;
+       if (imx_hab_authenticate_image((uintptr_t)fit, (uintptr_t)ivt, offset))
+               panic("spl: ERROR: image authentication unsuccessful\n");
+
+       return (void *)fit;
 }
+#endif /* CONFIG_IMX_HAB */
+
+#if defined(CONFIG_MX6) && defined(CONFIG_SPL_OS_BOOT)
+int dram_init_banksize(void)
+{
+       gd->bd->bi_dram[0].start = CFG_SYS_SDRAM_BASE;
+       gd->bd->bi_dram[0].size = imx_ddr_size();
+
+       return 0;
+}
+#endif
index c51482b..730639f 100644 (file)
@@ -27,10 +27,6 @@ struct spl_fit_info {
        int conf_node;          /* FDT offset to selected configuration node */
 };
 
-__weak void board_spl_fit_post_load(const void *fit)
-{
-}
-
 __weak ulong board_spl_fit_size_align(ulong size)
 {
        return size;
@@ -829,8 +825,5 @@ int spl_load_simple_fit(struct spl_image_info *spl_image,
 
        spl_image->flags |= SPL_FIT_FOUND;
 
-       if (IS_ENABLED(CONFIG_IMX_HAB))
-               board_spl_fit_post_load(ctx.fit);
-
        return 0;
 }
index 7a9a05e..5b383fa 100644 (file)
@@ -37,29 +37,11 @@ dd if=csf_spl.bin of=flash.bin bs=1 seek=${spl_dd_offset} conv=notrunc
 
 # 3) Sign u-boot.itb
 
-# fitImage tree
-fit_block_base=$(printf "0x%x" $(( $(sed -n "/CONFIG_TEXT_BASE=/ s@.*=@@p" .config) - $(sed -n "/CONFIG_FIT_EXTERNAL_OFFSET=/ s@.*=@@p" .config) - 0x200 - 0x40)) )
+# fitImage
+fit_block_base=$(printf "0x%x" $(sed -n "/CONFIG_SPL_LOAD_FIT_ADDRESS=/ s@.*=@@p" .config) )
 fit_block_offset=$(printf "0x%s" $(fdtget -t x u-boot.dtb /binman/imx-boot/uboot offset))
-fit_block_size=$(printf "0x%x" $(( ( ($(fdtdump u-boot.itb 2>/dev/null | sed -n "/^...totalsize:/ s@.*\(0x[0-9a-f]\+\).*@\1@p") + 0x1000 - 0x1 ) & ~(0x1000 - 0x1)) + 0x20 )) )
-sed -i "/Blocks = / s@.*@  Blocks = $fit_block_base $fit_block_offset $fit_block_size \"flash.bin\", \\\\@" csf_fit.tmp
-
-# U-Boot
-uboot_block_base=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/uboot load))
-uboot_block_offset=$(printf "0x%x" $(( $(printf "0x%s" $(fdtget -t x u-boot.itb /images/uboot data-position)) + ${fit_block_offset} )))
-uboot_block_size=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/uboot data-size))
-sed -i "/0xuuuu/ s@.*@           $uboot_block_base $uboot_block_offset $uboot_block_size \"flash.bin\", \\\\@" csf_fit.tmp
-
-# ATF
-atf_block_base=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/atf load))
-atf_block_offset=$(printf "0x%x" $(( $(printf "0x%s" $(fdtget -t x u-boot.itb /images/atf data-position)) + ${fit_block_offset} )))
-atf_block_size=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/atf data-size))
-sed -i "/0xaaaa/ s@.*@           $atf_block_base $atf_block_offset $atf_block_size \"flash.bin\", \\\\@" csf_fit.tmp
-
-# DTB
-dtb_block_base=$(printf "0x%x" $(( ${uboot_block_base} + ${uboot_block_size} )))
-dtb_block_offset=$(printf "0x%x" $(( $(printf "0x%s" $(fdtget -t x u-boot.itb /images/fdt-1 data-position)) + ${fit_block_offset} )))
-dtb_block_size=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/fdt-1 data-size))
-sed -i "/0xdddd/ s@.*@           $dtb_block_base $dtb_block_offset $dtb_block_size \"flash.bin\"@" csf_fit.tmp
+fit_block_size=$(printf "0x%x" $(( ( ( $(stat -tc %s u-boot.itb) + 0x1000 - 0x1 ) & ~(0x1000 - 0x1)) + 0x20 )) )
+sed -i "/Blocks = / s@.*@  Blocks = $fit_block_base $fit_block_offset $fit_block_size \"flash.bin\"@" csf_fit.tmp
 
 # IVT
 ivt_ptr_base=$(printf "%08x" ${fit_block_base} | sed "s@\(..\)\(..\)\(..\)\(..\)@0x\4\3\2\1@")
@@ -68,7 +50,7 @@ csf_block_base=$(printf "%08x" $(( ${fit_block_base} + ${fit_block_size} )) | se
 ivt_block_offset=$((${fit_block_offset} + ${fit_block_size} - 0x20))
 csf_block_offset=$((${ivt_block_offset} + 0x20))
 
-echo "0xd1002041 ${ivt_ptr_base} 0x00000000 0x00000000 0x00000000 ${ivt_block_base} ${csf_block_base} 0x00000000" | xxd -r -p > ivt.bin
+echo "0xd1002041 ${ivt_block_base} 0x00000000 0x00000000 0x00000000 ${ivt_block_base} ${csf_block_base} 0x00000000" | xxd -r -p > ivt.bin
 dd if=ivt.bin of=flash.bin bs=1 seek=${ivt_block_offset} conv=notrunc
 
 # Generate CSF blob
index cd1d407..bbb82f6 100644 (file)
 [Authenticate Data]
   Verification index = 2
   # FIXME:
-  # Line 1 -- fitImage tree
-  # Line 2 -- U-Boot u-boot-nodtb.bin blob
-  # Line 3 -- ATF BL31 blob
-  # Line 4 -- DT blob
-  Blocks = 0x401fcdc0 0x57c00 0xffff "flash.bin", \
-           0x40200000 0x62c00 0xuuuu "flash.bin", \
-          0x920000   0x00000 0xaaaa "flash.bin", \
-          0x40200000 0x00000 0xdddd "flash.bin"
+  # Line 1 -- fitImage
+  Blocks = 0x401fcdc0 0x57c00 0xffff "flash.bin"
index 3e3d384..e79726b 100644 (file)
@@ -79,18 +79,16 @@ code within it:
 
 The diagram below illustrate a signed U-Boot binary, DT blob and external
 ATF BL31 blob combined to form fitImage part of flash.bin container layout.
-The *load_address is derived from CONFIG_TEXT_BASE such that the U-Boot
-binary *start is placed exactly at CONFIG_SPL_TEXT_BASE in DRAM, however the
-SPL moves the fitImage tree further to location:
- *load_address = CONFIG_SPL_TEXT_BASE - CONFIG_FIT_EXTERNAL_OFFSET (=12kiB) -
-                 512 Byte sector - sizeof(mkimage header)
+The *load_address is CONFIG_SPL_LOAD_FIT_ADDRESS, the fitImage is loaded
+including all of its embedded data, authenticated using IVT+CSF concatenated
+at the end of the fitImage at offset aligned to 4 kiB. The fitImage with
+external data is not supported.
 
             ------- +-----------------------------+ <-- *load_address
                 ^   |                             |
                 |   |        fitImage tree        |
-                |   |    with external data at    |
-                |   |   offset 12 kiB from tree   |
-                |   |        (cca. 1 kiB)         |
+                |   |      with embedded data     |
+                |   |        (cca. 1 MiB)         |
          Signed |   |                             |
   .-----  Tree  |   +-----------------------------+
   |       Data  |   | Padding to next 4k aligned  |
@@ -101,34 +99,9 @@ SPL moves the fitImage tree further to location:
   |         ------- +-----------------------------+ <-- *csf
   |                 | Command Sequence File (CSF) |
   |                 |  for all signed entries in  |
-   >--------------->| the fitImage, tree and data |
-  |                 |        (cca 6-7 kiB)        |
-  |                 +-----------------------------+
-  |                 |  Padding to 12 kiB offset   |
-  |                 |     from *load_address      |
-  |         ------- +-----------------------------+ <-- *start
-  |             ^   |                             |
-  |      Signed |   |                             |
-  |---- Payload |   |  U-Boot external data blob  |
-  |       Data  |   |                             |
-  |             v   |                             |
-  |         ------- +-----------------------------+
-  |                 |     Padding to 4 Bytes      |
-  |         ------- +-----------------------------+
-  |             ^   |                             |
-  |      Signed |   |                             |
-  |---- Payload |   |    ATF external data blob   |
-  |       Data  |   |                             |
-  |             v   |                             |
-  |         ------- +-----------------------------+
-  |                 |     Padding to 4 Bytes      |
-  |         ------- +-----------------------------+
-  |             ^   |                             |
-  |      Signed |   |                             |
-  '---- Payload |   |    DTB external data blob   |
-          Data  |   |                             |
-                v   |                             |
-            ------- +-----------------------------+
+  '---------------->| the fitImage, tree and data |
+                    |        (cca 6-7 kiB)        |
+                    +-----------------------------+
 
 The diagram below illustrate a combined flash.bin container layout:
 
@@ -202,29 +175,11 @@ dd if=csf_spl.bin of=flash.bin bs=1 seek=${spl_dd_offset} conv=notrunc
 
 CSF "Blocks" line for csf_fit.txt can be generated as follows:
 ```
-# fitImage tree
-fit_block_base=$(printf "0x%x" $(( $(sed -n "/CONFIG_TEXT_BASE=/ s@.*=@@p" .config) - $(sed -n "/CONFIG_FIT_EXTERNAL_OFFSET=/ s@.*=@@p" .config) - 0x200 - 0x40)) )
+# fitImage
+fit_block_base=$(printf "0x%x" $(sed -n "/CONFIG_SPL_LOAD_FIT_ADDRESS=/ s@.*=@@p" .config) )
 fit_block_offset=$(printf "0x%s" $(fdtget -t x u-boot.dtb /binman/imx-boot/uboot offset))
-fit_block_size=$(printf "0x%x" $(( ( $(fdtdump u-boot.itb 2>/dev/null | sed -n "/^...totalsize:/ s@.*\(0x[0-9a-f]\+\).*@\1@p") + 0x1000 - 0x1 ) & ~(0x1000 - 0x1) + 0x20 )) )
-sed -i "/Blocks = / s@.*@  Blocks = $fit_block_base $fit_block_offset $fit_block_size \"flash.bin\", \\\\@" csf_fit.tmp
-
-# U-Boot
-uboot_block_base=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/uboot load))
-uboot_block_offset=$(printf "0x%x" $(( $(printf "0x%s" $(fdtget -t x u-boot.itb /images/uboot data-position)) + ${fit_block_offset} )))
-uboot_block_size=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/uboot data-size))
-sed -i "/0xuuuu/ s@.*@           $uboot_block_base $uboot_block_offset $uboot_block_size \"flash.bin\", \\\\@" csf_fit.tmp
-
-# ATF
-atf_block_base=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/atf load))
-atf_block_offset=$(printf "0x%x" $(( $(printf "0x%s" $(fdtget -t x u-boot.itb /images/atf data-position)) + ${fit_block_offset} )))
-atf_block_size=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/atf data-size))
-sed -i "/0xaaaa/ s@.*@           $atf_block_base $atf_block_offset $atf_block_size \"flash.bin\", \\\\@" csf_fit.tmp
-
-# DTB
-dtb_block_base=$(printf "0x%x" $(( ${uboot_block_base} + ${uboot_block_size} )))
-dtb_block_offset=$(printf "0x%x" $(( $(printf "0x%s" $(fdtget -t x u-boot.itb /images/fdt-1 data-position)) + ${fit_block_offset} )))
-dtb_block_size=$(printf "0x%s" $(fdtget -t x u-boot.itb /images/fdt-1 data-size))
-sed -i "/0xdddd/ s@.*@           $dtb_block_base $dtb_block_offset $dtb_block_size \"flash.bin\"@" csf_fit.tmp
+fit_block_size=$(printf "0x%x" $(( ( ( $(stat -tc %s u-boot.itb) + 0x1000 - 0x1 ) & ~(0x1000 - 0x1)) + 0x20 )) )
+sed -i "/Blocks = / s@.*@  Blocks = $fit_block_base $fit_block_offset $fit_block_size \"flash.bin\"@" csf_fit.tmp
 ```
 
 The fitImage part of flash.bin requires separate IVT. Generate the IVT and
@@ -237,8 +192,9 @@ csf_block_base=$(printf "%08x" $(( ${fit_block_base} + ${fit_block_size} )) | se
 ivt_block_offset=$((${fit_block_offset} + ${fit_block_size} - 0x20))
 csf_block_offset=$((${ivt_block_offset} + 0x20))
 
-echo "0xd1002041 ${ivt_ptr_base} 0x00000000 0x00000000 0x00000000 ${ivt_block_base} ${csf_block_base} 0x00000000" | xxd -r -p > ivt.bin
+echo "0xd1002041 ${ivt_block_base} 0x00000000 0x00000000 0x00000000 ${ivt_block_base} ${csf_block_base} 0x00000000" | xxd -r -p > ivt.bin
 dd if=ivt.bin of=flash.bin bs=1 seek=${ivt_block_offset} conv=notrunc
+```
 
 To generate CSF signature for the fitImage part of flash.bin container, use CST:
 ```
index 7e0f5ac..98f5732 100644 (file)
@@ -871,12 +871,6 @@ void spl_invoke_opensbi(struct spl_image_info *spl_image);
 int board_return_to_bootrom(struct spl_image_info *spl_image,
                            struct spl_boot_device *bootdev);
 
-/**
- * board_spl_fit_post_load - allow process images after loading finished
- * @fit: Pointer to a valid Flattened Image Tree blob
- */
-void board_spl_fit_post_load(const void *fit);
-
 /**
  * board_spl_fit_size_align - specific size align before processing payload
  *