Merge changes from topic "fwu-on-stm32mp1" into integration

* changes:
  feat(stm32mp1): add support for building the FWU feature
  feat(stm32mp1): add logic to pass the boot index to the Update Agent
  feat(stm32mp1): add support for reading the metadata partition
  feat(stm32mp1): add logic to select the images to be booted
  feat(stm32mp1): add GUID's for identifying firmware images to be booted
  feat(stm32mp1): add GUID values for updatable images
  feat(fwu): add platform hook for getting the boot index
  feat(fwu): simplify the assert to check for fwu init
  feat(fwu): add a function to pass metadata structure to platforms
  feat(partition): add a function to identify a partition by GUID
  feat(partition): copy the partition GUID into the partition structure
  feat(partition): make provision to store partition GUID value
  feat(partition): cleanup partition and gpt headers
  feat(fwu): add basic definitions for GUID handling
  feat(fwu): pass a const metadata structure to platform routines
  build(changelog): add a valid scope for partition code
This commit is contained in:
Madhukar Pappireddy 2022-01-27 15:49:15 +01:00 committed by TrustedFirmware Code Review
commit 222eb8c7f9
20 changed files with 315 additions and 17 deletions

View File

@ -566,6 +566,9 @@ subsections:
deprecated:
- spi_nand
- title: Partition
scope: partition
- title: SCMI
scope: scmi

View File

@ -889,7 +889,7 @@ Function : plat_fwu_set_images_source() [when PSA_FWU_SUPPORT == 1]
::
Argument : struct fwu_metadata *metadata
Argument : const struct fwu_metadata *metadata
Return : void
This function is mandatory when PSA_FWU_SUPPORT is enabled.
@ -932,6 +932,25 @@ It returns '0' on success, otherwise a negative error value on error.
Alongside, returns device handle and image specification from the I/O policy
of the requested FWU metadata image.
Function : plat_fwu_get_boot_idx() [when PSA_FWU_SUPPORT == 1]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
::
Argument : void
Return : uint32_t
This function is mandatory when PSA_FWU_SUPPORT is enabled. It provides the
means to retrieve the boot index value from the platform. The boot index is the
bank from which the platform has booted the firmware images.
By default, the platform will read the metadata structure and try to boot from
the active bank. If the platform fails to boot from the active bank due to
reasons like an Authentication failure, or on crossing a set number of watchdog
resets while booting from the active bank, the platform can then switch to boot
from a different bank. This function then returns the bank that the platform
should boot its images from.
Common optional modifications
-----------------------------

View File

@ -142,7 +142,7 @@ bool fwu_is_trial_run_state(void)
{
bool trial_run = false;
assert(is_fwu_initialized == true);
assert(is_fwu_initialized);
for (unsigned int i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
struct fwu_image_entry *entry = &metadata.img_entry[i];
@ -157,6 +157,13 @@ bool fwu_is_trial_run_state(void)
return trial_run;
}
const struct fwu_metadata *fwu_get_metadata(void)
{
assert(is_fwu_initialized);
return &metadata;
}
/*******************************************************************************
* Load verified copy of FWU metadata image kept in the platform NV storage
* into local FWU metadata structure.

View File

@ -9,6 +9,7 @@
#include <string.h>
#include <common/debug.h>
#include <drivers/partition/efi.h>
#include <drivers/partition/gpt.h>
#include <lib/utils.h>
@ -57,5 +58,7 @@ int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry)
entry->length = (uint64_t)(gpt_entry->last_lba -
gpt_entry->first_lba + 1) *
PLAT_PARTITION_BLOCK_SIZE;
guidcpy(&entry->part_guid, &gpt_entry->unique_uuid);
return 0;
}

View File

@ -11,6 +11,7 @@
#include <common/debug.h>
#include <drivers/io/io_storage.h>
#include <drivers/partition/efi.h>
#include <drivers/partition/partition.h>
#include <drivers/partition/gpt.h>
#include <drivers/partition/mbr.h>
@ -246,6 +247,19 @@ const partition_entry_t *get_partition_entry(const char *name)
return NULL;
}
const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid)
{
int i;
for (i = 0; i < list.entry_count; i++) {
if (guidcmp(part_uuid, &list.list[i].part_guid) == 0) {
return &list.list[i];
}
}
return NULL;
}
const partition_entry_list_t *get_partition_entry_list(void)
{
return &list;

View File

@ -11,5 +11,6 @@
void fwu_init(void);
bool fwu_is_trial_run_state(void);
const struct fwu_metadata *fwu_get_metadata(void);
#endif /* FWU_H */

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2021, Linaro Limited
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#ifndef DRIVERS_PARTITION_EFI_H
#define DRIVERS_PARTITION_EFI_H
#include <string.h>
#include <tools_share/uuid.h>
#define EFI_NAMELEN 36
static inline int guidcmp(const void *g1, const void *g2)
{
return memcmp(g1, g2, sizeof(struct efi_guid));
}
static inline void *guidcpy(void *dst, const void *src)
{
return memcpy(dst, src, sizeof(struct efi_guid));
}
#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
{ (a) & 0xffffffff, \
(b) & 0xffff, \
(c) & 0xffff, \
{ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) } }
#define NULL_GUID \
EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
#endif /* DRIVERS_PARTITION_EFI_H */

