mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-18 02:24:18 +00:00
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:
commit
e528bc22eb
9 changed files with 205 additions and 72 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
Loading…
Add table
Reference in a new issue