GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -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 */
@@ -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 = &ethosn_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);
@@ -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, &reg, 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);
@@ -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);
@@ -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);