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