feat(plat/st): add STM32MP_EMMC_BOOT option
Added a new STM32MP_EMMC_BOOT option, which is used to look for SSBL in
the same eMMC boot partition TF-A booted from at a fixed 256k offset. In
case STM32 image header is not found, the boot process rolls back to a
GPT partition look-up scheme.
Signed-off-by: Vyacheslav Yurkov <uvv.mail@gmail.com>
Change-Id: I85a87dc9ae7f2b915ed8e584be80f4b3588efc48
diff --git a/plat/st/common/bl2_io_storage.c b/plat/st/common/bl2_io_storage.c
index a25643b..0a18d99 100644
--- a/plat/st/common/bl2_io_storage.c
+++ b/plat/st/common/bl2_io_storage.c
@@ -62,6 +62,30 @@
.block_size = MMC_BLOCK_SIZE,
};
+#if STM32MP_EMMC_BOOT
+static io_block_spec_t emmc_boot_ssbl_block_spec = {
+ .offset = PLAT_EMMC_BOOT_SSBL_OFFSET,
+ .length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
+};
+
+static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = {
+ /* It's used as temp buffer in block driver */
+ .buffer = {
+ .offset = (size_t)&block_buffer,
+ .length = MMC_BLOCK_SIZE,
+ },
+ .ops = {
+ .read = mmc_boot_part_read_blocks,
+ .write = NULL,
+ },
+ .block_size = MMC_BLOCK_SIZE,
+};
+#endif
+
+static struct io_mmc_dev_spec mmc_device_spec = {
+ .use_boot_part = false,
+};
+
static const io_dev_connector_t *mmc_dev_con;
#endif /* STM32MP_SDMMC || STM32MP_EMMC */
@@ -236,6 +260,38 @@
return io_dev_init(storage_dev_handle, 0);
}
+#if STM32MP_EMMC_BOOT
+static uint32_t get_boot_part_ssbl_header(void)
+{
+ uint32_t magic = 0;
+ int io_result;
+ size_t bytes_read;
+
+ io_result = register_io_dev_block(&mmc_dev_con);
+ if (io_result != 0) {
+ panic();
+ }
+
+ io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_block_dev_boot_part_spec,
+ &storage_dev_handle);
+ assert(io_result == 0);
+
+ io_result = io_open(storage_dev_handle, (uintptr_t) &emmc_boot_ssbl_block_spec,
+ &image_dev_handle);
+ assert(io_result == 0);
+
+ io_result = io_read(image_dev_handle, (uintptr_t) &magic, sizeof(magic),
+ &bytes_read);
+ assert(io_result == 0);
+ assert(bytes_read == sizeof(magic));
+
+ io_result = io_dev_close(storage_dev_handle);
+ assert(io_result == 0);
+
+ return magic;
+}
+#endif
+
static void print_boot_device(boot_api_context_t *boot_context)
{
switch (boot_context->boot_interface_selected) {
@@ -273,7 +329,8 @@
uint8_t idx;
struct stm32image_part_info *part;
struct stm32_sdmmc2_params params;
- const partition_entry_t *entry;
+ const partition_entry_t *entry __unused;
+ uint32_t magic __unused;
zeromem(¶ms, sizeof(struct stm32_sdmmc2_params));
@@ -304,6 +361,26 @@
ERROR("SDMMC%u init failed\n", boot_interface_instance);
panic();
}
+
+ stm32image_dev_info_spec.device_size =
+ stm32_sdmmc2_mmc_get_device_size();
+
+#if STM32MP_EMMC_BOOT
+ magic = get_boot_part_ssbl_header();
+
+ if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) {
+ VERBOSE("%s, header found, jump to emmc load\n", __func__);
+ idx = IMG_IDX_BL33;
+ part = &stm32image_dev_info_spec.part_info[idx];
+ part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET;
+ part->bkp_offset = 0U;
+ mmc_device_spec.use_boot_part = true;
+
+ goto emmc_boot;
+ } else {
+ WARN("%s: Can't find STM32 header on a boot partition\n", __func__);
+ }
+#endif
/* Open MMC as a block device to read GPT table */
io_result = register_io_dev_block(&mmc_dev_con);
@@ -320,9 +397,6 @@
io_result = io_dev_close(storage_dev_handle);
assert(io_result == 0);
- stm32image_dev_info_spec.device_size =
- stm32_sdmmc2_mmc_get_device_size();
-
for (idx = 0U; idx < IMG_IDX_NUM; idx++) {
part = &stm32image_dev_info_spec.part_info[idx];
entry = get_partition_entry(part->name);
@@ -335,6 +409,9 @@
part->bkp_offset = 0U;
}
+#if STM32MP_EMMC_BOOT
+emmc_boot:
+#endif
/*
* Re-open MMC with io_mmc, for better perfs compared to
* io_block.
@@ -342,7 +419,8 @@
io_result = register_io_dev_mmc(&mmc_dev_con);
assert(io_result == 0);
- io_result = io_dev_open(mmc_dev_con, 0, &storage_dev_handle);
+ io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec,
+ &storage_dev_handle);
assert(io_result == 0);
io_result = register_io_dev_stm32image(&stm32image_dev_con);
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 9a2f54a..2d7d369 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -88,6 +88,12 @@
*/
#define PLAT_STM32MP_NS_IMAGE_OFFSET BL33_BASE
+/*
+ * SSBL offset in case it's stored in eMMC boot partition.
+ * We can fix it to 256K because TF-A size can't be bigger than SRAM
+ */
+#define PLAT_EMMC_BOOT_SSBL_OFFSET U(0x40000)
+
/*******************************************************************************
* DTB specific defines.
******************************************************************************/
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 50fb1b7..128dbc4 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -42,6 +42,7 @@
STM32MP_RAW_NAND ?= 0
STM32MP_SPI_NAND ?= 0
STM32MP_SPI_NOR ?= 0
+STM32MP_EMMC_BOOT ?= 0
ifeq ($(filter 1,${STM32MP_EMMC} ${STM32MP_SDMMC} ${STM32MP_RAW_NAND} \
${STM32MP_SPI_NAND} ${STM32MP_SPI_NOR}),)
@@ -77,6 +78,7 @@
STM32MP_RAW_NAND \
STM32MP_SPI_NAND \
STM32MP_SPI_NOR \
+ STM32MP_EMMC_BOOT \
PLAT_XLAT_TABLES_DYNAMIC \
)))
@@ -93,6 +95,7 @@
STM32MP_RAW_NAND \
STM32MP_SPI_NAND \
STM32MP_SPI_NOR \
+ STM32MP_EMMC_BOOT \
PLAT_XLAT_TABLES_DYNAMIC \
STM32_TF_A_COPIES \
PLAT_PARTITION_MAX_ENTRIES \