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