View File

@ -7,19 +7,20 @@
#ifndef GPT_H
#define GPT_H
#include <drivers/partition/efi.h>
#include <drivers/partition/partition.h>
#include <tools_share/uuid.h>
#define PARTITION_TYPE_GPT 0xee
#define GPT_HEADER_OFFSET PLAT_PARTITION_BLOCK_SIZE
#define GPT_ENTRY_OFFSET (GPT_HEADER_OFFSET + \
PLAT_PARTITION_BLOCK_SIZE)
#define GUID_LEN 16
#define GPT_SIGNATURE "EFI PART"
typedef struct gpt_entry {
unsigned char type_uuid[GUID_LEN];
unsigned char unique_uuid[GUID_LEN];
struct efi_guid type_uuid;
struct efi_guid unique_uuid;
unsigned long long first_lba;
unsigned long long last_lba;
unsigned long long attr;
@ -36,7 +37,7 @@ typedef struct gpt_header {
unsigned long long backup_lba;
unsigned long long first_lba;
unsigned long long last_lba;
unsigned char disk_uuid[16];
struct efi_guid disk_uuid;
/* starting LBA of array of partition entries */
unsigned long long part_lba;
/* number of partition entries in array */

View File

@ -10,6 +10,8 @@
#include <stdint.h>
#include <lib/cassert.h>
#include <drivers/partition/efi.h>
#include <tools_share/uuid.h>
#if !PLAT_PARTITION_MAX_ENTRIES
# define PLAT_PARTITION_MAX_ENTRIES 128
@ -27,12 +29,11 @@ CASSERT((PLAT_PARTITION_BLOCK_SIZE == 512) ||
#define LEGACY_PARTITION_BLOCK_SIZE 512
#define EFI_NAMELEN 36
typedef struct partition_entry {
uint64_t start;
uint64_t length;
char name[EFI_NAMELEN];
struct efi_guid part_guid;
} partition_entry_t;
typedef struct partition_entry_list {
@ -42,6 +43,7 @@ typedef struct partition_entry_list {
int load_partition_table(unsigned int image_id);
const partition_entry_t *get_partition_entry(const char *name);
const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid);
const partition_entry_list_t *get_partition_entry_list(void);
void partition_init(unsigned int image_id);

View File

@ -389,6 +389,7 @@ int32_t plat_is_smccc_feature_available(u_register_t fid);
int plat_fwu_set_metadata_image_source(unsigned int image_id,
uintptr_t *dev_handle,
uintptr_t *image_spec);
void plat_fwu_set_images_source(struct fwu_metadata *metadata);
void plat_fwu_set_images_source(const struct fwu_metadata *metadata);
uint32_t plat_fwu_get_boot_idx(void);
#endif /* PLATFORM_H */

View File

@ -217,7 +217,7 @@ void arm_set_fip_addr(uint32_t active_fw_bank_idx)
* bank to get its offset and length, and update these details in the I/O policy
* of the FIP image.
******************************************************************************/
void plat_fwu_set_images_source(struct fwu_metadata *metadata)
void plat_fwu_set_images_source(const struct fwu_metadata *metadata)
{
arm_set_fip_addr(metadata->active_index);
}

View File

@ -10,6 +10,8 @@
#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_fip.h>
@ -17,6 +19,7 @@
#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>
@ -384,6 +387,12 @@ int bl2_plat_handle_pre_image_load(unsigned int image_id)
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
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;
partition_init(GPT_IMAGE_ID);
@ -396,7 +405,7 @@ int bl2_plat_handle_pre_image_load(unsigned int image_id)
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);
@ -473,3 +482,117 @@ int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle,
return rc;
}
#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
/*
* Eventually, this function will return the
* boot index to be passed on to the Update
* Agent after performing certain checks like
* a watchdog timeout, or Auth failure while
* trying to load from a certain bank.
* For now, since we do not have that logic
* implemented, just pass the active_index
* read from the metadata.
*/
uint32_t plat_fwu_get_boot_idx(void)
{
const struct fwu_metadata *metadata;
metadata = fwu_get_metadata();
return metadata->active_index;
}
static void *stm32_get_image_spec(const uuid_t *img_type_uuid)
{
unsigned int i;
for (i = 0U; i < MAX_NUMBER_IDS; i++) {
if ((guidcmp(&policies[i].img_type_guid, img_type_uuid)) == 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;
const uuid_t *img_type_uuid, *img_uuid;
io_block_spec_t *image_spec;
boot_idx = plat_fwu_get_boot_idx();
assert(boot_idx < NR_OF_FW_BANKS);
for (i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) {
img_type_uuid = &metadata->img_entry[i].img_type_uuid;
image_spec = stm32_get_image_spec(img_type_uuid);
if (image_spec == NULL) {
ERROR("Unable to get image spec for the image in the metadata\n");
panic();
}
img_uuid =
&metadata->img_entry[i].img_props[boot_idx].img_uuid;
entry = get_partition_entry_by_uuid(img_uuid);
if (entry == NULL) {
ERROR("Unable to find the partition with the uuid mentioned in metadata\n");
panic();
}
image_spec->offset = entry->start;
image_spec->length = entry->length;
}
}
static int plat_set_image_source(unsigned int image_id,
uintptr_t *handle,
uintptr_t *image_spec,
const char *part_name)
{
struct plat_io_policy *policy;
io_block_spec_t *spec;
const partition_entry_t *entry = get_partition_entry(part_name);
if (entry == NULL) {
ERROR("Unable to find the %s partition\n", part_name);
return -ENOENT;
}
policy = &policies[image_id];
spec = (io_block_spec_t *)policy->image_spec;
spec->offset = entry->start;
spec->length = entry->length;
*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)
{
char *part_name;
assert((image_id == FWU_METADATA_IMAGE_ID) ||
(image_id == BKUP_FWU_METADATA_IMAGE_ID));
partition_init(GPT_IMAGE_ID);
if (image_id == FWU_METADATA_IMAGE_ID) {
part_name = METADATA_PART_1;
} else {
part_name = METADATA_PART_2;
}
return plat_set_image_source(image_id, handle, image_spec,
part_name);
}
#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */

View File

@ -113,4 +113,8 @@ int stm32mp_unmap_ddr(void);
void stm32_save_boot_interface(uint32_t interface, uint32_t instance);
void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance);
#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT
void stm32mp1_fwu_set_boot_idx(void);
#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */
#endif /* STM32MP_COMMON_H */

View File

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Copyright (c) 2021, Linaro Limited
*/
#ifndef STM32MP_EFI_H
#define STM32MP_EFI_H
#include <drivers/partition/efi.h>
#define STM32MP_FIP_GUID \
EFI_GUID(0x19d5df83, 0x11b0, 0x457b, \
0xbe, 0x2c, 0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5)
#endif /* STM32MP_EFI_H */

View File

@ -10,6 +10,7 @@
#include <assert.h>
#include <lib/fconf/fconf.h>
#include <tools_share/uuid.h>
/* IO policies */
#define stm32mp__io_policies_getter(id) __extension__ ({ \
@ -20,6 +21,7 @@
struct plat_io_policy {
uintptr_t *dev_handle;
uintptr_t image_spec;
struct efi_guid img_type_guid;
int (*check)(const uintptr_t spec);
};

View File

@ -16,6 +16,7 @@
#include <tools_share/firmware_image_package.h>
#include <platform_def.h>
#include <stm32mp_efi.h>
#include <stm32mp_fconf_getter.h>
#include <stm32mp_io_storage.h>
@ -26,20 +27,43 @@ static io_block_spec_t gpt_block_spec = {
};
#endif
#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
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) && PSA_FWU_SUPPORT */
/* By default, STM32 platforms load images from the FIP */
struct plat_io_policy policies[MAX_NUMBER_IDS] = {
[FIP_IMAGE_ID] = {
&storage_dev_handle,
(uintptr_t)&image_block_spec,
open_storage
.dev_handle = &storage_dev_handle,
.image_spec = (uintptr_t)&image_block_spec,
.img_type_guid = STM32MP_FIP_GUID,
.check = open_storage
},
#if STM32MP_SDMMC || STM32MP_EMMC
[GPT_IMAGE_ID] = {
&storage_dev_handle,
(uintptr_t)&gpt_block_spec,
open_storage
.dev_handle = &storage_dev_handle,
.image_spec = (uintptr_t)&gpt_block_spec,
.img_type_guid = NULL_GUID,
.check = open_storage
},
#endif
#if (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT
[FWU_METADATA_IMAGE_ID] = {
.dev_handle = &storage_dev_handle,
.image_spec = (uintptr_t)&metadata_block_spec,
.img_type_guid = NULL_GUID,
.check = open_storage
},
[BKUP_FWU_METADATA_IMAGE_ID] = {
.dev_handle = &storage_dev_handle,
.image_spec = (uintptr_t)&metadata_block_spec,
.img_type_guid = NULL_GUID,
.check = open_storage
},
#endif /* (STM32MP_SDMMC || STM32MP_EMMC) && PSA_FWU_SUPPORT */
};
#define FCONF_ST_IO_UUID_NUMBER U(8)

View File

@ -30,6 +30,7 @@
#include <plat/common/platform.h>
#include <platform_def.h>
#include <stm32mp_common.h>
#include <stm32mp1_dbgmcu.h>
static struct stm32mp_auth_ops stm32mp1_auth_ops;
@ -452,6 +453,9 @@ int bl2_plat_handle_post_image_load(unsigned int image_id)
bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
assert(bl32_mem_params != NULL);
bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT
stm32mp1_fwu_set_boot_idx();
#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */
break;
default:

View File

@ -40,6 +40,9 @@
#define BL33_BINARY_TYPE U(0x0)
#else /* STM32MP_USE_STM32IMAGE */
#define FIP_IMAGE_NAME "fip"
#define METADATA_PART_1 "metadata1"
#define METADATA_PART_2 "metadata2"
#endif /* STM32MP_USE_STM32IMAGE */
#define STM32MP_PRIMARY_CPU U(0x0)

View File

@ -38,6 +38,20 @@ TF_CFLAGS += -Wsign-compare
# Not needed for Cortex-A7
WORKAROUND_CVE_2017_5715:= 0
ifeq (${PSA_FWU_SUPPORT},1)
ifneq (${STM32MP_USE_STM32IMAGE},1)
# Number of banks of updatable firmware
NR_OF_FW_BANKS := 2
NR_OF_IMAGES_IN_FW_BANK := 1
# Number of TF-A copies in the device
STM32_TF_A_COPIES := 2
STM32_BL33_PARTS_NUM := 2
STM32_RUNTIME_PARTS_NUM := 4
else
$(error FWU Feature enabled only with FIP images)
endif
else
# Number of TF-A copies in the device
STM32_TF_A_COPIES := 2
STM32_BL33_PARTS_NUM := 1
@ -48,6 +62,7 @@ STM32_RUNTIME_PARTS_NUM := 0
else
STM32_RUNTIME_PARTS_NUM := 1
endif
endif
PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + \
$(STM32_BL33_PARTS_NUM) + \
$(STM32_RUNTIME_PARTS_NUM))))
@ -237,6 +252,13 @@ BL2_SOURCES += drivers/io/io_dummy.c \
plat/st/stm32mp1/stm32mp1_security.c
endif
ifeq (${PSA_FWU_SUPPORT},1)
include lib/zlib/zlib.mk
include drivers/fwu/fwu.mk
BL2_SOURCES += $(ZLIB_SOURCES)
endif
BL2_SOURCES += drivers/io/io_block.c \
drivers/io/io_mtd.c \
drivers/io/io_storage.c \

View File

@ -13,6 +13,7 @@
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <libfdt.h>
#include <plat/common/platform.h>
#include <platform_def.h>
/* Internal layout of the 32bit OTP word board_id */
@ -40,6 +41,8 @@
#define TAMP_BOOT_MODE_ITF_MASK U(0x0000FF00)
#define TAMP_BOOT_MODE_ITF_SHIFT 8
#define TAMP_BOOT_COUNTER_REG_ID U(21)
#if defined(IMAGE_BL2)
#define MAP_SEC_SYSRAM MAP_REGION_FLAT(STM32MP_SYSRAM_BASE, \
STM32MP_SYSRAM_SIZE, \
@ -597,3 +600,13 @@ void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance)
*interface = itf >> 4;
*instance = itf & 0xFU;
}
#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT
void stm32mp1_fwu_set_boot_idx(void)
{
clk_enable(RTCAPB);
mmio_write_32(tamp_bkpr(TAMP_BOOT_COUNTER_REG_ID),
plat_fwu_get_boot_idx());
clk_disable(RTCAPB);
}
#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */