Browse Source

Merge changes from topic "st-nand-backup-fwu" into integration

* changes:
  refactor(st): rename plat_set_image_source
  feat(st): add FWU with boot from NAND
  feat(st): manage backup partitions for NAND devices
  feat(bl): add plat handler for image loading
  refactor(bl)!: remove unused plat_try_next_boot_source
pull/2000/merge
Manish V Badarkhe 5 months ago
committed by TrustedFirmware Code Review
parent
commit
08fc380ab3
  1. 22
      common/bl_common.c
  2. 57
      docs/porting-guide.rst
  3. 12
      include/plat/common/platform.h
  4. 11
      plat/common/aarch32/plat_common.c
  5. 8
      plat/common/aarch64/plat_common.c
  6. 8
      plat/common/plat_bl_common.c
  7. 98
      plat/st/common/bl2_io_storage.c
  8. 10
      plat/st/common/stm32mp_fconf_io.c

22
common/bl_common.c

@ -211,18 +211,18 @@ int load_auth_image(unsigned int image_id, image_info_t *image_data)
{
int err;
/*
* All firmware banks should be part of the same non-volatile storage as per
* PSA FWU specification, hence don't check for any alternate boot source
* when PSA FWU is enabled.
*/
#if PSA_FWU_SUPPORT
err = load_auth_image_internal(image_id, image_data);
#else
do {
if ((plat_try_img_ops == NULL) || (plat_try_img_ops->next_instance == NULL)) {
err = load_auth_image_internal(image_id, image_data);
} while ((err != 0) && (plat_try_next_boot_source() != 0));
#endif /* PSA_FWU_SUPPORT */
} else {
do {
err = load_auth_image_internal(image_id, image_data);
if (err != 0) {
if (plat_try_img_ops->next_instance(image_id) != 0) {
return err;
}
}
} while (err != 0);
}
if (err == 0) {
/*

57
docs/porting-guide.rst

@ -1518,6 +1518,40 @@ When CONDITIONAL_CMO flag is enabled:
- The function must not clobber x1, x2 and x3. It's also not safe to rely on
stack. Otherwise obey AAPCS.
Struct: plat_try_images_ops [optional]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This optional structure holds platform hooks for alternative images load.
It has to be defined in platform code and registered by calling
plat_setup_try_img_ops() function, passing it the address of the
plat_try_images_ops struct.
Function : plat_setup_try_img_ops [optional]
............................................
::
Argument : const struct plat_try_images_ops *
Return : void
This optional function is called to register platform try images ops, given
as argument.
Function : plat_try_images_ops.next_instance [optional]
.......................................................
::
Argument : unsigned int image_id
Return : int
This optional function tries to load images from alternative places.
In case PSA FWU is not used, it can be any instance or media. If PSA FWU is
used, it is mandatory that the backup image is on the same media.
This is required for MTD devices like NAND.
The argument is the ID of the image for which we are looking for an alternative
place. It returns 0 in case of success and a negative errno value otherwise.
Modifications specific to a Boot Loader stage
---------------------------------------------
@ -1607,9 +1641,6 @@ This function executes with the MMU and data caches enabled. It is responsible
for performing any remaining platform-specific setup that can occur after the
MMU and data cache have been enabled.
if support for multiple boot sources is required, it initializes the boot
sequence used by plat_try_next_boot_source().
In Arm standard platforms, this function initializes the storage abstraction
layer used to load the next bootloader image.
@ -1892,25 +1923,7 @@ Function : bl2_plat_preload_setup [optional]
This optional function performs any BL2 platform initialization
required before image loading, that is not done later in
bl2_platform_setup(). Specifically, if support for multiple
boot sources is required, it initializes the boot sequence used by
plat_try_next_boot_source().
Function : plat_try_next_boot_source() [optional]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
Argument : void
Return : int
This optional function passes to the next boot source in the redundancy
sequence.
This function moves the current boot redundancy source to the next
element in the boot sequence. If there are no more boot sources then it
must return 0, otherwise it must return 1. The default implementation
of this always returns 0.
bl2_platform_setup().
Boot Loader Stage 2 (BL2) at EL3
--------------------------------

12
include/plat/common/platform.h

@ -40,6 +40,16 @@ struct sp_res_desc;
struct rmm_manifest;
enum fw_enc_status_t;
/*******************************************************************************
* Structure populated by platform specific code to export routines which
* perform load images functions, and associated pointer to platform ops
******************************************************************************/
struct plat_try_images_ops {
int (*next_instance)(unsigned int image_id);
};
extern const struct plat_try_images_ops *plat_try_img_ops;
/*******************************************************************************
* plat_get_rotpk_info() flags
******************************************************************************/
@ -154,7 +164,7 @@ void plat_panic_handler(void) __dead2;
void plat_system_reset(void) __dead2;
const char *plat_log_get_prefix(unsigned int log_level);
void bl2_plat_preload_setup(void);
int plat_try_next_boot_source(void);
void plat_setup_try_img_ops(const struct plat_try_images_ops *plat_try_ops);
#if MEASURED_BOOT
int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data);

11
plat/common/aarch32/plat_common.c

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2016-2024, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -7,6 +7,14 @@
#include <lib/xlat_tables/xlat_mmu_helpers.h>
#include <plat/common/platform.h>
/* Pointer and function to register platform function to load alernate images */
const struct plat_try_images_ops *plat_try_img_ops;
void plat_setup_try_img_ops(const struct plat_try_images_ops *plat_try_ops)
{
plat_try_img_ops = plat_try_ops;
}
/*
* The following platform setup functions are weakly defined. They
* provide typical implementations that may be re-used by multiple
@ -14,7 +22,6 @@
*/
#pragma weak bl32_plat_enable_mmu
void bl32_plat_enable_mmu(uint32_t flags)
{
enable_mmu_svc_mon(flags);

8
plat/common/aarch64/plat_common.c

@ -17,6 +17,14 @@
#include <lib/xlat_tables/xlat_mmu_helpers.h>
#include <plat/common/platform.h>
/* Pointer and function to register platform function to load alernate images */
const struct plat_try_images_ops *plat_try_img_ops;
void plat_setup_try_img_ops(const struct plat_try_images_ops *plat_try_ops)
{
plat_try_img_ops = plat_try_ops;
}
/*
* The following platform setup functions are weakly defined. They
* provide typical implementations that may be re-used by multiple

8
plat/common/plat_bl_common.c

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2018-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -24,7 +24,6 @@
#pragma weak bl2_plat_preload_setup
#pragma weak bl2_plat_handle_pre_image_load
#pragma weak bl2_plat_handle_post_image_load
#pragma weak plat_try_next_boot_source
#pragma weak plat_get_enc_key_info
#pragma weak plat_is_smccc_feature_available
#pragma weak plat_get_soc_version
@ -69,11 +68,6 @@ int bl2_plat_handle_post_image_load(unsigned int image_id)
return 0;
}
int plat_try_next_boot_source(void)
{
return 0;
}
/*
* Weak implementation to provide dummy decryption key only for test purposes,
* platforms must override this API for any real world firmware encryption

98
plat/st/common/bl2_io_storage.c

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2023, Arm Limited and Contributors. All rights reserved.
* Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -47,6 +47,7 @@ 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;
@ -310,11 +311,55 @@ static void boot_spi_nor(boot_api_context_t *boot_context)
}
#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);
@ -326,6 +371,8 @@ static void boot_fmc2_nand(boot_api_context_t *boot_context)
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 */
@ -334,6 +381,8 @@ 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);
@ -345,6 +394,8 @@ static void boot_spi_nand(boot_api_context_t *boot_context)
(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 */
@ -530,7 +581,14 @@ int bl2_plat_handle_pre_image_load(unsigned int image_id)
#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
@ -596,7 +654,7 @@ int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
return rc;
}
#if (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT
#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.
@ -709,6 +767,19 @@ void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
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();
@ -717,9 +788,9 @@ void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
}
}
static int plat_set_image_source(unsigned int image_id,
uintptr_t *handle,
uintptr_t *image_spec)
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;
@ -762,6 +833,19 @@ static int plat_set_image_source(unsigned int image_id,
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;
@ -780,6 +864,6 @@ int plat_fwu_set_metadata_image_source(unsigned int image_id,
assert((image_id == FWU_METADATA_IMAGE_ID) ||
(image_id == BKUP_FWU_METADATA_IMAGE_ID));
return plat_set_image_source(image_id, handle, image_spec);
return set_metadata_image_source(image_id, handle, image_spec);
}
#endif /* (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT */
#endif /* PSA_FWU_SUPPORT */

10
plat/st/common/stm32mp_fconf_io.c

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2023, STMicroelectronics - All Rights Reserved
* Copyright (c) 2021-2024, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -27,12 +27,12 @@ static io_block_spec_t gpt_block_spec = {
};
#endif
#if (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT
#if PSA_FWU_SUPPORT
static io_block_spec_t metadata_block_spec = {
.offset = 0, /* To be filled at runtime */
.length = 0, /* To be filled at runtime */
};
#endif /* (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT */
#endif /* PSA_FWU_SUPPORT */
/* By default, STM32 platforms load images from the FIP */
struct plat_io_policy policies[MAX_NUMBER_IDS] = {
@ -58,7 +58,7 @@ struct plat_io_policy policies[MAX_NUMBER_IDS] = {
.check = open_storage
},
#endif
#if (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT
#if PSA_FWU_SUPPORT
[FWU_METADATA_IMAGE_ID] = {
.dev_handle = &storage_dev_handle,
.image_spec = (uintptr_t)&metadata_block_spec,
@ -71,7 +71,7 @@ struct plat_io_policy policies[MAX_NUMBER_IDS] = {
.img_type_guid = NULL_GUID,
.check = open_storage
},
#endif /* (STM32MP_SDMMC || STM32MP_EMMC || STM32MP_SPI_NOR) && PSA_FWU_SUPPORT */
#endif /* PSA_FWU_SUPPORT */
};
#define DEFAULT_UUID_NUMBER U(7)

Loading…
Cancel
Save