10cb64d01SAchin Gupta /* 20cb64d01SAchin Gupta * Copyright (c) 2020, Arm Limited. All rights reserved. 30cb64d01SAchin Gupta * 40cb64d01SAchin Gupta * SPDX-License-Identifier: BSD-3-Clause 50cb64d01SAchin Gupta */ 60cb64d01SAchin Gupta 70cb64d01SAchin Gupta #include <assert.h> 8*52696946SOlivier Deprez #include <errno.h> 90cb64d01SAchin Gupta #include <string.h> 100cb64d01SAchin Gupta #include <libfdt.h> 110cb64d01SAchin Gupta 120cb64d01SAchin Gupta #include <common/debug.h> 130cb64d01SAchin Gupta #include <common/fdt_wrappers.h> 140cb64d01SAchin Gupta #include <platform_def.h> 150cb64d01SAchin Gupta #include <services/spm_core_manifest.h> 160cb64d01SAchin Gupta 17*52696946SOlivier Deprez #define ATTRIBUTE_ROOT_NODE_STR "attribute" 18*52696946SOlivier Deprez 190cb64d01SAchin Gupta /******************************************************************************* 20*52696946SOlivier Deprez * SPMC attribute node parser 210cb64d01SAchin Gupta ******************************************************************************/ 22*52696946SOlivier Deprez static int manifest_parse_attribute(spmc_manifest_attribute_t *attr, 230cb64d01SAchin Gupta const void *fdt, 240cb64d01SAchin Gupta int node) 250cb64d01SAchin Gupta { 26ff4e6c35SAndre Przywara uint32_t val32; 27*52696946SOlivier Deprez int rc; 280cb64d01SAchin Gupta 29*52696946SOlivier Deprez assert((attr != NULL) && (fdt != NULL)); 300cb64d01SAchin Gupta 31ff4e6c35SAndre Przywara rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version); 32*52696946SOlivier Deprez if (rc != 0) { 33*52696946SOlivier Deprez ERROR("Missing SPCI %s version in SPM Core manifest.\n", 34*52696946SOlivier Deprez "major"); 35*52696946SOlivier Deprez return rc; 360cb64d01SAchin Gupta } 370cb64d01SAchin Gupta 38ff4e6c35SAndre Przywara rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version); 39*52696946SOlivier Deprez if (rc != 0) { 40*52696946SOlivier Deprez ERROR("Missing SPCI %s version in SPM Core manifest.\n", 41*52696946SOlivier Deprez "minor"); 42*52696946SOlivier Deprez return rc; 430cb64d01SAchin Gupta } 440cb64d01SAchin Gupta 45ff4e6c35SAndre Przywara rc = fdt_read_uint32(fdt, node, "spmc_id", &val32); 46*52696946SOlivier Deprez if (rc != 0) { 47ac03ac5eSMax Shvetsov ERROR("Missing SPMC ID in manifest.\n"); 48*52696946SOlivier Deprez return rc; 49ac03ac5eSMax Shvetsov } 50*52696946SOlivier Deprez 51*52696946SOlivier Deprez attr->spmc_id = val32 & 0xffff; 52ac03ac5eSMax Shvetsov 53ff4e6c35SAndre Przywara rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state); 54*52696946SOlivier Deprez if (rc != 0) { 55*52696946SOlivier Deprez NOTICE("%s not specified in SPM Core manifest.\n", 56*52696946SOlivier Deprez "Execution state"); 57*52696946SOlivier Deprez } 580cb64d01SAchin Gupta 59ff4e6c35SAndre Przywara rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size); 60*52696946SOlivier Deprez if (rc != 0) { 61*52696946SOlivier Deprez NOTICE("%s not specified in SPM Core manifest.\n", 62*52696946SOlivier Deprez "Binary size"); 63*52696946SOlivier Deprez } 640cb64d01SAchin Gupta 65ff4e6c35SAndre Przywara rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address); 66*52696946SOlivier Deprez if (rc != 0) { 67*52696946SOlivier Deprez NOTICE("%s not specified in SPM Core manifest.\n", 68*52696946SOlivier Deprez "Load address"); 69*52696946SOlivier Deprez } 700cb64d01SAchin Gupta 71ff4e6c35SAndre Przywara rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint); 72*52696946SOlivier Deprez if (rc != 0) { 73*52696946SOlivier Deprez NOTICE("%s not specified in SPM Core manifest.\n", 74*52696946SOlivier Deprez "Entry point"); 75*52696946SOlivier Deprez } 760cb64d01SAchin Gupta 77*52696946SOlivier Deprez VERBOSE("SPM Core manifest attribute section:\n"); 78*52696946SOlivier Deprez VERBOSE(" version: %u.%u\n", attr->major_version, attr->minor_version); 79*52696946SOlivier Deprez VERBOSE(" spmc_id: 0x%x\n", attr->spmc_id); 800cb64d01SAchin Gupta VERBOSE(" binary_size: 0x%x\n", attr->binary_size); 810cb64d01SAchin Gupta VERBOSE(" load_address: 0x%llx\n", attr->load_address); 820cb64d01SAchin Gupta VERBOSE(" entrypoint: 0x%llx\n", attr->entrypoint); 830cb64d01SAchin Gupta 840cb64d01SAchin Gupta return 0; 850cb64d01SAchin Gupta } 860cb64d01SAchin Gupta 870cb64d01SAchin Gupta /******************************************************************************* 880cb64d01SAchin Gupta * Root node handler 890cb64d01SAchin Gupta ******************************************************************************/ 90*52696946SOlivier Deprez static int manifest_parse_root(spmc_manifest_attribute_t *manifest, 910cb64d01SAchin Gupta const void *fdt, 920cb64d01SAchin Gupta int root) 930cb64d01SAchin Gupta { 940cb64d01SAchin Gupta int node; 950cb64d01SAchin Gupta 96*52696946SOlivier Deprez assert(manifest != NULL); 97*52696946SOlivier Deprez 98*52696946SOlivier Deprez node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR, 99*52696946SOlivier Deprez sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1); 1000cb64d01SAchin Gupta if (node < 0) { 101*52696946SOlivier Deprez ERROR("Root node doesn't contain subnode '%s'\n", 102*52696946SOlivier Deprez ATTRIBUTE_ROOT_NODE_STR); 103*52696946SOlivier Deprez return node; 1040cb64d01SAchin Gupta } 1050cb64d01SAchin Gupta 1060cb64d01SAchin Gupta return manifest_parse_attribute(manifest, fdt, node); 1070cb64d01SAchin Gupta } 1080cb64d01SAchin Gupta 1090cb64d01SAchin Gupta /******************************************************************************* 110*52696946SOlivier Deprez * Platform handler to parse a SPM Core manifest. 1110cb64d01SAchin Gupta ******************************************************************************/ 112*52696946SOlivier Deprez int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest, 1130cb64d01SAchin Gupta const void *ptr, 1140cb64d01SAchin Gupta size_t size) 1150cb64d01SAchin Gupta { 1160cb64d01SAchin Gupta int rc; 1170cb64d01SAchin Gupta 1180cb64d01SAchin Gupta assert(manifest != NULL); 1190cb64d01SAchin Gupta assert(ptr != NULL); 1200cb64d01SAchin Gupta 121*52696946SOlivier Deprez INFO("Reading SPM Core manifest at address %p\n", ptr); 1220cb64d01SAchin Gupta 1230cb64d01SAchin Gupta rc = fdt_check_header(ptr); 1240cb64d01SAchin Gupta if (rc != 0) { 125*52696946SOlivier Deprez ERROR("Wrong format for SPM Core manifest (%d).\n", rc); 126*52696946SOlivier Deprez return rc; 1270cb64d01SAchin Gupta } 1280cb64d01SAchin Gupta 129*52696946SOlivier Deprez rc = fdt_node_offset_by_compatible(ptr, -1, 1300cb64d01SAchin Gupta "arm,spci-core-manifest-1.0"); 131*52696946SOlivier Deprez if (rc < 0) { 132*52696946SOlivier Deprez ERROR("Unrecognized SPM Core manifest\n"); 133*52696946SOlivier Deprez return rc; 1340cb64d01SAchin Gupta } 1350cb64d01SAchin Gupta 136*52696946SOlivier Deprez return manifest_parse_root(manifest, ptr, rc); 1370cb64d01SAchin Gupta } 138