GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <drivers/partition/partition.h>
|
||||
#include <lib/object_pool.h>
|
||||
#include <libfdt.h>
|
||||
#include <tools_share/firmware_image_package.h>
|
||||
|
||||
#include <plat/arm/common/arm_fconf_getter.h>
|
||||
#include <plat/arm/common/arm_fconf_io_storage.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#if PSA_FWU_SUPPORT
|
||||
/* metadata entry details */
|
||||
static io_block_spec_t fwu_metadata_spec;
|
||||
#endif /* PSA_FWU_SUPPORT */
|
||||
|
||||
io_block_spec_t fip_block_spec = {
|
||||
/*
|
||||
* This is fixed FIP address used by BL1, BL2 loads partition table
|
||||
* to get FIP address.
|
||||
*/
|
||||
#if ARM_GPT_SUPPORT
|
||||
.offset = PLAT_ARM_FLASH_IMAGE_BASE + PLAT_ARM_FIP_OFFSET_IN_GPT,
|
||||
#else
|
||||
.offset = PLAT_ARM_FLASH_IMAGE_BASE,
|
||||
#endif /* ARM_GPT_SUPPORT */
|
||||
.length = PLAT_ARM_FLASH_IMAGE_MAX_SIZE
|
||||
};
|
||||
|
||||
#if ARM_GPT_SUPPORT
|
||||
static const io_block_spec_t gpt_spec = {
|
||||
.offset = PLAT_ARM_FLASH_IMAGE_BASE,
|
||||
/*
|
||||
* PLAT_PARTITION_BLOCK_SIZE = 512
|
||||
* PLAT_PARTITION_MAX_ENTRIES = 128
|
||||
* each sector has 4 partition entries, and there are
|
||||
* 2 reserved sectors i.e. protective MBR and primary
|
||||
* GPT header hence length gets calculated as,
|
||||
* length = 512 * (128/4 + 2)
|
||||
*/
|
||||
.length = PLAT_PARTITION_BLOCK_SIZE *
|
||||
(PLAT_PARTITION_MAX_ENTRIES / 4 + 2),
|
||||
};
|
||||
#endif /* ARM_GPT_SUPPORT */
|
||||
|
||||
const io_uuid_spec_t arm_uuid_spec[MAX_NUMBER_IDS] = {
|
||||
[BL2_IMAGE_ID] = {UUID_TRUSTED_BOOT_FIRMWARE_BL2},
|
||||
[TB_FW_CONFIG_ID] = {UUID_TB_FW_CONFIG},
|
||||
[FW_CONFIG_ID] = {UUID_FW_CONFIG},
|
||||
#if !ARM_IO_IN_DTB
|
||||
[SCP_BL2_IMAGE_ID] = {UUID_SCP_FIRMWARE_SCP_BL2},
|
||||
[BL31_IMAGE_ID] = {UUID_EL3_RUNTIME_FIRMWARE_BL31},
|
||||
[BL32_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32},
|
||||
[BL32_EXTRA1_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32_EXTRA1},
|
||||
[BL32_EXTRA2_IMAGE_ID] = {UUID_SECURE_PAYLOAD_BL32_EXTRA2},
|
||||
[BL33_IMAGE_ID] = {UUID_NON_TRUSTED_FIRMWARE_BL33},
|
||||
[HW_CONFIG_ID] = {UUID_HW_CONFIG},
|
||||
[SOC_FW_CONFIG_ID] = {UUID_SOC_FW_CONFIG},
|
||||
[TOS_FW_CONFIG_ID] = {UUID_TOS_FW_CONFIG},
|
||||
[NT_FW_CONFIG_ID] = {UUID_NT_FW_CONFIG},
|
||||
[RMM_IMAGE_ID] = {UUID_REALM_MONITOR_MGMT_FIRMWARE},
|
||||
#endif /* ARM_IO_IN_DTB */
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
[TRUSTED_BOOT_FW_CERT_ID] = {UUID_TRUSTED_BOOT_FW_CERT},
|
||||
#if !ARM_IO_IN_DTB
|
||||
[CCA_CONTENT_CERT_ID] = {UUID_CCA_CONTENT_CERT},
|
||||
[CORE_SWD_KEY_CERT_ID] = {UUID_CORE_SWD_KEY_CERT},
|
||||
[PLAT_KEY_CERT_ID] = {UUID_PLAT_KEY_CERT},
|
||||
[TRUSTED_KEY_CERT_ID] = {UUID_TRUSTED_KEY_CERT},
|
||||
[SCP_FW_KEY_CERT_ID] = {UUID_SCP_FW_KEY_CERT},
|
||||
[SOC_FW_KEY_CERT_ID] = {UUID_SOC_FW_KEY_CERT},
|
||||
[TRUSTED_OS_FW_KEY_CERT_ID] = {UUID_TRUSTED_OS_FW_KEY_CERT},
|
||||
[NON_TRUSTED_FW_KEY_CERT_ID] = {UUID_NON_TRUSTED_FW_KEY_CERT},
|
||||
[SCP_FW_CONTENT_CERT_ID] = {UUID_SCP_FW_CONTENT_CERT},
|
||||
[SOC_FW_CONTENT_CERT_ID] = {UUID_SOC_FW_CONTENT_CERT},
|
||||
[TRUSTED_OS_FW_CONTENT_CERT_ID] = {UUID_TRUSTED_OS_FW_CONTENT_CERT},
|
||||
[NON_TRUSTED_FW_CONTENT_CERT_ID] = {UUID_NON_TRUSTED_FW_CONTENT_CERT},
|
||||
#if defined(SPD_spmd)
|
||||
[SIP_SP_CONTENT_CERT_ID] = {UUID_SIP_SECURE_PARTITION_CONTENT_CERT},
|
||||
[PLAT_SP_CONTENT_CERT_ID] = {UUID_PLAT_SECURE_PARTITION_CONTENT_CERT},
|
||||
#endif
|
||||
#endif /* ARM_IO_IN_DTB */
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
};
|
||||
|
||||
/* By default, ARM platforms load images from the FIP */
|
||||
struct plat_io_policy policies[MAX_NUMBER_IDS] = {
|
||||
#if ARM_GPT_SUPPORT
|
||||
[GPT_IMAGE_ID] = {
|
||||
&memmap_dev_handle,
|
||||
(uintptr_t)&gpt_spec,
|
||||
open_memmap
|
||||
},
|
||||
#endif /* ARM_GPT_SUPPORT */
|
||||
#if PSA_FWU_SUPPORT
|
||||
[FWU_METADATA_IMAGE_ID] = {
|
||||
&memmap_dev_handle,
|
||||
/* filled runtime from partition information */
|
||||
(uintptr_t)&fwu_metadata_spec,
|
||||
open_memmap
|
||||
},
|
||||
[BKUP_FWU_METADATA_IMAGE_ID] = {
|
||||
&memmap_dev_handle,
|
||||
/* filled runtime from partition information */
|
||||
(uintptr_t)&fwu_metadata_spec,
|
||||
open_memmap
|
||||
},
|
||||
#endif /* PSA_FWU_SUPPORT */
|
||||
[FIP_IMAGE_ID] = {
|
||||
&memmap_dev_handle,
|
||||
(uintptr_t)&fip_block_spec,
|
||||
open_memmap
|
||||
},
|
||||
[BL2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[BL2_IMAGE_ID],
|
||||
open_fip
|
||||
},
|
||||
[TB_FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[TB_FW_CONFIG_ID],
|
||||
open_fip
|
||||
},
|
||||
[FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[FW_CONFIG_ID],
|
||||
open_fip
|
||||
},
|
||||
#if !ARM_IO_IN_DTB
|
||||
[SCP_BL2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[SCP_BL2_IMAGE_ID],
|
||||
open_fip
|
||||
},
|
||||
[BL31_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[BL31_IMAGE_ID],
|
||||
open_fip
|
||||
},
|
||||
[BL32_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[BL32_IMAGE_ID],
|
||||
open_fip
|
||||
},
|
||||
[BL32_EXTRA1_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[BL32_EXTRA1_IMAGE_ID],
|
||||
open_fip
|
||||
},
|
||||
[BL32_EXTRA2_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[BL32_EXTRA2_IMAGE_ID],
|
||||
open_fip
|
||||
},
|
||||
[BL33_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[BL33_IMAGE_ID],
|
||||
open_fip
|
||||
},
|
||||
[RMM_IMAGE_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[RMM_IMAGE_ID],
|
||||
open_fip
|
||||
},
|
||||
[HW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[HW_CONFIG_ID],
|
||||
open_fip
|
||||
},
|
||||
[SOC_FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[SOC_FW_CONFIG_ID],
|
||||
open_fip
|
||||
},
|
||||
[TOS_FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[TOS_FW_CONFIG_ID],
|
||||
open_fip
|
||||
},
|
||||
[NT_FW_CONFIG_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[NT_FW_CONFIG_ID],
|
||||
open_fip
|
||||
},
|
||||
#endif /* ARM_IO_IN_DTB */
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
[TRUSTED_BOOT_FW_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[TRUSTED_BOOT_FW_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
#if !ARM_IO_IN_DTB
|
||||
[CCA_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[CCA_CONTENT_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[CORE_SWD_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[CORE_SWD_KEY_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[PLAT_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[PLAT_KEY_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[TRUSTED_KEY_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[SCP_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[SCP_FW_KEY_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[SOC_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[SOC_FW_KEY_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_OS_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[TRUSTED_OS_FW_KEY_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[NON_TRUSTED_FW_KEY_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[NON_TRUSTED_FW_KEY_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[SCP_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[SCP_FW_CONTENT_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[SOC_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[SOC_FW_CONTENT_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[TRUSTED_OS_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[TRUSTED_OS_FW_CONTENT_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[NON_TRUSTED_FW_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[NON_TRUSTED_FW_CONTENT_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
#if defined(SPD_spmd)
|
||||
[SIP_SP_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[SIP_SP_CONTENT_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
[PLAT_SP_CONTENT_CERT_ID] = {
|
||||
&fip_dev_handle,
|
||||
(uintptr_t)&arm_uuid_spec[PLAT_SP_CONTENT_CERT_ID],
|
||||
open_fip
|
||||
},
|
||||
#endif
|
||||
#endif /* ARM_IO_IN_DTB */
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
};
|
||||
|
||||
#ifdef IMAGE_BL2
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
#define FCONF_ARM_IO_UUID_NUMBER U(24)
|
||||
#else
|
||||
#define FCONF_ARM_IO_UUID_NUMBER U(10)
|
||||
#endif
|
||||
|
||||
static io_uuid_spec_t fconf_arm_uuids[FCONF_ARM_IO_UUID_NUMBER];
|
||||
static OBJECT_POOL_ARRAY(fconf_arm_uuids_pool, fconf_arm_uuids);
|
||||
|
||||
struct policies_load_info {
|
||||
unsigned int image_id;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
/* image id to property name table */
|
||||
static const struct policies_load_info load_info[FCONF_ARM_IO_UUID_NUMBER] = {
|
||||
{SCP_BL2_IMAGE_ID, "scp_bl2_uuid"},
|
||||
{BL31_IMAGE_ID, "bl31_uuid"},
|
||||
{BL32_IMAGE_ID, "bl32_uuid"},
|
||||
{BL32_EXTRA1_IMAGE_ID, "bl32_extra1_uuid"},
|
||||
{BL32_EXTRA2_IMAGE_ID, "bl32_extra2_uuid"},
|
||||
{BL33_IMAGE_ID, "bl33_uuid"},
|
||||
{HW_CONFIG_ID, "hw_cfg_uuid"},
|
||||
{SOC_FW_CONFIG_ID, "soc_fw_cfg_uuid"},
|
||||
{TOS_FW_CONFIG_ID, "tos_fw_cfg_uuid"},
|
||||
{NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"},
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
{CCA_CONTENT_CERT_ID, "cca_cert_uuid"},
|
||||
{CORE_SWD_KEY_CERT_ID, "core_swd_cert_uuid"},
|
||||
{PLAT_KEY_CERT_ID, "plat_cert_uuid"},
|
||||
{TRUSTED_KEY_CERT_ID, "t_key_cert_uuid"},
|
||||
{SCP_FW_KEY_CERT_ID, "scp_fw_key_uuid"},
|
||||
{SOC_FW_KEY_CERT_ID, "soc_fw_key_uuid"},
|
||||
{TRUSTED_OS_FW_KEY_CERT_ID, "tos_fw_key_cert_uuid"},
|
||||
{NON_TRUSTED_FW_KEY_CERT_ID, "nt_fw_key_cert_uuid"},
|
||||
{SCP_FW_CONTENT_CERT_ID, "scp_fw_content_cert_uuid"},
|
||||
{SOC_FW_CONTENT_CERT_ID, "soc_fw_content_cert_uuid"},
|
||||
{TRUSTED_OS_FW_CONTENT_CERT_ID, "tos_fw_content_cert_uuid"},
|
||||
{NON_TRUSTED_FW_CONTENT_CERT_ID, "nt_fw_content_cert_uuid"},
|
||||
#if defined(SPD_spmd)
|
||||
{SIP_SP_CONTENT_CERT_ID, "sip_sp_content_cert_uuid"},
|
||||
{PLAT_SP_CONTENT_CERT_ID, "plat_sp_content_cert_uuid"},
|
||||
#endif
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
};
|
||||
|
||||
int fconf_populate_arm_io_policies(uintptr_t config)
|
||||
{
|
||||
int err, node;
|
||||
unsigned int i;
|
||||
|
||||
union uuid_helper_t uuid_helper;
|
||||
io_uuid_spec_t *uuid_ptr;
|
||||
|
||||
/* As libfdt uses void *, we can't avoid this cast */
|
||||
const void *dtb = (void *)config;
|
||||
|
||||
/* Assert the node offset point to "arm,io-fip-handle" compatible property */
|
||||
const char *compatible_str = "arm,io-fip-handle";
|
||||
node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Can't find %s compatible in dtb\n", compatible_str);
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Locate the uuid cells and read the value for all the load info uuid */
|
||||
for (i = 0; i < FCONF_ARM_IO_UUID_NUMBER; i++) {
|
||||
uuid_ptr = pool_alloc(&fconf_arm_uuids_pool);
|
||||
err = fdtw_read_uuid(dtb, node, load_info[i].name, 16,
|
||||
(uint8_t *)&uuid_helper);
|
||||
if (err < 0) {
|
||||
WARN("FCONF: Read cell failed for %s\n", load_info[i].name);
|
||||
return err;
|
||||
}
|
||||
|
||||
VERBOSE("FCONF: arm-io_policies.%s cell found with value = "
|
||||
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
|
||||
load_info[i].name,
|
||||
uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1],
|
||||
uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3],
|
||||
uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1],
|
||||
uuid_helper.uuid_struct.time_hi_and_version[0],
|
||||
uuid_helper.uuid_struct.time_hi_and_version[1],
|
||||
uuid_helper.uuid_struct.clock_seq_hi_and_reserved,
|
||||
uuid_helper.uuid_struct.clock_seq_low,
|
||||
uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1],
|
||||
uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3],
|
||||
uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5]);
|
||||
|
||||
uuid_ptr->uuid = uuid_helper.uuid_struct;
|
||||
policies[load_info[i].image_id].image_spec = (uintptr_t)uuid_ptr;
|
||||
policies[load_info[i].image_id].dev_handle = &fip_dev_handle;
|
||||
policies[load_info[i].image_id].check = open_fip;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if ARM_IO_IN_DTB
|
||||
FCONF_REGISTER_POPULATOR(TB_FW, arm_io, fconf_populate_arm_io_policies);
|
||||
#endif /* ARM_IO_IN_DTB */
|
||||
|
||||
#endif /* IMAGE_BL2 */
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/desc_image_load.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <drivers/io/io_storage.h>
|
||||
#include <lib/object_pool.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/arm/common/arm_fconf_getter.h>
|
||||
#include <plat/arm/common/arm_fconf_io_storage.h>
|
||||
#include <plat/arm/common/fconf_arm_sp_getter.h>
|
||||
#include <platform_def.h>
|
||||
#include <tools_share/firmware_image_package.h>
|
||||
|
||||
#ifdef IMAGE_BL2
|
||||
|
||||
bl_mem_params_node_t sp_mem_params_descs[MAX_SP_IDS];
|
||||
|
||||
struct arm_sp_t arm_sp;
|
||||
|
||||
int fconf_populate_arm_sp(uintptr_t config)
|
||||
{
|
||||
int sp_node, node, err;
|
||||
union uuid_helper_t uuid_helper;
|
||||
unsigned int index = 0;
|
||||
uint32_t val32;
|
||||
const unsigned int sip_start = SP_PKG1_ID;
|
||||
unsigned int sip_index = sip_start;
|
||||
#if defined(ARM_COT_dualroot)
|
||||
const unsigned int sip_end = sip_start + MAX_SP_IDS / 2;
|
||||
/* Allocating index range for platform SPs */
|
||||
const unsigned int plat_start = SP_PKG5_ID;
|
||||
unsigned int plat_index = plat_start;
|
||||
const unsigned int plat_end = plat_start + MAX_SP_IDS / 2;
|
||||
bool is_plat_owned = false;
|
||||
#endif /* ARM_COT_dualroot */
|
||||
|
||||
/* As libfdt use void *, we can't avoid this cast */
|
||||
const void *dtb = (void *)config;
|
||||
|
||||
/* Assert the node offset point to "arm,sp" compatible property */
|
||||
const char *compatible_str = "arm,sp";
|
||||
|
||||
node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Can't find %s in dtb\n", compatible_str);
|
||||
return node;
|
||||
}
|
||||
|
||||
fdt_for_each_subnode(sp_node, dtb, node) {
|
||||
if (index == MAX_SP_IDS) {
|
||||
ERROR("FCONF: Reached max number of SPs\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(ARM_COT_dualroot)
|
||||
if ((sip_index == sip_end) || (plat_index == plat_end)) {
|
||||
ERROR("FCONF: Reached max number of plat/SiP SPs\n");
|
||||
return -1;
|
||||
}
|
||||
#endif /* ARM_COT_dualroot */
|
||||
|
||||
/* Read UUID */
|
||||
err = fdtw_read_uuid(dtb, sp_node, "uuid", 16,
|
||||
(uint8_t *)&uuid_helper);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: cannot read SP uuid\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
arm_sp.uuids[index] = uuid_helper;
|
||||
|
||||
/* Read Load address */
|
||||
err = fdt_read_uint32(dtb, sp_node, "load-address", &val32);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: cannot read SP load address\n");
|
||||
return -1;
|
||||
}
|
||||
arm_sp.load_addr[index] = val32;
|
||||
|
||||
VERBOSE("FCONF: %s UUID"
|
||||
" %02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
|
||||
" load_addr=%lx\n",
|
||||
__func__,
|
||||
uuid_helper.uuid_struct.time_low[0], uuid_helper.uuid_struct.time_low[1],
|
||||
uuid_helper.uuid_struct.time_low[2], uuid_helper.uuid_struct.time_low[3],
|
||||
uuid_helper.uuid_struct.time_mid[0], uuid_helper.uuid_struct.time_mid[1],
|
||||
uuid_helper.uuid_struct.time_hi_and_version[0],
|
||||
uuid_helper.uuid_struct.time_hi_and_version[1],
|
||||
uuid_helper.uuid_struct.clock_seq_hi_and_reserved,
|
||||
uuid_helper.uuid_struct.clock_seq_low,
|
||||
uuid_helper.uuid_struct.node[0], uuid_helper.uuid_struct.node[1],
|
||||
uuid_helper.uuid_struct.node[2], uuid_helper.uuid_struct.node[3],
|
||||
uuid_helper.uuid_struct.node[4], uuid_helper.uuid_struct.node[5],
|
||||
arm_sp.load_addr[index]);
|
||||
|
||||
/* Read owner field only for dualroot CoT */
|
||||
#if defined(ARM_COT_dualroot)
|
||||
/* Owner is an optional field, no need to catch error */
|
||||
fdtw_read_string(dtb, sp_node, "owner",
|
||||
arm_sp.owner[index], ARM_SP_OWNER_NAME_LEN);
|
||||
|
||||
/* If owner is empty mark it as SiP owned */
|
||||
if ((strncmp(arm_sp.owner[index], "SiP",
|
||||
ARM_SP_OWNER_NAME_LEN) == 0) ||
|
||||
(strncmp(arm_sp.owner[index], "",
|
||||
ARM_SP_OWNER_NAME_LEN) == 0)) {
|
||||
is_plat_owned = false;
|
||||
} else if (strcmp(arm_sp.owner[index], "Plat") == 0) {
|
||||
is_plat_owned = true;
|
||||
} else {
|
||||
ERROR("FCONF: %s is not a valid SP owner\n",
|
||||
arm_sp.owner[index]);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Add SP information in mem param descriptor and IO policies
|
||||
* structure.
|
||||
*/
|
||||
if (is_plat_owned) {
|
||||
sp_mem_params_descs[index].image_id = plat_index;
|
||||
policies[plat_index].image_spec =
|
||||
(uintptr_t)&arm_sp.uuids[index];
|
||||
policies[plat_index].dev_handle = &fip_dev_handle;
|
||||
policies[plat_index].check = open_fip;
|
||||
plat_index++;
|
||||
} else
|
||||
#endif /* ARM_COT_dualroot */
|
||||
{
|
||||
sp_mem_params_descs[index].image_id = sip_index;
|
||||
policies[sip_index].image_spec =
|
||||
(uintptr_t)&arm_sp.uuids[index];
|
||||
policies[sip_index].dev_handle = &fip_dev_handle;
|
||||
policies[sip_index].check = open_fip;
|
||||
sip_index++;
|
||||
}
|
||||
SET_PARAM_HEAD(&sp_mem_params_descs[index].image_info,
|
||||
PARAM_IMAGE_BINARY, VERSION_2, 0);
|
||||
sp_mem_params_descs[index].image_info.image_max_size =
|
||||
ARM_SP_MAX_SIZE;
|
||||
sp_mem_params_descs[index].next_handoff_image_id =
|
||||
INVALID_IMAGE_ID;
|
||||
sp_mem_params_descs[index].image_info.image_base =
|
||||
arm_sp.load_addr[index];
|
||||
index++;
|
||||
}
|
||||
|
||||
if ((sp_node < 0) && (sp_node != -FDT_ERR_NOTFOUND)) {
|
||||
ERROR("%u: fdt_for_each_subnode(): %d\n", __LINE__, node);
|
||||
return sp_node;
|
||||
}
|
||||
|
||||
arm_sp.number_of_sp = index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(TB_FW, arm_sp, fconf_populate_arm_sp);
|
||||
|
||||
#endif /* IMAGE_BL2 */
|
||||
+354
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (c) 2021-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/arm/common/fconf_ethosn_getter.h>
|
||||
|
||||
struct ethosn_config_t ethosn_config = {0};
|
||||
|
||||
struct ethosn_sub_allocator_t {
|
||||
const char *name;
|
||||
size_t name_len;
|
||||
uint32_t stream_id;
|
||||
};
|
||||
|
||||
static bool fdt_node_is_enabled(const void *fdt, int node)
|
||||
{
|
||||
int len;
|
||||
const char *node_status;
|
||||
|
||||
node_status = fdt_getprop(fdt, node, "status", &len);
|
||||
if (node_status == NULL ||
|
||||
(len == 5 && /* Includes null character */
|
||||
strncmp(node_status, "okay", 4U) == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool fdt_node_has_reserved_memory(const void *fdt, int dev_node)
|
||||
{
|
||||
return fdt_get_property(fdt, dev_node, "memory-region", NULL) != NULL;
|
||||
}
|
||||
|
||||
static int fdt_node_get_iommus_stream_id(const void *fdt, int node, uint32_t *stream_id)
|
||||
{
|
||||
int err;
|
||||
uint32_t iommus_array[2] = {0U};
|
||||
|
||||
err = fdt_read_uint32_array(fdt, node, "iommus", 2U, iommus_array);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
*stream_id = iommus_array[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdt_node_populate_sub_allocators(const void *fdt,
|
||||
int alloc_node,
|
||||
struct ethosn_sub_allocator_t *sub_allocators,
|
||||
size_t num_allocs)
|
||||
{
|
||||
int sub_node;
|
||||
size_t i;
|
||||
int err = -FDT_ERR_NOTFOUND;
|
||||
uint32_t found_sub_allocators = 0U;
|
||||
|
||||
fdt_for_each_subnode(sub_node, fdt, alloc_node) {
|
||||
const char *node_name;
|
||||
|
||||
if (!fdt_node_is_enabled(fdt, sub_node)) {
|
||||
/* Ignore disabled node */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fdt_node_check_compatible(fdt, sub_node, "ethosn-memory") != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
node_name = fdt_get_name(fdt, sub_node, NULL);
|
||||
for (i = 0U; i < num_allocs; ++i) {
|
||||
if (strncmp(node_name, sub_allocators[i].name,
|
||||
sub_allocators[i].name_len) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
err = fdt_node_get_iommus_stream_id(fdt, sub_node,
|
||||
&sub_allocators[i].stream_id);
|
||||
if (err) {
|
||||
ERROR("FCONF: Failed to get stream ID from sub-allocator %s\n",
|
||||
node_name);
|
||||
return err;
|
||||
}
|
||||
|
||||
++found_sub_allocators;
|
||||
/* Nothing more to do for this node */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that at least one of the sub-allocators matched */
|
||||
if (i == num_allocs) {
|
||||
ERROR("FCONF: Unknown sub-allocator %s\n", node_name);
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
|
||||
ERROR("FCONF: Failed to parse sub-allocators\n");
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
if (err == -FDT_ERR_NOTFOUND) {
|
||||
ERROR("FCONF: No matching sub-allocator found\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (found_sub_allocators != num_allocs) {
|
||||
ERROR("FCONF: Not all sub-allocators were found\n");
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdt_node_populate_main_allocator(const void *fdt,
|
||||
int alloc_node,
|
||||
struct ethosn_main_allocator_t *allocator)
|
||||
{
|
||||
int err;
|
||||
struct ethosn_sub_allocator_t sub_allocators[] = {
|
||||
{.name = "firmware", .name_len = 8U},
|
||||
{.name = "working_data", .name_len = 12U}
|
||||
};
|
||||
|
||||
err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
|
||||
ARRAY_SIZE(sub_allocators));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
allocator->firmware.stream_id = sub_allocators[0].stream_id;
|
||||
allocator->working_data.stream_id = sub_allocators[1].stream_id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdt_node_populate_asset_allocator(const void *fdt,
|
||||
int alloc_node,
|
||||
struct ethosn_asset_allocator_t *allocator)
|
||||
{
|
||||
int err;
|
||||
struct ethosn_sub_allocator_t sub_allocators[] = {
|
||||
{.name = "command_stream", .name_len = 14U},
|
||||
{.name = "weight_data", .name_len = 11U},
|
||||
{.name = "buffer_data", .name_len = 11U},
|
||||
{.name = "intermediate_data", .name_len = 17U}
|
||||
};
|
||||
|
||||
err = fdt_node_populate_sub_allocators(fdt, alloc_node, sub_allocators,
|
||||
ARRAY_SIZE(sub_allocators));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
allocator->command_stream.stream_id = sub_allocators[0].stream_id;
|
||||
allocator->weight_data.stream_id = sub_allocators[1].stream_id;
|
||||
allocator->buffer_data.stream_id = sub_allocators[2].stream_id;
|
||||
allocator->intermediate_data.stream_id = sub_allocators[3].stream_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fdt_node_populate_core(const void *fdt,
|
||||
int device_node,
|
||||
int core_node,
|
||||
bool has_reserved_memory,
|
||||
uint32_t core_index,
|
||||
struct ethosn_core_t *core)
|
||||
{
|
||||
int err;
|
||||
int sub_node;
|
||||
uintptr_t core_addr;
|
||||
|
||||
err = fdt_get_reg_props_by_index(fdt, device_node, core_index,
|
||||
&core_addr, NULL);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Failed to read reg property for NPU core %u\n",
|
||||
core_index);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = -FDT_ERR_NOTFOUND;
|
||||
fdt_for_each_subnode(sub_node, fdt, core_node) {
|
||||
|
||||
if (!fdt_node_is_enabled(fdt, sub_node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fdt_node_check_compatible(fdt,
|
||||
sub_node,
|
||||
"ethosn-main_allocator") != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (has_reserved_memory) {
|
||||
ERROR("FCONF: Main allocator not supported when using reserved memory\n");
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
if (err != -FDT_ERR_NOTFOUND) {
|
||||
ERROR("FCONF: NPU core 0x%lx has more than one main allocator\n",
|
||||
core_addr);
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
err = fdt_node_populate_main_allocator(fdt, sub_node, &core->main_allocator);
|
||||
if (err) {
|
||||
ERROR("FCONF: Failed to parse main allocator for NPU core 0x%lx\n",
|
||||
core_addr);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
|
||||
ERROR("FCONF: Failed to parse core sub nodes\n");
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
if (!has_reserved_memory && err) {
|
||||
ERROR("FCONF: Main allocator not found for NPU core 0x%lx\n",
|
||||
core_addr);
|
||||
return err;
|
||||
}
|
||||
|
||||
core->addr = core_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fconf_populate_ethosn_config(uintptr_t config)
|
||||
{
|
||||
int ethosn_node;
|
||||
uint32_t dev_count = 0U;
|
||||
const void *hw_conf_dtb = (const void *)config;
|
||||
|
||||
INFO("Probing Arm(R) Ethos(TM)-N NPU\n");
|
||||
|
||||
fdt_for_each_compatible_node(hw_conf_dtb, ethosn_node, "ethosn") {
|
||||
struct ethosn_device_t *dev = ðosn_config.devices[dev_count];
|
||||
uint32_t dev_asset_alloc_count = 0U;
|
||||
uint32_t dev_core_count = 0U;
|
||||
bool has_reserved_memory;
|
||||
int sub_node;
|
||||
|
||||
if (!fdt_node_is_enabled(hw_conf_dtb, ethosn_node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dev_count >= ETHOSN_DEV_NUM_MAX) {
|
||||
ERROR("FCONF: Reached max number of NPUs\n");
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
has_reserved_memory = fdt_node_has_reserved_memory(hw_conf_dtb, ethosn_node);
|
||||
fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) {
|
||||
int err;
|
||||
|
||||
if (!fdt_node_is_enabled(hw_conf_dtb, sub_node)) {
|
||||
/* Ignore disabled sub node */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fdt_node_check_compatible(hw_conf_dtb,
|
||||
sub_node,
|
||||
"ethosn-core") == 0) {
|
||||
|
||||
if (dev_core_count >= ETHOSN_DEV_CORE_NUM_MAX) {
|
||||
ERROR("FCONF: Reached max number of NPU cores for NPU %u\n",
|
||||
dev_count);
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
err = fdt_node_populate_core(hw_conf_dtb,
|
||||
ethosn_node,
|
||||
sub_node,
|
||||
has_reserved_memory,
|
||||
dev_core_count,
|
||||
&(dev->cores[dev_core_count]));
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
++dev_core_count;
|
||||
} else if (fdt_node_check_compatible(hw_conf_dtb,
|
||||
sub_node,
|
||||
"ethosn-asset_allocator") == 0) {
|
||||
|
||||
if (dev_asset_alloc_count >=
|
||||
ETHOSN_DEV_ASSET_ALLOCATOR_NUM_MAX) {
|
||||
ERROR("FCONF: Reached max number of asset allocators for NPU %u\n",
|
||||
dev_count);
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
if (has_reserved_memory) {
|
||||
ERROR("FCONF: Asset allocator not supported when using reserved memory\n");
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
err = fdt_node_populate_asset_allocator(hw_conf_dtb,
|
||||
sub_node,
|
||||
&(dev->asset_allocators[dev_asset_alloc_count]));
|
||||
if (err) {
|
||||
ERROR("FCONF: Failed to parse asset allocator for NPU %u\n",
|
||||
dev_count);
|
||||
return err;
|
||||
}
|
||||
++dev_asset_alloc_count;
|
||||
}
|
||||
}
|
||||
|
||||
if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) {
|
||||
ERROR("FCONF: Failed to parse sub nodes for NPU %u\n",
|
||||
dev_count);
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
if (dev_core_count == 0U) {
|
||||
ERROR("FCONF: NPU %u must have at least one enabled core\n",
|
||||
dev_count);
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
if (!has_reserved_memory && dev_asset_alloc_count == 0U) {
|
||||
ERROR("FCONF: NPU %u must have at least one asset allocator\n",
|
||||
dev_count);
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
dev->num_cores = dev_core_count;
|
||||
dev->num_allocators = dev_asset_alloc_count;
|
||||
dev->has_reserved_memory = has_reserved_memory;
|
||||
++dev_count;
|
||||
}
|
||||
|
||||
if (dev_count == 0U) {
|
||||
ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n");
|
||||
return -FDT_ERR_BADSTRUCTURE;
|
||||
}
|
||||
|
||||
ethosn_config.num_devices = dev_count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config);
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <plat/arm/common/fconf_nv_cntr_getter.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* fconf_populate_cot_descs() - Populate available nv-counters and update global
|
||||
* structure.
|
||||
* @config[in]: Pointer to the device tree blob in memory
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int fconf_populate_nv_cntrs(uintptr_t config)
|
||||
{
|
||||
int rc, node, child;
|
||||
uint32_t id;
|
||||
uintptr_t reg;
|
||||
|
||||
/* As libfdt uses void *, we can't avoid this cast */
|
||||
const void *dtb = (void *)config;
|
||||
const char *compatible_str = "arm, non-volatile-counter";
|
||||
|
||||
node = fdt_node_offset_by_compatible(dtb, -1, compatible_str);
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Can't find %s compatible in node\n",
|
||||
compatible_str);
|
||||
return node;
|
||||
}
|
||||
|
||||
fdt_for_each_subnode(child, dtb, node) {
|
||||
|
||||
rc = fdt_read_uint32(dtb, child, "id", &id);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: Can't find %s property in node\n", "id");
|
||||
return rc;
|
||||
}
|
||||
|
||||
assert(id < MAX_NV_CTR_IDS);
|
||||
|
||||
rc = fdt_get_reg_props_by_index(dtb, child, 0, ®, NULL);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: Can't find %s property in node\n", "reg");
|
||||
return rc;
|
||||
}
|
||||
|
||||
nv_cntr_base_addr[id] = reg;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(TB_FW, nv_cntrs, fconf_populate_nv_cntrs);
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/arm/common/fconf_sdei_getter.h>
|
||||
|
||||
#define PRIVATE_EVENT_NUM(i) private_events[3 * (i)]
|
||||
#define PRIVATE_EVENT_INTR(i) private_events[3 * (i) + 1]
|
||||
#define PRIVATE_EVENT_FLAGS(i) private_events[3 * (i) + 2]
|
||||
|
||||
#define SHARED_EVENT_NUM(i) shared_events[3 * (i)]
|
||||
#define SHARED_EVENT_INTR(i) shared_events[3 * (i) + 1]
|
||||
#define SHARED_EVENT_FLAGS(i) shared_events[3 * (i) + 2]
|
||||
|
||||
struct sdei_dyn_config_t sdei_dyn_config;
|
||||
|
||||
int fconf_populate_sdei_dyn_config(uintptr_t config)
|
||||
{
|
||||
uint32_t i;
|
||||
int node, err;
|
||||
uint32_t private_events[PLAT_SDEI_DP_EVENT_MAX_CNT * 3];
|
||||
uint32_t shared_events[PLAT_SDEI_DS_EVENT_MAX_CNT * 3];
|
||||
|
||||
const void *dtb = (void *)config;
|
||||
|
||||
/* Check that the node offset points to compatible property */
|
||||
node = fdt_node_offset_by_compatible(dtb, -1, "arm,sdei-1.0");
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Can't find 'arm,sdei-1.0' compatible node in dtb\n");
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Read number of private mappings */
|
||||
err = fdt_read_uint32(dtb, node, "private_event_count",
|
||||
&sdei_dyn_config.private_ev_cnt);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'private_event_count': %u\n",
|
||||
sdei_dyn_config.private_ev_cnt);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Check if the value is in range */
|
||||
if (sdei_dyn_config.private_ev_cnt > PLAT_SDEI_DP_EVENT_MAX_CNT) {
|
||||
ERROR("FCONF: Invalid value for 'private_event_count': %u\n",
|
||||
sdei_dyn_config.private_ev_cnt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read private mappings */
|
||||
err = fdt_read_uint32_array(dtb, node, "private_events",
|
||||
sdei_dyn_config.private_ev_cnt * 3, private_events);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'private_events': %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Move data to fconf struct */
|
||||
for (i = 0; i < sdei_dyn_config.private_ev_cnt; i++) {
|
||||
sdei_dyn_config.private_ev_nums[i] = PRIVATE_EVENT_NUM(i);
|
||||
sdei_dyn_config.private_ev_intrs[i] = PRIVATE_EVENT_INTR(i);
|
||||
sdei_dyn_config.private_ev_flags[i] = PRIVATE_EVENT_FLAGS(i);
|
||||
}
|
||||
|
||||
/* Read number of shared mappings */
|
||||
err = fdt_read_uint32(dtb, node, "shared_event_count",
|
||||
&sdei_dyn_config.shared_ev_cnt);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'shared_event_count'\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Check if the value is in range */
|
||||
if (sdei_dyn_config.shared_ev_cnt > PLAT_SDEI_DS_EVENT_MAX_CNT) {
|
||||
ERROR("FCONF: Invalid value for 'shared_event_count': %u\n",
|
||||
sdei_dyn_config.shared_ev_cnt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read shared mappings */
|
||||
err = fdt_read_uint32_array(dtb, node, "shared_events",
|
||||
sdei_dyn_config.shared_ev_cnt * 3, shared_events);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'shared_events': %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Move data to fconf struct */
|
||||
for (i = 0; i < sdei_dyn_config.shared_ev_cnt; i++) {
|
||||
sdei_dyn_config.shared_ev_nums[i] = SHARED_EVENT_NUM(i);
|
||||
sdei_dyn_config.shared_ev_intrs[i] = SHARED_EVENT_INTR(i);
|
||||
sdei_dyn_config.shared_ev_flags[i] = SHARED_EVENT_FLAGS(i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, sdei, fconf_populate_sdei_dyn_config);
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/arm/common/fconf_sec_intr_config.h>
|
||||
|
||||
#define G0_INTR_NUM(i) g0_intr_prop[3U * (i)]
|
||||
#define G0_INTR_PRIORITY(i) g0_intr_prop[3U * (i) + 1]
|
||||
#define G0_INTR_CONFIG(i) g0_intr_prop[3U * (i) + 2]
|
||||
|
||||
#define G1S_INTR_NUM(i) g1s_intr_prop[3U * (i)]
|
||||
#define G1S_INTR_PRIORITY(i) g1s_intr_prop[3U * (i) + 1]
|
||||
#define G1S_INTR_CONFIG(i) g1s_intr_prop[3U * (i) + 2]
|
||||
|
||||
struct sec_intr_prop_t sec_intr_prop;
|
||||
|
||||
static void print_intr_prop(interrupt_prop_t prop)
|
||||
{
|
||||
VERBOSE("FCONF: Secure Interrupt NUM: %d, PRI: %d, TYPE: %d\n",
|
||||
prop.intr_num, prop.intr_pri, prop.intr_cfg);
|
||||
}
|
||||
|
||||
int fconf_populate_sec_intr_config(uintptr_t config)
|
||||
{
|
||||
int node, err;
|
||||
uint32_t g0_intr_count, g1s_intr_count;
|
||||
uint32_t g0_intr_prop[SEC_INT_COUNT_MAX * 3];
|
||||
uint32_t g1s_intr_prop[SEC_INT_COUNT_MAX * 3];
|
||||
|
||||
/* Necessary to work with libfdt APIs */
|
||||
const void *hw_config_dtb = (const void *)config;
|
||||
|
||||
node = fdt_node_offset_by_compatible(hw_config_dtb, -1,
|
||||
"arm,secure_interrupt_desc");
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Unable to locate node with %s compatible property\n",
|
||||
"arm,secure_interrupt_desc");
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Read number of Group 0 interrupts specified by platform */
|
||||
err = fdt_read_uint32(hw_config_dtb, node, "g0_intr_cnt", &g0_intr_count);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Could not locate g0s_intr_cnt property\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* At least 1 Group 0 interrupt description has to be provided*/
|
||||
if (g0_intr_count < 1U) {
|
||||
ERROR("FCONF: Invalid number of Group 0 interrupts count specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read number of Group 1 secure interrupts specified by platform */
|
||||
err = fdt_read_uint32(hw_config_dtb, node, "g1s_intr_cnt",
|
||||
&g1s_intr_count);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Could not locate g1s_intr_cnt property\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* At least one Group 1 interrupt description has to be provided*/
|
||||
if (g1s_intr_count < 1U) {
|
||||
ERROR("FCONF: Invalid number of Group 1 secure interrupts count specified\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the total number of secure interrupts described are within
|
||||
* the limit defined statically by the platform.
|
||||
*/
|
||||
if ((g0_intr_count + g1s_intr_count) > SEC_INT_COUNT_MAX) {
|
||||
ERROR("FCONF: Total number of secure interrupts exceed limit the of %d\n",
|
||||
SEC_INT_COUNT_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sec_intr_prop.count = g0_intr_count + g1s_intr_count;
|
||||
|
||||
/* Read the Group 0 interrupt descriptors */
|
||||
err = fdt_read_uint32_array(hw_config_dtb, node, "g0_intr_desc",
|
||||
g0_intr_count * 3, g0_intr_prop);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'g0s_intr_desc': %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Read the Group 1 secure interrupt descriptors */
|
||||
err = fdt_read_uint32_array(hw_config_dtb, node, "g1s_intr_desc",
|
||||
g1s_intr_count * 3, g1s_intr_prop);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read cell failed for 'g1s_intr_desc': %d\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Populate Group 0 interrupt descriptors into fconf based C struct */
|
||||
for (uint32_t i = 0; i < g0_intr_count; i++) {
|
||||
interrupt_prop_t sec_intr_property;
|
||||
|
||||
/* Secure Interrupt Group: INTR_GROUP0 i.e., 0x1 */
|
||||
sec_intr_property.intr_grp = 1;
|
||||
sec_intr_property.intr_num = G0_INTR_NUM(i);
|
||||
sec_intr_property.intr_pri = G0_INTR_PRIORITY(i);
|
||||
sec_intr_property.intr_cfg = G0_INTR_CONFIG(i);
|
||||
sec_intr_prop.descriptor[i] = sec_intr_property;
|
||||
print_intr_prop(sec_intr_property);
|
||||
}
|
||||
|
||||
/* Populate G1 secure interrupt descriptors into fconf based C struct */
|
||||
for (uint32_t i = 0; i < g1s_intr_count; i++) {
|
||||
interrupt_prop_t sec_intr_property;
|
||||
|
||||
/* Secure Interrupt Group: INTR_GROUP1S i.e., 0x0 */
|
||||
sec_intr_property.intr_grp = 0;
|
||||
sec_intr_property.intr_num = G1S_INTR_NUM(i);
|
||||
sec_intr_property.intr_pri = G1S_INTR_PRIORITY(i);
|
||||
sec_intr_property.intr_cfg = G1S_INTR_CONFIG(i);
|
||||
sec_intr_prop.descriptor[i + g0_intr_count] = sec_intr_property;
|
||||
print_intr_prop(sec_intr_property);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, sec_intr_prop, fconf_populate_sec_intr_config);
|
||||
Reference in New Issue
Block a user