123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869 |
- /*
- * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #include <assert.h>
- #include <string.h>
- #include <arch_helpers.h>
- #include <common/debug.h>
- #include <common/desc_image_load.h>
- #include <drivers/fwu/fwu.h>
- #include <drivers/fwu/fwu_metadata.h>
- #include <drivers/io/io_block.h>
- #include <drivers/io/io_driver.h>
- #include <drivers/io/io_encrypted.h>
- #include <drivers/io/io_fip.h>
- #include <drivers/io/io_memmap.h>
- #include <drivers/io/io_mtd.h>
- #include <drivers/io/io_storage.h>
- #include <drivers/mmc.h>
- #include <drivers/partition/efi.h>
- #include <drivers/partition/partition.h>
- #include <drivers/raw_nand.h>
- #include <drivers/spi_nand.h>
- #include <drivers/spi_nor.h>
- #include <drivers/st/stm32_fmc2_nand.h>
- #include <drivers/st/stm32_qspi.h>
- #include <drivers/st/stm32_sdmmc2.h>
- #include <drivers/usb_device.h>
- #include <lib/fconf/fconf.h>
- #include <lib/mmio.h>
- #include <lib/utils.h>
- #include <plat/common/platform.h>
- #include <tools_share/firmware_image_package.h>
- #include <platform_def.h>
- #include <stm32cubeprogrammer.h>
- #include <stm32mp_efi.h>
- #include <stm32mp_fconf_getter.h>
- #include <stm32mp_io_storage.h>
- #include <usb_dfu.h>
- /* IO devices */
- uintptr_t fip_dev_handle;
- uintptr_t storage_dev_handle;
- static const io_dev_connector_t *fip_dev_con;
- static uint32_t nand_block_sz __maybe_unused;
- #ifndef DECRYPTION_SUPPORT_none
- static const io_dev_connector_t *enc_dev_con;
- uintptr_t enc_dev_handle;
- #endif
- #if STM32MP_SDMMC || STM32MP_EMMC
- static struct mmc_device_info mmc_info;
- static uint8_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE);
- static io_block_dev_spec_t mmc_block_dev_spec = {
- /* It's used as temp buffer in block driver */
- .buffer = {
- .offset = (size_t)&block_buffer,
- .length = MMC_BLOCK_SIZE,
- },
- .ops = {
- .read = mmc_read_blocks,
- .write = NULL,
- },
- .block_size = MMC_BLOCK_SIZE,
- };
- static const io_dev_connector_t *mmc_dev_con;
- #endif /* STM32MP_SDMMC || STM32MP_EMMC */
- #if STM32MP_SPI_NOR
- static io_mtd_dev_spec_t spi_nor_dev_spec = {
- .ops = {
- .init = spi_nor_init,
- .read = spi_nor_read,
- },
- };
- #endif
- #if STM32MP_RAW_NAND
- static io_mtd_dev_spec_t nand_dev_spec = {
- .ops = {
- .init = nand_raw_init,
- .read = nand_read,
- .seek = nand_seek_bb
- },
- };
- static const io_dev_connector_t *nand_dev_con;
- #endif
- #if STM32MP_SPI_NAND
- static io_mtd_dev_spec_t spi_nand_dev_spec = {
- .ops = {
- .init = spi_nand_init,
- .read = nand_read,
- .seek = nand_seek_bb
- },
- };
- #endif
- #if STM32MP_SPI_NAND || STM32MP_SPI_NOR
- static const io_dev_connector_t *spi_dev_con;
- #endif
- #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
- static const io_dev_connector_t *memmap_dev_con;
- #endif
- io_block_spec_t image_block_spec = {
- .offset = 0U,
- .length = 0U,
- };
- int open_fip(const uintptr_t spec)
- {
- return io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID);
- }
- #ifndef DECRYPTION_SUPPORT_none
- int open_enc_fip(const uintptr_t spec)
- {
- int result;
- uintptr_t local_image_handle;
- result = io_dev_init(enc_dev_handle, (uintptr_t)ENC_IMAGE_ID);
- if (result != 0) {
- return result;
- }
- result = io_open(enc_dev_handle, spec, &local_image_handle);
- if (result != 0) {
- return result;
- }
- VERBOSE("Using encrypted FIP\n");
- io_close(local_image_handle);
- return 0;
- }
- #endif
- int open_storage(const uintptr_t spec)
- {
- return io_dev_init(storage_dev_handle, 0);
- }
- #if STM32MP_EMMC_BOOT
- static uint32_t get_boot_part_fip_header(void)
- {
- io_block_spec_t emmc_boot_fip_block_spec = {
- .offset = STM32MP_EMMC_BOOT_FIP_OFFSET,
- .length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */
- };
- uint32_t magic = 0U;
- int io_result;
- size_t bytes_read;
- uintptr_t fip_hdr_handle;
- io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_fip_block_spec,
- &fip_hdr_handle);
- assert(io_result == 0);
- io_result = io_read(fip_hdr_handle, (uintptr_t)&magic, sizeof(magic),
- &bytes_read);
- if ((io_result != 0) || (bytes_read != sizeof(magic))) {
- panic();
- }
- io_close(fip_hdr_handle);
- VERBOSE("%s: eMMC boot magic at offset 256K: %08x\n",
- __func__, magic);
- return magic;
- }
- #endif
- static void print_boot_device(boot_api_context_t *boot_context)
- {
- switch (boot_context->boot_interface_selected) {
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
- INFO("Using SDMMC\n");
- break;
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
- INFO("Using EMMC\n");
- break;
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI:
- INFO("Using SPI NOR\n");
- break;
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
- INFO("Using FMC NAND\n");
- break;
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI:
- INFO("Using SPI NAND\n");
- break;
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
- INFO("Using UART\n");
- break;
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
- INFO("Using USB\n");
- break;
- default:
- ERROR("Boot interface %u not found\n",
- boot_context->boot_interface_selected);
- panic();
- break;
- }
- if (boot_context->boot_interface_instance != 0U) {
- INFO(" Instance %d\n", boot_context->boot_interface_instance);
- }
- }
- #if STM32MP_SDMMC || STM32MP_EMMC
- static void boot_mmc(enum mmc_device_type mmc_dev_type,
- uint16_t boot_interface_instance)
- {
- int io_result __maybe_unused;
- struct stm32_sdmmc2_params params;
- zeromem(¶ms, sizeof(struct stm32_sdmmc2_params));
- mmc_info.mmc_dev_type = mmc_dev_type;
- switch (boot_interface_instance) {
- case 1:
- params.reg_base = STM32MP_SDMMC1_BASE;
- break;
- case 2:
- params.reg_base = STM32MP_SDMMC2_BASE;
- break;
- case 3:
- params.reg_base = STM32MP_SDMMC3_BASE;
- break;
- default:
- WARN("SDMMC instance not found, using default\n");
- if (mmc_dev_type == MMC_IS_SD) {
- params.reg_base = STM32MP_SDMMC1_BASE;
- } else {
- params.reg_base = STM32MP_SDMMC2_BASE;
- }
- break;
- }
- if (mmc_dev_type != MMC_IS_EMMC) {
- params.flags = MMC_FLAG_SD_CMD6;
- }
- params.device_info = &mmc_info;
- if (stm32_sdmmc2_mmc_init(¶ms) != 0) {
- ERROR("SDMMC%u init failed\n", boot_interface_instance);
- panic();
- }
- /* Open MMC as a block device to read FIP */
- 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_spec,
- &storage_dev_handle);
- assert(io_result == 0);
- #if STM32MP_EMMC_BOOT
- if (mmc_dev_type == MMC_IS_EMMC) {
- io_result = mmc_part_switch_current_boot();
- assert(io_result == 0);
- if (get_boot_part_fip_header() != TOC_HEADER_NAME) {
- WARN("%s: Can't find FIP header on eMMC boot partition. Trying GPT\n",
- __func__);
- io_result = mmc_part_switch_user();
- assert(io_result == 0);
- return;
- }
- VERBOSE("%s: FIP header found on eMMC boot partition\n",
- __func__);
- image_block_spec.offset = STM32MP_EMMC_BOOT_FIP_OFFSET;
- image_block_spec.length = mmc_boot_part_size() - STM32MP_EMMC_BOOT_FIP_OFFSET;
- }
- #endif
- }
- #endif /* STM32MP_SDMMC || STM32MP_EMMC */
- #if STM32MP_SPI_NOR
- static void boot_spi_nor(boot_api_context_t *boot_context)
- {
- int io_result __maybe_unused;
- io_result = stm32_qspi_init();
- assert(io_result == 0);
- io_result = register_io_dev_mtd(&spi_dev_con);
- assert(io_result == 0);
- /* Open connections to device */
- io_result = io_dev_open(spi_dev_con,
- (uintptr_t)&spi_nor_dev_spec,
- &storage_dev_handle);
- assert(io_result == 0);
- }
- #endif /* STM32MP_SPI_NOR */
- #if STM32MP_RAW_NAND || STM32MP_SPI_NAND
- /*
- * This function returns 0 if it can find an alternate
- * image to be loaded or a negative errno otherwise.
- */
- static int try_nand_backup_partitions(unsigned int image_id)
- {
- static unsigned int backup_id;
- static unsigned int backup_block_nb;
- /* Check if NAND storage used */
- if (nand_block_sz == 0U) {
- return -ENODEV;
- }
- if (backup_id != image_id) {
- backup_block_nb = PLATFORM_MTD_MAX_PART_SIZE / nand_block_sz;
- backup_id = image_id;
- }
- if (backup_block_nb-- == 0U) {
- return -ENOSPC;
- }
- #if PSA_FWU_SUPPORT
- if (((image_block_spec.offset < STM32MP_NAND_FIP_B_OFFSET) &&
- ((image_block_spec.offset + nand_block_sz) >= STM32MP_NAND_FIP_B_OFFSET)) ||
- (image_block_spec.offset + nand_block_sz >= STM32MP_NAND_FIP_B_MAX_OFFSET)) {
- return 0;
- }
- #endif
- image_block_spec.offset += nand_block_sz;
- return 0;
- }
- static const struct plat_try_images_ops try_img_ops = {
- .next_instance = try_nand_backup_partitions,
- };
- #endif /* STM32MP_RAW_NAND || STM32MP_SPI_NAND */
- #if STM32MP_RAW_NAND
- static void boot_fmc2_nand(boot_api_context_t *boot_context)
- {
- int io_result __maybe_unused;
- plat_setup_try_img_ops(&try_img_ops);
- io_result = stm32_fmc2_init();
- assert(io_result == 0);
- /* Register the IO device on this platform */
- io_result = register_io_dev_mtd(&nand_dev_con);
- assert(io_result == 0);
- /* Open connections to device */
- io_result = io_dev_open(nand_dev_con, (uintptr_t)&nand_dev_spec,
- &storage_dev_handle);
- assert(io_result == 0);
- nand_block_sz = nand_dev_spec.erase_size;
- }
- #endif /* STM32MP_RAW_NAND */
- #if STM32MP_SPI_NAND
- static void boot_spi_nand(boot_api_context_t *boot_context)
- {
- int io_result __maybe_unused;
- plat_setup_try_img_ops(&try_img_ops);
- io_result = stm32_qspi_init();
- assert(io_result == 0);
- io_result = register_io_dev_mtd(&spi_dev_con);
- assert(io_result == 0);
- /* Open connections to device */
- io_result = io_dev_open(spi_dev_con,
- (uintptr_t)&spi_nand_dev_spec,
- &storage_dev_handle);
- assert(io_result == 0);
- nand_block_sz = spi_nand_dev_spec.erase_size;
- }
- #endif /* STM32MP_SPI_NAND */
- #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
- static void mmap_io_setup(void)
- {
- int io_result __maybe_unused;
- io_result = register_io_dev_memmap(&memmap_dev_con);
- assert(io_result == 0);
- io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL,
- &storage_dev_handle);
- assert(io_result == 0);
- }
- #if STM32MP_UART_PROGRAMMER
- static void stm32cubeprogrammer_uart(void)
- {
- int ret __maybe_unused;
- boot_api_context_t *boot_context =
- (boot_api_context_t *)stm32mp_get_boot_ctx_address();
- uintptr_t uart_base;
- uart_base = get_uart_address(boot_context->boot_interface_instance);
- ret = stm32cubeprog_uart_load(uart_base, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
- assert(ret == 0);
- }
- #endif
- #if STM32MP_USB_PROGRAMMER
- static void stm32cubeprogrammer_usb(void)
- {
- int ret __maybe_unused;
- struct usb_handle *pdev;
- /* Init USB on platform */
- pdev = usb_dfu_plat_init();
- ret = stm32cubeprog_usb_load(pdev, DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
- assert(ret == 0);
- }
- #endif
- #endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
- void stm32mp_io_setup(void)
- {
- int io_result __maybe_unused;
- boot_api_context_t *boot_context =
- (boot_api_context_t *)stm32mp_get_boot_ctx_address();
- print_boot_device(boot_context);
- if ((boot_context->boot_partition_used_toboot == 1U) ||
- (boot_context->boot_partition_used_toboot == 2U)) {
- INFO("Boot used partition fsbl%u\n",
- boot_context->boot_partition_used_toboot);
- }
- io_result = register_io_dev_fip(&fip_dev_con);
- assert(io_result == 0);
- io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL,
- &fip_dev_handle);
- #ifndef DECRYPTION_SUPPORT_none
- io_result = register_io_dev_enc(&enc_dev_con);
- assert(io_result == 0);
- io_result = io_dev_open(enc_dev_con, (uintptr_t)NULL,
- &enc_dev_handle);
- assert(io_result == 0);
- #endif
- switch (boot_context->boot_interface_selected) {
- #if STM32MP_SDMMC
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
- dmbsy();
- boot_mmc(MMC_IS_SD, boot_context->boot_interface_instance);
- break;
- #endif
- #if STM32MP_EMMC
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
- dmbsy();
- boot_mmc(MMC_IS_EMMC, boot_context->boot_interface_instance);
- break;
- #endif
- #if STM32MP_SPI_NOR
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI:
- dmbsy();
- boot_spi_nor(boot_context);
- break;
- #endif
- #if STM32MP_RAW_NAND
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
- dmbsy();
- boot_fmc2_nand(boot_context);
- break;
- #endif
- #if STM32MP_SPI_NAND
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI:
- dmbsy();
- boot_spi_nand(boot_context);
- break;
- #endif
- #if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
- #if STM32MP_UART_PROGRAMMER
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
- #endif
- #if STM32MP_USB_PROGRAMMER
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
- #endif
- dmbsy();
- mmap_io_setup();
- break;
- #endif
- default:
- ERROR("Boot interface %d not supported\n",
- boot_context->boot_interface_selected);
- panic();
- break;
- }
- }
- int bl2_plat_handle_pre_image_load(unsigned int image_id)
- {
- static bool gpt_init_done __maybe_unused;
- uint16_t boot_itf = stm32mp_get_boot_itf_selected();
- switch (boot_itf) {
- #if STM32MP_SDMMC || STM32MP_EMMC
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
- #if STM32MP_EMMC_BOOT
- if (image_block_spec.offset == STM32MP_EMMC_BOOT_FIP_OFFSET) {
- break;
- }
- #endif
- /* fallthrough */
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
- if (!gpt_init_done) {
- /*
- * With FWU Multi Bank feature enabled, the selection of
- * the image to boot will be done by fwu_init calling the
- * platform hook, plat_fwu_set_images_source.
- */
- #if !PSA_FWU_SUPPORT
- const partition_entry_t *entry;
- const struct efi_guid fip_guid = STM32MP_FIP_GUID;
- partition_init(GPT_IMAGE_ID);
- entry = get_partition_entry_by_type(&fip_guid);
- if (entry == NULL) {
- entry = get_partition_entry(FIP_IMAGE_NAME);
- if (entry == NULL) {
- ERROR("Could NOT find the %s partition!\n",
- FIP_IMAGE_NAME);
- return -ENOENT;
- }
- }
- image_block_spec.offset = entry->start;
- image_block_spec.length = entry->length;
- #endif
- gpt_init_done = true;
- } else {
- bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
- assert(bl_mem_params != NULL);
- mmc_block_dev_spec.buffer.offset = bl_mem_params->image_info.image_base;
- mmc_block_dev_spec.buffer.length = bl_mem_params->image_info.image_max_size;
- }
- break;
- #endif
- #if STM32MP_RAW_NAND || STM32MP_SPI_NAND
- #if STM32MP_RAW_NAND
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
- #endif
- #if STM32MP_SPI_NAND
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI:
- #endif
- /*
- * With FWU Multi Bank feature enabled, the selection of
- * the image to boot will be done by fwu_init calling the
- * platform hook, plat_fwu_set_images_source.
- */
- #if !PSA_FWU_SUPPORT
- image_block_spec.offset = STM32MP_NAND_FIP_OFFSET;
- #endif
- break;
- #endif
- #if STM32MP_SPI_NOR
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI:
- /*
- * With FWU Multi Bank feature enabled, the selection of
- * the image to boot will be done by fwu_init calling the
- * platform hook, plat_fwu_set_images_source.
- */
- #if !PSA_FWU_SUPPORT
- image_block_spec.offset = STM32MP_NOR_FIP_OFFSET;
- #endif
- break;
- #endif
- #if STM32MP_UART_PROGRAMMER
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
- if (image_id == FW_CONFIG_ID) {
- stm32cubeprogrammer_uart();
- /* FIP loaded at DWL address */
- image_block_spec.offset = DWL_BUFFER_BASE;
- image_block_spec.length = DWL_BUFFER_SIZE;
- }
- break;
- #endif
- #if STM32MP_USB_PROGRAMMER
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
- if (image_id == FW_CONFIG_ID) {
- stm32cubeprogrammer_usb();
- /* FIP loaded at DWL address */
- image_block_spec.offset = DWL_BUFFER_BASE;
- image_block_spec.length = DWL_BUFFER_SIZE;
- }
- break;
- #endif
- default:
- ERROR("FIP Not found\n");
- panic();
- }
- return 0;
- }
- /*
- * Return an IO device handle and specification which can be used to access
- * an image. Use this to enforce platform load policy.
- */
- int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
- uintptr_t *image_spec)
- {
- int rc;
- const struct plat_io_policy *policy;
- policy = FCONF_GET_PROPERTY(stm32mp, io_policies, image_id);
- rc = policy->check(policy->image_spec);
- if (rc == 0) {
- *image_spec = policy->image_spec;
- *dev_handle = *(policy->dev_handle);
- }
- return rc;
- }
- #if PSA_FWU_SUPPORT
- /*
- * In each boot in non-trial mode, we set the BKP register to
- * FWU_MAX_TRIAL_REBOOT, and return the active_index from metadata.
- *
- * As long as the update agent didn't update the "accepted" field in metadata
- * (i.e. we are in trial mode), we select the new active_index.
- * To avoid infinite boot loop at trial boot we decrement a BKP register.
- * If this counter is 0:
- * - an unexpected TAMPER event raised (that resets the BKP registers to 0)
- * - a power-off occurs before the update agent was able to update the
- * "accepted' field
- * - we already boot FWU_MAX_TRIAL_REBOOT times in trial mode.
- * we select the previous_active_index.
- */
- uint32_t plat_fwu_get_boot_idx(void)
- {
- /*
- * Select boot index and update boot counter only once per boot
- * even if this function is called several times.
- */
- static uint32_t boot_idx = INVALID_BOOT_IDX;
- if (boot_idx == INVALID_BOOT_IDX) {
- const struct fwu_metadata *data = fwu_get_metadata();
- boot_idx = data->active_index;
- if (data->bank_state[boot_idx] == FWU_BANK_STATE_VALID) {
- if (stm32_get_and_dec_fwu_trial_boot_cnt() == 0U) {
- WARN("Trial FWU fails %u times\n",
- FWU_MAX_TRIAL_REBOOT);
- boot_idx = fwu_get_alternate_boot_bank();
- }
- } else if (data->bank_state[boot_idx] ==
- FWU_BANK_STATE_ACCEPTED) {
- stm32_set_max_fwu_trial_boot_cnt();
- } else {
- ERROR("The active bank(%u) of the platform is in Invalid State.\n",
- boot_idx);
- boot_idx = fwu_get_alternate_boot_bank();
- stm32_clear_fwu_trial_boot_cnt();
- }
- }
- return boot_idx;
- }
- static void *stm32_get_image_spec(const struct efi_guid *img_type_guid)
- {
- unsigned int i;
- for (i = 0U; i < MAX_NUMBER_IDS; i++) {
- if ((guidcmp(&policies[i].img_type_guid, img_type_guid)) == 0) {
- return (void *)policies[i].image_spec;
- }
- }
- return NULL;
- }
- void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
- {
- unsigned int i;
- uint32_t boot_idx;
- const partition_entry_t *entry __maybe_unused;
- const struct fwu_image_entry *img_entry;
- const void *img_type_guid;
- const void *img_guid;
- io_block_spec_t *image_spec;
- const uint16_t boot_itf = stm32mp_get_boot_itf_selected();
- boot_idx = plat_fwu_get_boot_idx();
- assert(boot_idx < NR_OF_FW_BANKS);
- VERBOSE("Selecting to boot from bank %u\n", boot_idx);
- img_entry = (void *)&metadata->fw_desc.img_entry;
- for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
- img_type_guid = &img_entry[i].img_type_guid;
- img_guid = &img_entry[i].img_bank_info[boot_idx].img_guid;
- image_spec = stm32_get_image_spec(img_type_guid);
- if (image_spec == NULL) {
- ERROR("Unable to get image spec for the image in the metadata\n");
- panic();
- }
- switch (boot_itf) {
- #if (STM32MP_SDMMC || STM32MP_EMMC)
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
- entry = get_partition_entry_by_guid(img_guid);
- if (entry == NULL) {
- ERROR("No partition with the uuid mentioned in metadata\n");
- panic();
- }
- image_spec->offset = entry->start;
- image_spec->length = entry->length;
- break;
- #endif
- #if STM32MP_SPI_NOR
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI:
- if (guidcmp(img_guid, &STM32MP_NOR_FIP_A_GUID) == 0) {
- image_spec->offset = STM32MP_NOR_FIP_A_OFFSET;
- } else if (guidcmp(img_guid, &STM32MP_NOR_FIP_B_GUID) == 0) {
- image_spec->offset = STM32MP_NOR_FIP_B_OFFSET;
- } else {
- ERROR("Invalid uuid mentioned in metadata\n");
- panic();
- }
- break;
- #endif
- #if (STM32MP_RAW_NAND || STM32MP_SPI_NAND)
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI:
- if (guidcmp(img_guid, &STM32MP_NAND_FIP_A_GUID) == 0) {
- image_spec->offset = STM32MP_NAND_FIP_A_OFFSET;
- } else if (guidcmp(img_guid, &STM32MP_NAND_FIP_B_GUID) == 0) {
- image_spec->offset = STM32MP_NAND_FIP_B_OFFSET;
- } else {
- ERROR("Invalid uuid mentioned in metadata\n");
- panic();
- }
- break;
- #endif
- default:
- panic();
- break;
- }
- }
- }
- static int set_metadata_image_source(unsigned int image_id,
- uintptr_t *handle,
- uintptr_t *image_spec)
- {
- struct plat_io_policy *policy;
- io_block_spec_t *spec __maybe_unused;
- const partition_entry_t *entry __maybe_unused;
- const uint16_t boot_itf = stm32mp_get_boot_itf_selected();
- policy = &policies[image_id];
- spec = (io_block_spec_t *)policy->image_spec;
- switch (boot_itf) {
- #if (STM32MP_SDMMC || STM32MP_EMMC)
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
- partition_init(GPT_IMAGE_ID);
- if (image_id == FWU_METADATA_IMAGE_ID) {
- entry = get_partition_entry(METADATA_PART_1);
- } else {
- entry = get_partition_entry(METADATA_PART_2);
- }
- if (entry == NULL) {
- ERROR("Unable to find a metadata partition\n");
- return -ENOENT;
- }
- spec->offset = entry->start;
- spec->length = entry->length;
- break;
- #endif
- #if STM32MP_SPI_NOR
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_SPI:
- if (image_id == FWU_METADATA_IMAGE_ID) {
- spec->offset = STM32MP_NOR_METADATA1_OFFSET;
- } else {
- spec->offset = STM32MP_NOR_METADATA2_OFFSET;
- }
- spec->length = sizeof(struct fwu_metadata);
- break;
- #endif
- #if (STM32MP_RAW_NAND || STM32MP_SPI_NAND)
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC:
- case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_SPI:
- if (image_id == FWU_METADATA_IMAGE_ID) {
- spec->offset = STM32MP_NAND_METADATA1_OFFSET;
- } else {
- spec->offset = STM32MP_NAND_METADATA2_OFFSET;
- }
- spec->length = sizeof(struct fwu_metadata);
- break;
- #endif
- default:
- panic();
- break;
- }
- *image_spec = policy->image_spec;
- *handle = *policy->dev_handle;
- return 0;
- }
- int plat_fwu_set_metadata_image_source(unsigned int image_id,
- uintptr_t *handle,
- uintptr_t *image_spec)
- {
- assert((image_id == FWU_METADATA_IMAGE_ID) ||
- (image_id == BKUP_FWU_METADATA_IMAGE_ID));
- return set_metadata_image_source(image_id, handle, image_spec);
- }
- #endif /* PSA_FWU_SUPPORT */
|