blob: f0aa27cfb0d3010b52c2b061418c7827ce91a1f0 [file] [log] [blame]
/*
* Copyright (c) 2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <string.h>
#include <libfdt.h>
#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <errno.h>
#include <platform_def.h>
#include <services/spm_core_manifest.h>
/*******************************************************************************
* Attribute section handler
******************************************************************************/
static int manifest_parse_attribute(spmc_manifest_sect_attribute_t *attr,
const void *fdt,
int node)
{
int rc = 0;
assert(attr && fdt);
rc = fdtw_read_cells(fdt, node, "maj_ver", 1, &attr->major_version);
if (rc) {
ERROR("Missing SPCI major version in SPM core manifest.\n");
return -ENOENT;
}
rc = fdtw_read_cells(fdt, node, "min_ver", 1, &attr->minor_version);
if (rc) {
ERROR("Missing SPCI minor version in SPM core manifest.\n");
return -ENOENT;
}
rc = fdtw_read_cells(fdt, node, "spmc_id", 1, &attr->spmc_id);
if (rc) {
ERROR("Missing SPMC ID in manifest.\n");
return -ENOENT;
}
rc = fdtw_read_cells(fdt, node, "exec_state", 1, &attr->exec_state);
if (rc)
NOTICE("Execution state not specified in SPM core manifest.\n");
rc = fdtw_read_cells(fdt, node, "binary_size", 1, &attr->binary_size);
if (rc)
NOTICE("Binary size not specified in SPM core manifest.\n");
rc = fdtw_read_cells(fdt, node, "load_address", 2, &attr->load_address);
if (rc)
NOTICE("Load address not specified in SPM core manifest.\n");
rc = fdtw_read_cells(fdt, node, "entrypoint", 2, &attr->entrypoint);
if (rc)
NOTICE("Entrypoint not specified in SPM core manifest.\n");
VERBOSE("SPM core manifest attribute section:\n");
VERBOSE(" version: %x.%x\n", attr->major_version, attr->minor_version);
VERBOSE(" spmc_id: %x\n", attr->spmc_id);
VERBOSE(" binary_size: 0x%x\n", attr->binary_size);
VERBOSE(" load_address: 0x%llx\n", attr->load_address);
VERBOSE(" entrypoint: 0x%llx\n", attr->entrypoint);
return 0;
}
/*******************************************************************************
* Root node handler
******************************************************************************/
static int manifest_parse_root(spmc_manifest_sect_attribute_t *manifest,
const void *fdt,
int root)
{
int node;
char *str;
str = "attribute";
node = fdt_subnode_offset_namelen(fdt, root, str, strlen(str));
if (node < 0) {
ERROR("Root node doesn't contain subnode '%s'\n", str);
return -ENOENT;
}
return manifest_parse_attribute(manifest, fdt, node);
}
/*******************************************************************************
* Platform handler to parse a SPM core manifest.
******************************************************************************/
int plat_spm_core_manifest_load(spmc_manifest_sect_attribute_t *manifest,
const void *ptr,
size_t size)
{
int rc;
int root_node;
assert(manifest != NULL);
assert(ptr != NULL);
INFO("Reading SPM core manifest at address %p\n", ptr);
rc = fdt_check_header(ptr);
if (rc != 0) {
ERROR("Wrong format for SPM core manifest (%d).\n", rc);
return -EINVAL;
}
INFO("Reading SPM core manifest at address %p\n", ptr);
root_node = fdt_node_offset_by_compatible(ptr, -1,
"arm,spci-core-manifest-1.0");
if (root_node < 0) {
ERROR("Unrecognized SPM core manifest\n");
return -ENOENT;
}
INFO("Reading SPM core manifest at address %p\n", ptr);
return manifest_parse_root(manifest, ptr, root_node);
}