imx: hab: Simplify the mechanism

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>
This commit is contained in:
Marek Vasut 2023-05-28 23:00:30 +02:00 committed by Tom Rini
parent 6a412faea3
commit 6039e0edc8
10 changed files with 67 additions and 159 deletions

View 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>;

View file

@ -145,7 +145,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>;

View file

@ -103,7 +103,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>;

View 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 {

View 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,36 +316,49 @@ ulong board_spl_fit_size_align(ulong size)
size = ALIGN(size, 0x1000);
size += CONFIG_CSF_SIZE;
if (size > CONFIG_SYS_BOOTM_LEN)
panic("spl: ERROR: image too big\n");
return size;
}
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");
}
}
#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
}
/*
* read the address where the IVT header must sit
* from IVT image header, loaded from SPL into
* an malloced buffer and copy the IVT header
* to this address
*/
void *spl_load_simple_fit_fix_load(const void *fit)
{
struct ivt *ivt;
unsigned long offset;
unsigned long size;
u8 *tmp = (u8 *)fit;
offset = ALIGN(fdt_totalsize(fit), 0x1000);
size = ALIGN(fdt_totalsize(fit), 4);
size = board_spl_fit_size_align(size);
tmp += offset;
ivt = (struct ivt *)tmp;
debug("%s: ivt: %p offset: %lx size: %lx\n", __func__, ivt, offset, size);
debug("%s: ivt self: %x\n", __func__, ivt->self);
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)
@ -355,36 +369,3 @@ int dram_init_banksize(void)
return 0;
}
#endif
/*
* read the address where the IVT header must sit
* from IVT image header, loaded from SPL into
* an malloced buffer and copy the IVT header
* to this address
*/
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;
offset = ALIGN(fdt_totalsize(fit), 0x1000);
size = ALIGN(fdt_totalsize(fit), 4);
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;
}

View 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;
}

View 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

View file

@ -26,11 +26,5 @@
[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"

View 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:
```

View 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
*