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