[U-Boot,3/6] imx8: support parsing i.MX8 Container file
diff mbox series

Message ID 20190507130554.4598-4-peng.fan@nxp.com
State New
Delegated to: Stefano Babic
Headers show
Series
  • imx8: support container
Related show

Commit Message

Peng Fan May 7, 2019, 12:52 p.m. UTC
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   |  56 +++++++++++++++
 arch/arm/mach-imx/imx8/Kconfig           |   6 ++
 arch/arm/mach-imx/imx8/Makefile          |   4 ++
 arch/arm/mach-imx/imx8/parse-container.c | 120 +++++++++++++++++++++++++++++++
 4 files changed, 186 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-imx8/image.h
 create mode 100644 arch/arm/mach-imx/imx8/parse-container.c

Patch
diff mbox series

diff --git a/arch/arm/include/asm/arch-imx8/image.h b/arch/arm/include/asm/arch-imx8/image.h
new file mode 100644
index 0000000000..c1e5700859
--- /dev/null
+++ b/arch/arm/include/asm/arch-imx8/image.h
@@ -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
diff --git a/arch/arm/mach-imx/imx8/Kconfig b/arch/arm/mach-imx/imx8/Kconfig
index c32f7dbb61..8e6b79eb77 100644
--- a/arch/arm/mach-imx/imx8/Kconfig
+++ b/arch/arm/mach-imx/imx8/Kconfig
@@ -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
diff --git a/arch/arm/mach-imx/imx8/Makefile b/arch/arm/mach-imx/imx8/Makefile
index 31ad169ccf..19690110a5 100644
--- a/arch/arm/mach-imx/imx8/Makefile
+++ b/arch/arm/mach-imx/imx8/Makefile
@@ -5,3 +5,7 @@ 
 #
 
 obj-y += cpu.o iomux.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
index 0000000000..32f78bdddf
--- /dev/null
+++ b/arch/arm/mach-imx/imx8/parse-container.c
@@ -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);
+}