Merge changes from topic "st_fip_fconf" into integration

* changes:
  feat(io_mtd): offset management for FIP usage
  feat(nand): count bad blocks before a given offset
  feat(plat/st): add helper to save boot interface
  fix(plat/st): improve DDR get size function
  refactor(plat/st): map DDR secure at boot
  refactor(plat/st): rework TZC400 configuration
This commit is contained in:
Manish Pandey 2021-08-13 00:22:55 +02:00 committed by TrustedFirmware Code Review
commit e528bc22eb
9 changed files with 205 additions and 72 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -18,8 +18,9 @@
typedef struct {
io_mtd_dev_spec_t *dev_spec;
uintptr_t base;
unsigned long long offset; /* Offset in bytes */
unsigned long long size; /* Size of device in bytes */
unsigned long long pos; /* Offset in bytes */
unsigned long long size; /* Size of device in bytes */
unsigned long long extra_offset; /* Extra offset in bytes */
} mtd_dev_state_t;
io_type_t device_type_mtd(void);
@ -110,16 +111,47 @@ static int free_dev_info(io_dev_info_t *dev_info)
return 0;
}
static int mtd_add_extra_offset(mtd_dev_state_t *cur, size_t *extra_offset)
{
io_mtd_ops_t *ops = &cur->dev_spec->ops;
int ret;
if (ops->seek == NULL) {
return 0;
}
ret = ops->seek(cur->base, cur->pos, extra_offset);
if (ret != 0) {
ERROR("%s: Seek error %d\n", __func__, ret);
return ret;
}
return 0;
}
static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec,
io_entity_t *entity)
{
mtd_dev_state_t *cur;
io_block_spec_t *region;
size_t extra_offset = 0U;
int ret;
assert((dev_info->info != 0UL) && (entity->info == 0UL));
region = (io_block_spec_t *)spec;
cur = (mtd_dev_state_t *)dev_info->info;
entity->info = (uintptr_t)cur;
cur->offset = 0U;
cur->base = region->offset;
cur->pos = 0U;
cur->extra_offset = 0U;
ret = mtd_add_extra_offset(cur, &extra_offset);
if (ret != 0) {
return ret;
}
cur->base += extra_offset;
return 0;
}
@ -128,6 +160,8 @@ static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec,
static int mtd_seek(io_entity_t *entity, int mode, signed long long offset)
{
mtd_dev_state_t *cur;
size_t extra_offset = 0U;
int ret;
assert((entity->info != (uintptr_t)NULL) && (offset >= 0));
@ -140,22 +174,29 @@ static int mtd_seek(io_entity_t *entity, int mode, signed long long offset)
return -EINVAL;
}
cur->offset = offset;
cur->pos = offset;
break;
case IO_SEEK_CUR:
if (((cur->offset + (unsigned long long)offset) >=
if (((cur->base + cur->pos + (unsigned long long)offset) >=
cur->size) ||
((cur->offset + (unsigned long long)offset) <
cur->offset)) {
((cur->base + cur->pos + (unsigned long long)offset) <
cur->base + cur->pos)) {
return -EINVAL;
}
cur->offset += (unsigned long long)offset;
cur->pos += (unsigned long long)offset;
break;
default:
return -EINVAL;
}
ret = mtd_add_extra_offset(cur, &extra_offset);
if (ret != 0) {
return ret;
}
cur->extra_offset = extra_offset;
return 0;
}
@ -174,18 +215,19 @@ static int mtd_read(io_entity_t *entity, uintptr_t buffer, size_t length,
assert(ops->read != NULL);
VERBOSE("Read at %llx into %lx, length %zi\n",
cur->offset, buffer, length);
if ((cur->offset + length) > cur->dev_spec->device_size) {
cur->base + cur->pos, buffer, length);
if ((cur->base + cur->pos + length) > cur->dev_spec->device_size) {
return -EINVAL;
}
ret = ops->read(cur->offset, buffer, length, out_length);
ret = ops->read(cur->base + cur->pos + cur->extra_offset, buffer,
length, out_length);
if (ret < 0) {
return ret;
}
assert(*out_length == length);
cur->offset += *out_length;
cur->pos += *out_length;
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, STMicroelectronics - All Rights Reserved
* Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -112,6 +112,47 @@ int nand_read(unsigned int offset, uintptr_t buffer, size_t length,
return 0;
}
int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset)
{
unsigned int block;
unsigned int offset_block;
unsigned int max_block;
int is_bad;
size_t count_bb = 0U;
block = base / nand_dev.block_size;
if (offset != 0U) {
offset_block = (base + offset - 1U) / nand_dev.block_size;
} else {
offset_block = block;
}
max_block = nand_dev.size / nand_dev.block_size;
while (block <= offset_block) {
if (offset_block >= max_block) {
return -EIO;
}
is_bad = nand_dev.mtd_block_is_bad(block);
if (is_bad < 0) {
return is_bad;
}
if (is_bad == 1) {
count_bb++;
offset_block++;
}
block++;
}
*extra_offset = count_bb * nand_dev.block_size;
return 0;
}
struct nand_device *get_nand_device(void)
{
return &nand_dev;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
* Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -44,11 +44,22 @@ typedef struct io_mtd_ops {
* Return 0 on success, a negative error code otherwise.
*/
int (*write)(unsigned int offset, uintptr_t buffer, size_t length);
/*
* Look for an offset to be added to the given offset.
*
* @base: Base address of the area.
* @offset: Offset in bytes to start read operation.
* @extra_offset: [out] Offset to be added to the previous offset.
* Return 0 on success, a negative error code otherwise.
*/
int (*seek)(uintptr_t base, unsigned int offset, size_t *extra_offset);
} io_mtd_ops_t;
typedef struct io_mtd_dev_spec {
unsigned long long device_size;
unsigned int erase_size;
size_t offset;
io_mtd_ops_t ops;
} io_mtd_dev_spec_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, STMicroelectronics - All Rights Reserved
* Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@ -45,6 +45,16 @@ struct nand_device {
int nand_read(unsigned int offset, uintptr_t buffer, size_t length,
size_t *length_read);
/*
* Look for an extra offset to be added in case of bad blocks
*
* @base: Base address of the area
* @offset: Byte offset to read from in device
* @extra_offset: [out] Extra offset to be added if bad blocks are found
* Return: 0 on success, a negative errno on failure
*/
int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset);
/*
* Get NAND device instance
*

View File

@ -17,6 +17,7 @@
/* Functions to save and get boot context address given by ROM code */
void stm32mp_save_boot_ctx_address(uintptr_t address);
uintptr_t stm32mp_get_boot_ctx_address(void);
uint16_t stm32mp_get_boot_itf_selected(void);
bool stm32mp_is_single_core(void);
bool stm32mp_is_closed_device(void);

View File

@ -28,10 +28,14 @@ unsigned int plat_get_syscnt_freq2(void)
}
static uintptr_t boot_ctx_address;
static uint16_t boot_itf_selected;
void stm32mp_save_boot_ctx_address(uintptr_t address)
{
boot_api_context_t *boot_context = (boot_api_context_t *)address;
boot_ctx_address = address;
boot_itf_selected = boot_context->boot_interface_selected;
}
uintptr_t stm32mp_get_boot_ctx_address(void)
@ -39,6 +43,11 @@ uintptr_t stm32mp_get_boot_ctx_address(void)
return boot_ctx_address;
}
uint16_t stm32mp_get_boot_itf_selected(void)
{
return boot_itf_selected;
}
uintptr_t stm32mp_ddrctrl_base(void)
{
return DDRCTRL_BASE;
@ -105,7 +114,7 @@ int stm32mp_map_ddr_non_cacheable(void)
{
return mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
STM32MP_DDR_MAX_SIZE,
MT_NON_CACHEABLE | MT_RW | MT_NS);
MT_NON_CACHEABLE | MT_RW | MT_SECURE);
}
int stm32mp_unmap_ddr(void)

