blob: e65980bc81385128cc7bd72f48da8ea7a5a7adfc [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
12#include <common/debug.h>
13#include <common/fdt_wrappers.h>
Olivier Deprez69ca84a2020-02-07 15:44:43 +010014#include <lib/xlat_tables/xlat_tables_v2.h>
Achin Guptada6ef0e2019-10-11 14:54:48 +010015#include <platform_def.h>
16#include <services/spm_core_manifest.h>
17
Olivier Deprez2bae35f2020-04-16 13:39:06 +020018#define ATTRIBUTE_ROOT_NODE_STR "attribute"
19
Achin Guptada6ef0e2019-10-11 14:54:48 +010020/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +020021 * SPMC attribute node parser
Achin Guptada6ef0e2019-10-11 14:54:48 +010022 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020023static int manifest_parse_attribute(spmc_manifest_attribute_t *attr,
Achin Guptada6ef0e2019-10-11 14:54:48 +010024 const void *fdt,
25 int node)
26{
Andre Przywarafe5bdf52020-03-26 11:22:37 +000027 uint32_t val32;
Olivier Deprez2bae35f2020-04-16 13:39:06 +020028 int rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010029
Olivier Deprez2bae35f2020-04-16 13:39:06 +020030 assert((attr != NULL) && (fdt != NULL));
Achin Guptada6ef0e2019-10-11 14:54:48 +010031
Andre Przywarafe5bdf52020-03-26 11:22:37 +000032 rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020033 if (rc != 0) {
J-Alves2672cde2020-05-07 18:42:25 +010034 ERROR("Missing FFA %s version in SPM Core manifest.\n",
Olivier Deprez2bae35f2020-04-16 13:39:06 +020035 "major");
36 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010037 }
38
Andre Przywarafe5bdf52020-03-26 11:22:37 +000039 rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020040 if (rc != 0) {
J-Alves2672cde2020-05-07 18:42:25 +010041 ERROR("Missing FFA %s version in SPM Core manifest.\n",
Olivier Deprez2bae35f2020-04-16 13:39:06 +020042 "minor");
43 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010044 }
45
Andre Przywarafe5bdf52020-03-26 11:22:37 +000046 rc = fdt_read_uint32(fdt, node, "spmc_id", &val32);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020047 if (rc != 0) {
Max Shvetsove79062e2020-03-12 15:16:40 +000048 ERROR("Missing SPMC ID in manifest.\n");
Olivier Deprez2bae35f2020-04-16 13:39:06 +020049 return rc;
Max Shvetsove79062e2020-03-12 15:16:40 +000050 }
Olivier Deprez2bae35f2020-04-16 13:39:06 +020051
52 attr->spmc_id = val32 & 0xffff;
Max Shvetsove79062e2020-03-12 15:16:40 +000053
Andre Przywarafe5bdf52020-03-26 11:22:37 +000054 rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020055 if (rc != 0) {
56 NOTICE("%s not specified in SPM Core manifest.\n",
57 "Execution state");
58 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010059
Andre Przywarafe5bdf52020-03-26 11:22:37 +000060 rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020061 if (rc != 0) {
62 NOTICE("%s not specified in SPM Core manifest.\n",
63 "Binary size");
64 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010065
Andre Przywarafe5bdf52020-03-26 11:22:37 +000066 rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020067 if (rc != 0) {
68 NOTICE("%s not specified in SPM Core manifest.\n",
69 "Load address");
70 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010071
Andre Przywarafe5bdf52020-03-26 11:22:37 +000072 rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020073 if (rc != 0) {
74 NOTICE("%s not specified in SPM Core manifest.\n",
75 "Entry point");
76 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010077
Olivier Deprez2bae35f2020-04-16 13:39:06 +020078 VERBOSE("SPM Core manifest attribute section:\n");
79 VERBOSE(" version: %u.%u\n", attr->major_version, attr->minor_version);
80 VERBOSE(" spmc_id: 0x%x\n", attr->spmc_id);
Achin Guptada6ef0e2019-10-11 14:54:48 +010081 VERBOSE(" binary_size: 0x%x\n", attr->binary_size);
82 VERBOSE(" load_address: 0x%llx\n", attr->load_address);
83 VERBOSE(" entrypoint: 0x%llx\n", attr->entrypoint);
84
85 return 0;
86}
87
88/*******************************************************************************
89 * Root node handler
90 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020091static int manifest_parse_root(spmc_manifest_attribute_t *manifest,
92 const void *fdt,
93 int root)
Achin Guptada6ef0e2019-10-11 14:54:48 +010094{
95 int node;
Olivier Deprez2bae35f2020-04-16 13:39:06 +020096
97 assert(manifest != NULL);
Achin Guptada6ef0e2019-10-11 14:54:48 +010098
Olivier Deprez2bae35f2020-04-16 13:39:06 +020099 node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR,
100 sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1);
Achin Guptada6ef0e2019-10-11 14:54:48 +0100101 if (node < 0) {
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200102 ERROR("Root node doesn't contain subnode '%s'\n",
103 ATTRIBUTE_ROOT_NODE_STR);
104 return node;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100105 }
106
107 return manifest_parse_attribute(manifest, fdt, node);
108}
109
110/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200111 * Platform handler to parse a SPM Core manifest.
Achin Guptada6ef0e2019-10-11 14:54:48 +0100112 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200113int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100114 const void *pm_addr)
Achin Guptada6ef0e2019-10-11 14:54:48 +0100115{
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100116 int rc, unmap_ret;
117 uintptr_t pm_base, pm_base_align;
118 size_t mapped_size;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100119
120 assert(manifest != NULL);
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100121 assert(pm_addr != NULL);
122
123 /*
124 * Assume TOS_FW_CONFIG is not necessarily aligned to a page
125 * boundary, thus calculate the remaining space between SPMC
126 * manifest start address and upper page limit.
127 *
128 */
129 pm_base = (uintptr_t)pm_addr;
130 pm_base_align = page_align(pm_base, UP);
Manish Pandeybc62d152020-07-09 00:39:16 +0100131
132 if (pm_base == pm_base_align) {
133 /* Page aligned */
134 mapped_size = PAGE_SIZE;
135 } else {
136 mapped_size = pm_base_align - pm_base;
137 }
Achin Guptada6ef0e2019-10-11 14:54:48 +0100138
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100139 /* Check space within the page at least maps the FDT header */
140 if (mapped_size < sizeof(struct fdt_header)) {
141 ERROR("Error while mapping SPM Core manifest.\n");
142 return -EINVAL;
143 }
Achin Guptada6ef0e2019-10-11 14:54:48 +0100144
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100145 /* Map first SPMC manifest page in the SPMD translation regime */
146 pm_base_align = page_align(pm_base, DOWN);
147 rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
148 pm_base_align,
149 PAGE_SIZE,
150 MT_RO_DATA);
Achin Guptada6ef0e2019-10-11 14:54:48 +0100151 if (rc != 0) {
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100152 ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200153 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100154 }
155
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100156 rc = fdt_check_header(pm_addr);
157 if (rc != 0) {
158 ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
159 goto exit_unmap;
160 }
161
162 /* Check SPMC manifest fits within the upper mapped page boundary */
163 if (mapped_size < fdt_totalsize(pm_addr)) {
164 ERROR("SPM Core manifest too large.\n");
165 rc = -EINVAL;
166 goto exit_unmap;
167 }
168
169 VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
170
171 rc = fdt_node_offset_by_compatible(pm_addr, -1,
J-Alves2672cde2020-05-07 18:42:25 +0100172 "arm,ffa-core-manifest-1.0");
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200173 if (rc < 0) {
174 ERROR("Unrecognized SPM Core manifest\n");
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100175 goto exit_unmap;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100176 }
177
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100178 rc = manifest_parse_root(manifest, pm_addr, rc);
179
180exit_unmap:
181 unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
182 if (unmap_ret != 0) {
183 ERROR("Error while unmapping SPM Core manifest (%d).\n",
184 unmap_ret);
185 if (rc == 0) {
186 rc = unmap_ret;
187 }
188 }
189
190 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100191}