summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-imx/imx8/Makefile1
-rw-r--r--arch/arm/mach-imx/imx8/parser.c231
-rw-r--r--common/spl/spl_mmc.c15
-rw-r--r--include/configs/imx8qm_mek.h1
-rw-r--r--include/configs/imx8qxp_mek.h1
5 files changed, 249 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/imx8/Makefile b/arch/arm/mach-imx/imx8/Makefile
index 71f2af67d23..fff241ebf7d 100644
--- a/arch/arm/mach-imx/imx8/Makefile
+++ b/arch/arm/mach-imx/imx8/Makefile
@@ -10,6 +10,7 @@ obj-y += fsl_mu_hal.o
obj-y += fuse.o
obj-y += iomux.o
obj-y += image.o
+obj-$(CONFIG_SPL_BUILD) += parser.o
ifneq ($(CONFIG_SPL_BUILD),y)
obj-y += partition.o
endif
diff --git a/arch/arm/mach-imx/imx8/parser.c b/arch/arm/mach-imx/imx8/parser.c
new file mode 100644
index 00000000000..6a3b01f7551
--- /dev/null
+++ b/arch/arm/mach-imx/imx8/parser.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2018 NXP
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <mmc.h>
+#include <spi_flash.h>
+#include <asm/arch/image.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/mach-imx/sci/sci.h>
+#include <asm/mach-imx/boot_mode.h>
+
+#define MMC_DEV 0
+#define QSPI_DEV 1
+
+#define SEC_SECURE_RAM_BASE (0x31800000UL)
+#define SEC_SECURE_RAM_END_BASE (SEC_SECURE_RAM_BASE + 0xFFFFUL)
+#define SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE (0x60000000UL)
+
+#define SECO_PT 2U
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int current_dev_type = MMC_DEV;
+static int start_offset;
+static void *device;
+
+static int read(int start, int len, void *load_addr)
+{
+ int ret = -ENODEV;
+
+ if (!device) {
+ debug("No device selected\n");
+ return ret;
+ }
+
+#ifdef CONFIG_SPL_MMC_SUPPORT
+ if (current_dev_type == MMC_DEV) {
+ struct mmc *mmc = (struct mmc *)device;
+ unsigned long count;
+
+ ret = 0;
+
+ count = blk_dread(mmc_get_blk_desc(mmc),
+ start / mmc->read_bl_len,
+ len / mmc->read_bl_len,
+ load_addr);
+ if (count == 0) {
+ debug("Read container image failed\n");
+ return -EIO;
+ }
+ }
+#elif CONFIG_SPL_SPI_LOAD
+ if (current_dev_type == QSPI_DEV) {
+ struct spi_flash *flash = (struct spi_flash *)device;
+
+ int ret = spi_flash_read(flash, start,
+ CONTAINER_HDR_ALIGNMENT, load_addr);
+ if (ret != 0) {
+ debug("Read container image from QSPI failed\n");
+ return -EIO;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+static int authenticate_image(struct boot_img_t *img, int image_index)
+{
+ sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle;
+ sc_faddr_t start, end;
+ sc_rm_mr_t mr;
+ sc_err_t err;
+ int ret = 0;
+
+ debug("img %d, dst 0x%llx, src 0x%x, size 0x%x\n",
+ image_index, img->dst, img->offset, img->size);
+
+ /* Find the memreg and set permission for seco pt */
+ err = sc_rm_find_memreg(ipcHndl, &mr,
+ img->dst & ~(CONFIG_SYS_CACHELINE_SIZE - 1),
+ ALIGN(img->dst + img->size, CONFIG_SYS_CACHELINE_SIZE));
+
+ if (err) {
+ printf("can't find memreg for image load address %d, error %d\n",
+ image_index, err);
+ return -ENOMEM;
+ }
+
+ err = sc_rm_get_memreg_info(ipcHndl, mr, &start, &end);
+ if (!err)
+ debug("memreg %u 0x%llx -- 0x%llx\n", mr, start, end);
+
+ err = sc_rm_set_memreg_permissions(ipcHndl, mr,
+ SECO_PT, SC_RM_PERM_FULL);
+ if (err) {
+ printf("set permission failed for img %d, error %d\n",
+ image_index, err);
+ return -EPERM;
+ }
+
+ err = sc_misc_seco_authenticate(ipcHndl, SC_MISC_VERIFY_IMAGE,
+ 1 << image_index);
+ if (err) {
+ printf("authenticate img %d failed, return %d\n",
+ image_index, err);
+ ret = -EIO;
+ }
+
+ err = sc_rm_set_memreg_permissions(ipcHndl, mr,
+ SECO_PT, SC_RM_PERM_NONE);
+ if (err) {
+ printf("remove permission failed for img %d, error %d\n",
+ image_index, err);
+ ret = -EPERM;
+ }
+
+ return ret;
+}
+
+static struct boot_img_t *read_auth_image(struct container_hdr *container,
+ int image_index)
+{
+ struct boot_img_t *images;
+
+ if (image_index > container->num_images) {
+ debug("Invalid image number\n");
+ return NULL;
+ }
+
+ images = (struct boot_img_t *)
+ ((uint8_t *)container + sizeof(struct container_hdr));
+
+ if (read(images[image_index].offset + start_offset,
+ images[image_index].size,
+ (void *)images[image_index].entry) < 0) {
+ return NULL;
+ }
+
+ if (authenticate_image(&images[image_index], image_index)) {
+ printf("Failed to authenticate image %d\n", image_index);
+ return NULL;
+ }
+
+ return &images[image_index];
+}
+
+static int read_auth_container(struct spl_image_info *spl_image)
+{
+ sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle;
+ struct container_hdr *container = NULL;
+ uint16_t length;
+ int ret;
+ int i;
+
+ container = malloc(sizeof(struct container_hdr));
+ if (!container)
+ return -ENOMEM;
+
+ ret = read(start_offset, CONTAINER_HDR_ALIGNMENT, (void *)container);
+ if (ret)
+ return ret;
+
+ if (container->tag != 0x87 && container->version != 0x0) {
+ printf("Wrong container header\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ if (!container->num_images) {
+ printf("Wrong container, no image found\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ length = container->length_lsb + (container->length_msb << 8);
+
+ debug("container length %u\n", length);
+ memcpy((void *)SEC_SECURE_RAM_BASE, (const void *)container,
+ ALIGN(length, CONFIG_SYS_CACHELINE_SIZE));
+
+ ret = sc_misc_seco_authenticate(ipcHndl, SC_MISC_AUTH_CONTAINER,
+ SECO_LOCAL_SEC_SEC_SECURE_RAM_BASE);
+ if (ret) {
+ printf("authenticate container hdr failed, return %d\n", ret);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ for (i = 0; i < container->num_images; i++) {
+ struct boot_img_t *image = read_auth_image(container, i);
+
+ if (!image) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (i == 0) {
+ spl_image->load_addr = image->dst;
+ spl_image->entry_point = image->entry;
+ }
+ }
+
+ sc_misc_seco_authenticate(ipcHndl, SC_MISC_REL_CONTAINER, 0);
+
+out:
+ free(container);
+
+ return ret;
+}
+
+int mmc_load_image_parse_container(struct spl_image_info *spl_image,
+ struct mmc *mmc, unsigned long sector)
+{
+ int ret = 0;
+
+ current_dev_type = MMC_DEV;
+ device = mmc;
+
+ start_offset = sector * mmc->read_bl_len;
+
+ ret = read_auth_container(spl_image);
+
+ return ret;
+}
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index 91b5190c073..785bbd53387 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -319,6 +319,14 @@ unsigned long __weak spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
}
#endif
+#ifdef CONFIG_PARSE_CONTAINER
+int __weak mmc_load_image_parse_container(struct spl_image_info *spl_image,
+ struct mmc *mmc, unsigned long sector)
+{
+ return -ENODEV;
+};
+#endif
+
int spl_mmc_load_image(struct spl_image_info *spl_image,
struct spl_boot_device *bootdev)
{
@@ -389,6 +397,13 @@ int spl_mmc_load_image(struct spl_image_info *spl_image,
err = mmc_load_image_raw_sector_dual_uboot(spl_image,
mmc);
#else
+#ifdef CONFIG_PARSE_CONTAINER
+ err = mmc_load_image_parse_container(spl_image, mmc,
+ spl_mmc_get_uboot_raw_sector(mmc));
+
+ if (!err)
+ return err;
+#endif
err = mmc_load_image_raw_sector(spl_image, mmc,
spl_mmc_get_uboot_raw_sector(mmc));
#endif
diff --git a/include/configs/imx8qm_mek.h b/include/configs/imx8qm_mek.h
index d8ba38cecee..61662433a67 100644
--- a/include/configs/imx8qm_mek.h
+++ b/include/configs/imx8qm_mek.h
@@ -17,6 +17,7 @@
#define CONFIG_SPL_SPI_LOAD
#endif
+#define CONFIG_PARSE_CONTAINER
#define CONFIG_SPL_TEXT_BASE 0x0
#define CONFIG_SPL_MAX_SIZE (124 * 1024)
#define CONFIG_SYS_MONITOR_LEN (1024 * 1024)
diff --git a/include/configs/imx8qxp_mek.h b/include/configs/imx8qxp_mek.h
index 5871935aa5a..d811a1fe731 100644
--- a/include/configs/imx8qxp_mek.h
+++ b/include/configs/imx8qxp_mek.h
@@ -18,6 +18,7 @@
#define CONFIG_SPL_SPI_LOAD
#endif
+#define CONFIG_PARSE_CONTAINER
#define CONFIG_SPL_TEXT_BASE 0x0
#define CONFIG_SPL_MAX_SIZE (124 * 1024)
#define CONFIG_SYS_MONITOR_LEN (1024 * 1024)