1 /* 2 * Copyright (c) 2020, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 #include <string.h> 10 #include <libfdt.h> 11 12 #include <common/debug.h> 13 #include <common/fdt_wrappers.h> 14 #include <platform_def.h> 15 #include <services/spm_core_manifest.h> 16 17 #define ATTRIBUTE_ROOT_NODE_STR "attribute" 18 19 /******************************************************************************* 20 * SPMC attribute node parser 21 ******************************************************************************/ 22 static int manifest_parse_attribute(spmc_manifest_attribute_t *attr, 23 const void *fdt, 24 int node) 25 { 26 uint32_t val32; 27 int rc; 28 29 assert((attr != NULL) && (fdt != NULL)); 30 31 rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version); 32 if (rc != 0) { 33 ERROR("Missing SPCI %s version in SPM Core manifest.\n", 34 "major"); 35 return rc; 36 } 37 38 rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version); 39 if (rc != 0) { 40 ERROR("Missing SPCI %s version in SPM Core manifest.\n", 41 "minor"); 42 return rc; 43 } 44 45 rc = fdt_read_uint32(fdt, node, "spmc_id", &val32); 46 if (rc != 0) { 47 ERROR("Missing SPMC ID in manifest.\n"); 48 return rc; 49 } 50 51 attr->spmc_id = val32 & 0xffff; 52 53 rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state); 54 if (rc != 0) { 55 NOTICE("%s not specified in SPM Core manifest.\n", 56 "Execution state"); 57 } 58 59 rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size); 60 if (rc != 0) { 61 NOTICE("%s not specified in SPM Core manifest.\n", 62 "Binary size"); 63 } 64 65 rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address); 66 if (rc != 0) { 67 NOTICE("%s not specified in SPM Core manifest.\n", 68 "Load address"); 69 } 70 71 rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint); 72 if (rc != 0) { 73 NOTICE("%s not specified in SPM Core manifest.\n", 74 "Entry point"); 75 } 76 77 VERBOSE("SPM Core manifest attribute section:\n"); 78 VERBOSE(" version: %u.%u\n", attr->major_version, attr->minor_version); 79 VERBOSE(" spmc_id: 0x%x\n", attr->spmc_id); 80 VERBOSE(" binary_size: 0x%x\n", attr->binary_size); 81 VERBOSE(" load_address: 0x%llx\n", attr->load_address); 82 VERBOSE(" entrypoint: 0x%llx\n", attr->entrypoint); 83 84 return 0; 85 } 86 87 /******************************************************************************* 88 * Root node handler 89 ******************************************************************************/ 90 static int manifest_parse_root(spmc_manifest_attribute_t *manifest, 91 const void *fdt, 92 int root) 93 { 94 int node; 95 96 assert(manifest != NULL); 97 98 node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR, 99 sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1); 100 if (node < 0) { 101 ERROR("Root node doesn't contain subnode '%s'\n", 102 ATTRIBUTE_ROOT_NODE_STR); 103 return node; 104 } 105 106 return manifest_parse_attribute(manifest, fdt, node); 107 } 108 109 /******************************************************************************* 110 * Platform handler to parse a SPM Core manifest. 111 ******************************************************************************/ 112 int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest, 113 const void *ptr, 114 size_t size) 115 { 116 int rc; 117 118 assert(manifest != NULL); 119 assert(ptr != NULL); 120 121 INFO("Reading SPM Core manifest at address %p\n", ptr); 122 123 rc = fdt_check_header(ptr); 124 if (rc != 0) { 125 ERROR("Wrong format for SPM Core manifest (%d).\n", rc); 126 return rc; 127 } 128 129 rc = fdt_node_offset_by_compatible(ptr, -1, 130 "arm,spci-core-manifest-1.0"); 131 if (rc < 0) { 132 ERROR("Unrecognized SPM Core manifest\n"); 133 return rc; 134 } 135 136 return manifest_parse_root(manifest, ptr, rc); 137 } 138