View File

@ -209,15 +209,24 @@ int dt_get_stdout_uart_info(struct dt_node_info *info)
******************************************************************************/
uint32_t dt_get_ddr_size(void)
{
static uint32_t size;
int node;
if (size != 0U) {
return size;
}
node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT);
if (node < 0) {
INFO("%s: Cannot read DDR node in DT\n", __func__);
return 0;
}
return fdt_read_uint32_default(fdt, node, "st,mem-size", 0);
size = fdt_read_uint32_default(fdt, node, "st,mem-size", 0U);
flush_dcache_range((uintptr_t)&size, sizeof(uint32_t));
return size;
}
/*******************************************************************************

View File

@ -132,7 +132,6 @@ void bl2_el3_early_platform_setup(u_register_t arg0,
void bl2_platform_setup(void)
{
int ret;
uint32_t ddr_ns_size;
if (dt_pmic_status() > 0) {
initialize_pmic();
@ -144,24 +143,16 @@ void bl2_platform_setup(void)
panic();
}
ddr_ns_size = stm32mp_get_ddr_ns_size();
assert(ddr_ns_size > 0U);
/* Map non secure DDR for BL33 load, now with cacheable attribute */
/* Map DDR for binary load, now with cacheable attribute */
ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
ddr_ns_size, MT_MEMORY | MT_RW | MT_NS);
assert(ret == 0);
STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE);
if (ret < 0) {
ERROR("DDR mapping: error %d\n", ret);
panic();
}
#ifdef AARCH32_SP_OPTEE
INFO("BL2 runs OP-TEE setup\n");
/* Map secure DDR for OP-TEE paged area */
ret = mmap_add_dynamic_region(STM32MP_DDR_BASE + ddr_ns_size,
STM32MP_DDR_BASE + ddr_ns_size,
STM32MP_DDR_S_SIZE,
MT_MEMORY | MT_RW | MT_SECURE);
assert(ret == 0);
/* Initialize tzc400 after DDR initialization */
stm32mp1_security_setup();
#else

