GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 <lib/fconf/fconf.h>
|
||||
#include <lib/fconf/fconf_dyn_cfg_getter.h>
|
||||
#include <libfdt.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
int fconf_load_config(unsigned int image_id)
|
||||
{
|
||||
int err;
|
||||
const struct dyn_cfg_dtb_info_t *config_info;
|
||||
|
||||
assert((image_id == FW_CONFIG_ID) || (image_id == TB_FW_CONFIG_ID));
|
||||
|
||||
image_info_t config_image_info = {
|
||||
.h.type = (uint8_t)PARAM_IMAGE_BINARY,
|
||||
.h.version = (uint8_t)VERSION_2,
|
||||
.h.size = (uint16_t)sizeof(image_info_t),
|
||||
.h.attr = 0
|
||||
};
|
||||
|
||||
config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_id);
|
||||
assert(config_info != NULL);
|
||||
|
||||
config_image_info.image_base = config_info->config_addr;
|
||||
config_image_info.image_max_size = config_info->config_max_size;
|
||||
|
||||
VERBOSE("FCONF: Loading config with image ID: %u\n", image_id);
|
||||
err = load_auth_image(image_id, &config_image_info);
|
||||
if (err != 0) {
|
||||
VERBOSE("Failed to load config %u\n", image_id);
|
||||
return err;
|
||||
}
|
||||
|
||||
INFO("FCONF: Config file with image ID:%u loaded at address = 0x%lx\n",
|
||||
image_id, config_image_info.image_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fconf_populate(const char *config_type, uintptr_t config)
|
||||
{
|
||||
assert(config != 0UL);
|
||||
|
||||
/* Check if the pointer to DTB is correct */
|
||||
if (fdt_check_header((void *)config) != 0) {
|
||||
ERROR("FCONF: Invalid DTB file passed for %s\n", config_type);
|
||||
panic();
|
||||
}
|
||||
|
||||
INFO("FCONF: Reading %s firmware configuration file from: 0x%lx\n", config_type, config);
|
||||
|
||||
/* Go through all registered populate functions */
|
||||
IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_START__, start);
|
||||
IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_END__, end);
|
||||
const struct fconf_populator *populator;
|
||||
|
||||
for (populator = start; populator != end; populator++) {
|
||||
assert((populator->info != NULL) && (populator->populate != NULL));
|
||||
|
||||
if (strcmp(populator->config_type, config_type) == 0) {
|
||||
INFO("FCONF: Reading firmware configuration information for: %s\n", populator->info);
|
||||
if (populator->populate(config) != 0) {
|
||||
/* TODO: handle property miss */
|
||||
panic();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2019-2021, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
include common/fdt_wrappers.mk
|
||||
|
||||
FCONF_SOURCES := lib/fconf/fconf.c
|
||||
FCONF_SOURCES += ${FDT_WRAPPERS_SOURCES}
|
||||
|
||||
FCONF_DYN_SOURCES := lib/fconf/fconf_dyn_cfg_getter.c
|
||||
FCONF_DYN_SOURCES += ${FDT_WRAPPERS_SOURCES}
|
||||
|
||||
FCONF_AMU_SOURCES := lib/fconf/fconf_amu_getter.c
|
||||
FCONF_AMU_SOURCES += ${FDT_WRAPPERS_SOURCES}
|
||||
|
||||
FCONF_MPMM_SOURCES := lib/fconf/fconf_mpmm_getter.c
|
||||
FCONF_MPMM_SOURCES += ${FDT_WRAPPERS_SOURCES}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <lib/fconf/fconf.h>
|
||||
#include <lib/fconf/fconf_amu_getter.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
struct fconf_amu_config fconf_amu_config;
|
||||
static struct amu_topology fconf_amu_topology_;
|
||||
|
||||
/*
|
||||
* Populate the core-specific AMU structure with information retrieved from a
|
||||
* device tree.
|
||||
*
|
||||
* Returns `0` on success, or a negative integer representing an error code.
|
||||
*/
|
||||
static int fconf_populate_amu_cpu_amu(const void *fdt, int parent,
|
||||
struct amu_core *amu)
|
||||
{
|
||||
int ret = 0;
|
||||
int node = 0;
|
||||
|
||||
fdt_for_each_subnode(node, fdt, parent) {
|
||||
const char *name;
|
||||
const char *value;
|
||||
int len;
|
||||
|
||||
uintptr_t idx = 0U;
|
||||
|
||||
name = fdt_get_name(fdt, node, &len);
|
||||
if (strncmp(name, "counter@", 8) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = fdt_get_reg_props_by_index(fdt, node, 0, &idx, NULL);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
value = fdt_getprop(fdt, node, "enable-at-el3", &len);
|
||||
if ((value == NULL) && (len != -FDT_ERR_NOTFOUND)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (len != -FDT_ERR_NOTFOUND) {
|
||||
amu->enable |= (1 << idx);
|
||||
}
|
||||
}
|
||||
|
||||
if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Within a `cpu` node, attempt to dereference the `amu` property, and populate
|
||||
* the AMU information for the core.
|
||||
*
|
||||
* Returns `0` on success, or a negative integer representing an error code.
|
||||
*/
|
||||
static int fconf_populate_amu_cpu(const void *fdt, int node, uintptr_t mpidr)
|
||||
{
|
||||
int ret;
|
||||
int idx;
|
||||
|
||||
uint32_t amu_phandle;
|
||||
struct amu_core *amu;
|
||||
|
||||
ret = fdt_read_uint32(fdt, node, "amu", &amu_phandle);
|
||||
if (ret < 0) {
|
||||
if (ret == -FDT_ERR_NOTFOUND) {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
node = fdt_node_offset_by_phandle(fdt, amu_phandle);
|
||||
if (node < 0) {
|
||||
return node;
|
||||
}
|
||||
|
||||
idx = plat_core_pos_by_mpidr(mpidr);
|
||||
if (idx < 0) {
|
||||
return -FDT_ERR_BADVALUE;
|
||||
}
|
||||
|
||||
amu = &fconf_amu_topology_.cores[idx];
|
||||
|
||||
return fconf_populate_amu_cpu_amu(fdt, node, amu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Populates the global `amu_topology` structure based on what's described by
|
||||
* the hardware configuration device tree blob.
|
||||
*
|
||||
* The device tree is expected to provide an `amu` property for each `cpu` node,
|
||||
* like so:
|
||||
*
|
||||
* cpu@0 {
|
||||
* amu = <&cpu0_amu>;
|
||||
* };
|
||||
*
|
||||
* amus {
|
||||
* cpu0_amu: amu-0 {
|
||||
* counters {
|
||||
* #address-cells = <2>;
|
||||
* #size-cells = <0>;
|
||||
*
|
||||
* counter@x,y {
|
||||
* reg = <x y>; // Group x, counter y
|
||||
* };
|
||||
* };
|
||||
* };
|
||||
* };
|
||||
*/
|
||||
static int fconf_populate_amu(uintptr_t config)
|
||||
{
|
||||
int ret = fdtw_for_each_cpu(
|
||||
(const void *)config, fconf_populate_amu_cpu);
|
||||
if (ret == 0) {
|
||||
fconf_amu_config.topology = &fconf_amu_topology_;
|
||||
} else {
|
||||
ERROR("FCONF: failed to parse AMU information: %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, amu, fconf_populate_amu);
|
||||
@@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#include <drivers/auth/auth_mod.h>
|
||||
#include <lib/fconf/fconf.h>
|
||||
#include <lib/object_pool.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <tools_share/tbbr_oid.h>
|
||||
|
||||
/* static structures used during authentication process */
|
||||
static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
|
||||
AUTH_PARAM_SIG, 0);
|
||||
static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
|
||||
AUTH_PARAM_SIG_ALG, 0);
|
||||
static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
|
||||
AUTH_PARAM_RAW_DATA, 0);
|
||||
|
||||
/* pointers to an array of CoT descriptors */
|
||||
static const auth_img_desc_t *cot_desc[MAX_NUMBER_IDS];
|
||||
/* array of CoT descriptors */
|
||||
static auth_img_desc_t auth_img_descs[MAX_NUMBER_IDS];
|
||||
|
||||
/* array of authentication methods structures */
|
||||
static auth_method_desc_t auth_methods[MAX_NUMBER_IDS * AUTH_METHOD_NUM];
|
||||
static OBJECT_POOL_ARRAY(auth_methods_pool, auth_methods);
|
||||
|
||||
/* array of authentication params structures */
|
||||
static auth_param_desc_t auth_params[MAX_NUMBER_IDS * COT_MAX_VERIFIED_PARAMS];
|
||||
static OBJECT_POOL_ARRAY(auth_params_pool, auth_params);
|
||||
|
||||
/* array of authentication param type structures */
|
||||
static auth_param_type_desc_t auth_param_type_descs[MAX_NUMBER_IDS];
|
||||
static OBJECT_POOL_ARRAY(auth_param_type_descs_pool, auth_param_type_descs);
|
||||
|
||||
/*
|
||||
* array of OIDs
|
||||
* Object IDs are used to search hash, pk, counter values in certificate.
|
||||
* As per binding we have below 2 combinations:
|
||||
* 1. Certificates are validated using nv-cntr and pk
|
||||
* 2. Raw images are authenticated using hash
|
||||
* Hence in worst case, there are maximum 2 OIDs per image/certificate
|
||||
*/
|
||||
static unsigned char oids[(MAX_NUMBER_IDS * 2)][MAX_OID_NAME_LEN];
|
||||
static OBJECT_POOL_ARRAY(oid_pool, oids);
|
||||
|
||||
/* An array of auth buffer which holds hashes and pk
|
||||
* ToDo: Size decided with the current number of images and
|
||||
* certificates which are available in CoT. Size of these buffers bound to
|
||||
* increase in the future on the addition of images/certificates.
|
||||
*/
|
||||
static unsigned char hash_auth_bufs[20][HASH_DER_LEN];
|
||||
static OBJECT_POOL_ARRAY(hash_auth_buf_pool, hash_auth_bufs);
|
||||
static unsigned char pk_auth_bufs[12][PK_DER_LEN];
|
||||
static OBJECT_POOL_ARRAY(pk_auth_buf_pool, pk_auth_bufs);
|
||||
|
||||
/*******************************************************************************
|
||||
* update_parent_auth_data() - Update authentication data structure
|
||||
* @auth_desc[in]: Pointer to the auth image descriptor
|
||||
* @type_desc[in]: Pointer to authentication parameter
|
||||
* @auth_buf_size[in]: Buffer size to hold pk or hash
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int update_parent_auth_data(const auth_img_desc_t *auth_desc,
|
||||
auth_param_type_desc_t *type_desc,
|
||||
unsigned int auth_buf_size)
|
||||
{
|
||||
unsigned int i;
|
||||
auth_param_desc_t *auth_data = &auth_desc->authenticated_data[0];
|
||||
unsigned char *auth_buf;
|
||||
|
||||
for (i = 0U; i < COT_MAX_VERIFIED_PARAMS; i++) {
|
||||
if (auth_data[i].type_desc == type_desc) {
|
||||
return 0;
|
||||
}
|
||||
if (auth_data[i].type_desc == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (auth_buf_size == HASH_DER_LEN) {
|
||||
auth_buf = pool_alloc(&hash_auth_buf_pool);
|
||||
} else if (auth_buf_size == PK_DER_LEN) {
|
||||
auth_buf = pool_alloc(&pk_auth_buf_pool);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (i < COT_MAX_VERIFIED_PARAMS) {
|
||||
auth_data[i].type_desc = type_desc;
|
||||
auth_data[i].data.ptr = auth_buf;
|
||||
auth_data[i].data.len = auth_buf_size;
|
||||
} else {
|
||||
ERROR("Out of authentication data array\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* get_auth_param_type_desc() - Get pointer of authentication parameter
|
||||
* @img_id[in]: Image Id
|
||||
* @type_desc[out]: Pointer to authentication parameter
|
||||
* @buf_size[out]: Buffer size which hold hash/pk
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int get_auth_param_type_desc(unsigned int img_id,
|
||||
auth_param_type_desc_t **type_desc,
|
||||
unsigned int *buf_size)
|
||||
{
|
||||
auth_method_desc_t *img_auth_method = NULL;
|
||||
img_type_t type = auth_img_descs[img_id].img_type;
|
||||
|
||||
if (type == IMG_CERT) {
|
||||
img_auth_method =
|
||||
&auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_SIG];
|
||||
*type_desc = img_auth_method->param.sig.pk;
|
||||
*buf_size = PK_DER_LEN;
|
||||
} else if (type == IMG_RAW) {
|
||||
img_auth_method =
|
||||
&auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_HASH];
|
||||
*type_desc = img_auth_method->param.hash.hash;
|
||||
*buf_size = HASH_DER_LEN;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* set_auth_method() - Update global auth image descriptors with authentication
|
||||
* method data
|
||||
* @auth_method_type[in]: Type of authentication method
|
||||
* @oid[in]: Object Idetifier for pk/hash search
|
||||
* @auth_method[in]: Pointer to authentication method to set
|
||||
******************************************************************************/
|
||||
static void set_auth_method(auth_method_type_t auth_method_type, char *oid,
|
||||
auth_method_desc_t *auth_method)
|
||||
{
|
||||
auth_param_type_t auth_param_type = AUTH_PARAM_NONE;
|
||||
auth_param_type_desc_t *auth_param_type_desc;
|
||||
|
||||
assert(auth_method != NULL);
|
||||
|
||||
auth_param_type_desc = pool_alloc(&auth_param_type_descs_pool);
|
||||
auth_method->type = auth_method_type;
|
||||
|
||||
if (auth_method_type == AUTH_METHOD_SIG) {
|
||||
auth_param_type = AUTH_PARAM_PUB_KEY;
|
||||
auth_method->param.sig.sig = &sig;
|
||||
auth_method->param.sig.alg = &sig_alg;
|
||||
auth_method->param.sig.data = &raw_data;
|
||||
auth_method->param.sig.pk = auth_param_type_desc;
|
||||
} else if (auth_method_type == AUTH_METHOD_HASH) {
|
||||
auth_param_type = AUTH_PARAM_HASH;
|
||||
auth_method->param.hash.data = &raw_data;
|
||||
auth_method->param.hash.hash = auth_param_type_desc;
|
||||
} else if (auth_method_type == AUTH_METHOD_NV_CTR) {
|
||||
auth_param_type = AUTH_PARAM_NV_CTR;
|
||||
auth_method->param.nv_ctr.cert_nv_ctr = auth_param_type_desc;
|
||||
auth_method->param.nv_ctr.plat_nv_ctr = auth_param_type_desc;
|
||||
}
|
||||
|
||||
auth_param_type_desc->type = auth_param_type;
|
||||
auth_param_type_desc->cookie = (void *)oid;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* get_oid() - get object identifier from device tree
|
||||
* @dtb[in]: Pointer to the device tree blob in memory
|
||||
* @node[in]: Offset of the node
|
||||
* @prop[in]: Property to read from the given node
|
||||
* @oid[out]: Object Indentifier of key/hash/nv-counter in certificate
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int get_oid(const void *dtb, int node, const char *prop, char **oid)
|
||||
{
|
||||
uint32_t phandle;
|
||||
int rc;
|
||||
|
||||
rc = fdt_read_uint32(dtb, node, prop, &phandle);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
node = fdt_node_offset_by_phandle(dtb, phandle);
|
||||
if (node < 0) {
|
||||
return node;
|
||||
}
|
||||
|
||||
*oid = pool_alloc(&oid_pool);
|
||||
rc = fdtw_read_string(dtb, node, "oid", *oid, MAX_OID_NAME_LEN);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* populate_and_set_auth_methods() - Populate auth method parameters from
|
||||
* device tree and set authentication method
|
||||
* structure.
|
||||
* @dtb[in]: Pointer to the device tree blob in memory
|
||||
* @node[in]: Offset of the node
|
||||
* @img_id[in]: Image identifier
|
||||
* @type[in]: Type of image
|
||||
* @root_certificate[in]:Root certificate (authenticated by ROTPK)
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int populate_and_set_auth_methods(const void *dtb, int node,
|
||||
unsigned int img_id, img_type_t type,
|
||||
bool root_certificate)
|
||||
{
|
||||
auth_method_type_t auth_method_type = AUTH_METHOD_NONE;
|
||||
int rc;
|
||||
char *oid = NULL;
|
||||
|
||||
auth_method_desc_t *auth_method = pool_alloc_n(&auth_methods_pool,
|
||||
AUTH_METHOD_NUM);
|
||||
|
||||
/*
|
||||
* This is as per binding document where certificates are
|
||||
* verified by signature and images are verified by hash.
|
||||
*/
|
||||
if (type == IMG_CERT) {
|
||||
if (root_certificate) {
|
||||
oid = NULL;
|
||||
} else {
|
||||
rc = get_oid(dtb, node, "signing-key", &oid);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: Can't read %s property\n",
|
||||
"signing-key");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
auth_method_type = AUTH_METHOD_SIG;
|
||||
} else if (type == IMG_RAW) {
|
||||
rc = get_oid(dtb, node, "hash", &oid);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: Can't read %s property\n",
|
||||
"hash");
|
||||
return rc;
|
||||
}
|
||||
auth_method_type = AUTH_METHOD_HASH;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_auth_method(auth_method_type, oid,
|
||||
&auth_method[auth_method_type]);
|
||||
|
||||
/* Retrieve the optional property */
|
||||
rc = get_oid(dtb, node, "antirollback-counter", &oid);
|
||||
if (rc == 0) {
|
||||
auth_method_type = AUTH_METHOD_NV_CTR;
|
||||
set_auth_method(auth_method_type, oid,
|
||||
&auth_method[auth_method_type]);
|
||||
}
|
||||
|
||||
auth_img_descs[img_id].img_auth_methods = &auth_method[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* get_parent_img_id() - Get parent image id for given child node
|
||||
* @dtb[in]: Pointer to the device tree blob in memory
|
||||
* @node[in]: Offset of the child node
|
||||
* @parent_img_id[out]: Image id of parent
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int get_parent_img_id(const void *dtb, int node,
|
||||
unsigned int *parent_img_id)
|
||||
{
|
||||
uint32_t phandle;
|
||||
int err;
|
||||
|
||||
err = fdt_read_uint32(dtb, node, "parent", &phandle);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Could not read %s property in node\n",
|
||||
"parent");
|
||||
return err;
|
||||
}
|
||||
|
||||
node = fdt_node_offset_by_phandle(dtb, phandle);
|
||||
if (node < 0) {
|
||||
ERROR("FCONF: Failed to locate node using its phandle\n");
|
||||
return node;
|
||||
}
|
||||
|
||||
err = fdt_read_uint32(dtb, node, "image-id", parent_img_id);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Could not read %s property in node\n",
|
||||
"image-id");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* set_desc_data() - Update data in descriptor's structure
|
||||
* @dtb[in]: Pointer to the device tree blob in memory
|
||||
* @node[in]: Offset of the node
|
||||
* @type[in]: Type of image (RAW/CERT)
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int set_desc_data(const void *dtb, int node, img_type_t type)
|
||||
{
|
||||
int rc;
|
||||
bool root_certificate = false;
|
||||
unsigned int img_id, parent_img_id;
|
||||
|
||||
rc = fdt_read_uint32(dtb, node, "image-id", &img_id);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: Can't find property %s in node\n",
|
||||
"image-id");
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (fdt_getprop(dtb, node, "root-certificate",
|
||||
NULL) != NULL) {
|
||||
root_certificate = true;
|
||||
}
|
||||
|
||||
if (!root_certificate) {
|
||||
rc = get_parent_img_id(dtb, node, &parent_img_id);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
auth_img_descs[img_id].parent = &auth_img_descs[parent_img_id];
|
||||
}
|
||||
|
||||
auth_img_descs[img_id].img_id = img_id;
|
||||
auth_img_descs[img_id].img_type = type;
|
||||
|
||||
rc = populate_and_set_auth_methods(dtb, node, img_id, type,
|
||||
root_certificate);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (type == IMG_CERT) {
|
||||
auth_param_desc_t *auth_param =
|
||||
pool_alloc_n(&auth_params_pool,
|
||||
COT_MAX_VERIFIED_PARAMS);
|
||||
auth_img_descs[img_id].authenticated_data = &auth_param[0];
|
||||
}
|
||||
|
||||
cot_desc[img_id] = &auth_img_descs[img_id];
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* populate_manifest_descs() - Populate CoT descriptors and update global
|
||||
* certificate structures
|
||||
* @dtb[in]: Pointer to the device tree blob in memory
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int populate_manifest_descs(const void *dtb)
|
||||
{
|
||||
int node, child;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Assert the node offset points to "arm, cert-descs"
|
||||
* compatible property
|
||||
*/
|
||||
const char *compatible_str = "arm, cert-descs";
|
||||
|
||||
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 = set_desc_data(dtb, child, IMG_CERT);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* populate_image_descs() - Populate CoT descriptors and update global
|
||||
* image descriptor structures.
|
||||
* @dtb[in]: Pointer to the device tree blob in memory
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int populate_image_descs(const void *dtb)
|
||||
{
|
||||
int node, child;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* Assert the node offset points to "arm, img-descs"
|
||||
* compatible property
|
||||
*/
|
||||
const char *compatible_str = "arm, img-descs";
|
||||
|
||||
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 = set_desc_data(dtb, child, IMG_RAW);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* fconf_populate_cot_descs() - Populate CoT descriptors and update global
|
||||
* structures
|
||||
* @config[in]: Pointer to the device tree blob in memory
|
||||
*
|
||||
* Return 0 on success or an error value otherwise.
|
||||
******************************************************************************/
|
||||
static int fconf_populate_cot_descs(uintptr_t config)
|
||||
{
|
||||
auth_param_type_desc_t *type_desc = NULL;
|
||||
unsigned int auth_buf_size = 0U;
|
||||
int rc;
|
||||
|
||||
/* As libfdt uses void *, we can't avoid this cast */
|
||||
const void *dtb = (void *)config;
|
||||
|
||||
/* populate manifest descs information */
|
||||
rc = populate_manifest_descs(dtb);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: population of %s descs failed %d\n",
|
||||
"manifest", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* populate image descs information */
|
||||
rc = populate_image_descs(dtb);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: population of %s descs failed %d\n",
|
||||
"images", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* update parent's authentication data */
|
||||
for (unsigned int i = 0U; i < MAX_NUMBER_IDS; i++) {
|
||||
if (auth_img_descs[i].parent != NULL) {
|
||||
rc = get_auth_param_type_desc(i,
|
||||
&type_desc,
|
||||
&auth_buf_size);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: failed to get auth data %d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = update_parent_auth_data(auth_img_descs[i].parent,
|
||||
type_desc,
|
||||
auth_buf_size);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: auth data update failed %d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(TB_FW, cot_desc, fconf_populate_cot_descs);
|
||||
REGISTER_COT(cot_desc);
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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 <lib/fconf/fconf_dyn_cfg_getter.h>
|
||||
#include <lib/object_pool.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NT_FW and HW configs */
|
||||
#define MAX_DTB_INFO U(6)
|
||||
/*
|
||||
* Compile time assert if FW_CONFIG_ID is 0 which is more
|
||||
* unlikely as 0 is a valid image ID for FIP as per the current
|
||||
* code but still to avoid code breakage in case of unlikely
|
||||
* event when image IDs get changed.
|
||||
*/
|
||||
CASSERT(FW_CONFIG_ID != U(0), assert_invalid_fw_config_id);
|
||||
|
||||
static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO];
|
||||
static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos);
|
||||
|
||||
/*
|
||||
* This function is used to alloc memory for config information from
|
||||
* global pool and set the configuration information.
|
||||
*/
|
||||
void set_config_info(uintptr_t config_addr, uintptr_t ns_config_addr,
|
||||
uint32_t config_max_size,
|
||||
unsigned int config_id)
|
||||
{
|
||||
struct dyn_cfg_dtb_info_t *dtb_info;
|
||||
|
||||
dtb_info = pool_alloc(&dtb_info_pool);
|
||||
dtb_info->config_addr = config_addr;
|
||||
dtb_info->ns_config_addr = ns_config_addr;
|
||||
dtb_info->config_max_size = config_max_size;
|
||||
dtb_info->config_id = config_id;
|
||||
}
|
||||
|
||||
/* Get index of the config_id image */
|
||||
unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id)
|
||||
{
|
||||
unsigned int index;
|
||||
|
||||
/* Positions index to the proper config-id */
|
||||
for (index = 0U; index < MAX_DTB_INFO; index++) {
|
||||
if (dtb_infos[index].config_id == config_id) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return FCONF_INVALID_IDX;
|
||||
}
|
||||
|
||||
struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id)
|
||||
{
|
||||
/* Positions index to the proper config-id */
|
||||
unsigned int index = dyn_cfg_dtb_info_get_index(config_id);
|
||||
|
||||
if (index < MAX_DTB_INFO) {
|
||||
return &dtb_infos[index];
|
||||
}
|
||||
|
||||
WARN("FCONF: Invalid config id %u\n", config_id);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fconf_populate_dtb_registry(uintptr_t config)
|
||||
{
|
||||
int rc;
|
||||
int node, child;
|
||||
|
||||
/* As libfdt use void *, we can't avoid this cast */
|
||||
const void *dtb = (void *)config;
|
||||
|
||||
/*
|
||||
* In case of BL1, fw_config dtb information is already
|
||||
* populated in global dtb_infos array by 'set_fw_config_info'
|
||||
* function, Below check is present to avoid re-population of
|
||||
* fw_config information.
|
||||
*
|
||||
* Other BLs, satisfy below check and populate fw_config information
|
||||
* in global dtb_infos array.
|
||||
*/
|
||||
if (dtb_infos[0].config_id == 0U) {
|
||||
uint32_t config_max_size = fdt_totalsize(dtb);
|
||||
set_config_info(config, ~0UL, config_max_size, FW_CONFIG_ID);
|
||||
}
|
||||
|
||||
/* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */
|
||||
const char *compatible_str = "fconf,dyn_cfg-dtb_registry";
|
||||
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;
|
||||
}
|
||||
|
||||
fdt_for_each_subnode(child, dtb, node) {
|
||||
uint32_t config_max_size, config_id;
|
||||
uintptr_t config_addr;
|
||||
uintptr_t ns_config_addr = ~0UL;
|
||||
uint64_t val64;
|
||||
|
||||
/* Read configuration dtb information */
|
||||
rc = fdt_read_uint64(dtb, child, "load-address", &val64);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
|
||||
return rc;
|
||||
}
|
||||
config_addr = (uintptr_t)val64;
|
||||
|
||||
rc = fdt_read_uint32(dtb, child, "max-size", &config_max_size);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = fdt_read_uint32(dtb, child, "id", &config_id);
|
||||
if (rc < 0) {
|
||||
ERROR("FCONF: Incomplete configuration property in dtb-registry.\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n");
|
||||
VERBOSE("\tload-address = %lx\n", config_addr);
|
||||
VERBOSE("\tmax-size = 0x%x\n", config_max_size);
|
||||
VERBOSE("\tconfig-id = %u\n", config_id);
|
||||
|
||||
rc = fdt_read_uint64(dtb, child, "ns-load-address", &val64);
|
||||
if (rc == 0) {
|
||||
ns_config_addr = (uintptr_t)val64;
|
||||
VERBOSE("\tns-load-address = %lx\n", ns_config_addr);
|
||||
}
|
||||
|
||||
set_config_info(config_addr, ns_config_addr, config_max_size,
|
||||
config_id);
|
||||
}
|
||||
|
||||
if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) {
|
||||
ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node);
|
||||
return child;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(FW_CONFIG, dyn_cfg, fconf_populate_dtb_registry);
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <lib/fconf/fconf.h>
|
||||
#include <lib/fconf/fconf_mpmm_getter.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
struct fconf_mpmm_config fconf_mpmm_config;
|
||||
static struct mpmm_topology fconf_mpmm_topology;
|
||||
|
||||
/*
|
||||
* Within a `cpu` node, determine support for MPMM via the `supports-mpmm`
|
||||
* property.
|
||||
*
|
||||
* Returns `0` on success, or a negative integer representing an error code.
|
||||
*/
|
||||
static int fconf_populate_mpmm_cpu(const void *fdt, int off, uintptr_t mpidr)
|
||||
{
|
||||
int ret, len;
|
||||
|
||||
int core_pos;
|
||||
struct mpmm_core *core;
|
||||
|
||||
core_pos = plat_core_pos_by_mpidr(mpidr);
|
||||
if (core_pos < 0) {
|
||||
return -FDT_ERR_BADVALUE;
|
||||
}
|
||||
|
||||
core = &fconf_mpmm_topology.cores[core_pos];
|
||||
|
||||
fdt_getprop(fdt, off, "supports-mpmm", &len);
|
||||
if (len >= 0) {
|
||||
core->supported = true;
|
||||
ret = 0;
|
||||
} else {
|
||||
core->supported = false;
|
||||
ret = len;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Populates the global `fconf_mpmm_config` structure based on what's described
|
||||
* by the hardware configuration device tree blob.
|
||||
*
|
||||
* The device tree is expected to provide a `supports-mpmm` property for each
|
||||
* `cpu` node, like so:
|
||||
*
|
||||
* cpu@0 {
|
||||
* supports-mpmm;
|
||||
* };
|
||||
*
|
||||
* This property indicates whether the core implements MPMM, as we cannot detect
|
||||
* support for it dynamically.
|
||||
*/
|
||||
static int fconf_populate_mpmm(uintptr_t config)
|
||||
{
|
||||
int ret = fdtw_for_each_cpu(
|
||||
(const void *)config, fconf_populate_mpmm_cpu);
|
||||
if (ret == 0) {
|
||||
fconf_mpmm_config.topology = &fconf_mpmm_topology;
|
||||
} else {
|
||||
ERROR("FCONF: failed to configure MPMM: %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(HW_CONFIG, mpmm, fconf_populate_mpmm);
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <common/fdt_wrappers.h>
|
||||
#include <lib/fconf/fconf_tbbr_getter.h>
|
||||
#include <libfdt.h>
|
||||
|
||||
struct tbbr_dyn_config_t tbbr_dyn_config;
|
||||
|
||||
int fconf_populate_tbbr_dyn_config(uintptr_t config)
|
||||
{
|
||||
int err;
|
||||
int node;
|
||||
uint64_t val64;
|
||||
uint32_t val32;
|
||||
|
||||
/* As libfdt use void *, we can't avoid this cast */
|
||||
const void *dtb = (void *)config;
|
||||
|
||||
/* Assert the node offset point to "arm,tb_fw" compatible property */
|
||||
const char *compatible_str = "arm,tb_fw";
|
||||
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 disable_auth cell and read the value */
|
||||
err = fdt_read_uint32(dtb, node, "disable_auth",
|
||||
&tbbr_dyn_config.disable_auth);
|
||||
if (err < 0) {
|
||||
WARN("FCONF: Read %s failed for `%s`\n",
|
||||
"cell", "disable_auth");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Check if the value is boolean */
|
||||
if ((tbbr_dyn_config.disable_auth != 0U) &&
|
||||
(tbbr_dyn_config.disable_auth != 1U)) {
|
||||
WARN("Invalid value for `%s` cell %u\n",
|
||||
"disable_auth", tbbr_dyn_config.disable_auth);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(DYN_DISABLE_AUTH)
|
||||
if (tbbr_dyn_config.disable_auth == 1)
|
||||
dyn_disable_auth();
|
||||
#endif
|
||||
|
||||
/* Retrieve the Mbed TLS heap details from the DTB */
|
||||
err = fdt_read_uint64(dtb, node, "mbedtls_heap_addr", &val64);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read %s failed for `%s`\n",
|
||||
"cell", "mbedtls_heap_addr");
|
||||
return err;
|
||||
}
|
||||
tbbr_dyn_config.mbedtls_heap_addr = (void *)(uintptr_t)val64;
|
||||
|
||||
err = fdt_read_uint32(dtb, node, "mbedtls_heap_size", &val32);
|
||||
if (err < 0) {
|
||||
ERROR("FCONF: Read %s failed for `%s`\n",
|
||||
"cell", "mbedtls_heap_size");
|
||||
return err;
|
||||
}
|
||||
tbbr_dyn_config.mbedtls_heap_size = val32;
|
||||
|
||||
VERBOSE("%s%s%s %u\n", "FCONF: `tbbr.", "disable_auth",
|
||||
"` cell found with value =", tbbr_dyn_config.disable_auth);
|
||||
VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr",
|
||||
"` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr);
|
||||
VERBOSE("%s%s%s %zu\n", "FCONF: `tbbr.", "mbedtls_heap_size",
|
||||
"` cell found with value =", tbbr_dyn_config.mbedtls_heap_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FCONF_REGISTER_POPULATOR(TB_FW, tbbr, fconf_populate_tbbr_dyn_config);
|
||||
Reference in New Issue
Block a user