blob: 940d5ac93df40e0903860f16a058ca1606e1b186 [file] [log] [blame]
David Brazdil7a462ec2019-08-15 12:27:47 +01001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * 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.
David Brazdil7a462ec2019-08-15 12:27:47 +01007 */
8
David Brazdil52256ff2019-08-23 15:15:15 +01009#include <array>
Karl Meakincedbdf92024-11-19 13:47:53 +000010#include <format>
Andrew Scullae9962e2019-10-03 16:51:16 +010011#include <span>
David Brazdil52256ff2019-08-23 15:15:15 +010012
David Brazdil7a462ec2019-08-15 12:27:47 +010013#include <gmock/gmock.h>
14
15extern "C" {
J-Alves2f86c1e2022-02-23 18:44:19 +000016#include "hf/arch/std.h"
17
J-Alves77b6f4f2023-03-15 11:34:49 +000018#include "hf/boot_params.h"
David Brazdil7a462ec2019-08-15 12:27:47 +010019#include "hf/manifest.h"
Karl Meakin0f506a12025-02-08 23:28:45 +000020#include "hf/mm.h"
J-Alves2f86c1e2022-02-23 18:44:19 +000021#include "hf/sp_pkg.h"
David Brazdil7a462ec2019-08-15 12:27:47 +010022}
23
24namespace
25{
Andrew Scullae9962e2019-10-03 16:51:16 +010026using ::testing::ElementsAre;
David Brazdil7a462ec2019-08-15 12:27:47 +010027using ::testing::Eq;
Andrew Scullae9962e2019-10-03 16:51:16 +010028using ::testing::IsEmpty;
David Brazdil7a462ec2019-08-15 12:27:47 +010029using ::testing::NotNull;
30
Daniel Boulby801f8ef2022-06-27 14:21:01 +010031using struct_manifest = struct manifest;
32
J-Alves5c0ae6f2023-06-14 15:20:21 +010033constexpr size_t TEST_HEAP_SIZE = PAGE_SIZE * 128;
Daniel Boulby801f8ef2022-06-27 14:21:01 +010034
David Brazdil52256ff2019-08-23 15:15:15 +010035template <typename T>
David Brazdil0dbb41f2019-09-09 18:03:35 +010036void exec(const char *program, const char *args[], const T &stdin,
David Brazdil52256ff2019-08-23 15:15:15 +010037 std::vector<char> *stdout)
38{
39 /* Create two pipes, one for stdin and one for stdout. */
40 int pipes[2][2];
41 pipe(pipes[0]);
42 pipe(pipes[1]);
David Brazdil7a462ec2019-08-15 12:27:47 +010043
David Brazdil52256ff2019-08-23 15:15:15 +010044 /* Assign FDs for reading/writing by the parent/child. */
45 int parent_read_fd = pipes[1][0]; /* stdout pipe, read FD */
46 int parent_write_fd = pipes[0][1]; /* stdin pipe, write FD */
47 int child_read_fd = pipes[0][0]; /* stdin pipe, read FD */
48 int child_write_fd = pipes[1][1]; /* stdout pipe, write FD */
David Brazdil7a462ec2019-08-15 12:27:47 +010049
David Brazdil52256ff2019-08-23 15:15:15 +010050 if (fork()) {
51 /* Parent process. */
52 std::array<char, 128> buf;
53 ssize_t res;
54
55 /* Close child FDs which won't be used. */
56 close(child_read_fd);
57 close(child_write_fd);
58
59 /* Write to stdin. */
60 for (size_t count = 0; count < stdin.size();) {
61 res = write(parent_write_fd, stdin.data() + count,
62 stdin.size() - count);
63 if (res < 0) {
64 std::cerr << "IO error" << std::endl;
65 exit(1);
66 }
67 count += res;
68 }
69 close(parent_write_fd);
70
71 /* Read from stdout. */
72 while (true) {
73 res = read(parent_read_fd, buf.data(), buf.size());
74 if (res == 0) {
75 /* EOF */
76 break;
77 } else if (res < 0) {
78 std::cerr << "IO error" << std::endl;
79 exit(1);
80 }
81 stdout->insert(stdout->end(), buf.begin(),
82 buf.begin() + res);
83 }
84 close(parent_read_fd);
85 } else {
86 /* Child process. */
87
88 /* Redirect stdin/stdout to read/write FDs. */
89 dup2(child_read_fd, STDIN_FILENO);
90 dup2(child_write_fd, STDOUT_FILENO);
91
92 /* Close all FDs which are now unused. */
93 close(child_read_fd);
94 close(child_write_fd);
95 close(parent_read_fd);
96 close(parent_write_fd);
97
98 /* Execute the given program. */
David Brazdil0dbb41f2019-09-09 18:03:35 +010099 execv(program, const_cast<char *const *>(args));
David Brazdil52256ff2019-08-23 15:15:15 +0100100 }
101}
102
103/**
104 * Class for programatically building a Device Tree.
105 *
106 * Usage:
107 * std::vector<char> dtb = ManifestDtBuilder()
108 * .Command1()
109 * .Command2()
110 * ...
111 * .CommandN()
112 * .Build();
113 */
114class ManifestDtBuilder
115{
116 public:
117 ManifestDtBuilder()
118 {
119 dts_ << "/dts-v1/;" << std::endl;
120 dts_ << std::endl;
121
122 /* Start root node. */
123 StartChild("/");
124 }
125
Andrew Scullae9962e2019-10-03 16:51:16 +0100126 std::vector<char> Build(bool dump = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100127 {
David Brazdil0dbb41f2019-09-09 18:03:35 +0100128 const char *program = "./build/image/dtc.py";
129 const char *dtc_args[] = {program, "compile", NULL};
David Brazdil52256ff2019-08-23 15:15:15 +0100130 std::vector<char> dtc_stdout;
131
132 /* Finish root node. */
133 EndChild();
134
Andrew Scullae9962e2019-10-03 16:51:16 +0100135 if (dump) {
136 Dump();
137 }
138
David Brazdil0dbb41f2019-09-09 18:03:35 +0100139 exec(program, dtc_args, dts_.str(), &dtc_stdout);
David Brazdil52256ff2019-08-23 15:15:15 +0100140 return dtc_stdout;
141 }
142
Andrew Scullae9962e2019-10-03 16:51:16 +0100143 void Dump()
144 {
145 std::cerr << dts_.str() << std::endl;
146 }
147
David Brazdil52256ff2019-08-23 15:15:15 +0100148 ManifestDtBuilder &StartChild(const std::string_view &name)
149 {
150 dts_ << name << " {" << std::endl;
151 return *this;
152 }
153
154 ManifestDtBuilder &EndChild()
155 {
156 dts_ << "};" << std::endl;
157 return *this;
158 }
159
David Brazdil74e9c3b2019-08-28 11:09:08 +0100160 ManifestDtBuilder &Compatible(const std::vector<std::string_view>
161 &value = {"hafnium,hafnium"})
162 {
163 return StringListProperty("compatible", value);
164 }
165
David Brazdil52256ff2019-08-23 15:15:15 +0100166 ManifestDtBuilder &DebugName(const std::string_view &value)
167 {
168 return StringProperty("debug_name", value);
169 }
170
Manish Pandey6542f5c2020-04-27 14:37:46 +0100171 ManifestDtBuilder &Description(const std::string_view &value)
172 {
173 return StringProperty("description", value);
174 }
175
David Brazdil52256ff2019-08-23 15:15:15 +0100176 ManifestDtBuilder &KernelFilename(const std::string_view &value)
177 {
178 return StringProperty("kernel_filename", value);
179 }
180
David Brazdile6f83222019-09-23 14:47:37 +0100181 ManifestDtBuilder &RamdiskFilename(const std::string_view &value)
182 {
183 return StringProperty("ramdisk_filename", value);
184 }
185
David Brazdil080ee312020-02-25 15:30:30 -0800186 ManifestDtBuilder &BootAddress(uint64_t value)
187 {
188 return Integer64Property("boot_address", value);
189 }
190
Andrew Scullae9962e2019-10-03 16:51:16 +0100191 ManifestDtBuilder &VcpuCount(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100192 {
193 return IntegerProperty("vcpu_count", value);
194 }
195
Andrew Scullae9962e2019-10-03 16:51:16 +0100196 ManifestDtBuilder &MemSize(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100197 {
198 return IntegerProperty("mem_size", value);
199 }
200
Andrew Scullae9962e2019-10-03 16:51:16 +0100201 ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
202 {
203 return IntegerListProperty("smc_whitelist", value);
204 }
205
206 ManifestDtBuilder &SmcWhitelistPermissive()
207 {
208 return BooleanProperty("smc_whitelist_permissive");
209 }
210
Olivier Deprez62d99e32020-01-09 15:58:07 +0100211 ManifestDtBuilder &LoadAddress(uint64_t value)
212 {
Karl Meakincedbdf92024-11-19 13:47:53 +0000213 return Integer64Property("load_address", value, true);
Olivier Deprez62d99e32020-01-09 15:58:07 +0100214 }
215
216 ManifestDtBuilder &FfaPartition()
217 {
218 return BooleanProperty("is_ffa_partition");
219 }
220
Andrew Scullae9962e2019-10-03 16:51:16 +0100221 ManifestDtBuilder &Property(const std::string_view &name,
222 const std::string_view &value)
223 {
224 dts_ << name << " = " << value << ";" << std::endl;
225 return *this;
226 }
227
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100228 ManifestDtBuilder &Label(const std::string_view &name)
229 {
230 dts_ << name << ": ";
231 return *this;
232 }
233
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100234 ManifestDtBuilder &FfaValidManifest()
235 {
236 Compatible({"arm,ffa-manifest-1.0"});
237 Property("ffa-version", "<0x10000>");
238 Property("uuid",
239 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>");
240 Property("execution-ctx-count", "<1>");
241 Property("exception-level", "<2>");
242 Property("execution-state", "<0>");
J-Alves2f86c1e2022-02-23 18:44:19 +0000243 Property("entrypoint-offset", "<0x00002000>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100244 Property("xlat-granule", "<0>");
J-Alvesb37fd082020-10-22 12:29:21 +0100245 Property("boot-order", "<0>");
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400246 Property("messaging-method", "<0x4>");
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500247 Property("ns-interrupts-action", "<1>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100248 return *this;
249 }
250
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400251 ManifestDtBuilder &FfaLoadAddress(uint64_t value)
252 {
Karl Meakincedbdf92024-11-19 13:47:53 +0000253 Integer64Property("load-address", value, true);
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400254 return *this;
255 }
256
David Brazdil52256ff2019-08-23 15:15:15 +0100257 ManifestDtBuilder &StringProperty(const std::string_view &name,
258 const std::string_view &value)
259 {
260 dts_ << name << " = \"" << value << "\";" << std::endl;
261 return *this;
262 }
263
David Brazdil74e9c3b2019-08-28 11:09:08 +0100264 ManifestDtBuilder &StringListProperty(
265 const std::string_view &name,
266 const std::vector<std::string_view> &value)
267 {
268 bool is_first = true;
269
270 dts_ << name << " = ";
271 for (const std::string_view &entry : value) {
272 if (is_first) {
273 is_first = false;
274 } else {
275 dts_ << ", ";
276 }
277 dts_ << "\"" << entry << "\"";
278 }
279 dts_ << ";" << std::endl;
280 return *this;
281 }
282
David Brazdil52256ff2019-08-23 15:15:15 +0100283 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Karl Meakincedbdf92024-11-19 13:47:53 +0000284 uint32_t value, bool hex = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100285 {
Karl Meakincedbdf92024-11-19 13:47:53 +0000286 std::ostream_iterator<char> out(dts_);
287
288 if (hex) {
289 std::format_to(out, "{} = <{:#08x}>;\n", name, value);
290 } else {
291 std::format_to(out, "{} = <{}>;\n", name, value);
292 }
David Brazdil52256ff2019-08-23 15:15:15 +0100293 return *this;
294 }
295
David Brazdil080ee312020-02-25 15:30:30 -0800296 ManifestDtBuilder &Integer64Property(const std::string_view &name,
Karl Meakincedbdf92024-11-19 13:47:53 +0000297 uint64_t value, bool hex = false)
David Brazdil080ee312020-02-25 15:30:30 -0800298 {
299 uint32_t high = value >> 32;
300 uint32_t low = (uint32_t)value;
Karl Meakincedbdf92024-11-19 13:47:53 +0000301 std::ostream_iterator<char> out(dts_);
302
303 if (hex) {
304 std::format_to(out, "{} = <{:#08x} {:#08x}>;\n", name,
305 high, low);
306 } else {
307 std::format_to(out, "{} = <{} {}>;\n", name, high, low);
308 }
309
David Brazdil080ee312020-02-25 15:30:30 -0800310 return *this;
311 }
312
Andrew Scullae9962e2019-10-03 16:51:16 +0100313 ManifestDtBuilder &IntegerListProperty(
314 const std::string_view &name,
315 const std::vector<uint32_t> &value)
316 {
317 dts_ << name << " = < ";
318 for (const uint32_t entry : value) {
319 dts_ << entry << " ";
320 }
321 dts_ << ">;" << std::endl;
322 return *this;
323 }
324
325 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
326 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000327 dts_ << name << ";" << std::endl;
328 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100329 }
330
David Brazdil52256ff2019-08-23 15:15:15 +0100331 std::stringstream dts_;
332};
333
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100334class manifest : public ::testing::Test
David Brazdil0dbb41f2019-09-09 18:03:35 +0100335{
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100336 void SetUp() override
337 {
338 test_heap = std::make_unique<uint8_t[]>(TEST_HEAP_SIZE);
339 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
340 mpool_add_chunk(&ppool, test_heap.get(), TEST_HEAP_SIZE);
341 }
342
Olivier Deprez93644652022-09-09 11:01:12 +0200343 void TearDown() override
344 {
345 manifest_dealloc();
346 }
347
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100348 std::unique_ptr<uint8_t[]> test_heap;
349
350 protected:
Olivier Deprez62d99e32020-01-09 15:58:07 +0100351 struct mpool ppool;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100352
Olivier Deprez93644652022-09-09 11:01:12 +0200353 void manifest_dealloc(void)
354 {
355 manifest_deinit(&ppool);
356 }
357
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100358 public:
359 /**
360 * Class for programatically building a Partition package.
361 */
362 class Partition_package
363 {
364 public:
Karl Meakinf42eaf32025-03-19 15:10:47 +0000365 alignas(PAGE_SIZE) struct sp_pkg_header spkg;
366 alignas(PAGE_SIZE) char manifest_dtb[PAGE_SIZE] = {};
367 alignas(PAGE_SIZE) char img[PAGE_SIZE] = {};
David Brazdil0dbb41f2019-09-09 18:03:35 +0100368
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100369 Partition_package(const std::vector<char> &vec)
370 {
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400371 init(vec);
372 }
373
374 Partition_package()
375 {
376 }
377
378 void init(const std::vector<char> &vec)
379 {
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100380 // Initialise header field
381 spkg.magic = SP_PKG_HEADER_MAGIC;
382 spkg.version = SP_PKG_HEADER_VERSION_2;
383 spkg.pm_offset = PAGE_SIZE;
384 spkg.pm_size = vec.size();
385 spkg.img_offset = 2 * PAGE_SIZE;
386 spkg.img_size = ARRAY_SIZE(img);
387
388 // Copy dtb into package
389 std::copy(vec.begin(), vec.end(), manifest_dtb);
390 }
391 };
392
J-Alves77b6f4f2023-03-15 11:34:49 +0000393 static void boot_params_init(struct boot_params *params,
394 Partition_package *pkg)
395 {
396 /*
397 * For the manifest tests we only care about the memory ranges
398 * in boot_params.
399 */
400 params->mem_ranges[0].begin = pa_init((uintpaddr_t)0x7000000);
401 params->mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
402 params->mem_ranges_count = 1;
403
404 if (pkg != nullptr) {
405 auto mem_base = (uintpaddr_t)pkg;
406 uintpaddr_t mem_end =
407 mem_base + sp_pkg_get_mem_size(&pkg->spkg);
408
409 params->mem_ranges_count++;
410
411 params->mem_ranges[1].begin = pa_init(mem_base);
412 params->mem_ranges[1].end = pa_init(mem_end);
413 }
414
415 params->ns_mem_ranges[0].begin =
416 pa_init((uintpaddr_t)0x7000000);
417 params->ns_mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
418 params->ns_mem_ranges_count = 1;
Daniel Boulby4339edc2024-02-21 14:59:00 +0000419
420 params->ns_device_mem_ranges[0].begin =
421 pa_init((uintpaddr_t)0x20000000);
422 params->ns_device_mem_ranges[0].end =
423 pa_init((uintpaddr_t)0x24000000);
424 params->ns_device_mem_ranges_count = 1;
425
426 params->device_mem_ranges[0].begin =
427 pa_init((uintpaddr_t)0x24000000);
428 params->device_mem_ranges[0].end =
429 pa_init((uintpaddr_t)0x28000000);
430 params->device_mem_ranges_count = 1;
J-Alves77b6f4f2023-03-15 11:34:49 +0000431 }
432
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100433 enum manifest_return_code manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200434 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100435 {
436 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +0000437 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
J-Alves77b6f4f2023-03-15 11:34:49 +0000438 struct boot_params params;
Karl Meakin0f506a12025-02-08 23:28:45 +0000439 enum manifest_return_code ret;
J-Alves77b6f4f2023-03-15 11:34:49 +0000440
441 boot_params_init(&params, nullptr);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100442
443 memiter_init(&it, vec.data(), vec.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100444
Karl Meakin0f506a12025-02-08 23:28:45 +0000445 ret = manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
446 mm_unlock_stage1(&mm_stage1_locked);
447 return ret;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100448 }
449
Karl Meakin6291eb22024-11-18 12:43:47 +0000450 enum manifest_return_code ffa_manifest_from_spkg(
451 struct_manifest **m, Partition_package *spkg)
452 {
453 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +0000454 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
Karl Meakin6291eb22024-11-18 12:43:47 +0000455 struct boot_params params;
Karl Meakin0f506a12025-02-08 23:28:45 +0000456 enum manifest_return_code ret;
Karl Meakin6291eb22024-11-18 12:43:47 +0000457
458 boot_params_init(&params, spkg);
459
460 /* clang-format off */
461 std::vector<char> core_dtb = ManifestDtBuilder()
462 .StartChild("hypervisor")
463 .Compatible()
464 .StartChild("vm1")
465 .DebugName("primary_vm")
466 .FfaPartition()
467 .LoadAddress((uint64_t)spkg)
468 .EndChild()
469 .EndChild()
470 .Build(true);
471 /* clang-format on */
472 memiter_init(&it, core_dtb.data(), core_dtb.size());
473
Karl Meakin0f506a12025-02-08 23:28:45 +0000474 ret = manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
475 mm_unlock_stage1(&mm_stage1_locked);
476 return ret;
Karl Meakin6291eb22024-11-18 12:43:47 +0000477 }
478
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100479 enum manifest_return_code ffa_manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200480 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100481 {
482 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +0000483 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100484 Partition_package spkg(vec);
J-Alves77b6f4f2023-03-15 11:34:49 +0000485 struct boot_params params;
Karl Meakin0f506a12025-02-08 23:28:45 +0000486 enum manifest_return_code ret;
J-Alves77b6f4f2023-03-15 11:34:49 +0000487
488 boot_params_init(&params, &spkg);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100489
490 /* clang-format off */
491 std::vector<char> core_dtb = ManifestDtBuilder()
492 .StartChild("hypervisor")
493 .Compatible()
494 .StartChild("vm1")
495 .DebugName("primary_vm")
496 .FfaPartition()
497 .LoadAddress((uint64_t)&spkg)
498 .EndChild()
499 .EndChild()
500 .Build();
501 /* clang-format on */
502 memiter_init(&it, core_dtb.data(), core_dtb.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100503
Karl Meakin0f506a12025-02-08 23:28:45 +0000504 ret = manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
505 mm_unlock_stage1(&mm_stage1_locked);
506 return ret;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100507 }
508};
509
510TEST_F(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100511{
Olivier Deprez93644652022-09-09 11:01:12 +0200512 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100513 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100514
David Brazdila2358d42020-01-27 18:51:38 +0000515 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100516 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
517}
518
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100519TEST_F(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100520{
Olivier Deprez93644652022-09-09 11:01:12 +0200521 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100522
David Brazdil52256ff2019-08-23 15:15:15 +0100523 /* clang-format off */
524 std::vector<char> dtb = ManifestDtBuilder()
525 .StartChild("hypervisor")
526 .EndChild()
527 .Build();
528 /* clang-format on */
529
David Brazdilf4925382020-03-25 13:33:51 +0000530 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100531}
532
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100533TEST_F(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100534{
Olivier Deprez93644652022-09-09 11:01:12 +0200535 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100536
David Brazdil52256ff2019-08-23 15:15:15 +0100537 /* clang-format off */
538 std::vector<char> dtb = ManifestDtBuilder()
539 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100540 .Compatible({ "foo,bar" })
541 .EndChild()
542 .Build();
543 /* clang-format on */
544
David Brazdila2358d42020-01-27 18:51:38 +0000545 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100546}
547
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100548TEST_F(manifest, compatible_one_of_many)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100549{
Olivier Deprez93644652022-09-09 11:01:12 +0200550 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100551
552 /* clang-format off */
553 std::vector<char> dtb = ManifestDtBuilder()
554 .StartChild("hypervisor")
555 .Compatible({ "foo,bar", "hafnium,hafnium" })
556 .StartChild("vm1")
557 .DebugName("primary")
558 .EndChild()
559 .EndChild()
560 .Build();
561 /* clang-format on */
562
David Brazdila2358d42020-01-27 18:51:38 +0000563 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100564}
565
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100566TEST_F(manifest, no_vm_nodes)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100567{
Olivier Deprez93644652022-09-09 11:01:12 +0200568 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100569
570 /* clang-format off */
571 std::vector<char> dtb = ManifestDtBuilder()
572 .StartChild("hypervisor")
573 .Compatible()
574 .EndChild()
575 .Build();
576 /* clang-format on */
577
David Brazdila2358d42020-01-27 18:51:38 +0000578 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100579}
580
581static std::vector<char> gen_long_string_dtb(bool valid)
582{
583 const char last_valid[] = "1234567890123456789012345678901";
584 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100585 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
586 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100587
588 /* clang-format off */
589 return ManifestDtBuilder()
590 .StartChild("hypervisor")
591 .Compatible()
592 .StartChild("vm1")
593 .DebugName(valid ? last_valid : first_invalid)
594 .EndChild()
595 .EndChild()
596 .Build();
597 /* clang-format on */
598}
599
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100600TEST_F(manifest, long_string)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100601{
Olivier Deprez93644652022-09-09 11:01:12 +0200602 struct_manifest *m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100603 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
604 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
605
David Brazdila2358d42020-01-27 18:51:38 +0000606 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200607 manifest_dealloc();
608
David Brazdila2358d42020-01-27 18:51:38 +0000609 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
610 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100611}
612
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100613TEST_F(manifest, reserved_vm_id)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100614{
Olivier Deprez93644652022-09-09 11:01:12 +0200615 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100616
617 /* clang-format off */
618 std::vector<char> dtb = ManifestDtBuilder()
619 .StartChild("hypervisor")
620 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100621 .StartChild("vm1")
622 .DebugName("primary_vm")
623 .EndChild()
624 .StartChild("vm0")
625 .DebugName("reserved_vm")
626 .VcpuCount(1)
627 .MemSize(0x1000)
628 .KernelFilename("kernel")
629 .EndChild()
630 .EndChild()
631 .Build();
632 /* clang-format on */
633
David Brazdila2358d42020-01-27 18:51:38 +0000634 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100635}
636
Andrew Scullae9962e2019-10-03 16:51:16 +0100637static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100638{
639 /* clang-format off */
640 return ManifestDtBuilder()
641 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100642 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100643 .StartChild("vm1")
644 .DebugName("primary_vm")
645 .EndChild()
646 .StartChild("vm2")
647 .DebugName("secondary_vm")
648 .VcpuCount(vcpu_count)
649 .MemSize(0x1000)
650 .KernelFilename("kernel")
651 .EndChild()
652 .EndChild()
653 .Build();
654 /* clang-format on */
655}
David Brazdil7a462ec2019-08-15 12:27:47 +0100656
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100657TEST_F(manifest, vcpu_count_limit)
David Brazdil7a462ec2019-08-15 12:27:47 +0100658{
Olivier Deprez93644652022-09-09 11:01:12 +0200659 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100660 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
661 std::vector<char> dtb_first_invalid =
662 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100663
David Brazdila2358d42020-01-27 18:51:38 +0000664 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200665 ASSERT_EQ(m->vm_count, 2);
666 ASSERT_EQ(m->vm[1].secondary.vcpu_count, UINT16_MAX);
667 manifest_dealloc();
David Brazdil7a462ec2019-08-15 12:27:47 +0100668
David Brazdila2358d42020-01-27 18:51:38 +0000669 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100670 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100671}
672
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100673TEST_F(manifest, no_ramdisk_primary)
David Brazdile6f83222019-09-23 14:47:37 +0100674{
Olivier Deprez93644652022-09-09 11:01:12 +0200675 struct_manifest *m;
David Brazdile6f83222019-09-23 14:47:37 +0100676
677 /* clang-format off */
678 std::vector<char> dtb = ManifestDtBuilder()
679 .StartChild("hypervisor")
680 .Compatible()
681 .StartChild("vm1")
682 .DebugName("primary_vm")
683 .EndChild()
684 .EndChild()
685 .Build();
686 /* clang-format on */
687
David Brazdila2358d42020-01-27 18:51:38 +0000688 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200689 ASSERT_EQ(m->vm_count, 1);
690 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
691 ASSERT_STREQ(string_data(&m->vm[0].primary.ramdisk_filename), "");
David Brazdile6f83222019-09-23 14:47:37 +0100692}
693
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100694TEST_F(manifest, no_boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800695{
Olivier Deprez93644652022-09-09 11:01:12 +0200696 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800697
698 /* clang-format off */
699 std::vector<char> dtb = ManifestDtBuilder()
700 .StartChild("hypervisor")
701 .Compatible()
702 .StartChild("vm1")
703 .DebugName("primary_vm")
704 .EndChild()
705 .EndChild()
706 .Build();
707 /* clang-format on */
708
709 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200710 ASSERT_EQ(m->vm_count, 1);
711 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
712 ASSERT_EQ(m->vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
David Brazdil080ee312020-02-25 15:30:30 -0800713}
714
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100715TEST_F(manifest, boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800716{
Olivier Deprez93644652022-09-09 11:01:12 +0200717 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800718 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
719
720 /* clang-format off */
721 std::vector<char> dtb = ManifestDtBuilder()
722 .StartChild("hypervisor")
723 .Compatible()
724 .StartChild("vm1")
725 .DebugName("primary_vm")
726 .BootAddress(addr)
727 .EndChild()
728 .EndChild()
729 .Build();
730 /* clang-format on */
731
732 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200733 ASSERT_EQ(m->vm_count, 1);
734 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
735 ASSERT_EQ(m->vm[0].primary.boot_address, addr);
David Brazdil080ee312020-02-25 15:30:30 -0800736}
737
Andrew Scullb2c3a242019-11-04 13:52:36 +0000738static std::vector<char> gen_malformed_boolean_dtb(
739 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100740{
Andrew Scullae9962e2019-10-03 16:51:16 +0100741 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000742 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100743 .StartChild("hypervisor")
744 .Compatible()
745 .StartChild("vm1")
746 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000747 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000748 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100749 .EndChild()
750 .Build();
751 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000752}
Andrew Scullae9962e2019-10-03 16:51:16 +0100753
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100754TEST_F(manifest, malformed_booleans)
Andrew Scullb2c3a242019-11-04 13:52:36 +0000755{
Olivier Deprez93644652022-09-09 11:01:12 +0200756 struct_manifest *m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100757
Andrew Scullb2c3a242019-11-04 13:52:36 +0000758 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
759 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
760 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
761 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100762
David Brazdila2358d42020-01-27 18:51:38 +0000763 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000764 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200765 manifest_dealloc();
766
David Brazdila2358d42020-01-27 18:51:38 +0000767 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000768 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200769 manifest_dealloc();
770
David Brazdila2358d42020-01-27 18:51:38 +0000771 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000772 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200773 manifest_dealloc();
774
David Brazdila2358d42020-01-27 18:51:38 +0000775 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000776 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100777}
778
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100779TEST_F(manifest, valid)
David Brazdil7a462ec2019-08-15 12:27:47 +0100780{
Olivier Deprez93644652022-09-09 11:01:12 +0200781 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100782 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100783
David Brazdil52256ff2019-08-23 15:15:15 +0100784 /* clang-format off */
785 std::vector<char> dtb = ManifestDtBuilder()
786 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100787 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100788 .StartChild("vm1")
789 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100790 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100791 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100792 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100793 .EndChild()
794 .StartChild("vm3")
795 .DebugName("second_secondary_vm")
796 .VcpuCount(43)
797 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100798 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100799 .EndChild()
800 .StartChild("vm2")
801 .DebugName("first_secondary_vm")
802 .VcpuCount(42)
803 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100804 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
805 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100806 .EndChild()
807 .EndChild()
808 .Build();
809 /* clang-format on */
810
David Brazdila2358d42020-01-27 18:51:38 +0000811 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200812 ASSERT_EQ(m->vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100813
Olivier Deprez93644652022-09-09 11:01:12 +0200814 vm = &m->vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100815 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
816 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100817 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
818 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100819 ASSERT_THAT(
820 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
821 ElementsAre(0x32000000, 0x33001111));
822 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100823
Olivier Deprez93644652022-09-09 11:01:12 +0200824 vm = &m->vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100825 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
826 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100827 ASSERT_EQ(vm->secondary.vcpu_count, 42);
828 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100829 ASSERT_THAT(
830 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
831 ElementsAre(0x04000000, 0x30002222, 0x31445566));
832 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100833
Olivier Deprez93644652022-09-09 11:01:12 +0200834 vm = &m->vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100835 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
836 ASSERT_STREQ(string_data(&vm->kernel_filename),
837 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100838 ASSERT_EQ(vm->secondary.vcpu_count, 43);
839 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100840 ASSERT_THAT(
841 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
842 IsEmpty());
843 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100844}
845
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100846TEST_F(manifest, ffa_not_compatible)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100847{
Olivier Deprez93644652022-09-09 11:01:12 +0200848 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100849
850 /* clang-format off */
851 std::vector<char> dtb = ManifestDtBuilder()
852 .Compatible({ "arm,ffa-manifest-2.0" })
853 .Property("ffa-version", "<0x10000>")
854 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
855 .Property("execution-ctx-count", "<1>")
856 .Property("exception-level", "<2>")
857 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000858 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100859 .Property("xlat-granule", "<0>")
860 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500861 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100862 .Build();
863 /* clang-format on */
864
865 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
866 MANIFEST_ERROR_NOT_COMPATIBLE);
867}
868
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100869TEST_F(manifest, ffa_missing_property)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100870{
Olivier Deprez93644652022-09-09 11:01:12 +0200871 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100872
873 /* clang-format off */
874 std::vector<char> dtb = ManifestDtBuilder()
875 .Compatible({ "arm,ffa-manifest-1.0" })
876 .Property("ffa-version", "<0x10000>")
877 .Build();
878 /* clang-format on */
879
880 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
881 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
882}
883
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100884TEST_F(manifest, ffa_validate_sanity_check)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100885{
J-Alvesb37fd082020-10-22 12:29:21 +0100886 /*
887 * TODO: write test excluding all optional fields of the manifest, in
888 * accordance with specification.
889 */
Olivier Deprez93644652022-09-09 11:01:12 +0200890 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100891
892 /* Incompatible version */
893 /* clang-format off */
894 std::vector<char> dtb = ManifestDtBuilder()
895 .Compatible({ "arm,ffa-manifest-1.0" })
896 .Property("ffa-version", "<0xa1>")
897 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
898 .Property("execution-ctx-count", "<1>")
899 .Property("exception-level", "<2>")
900 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000901 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100902 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100903 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100904 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500905 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100906 .Build();
907 /* clang-format on */
908 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
909 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200910 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100911
912 /* Incompatible translation granule */
913 /* clang-format off */
914 dtb = ManifestDtBuilder()
915 .Compatible({ "arm,ffa-manifest-1.0" })
916 .Property("ffa-version", "<0x10000>")
917 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
918 .Property("execution-ctx-count", "<1>")
919 .Property("exception-level", "<2>")
920 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000921 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100922 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100923 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100924 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500925 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100926 .Build();
927 /* clang-format on */
928 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
929 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200930 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100931
932 /* Incompatible exeption level */
933 /* clang-format off */
934 dtb = ManifestDtBuilder()
935 .Compatible({ "arm,ffa-manifest-1.0" })
936 .Property("ffa-version", "<0x10000>")
937 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
938 .Property("execution-ctx-count", "<1>")
Daniel Boulby874d5432023-04-27 12:40:24 +0100939 .Property("exception-level", "<10>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100940 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000941 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100942 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100943 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100944 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500945 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100946 .Build();
947 /* clang-format on */
948 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
949 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200950 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100951
952 /* Incompatible execution state */
953 /* clang-format off */
954 dtb = ManifestDtBuilder()
955 .Compatible({ "arm,ffa-manifest-1.0" })
956 .Property("ffa-version", "<0x10000>")
957 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
958 .Property("execution-ctx-count", "<1>")
959 .Property("exception-level", "<2>")
960 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000961 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100962 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100963 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100964 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500965 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100966 .Build();
967 /* clang-format on */
968 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
969 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200970 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100971
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400972 /* Incompatible messaging method - unrecognized messaging-method. */
973 /* clang-format off */
974 dtb = ManifestDtBuilder()
975 .Compatible({ "arm,ffa-manifest-1.0" })
976 .Property("ffa-version", "<0x10002>")
977 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
978 .Property("execution-ctx-count", "<1>")
979 .Property("exception-level", "<2>")
980 .Property("execution-state", "<0>")
981 .Property("entrypoint-offset", "<0x00002000>")
982 .Property("xlat-granule", "<0>")
983 .Property("boot-order", "<0>")
984 .Property("messaging-method", "<0x272>")
985 .Property("ns-interrupts-action", "<0>")
986 .Build();
987 /* clang-format on */
988 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
989 MANIFEST_ERROR_NOT_COMPATIBLE);
990 manifest_dealloc();
991
992 /* Incompatible messaging method - only endpoints using FF-A version >=
993 * FF-A v1.2 are allowed to set FFA_PARTITION_DIRECT_REQ2_RECV and
994 * FFA_PARTITION_DIRECT_REQ2_SEND. */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100995 /* clang-format off */
996 dtb = ManifestDtBuilder()
997 .Compatible({ "arm,ffa-manifest-1.0" })
998 .Property("ffa-version", "<0x10000>")
999 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1000 .Property("execution-ctx-count", "<1>")
1001 .Property("exception-level", "<2>")
1002 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +00001003 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +01001004 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +01001005 .Property("boot-order", "<0>")
Kathleen Capellaf71dee42023-08-08 16:24:14 -04001006 .Property("messaging-method", "<0x204>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -05001007 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +01001008 .Build();
1009 /* clang-format on */
1010 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1011 MANIFEST_ERROR_NOT_COMPATIBLE);
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001012
1013 /*
1014 * No need to invoke manifest_dealloac() since manifest TearDown calls
1015 * it when the test ends.
1016 */
1017}
1018
1019TEST_F(manifest, ffa_validate_interrupt_actions)
1020{
1021 struct_manifest *m;
Madhukar Pappireddy84154052022-06-21 18:30:25 -05001022
1023 /* Incompatible NS interrupt action */
1024 /* clang-format off */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001025 std::vector<char> dtb = ManifestDtBuilder()
Madhukar Pappireddy84154052022-06-21 18:30:25 -05001026 .Compatible({ "arm,ffa-manifest-1.0" })
1027 .Property("ffa-version", "<0x10000>")
1028 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1029 .Property("execution-ctx-count", "<1>")
1030 .Property("exception-level", "<2>")
1031 .Property("execution-state", "<0>")
1032 .Property("entrypoint-offset", "<0x00002000>")
1033 .Property("xlat-granule", "<0>")
1034 .Property("boot-order", "<0>")
1035 .Property("messaging-method", "<1>")
1036 .Property("ns-interrupts-action", "<4>")
1037 .Build();
1038 /* clang-format on */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001039 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1040 MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
Madhukar Pappireddyee736ad2022-12-28 11:37:09 -06001041 manifest_dealloc();
1042
1043 /* Incompatible other-s-interrupts-action for S-EL1 partition */
1044 /* clang-format off */
1045 dtb = ManifestDtBuilder()
1046 .Compatible({ "arm,ffa-manifest-1.0" })
1047 .Property("ffa-version", "<0x10000>")
1048 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1049 .Property("execution-ctx-count", "<1>")
1050 .Property("exception-level", "<2>")
1051 .Property("execution-state", "<0>")
1052 .Property("entrypoint-offset", "<0x00002000>")
1053 .Property("xlat-granule", "<0>")
1054 .Property("boot-order", "<0>")
1055 .Property("messaging-method", "<1>")
1056 .Property("ns-interrupts-action", "<1>")
1057 .Property("other-s-interrupts-action", "<0>")
1058 .Build();
1059 /* clang-format on */
1060 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1061 MANIFEST_ERROR_NOT_COMPATIBLE);
1062 manifest_dealloc();
1063
1064 /*
1065 * Incompatible choice of the fields ns-interrupts-action and
1066 * other-s-interrupts-action.
1067 */
1068 /* clang-format off */
1069 dtb = ManifestDtBuilder()
1070 .Compatible({ "arm,ffa-manifest-1.0" })
1071 .Property("ffa-version", "<0x10000>")
1072 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1073 .Property("execution-ctx-count", "<1>")
1074 .Property("exception-level", "<1>")
1075 .Property("execution-state", "<0>")
1076 .Property("entrypoint-offset", "<0x00002000>")
1077 .Property("xlat-granule", "<0>")
1078 .Property("boot-order", "<0>")
1079 .Property("messaging-method", "<1>")
1080 .Property("ns-interrupts-action", "<2>")
1081 .Property("other-s-interrupts-action", "<0>")
1082 .Build();
1083 /* clang-format on */
1084 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1085 MANIFEST_ERROR_NOT_COMPATIBLE);
1086 manifest_dealloc();
1087
1088 /* Illegal value specified for the field other-s-interrupts-action. */
1089 /* clang-format off */
1090 dtb = ManifestDtBuilder()
1091 .Compatible({ "arm,ffa-manifest-1.0" })
1092 .Property("ffa-version", "<0x10000>")
1093 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1094 .Property("execution-ctx-count", "<1>")
1095 .Property("exception-level", "<1>")
1096 .Property("execution-state", "<0>")
1097 .Property("entrypoint-offset", "<0x00002000>")
1098 .Property("xlat-granule", "<0>")
1099 .Property("boot-order", "<0>")
1100 .Property("messaging-method", "<1>")
1101 .Property("other-s-interrupts-action", "<2>")
1102 .Build();
1103 /* clang-format on */
1104 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1105 MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001106}
1107
Karl Meakin18694022024-08-02 13:59:25 +01001108TEST_F(manifest, vm_availability_messages)
1109{
1110 struct manifest_vm *vm;
1111 struct_manifest *m;
1112 std::vector<char> dtb;
1113
1114 /* clang-format off */
1115 dtb = ManifestDtBuilder()
1116 .Compatible({ "arm,ffa-manifest-1.0" })
1117 .Property("ffa-version", "<0x10001>")
1118 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1119 .Property("execution-ctx-count", "<8>")
1120 .Property("exception-level", "<2>")
1121 .Property("execution-state", "<0>")
1122 .Property("entrypoint-offset", "<0x00002000>")
1123 .Property("messaging-method", "<1>")
1124 .Property("vm-availability-messages", "<0>")
1125 .Build();
1126 /* clang-format on */
1127 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1128 vm = &m->vm[0];
1129 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1130 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1131 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1132 manifest_dealloc();
1133
1134 /* clang-format off */
1135 dtb = ManifestDtBuilder()
1136 .Compatible({ "arm,ffa-manifest-1.0" })
1137 .Property("ffa-version", "<0x10001>")
1138 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1139 .Property("execution-ctx-count", "<8>")
1140 .Property("exception-level", "<2>")
1141 .Property("execution-state", "<0>")
1142 .Property("entrypoint-offset", "<0x00002000>")
1143 .Property("messaging-method", "<1>")
1144 .Property("vm-availability-messages", "<1>")
1145 .Build();
1146 /* clang-format on */
1147 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1148 vm = &m->vm[0];
1149 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1150 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1151 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1152 manifest_dealloc();
1153
1154 /* clang-format off */
1155 dtb = ManifestDtBuilder()
1156 .Compatible({ "arm,ffa-manifest-1.0" })
1157 .Property("ffa-version", "<0x10001>")
1158 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1159 .Property("execution-ctx-count", "<8>")
1160 .Property("exception-level", "<2>")
1161 .Property("execution-state", "<0>")
1162 .Property("entrypoint-offset", "<0x00002000>")
1163 .Property("messaging-method", "<1>")
1164 .Property("vm-availability-messages", "<2>")
1165 .Build();
1166 /* clang-format on */
1167 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1168 vm = &m->vm[0];
1169 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1170 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1171 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1172 manifest_dealloc();
1173
1174 /* clang-format off */
1175 dtb = ManifestDtBuilder()
1176 .Compatible({ "arm,ffa-manifest-1.0" })
1177 .Property("ffa-version", "<0x10001>")
1178 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1179 .Property("execution-ctx-count", "<8>")
1180 .Property("exception-level", "<2>")
1181 .Property("execution-state", "<0>")
1182 .Property("entrypoint-offset", "<0x00002000>")
1183 .Property("messaging-method", "<1>")
1184 .Property("vm-availability-messages", "<3>")
1185 .Build();
1186 /* clang-format on */
1187 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1188 vm = &m->vm[0];
1189 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1190 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1191 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1192 manifest_dealloc();
1193
1194 /* clang-format off */
1195 dtb = ManifestDtBuilder()
1196 .Compatible({ "arm,ffa-manifest-1.0" })
1197 .Property("ffa-version", "<0x10001>")
1198 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1199 .Property("execution-ctx-count", "<8>")
1200 .Property("exception-level", "<2>")
1201 .Property("execution-state", "<0>")
1202 .Property("entrypoint-offset", "<0x00002000>")
1203 .Property("messaging-method", "<1>")
1204 .Build();
1205 /* clang-format on */
1206 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1207 vm = &m->vm[0];
1208 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1209 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1210 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1211 manifest_dealloc();
1212
1213 /* clang-format off */
1214 dtb = ManifestDtBuilder()
1215 .Compatible({ "arm,ffa-manifest-1.0" })
1216 .Property("ffa-version", "<0x10001>")
1217 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1218 .Property("execution-ctx-count", "<8>")
1219 .Property("exception-level", "<2>")
1220 .Property("execution-state", "<0>")
1221 .Property("entrypoint-offset", "<0x00002000>")
1222 .Property("messaging-method", "<2>")
1223 .Property("vm-availability-messages", "<4>")
1224 .Build();
1225 /* clang-format on */
1226 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1227 MANIFEST_ERROR_VM_AVAILABILITY_MESSAGE_INVALID);
1228 vm = &m->vm[0];
1229 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1230 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1231 ASSERT_NE(vm->partition.vm_availability_messages.mbz, 0);
1232 manifest_dealloc();
1233}
1234
Olivier Depreza15f2352022-09-26 09:17:24 +02001235TEST_F(manifest, power_management)
1236{
1237 struct manifest_vm *vm;
1238 struct_manifest *m;
1239
Madhukar Pappireddy958c8412024-11-25 09:54:17 -06001240 /* S-EL1 partition power management field can only set bit 0. */
Olivier Depreza15f2352022-09-26 09:17:24 +02001241 /* clang-format off */
1242 std::vector<char> dtb = ManifestDtBuilder()
1243 .Compatible({ "arm,ffa-manifest-1.0" })
1244 .Property("ffa-version", "<0x10001>")
1245 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1246 .Property("execution-ctx-count", "<8>")
1247 .Property("exception-level", "<2>")
1248 .Property("execution-state", "<0>")
1249 .Property("entrypoint-offset", "<0x00002000>")
1250 .Property("messaging-method", "<1>")
Olivier Depreza15f2352022-09-26 09:17:24 +02001251 .Property("power-management-messages", "<0xf>")
1252 .Build();
1253 /* clang-format on */
1254 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1255 vm = &m->vm[0];
Madhukar Pappireddy958c8412024-11-25 09:54:17 -06001256 ASSERT_EQ(vm->partition.power_management, 1);
Olivier Depreza15f2352022-09-26 09:17:24 +02001257 manifest_dealloc();
1258
1259 /* S-EL0 partition power management field is forced to 0. */
1260 /* clang-format off */
1261 dtb = ManifestDtBuilder()
1262 .Compatible({ "arm,ffa-manifest-1.0" })
1263 .Property("ffa-version", "<0x10001>")
1264 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1265 .Property("execution-ctx-count", "<1>")
1266 .Property("exception-level", "<1>")
1267 .Property("execution-state", "<0>")
1268 .Property("entrypoint-offset", "<0x00002000>")
1269 .Property("messaging-method", "<1>")
1270 .Property("power-management-messages", "<0xff>")
1271 .Build();
1272 /* clang-format on */
1273 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1274 vm = &m->vm[0];
1275 ASSERT_EQ(vm->partition.power_management, 0);
1276}
1277
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001278TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001279{
Olivier Deprez93644652022-09-09 11:01:12 +02001280 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001281
1282 /* Not Compatible */
1283 /* clang-format off */
1284 std::vector<char> dtb = ManifestDtBuilder()
1285 .FfaValidManifest()
1286 .StartChild("rx_tx-info")
1287 .Compatible({ "foo,bar" })
1288 .EndChild()
1289 .Build();
1290 /* clang-format on */
1291 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1292 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001293 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001294
1295 /* Missing Properties */
1296 /* clang-format off */
1297 dtb = ManifestDtBuilder()
1298 .FfaValidManifest()
1299 .StartChild("rx_tx-info")
1300 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1301 .EndChild()
1302 .Build();
1303 /* clang-format on */
1304 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1305 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1306}
1307
Karl Meakinf955dbe2024-11-18 16:38:58 +00001308TEST_F(manifest, ffa_validate_mem_regions_not_compatible)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001309{
Olivier Deprez93644652022-09-09 11:01:12 +02001310 struct_manifest *m;
Karl Meakinf955dbe2024-11-18 16:38:58 +00001311 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001312
1313 /* Not Compatible */
1314 /* clang-format off */
Karl Meakinf955dbe2024-11-18 16:38:58 +00001315 dtb = ManifestDtBuilder()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001316 .FfaValidManifest()
1317 .StartChild("memory-regions")
1318 .Compatible({ "foo,bar" })
1319 .EndChild()
1320 .Build();
1321 /* clang-format on */
1322 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1323 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001324 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001325}
1326
1327TEST_F(manifest, ffa_validate_mem_regions_unavailable)
1328{
1329 struct_manifest *m;
1330 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001331
1332 /* Memory regions unavailable */
1333 /* clang-format off */
1334 dtb = ManifestDtBuilder()
1335 .FfaValidManifest()
1336 .StartChild("memory-regions")
1337 .Compatible({ "arm,ffa-manifest-memory-regions" })
1338 .EndChild()
1339 .Build();
1340 /* clang-format on */
1341 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1342 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001343 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001344}
1345
1346TEST_F(manifest, ffa_validate_mem_regions_missing_properties)
1347{
1348 struct_manifest *m;
1349 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001350
1351 /* Missing Properties */
1352 /* clang-format off */
1353 dtb = ManifestDtBuilder()
1354 .FfaValidManifest()
1355 .StartChild("memory-regions")
1356 .Compatible({ "arm,ffa-manifest-memory-regions" })
1357 .StartChild("test-memory")
1358 .Description("test-memory")
1359 .EndChild()
1360 .EndChild()
1361 .Build();
1362 /* clang-format on */
1363 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1364 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001365 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001366}
1367
1368TEST_F(manifest, ffa_validate_mem_regions_empty_region)
1369{
1370 struct_manifest *m;
1371 std::vector<char> dtb;
Manish Pandeyf06c9072020-09-29 15:41:58 +01001372
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001373 /* Empty memory region */
1374 /* clang-format off */
1375 dtb = ManifestDtBuilder()
1376 .FfaValidManifest()
1377 .StartChild("memory-regions")
1378 .Compatible({ "arm,ffa-manifest-memory-regions" })
1379 .Label("rx")
1380 .StartChild("rx")
1381 .Description("rx-buffer")
1382 .Property("base-address", "<0x7300000>")
1383 .Property("pages-count", "<0>")
1384 .Property("attributes", "<1>")
1385 .EndChild()
1386 .Label("tx")
1387 .StartChild("tx")
1388 .Description("tx-buffer")
1389 .Property("base-address", "<0x7310000>")
1390 .Property("pages-count", "<2>")
1391 .Property("attributes", "<3>")
1392 .EndChild()
1393 .EndChild()
1394 .StartChild("rx_tx-info")
1395 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1396 .Property("rx-buffer", "<&rx>")
1397 .Property("tx-buffer", "<&tx>")
1398 .EndChild()
1399 .Build();
1400 /* clang-format on */
1401 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1402 MANIFEST_ERROR_MEM_REGION_EMPTY);
1403 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001404}
1405
1406TEST_F(manifest, ffa_validate_mem_regions_base_address_and_relative_offset)
1407{
1408 struct_manifest *m;
1409 std::vector<char> dtb;
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001410
Davidson K8ccd2d02024-09-03 16:10:54 +05301411 /* Mutually exclusive base-address and load-address-relative-offset
1412 * properties */
Karl Meakine92efbe2023-06-01 14:16:22 +01001413 /* clang-format off */
1414 dtb = ManifestDtBuilder()
1415 .FfaValidManifest()
1416 .StartChild("memory-regions")
1417 .Compatible({ "arm,ffa-manifest-memory-regions" })
1418 .Label("rx")
1419 .StartChild("rx")
1420 .Description("rx-buffer")
1421 .Property("base-address", "<0x7300000>")
Davidson K8ccd2d02024-09-03 16:10:54 +05301422 .Property("load-address-relative-offset", "<0x7300000>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001423 .Property("pages-count", "<1>")
1424 .Property("attributes", "<1>")
1425 .EndChild()
1426 .EndChild()
1427 .Build();
1428 /* clang-format on */
1429 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1430 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1431 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001432}
1433
1434TEST_F(manifest, ffa_validate_mem_regions_relative_address_overflow)
1435{
1436 struct_manifest *m;
1437 std::vector<char> dtb;
1438
Karl Meakine92efbe2023-06-01 14:16:22 +01001439 /* Relative-address overflow*/
1440 /* clang-format off */
1441 dtb = ManifestDtBuilder()
1442 .FfaValidManifest()
1443 .Property("load-address", "<0xffffff00 0xffffff00>")
1444 .StartChild("memory-regions")
1445 .Compatible({ "arm,ffa-manifest-memory-regions" })
1446 .Label("rx")
1447 .StartChild("rx")
1448 .Description("rx-buffer")
Davidson K8ccd2d02024-09-03 16:10:54 +05301449 .Property("load-address-relative-offset", "<0xffffff00 0xffffff00>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001450 .Property("pages-count", "<1>")
1451 .Property("attributes", "<1>")
1452 .EndChild()
1453 .EndChild()
1454 .Build();
1455 /* clang-format on */
1456 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1457 MANIFEST_ERROR_INTEGER_OVERFLOW);
1458 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001459}
1460
1461TEST_F(manifest, ffa_validate_mem_regions_relative_offset_valid)
1462{
1463 struct_manifest *m;
1464 std::vector<char> dtb;
1465
1466 /* valid relative offset */
1467 /* clang-format off */
1468 dtb = ManifestDtBuilder()
1469 .FfaValidManifest()
1470 .Property("load-address", "<0xffffff00 0xffffff00>")
1471 .StartChild("memory-regions")
1472 .Compatible({ "arm,ffa-manifest-memory-regions" })
1473 .Label("rx")
1474 .StartChild("rx")
1475 .Description("rx-buffer")
1476 .Property("load-address-relative-offset", "<0x1000>")
1477 .Property("pages-count", "<1>")
1478 .Property("attributes", "<1>")
1479 .EndChild()
1480 .EndChild()
1481 .Build();
1482 /* clang-format on */
1483 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1484 manifest_dealloc();
1485}
1486
1487TEST_F(manifest, ffa_validate_mem_regions_overlapping)
1488{
1489 struct_manifest *m;
1490 std::vector<char> dtb;
Karl Meakine92efbe2023-06-01 14:16:22 +01001491
Daniel Boulby9279b552022-06-28 17:04:01 +01001492 /* Overlapping memory regions */
1493 /* clang-format off */
1494 dtb = ManifestDtBuilder()
1495 .FfaValidManifest()
1496 .StartChild("memory-regions")
1497 .Compatible({ "arm,ffa-manifest-memory-regions" })
1498 .Label("rx")
1499 .StartChild("rx")
1500 .Description("rx-buffer")
1501 .Property("base-address", "<0x7300000>")
1502 .Property("pages-count", "<1>")
1503 .Property("attributes", "<1>")
1504 .EndChild()
1505 .Label("tx")
1506 .StartChild("tx")
1507 .Description("tx-buffer")
1508 .Property("base-address", "<0x7300000>")
1509 .Property("pages-count", "<2>")
1510 .Property("attributes", "<3>")
1511 .EndChild()
1512 .EndChild()
1513 .Build();
1514 /* clang-format on */
1515 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1516 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001517 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001518
1519 /* clang-format off */
1520 dtb = ManifestDtBuilder()
1521 .FfaValidManifest()
1522 .StartChild("memory-regions")
1523 .Compatible({ "arm,ffa-manifest-memory-regions" })
1524 .Label("rx")
1525 .StartChild("rx")
1526 .Description("rx-buffer")
Karl Meakin6291eb22024-11-18 12:43:47 +00001527 .Property("load-address-relative-offset", "<0x0>")
1528 .Property("pages-count", "<1>")
1529 .Property("attributes", "<1>")
1530 .EndChild()
1531 .Label("tx")
1532 .StartChild("tx")
1533 .Description("tx-buffer")
1534 .Property("load-address-relative-offset", "<0x0>")
1535 .Property("pages-count", "<2>")
1536 .Property("attributes", "<3>")
1537 .EndChild()
1538 .EndChild()
1539 .Build();
1540 /* clang-format on */
1541 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1542 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1543 manifest_dealloc();
1544
1545 /* clang-format off */
1546 dtb = ManifestDtBuilder()
1547 .FfaValidManifest()
1548 .StartChild("memory-regions")
1549 .Compatible({ "arm,ffa-manifest-memory-regions" })
1550 .Label("rx")
1551 .StartChild("rx")
1552 .Description("rx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001553 .Property("base-address", "<0x7300000>")
1554 .Property("pages-count", "<2>")
1555 .Property("attributes", "<1>")
1556 .EndChild()
1557 .Label("tx")
1558 .StartChild("tx")
1559 .Description("tx-buffer")
1560 .Property("base-address", "<0x7301000>")
1561 .Property("pages-count", "<2>")
1562 .Property("attributes", "<3>")
1563 .EndChild()
1564 .EndChild()
1565 .Build();
1566 /* clang-format on */
1567 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1568 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001569 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001570
1571 /* clang-format off */
1572 dtb = ManifestDtBuilder()
1573 .FfaValidManifest()
1574 .StartChild("memory-regions")
1575 .Compatible({ "arm,ffa-manifest-memory-regions" })
1576 .Label("rx")
1577 .StartChild("rx")
1578 .Description("rx-buffer")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001579 .Property("base-address", "<0x7301000>")
1580 .Property("pages-count", "<1>")
1581 .Property("attributes", "<1>")
1582 .EndChild()
1583 .Label("tx")
1584 .StartChild("tx")
1585 .Description("tx-buffer")
1586 .Property("base-address", "<0x7300000>")
1587 .Property("pages-count", "<2>")
1588 .Property("attributes", "<3>")
1589 .EndChild()
1590 .EndChild()
1591 .Build();
1592 /* clang-format on */
1593 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1594 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001595 manifest_dealloc();
Karl Meakin6291eb22024-11-18 12:43:47 +00001596
1597 /* clang-format off */
1598 Partition_package spkg(dtb);
1599 dtb = ManifestDtBuilder()
1600 .FfaValidManifest()
1601 .StartChild("memory-regions")
1602 .Compatible({ "arm,ffa-manifest-memory-regions" })
1603 .StartChild("test-memory")
1604 .Description("test-memory")
1605 .Integer64Property("base-address", (uint64_t)&spkg,true)
1606 .Property("pages-count", "<1>")
1607 .Property("attributes", "<1>")
1608 .EndChild()
1609 .EndChild()
1610 .Build(true);
1611 /* clang-format on */
1612 spkg.init(dtb);
1613 ASSERT_EQ(ffa_manifest_from_spkg(&m, &spkg),
1614 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1615 manifest_dealloc();
1616}
1617
1618TEST_F(manifest, ffa_validate_mem_regions_overlapping_allowed)
1619{
1620 struct_manifest *m;
1621 std::vector<char> dtb;
1622
1623 /*
1624 * Mem regions are allowed to overlap with parent `load-address` if the
1625 * `load-address-relative-offset` was specified.
1626 */
1627 /* clang-format off */
1628 dtb = ManifestDtBuilder()
1629 .FfaValidManifest()
1630 .StartChild("memory-regions")
1631 .Compatible({ "arm,ffa-manifest-memory-regions" })
1632 .Label("rx")
1633 .StartChild("rx")
1634 .Description("rx-buffer")
1635 .Property("load-address-relative-offset", "<0x1000>")
1636 .Property("pages-count", "<1>")
1637 .Property("attributes", "<1>")
1638 .EndChild()
1639 .Label("tx")
1640 .StartChild("tx")
1641 .Description("tx-buffer")
1642 .Property("base-address", "<0x7300000>")
1643 .Property("pages-count", "<2>")
1644 .Property("attributes", "<3>")
1645 .EndChild()
1646 .EndChild()
1647 .Build();
1648 /* clang-format on */
1649 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1650 ASSERT_EQ(m->vm[0].partition.mem_regions[0].is_relative, true);
1651 ASSERT_EQ(m->vm[0].partition.mem_regions[0].base_address,
1652 m->vm[0].partition.load_addr + 0x1000);
1653 manifest_dealloc();
1654
1655 /* clang-format off */
1656 dtb = ManifestDtBuilder()
1657 .FfaValidManifest()
1658 .StartChild("memory-regions")
1659 .Compatible({ "arm,ffa-manifest-memory-regions" })
1660 .Label("rx")
1661 .StartChild("rx")
1662 .Description("rx-buffer")
1663 .Property("base-address", "<0x7300000>")
1664 .Property("pages-count", "<1>")
1665 .Property("attributes", "<1>")
1666 .EndChild()
1667 .Label("tx")
1668 .StartChild("tx")
1669 .Description("tx-buffer")
1670 .Property("load-address-relative-offset", "<0x1000>")
1671 .Property("pages-count", "<2>")
1672 .Property("attributes", "<3>")
1673 .EndChild()
1674 .EndChild()
1675 .Build();
1676 /* clang-format on */
1677 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1678 ASSERT_EQ(m->vm[0].partition.mem_regions[1].is_relative, true);
1679 ASSERT_EQ(m->vm[0].partition.mem_regions[1].base_address,
1680 m->vm[0].partition.load_addr + 0x1000);
1681 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001682}
1683
1684TEST_F(manifest, ffa_validate_mem_regions_unaligned)
1685{
1686 struct_manifest *m;
1687 std::vector<char> dtb;
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001688
1689 /* Unaligned memory region */
1690 /* clang-format off */
1691 dtb = ManifestDtBuilder()
1692 .FfaValidManifest()
1693 .StartChild("memory-regions")
1694 .Compatible({ "arm,ffa-manifest-memory-regions" })
1695 .Label("rx")
1696 .StartChild("rx")
1697 .Description("rx-buffer")
1698 .Property("base-address", "<0x7300FFF>")
1699 .Property("pages-count", "<2>")
1700 .Property("attributes", "<1>")
1701 .EndChild()
1702 .Label("tx")
1703 .StartChild("tx")
1704 .Description("tx-buffer")
1705 .Property("base-address", "<0x7303000>")
1706 .Property("pages-count", "<2>")
1707 .Property("attributes", "<3>")
1708 .EndChild()
1709 .EndChild()
1710 .Build();
1711 /* clang-format on */
1712 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1713 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1714 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001715}
1716
1717TEST_F(manifest, ffa_validate_mem_regions_different_rxtx_sizes)
1718{
1719 struct_manifest *m;
1720 std::vector<char> dtb;
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001721
Manish Pandeyf06c9072020-09-29 15:41:58 +01001722 /* Different RXTX buffer sizes */
1723 /* clang-format off */
1724 dtb = ManifestDtBuilder()
1725 .FfaValidManifest()
1726 .StartChild("memory-regions")
1727 .Compatible({ "arm,ffa-manifest-memory-regions" })
1728 .Label("rx")
1729 .StartChild("rx")
1730 .Description("rx-buffer")
1731 .Property("base-address", "<0x7300000>")
1732 .Property("pages-count", "<1>")
1733 .Property("attributes", "<1>")
1734 .EndChild()
1735 .Label("tx")
1736 .StartChild("tx")
1737 .Description("tx-buffer")
1738 .Property("base-address", "<0x7310000>")
1739 .Property("pages-count", "<2>")
1740 .Property("attributes", "<3>")
1741 .EndChild()
1742 .EndChild()
1743 .StartChild("rx_tx-info")
1744 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1745 .Property("rx-buffer", "<&rx>")
1746 .Property("tx-buffer", "<&tx>")
1747 .EndChild()
1748 .Build();
1749 /* clang-format on */
1750 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1751 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001752}
1753
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001754TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001755{
Olivier Deprez93644652022-09-09 11:01:12 +02001756 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001757
1758 /* Not Compatible */
1759 /* clang-format off */
1760 std::vector<char> dtb = ManifestDtBuilder()
1761 .FfaValidManifest()
1762 .StartChild("device-regions")
1763 .Compatible({ "foo,bar" })
1764 .EndChild()
1765 .Build();
1766 /* clang-format on */
1767 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1768 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001769 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001770
1771 /* Memory regions unavailable */
1772 /* clang-format off */
1773 dtb = ManifestDtBuilder()
1774 .FfaValidManifest()
1775 .StartChild("device-regions")
1776 .Compatible({ "arm,ffa-manifest-device-regions" })
1777 .EndChild()
1778 .Build();
1779 /* clang-format on */
1780 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1781 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001782 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001783
1784 /* Missing Properties */
1785 /* clang-format off */
1786 dtb = ManifestDtBuilder()
1787 .FfaValidManifest()
1788 .StartChild("device-regions")
1789 .Compatible({ "arm,ffa-manifest-device-regions" })
1790 .StartChild("test-device")
1791 .Description("test-device")
1792 .EndChild()
1793 .EndChild()
1794 .Build();
1795 /* clang-format on */
1796 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1797 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001798 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001799
1800 /* Malformed interrupt list pair */
1801 /* clang-format off */
1802 dtb = ManifestDtBuilder()
1803 .FfaValidManifest()
1804 .StartChild("device-regions")
1805 .Compatible({ "arm,ffa-manifest-device-regions" })
1806 .StartChild("test-device")
1807 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001808 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001809 .Property("pages-count", "<16>")
1810 .Property("attributes", "<3>")
1811 .Property("smmu-id", "<1>")
1812 .Property("stream-ids", "<0 1>")
1813 .Property("interrupts", "<2 3>, <4>")
1814 .EndChild()
1815 .EndChild()
1816 .Build();
1817 /* clang-format on */
1818 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1819 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001820 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001821
1822 /* Non-unique interrupt IDs */
1823 /* clang-format off */
1824 dtb = ManifestDtBuilder()
1825 .FfaValidManifest()
1826 .StartChild("device-regions")
1827 .Compatible({ "arm,ffa-manifest-device-regions" })
1828 .StartChild("test-device-0")
1829 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001830 .Property("base-address", "<0x24000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001831 .Property("pages-count", "<16>")
1832 .Property("attributes", "<3>")
1833 .Property("interrupts", "<2 3>")
1834 .EndChild()
1835 .StartChild("test-device-1")
1836 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001837 .Property("base-address", "<0x25000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001838 .Property("pages-count", "<16>")
1839 .Property("attributes", "<3>")
1840 .Property("interrupts", "<1 3>, <2 5> ")
1841 .EndChild()
1842 .EndChild()
1843 .Build();
Daniel Boulby941ef342023-11-21 13:47:15 +00001844
Daniel Boulby667334f2022-06-27 15:23:21 +01001845 /* clang-format on */
1846 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1847 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1848 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001849 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1850 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1851 3);
1852 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1853 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1854 3);
Daniel Boulby941ef342023-11-21 13:47:15 +00001855 manifest_dealloc();
1856
1857 /* Overlapping address space between two device region nodes. */
1858 /* clang-format off */
1859 dtb = ManifestDtBuilder()
1860 .FfaValidManifest()
1861 .StartChild("device-regions")
1862 .Compatible({"arm,ffa-manifest-device-regions"})
1863 .StartChild("test-device-0")
1864 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001865 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001866 .Property("pages-count", "<16>")
1867 .Property("attributes", "<3>")
1868 .EndChild()
1869 .StartChild("test-device-1")
1870 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001871 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001872 .Property("pages-count", "<16>")
1873 .Property("attributes", "<3>")
1874 .EndChild()
Daniel Boulby4339edc2024-02-21 14:59:00 +00001875 .EndChild()
Daniel Boulby941ef342023-11-21 13:47:15 +00001876 .Build();
1877
1878 /* clang-format on */
1879 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1880 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1881 manifest_dealloc();
1882
1883 /*
Daniel Boulby4339edc2024-02-21 14:59:00 +00001884 * Device regions cannot be defined outside of the regions specified in
1885 * the spmc.
Daniel Boulby941ef342023-11-21 13:47:15 +00001886 */
1887 /* clang-format off */
1888 dtb = ManifestDtBuilder()
1889 .FfaValidManifest()
Daniel Boulby941ef342023-11-21 13:47:15 +00001890 .StartChild("device-regions")
1891 .Compatible({"arm,ffa-manifest-device-regions"})
1892 .StartChild("test-device-0")
1893 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001894 .Property("base-address", "<0x50000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001895 .Property("pages-count", "<16>")
1896 .Property("attributes", "<3>")
1897 .EndChild()
1898 .EndChild()
1899 .Build();
1900 /* clang-format on */
1901 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
Daniel Boulby4339edc2024-02-21 14:59:00 +00001902 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
1903 manifest_dealloc();
1904
1905 /*
1906 * Memory defined as NS in SPMC manifest given Secure attribute should
1907 * fail.
1908 */
1909 /* clang-format off */
1910 dtb = ManifestDtBuilder()
1911 .FfaValidManifest()
1912 .StartChild("device-regions")
1913 .Compatible({"arm,ffa-manifest-device-regions"})
1914 .StartChild("test-device-0")
1915 .Description("test-device-0")
1916 .Property("base-address", "<0x20000000>")
1917 .Property("pages-count", "<16>")
1918 .Property("attributes", "<3>")
1919 .EndChild()
1920 .EndChild()
1921 .Build();
1922 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1923 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
Manish Pandeye68e7932020-04-23 15:29:28 +01001924}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001925
1926TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001927{
Olivier Deprez93644652022-09-09 11:01:12 +02001928 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001929
1930 /* clang-format off */
1931 std::vector<char> dtb = ManifestDtBuilder()
1932 .FfaValidManifest()
1933 .StartChild("rx_tx-info")
1934 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1935 .Property("rx-buffer", "<&rx>")
1936 .Property("tx-buffer", "<&tx>")
1937 .EndChild()
1938 .StartChild("memory-regions")
1939 .Compatible({ "arm,ffa-manifest-memory-regions" })
1940 .StartChild("test-memory")
1941 .Description("test-memory")
1942 .Property("base-address", "<0x7100000>")
1943 .Property("pages-count", "<4>")
1944 .Property("attributes", "<7>")
1945 .EndChild()
1946 .Label("rx")
1947 .StartChild("rx")
1948 .Description("rx-buffer")
1949 .Property("base-address", "<0x7300000>")
1950 .Property("pages-count", "<1>")
1951 .Property("attributes", "<1>")
1952 .EndChild()
1953 .Label("tx")
1954 .StartChild("tx")
1955 .Description("tx-buffer")
1956 .Property("base-address", "<0x7310000>")
1957 .Property("pages-count", "<1>")
1958 .Property("attributes", "<3>")
1959 .EndChild()
1960 .EndChild()
1961 .Build();
1962 /* clang-format on */
1963
1964 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1965 MANIFEST_ERROR_INVALID_MEM_PERM);
1966}
1967
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001968TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001969{
Olivier Deprez93644652022-09-09 11:01:12 +02001970 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001971
1972 /* clang-format off */
1973 std::vector<char> dtb = ManifestDtBuilder()
1974 .FfaValidManifest()
1975 .StartChild("rx_tx-info")
1976 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1977 .Property("rx-buffer", "<&rx>")
1978 .Property("tx-buffer", "<&tx>")
1979 .EndChild()
1980 .StartChild("memory-regions")
1981 .Compatible({ "arm,ffa-manifest-memory-regions" })
1982 .StartChild("test-memory")
1983 .Description("test-memory")
1984 .Property("base-address", "<0x7100000>")
1985 .Property("pages-count", "<4>")
1986 .Property("attributes", "<3>")
1987 .EndChild()
1988 .Label("rx")
1989 .StartChild("rx")
1990 .Description("rx-buffer")
1991 .Property("base-address", "<0x7300000>")
1992 .Property("pages-count", "<1>")
1993 .Property("attributes", "<1>")
1994 .EndChild()
1995 .Label("tx")
1996 .StartChild("tx")
1997 .Description("tx-buffer")
1998 .Property("base-address", "<0x7310000>")
1999 .Property("pages-count", "<1>")
2000 .Property("attributes", "<3>")
2001 .EndChild()
2002 .EndChild()
2003 .StartChild("device-regions")
2004 .Compatible({ "arm,ffa-manifest-device-regions" })
2005 .StartChild("test-device")
2006 .Description("test-device")
2007 .Property("base-address", "<0x7200000>")
2008 .Property("pages-count", "<16>")
2009 .Property("attributes", "<5>")
2010 .Property("smmu-id", "<1>")
2011 .Property("stream-ids", "<0 1>")
2012 .Property("interrupts", "<2 3>, <4 5>")
2013 .EndChild()
2014 .EndChild()
2015 .Build();
2016 /* clang-format on */
2017
2018 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2019 MANIFEST_ERROR_INVALID_MEM_PERM);
2020}
Manish Pandeye68e7932020-04-23 15:29:28 +01002021
Daniel Boulby801f8ef2022-06-27 14:21:01 +01002022TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01002023{
Olivier Deprez93644652022-09-09 11:01:12 +02002024 struct manifest_vm *vm;
2025 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01002026
2027 /* clang-format off */
2028 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01002029 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002030 .StartChild("rx_tx-info")
2031 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
2032 .Property("rx-buffer", "<&rx>")
2033 .Property("tx-buffer", "<&tx>")
2034 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01002035 .StartChild("memory-regions")
2036 .Compatible({ "arm,ffa-manifest-memory-regions" })
Olivier Deprez035fa152022-03-14 11:19:10 +01002037 .StartChild("test-memory-ns")
2038 .Description("test-memory")
2039 .Property("base-address", "<0x7200000>")
2040 .Property("pages-count", "<1>")
2041 .Property("attributes", "<0xb>")
2042 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002043 .Label("rx")
2044 .StartChild("rx")
2045 .Description("rx-buffer")
2046 .Property("base-address", "<0x7300000>")
2047 .Property("pages-count", "<1>")
2048 .Property("attributes", "<1>")
2049 .EndChild()
2050 .Label("tx")
2051 .StartChild("tx")
2052 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01002053 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002054 .Property("pages-count", "<1>")
2055 .Property("attributes", "<3>")
2056 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01002057 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01002058 .StartChild("device-regions")
2059 .Compatible({ "arm,ffa-manifest-device-regions" })
2060 .StartChild("test-device")
2061 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002062 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01002063 .Property("pages-count", "<16>")
2064 .Property("attributes", "<3>")
2065 .Property("smmu-id", "<1>")
2066 .Property("stream-ids", "<0 1>")
2067 .Property("interrupts", "<2 3>, <4 5>")
2068 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01002069 .StartChild("test-device-ns")
2070 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002071 .Property("base-address", "<0x20000000>")
Olivier Deprez035fa152022-03-14 11:19:10 +01002072 .Property("pages-count", "<1>")
2073 .Property("attributes", "<0x9>")
2074 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01002075 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01002076 .Build();
Daniel Boulby4339edc2024-02-21 14:59:00 +00002077
Olivier Deprez62d99e32020-01-09 15:58:07 +01002078 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01002079 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2080
Olivier Deprez93644652022-09-09 11:01:12 +02002081 vm = &m->vm[0];
2082 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01002083 ASSERT_THAT(
Kathleen Capella422b10b2023-06-30 18:28:27 -04002084 std::span(vm->partition.uuids[0].uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01002085 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02002086 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2087 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2088 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2089 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2090 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2091 ASSERT_EQ(vm->partition.boot_order, 0);
2092 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2093 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
Davidson K5d5f2792024-08-19 19:09:12 +05302094 ASSERT_EQ(vm->partition.mem_regions[0].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07002095
Olivier Deprez93644652022-09-09 11:01:12 +02002096 ASSERT_EQ(vm->partition.rxtx.available, true);
2097 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
2098 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
2099 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
2100 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
2101 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
2102 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
2103
Daniel Boulby4339edc2024-02-21 14:59:00 +00002104 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Olivier Deprez93644652022-09-09 11:01:12 +02002105 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002106 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002107 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2108 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2109 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Olivier Deprez93644652022-09-09 11:01:12 +02002110 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2111 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2112 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2113 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
Daniel Boulby4339edc2024-02-21 14:59:00 +00002114 ASSERT_EQ(vm->partition.dev_regions[1].base_address, 0x20000000);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002115 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01002116}
2117
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002118TEST_F(manifest, ffa_valid_interrupt_target_manifest)
2119{
2120 struct manifest_vm *vm;
2121 struct_manifest *m;
2122
2123 /* clang-format off */
2124 std::vector<char> dtb = ManifestDtBuilder()
2125 .FfaValidManifest()
2126 .StartChild("device-regions")
2127 .Compatible({ "arm,ffa-manifest-device-regions" })
2128 .StartChild("test-device")
2129 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002130 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002131 .Property("pages-count", "<16>")
2132 .Property("attributes", "<3>")
2133 .Property("smmu-id", "<1>")
2134 .Property("stream-ids", "<0 1>")
2135 .Property("interrupts", "<2 3>, <4 5>")
2136 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
2137 .EndChild()
2138 .EndChild()
2139 .Build();
2140 /* clang-format on */
2141
2142 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2143
2144 vm = &m->vm[0];
2145
Daniel Boulby4339edc2024-02-21 14:59:00 +00002146 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002147 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002148 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002149 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2150 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2151 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002152 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2153 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2154 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
2155 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
2156 0x123400005678);
2157 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2158 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
2159 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
2160 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
2161 0x1234567887654321);
2162}
2163
2164TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
2165{
2166 struct_manifest *m;
2167
2168 /* clang-format off */
2169 std::vector<char> dtb = ManifestDtBuilder()
2170 .FfaValidManifest()
2171 .StartChild("device-regions")
2172 .Compatible({ "arm,ffa-manifest-device-regions" })
2173 .StartChild("test-device")
2174 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002175 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002176 .Property("pages-count", "<16>")
2177 .Property("attributes", "<3>")
2178 .Property("smmu-id", "<1>")
2179 .Property("stream-ids", "<0 1>")
2180 .Property("interrupts", "<2 3>, <4 5>")
2181 .Property("interrupts-target", "<20 0x1234 0x5678>")
2182 .EndChild()
2183 .EndChild()
2184 .Build();
2185 /* clang-format on */
2186
2187 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2188 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
2189}
2190
J-Alvesbb2703a2025-02-10 12:11:56 +00002191TEST_F(manifest, sri_policy)
2192{
2193 struct_manifest *m;
2194 std::vector<char> dtb;
2195
2196 /* clang-format off */
2197 dtb = ManifestDtBuilder()
2198 .FfaValidManifest()
2199 .Property("sri-interrupts-policy", "<0x0>")
2200 .Build();
2201 /* clang-format on */
2202
2203 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2204
2205 /* clang-format off */
2206 dtb = ManifestDtBuilder()
2207 .FfaValidManifest()
2208 .Property("sri-interrupts-policy", "<0x1>")
2209 .Build();
2210 /* clang-format on */
2211
2212 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2213
2214 /* clang-format off */
2215 dtb = ManifestDtBuilder()
2216 .FfaValidManifest()
2217 .Property("sri-interrupts-policy", "<0x2>")
2218 .Build();
2219 /* clang-format on */
2220
2221 /* clang-format off */
2222 dtb = ManifestDtBuilder()
2223 .FfaValidManifest()
2224 .Property("sri-interrupts-policy", "<0x3>")
2225 .Build();
2226 /* clang-format on */
2227
2228 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2229
2230 /* clang-format off */
2231 dtb = ManifestDtBuilder()
2232 .FfaValidManifest()
2233 .Property("sri-interrupts-policy", "<0xF>")
2234 .Build();
2235 /* clang-format on */
2236
2237 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2238 MANIFEST_ERROR_ILLEGAL_SRI_POLICY);
2239}
2240
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002241TEST_F(manifest, ffa_boot_order_not_unique)
2242{
2243 struct_manifest *m;
2244 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +00002245 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002246 struct boot_params params;
2247 Partition_package spkg_1;
2248 Partition_package spkg_2;
2249
2250 /* clang-format off */
2251 std::vector<char> dtb1 = ManifestDtBuilder()
2252 .Compatible({ "arm,ffa-manifest-1.0" })
2253 .Property("ffa-version", "<0x10001>")
2254 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2255 .FfaLoadAddress((uint64_t)&spkg_1)
2256 .Property("execution-ctx-count", "<1>")
2257 .Property("exception-level", "<1>")
2258 .Property("execution-state", "<0>")
2259 .Property("entrypoint-offset", "<0x00002000>")
2260 .Property("xlat-granule", "<0>")
2261 .Property("boot-order", "<1>")
2262 .Property("messaging-method", "<1>")
2263 .Property("ns-interrupts-action", "<0>")
2264 .Build();
2265
2266 std::vector<char> dtb2 = ManifestDtBuilder()
2267 .Compatible({ "arm,ffa-manifest-1.0" })
2268 .Property("ffa-version", "<0x10001>")
2269 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2270 .FfaLoadAddress((uint64_t)&spkg_2)
2271 .Property("execution-ctx-count", "<1>")
2272 .Property("exception-level", "<1>")
2273 .Property("execution-state", "<0>")
2274 .Property("entrypoint-offset", "<0x00002000>")
2275 .Property("xlat-granule", "<0>")
2276 .Property("boot-order", "<1>")
2277 .Property("messaging-method", "<1>")
2278 .Property("ns-interrupts-action", "<0>")
2279 .Build();
2280
2281 /* clang-format on */
2282 spkg_1.init(dtb1);
2283 spkg_2.init(dtb2);
2284
2285 /* clang-format off */
2286 std::vector<char> core_dtb = ManifestDtBuilder()
2287 .StartChild("hypervisor")
2288 .Compatible()
2289 .StartChild("vm1")
2290 .DebugName("ffa_partition_1")
2291 .FfaPartition()
2292 .LoadAddress((uint64_t)&spkg_1)
2293 .VcpuCount(1)
2294 .MemSize(0x10000000)
2295 .EndChild()
2296 .StartChild("vm2")
2297 .DebugName("ffa_partition_2")
2298 .FfaPartition()
2299 .LoadAddress((uint64_t)&spkg_2)
2300 .VcpuCount(1)
2301 .MemSize(0x10000000)
2302 .EndChild()
2303 .EndChild()
2304 .Build();
2305 /* clang-format on */
2306
2307 boot_params_init(&params, nullptr);
2308 memiter_init(&it, core_dtb.data(), core_dtb.size());
2309 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2310 MANIFEST_ERROR_INVALID_BOOT_ORDER);
Karl Meakin0f506a12025-02-08 23:28:45 +00002311
2312 mm_unlock_stage1(&mm_stage1_locked);
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002313}
Daniel Boulby941ef342023-11-21 13:47:15 +00002314
Kathleen Capella422b10b2023-06-30 18:28:27 -04002315TEST_F(manifest, ffa_valid_multiple_uuids)
2316{
2317 struct manifest_vm *vm;
2318 struct_manifest *m;
2319
2320 /* clang-format off */
2321 std::vector<char> dtb = ManifestDtBuilder()
2322 .Compatible({ "arm,ffa-manifest-1.0" })
2323 .Property("ffa-version", "<0x10002>")
2324 .Property("uuid",
2325 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,\
2326 <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2327 .Property("execution-ctx-count", "<1>")
2328 .Property("exception-level", "<2>")
2329 .Property("execution-state", "<0>")
2330 .Property("entrypoint-offset", "<0x00002000>")
2331 .Property("xlat-granule", "<0>")
2332 .Property("boot-order", "<0>")
2333 .Property("messaging-method", "<4>")
2334 .Property("ns-interrupts-action", "<1>")
2335 .Build();
2336 /* clang-format on */
2337 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2338
2339 vm = &m->vm[0];
2340 ASSERT_EQ(vm->partition.ffa_version, 0x10002);
2341 ASSERT_THAT(
2342 std::span(vm->partition.uuids[0].uuid, 4),
2343 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
2344 ASSERT_THAT(
2345 std::span(vm->partition.uuids[1].uuid, 4),
2346 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1daaa));
2347 ASSERT_EQ(vm->partition.uuid_count, 2);
2348 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2349 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2350 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2351 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2352 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2353 ASSERT_EQ(vm->partition.boot_order, 0);
2354 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2355 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
2356}
Karl Meakin45abeeb2024-08-02 16:55:44 +01002357
2358TEST_F(manifest, ffa_too_many_uuids)
2359{
2360 struct_manifest *m;
2361
2362 /* clang-format off */
2363 std::vector<char> dtb = ManifestDtBuilder()
2364 .Compatible({ "arm,ffa-manifest-1.0" })
2365 .Property("ffa-version", "<0x10002>")
2366 .Property("uuid",
2367 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,"
2368 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2369 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2370 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2371 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2372 .Property("execution-ctx-count", "<1>")
2373 .Property("exception-level", "<2>")
2374 .Property("execution-state", "<0>")
2375 .Property("entrypoint-offset", "<0x00002000>")
2376 .Property("xlat-granule", "<0>")
2377 .Property("boot-order", "<0>")
2378 .Property("messaging-method", "<4>")
2379 .Property("ns-interrupts-action", "<1>")
2380 .Build();
2381 /* clang-format on */
2382 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2383 MANIFEST_ERROR_TOO_MANY_UUIDS);
2384}
2385
Kathleen Capella422b10b2023-06-30 18:28:27 -04002386TEST_F(manifest, ffa_uuid_all_zeros)
2387{
2388 struct_manifest *m;
2389
2390 /* clang-format off */
2391 std::vector<char> dtb = ManifestDtBuilder()
2392 .Compatible({ "arm,ffa-manifest-1.0" })
2393 .Property("ffa-version", "<0x10002>")
2394 .Property("uuid",
2395 "<0x0 0x0 0x0 0x0>, <0x0 0x0 0x0 0x0>")
2396 .Property("execution-ctx-count", "<1>")
2397 .Property("exception-level", "<2>")
2398 .Property("execution-state", "<0>")
2399 .Property("entrypoint-offset", "<0x00002000>")
2400 .Property("xlat-granule", "<0>")
2401 .Property("boot-order", "<0>")
2402 .Property("messaging-method", "<4>")
2403 .Property("ns-interrupts-action", "<1>")
2404 .Build();
2405 /* clang-format on */
2406 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2407 MANIFEST_ERROR_UUID_ALL_ZEROS);
2408}
Daniel Boulby941ef342023-11-21 13:47:15 +00002409
2410/*
2411 * Test that the address space of two device region nodes specified across
2412 * different SPs cannot overlap.
2413 */
2414TEST_F(manifest, ffa_device_region_multi_sps)
2415{
2416 struct_manifest *m;
2417 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +00002418 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
Daniel Boulby941ef342023-11-21 13:47:15 +00002419 struct boot_params params;
2420 Partition_package spkg_1;
2421 Partition_package spkg_2;
2422
2423 /* clang-format off */
2424 std::vector<char> dtb1 = ManifestDtBuilder()
2425 .Compatible({ "arm,ffa-manifest-1.0" })
2426 .Property("ffa-version", "<0x10001>")
2427 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2428 .FfaLoadAddress((uint64_t)&spkg_1)
2429 .Property("execution-ctx-count", "<1>")
2430 .Property("exception-level", "<0>")
2431 .Property("execution-state", "<0>")
2432 .Property("entrypoint-offset", "<0x0>")
2433 .Property("xlat-granule", "<0>")
2434 .Property("messaging-method", "<0x7>")
2435 .StartChild("device-regions")
2436 .Compatible({ "arm,ffa-manifest-device-regions" })
2437 .StartChild("test-device-0")
2438 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002439 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002440 .Property("pages-count", "<16>")
2441 .Property("attributes", "<3>")
2442 .EndChild()
2443 .EndChild()
2444 .Build();
2445
2446 std::vector<char> dtb2 = ManifestDtBuilder()
2447 .Compatible({ "arm,ffa-manifest-1.0" })
2448 .Property("ffa-version", "<0x10001>")
2449 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2450 .FfaLoadAddress((uint64_t)&spkg_2)
2451 .Property("execution-ctx-count", "<1>")
2452 .Property("exception-level", "<0>")
2453 .Property("execution-state", "<0>")
2454 .Property("entrypoint-offset", "<0x0>")
2455 .Property("xlat-granule", "<0>")
2456 .Property("messaging-method", "<0x7>")
2457 .StartChild("device-regions")
2458 .Compatible({ "arm,ffa-manifest-device-regions" })
2459 .StartChild("test-device-0")
2460 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002461 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002462 .Property("pages-count", "<16>")
2463 .Property("attributes", "<3>")
2464 .EndChild()
2465 .EndChild()
2466 .Build();
2467
2468 /* clang-format on */
2469 spkg_1.init(dtb1);
2470 spkg_2.init(dtb2);
2471
2472 /* clang-format off */
2473 std::vector<char> core_dtb = ManifestDtBuilder()
2474 .StartChild("hypervisor")
2475 .Compatible()
2476 .StartChild("vm1")
2477 .DebugName("ffa_partition_1")
2478 .FfaPartition()
2479 .LoadAddress((uint64_t)&spkg_1)
2480 .VcpuCount(1)
2481 .MemSize(0x4000)
2482 .EndChild()
2483 .StartChild("vm2")
2484 .DebugName("ffa_partition_2")
2485 .FfaPartition()
2486 .LoadAddress((uint64_t)&spkg_2)
2487 .VcpuCount(1)
2488 .MemSize(0x4000)
2489 .EndChild()
2490 .EndChild()
2491 .Build();
2492 /* clang-format on */
2493 boot_params_init(&params, &spkg_1);
2494 memiter_init(&it, core_dtb.data(), core_dtb.size());
2495 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2496 MANIFEST_ERROR_MEM_REGION_OVERLAP);
2497
2498 manifest_dealloc();
2499
2500 /* clang-format off */
2501 dtb1 = ManifestDtBuilder()
2502 .Compatible({ "arm,ffa-manifest-1.0" })
2503 .Property("ffa-version", "<0x10001>")
2504 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2505 .FfaLoadAddress((uint64_t)&spkg_1)
2506 .Property("execution-ctx-count", "<1>")
2507 .Property("exception-level", "<0>")
2508 .Property("execution-state", "<0>")
2509 .Property("entrypoint-offset", "<0x0>")
2510 .Property("xlat-granule", "<0>")
2511 .Property("messaging-method", "<0x7>")
2512 .StartChild("device-regions")
2513 .Compatible({ "arm,ffa-manifest-device-regions" })
2514 .StartChild("test-device-0")
2515 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002516 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002517 .Property("pages-count", "<16>")
2518 .Property("attributes", "<3>")
2519 .EndChild()
2520 .EndChild()
2521 .Build();
2522
2523 dtb2 = ManifestDtBuilder()
2524 .Compatible({ "arm,ffa-manifest-1.0" })
2525 .Property("ffa-version", "<0x10001>")
2526 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2527 .FfaLoadAddress((uint64_t)&spkg_2)
2528 .Property("execution-ctx-count", "<1>")
2529 .Property("exception-level", "<0>")
2530 .Property("execution-state", "<0>")
2531 .Property("entrypoint-offset", "<0x0>")
2532 .Property("xlat-granule", "<0>")
2533 .Property("messaging-method", "<0x7>")
2534 .StartChild("device-regions")
2535 .Compatible({ "arm,ffa-manifest-device-regions" })
2536 .StartChild("test-device-0")
2537 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002538 .Property("base-address", "<0x25000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002539 .Property("pages-count", "<16>")
2540 .Property("attributes", "<3>")
2541 .EndChild()
2542 .EndChild()
2543 .Build();
2544
2545 /* clang-format on */
2546 spkg_1.init(dtb1);
2547 spkg_2.init(dtb2);
2548
2549 /* clang-format off */
2550 core_dtb = ManifestDtBuilder()
2551 .StartChild("hypervisor")
2552 .Compatible()
2553 .StartChild("vm1")
2554 .DebugName("ffa_partition_1")
2555 .FfaPartition()
2556 .LoadAddress((uint64_t)&spkg_1)
2557 .VcpuCount(1)
2558 .MemSize(0x4000)
2559 .EndChild()
2560 .StartChild("vm2")
2561 .DebugName("ffa_partition_2")
2562 .FfaPartition()
2563 .LoadAddress((uint64_t)&spkg_2)
2564 .VcpuCount(1)
2565 .MemSize(0x4000)
2566 .EndChild()
2567 .EndChild()
2568 .Build();
2569 /* clang-format on */
2570 boot_params_init(&params, &spkg_1);
2571 memiter_init(&it, core_dtb.data(), core_dtb.size());
2572 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2573 MANIFEST_SUCCESS);
Karl Meakin0f506a12025-02-08 23:28:45 +00002574
2575 mm_unlock_stage1(&mm_stage1_locked);
Daniel Boulby941ef342023-11-21 13:47:15 +00002576}
Madhukar Pappireddy99c5eff2024-07-08 15:07:41 -05002577
2578/*
2579 * Tests to trigger various error conditions while parsing dma related
2580 * properties of memory region nodes.
2581 */
2582TEST_F(manifest, ffa_memory_region_invalid_dma_properties)
2583{
2584 struct_manifest *m;
2585
2586 /*
2587 * SMMU ID must be specified if the partition specifies Stream IDs for
2588 * any device upstream of SMMU.
2589 */
2590 /* clang-format off */
2591 std::vector<char> dtb = ManifestDtBuilder()
2592 .FfaValidManifest()
2593 .StartChild("memory-regions")
2594 .Compatible({ "arm,ffa-manifest-memory-regions" })
2595 .StartChild("test-memory")
2596 .Description("test-memory")
2597 .Property("base-address", "<0x7100000>")
2598 .Property("pages-count", "<16>")
2599 .Property("attributes", "<3>")
2600 .Property("stream-ids", "<0 1>")
2601 .Property("interrupts", "<2 3>, <4 5>")
2602 .EndChild()
2603 .EndChild()
2604 .Build();
2605 /* clang-format on */
2606
2607 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2608 MANIFEST_ERROR_MISSING_SMMU_ID);
2609 manifest_dealloc();
2610
2611 /*
2612 * All stream ids belonging to a dma device must specify the same access
2613 * permissions.
2614 */
2615 /* clang-format off */
2616 dtb = ManifestDtBuilder()
2617 .FfaValidManifest()
2618 .StartChild("memory-regions")
2619 .Compatible({ "arm,ffa-manifest-memory-regions" })
2620 .StartChild("test-memory")
2621 .Description("test-memory")
2622 .Property("base-address", "<0x7100000>")
2623 .Property("pages-count", "<16>")
2624 .Property("attributes", "<3>")
2625 .Property("smmu-id", "<1>")
2626 .Property("stream-ids", "<0 1>")
2627 .Property("stream-ids-access-permissions", "<0x3 0xb>")
2628 .Property("interrupts", "<2 3>, <4 5>")
2629 .EndChild()
2630 .EndChild()
2631 .Build();
2632 /* clang-format on */
2633
2634 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2635 MANIFEST_ERROR_MISMATCH_DMA_ACCESS_PERMISSIONS);
2636 manifest_dealloc();
2637
2638 /*
2639 * DMA device stream ID count exceeds predefined limit.
2640 */
2641 /* clang-format off */
2642 dtb = ManifestDtBuilder()
2643 .FfaValidManifest()
2644 .StartChild("memory-regions")
2645 .Compatible({ "arm,ffa-manifest-memory-regions" })
2646 .StartChild("test-memory")
2647 .Description("test-memory")
2648 .Property("base-address", "<0x7100000>")
2649 .Property("pages-count", "<16>")
2650 .Property("attributes", "<3>")
2651 .Property("smmu-id", "<1>")
2652 .Property("stream-ids", "<0 1 4 9 12 >")
2653 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3>")
2654 .EndChild()
2655 .EndChild()
2656 .Build();
2657 /* clang-format on */
2658
2659 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2660 MANIFEST_ERROR_STREAM_IDS_OVERFLOW);
2661 manifest_dealloc();
2662
2663 /*
2664 * DMA access permissions count exceeds predefined limit
2665 */
2666 /* clang-format off */
2667 dtb = ManifestDtBuilder()
2668 .FfaValidManifest()
2669 .StartChild("memory-regions")
2670 .Compatible({ "arm,ffa-manifest-memory-regions" })
2671 .StartChild("test-memory")
2672 .Description("test-memory")
2673 .Property("base-address", "<0x7100000>")
2674 .Property("pages-count", "<16>")
2675 .Property("attributes", "<3>")
2676 .Property("smmu-id", "<1>")
2677 .Property("stream-ids", "<0 1>")
2678 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3 0x3 0x3>")
2679 .EndChild()
2680 .EndChild()
2681 .Build();
2682 /* clang-format on */
2683
2684 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2685 MANIFEST_ERROR_DMA_ACCESS_PERMISSIONS_OVERFLOW);
2686}
2687
2688/*
2689 * Tests to trigger various error conditions while parsing dma related
2690 * properties of device region nodes.
2691 */
2692TEST_F(manifest, ffa_device_region_invalid_dma_properties)
2693{
2694 struct_manifest *m;
2695
2696 /*
2697 * SMMU ID must be specified if the partition specifies Stream IDs for
2698 * any device upstream of SMMU.
2699 */
2700 /* clang-format off */
2701 std::vector<char> dtb = ManifestDtBuilder()
2702 .FfaValidManifest()
2703 .StartChild("device-regions")
2704 .Compatible({ "arm,ffa-manifest-device-regions" })
2705 .StartChild("test-device")
2706 .Description("test-device")
2707 .Property("base-address", "<0x24000000>")
2708 .Property("pages-count", "<16>")
2709 .Property("attributes", "<3>")
2710 .Property("stream-ids", "<0 1>")
2711 .Property("interrupts", "<2 3>, <4 5>")
2712 .EndChild()
2713 .EndChild()
2714 .Build();
2715 /* clang-format on */
2716
2717 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2718 MANIFEST_ERROR_MISSING_SMMU_ID);
2719 manifest_dealloc();
2720
2721 /*
2722 * Dma devices defined through device region nodes exceed predefined
2723 * limit.
2724 */
2725 /* clang-format off */
2726 dtb = ManifestDtBuilder()
2727 .FfaValidManifest()
2728 .StartChild("device-regions")
2729 .Compatible({ "arm,ffa-manifest-device-regions" })
2730 .StartChild("test-device-0")
2731 .Description("test-device-0")
2732 .Property("base-address", "<0x27000000>")
2733 .Property("pages-count", "<16>")
2734 .Property("attributes", "<3>")
2735 .Property("smmu-id", "<1>")
2736 .Property("stream-ids", "<0 1>")
2737 .EndChild()
2738 .StartChild("test-device-1")
2739 .Description("test-device-1")
2740 .Property("base-address", "<0x25000000>")
2741 .Property("pages-count", "<16>")
2742 .Property("attributes", "<3>")
2743 .Property("smmu-id", "<1>")
2744 .Property("stream-ids", "<2 3>")
2745 .EndChild()
2746 .StartChild("test-device-2")
2747 .Description("test-device-2")
2748 .Property("base-address", "<0x26000000>")
2749 .Property("pages-count", "<16>")
2750 .Property("attributes", "<3>")
2751 .Property("smmu-id", "<1>")
2752 .Property("stream-ids", "<4 5>")
2753 .EndChild()
2754 .EndChild()
2755 .Build();
2756 /* clang-format on */
2757
2758 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2759 MANIFEST_ERROR_DMA_DEVICE_OVERFLOW);
2760}
David Brazdil7a462ec2019-08-15 12:27:47 +01002761} /* namespace */