View File

@ -27,6 +27,45 @@
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)
static unsigned int region_nb;
static void init_tzc400_begin(unsigned int region0_attr)
{
tzc400_init(STM32MP1_TZC_BASE);
tzc400_disable_filters();
/* Region 0 set to cover all DRAM at 0xC000_0000 */
tzc400_configure_region0(region0_attr, 0);
region_nb = 1U;
}
static void init_tzc400_end(unsigned int action)
{
tzc400_set_action(action);
tzc400_enable_filters();
}
static void tzc400_add_region(unsigned long long region_base,
unsigned long long region_top, bool sec)
{
unsigned int sec_attr;
unsigned int nsaid_permissions;
if (sec) {
sec_attr = TZC_REGION_S_RDWR;
nsaid_permissions = 0;
} else {
sec_attr = TZC_REGION_S_NONE;
nsaid_permissions = TZC_REGION_NSEC_ALL_ACCESS_RDWR;
}
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, region_nb, region_base,
region_top, sec_attr, nsaid_permissions);
region_nb++;
}
/*******************************************************************************
* Initialize the TrustZone Controller. Configure Region 0 with Secure RW access
* and allow Non-Secure masters full access.
@ -38,10 +77,9 @@ static void init_tzc400(void)
unsigned long long ddr_ns_size =
(unsigned long long)stm32mp_get_ddr_ns_size();
unsigned long long ddr_ns_top = ddr_base + (ddr_ns_size - 1U);
unsigned long long ddr_top __unused;
tzc400_init(STM32MP1_TZC_BASE);
tzc400_disable_filters();
init_tzc400_begin(TZC_REGION_S_NONE);
/*
* Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the
@ -49,35 +87,28 @@ static void init_tzc400(void)
*/
region_base = ddr_base;
region_top = ddr_ns_top;
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
region_base,
region_top,
TZC_REGION_S_NONE,
TZC_REGION_NSEC_ALL_ACCESS_RDWR);
tzc400_add_region(region_base, region_top, false);
#ifdef AARCH32_SP_OPTEE
/* Region 2 set to cover all secure DRAM. */
region_base = region_top + 1U;
region_top += STM32MP_DDR_S_SIZE;
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2,
region_base,
region_top,
TZC_REGION_S_RDWR,
0);
tzc400_add_region(region_base, region_top, true);
/* Region 3 set to cover non-secure shared memory DRAM. */
region_base = region_top + 1U;
region_top += STM32MP_DDR_SHMEM_SIZE;
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3,
region_base,
region_top,
TZC_REGION_S_NONE,
TZC_REGION_NSEC_ALL_ACCESS_RDWR);
ddr_top = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U;
if (region_top < ddr_top) {
/* Region 3 set to cover non-secure memory DRAM after BL32. */
region_base = region_top + 1U;
region_top = ddr_top;
tzc400_add_region(region_base, region_top, false);
}
#endif
tzc400_set_action(TZC_ACTION_INT);
tzc400_enable_filters();
/*
* Raise an interrupt (secure FIQ) if a NS device tries to access
* secure memory
*/
init_tzc400_end(TZC_ACTION_INT);
}
/*******************************************************************************
@ -90,23 +121,11 @@ static void early_init_tzc400(void)
stm32mp_clk_enable(TZC1);
stm32mp_clk_enable(TZC2);
tzc400_init(STM32MP1_TZC_BASE);
tzc400_disable_filters();
/* Region 1 set to cover Non-Secure DRAM at 0xC000_0000 */
tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1,
STM32MP_DDR_BASE,
STM32MP_DDR_BASE +
(STM32MP_DDR_MAX_SIZE - 1U),
TZC_REGION_S_NONE,
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID));
/* Region 0 set to cover all DRAM secure at 0xC000_0000 */
init_tzc400_begin(TZC_REGION_S_RDWR);
/* Raise an exception if a NS device tries to access secure memory */
tzc400_set_action(TZC_ACTION_ERR);
tzc400_enable_filters();
init_tzc400_end(TZC_ACTION_ERR);
}
/*******************************************************************************