blob: 109b001f0b163c74da8c7eab7001c788bcf1594c [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) {
34 ERROR("Missing SPCI %s version in SPM Core manifest.\n",
35 "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) {
41 ERROR("Missing SPCI %s version in SPM Core manifest.\n",
42 "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);
131 mapped_size = pm_base_align - pm_base;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100132
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100133 /* Check space within the page at least maps the FDT header */
134 if (mapped_size < sizeof(struct fdt_header)) {
135 ERROR("Error while mapping SPM Core manifest.\n");
136 return -EINVAL;
137 }
Achin Guptada6ef0e2019-10-11 14:54:48 +0100138
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100139 /* Map first SPMC manifest page in the SPMD translation regime */
140 pm_base_align = page_align(pm_base, DOWN);
141 rc = mmap_add_dynamic_region((unsigned long long)pm_base_align,
142 pm_base_align,
143 PAGE_SIZE,
144 MT_RO_DATA);
Achin Guptada6ef0e2019-10-11 14:54:48 +0100145 if (rc != 0) {
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100146 ERROR("Error while mapping SPM Core manifest (%d).\n", rc);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200147 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100148 }
149
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100150 rc = fdt_check_header(pm_addr);
151 if (rc != 0) {
152 ERROR("Wrong format for SPM Core manifest (%d).\n", rc);
153 goto exit_unmap;
154 }
155
156 /* Check SPMC manifest fits within the upper mapped page boundary */
157 if (mapped_size < fdt_totalsize(pm_addr)) {
158 ERROR("SPM Core manifest too large.\n");
159 rc = -EINVAL;
160 goto exit_unmap;
161 }
162
163 VERBOSE("Reading SPM Core manifest at address %p\n", pm_addr);
164
165 rc = fdt_node_offset_by_compatible(pm_addr, -1,
Achin Guptada6ef0e2019-10-11 14:54:48 +0100166 "arm,spci-core-manifest-1.0");
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200167 if (rc < 0) {
168 ERROR("Unrecognized SPM Core manifest\n");
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100169 goto exit_unmap;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100170 }
171
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100172 rc = manifest_parse_root(manifest, pm_addr, rc);
173
174exit_unmap:
175 unmap_ret = mmap_remove_dynamic_region(pm_base_align, PAGE_SIZE);
176 if (unmap_ret != 0) {
177 ERROR("Error while unmapping SPM Core manifest (%d).\n",
178 unmap_ret);
179 if (rc == 0) {
180 rc = unmap_ret;
181 }
182 }
183
184 return rc;
Achin Guptada6ef0e2019-10-11 14:54:48 +0100185}