blob: b1fc13ceeaf8a4cd3c50d024c2e2702e816a7452 [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>
Scott Brandene5dcf982020-08-25 13:49:32 -07009#include <inttypes.h>
Achin Guptada6ef0e2019-10-11 14:54:48 +010010#include <libfdt.h>
Scott Brandene5dcf982020-08-25 13:49:32 -070011#include <stdint.h>
12#include <string.h>
Achin Guptada6ef0e2019-10-11 14:54:48 +010013
Varun Wadekar2e70a342020-07-19 21:28:10 -070014#include <common/bl_common.h>
Achin Guptada6ef0e2019-10-11 14:54:48 +010015#include <common/debug.h>
16#include <common/fdt_wrappers.h>
Olivier Deprez69ca84a2020-02-07 15:44:43 +010017#include <lib/xlat_tables/xlat_tables_v2.h>
Achin Guptada6ef0e2019-10-11 14:54:48 +010018#include <platform_def.h>
19#include <services/spm_core_manifest.h>
20
Olivier Deprez2bae35f2020-04-16 13:39:06 +020021#define ATTRIBUTE_ROOT_NODE_STR "attribute"
22
Achin Guptada6ef0e2019-10-11 14:54:48 +010023/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +020024 * SPMC attribute node parser
Achin Guptada6ef0e2019-10-11 14:54:48 +010025 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020026static int manifest_parse_attribute(spmc_manifest_attribute_t *attr,
Achin Guptada6ef0e2019-10-11 14:54:48 +010027 const void *fdt,
28 int node)
29{
Andre Przywarafe5bdf52020-03-26 11:22:37 +000030 uint32_t val32;
Olivier Deprez2bae35f2020-04-16 13:39:06 +020031 int rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010032
Olivier Deprez2bae35f2020-04-16 13:39:06 +020033 assert((attr != NULL) && (fdt != NULL));
Achin Guptada6ef0e2019-10-11 14:54:48 +010034
Andre Przywarafe5bdf52020-03-26 11:22:37 +000035 rc = fdt_read_uint32(fdt, node, "maj_ver", &attr->major_version);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020036 if (rc != 0) {
J-Alves2672cde2020-05-07 18:42:25 +010037 ERROR("Missing FFA %s version in SPM Core manifest.\n",
Olivier Deprez2bae35f2020-04-16 13:39:06 +020038 "major");
39 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010040 }
41
Andre Przywarafe5bdf52020-03-26 11:22:37 +000042 rc = fdt_read_uint32(fdt, node, "min_ver", &attr->minor_version);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020043 if (rc != 0) {
J-Alves2672cde2020-05-07 18:42:25 +010044 ERROR("Missing FFA %s version in SPM Core manifest.\n",
Olivier Deprez2bae35f2020-04-16 13:39:06 +020045 "minor");
46 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +010047 }
48
Andre Przywarafe5bdf52020-03-26 11:22:37 +000049 rc = fdt_read_uint32(fdt, node, "spmc_id", &val32);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020050 if (rc != 0) {
Max Shvetsove79062e2020-03-12 15:16:40 +000051 ERROR("Missing SPMC ID in manifest.\n");
Olivier Deprez2bae35f2020-04-16 13:39:06 +020052 return rc;
Max Shvetsove79062e2020-03-12 15:16:40 +000053 }
Olivier Deprez2bae35f2020-04-16 13:39:06 +020054
55 attr->spmc_id = val32 & 0xffff;
Max Shvetsove79062e2020-03-12 15:16:40 +000056
Andre Przywarafe5bdf52020-03-26 11:22:37 +000057 rc = fdt_read_uint32(fdt, node, "exec_state", &attr->exec_state);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020058 if (rc != 0) {
59 NOTICE("%s not specified in SPM Core manifest.\n",
60 "Execution state");
61 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010062
Andre Przywarafe5bdf52020-03-26 11:22:37 +000063 rc = fdt_read_uint32(fdt, node, "binary_size", &attr->binary_size);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020064 if (rc != 0) {
65 NOTICE("%s not specified in SPM Core manifest.\n",
66 "Binary size");
67 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010068
Andre Przywarafe5bdf52020-03-26 11:22:37 +000069 rc = fdt_read_uint64(fdt, node, "load_address", &attr->load_address);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020070 if (rc != 0) {
71 NOTICE("%s not specified in SPM Core manifest.\n",
72 "Load address");
73 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010074
Andre Przywarafe5bdf52020-03-26 11:22:37 +000075 rc = fdt_read_uint64(fdt, node, "entrypoint", &attr->entrypoint);
Olivier Deprez2bae35f2020-04-16 13:39:06 +020076 if (rc != 0) {
77 NOTICE("%s not specified in SPM Core manifest.\n",
78 "Entry point");
79 }
Achin Guptada6ef0e2019-10-11 14:54:48 +010080
Olivier Deprez2bae35f2020-04-16 13:39:06 +020081 VERBOSE("SPM Core manifest attribute section:\n");
82 VERBOSE(" version: %u.%u\n", attr->major_version, attr->minor_version);
83 VERBOSE(" spmc_id: 0x%x\n", attr->spmc_id);
Achin Guptada6ef0e2019-10-11 14:54:48 +010084 VERBOSE(" binary_size: 0x%x\n", attr->binary_size);
Scott Brandene5dcf982020-08-25 13:49:32 -070085 VERBOSE(" load_address: 0x%" PRIx64 "\n", attr->load_address);
86 VERBOSE(" entrypoint: 0x%" PRIx64 "\n", attr->entrypoint);
Achin Guptada6ef0e2019-10-11 14:54:48 +010087
88 return 0;
89}
90
91/*******************************************************************************
92 * Root node handler
93 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020094static int manifest_parse_root(spmc_manifest_attribute_t *manifest,
95 const void *fdt,
96 int root)
Achin Guptada6ef0e2019-10-11 14:54:48 +010097{
98 int node;
Olivier Deprez2bae35f2020-04-16 13:39:06 +020099
100 assert(manifest != NULL);
Achin Guptada6ef0e2019-10-11 14:54:48 +0100101
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200102 node = fdt_subnode_offset_namelen(fdt, root, ATTRIBUTE_ROOT_NODE_STR,
103 sizeof(ATTRIBUTE_ROOT_NODE_STR) - 1);
Achin Guptada6ef0e2019-10-11 14:54:48 +0100104 if (node < 0) {
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200105 ERROR("Root node doesn't contain subnode '%s'\n",
106 ATTRIBUTE_ROOT_NODE_STR);
107 return node;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100108 }
109
110 return manifest_parse_attribute(manifest, fdt, node);
111}
112
113/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200114 * Platform handler to parse a SPM Core manifest.
Achin Guptada6ef0e2019-10-11 14:54:48 +0100115 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200116int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest,
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100117 const void *pm_addr)
Achin Guptada6ef0e2019-10-11 14:54:48 +0100118{
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100119 int rc, unmap_ret;
120 uintptr_t pm_base, pm_base_align;
121 size_t mapped_size;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100122
123 assert(manifest != NULL);
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100124 assert(pm_addr != NULL);
125
126 /*
127 * Assume TOS_FW_CONFIG is not necessarily aligned to a page
128 * boundary, thus calculate the remaining space between SPMC
129 * manifest start address and upper page limit.
130 *
131 */
132 pm_base = (uintptr_t)pm_addr;
133 pm_base_align = page_align(pm_base, UP);
Manish Pandeybc62d152020-07-09 00:39:16 +0100134
135 if (pm_base == pm_base_align) {
136 /* Page aligned */
137 mapped_size = PAGE_SIZE;
138 } else {
139 mapped_size = pm_base_align - pm_base;
140 }
Achin Guptada6ef0e2019-10-11 14:54:48 +0100141
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100142 /* Check space within the page at least maps the FDT header */
143 if (mapped_size < sizeof(struct fdt_header)) {
144 ERROR("Error while mapping SPM Core manifest.\n");
145 return -EINVAL;
146 }
Achin Guptada6ef0e2019-10-11 14:54:48 +0100147
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100148 /* Map first SPMC manifest page in the SPMD translation regime */
149 pm_base_align = page_align(pm_base, DOWN);
150 rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
151 pm_base_align,
152 PAGE_SIZE,
153 MT_RO_DATA);
Achin Guptada6ef0e2019-10-11 14:54:48 +0100154 if (rc != 0) {
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100155 ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200156 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100157 }
158
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100159 rc = fdt_check_header(pm_addr);
160 if (rc != 0) {
161 ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
162 goto exit_unmap;
163 }
164
165 /* Check SPMC manifest fits within the upper mapped page boundary */
166 if (mapped_size < fdt_totalsize(pm_addr)) {
167 ERROR("SPM Core manifest too large.\n");
168 rc = -EINVAL;
169 goto exit_unmap;
170 }
171
172 VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
173
174 rc = fdt_node_offset_by_compatible(pm_addr, -1,
J-Alves2672cde2020-05-07 18:42:25 +0100175 "arm,ffa-core-manifest-1.0");
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200176 if (rc < 0) {
177 ERROR("Unrecognized SPM Core manifest\n");
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100178 goto exit_unmap;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100179 }
180
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100181 rc = manifest_parse_root(manifest, pm_addr, rc);
182
183exit_unmap:
184 unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
185 if (unmap_ret != 0) {
186 ERROR("Error while unmapping SPM Core manifest (%d).\n",
187 unmap_ret);
188 if (rc == 0) {
189 rc = unmap_ret;
190 }
191 }
192
193 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100194}