blob: 8f4018c7cde74c2944d78d96529ec314bfff453c [file] [log] [blame]
Achin Guptada6ef0e2019-10-11 14:54:48 +01001/*
2 * Copyright (c) 2020, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
Olivier Deprez2bae35f2020-04-16 13:39:06 +02008#include <errno.h>
Achin Guptada6ef0e2019-10-11 14:54:48 +01009#include <string.h>
10#include <libfdt.h>
11
Varun Wadekar2e70a342020-07-19 21:28:10 -070012#include <common/bl_common.h>
Achin Guptada6ef0e2019-10-11 14:54:48 +010013#include <common/debug.h>
14#include <common/fdt_wrappers.h>
Olivier Deprez69ca84a2020-02-07 15:44:43 +010015#include <lib/xlat_tables/xlat_tables_v2.h>
Achin Guptada6ef0e2019-10-11 14:54:48 +010016#include <platform_def.h>
17#include <services/spm_core_manifest.h>
18
Olivier Deprez2bae35f2020-04-16 13:39:06 +020019#define ATTRIBUTE_ROOT_NODE_STR "attribute"
20
Achin Guptada6ef0e2019-10-11 14:54:48 +010021/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +020022 * SPMC attribute node parser
Achin Guptada6ef0e2019-10-11 14:54:48 +010023 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020024static int manifest_parse_attribute(spmc_manifest_attribute_t *attr,
Achin Guptada6ef0e2019-10-11 14:54:48 +010025 const void *fdt,
26 int node)
27{
Andre Przywarafe5bdf52020-03-26 11:22:37 +000028 uint32_t val32;
Olivier Deprez2bae35f2020-04-16 13:39:06 +020029 int rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010030
Olivier Deprez2bae35f2020-04-16 13:39:06 +020031 assert((attr != NULL) && (fdt != NULL));
Achin Guptada6ef0e2019-10-11 14:54:48 +010032
Andre Przywarafe5bdf52020-03-26 11:22:37 +000033 rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020034 if (rc != 0) {
J-Alves2672cde2020-05-07 18:42:25 +010035 ERROR("Missing FFA %s version in SPM Core manifest.\n",
Olivier Deprez2bae35f2020-04-16 13:39:06 +020036 "major");
37 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010038 }
39
Andre Przywarafe5bdf52020-03-26 11:22:37 +000040 rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020041 if (rc != 0) {
J-Alves2672cde2020-05-07 18:42:25 +010042 ERROR("Missing FFA %s version in SPM Core manifest.\n",
Olivier Deprez2bae35f2020-04-16 13:39:06 +020043 "minor");
44 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010045 }
46
Andre Przywarafe5bdf52020-03-26 11:22:37 +000047 rc = fdt_read_uint32(fdt, node, "spmc_id", &val32);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020048 if (rc != 0) {
Max Shvetsove79062e2020-03-12 15:16:40 +000049 ERROR("Missing SPMC ID in manifest.\n");
Olivier Deprez2bae35f2020-04-16 13:39:06 +020050 return rc;
Max Shvetsove79062e2020-03-12 15:16:40 +000051 }
Olivier Deprez2bae35f2020-04-16 13:39:06 +020052
53 attr->spmc_id = val32 & 0xffff;
Max Shvetsove79062e2020-03-12 15:16:40 +000054
Andre Przywarafe5bdf52020-03-26 11:22:37 +000055 rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020056 if (rc != 0) {
57 NOTICE("%s not specified in SPM Core manifest.\n",
58 "Execution state");
59 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010060
Andre Przywarafe5bdf52020-03-26 11:22:37 +000061 rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020062 if (rc != 0) {
63 NOTICE("%s not specified in SPM Core manifest.\n",
64 "Binary size");
65 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010066
Andre Przywarafe5bdf52020-03-26 11:22:37 +000067 rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020068 if (rc != 0) {
69 NOTICE("%s not specified in SPM Core manifest.\n",
70 "Load address");
71 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010072
Andre Przywarafe5bdf52020-03-26 11:22:37 +000073 rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020074 if (rc != 0) {
75 NOTICE("%s not specified in SPM Core manifest.\n",
76 "Entry point");
77 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010078
Olivier Deprez2bae35f2020-04-16 13:39:06 +020079 VERBOSE("SPM Core manifest attribute section:\n");
80 VERBOSE(" version: %u.%u\n", attr->major_version, attr->minor_version);
81 VERBOSE(" spmc_id: 0x%x\n", attr->spmc_id);
Achin Guptada6ef0e2019-10-11 14:54:48 +010082 VERBOSE(" binary_size: 0x%x\n", attr->binary_size);
83 VERBOSE(" load_address: 0x%llx\n", attr->load_address);
84 VERBOSE(" entrypoint: 0x%llx\n", attr->entrypoint);
85
86 return 0;
87}
88
89/*******************************************************************************
90 * Root node handler
91 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020092static int manifest_parse_root(spmc_manifest_attribute_t *manifest,
93 const void *fdt,
94 int root)
Achin Guptada6ef0e2019-10-11 14:54:48 +010095{
96 int node;
Olivier Deprez2bae35f2020-04-16 13:39:06 +020097
98 assert(manifest != NULL);
Achin Guptada6ef0e2019-10-11 14:54:48 +010099
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200100 node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR,
101 sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1);
Achin Guptada6ef0e2019-10-11 14:54:48 +0100102 if (node < 0) {
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200103 ERROR("Root node doesn't contain subnode '%s'\n",
104 ATTRIBUTE_ROOT_NODE_STR);
105 return node;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100106 }
107
108 return manifest_parse_attribute(manifest, fdt, node);
109}
110
111/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200112 * Platform handler to parse a SPM Core manifest.
Achin Guptada6ef0e2019-10-11 14:54:48 +0100113 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200114int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100115 const void *pm_addr)
Achin Guptada6ef0e2019-10-11 14:54:48 +0100116{
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100117 int rc, unmap_ret;
118 uintptr_t pm_base, pm_base_align;
119 size_t mapped_size;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100120
121 assert(manifest != NULL);
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100122 assert(pm_addr != NULL);
123
124 /*
125 * Assume TOS_FW_CONFIG is not necessarily aligned to a page
126 * boundary, thus calculate the remaining space between SPMC
127 * manifest start address and upper page limit.
128 *
129 */
130 pm_base = (uintptr_t)pm_addr;
131 pm_base_align = page_align(pm_base, UP);
Manish Pandeybc62d152020-07-09 00:39:16 +0100132
133 if (pm_base == pm_base_align) {
134 /* Page aligned */
135 mapped_size = PAGE_SIZE;
136 } else {
137 mapped_size = pm_base_align - pm_base;
138 }
Achin Guptada6ef0e2019-10-11 14:54:48 +0100139
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100140 /* Check space within the page at least maps the FDT header */
141 if (mapped_size < sizeof(struct fdt_header)) {
142 ERROR("Error while mapping SPM Core manifest.\n");
143 return -EINVAL;
144 }
Achin Guptada6ef0e2019-10-11 14:54:48 +0100145
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100146 /* Map first SPMC manifest page in the SPMD translation regime */
147 pm_base_align = page_align(pm_base, DOWN);
148 rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
149 pm_base_align,
150 PAGE_SIZE,
151 MT_RO_DATA);
Achin Guptada6ef0e2019-10-11 14:54:48 +0100152 if (rc != 0) {
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100153 ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200154 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100155 }
156
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100157 rc = fdt_check_header(pm_addr);
158 if (rc != 0) {
159 ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
160 goto exit_unmap;
161 }
162
163 /* Check SPMC manifest fits within the upper mapped page boundary */
164 if (mapped_size < fdt_totalsize(pm_addr)) {
165 ERROR("SPM Core manifest too large.\n");
166 rc = -EINVAL;
167 goto exit_unmap;
168 }
169
170 VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
171
172 rc = fdt_node_offset_by_compatible(pm_addr, -1,
J-Alves2672cde2020-05-07 18:42:25 +0100173 "arm,ffa-core-manifest-1.0");
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200174 if (rc < 0) {
175 ERROR("Unrecognized SPM Core manifest\n");
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100176 goto exit_unmap;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100177 }
178
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100179 rc = manifest_parse_root(manifest, pm_addr, rc);
180
181exit_unmap:
182 unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
183 if (unmap_ret != 0) {
184 ERROR("Error while unmapping SPM Core manifest (%d).\n",
185 unmap_ret);
186 if (rc == 0) {
187 rc = unmap_ret;
188 }
189 }
190
191 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100192}