imx8: support parsing i.MX8 Container file
authorPeng Fan <peng.fan@nxp.com>
Thu, 22 Aug 2019 07:42:33 +0000 (07:42 +0000)
committerStefano Babic <sbabic@denx.de>
Tue, 8 Oct 2019 14:35:58 +0000 (16:35 +0200)
Add parsing i.MX8 Container file support, this is to let
SPL could load images in a container file to destination address.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
arch/arm/include/asm/arch-imx8/image.h [new file with mode: 0644]
arch/arm/mach-imx/imx8/Kconfig
arch/arm/mach-imx/imx8/Makefile
arch/arm/mach-imx/imx8/parse-container.c [new file with mode: 0644]

diff --git a/arch/arm/include/asm/arch-imx8/image.h b/arch/arm/include/asm/arch-imx8/image.h
new file mode 100644 (file)
index 0000000..c1e5700
--- /dev/null
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright 2018-2019 NXP
+ */
+
+#ifndef __CONTAINER_HEADER_H_
+#define __CONTAINER_HEADER_H_
+
+#include <linux/sizes.h>
+#include <linux/types.h>
+
+#define IV_MAX_LEN                     32
+#define HASH_MAX_LEN                   64
+
+#define CONTAINER_HDR_ALIGNMENT 0x400
+#define CONTAINER_HDR_EMMC_OFFSET 0
+#define CONTAINER_HDR_MMCSD_OFFSET SZ_32K
+#define CONTAINER_HDR_QSPI_OFFSET SZ_4K
+#define CONTAINER_HDR_NAND_OFFSET SZ_128M
+
+struct container_hdr {
+       u8 version;
+       u8 length_lsb;
+       u8 length_msb;
+       u8 tag;
+       u32 flags;
+       u16 sw_version;
+       u8 fuse_version;
+       u8 num_images;
+       u16 sig_blk_offset;
+       u16 reserved;
+} __packed;
+
+struct boot_img_t {
+       u32 offset;
+       u32 size;
+       u64 dst;
+       u64 entry;
+       u32 hab_flags;
+       u32 meta;
+       u8 hash[HASH_MAX_LEN];
+       u8 iv[IV_MAX_LEN];
+} __packed;
+
+struct signature_block_hdr {
+       u8 version;
+       u8 length_lsb;
+       u8 length_msb;
+       u8 tag;
+       u16 srk_table_offset;
+       u16 cert_offset;
+       u16 blob_offset;
+       u16 signature_offset;
+       u32 reserved;
+} __packed;
+#endif
index bbe323d..e9496cb 100644 (file)
@@ -23,6 +23,12 @@ config IMX8QXP
 config SYS_SOC
        default "imx8"
 
+config SPL_LOAD_IMX_CONTAINER
+       bool "Enable SPL loading U-Boot as a i.MX Container image"
+       depends on SPL
+       help
+         This is to let SPL could load i.MX8 Container image
+
 choice
        prompt "i.MX8 board select"
        optional
index 92b5c56..5f62b28 100644 (file)
@@ -5,3 +5,7 @@
 #
 
 obj-y += cpu.o iomux.o misc.o
+
+ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += parse-container.o
+endif
diff --git a/arch/arm/mach-imx/imx8/parse-container.c b/arch/arm/mach-imx/imx8/parse-container.c
new file mode 100644 (file)
index 0000000..32f78bd
--- /dev/null
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018-2019 NXP
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <spl.h>
+#include <asm/arch/image.h>
+
+static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image,
+                                         struct spl_load_info *info,
+                                         struct container_hdr *container,
+                                         int image_index,
+                                         u32 container_sector)
+{
+       struct boot_img_t *images;
+       ulong sector;
+       u32 sectors;
+
+       if (image_index > container->num_images) {
+               debug("Invalid image number\n");
+               return NULL;
+       }
+
+       images = (struct boot_img_t *)((u8 *)container +
+                                      sizeof(struct container_hdr));
+
+       if (images[image_index].offset % info->bl_len) {
+               printf("%s: image%d offset not aligned to %u\n",
+                      __func__, image_index, info->bl_len);
+               return NULL;
+       }
+
+       sectors = roundup(images[image_index].size, info->bl_len) /
+               info->bl_len;
+       sector = images[image_index].offset / info->bl_len +
+               container_sector;
+
+       debug("%s: container: %p sector: %lu sectors: %u\n", __func__,
+             container, sector, sectors);
+       if (info->read(info, sector, sectors,
+                      (void *)images[image_index].entry) != sectors) {
+               printf("%s wrong\n", __func__);
+               return NULL;
+       }
+
+       return &images[image_index];
+}
+
+static int read_auth_container(struct spl_image_info *spl_image,
+                              struct spl_load_info *info, ulong sector)
+{
+       struct container_hdr *container = NULL;
+       u16 length;
+       u32 sectors;
+       int i, size;
+
+       size = roundup(CONTAINER_HDR_ALIGNMENT, info->bl_len);
+       sectors = size / info->bl_len;
+
+       /*
+        * It will not override the ATF code, so safe to use it here,
+        * no need malloc
+        */
+       container = (struct container_hdr *)spl_get_load_buffer(-size, size);
+
+       debug("%s: container: %p sector: %lu sectors: %u\n", __func__,
+             container, sector, sectors);
+       if (info->read(info, sector, sectors, container) != sectors)
+               return -EIO;
+
+       if (container->tag != 0x87 && container->version != 0x0) {
+               printf("Wrong container header");
+               return -ENOENT;
+       }
+
+       if (!container->num_images) {
+               printf("Wrong container, no image found");
+               return -ENOENT;
+       }
+
+       length = container->length_lsb + (container->length_msb << 8);
+       debug("Container length %u\n", length);
+
+       if (length > CONTAINER_HDR_ALIGNMENT) {
+               size = roundup(length, info->bl_len);
+               sectors = size / info->bl_len;
+
+               container = (struct container_hdr *)spl_get_load_buffer(-size, size);
+
+               debug("%s: container: %p sector: %lu sectors: %u\n",
+                     __func__, container, sector, sectors);
+               if (info->read(info, sector, sectors, container) !=
+                   sectors)
+                       return -EIO;
+       }
+
+       for (i = 0; i < container->num_images; i++) {
+               struct boot_img_t *image = read_auth_image(spl_image, info,
+                                                          container, i,
+                                                          sector);
+
+               if (!image)
+                       return -EINVAL;
+
+               if (i == 0) {
+                       spl_image->load_addr = image->dst;
+                       spl_image->entry_point = image->entry;
+               }
+       }
+
+       return 0;
+}
+
+int spl_load_imx_container(struct spl_image_info *spl_image,
+                          struct spl_load_info *info, ulong sector)
+{
+       return read_auth_container(spl_image, info, sector);
+}