blob: f0b8ac4b0b24bfbbe7c4b1de16bb33af6f9e5abe [file] [log] [blame]
J-Alves6e0abc42024-12-30 16:51:16 +00001/*
2 * Copyright 2024 The Hafnium Authors.
3 *
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
7 */
8
9#include "hf/partition_pkg.h"
10
11#include <stdint.h>
12
13#include "hf/arch/std.h"
14
15#include "hf/addr.h"
16#include "hf/check.h"
17#include "hf/dlog.h"
18#include "hf/mm.h"
19#include "hf/sp_pkg.h"
20#include "hf/std.h"
21#include "hf/transfer_list.h"
22
23static void dump_partition_package(struct partition_pkg *pkg)
24{
25 dlog_verbose("%s: total %lx %lx\n", __func__, pa_addr(pkg->total.begin),
26 pa_addr(pkg->total.end));
27 dlog_verbose("%s: pm: %lx %lx\n", __func__, pa_addr(pkg->pm.begin),
28 pa_addr(pkg->pm.end));
29 dlog_verbose("%s: img: %lx %lx\n", __func__, pa_addr(pkg->img.begin),
30 pa_addr(pkg->img.end));
31 dlog_verbose("%s: boot_info: %lx %lx\n", __func__,
32 pa_addr(pkg->boot_info.begin),
33 pa_addr(pkg->boot_info.end));
34 if (mem_range_is_valid(pkg->hob)) {
35 dlog_verbose("%s: hob %lx %lx\n", __func__,
36 pa_addr(pkg->hob.begin), pa_addr(pkg->hob.end));
37 }
38}
39
40static bool partition_pkg_from_sp_pkg(struct mm_stage1_locked stage1_locked,
41 paddr_t pkg_start,
42 struct partition_pkg *pkg,
43 struct mpool *ppool)
44{
45 struct sp_pkg_header header;
46 bool ret = sp_pkg_init(stage1_locked, pkg_start, &header, ppool);
47 size_t total_mem_size = sp_pkg_get_mem_size(&header);
48
49 pkg->total.begin = pkg_start;
50 pkg->total.end = pa_add(pkg_start, total_mem_size);
51
52 pkg->pm.begin = pa_add(pkg_start, header.pm_offset);
53 pkg->pm.end = pa_add(pkg->pm.begin, header.pm_size);
54
55 pkg->img.begin = pa_add(pkg_start, header.img_offset);
56 pkg->img.end = pa_add(pkg->img.begin, header.img_size);
57
58 /*
59 * Repurpose the first page of the SP Package.
60 * FF-A boot info will overwrite the package, but it doesn't
61 * matter at this stage, given Hafnium already parsed it.
62 */
63 pkg->boot_info.begin = pkg_start;
64 pkg->boot_info.end = pa_add(pkg_start, header.pm_offset);
65
66 /* HOB section doesn't exist in the SP Pkg type. */
67 pkg->hob.begin = pa_init(0);
68 pkg->hob.end = pa_init(0);
69
J-Alves6e0abc42024-12-30 16:51:16 +000070 /* Map the whole package as RO. */
71 CHECK(mm_identity_map(stage1_locked, pkg->total.begin, pkg->total.end,
72 MM_MODE_R, ppool) != NULL);
73
74 return ret;
75}
76
J-Alves01337a32024-11-18 17:51:59 +000077/**
78 * It creates a memory range structure which relates to the region of the
79 * TE data.
80 * It returns false if there is no TE entry with the specified type.
81 * It returns true, if there is a TE entry with the specified type, and
82 * returns the memory range via `mem_range`.
83 */
84static bool partition_pkg_init_memory_range_from_te(
85 struct mem_range *mem_range, struct transfer_list_entry *te)
86{
87 void *te_data;
88
89 assert(mem_range != NULL);
90
91 te_data = transfer_list_entry_data(te);
92
93 if (te == NULL || te_data == NULL) {
94 mem_range->begin = pa_init(0);
95 mem_range->end = pa_init(0);
96 return false;
97 }
98
99 mem_range->begin = pa_from_va(va_init((uintptr_t)te_data));
100 mem_range->end = pa_add(mem_range->begin, te->data_size);
101
102 return true;
103}
104
105static bool partition_pkg_from_tl(struct mm_stage1_locked stage1_locked,
106 paddr_t pkg_start, struct partition_pkg *pkg,
107 struct mpool *ppool)
108{
109 struct transfer_list_header *tl = ptr_from_va(va_from_pa(pkg_start));
110 enum transfer_list_ops tl_res;
111
112 dlog_verbose("%s: partition loaded in a transfer list.\n", __func__);
113
114 /* The total memory for the partition package. */
115 pkg->total.begin = pkg_start;
116 pkg->total.end = pa_add(pkg_start, tl->size);
117
118 /* Map the whole TL as RO. */
119 CHECK(mm_identity_map(stage1_locked, pkg->total.begin, pkg->total.end,
120 MM_MODE_R, ppool));
121
122 tl_res = transfer_list_check_header(tl);
123
124 if (tl_res == TL_OPS_NON || tl_res == TL_OPS_CUS) {
125 return false;
126 }
127
128 /*
129 * Get the memory ranges from the TL for:
130 * - FFA_MANIFEST.
131 * - Partition Image.
132 */
133 if (!partition_pkg_init_memory_range_from_te(
134 &(pkg->pm),
135 transfer_list_find(tl, TL_TAG_DT_FFA_MANIFEST)) ||
136 !partition_pkg_init_memory_range_from_te(
137 &(pkg->img),
138 transfer_list_find(tl, TL_TAG_FFA_SP_BINARY))) {
139 return false;
140 }
141
142 /* An HOB entry is optional. */
143 partition_pkg_init_memory_range_from_te(
144 &(pkg->hob), transfer_list_find(tl, TL_TAG_HOB_LIST));
145
146 if (!mem_range_aligns(pkg->pm, PAGE_SIZE)) {
147 dlog_error(
148 "%s: the partition manifest range must be 4k page "
149 "aligned.\n",
150 __func__);
151 return false;
152 }
153
154 if (!mem_range_aligns(pkg->img, PAGE_SIZE)) {
155 dlog_error(
156 "%s: the partition image range must be 4k page "
157 "aligned.\n",
158 __func__);
159 return false;
160 }
161
162 if (mem_range_is_valid(pkg->hob) &&
163 !mem_range_aligns(pkg->hob, PAGE_SIZE)) {
164 dlog_error("%s: the hob range must be 4k page aligned.\n",
165 __func__);
166 return false;
167 }
168
169 /*
170 * For the boot information descriptor, repurpose the TL's first page.
171 * The TL is only processed by Hafnium, and all items are placed at
172 * a page aligned offset.
173 * At this point, all references to artefacts in the TL have been
174 * obtained so the first page of the package can be repurposed to the
175 * FF-A boot information. There is no expectation that the boot info
176 * descriptors will need more than a page for the time being. If it does
177 * get full, Hafnium will fail at populating the boot info descriptors.
178 */
179 pkg->boot_info.begin = pkg_start;
180 pkg->boot_info.end = pa_add(pkg_start, PAGE_SIZE);
181
J-Alves01337a32024-11-18 17:51:59 +0000182 return true;
183}
184
J-Alves6e0abc42024-12-30 16:51:16 +0000185bool partition_pkg_init(struct mm_stage1_locked stage1_locked,
186 paddr_t pkg_start, struct partition_pkg *pkg,
187 struct mpool *ppool)
188{
189 bool ret = false;
190 paddr_t pkg_first_page = pa_add(pkg_start, PAGE_SIZE);
191 uint32_t *magic;
192 void *mapped_ptr;
193
194 /* Firstly, map a single page to be able to read package header. */
195 mapped_ptr = mm_identity_map(stage1_locked, pkg_start, pkg_first_page,
196 MM_MODE_R, ppool);
197 assert(mapped_ptr != NULL);
198 assert(pkg != NULL);
199
200 magic = (uint32_t *)mapped_ptr;
201
202 switch (*magic) {
203 case SP_PKG_HEADER_MAGIC:
204 /*
205 * Leave memory mapped in case it succeeded, to be cleared
206 * later.
207 */
208 if (!partition_pkg_from_sp_pkg(stage1_locked, pkg_start, pkg,
209 ppool)) {
210 goto out;
211 }
212 break;
J-Alves01337a32024-11-18 17:51:59 +0000213 case TRANSFER_LIST_SIGNATURE:
214 if (!partition_pkg_from_tl(stage1_locked, pkg_start, pkg,
215 ppool)) {
216 goto out;
217 }
218 break;
J-Alves6e0abc42024-12-30 16:51:16 +0000219 default:
220 dlog_error("%s: invalid secure partition package %x @ %lx\n",
221 __func__, *magic, (uint64_t)magic);
222 goto out;
223 }
224
225 dump_partition_package(pkg);
226
227 /**
228 * The total memory range should encompass the remaining.
229 * Assert that none of the memory ranges are out of bounds.
230 */
231 assert(mem_range_contains_range(pkg->total, pkg->img));
232 assert(mem_range_contains_range(pkg->total, pkg->pm));
233 assert(mem_range_contains_range(pkg->total, pkg->boot_info));
234 assert(!mem_range_is_valid(pkg->hob) ||
235 mem_range_contains_range(pkg->total, pkg->hob));
236
237 /* Map Boot info section as RW. */
238 if (pa_addr(pkg->boot_info.begin) != 0U &&
239 pa_addr(pkg->boot_info.end) != 0U) {
240 CHECK(mm_identity_map(stage1_locked, pkg->boot_info.begin,
241 pkg->boot_info.end, MM_MODE_R | MM_MODE_W,
242 ppool) != NULL);
243 }
244
245 ret = true;
246
247out:
248 /* If failing unmap the memory. */
249 if (!ret) {
250 CHECK(mm_unmap(stage1_locked, pkg_start, pkg_first_page,
251 ppool));
252 }
253
254 return ret;
255}
256
257void partition_pkg_deinit(struct mm_stage1_locked stage1_locked,
258 struct partition_pkg *pkg, struct mpool *ppool)
259{
260 CHECK(mm_unmap(stage1_locked, pkg->total.begin, pkg->total.end, ppool));
261}