blob: 9cbafb1d157f699b3724475e8343f8caebb8de63 [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:
365 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
366 __attribute__((
367 aligned(PAGE_SIZE))) char manifest_dtb[PAGE_SIZE] = {};
368 __attribute__((aligned(PAGE_SIZE))) char img[PAGE_SIZE] = {};
David Brazdil0dbb41f2019-09-09 18:03:35 +0100369
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100370 Partition_package(const std::vector<char> &vec)
371 {
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400372 init(vec);
373 }
374
375 Partition_package()
376 {
377 }
378
379 void init(const std::vector<char> &vec)
380 {
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100381 // Initialise header field
382 spkg.magic = SP_PKG_HEADER_MAGIC;
383 spkg.version = SP_PKG_HEADER_VERSION_2;
384 spkg.pm_offset = PAGE_SIZE;
385 spkg.pm_size = vec.size();
386 spkg.img_offset = 2 * PAGE_SIZE;
387 spkg.img_size = ARRAY_SIZE(img);
388
389 // Copy dtb into package
390 std::copy(vec.begin(), vec.end(), manifest_dtb);
391 }
392 };
393
J-Alves77b6f4f2023-03-15 11:34:49 +0000394 static void boot_params_init(struct boot_params *params,
395 Partition_package *pkg)
396 {
397 /*
398 * For the manifest tests we only care about the memory ranges
399 * in boot_params.
400 */
401 params->mem_ranges[0].begin = pa_init((uintpaddr_t)0x7000000);
402 params->mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
403 params->mem_ranges_count = 1;
404
405 if (pkg != nullptr) {
406 auto mem_base = (uintpaddr_t)pkg;
407 uintpaddr_t mem_end =
408 mem_base + sp_pkg_get_mem_size(&pkg->spkg);
409
410 params->mem_ranges_count++;
411
412 params->mem_ranges[1].begin = pa_init(mem_base);
413 params->mem_ranges[1].end = pa_init(mem_end);
414 }
415
416 params->ns_mem_ranges[0].begin =
417 pa_init((uintpaddr_t)0x7000000);
418 params->ns_mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
419 params->ns_mem_ranges_count = 1;
Daniel Boulby4339edc2024-02-21 14:59:00 +0000420
421 params->ns_device_mem_ranges[0].begin =
422 pa_init((uintpaddr_t)0x20000000);
423 params->ns_device_mem_ranges[0].end =
424 pa_init((uintpaddr_t)0x24000000);
425 params->ns_device_mem_ranges_count = 1;
426
427 params->device_mem_ranges[0].begin =
428 pa_init((uintpaddr_t)0x24000000);
429 params->device_mem_ranges[0].end =
430 pa_init((uintpaddr_t)0x28000000);
431 params->device_mem_ranges_count = 1;
J-Alves77b6f4f2023-03-15 11:34:49 +0000432 }
433
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100434 enum manifest_return_code manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200435 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100436 {
437 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +0000438 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
J-Alves77b6f4f2023-03-15 11:34:49 +0000439 struct boot_params params;
Karl Meakin0f506a12025-02-08 23:28:45 +0000440 enum manifest_return_code ret;
J-Alves77b6f4f2023-03-15 11:34:49 +0000441
442 boot_params_init(&params, nullptr);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100443
444 memiter_init(&it, vec.data(), vec.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100445
Karl Meakin0f506a12025-02-08 23:28:45 +0000446 ret = manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
447 mm_unlock_stage1(&mm_stage1_locked);
448 return ret;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100449 }
450
Karl Meakin6291eb22024-11-18 12:43:47 +0000451 enum manifest_return_code ffa_manifest_from_spkg(
452 struct_manifest **m, Partition_package *spkg)
453 {
454 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +0000455 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
Karl Meakin6291eb22024-11-18 12:43:47 +0000456 struct boot_params params;
Karl Meakin0f506a12025-02-08 23:28:45 +0000457 enum manifest_return_code ret;
Karl Meakin6291eb22024-11-18 12:43:47 +0000458
459 boot_params_init(&params, spkg);
460
461 /* clang-format off */
462 std::vector<char> core_dtb = ManifestDtBuilder()
463 .StartChild("hypervisor")
464 .Compatible()
465 .StartChild("vm1")
466 .DebugName("primary_vm")
467 .FfaPartition()
468 .LoadAddress((uint64_t)spkg)
469 .EndChild()
470 .EndChild()
471 .Build(true);
472 /* clang-format on */
473 memiter_init(&it, core_dtb.data(), core_dtb.size());
474
Karl Meakin0f506a12025-02-08 23:28:45 +0000475 ret = manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
476 mm_unlock_stage1(&mm_stage1_locked);
477 return ret;
Karl Meakin6291eb22024-11-18 12:43:47 +0000478 }
479
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100480 enum manifest_return_code ffa_manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200481 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100482 {
483 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +0000484 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100485 Partition_package spkg(vec);
J-Alves77b6f4f2023-03-15 11:34:49 +0000486 struct boot_params params;
Karl Meakin0f506a12025-02-08 23:28:45 +0000487 enum manifest_return_code ret;
J-Alves77b6f4f2023-03-15 11:34:49 +0000488
489 boot_params_init(&params, &spkg);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100490
491 /* clang-format off */
492 std::vector<char> core_dtb = ManifestDtBuilder()
493 .StartChild("hypervisor")
494 .Compatible()
495 .StartChild("vm1")
496 .DebugName("primary_vm")
497 .FfaPartition()
498 .LoadAddress((uint64_t)&spkg)
499 .EndChild()
500 .EndChild()
501 .Build();
502 /* clang-format on */
503 memiter_init(&it, core_dtb.data(), core_dtb.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100504
Karl Meakin0f506a12025-02-08 23:28:45 +0000505 ret = manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
506 mm_unlock_stage1(&mm_stage1_locked);
507 return ret;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100508 }
509};
510
511TEST_F(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100512{
Olivier Deprez93644652022-09-09 11:01:12 +0200513 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100514 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100515
David Brazdila2358d42020-01-27 18:51:38 +0000516 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100517 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
518}
519
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100520TEST_F(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100521{
Olivier Deprez93644652022-09-09 11:01:12 +0200522 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100523
David Brazdil52256ff2019-08-23 15:15:15 +0100524 /* clang-format off */
525 std::vector<char> dtb = ManifestDtBuilder()
526 .StartChild("hypervisor")
527 .EndChild()
528 .Build();
529 /* clang-format on */
530
David Brazdilf4925382020-03-25 13:33:51 +0000531 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100532}
533
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100534TEST_F(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100535{
Olivier Deprez93644652022-09-09 11:01:12 +0200536 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100537
David Brazdil52256ff2019-08-23 15:15:15 +0100538 /* clang-format off */
539 std::vector<char> dtb = ManifestDtBuilder()
540 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100541 .Compatible({ "foo,bar" })
542 .EndChild()
543 .Build();
544 /* clang-format on */
545
David Brazdila2358d42020-01-27 18:51:38 +0000546 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100547}
548
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100549TEST_F(manifest, compatible_one_of_many)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100550{
Olivier Deprez93644652022-09-09 11:01:12 +0200551 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100552
553 /* clang-format off */
554 std::vector<char> dtb = ManifestDtBuilder()
555 .StartChild("hypervisor")
556 .Compatible({ "foo,bar", "hafnium,hafnium" })
557 .StartChild("vm1")
558 .DebugName("primary")
559 .EndChild()
560 .EndChild()
561 .Build();
562 /* clang-format on */
563
David Brazdila2358d42020-01-27 18:51:38 +0000564 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100565}
566
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100567TEST_F(manifest, no_vm_nodes)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100568{
Olivier Deprez93644652022-09-09 11:01:12 +0200569 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100570
571 /* clang-format off */
572 std::vector<char> dtb = ManifestDtBuilder()
573 .StartChild("hypervisor")
574 .Compatible()
575 .EndChild()
576 .Build();
577 /* clang-format on */
578
David Brazdila2358d42020-01-27 18:51:38 +0000579 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100580}
581
582static std::vector<char> gen_long_string_dtb(bool valid)
583{
584 const char last_valid[] = "1234567890123456789012345678901";
585 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100586 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
587 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100588
589 /* clang-format off */
590 return ManifestDtBuilder()
591 .StartChild("hypervisor")
592 .Compatible()
593 .StartChild("vm1")
594 .DebugName(valid ? last_valid : first_invalid)
595 .EndChild()
596 .EndChild()
597 .Build();
598 /* clang-format on */
599}
600
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100601TEST_F(manifest, long_string)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100602{
Olivier Deprez93644652022-09-09 11:01:12 +0200603 struct_manifest *m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100604 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
605 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
606
David Brazdila2358d42020-01-27 18:51:38 +0000607 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200608 manifest_dealloc();
609
David Brazdila2358d42020-01-27 18:51:38 +0000610 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
611 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100612}
613
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100614TEST_F(manifest, reserved_vm_id)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100615{
Olivier Deprez93644652022-09-09 11:01:12 +0200616 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100617
618 /* clang-format off */
619 std::vector<char> dtb = ManifestDtBuilder()
620 .StartChild("hypervisor")
621 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100622 .StartChild("vm1")
623 .DebugName("primary_vm")
624 .EndChild()
625 .StartChild("vm0")
626 .DebugName("reserved_vm")
627 .VcpuCount(1)
628 .MemSize(0x1000)
629 .KernelFilename("kernel")
630 .EndChild()
631 .EndChild()
632 .Build();
633 /* clang-format on */
634
David Brazdila2358d42020-01-27 18:51:38 +0000635 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100636}
637
Andrew Scullae9962e2019-10-03 16:51:16 +0100638static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100639{
640 /* clang-format off */
641 return ManifestDtBuilder()
642 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100643 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100644 .StartChild("vm1")
645 .DebugName("primary_vm")
646 .EndChild()
647 .StartChild("vm2")
648 .DebugName("secondary_vm")
649 .VcpuCount(vcpu_count)
650 .MemSize(0x1000)
651 .KernelFilename("kernel")
652 .EndChild()
653 .EndChild()
654 .Build();
655 /* clang-format on */
656}
David Brazdil7a462ec2019-08-15 12:27:47 +0100657
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100658TEST_F(manifest, vcpu_count_limit)
David Brazdil7a462ec2019-08-15 12:27:47 +0100659{
Olivier Deprez93644652022-09-09 11:01:12 +0200660 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100661 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
662 std::vector<char> dtb_first_invalid =
663 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100664
David Brazdila2358d42020-01-27 18:51:38 +0000665 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200666 ASSERT_EQ(m->vm_count, 2);
667 ASSERT_EQ(m->vm[1].secondary.vcpu_count, UINT16_MAX);
668 manifest_dealloc();
David Brazdil7a462ec2019-08-15 12:27:47 +0100669
David Brazdila2358d42020-01-27 18:51:38 +0000670 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100671 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100672}
673
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100674TEST_F(manifest, no_ramdisk_primary)
David Brazdile6f83222019-09-23 14:47:37 +0100675{
Olivier Deprez93644652022-09-09 11:01:12 +0200676 struct_manifest *m;
David Brazdile6f83222019-09-23 14:47:37 +0100677
678 /* clang-format off */
679 std::vector<char> dtb = ManifestDtBuilder()
680 .StartChild("hypervisor")
681 .Compatible()
682 .StartChild("vm1")
683 .DebugName("primary_vm")
684 .EndChild()
685 .EndChild()
686 .Build();
687 /* clang-format on */
688
David Brazdila2358d42020-01-27 18:51:38 +0000689 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200690 ASSERT_EQ(m->vm_count, 1);
691 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
692 ASSERT_STREQ(string_data(&m->vm[0].primary.ramdisk_filename), "");
David Brazdile6f83222019-09-23 14:47:37 +0100693}
694
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100695TEST_F(manifest, no_boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800696{
Olivier Deprez93644652022-09-09 11:01:12 +0200697 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800698
699 /* clang-format off */
700 std::vector<char> dtb = ManifestDtBuilder()
701 .StartChild("hypervisor")
702 .Compatible()
703 .StartChild("vm1")
704 .DebugName("primary_vm")
705 .EndChild()
706 .EndChild()
707 .Build();
708 /* clang-format on */
709
710 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200711 ASSERT_EQ(m->vm_count, 1);
712 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
713 ASSERT_EQ(m->vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
David Brazdil080ee312020-02-25 15:30:30 -0800714}
715
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100716TEST_F(manifest, boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800717{
Olivier Deprez93644652022-09-09 11:01:12 +0200718 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800719 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
720
721 /* clang-format off */
722 std::vector<char> dtb = ManifestDtBuilder()
723 .StartChild("hypervisor")
724 .Compatible()
725 .StartChild("vm1")
726 .DebugName("primary_vm")
727 .BootAddress(addr)
728 .EndChild()
729 .EndChild()
730 .Build();
731 /* clang-format on */
732
733 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200734 ASSERT_EQ(m->vm_count, 1);
735 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
736 ASSERT_EQ(m->vm[0].primary.boot_address, addr);
David Brazdil080ee312020-02-25 15:30:30 -0800737}
738
Andrew Scullb2c3a242019-11-04 13:52:36 +0000739static std::vector<char> gen_malformed_boolean_dtb(
740 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100741{
Andrew Scullae9962e2019-10-03 16:51:16 +0100742 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000743 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100744 .StartChild("hypervisor")
745 .Compatible()
746 .StartChild("vm1")
747 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000748 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000749 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100750 .EndChild()
751 .Build();
752 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000753}
Andrew Scullae9962e2019-10-03 16:51:16 +0100754
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100755TEST_F(manifest, malformed_booleans)
Andrew Scullb2c3a242019-11-04 13:52:36 +0000756{
Olivier Deprez93644652022-09-09 11:01:12 +0200757 struct_manifest *m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100758
Andrew Scullb2c3a242019-11-04 13:52:36 +0000759 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
760 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
761 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
762 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100763
David Brazdila2358d42020-01-27 18:51:38 +0000764 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000765 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200766 manifest_dealloc();
767
David Brazdila2358d42020-01-27 18:51:38 +0000768 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000769 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200770 manifest_dealloc();
771
David Brazdila2358d42020-01-27 18:51:38 +0000772 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000773 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200774 manifest_dealloc();
775
David Brazdila2358d42020-01-27 18:51:38 +0000776 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000777 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100778}
779
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100780TEST_F(manifest, valid)
David Brazdil7a462ec2019-08-15 12:27:47 +0100781{
Olivier Deprez93644652022-09-09 11:01:12 +0200782 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100783 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100784
David Brazdil52256ff2019-08-23 15:15:15 +0100785 /* clang-format off */
786 std::vector<char> dtb = ManifestDtBuilder()
787 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100788 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100789 .StartChild("vm1")
790 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100791 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100792 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100793 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100794 .EndChild()
795 .StartChild("vm3")
796 .DebugName("second_secondary_vm")
797 .VcpuCount(43)
798 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100799 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100800 .EndChild()
801 .StartChild("vm2")
802 .DebugName("first_secondary_vm")
803 .VcpuCount(42)
804 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100805 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
806 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100807 .EndChild()
808 .EndChild()
809 .Build();
810 /* clang-format on */
811
David Brazdila2358d42020-01-27 18:51:38 +0000812 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200813 ASSERT_EQ(m->vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100814
Olivier Deprez93644652022-09-09 11:01:12 +0200815 vm = &m->vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100816 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
817 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100818 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
819 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100820 ASSERT_THAT(
821 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
822 ElementsAre(0x32000000, 0x33001111));
823 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100824
Olivier Deprez93644652022-09-09 11:01:12 +0200825 vm = &m->vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100826 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
827 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100828 ASSERT_EQ(vm->secondary.vcpu_count, 42);
829 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100830 ASSERT_THAT(
831 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
832 ElementsAre(0x04000000, 0x30002222, 0x31445566));
833 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100834
Olivier Deprez93644652022-09-09 11:01:12 +0200835 vm = &m->vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100836 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
837 ASSERT_STREQ(string_data(&vm->kernel_filename),
838 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100839 ASSERT_EQ(vm->secondary.vcpu_count, 43);
840 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100841 ASSERT_THAT(
842 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
843 IsEmpty());
844 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100845}
846
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100847TEST_F(manifest, ffa_not_compatible)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100848{
Olivier Deprez93644652022-09-09 11:01:12 +0200849 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100850
851 /* clang-format off */
852 std::vector<char> dtb = ManifestDtBuilder()
853 .Compatible({ "arm,ffa-manifest-2.0" })
854 .Property("ffa-version", "<0x10000>")
855 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
856 .Property("execution-ctx-count", "<1>")
857 .Property("exception-level", "<2>")
858 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000859 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100860 .Property("xlat-granule", "<0>")
861 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500862 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100863 .Build();
864 /* clang-format on */
865
866 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
867 MANIFEST_ERROR_NOT_COMPATIBLE);
868}
869
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100870TEST_F(manifest, ffa_missing_property)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100871{
Olivier Deprez93644652022-09-09 11:01:12 +0200872 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100873
874 /* clang-format off */
875 std::vector<char> dtb = ManifestDtBuilder()
876 .Compatible({ "arm,ffa-manifest-1.0" })
877 .Property("ffa-version", "<0x10000>")
878 .Build();
879 /* clang-format on */
880
881 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
882 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
883}
884
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100885TEST_F(manifest, ffa_validate_sanity_check)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100886{
J-Alvesb37fd082020-10-22 12:29:21 +0100887 /*
888 * TODO: write test excluding all optional fields of the manifest, in
889 * accordance with specification.
890 */
Olivier Deprez93644652022-09-09 11:01:12 +0200891 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100892
893 /* Incompatible version */
894 /* clang-format off */
895 std::vector<char> dtb = ManifestDtBuilder()
896 .Compatible({ "arm,ffa-manifest-1.0" })
897 .Property("ffa-version", "<0xa1>")
898 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
899 .Property("execution-ctx-count", "<1>")
900 .Property("exception-level", "<2>")
901 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000902 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100903 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100904 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100905 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500906 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100907 .Build();
908 /* clang-format on */
909 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
910 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200911 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100912
913 /* Incompatible translation granule */
914 /* clang-format off */
915 dtb = ManifestDtBuilder()
916 .Compatible({ "arm,ffa-manifest-1.0" })
917 .Property("ffa-version", "<0x10000>")
918 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
919 .Property("execution-ctx-count", "<1>")
920 .Property("exception-level", "<2>")
921 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000922 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100923 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100924 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100925 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500926 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100927 .Build();
928 /* clang-format on */
929 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
930 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200931 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100932
933 /* Incompatible exeption level */
934 /* clang-format off */
935 dtb = ManifestDtBuilder()
936 .Compatible({ "arm,ffa-manifest-1.0" })
937 .Property("ffa-version", "<0x10000>")
938 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
939 .Property("execution-ctx-count", "<1>")
Daniel Boulby874d5432023-04-27 12:40:24 +0100940 .Property("exception-level", "<10>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100941 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000942 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100943 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100944 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100945 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500946 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100947 .Build();
948 /* clang-format on */
949 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
950 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200951 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100952
953 /* Incompatible execution state */
954 /* clang-format off */
955 dtb = ManifestDtBuilder()
956 .Compatible({ "arm,ffa-manifest-1.0" })
957 .Property("ffa-version", "<0x10000>")
958 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
959 .Property("execution-ctx-count", "<1>")
960 .Property("exception-level", "<2>")
961 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000962 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100963 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100964 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100965 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500966 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100967 .Build();
968 /* clang-format on */
969 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
970 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200971 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100972
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400973 /* Incompatible messaging method - unrecognized messaging-method. */
974 /* clang-format off */
975 dtb = ManifestDtBuilder()
976 .Compatible({ "arm,ffa-manifest-1.0" })
977 .Property("ffa-version", "<0x10002>")
978 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
979 .Property("execution-ctx-count", "<1>")
980 .Property("exception-level", "<2>")
981 .Property("execution-state", "<0>")
982 .Property("entrypoint-offset", "<0x00002000>")
983 .Property("xlat-granule", "<0>")
984 .Property("boot-order", "<0>")
985 .Property("messaging-method", "<0x272>")
986 .Property("ns-interrupts-action", "<0>")
987 .Build();
988 /* clang-format on */
989 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
990 MANIFEST_ERROR_NOT_COMPATIBLE);
991 manifest_dealloc();
992
993 /* Incompatible messaging method - only endpoints using FF-A version >=
994 * FF-A v1.2 are allowed to set FFA_PARTITION_DIRECT_REQ2_RECV and
995 * FFA_PARTITION_DIRECT_REQ2_SEND. */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100996 /* clang-format off */
997 dtb = ManifestDtBuilder()
998 .Compatible({ "arm,ffa-manifest-1.0" })
999 .Property("ffa-version", "<0x10000>")
1000 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1001 .Property("execution-ctx-count", "<1>")
1002 .Property("exception-level", "<2>")
1003 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +00001004 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +01001005 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +01001006 .Property("boot-order", "<0>")
Kathleen Capellaf71dee42023-08-08 16:24:14 -04001007 .Property("messaging-method", "<0x204>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -05001008 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +01001009 .Build();
1010 /* clang-format on */
1011 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1012 MANIFEST_ERROR_NOT_COMPATIBLE);
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001013
1014 /*
1015 * No need to invoke manifest_dealloac() since manifest TearDown calls
1016 * it when the test ends.
1017 */
1018}
1019
1020TEST_F(manifest, ffa_validate_interrupt_actions)
1021{
1022 struct_manifest *m;
Madhukar Pappireddy84154052022-06-21 18:30:25 -05001023
1024 /* Incompatible NS interrupt action */
1025 /* clang-format off */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001026 std::vector<char> dtb = ManifestDtBuilder()
Madhukar Pappireddy84154052022-06-21 18:30:25 -05001027 .Compatible({ "arm,ffa-manifest-1.0" })
1028 .Property("ffa-version", "<0x10000>")
1029 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1030 .Property("execution-ctx-count", "<1>")
1031 .Property("exception-level", "<2>")
1032 .Property("execution-state", "<0>")
1033 .Property("entrypoint-offset", "<0x00002000>")
1034 .Property("xlat-granule", "<0>")
1035 .Property("boot-order", "<0>")
1036 .Property("messaging-method", "<1>")
1037 .Property("ns-interrupts-action", "<4>")
1038 .Build();
1039 /* clang-format on */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001040 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1041 MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
Madhukar Pappireddyee736ad2022-12-28 11:37:09 -06001042 manifest_dealloc();
1043
1044 /* Incompatible other-s-interrupts-action for S-EL1 partition */
1045 /* clang-format off */
1046 dtb = ManifestDtBuilder()
1047 .Compatible({ "arm,ffa-manifest-1.0" })
1048 .Property("ffa-version", "<0x10000>")
1049 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1050 .Property("execution-ctx-count", "<1>")
1051 .Property("exception-level", "<2>")
1052 .Property("execution-state", "<0>")
1053 .Property("entrypoint-offset", "<0x00002000>")
1054 .Property("xlat-granule", "<0>")
1055 .Property("boot-order", "<0>")
1056 .Property("messaging-method", "<1>")
1057 .Property("ns-interrupts-action", "<1>")
1058 .Property("other-s-interrupts-action", "<0>")
1059 .Build();
1060 /* clang-format on */
1061 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1062 MANIFEST_ERROR_NOT_COMPATIBLE);
1063 manifest_dealloc();
1064
1065 /*
1066 * Incompatible choice of the fields ns-interrupts-action and
1067 * other-s-interrupts-action.
1068 */
1069 /* clang-format off */
1070 dtb = ManifestDtBuilder()
1071 .Compatible({ "arm,ffa-manifest-1.0" })
1072 .Property("ffa-version", "<0x10000>")
1073 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1074 .Property("execution-ctx-count", "<1>")
1075 .Property("exception-level", "<1>")
1076 .Property("execution-state", "<0>")
1077 .Property("entrypoint-offset", "<0x00002000>")
1078 .Property("xlat-granule", "<0>")
1079 .Property("boot-order", "<0>")
1080 .Property("messaging-method", "<1>")
1081 .Property("ns-interrupts-action", "<2>")
1082 .Property("other-s-interrupts-action", "<0>")
1083 .Build();
1084 /* clang-format on */
1085 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1086 MANIFEST_ERROR_NOT_COMPATIBLE);
1087 manifest_dealloc();
1088
1089 /* Illegal value specified for the field other-s-interrupts-action. */
1090 /* clang-format off */
1091 dtb = ManifestDtBuilder()
1092 .Compatible({ "arm,ffa-manifest-1.0" })
1093 .Property("ffa-version", "<0x10000>")
1094 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1095 .Property("execution-ctx-count", "<1>")
1096 .Property("exception-level", "<1>")
1097 .Property("execution-state", "<0>")
1098 .Property("entrypoint-offset", "<0x00002000>")
1099 .Property("xlat-granule", "<0>")
1100 .Property("boot-order", "<0>")
1101 .Property("messaging-method", "<1>")
1102 .Property("other-s-interrupts-action", "<2>")
1103 .Build();
1104 /* clang-format on */
1105 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1106 MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001107}
1108
Karl Meakin18694022024-08-02 13:59:25 +01001109TEST_F(manifest, vm_availability_messages)
1110{
1111 struct manifest_vm *vm;
1112 struct_manifest *m;
1113 std::vector<char> dtb;
1114
1115 /* clang-format off */
1116 dtb = ManifestDtBuilder()
1117 .Compatible({ "arm,ffa-manifest-1.0" })
1118 .Property("ffa-version", "<0x10001>")
1119 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1120 .Property("execution-ctx-count", "<8>")
1121 .Property("exception-level", "<2>")
1122 .Property("execution-state", "<0>")
1123 .Property("entrypoint-offset", "<0x00002000>")
1124 .Property("messaging-method", "<1>")
1125 .Property("vm-availability-messages", "<0>")
1126 .Build();
1127 /* clang-format on */
1128 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1129 vm = &m->vm[0];
1130 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1131 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1132 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1133 manifest_dealloc();
1134
1135 /* clang-format off */
1136 dtb = ManifestDtBuilder()
1137 .Compatible({ "arm,ffa-manifest-1.0" })
1138 .Property("ffa-version", "<0x10001>")
1139 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1140 .Property("execution-ctx-count", "<8>")
1141 .Property("exception-level", "<2>")
1142 .Property("execution-state", "<0>")
1143 .Property("entrypoint-offset", "<0x00002000>")
1144 .Property("messaging-method", "<1>")
1145 .Property("vm-availability-messages", "<1>")
1146 .Build();
1147 /* clang-format on */
1148 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1149 vm = &m->vm[0];
1150 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1151 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1152 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1153 manifest_dealloc();
1154
1155 /* clang-format off */
1156 dtb = ManifestDtBuilder()
1157 .Compatible({ "arm,ffa-manifest-1.0" })
1158 .Property("ffa-version", "<0x10001>")
1159 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1160 .Property("execution-ctx-count", "<8>")
1161 .Property("exception-level", "<2>")
1162 .Property("execution-state", "<0>")
1163 .Property("entrypoint-offset", "<0x00002000>")
1164 .Property("messaging-method", "<1>")
1165 .Property("vm-availability-messages", "<2>")
1166 .Build();
1167 /* clang-format on */
1168 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1169 vm = &m->vm[0];
1170 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1171 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1172 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1173 manifest_dealloc();
1174
1175 /* clang-format off */
1176 dtb = ManifestDtBuilder()
1177 .Compatible({ "arm,ffa-manifest-1.0" })
1178 .Property("ffa-version", "<0x10001>")
1179 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1180 .Property("execution-ctx-count", "<8>")
1181 .Property("exception-level", "<2>")
1182 .Property("execution-state", "<0>")
1183 .Property("entrypoint-offset", "<0x00002000>")
1184 .Property("messaging-method", "<1>")
1185 .Property("vm-availability-messages", "<3>")
1186 .Build();
1187 /* clang-format on */
1188 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1189 vm = &m->vm[0];
1190 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1191 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1192 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1193 manifest_dealloc();
1194
1195 /* clang-format off */
1196 dtb = ManifestDtBuilder()
1197 .Compatible({ "arm,ffa-manifest-1.0" })
1198 .Property("ffa-version", "<0x10001>")
1199 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1200 .Property("execution-ctx-count", "<8>")
1201 .Property("exception-level", "<2>")
1202 .Property("execution-state", "<0>")
1203 .Property("entrypoint-offset", "<0x00002000>")
1204 .Property("messaging-method", "<1>")
1205 .Build();
1206 /* clang-format on */
1207 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1208 vm = &m->vm[0];
1209 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1210 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1211 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1212 manifest_dealloc();
1213
1214 /* clang-format off */
1215 dtb = ManifestDtBuilder()
1216 .Compatible({ "arm,ffa-manifest-1.0" })
1217 .Property("ffa-version", "<0x10001>")
1218 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1219 .Property("execution-ctx-count", "<8>")
1220 .Property("exception-level", "<2>")
1221 .Property("execution-state", "<0>")
1222 .Property("entrypoint-offset", "<0x00002000>")
1223 .Property("messaging-method", "<2>")
1224 .Property("vm-availability-messages", "<4>")
1225 .Build();
1226 /* clang-format on */
1227 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1228 MANIFEST_ERROR_VM_AVAILABILITY_MESSAGE_INVALID);
1229 vm = &m->vm[0];
1230 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1231 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1232 ASSERT_NE(vm->partition.vm_availability_messages.mbz, 0);
1233 manifest_dealloc();
1234}
1235
Olivier Depreza15f2352022-09-26 09:17:24 +02001236TEST_F(manifest, power_management)
1237{
1238 struct manifest_vm *vm;
1239 struct_manifest *m;
1240
Madhukar Pappireddy958c8412024-11-25 09:54:17 -06001241 /* S-EL1 partition power management field can only set bit 0. */
Olivier Depreza15f2352022-09-26 09:17:24 +02001242 /* clang-format off */
1243 std::vector<char> dtb = ManifestDtBuilder()
1244 .Compatible({ "arm,ffa-manifest-1.0" })
1245 .Property("ffa-version", "<0x10001>")
1246 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1247 .Property("execution-ctx-count", "<8>")
1248 .Property("exception-level", "<2>")
1249 .Property("execution-state", "<0>")
1250 .Property("entrypoint-offset", "<0x00002000>")
1251 .Property("messaging-method", "<1>")
Olivier Depreza15f2352022-09-26 09:17:24 +02001252 .Property("power-management-messages", "<0xf>")
1253 .Build();
1254 /* clang-format on */
1255 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1256 vm = &m->vm[0];
Madhukar Pappireddy958c8412024-11-25 09:54:17 -06001257 ASSERT_EQ(vm->partition.power_management, 1);
Olivier Depreza15f2352022-09-26 09:17:24 +02001258 manifest_dealloc();
1259
1260 /* S-EL0 partition power management field is forced to 0. */
1261 /* clang-format off */
1262 dtb = ManifestDtBuilder()
1263 .Compatible({ "arm,ffa-manifest-1.0" })
1264 .Property("ffa-version", "<0x10001>")
1265 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1266 .Property("execution-ctx-count", "<1>")
1267 .Property("exception-level", "<1>")
1268 .Property("execution-state", "<0>")
1269 .Property("entrypoint-offset", "<0x00002000>")
1270 .Property("messaging-method", "<1>")
1271 .Property("power-management-messages", "<0xff>")
1272 .Build();
1273 /* clang-format on */
1274 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1275 vm = &m->vm[0];
1276 ASSERT_EQ(vm->partition.power_management, 0);
1277}
1278
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001279TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001280{
Olivier Deprez93644652022-09-09 11:01:12 +02001281 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001282
1283 /* Not Compatible */
1284 /* clang-format off */
1285 std::vector<char> dtb = ManifestDtBuilder()
1286 .FfaValidManifest()
1287 .StartChild("rx_tx-info")
1288 .Compatible({ "foo,bar" })
1289 .EndChild()
1290 .Build();
1291 /* clang-format on */
1292 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1293 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001294 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001295
1296 /* Missing Properties */
1297 /* clang-format off */
1298 dtb = ManifestDtBuilder()
1299 .FfaValidManifest()
1300 .StartChild("rx_tx-info")
1301 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1302 .EndChild()
1303 .Build();
1304 /* clang-format on */
1305 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1306 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1307}
1308
Karl Meakinf955dbe2024-11-18 16:38:58 +00001309TEST_F(manifest, ffa_validate_mem_regions_not_compatible)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001310{
Olivier Deprez93644652022-09-09 11:01:12 +02001311 struct_manifest *m;
Karl Meakinf955dbe2024-11-18 16:38:58 +00001312 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001313
1314 /* Not Compatible */
1315 /* clang-format off */
Karl Meakinf955dbe2024-11-18 16:38:58 +00001316 dtb = ManifestDtBuilder()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001317 .FfaValidManifest()
1318 .StartChild("memory-regions")
1319 .Compatible({ "foo,bar" })
1320 .EndChild()
1321 .Build();
1322 /* clang-format on */
1323 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1324 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001325 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001326}
1327
1328TEST_F(manifest, ffa_validate_mem_regions_unavailable)
1329{
1330 struct_manifest *m;
1331 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001332
1333 /* Memory regions unavailable */
1334 /* clang-format off */
1335 dtb = ManifestDtBuilder()
1336 .FfaValidManifest()
1337 .StartChild("memory-regions")
1338 .Compatible({ "arm,ffa-manifest-memory-regions" })
1339 .EndChild()
1340 .Build();
1341 /* clang-format on */
1342 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1343 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001344 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001345}
1346
1347TEST_F(manifest, ffa_validate_mem_regions_missing_properties)
1348{
1349 struct_manifest *m;
1350 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001351
1352 /* Missing Properties */
1353 /* clang-format off */
1354 dtb = ManifestDtBuilder()
1355 .FfaValidManifest()
1356 .StartChild("memory-regions")
1357 .Compatible({ "arm,ffa-manifest-memory-regions" })
1358 .StartChild("test-memory")
1359 .Description("test-memory")
1360 .EndChild()
1361 .EndChild()
1362 .Build();
1363 /* clang-format on */
1364 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1365 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001366 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001367}
1368
1369TEST_F(manifest, ffa_validate_mem_regions_empty_region)
1370{
1371 struct_manifest *m;
1372 std::vector<char> dtb;
Manish Pandeyf06c9072020-09-29 15:41:58 +01001373
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001374 /* Empty memory region */
1375 /* clang-format off */
1376 dtb = ManifestDtBuilder()
1377 .FfaValidManifest()
1378 .StartChild("memory-regions")
1379 .Compatible({ "arm,ffa-manifest-memory-regions" })
1380 .Label("rx")
1381 .StartChild("rx")
1382 .Description("rx-buffer")
1383 .Property("base-address", "<0x7300000>")
1384 .Property("pages-count", "<0>")
1385 .Property("attributes", "<1>")
1386 .EndChild()
1387 .Label("tx")
1388 .StartChild("tx")
1389 .Description("tx-buffer")
1390 .Property("base-address", "<0x7310000>")
1391 .Property("pages-count", "<2>")
1392 .Property("attributes", "<3>")
1393 .EndChild()
1394 .EndChild()
1395 .StartChild("rx_tx-info")
1396 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1397 .Property("rx-buffer", "<&rx>")
1398 .Property("tx-buffer", "<&tx>")
1399 .EndChild()
1400 .Build();
1401 /* clang-format on */
1402 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1403 MANIFEST_ERROR_MEM_REGION_EMPTY);
1404 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001405}
1406
1407TEST_F(manifest, ffa_validate_mem_regions_base_address_and_relative_offset)
1408{
1409 struct_manifest *m;
1410 std::vector<char> dtb;
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001411
Davidson K8ccd2d02024-09-03 16:10:54 +05301412 /* Mutually exclusive base-address and load-address-relative-offset
1413 * properties */
Karl Meakine92efbe2023-06-01 14:16:22 +01001414 /* clang-format off */
1415 dtb = ManifestDtBuilder()
1416 .FfaValidManifest()
1417 .StartChild("memory-regions")
1418 .Compatible({ "arm,ffa-manifest-memory-regions" })
1419 .Label("rx")
1420 .StartChild("rx")
1421 .Description("rx-buffer")
1422 .Property("base-address", "<0x7300000>")
Davidson K8ccd2d02024-09-03 16:10:54 +05301423 .Property("load-address-relative-offset", "<0x7300000>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001424 .Property("pages-count", "<1>")
1425 .Property("attributes", "<1>")
1426 .EndChild()
1427 .EndChild()
1428 .Build();
1429 /* clang-format on */
1430 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1431 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1432 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001433}
1434
1435TEST_F(manifest, ffa_validate_mem_regions_relative_address_overflow)
1436{
1437 struct_manifest *m;
1438 std::vector<char> dtb;
1439
Karl Meakine92efbe2023-06-01 14:16:22 +01001440 /* Relative-address overflow*/
1441 /* clang-format off */
1442 dtb = ManifestDtBuilder()
1443 .FfaValidManifest()
1444 .Property("load-address", "<0xffffff00 0xffffff00>")
1445 .StartChild("memory-regions")
1446 .Compatible({ "arm,ffa-manifest-memory-regions" })
1447 .Label("rx")
1448 .StartChild("rx")
1449 .Description("rx-buffer")
Davidson K8ccd2d02024-09-03 16:10:54 +05301450 .Property("load-address-relative-offset", "<0xffffff00 0xffffff00>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001451 .Property("pages-count", "<1>")
1452 .Property("attributes", "<1>")
1453 .EndChild()
1454 .EndChild()
1455 .Build();
1456 /* clang-format on */
1457 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1458 MANIFEST_ERROR_INTEGER_OVERFLOW);
1459 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001460}
1461
1462TEST_F(manifest, ffa_validate_mem_regions_relative_offset_valid)
1463{
1464 struct_manifest *m;
1465 std::vector<char> dtb;
1466
1467 /* valid relative offset */
1468 /* clang-format off */
1469 dtb = ManifestDtBuilder()
1470 .FfaValidManifest()
1471 .Property("load-address", "<0xffffff00 0xffffff00>")
1472 .StartChild("memory-regions")
1473 .Compatible({ "arm,ffa-manifest-memory-regions" })
1474 .Label("rx")
1475 .StartChild("rx")
1476 .Description("rx-buffer")
1477 .Property("load-address-relative-offset", "<0x1000>")
1478 .Property("pages-count", "<1>")
1479 .Property("attributes", "<1>")
1480 .EndChild()
1481 .EndChild()
1482 .Build();
1483 /* clang-format on */
1484 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1485 manifest_dealloc();
1486}
1487
1488TEST_F(manifest, ffa_validate_mem_regions_overlapping)
1489{
1490 struct_manifest *m;
1491 std::vector<char> dtb;
Karl Meakine92efbe2023-06-01 14:16:22 +01001492
Daniel Boulby9279b552022-06-28 17:04:01 +01001493 /* Overlapping memory regions */
1494 /* clang-format off */
1495 dtb = ManifestDtBuilder()
1496 .FfaValidManifest()
1497 .StartChild("memory-regions")
1498 .Compatible({ "arm,ffa-manifest-memory-regions" })
1499 .Label("rx")
1500 .StartChild("rx")
1501 .Description("rx-buffer")
1502 .Property("base-address", "<0x7300000>")
1503 .Property("pages-count", "<1>")
1504 .Property("attributes", "<1>")
1505 .EndChild()
1506 .Label("tx")
1507 .StartChild("tx")
1508 .Description("tx-buffer")
1509 .Property("base-address", "<0x7300000>")
1510 .Property("pages-count", "<2>")
1511 .Property("attributes", "<3>")
1512 .EndChild()
1513 .EndChild()
1514 .Build();
1515 /* clang-format on */
1516 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1517 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001518 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001519
1520 /* clang-format off */
1521 dtb = ManifestDtBuilder()
1522 .FfaValidManifest()
1523 .StartChild("memory-regions")
1524 .Compatible({ "arm,ffa-manifest-memory-regions" })
1525 .Label("rx")
1526 .StartChild("rx")
1527 .Description("rx-buffer")
Karl Meakin6291eb22024-11-18 12:43:47 +00001528 .Property("load-address-relative-offset", "<0x0>")
1529 .Property("pages-count", "<1>")
1530 .Property("attributes", "<1>")
1531 .EndChild()
1532 .Label("tx")
1533 .StartChild("tx")
1534 .Description("tx-buffer")
1535 .Property("load-address-relative-offset", "<0x0>")
1536 .Property("pages-count", "<2>")
1537 .Property("attributes", "<3>")
1538 .EndChild()
1539 .EndChild()
1540 .Build();
1541 /* clang-format on */
1542 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1543 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1544 manifest_dealloc();
1545
1546 /* clang-format off */
1547 dtb = ManifestDtBuilder()
1548 .FfaValidManifest()
1549 .StartChild("memory-regions")
1550 .Compatible({ "arm,ffa-manifest-memory-regions" })
1551 .Label("rx")
1552 .StartChild("rx")
1553 .Description("rx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001554 .Property("base-address", "<0x7300000>")
1555 .Property("pages-count", "<2>")
1556 .Property("attributes", "<1>")
1557 .EndChild()
1558 .Label("tx")
1559 .StartChild("tx")
1560 .Description("tx-buffer")
1561 .Property("base-address", "<0x7301000>")
1562 .Property("pages-count", "<2>")
1563 .Property("attributes", "<3>")
1564 .EndChild()
1565 .EndChild()
1566 .Build();
1567 /* clang-format on */
1568 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1569 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001570 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001571
1572 /* clang-format off */
1573 dtb = ManifestDtBuilder()
1574 .FfaValidManifest()
1575 .StartChild("memory-regions")
1576 .Compatible({ "arm,ffa-manifest-memory-regions" })
1577 .Label("rx")
1578 .StartChild("rx")
1579 .Description("rx-buffer")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001580 .Property("base-address", "<0x7301000>")
1581 .Property("pages-count", "<1>")
1582 .Property("attributes", "<1>")
1583 .EndChild()
1584 .Label("tx")
1585 .StartChild("tx")
1586 .Description("tx-buffer")
1587 .Property("base-address", "<0x7300000>")
1588 .Property("pages-count", "<2>")
1589 .Property("attributes", "<3>")
1590 .EndChild()
1591 .EndChild()
1592 .Build();
1593 /* clang-format on */
1594 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1595 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001596 manifest_dealloc();
Karl Meakin6291eb22024-11-18 12:43:47 +00001597
1598 /* clang-format off */
1599 Partition_package spkg(dtb);
1600 dtb = ManifestDtBuilder()
1601 .FfaValidManifest()
1602 .StartChild("memory-regions")
1603 .Compatible({ "arm,ffa-manifest-memory-regions" })
1604 .StartChild("test-memory")
1605 .Description("test-memory")
1606 .Integer64Property("base-address", (uint64_t)&spkg,true)
1607 .Property("pages-count", "<1>")
1608 .Property("attributes", "<1>")
1609 .EndChild()
1610 .EndChild()
1611 .Build(true);
1612 /* clang-format on */
1613 spkg.init(dtb);
1614 ASSERT_EQ(ffa_manifest_from_spkg(&m, &spkg),
1615 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1616 manifest_dealloc();
1617}
1618
1619TEST_F(manifest, ffa_validate_mem_regions_overlapping_allowed)
1620{
1621 struct_manifest *m;
1622 std::vector<char> dtb;
1623
1624 /*
1625 * Mem regions are allowed to overlap with parent `load-address` if the
1626 * `load-address-relative-offset` was specified.
1627 */
1628 /* clang-format off */
1629 dtb = ManifestDtBuilder()
1630 .FfaValidManifest()
1631 .StartChild("memory-regions")
1632 .Compatible({ "arm,ffa-manifest-memory-regions" })
1633 .Label("rx")
1634 .StartChild("rx")
1635 .Description("rx-buffer")
1636 .Property("load-address-relative-offset", "<0x1000>")
1637 .Property("pages-count", "<1>")
1638 .Property("attributes", "<1>")
1639 .EndChild()
1640 .Label("tx")
1641 .StartChild("tx")
1642 .Description("tx-buffer")
1643 .Property("base-address", "<0x7300000>")
1644 .Property("pages-count", "<2>")
1645 .Property("attributes", "<3>")
1646 .EndChild()
1647 .EndChild()
1648 .Build();
1649 /* clang-format on */
1650 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1651 ASSERT_EQ(m->vm[0].partition.mem_regions[0].is_relative, true);
1652 ASSERT_EQ(m->vm[0].partition.mem_regions[0].base_address,
1653 m->vm[0].partition.load_addr + 0x1000);
1654 manifest_dealloc();
1655
1656 /* clang-format off */
1657 dtb = ManifestDtBuilder()
1658 .FfaValidManifest()
1659 .StartChild("memory-regions")
1660 .Compatible({ "arm,ffa-manifest-memory-regions" })
1661 .Label("rx")
1662 .StartChild("rx")
1663 .Description("rx-buffer")
1664 .Property("base-address", "<0x7300000>")
1665 .Property("pages-count", "<1>")
1666 .Property("attributes", "<1>")
1667 .EndChild()
1668 .Label("tx")
1669 .StartChild("tx")
1670 .Description("tx-buffer")
1671 .Property("load-address-relative-offset", "<0x1000>")
1672 .Property("pages-count", "<2>")
1673 .Property("attributes", "<3>")
1674 .EndChild()
1675 .EndChild()
1676 .Build();
1677 /* clang-format on */
1678 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1679 ASSERT_EQ(m->vm[0].partition.mem_regions[1].is_relative, true);
1680 ASSERT_EQ(m->vm[0].partition.mem_regions[1].base_address,
1681 m->vm[0].partition.load_addr + 0x1000);
1682 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001683}
1684
1685TEST_F(manifest, ffa_validate_mem_regions_unaligned)
1686{
1687 struct_manifest *m;
1688 std::vector<char> dtb;
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001689
1690 /* Unaligned memory region */
1691 /* clang-format off */
1692 dtb = ManifestDtBuilder()
1693 .FfaValidManifest()
1694 .StartChild("memory-regions")
1695 .Compatible({ "arm,ffa-manifest-memory-regions" })
1696 .Label("rx")
1697 .StartChild("rx")
1698 .Description("rx-buffer")
1699 .Property("base-address", "<0x7300FFF>")
1700 .Property("pages-count", "<2>")
1701 .Property("attributes", "<1>")
1702 .EndChild()
1703 .Label("tx")
1704 .StartChild("tx")
1705 .Description("tx-buffer")
1706 .Property("base-address", "<0x7303000>")
1707 .Property("pages-count", "<2>")
1708 .Property("attributes", "<3>")
1709 .EndChild()
1710 .EndChild()
1711 .Build();
1712 /* clang-format on */
1713 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1714 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1715 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001716}
1717
1718TEST_F(manifest, ffa_validate_mem_regions_different_rxtx_sizes)
1719{
1720 struct_manifest *m;
1721 std::vector<char> dtb;
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001722
Manish Pandeyf06c9072020-09-29 15:41:58 +01001723 /* Different RXTX buffer sizes */
1724 /* clang-format off */
1725 dtb = ManifestDtBuilder()
1726 .FfaValidManifest()
1727 .StartChild("memory-regions")
1728 .Compatible({ "arm,ffa-manifest-memory-regions" })
1729 .Label("rx")
1730 .StartChild("rx")
1731 .Description("rx-buffer")
1732 .Property("base-address", "<0x7300000>")
1733 .Property("pages-count", "<1>")
1734 .Property("attributes", "<1>")
1735 .EndChild()
1736 .Label("tx")
1737 .StartChild("tx")
1738 .Description("tx-buffer")
1739 .Property("base-address", "<0x7310000>")
1740 .Property("pages-count", "<2>")
1741 .Property("attributes", "<3>")
1742 .EndChild()
1743 .EndChild()
1744 .StartChild("rx_tx-info")
1745 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1746 .Property("rx-buffer", "<&rx>")
1747 .Property("tx-buffer", "<&tx>")
1748 .EndChild()
1749 .Build();
1750 /* clang-format on */
1751 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1752 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001753}
1754
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001755TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001756{
Olivier Deprez93644652022-09-09 11:01:12 +02001757 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001758
1759 /* Not Compatible */
1760 /* clang-format off */
1761 std::vector<char> dtb = ManifestDtBuilder()
1762 .FfaValidManifest()
1763 .StartChild("device-regions")
1764 .Compatible({ "foo,bar" })
1765 .EndChild()
1766 .Build();
1767 /* clang-format on */
1768 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1769 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001770 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001771
1772 /* Memory regions unavailable */
1773 /* clang-format off */
1774 dtb = ManifestDtBuilder()
1775 .FfaValidManifest()
1776 .StartChild("device-regions")
1777 .Compatible({ "arm,ffa-manifest-device-regions" })
1778 .EndChild()
1779 .Build();
1780 /* clang-format on */
1781 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1782 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001783 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001784
1785 /* Missing Properties */
1786 /* clang-format off */
1787 dtb = ManifestDtBuilder()
1788 .FfaValidManifest()
1789 .StartChild("device-regions")
1790 .Compatible({ "arm,ffa-manifest-device-regions" })
1791 .StartChild("test-device")
1792 .Description("test-device")
1793 .EndChild()
1794 .EndChild()
1795 .Build();
1796 /* clang-format on */
1797 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1798 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001799 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001800
1801 /* Malformed interrupt list pair */
1802 /* clang-format off */
1803 dtb = ManifestDtBuilder()
1804 .FfaValidManifest()
1805 .StartChild("device-regions")
1806 .Compatible({ "arm,ffa-manifest-device-regions" })
1807 .StartChild("test-device")
1808 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001809 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001810 .Property("pages-count", "<16>")
1811 .Property("attributes", "<3>")
1812 .Property("smmu-id", "<1>")
1813 .Property("stream-ids", "<0 1>")
1814 .Property("interrupts", "<2 3>, <4>")
1815 .EndChild()
1816 .EndChild()
1817 .Build();
1818 /* clang-format on */
1819 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1820 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001821 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001822
1823 /* Non-unique interrupt IDs */
1824 /* clang-format off */
1825 dtb = ManifestDtBuilder()
1826 .FfaValidManifest()
1827 .StartChild("device-regions")
1828 .Compatible({ "arm,ffa-manifest-device-regions" })
1829 .StartChild("test-device-0")
1830 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001831 .Property("base-address", "<0x24000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001832 .Property("pages-count", "<16>")
1833 .Property("attributes", "<3>")
1834 .Property("interrupts", "<2 3>")
1835 .EndChild()
1836 .StartChild("test-device-1")
1837 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001838 .Property("base-address", "<0x25000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001839 .Property("pages-count", "<16>")
1840 .Property("attributes", "<3>")
1841 .Property("interrupts", "<1 3>, <2 5> ")
1842 .EndChild()
1843 .EndChild()
1844 .Build();
Daniel Boulby941ef342023-11-21 13:47:15 +00001845
Daniel Boulby667334f2022-06-27 15:23:21 +01001846 /* clang-format on */
1847 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1848 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1849 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001850 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1851 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1852 3);
1853 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1854 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1855 3);
Daniel Boulby941ef342023-11-21 13:47:15 +00001856 manifest_dealloc();
1857
1858 /* Overlapping address space between two device region nodes. */
1859 /* clang-format off */
1860 dtb = ManifestDtBuilder()
1861 .FfaValidManifest()
1862 .StartChild("device-regions")
1863 .Compatible({"arm,ffa-manifest-device-regions"})
1864 .StartChild("test-device-0")
1865 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001866 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001867 .Property("pages-count", "<16>")
1868 .Property("attributes", "<3>")
1869 .EndChild()
1870 .StartChild("test-device-1")
1871 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001872 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001873 .Property("pages-count", "<16>")
1874 .Property("attributes", "<3>")
1875 .EndChild()
Daniel Boulby4339edc2024-02-21 14:59:00 +00001876 .EndChild()
Daniel Boulby941ef342023-11-21 13:47:15 +00001877 .Build();
1878
1879 /* clang-format on */
1880 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1881 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1882 manifest_dealloc();
1883
1884 /*
Daniel Boulby4339edc2024-02-21 14:59:00 +00001885 * Device regions cannot be defined outside of the regions specified in
1886 * the spmc.
Daniel Boulby941ef342023-11-21 13:47:15 +00001887 */
1888 /* clang-format off */
1889 dtb = ManifestDtBuilder()
1890 .FfaValidManifest()
Daniel Boulby941ef342023-11-21 13:47:15 +00001891 .StartChild("device-regions")
1892 .Compatible({"arm,ffa-manifest-device-regions"})
1893 .StartChild("test-device-0")
1894 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001895 .Property("base-address", "<0x50000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001896 .Property("pages-count", "<16>")
1897 .Property("attributes", "<3>")
1898 .EndChild()
1899 .EndChild()
1900 .Build();
1901 /* clang-format on */
1902 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
Daniel Boulby4339edc2024-02-21 14:59:00 +00001903 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
1904 manifest_dealloc();
1905
1906 /*
1907 * Memory defined as NS in SPMC manifest given Secure attribute should
1908 * fail.
1909 */
1910 /* clang-format off */
1911 dtb = ManifestDtBuilder()
1912 .FfaValidManifest()
1913 .StartChild("device-regions")
1914 .Compatible({"arm,ffa-manifest-device-regions"})
1915 .StartChild("test-device-0")
1916 .Description("test-device-0")
1917 .Property("base-address", "<0x20000000>")
1918 .Property("pages-count", "<16>")
1919 .Property("attributes", "<3>")
1920 .EndChild()
1921 .EndChild()
1922 .Build();
1923 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1924 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
Manish Pandeye68e7932020-04-23 15:29:28 +01001925}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001926
1927TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001928{
Olivier Deprez93644652022-09-09 11:01:12 +02001929 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001930
1931 /* clang-format off */
1932 std::vector<char> dtb = ManifestDtBuilder()
1933 .FfaValidManifest()
1934 .StartChild("rx_tx-info")
1935 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1936 .Property("rx-buffer", "<&rx>")
1937 .Property("tx-buffer", "<&tx>")
1938 .EndChild()
1939 .StartChild("memory-regions")
1940 .Compatible({ "arm,ffa-manifest-memory-regions" })
1941 .StartChild("test-memory")
1942 .Description("test-memory")
1943 .Property("base-address", "<0x7100000>")
1944 .Property("pages-count", "<4>")
1945 .Property("attributes", "<7>")
1946 .EndChild()
1947 .Label("rx")
1948 .StartChild("rx")
1949 .Description("rx-buffer")
1950 .Property("base-address", "<0x7300000>")
1951 .Property("pages-count", "<1>")
1952 .Property("attributes", "<1>")
1953 .EndChild()
1954 .Label("tx")
1955 .StartChild("tx")
1956 .Description("tx-buffer")
1957 .Property("base-address", "<0x7310000>")
1958 .Property("pages-count", "<1>")
1959 .Property("attributes", "<3>")
1960 .EndChild()
1961 .EndChild()
1962 .Build();
1963 /* clang-format on */
1964
1965 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1966 MANIFEST_ERROR_INVALID_MEM_PERM);
1967}
1968
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001969TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001970{
Olivier Deprez93644652022-09-09 11:01:12 +02001971 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001972
1973 /* clang-format off */
1974 std::vector<char> dtb = ManifestDtBuilder()
1975 .FfaValidManifest()
1976 .StartChild("rx_tx-info")
1977 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1978 .Property("rx-buffer", "<&rx>")
1979 .Property("tx-buffer", "<&tx>")
1980 .EndChild()
1981 .StartChild("memory-regions")
1982 .Compatible({ "arm,ffa-manifest-memory-regions" })
1983 .StartChild("test-memory")
1984 .Description("test-memory")
1985 .Property("base-address", "<0x7100000>")
1986 .Property("pages-count", "<4>")
1987 .Property("attributes", "<3>")
1988 .EndChild()
1989 .Label("rx")
1990 .StartChild("rx")
1991 .Description("rx-buffer")
1992 .Property("base-address", "<0x7300000>")
1993 .Property("pages-count", "<1>")
1994 .Property("attributes", "<1>")
1995 .EndChild()
1996 .Label("tx")
1997 .StartChild("tx")
1998 .Description("tx-buffer")
1999 .Property("base-address", "<0x7310000>")
2000 .Property("pages-count", "<1>")
2001 .Property("attributes", "<3>")
2002 .EndChild()
2003 .EndChild()
2004 .StartChild("device-regions")
2005 .Compatible({ "arm,ffa-manifest-device-regions" })
2006 .StartChild("test-device")
2007 .Description("test-device")
2008 .Property("base-address", "<0x7200000>")
2009 .Property("pages-count", "<16>")
2010 .Property("attributes", "<5>")
2011 .Property("smmu-id", "<1>")
2012 .Property("stream-ids", "<0 1>")
2013 .Property("interrupts", "<2 3>, <4 5>")
2014 .EndChild()
2015 .EndChild()
2016 .Build();
2017 /* clang-format on */
2018
2019 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2020 MANIFEST_ERROR_INVALID_MEM_PERM);
2021}
Manish Pandeye68e7932020-04-23 15:29:28 +01002022
Daniel Boulby801f8ef2022-06-27 14:21:01 +01002023TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01002024{
Olivier Deprez93644652022-09-09 11:01:12 +02002025 struct manifest_vm *vm;
2026 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01002027
2028 /* clang-format off */
2029 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01002030 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002031 .StartChild("rx_tx-info")
2032 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
2033 .Property("rx-buffer", "<&rx>")
2034 .Property("tx-buffer", "<&tx>")
2035 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01002036 .StartChild("memory-regions")
2037 .Compatible({ "arm,ffa-manifest-memory-regions" })
Olivier Deprez035fa152022-03-14 11:19:10 +01002038 .StartChild("test-memory-ns")
2039 .Description("test-memory")
2040 .Property("base-address", "<0x7200000>")
2041 .Property("pages-count", "<1>")
2042 .Property("attributes", "<0xb>")
2043 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002044 .Label("rx")
2045 .StartChild("rx")
2046 .Description("rx-buffer")
2047 .Property("base-address", "<0x7300000>")
2048 .Property("pages-count", "<1>")
2049 .Property("attributes", "<1>")
2050 .EndChild()
2051 .Label("tx")
2052 .StartChild("tx")
2053 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01002054 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002055 .Property("pages-count", "<1>")
2056 .Property("attributes", "<3>")
2057 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01002058 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01002059 .StartChild("device-regions")
2060 .Compatible({ "arm,ffa-manifest-device-regions" })
2061 .StartChild("test-device")
2062 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002063 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01002064 .Property("pages-count", "<16>")
2065 .Property("attributes", "<3>")
2066 .Property("smmu-id", "<1>")
2067 .Property("stream-ids", "<0 1>")
2068 .Property("interrupts", "<2 3>, <4 5>")
2069 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01002070 .StartChild("test-device-ns")
2071 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002072 .Property("base-address", "<0x20000000>")
Olivier Deprez035fa152022-03-14 11:19:10 +01002073 .Property("pages-count", "<1>")
2074 .Property("attributes", "<0x9>")
2075 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01002076 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01002077 .Build();
Daniel Boulby4339edc2024-02-21 14:59:00 +00002078
Olivier Deprez62d99e32020-01-09 15:58:07 +01002079 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01002080 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2081
Olivier Deprez93644652022-09-09 11:01:12 +02002082 vm = &m->vm[0];
2083 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01002084 ASSERT_THAT(
Kathleen Capella422b10b2023-06-30 18:28:27 -04002085 std::span(vm->partition.uuids[0].uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01002086 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02002087 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2088 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2089 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2090 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2091 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2092 ASSERT_EQ(vm->partition.boot_order, 0);
2093 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2094 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
Davidson K5d5f2792024-08-19 19:09:12 +05302095 ASSERT_EQ(vm->partition.mem_regions[0].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07002096
Olivier Deprez93644652022-09-09 11:01:12 +02002097 ASSERT_EQ(vm->partition.rxtx.available, true);
2098 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
2099 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
2100 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
2101 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
2102 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
2103 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
2104
Daniel Boulby4339edc2024-02-21 14:59:00 +00002105 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Olivier Deprez93644652022-09-09 11:01:12 +02002106 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002107 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002108 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2109 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2110 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Olivier Deprez93644652022-09-09 11:01:12 +02002111 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2112 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2113 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2114 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
Daniel Boulby4339edc2024-02-21 14:59:00 +00002115 ASSERT_EQ(vm->partition.dev_regions[1].base_address, 0x20000000);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002116 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01002117}
2118
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002119TEST_F(manifest, ffa_valid_interrupt_target_manifest)
2120{
2121 struct manifest_vm *vm;
2122 struct_manifest *m;
2123
2124 /* clang-format off */
2125 std::vector<char> dtb = ManifestDtBuilder()
2126 .FfaValidManifest()
2127 .StartChild("device-regions")
2128 .Compatible({ "arm,ffa-manifest-device-regions" })
2129 .StartChild("test-device")
2130 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002131 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002132 .Property("pages-count", "<16>")
2133 .Property("attributes", "<3>")
2134 .Property("smmu-id", "<1>")
2135 .Property("stream-ids", "<0 1>")
2136 .Property("interrupts", "<2 3>, <4 5>")
2137 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
2138 .EndChild()
2139 .EndChild()
2140 .Build();
2141 /* clang-format on */
2142
2143 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2144
2145 vm = &m->vm[0];
2146
Daniel Boulby4339edc2024-02-21 14:59:00 +00002147 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002148 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002149 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002150 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2151 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2152 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002153 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2154 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2155 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
2156 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
2157 0x123400005678);
2158 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2159 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
2160 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
2161 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
2162 0x1234567887654321);
2163}
2164
2165TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
2166{
2167 struct_manifest *m;
2168
2169 /* clang-format off */
2170 std::vector<char> dtb = ManifestDtBuilder()
2171 .FfaValidManifest()
2172 .StartChild("device-regions")
2173 .Compatible({ "arm,ffa-manifest-device-regions" })
2174 .StartChild("test-device")
2175 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002176 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002177 .Property("pages-count", "<16>")
2178 .Property("attributes", "<3>")
2179 .Property("smmu-id", "<1>")
2180 .Property("stream-ids", "<0 1>")
2181 .Property("interrupts", "<2 3>, <4 5>")
2182 .Property("interrupts-target", "<20 0x1234 0x5678>")
2183 .EndChild()
2184 .EndChild()
2185 .Build();
2186 /* clang-format on */
2187
2188 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2189 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
2190}
2191
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002192TEST_F(manifest, ffa_boot_order_not_unique)
2193{
2194 struct_manifest *m;
2195 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +00002196 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002197 struct boot_params params;
2198 Partition_package spkg_1;
2199 Partition_package spkg_2;
2200
2201 /* clang-format off */
2202 std::vector<char> dtb1 = ManifestDtBuilder()
2203 .Compatible({ "arm,ffa-manifest-1.0" })
2204 .Property("ffa-version", "<0x10001>")
2205 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2206 .FfaLoadAddress((uint64_t)&spkg_1)
2207 .Property("execution-ctx-count", "<1>")
2208 .Property("exception-level", "<1>")
2209 .Property("execution-state", "<0>")
2210 .Property("entrypoint-offset", "<0x00002000>")
2211 .Property("xlat-granule", "<0>")
2212 .Property("boot-order", "<1>")
2213 .Property("messaging-method", "<1>")
2214 .Property("ns-interrupts-action", "<0>")
2215 .Build();
2216
2217 std::vector<char> dtb2 = ManifestDtBuilder()
2218 .Compatible({ "arm,ffa-manifest-1.0" })
2219 .Property("ffa-version", "<0x10001>")
2220 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2221 .FfaLoadAddress((uint64_t)&spkg_2)
2222 .Property("execution-ctx-count", "<1>")
2223 .Property("exception-level", "<1>")
2224 .Property("execution-state", "<0>")
2225 .Property("entrypoint-offset", "<0x00002000>")
2226 .Property("xlat-granule", "<0>")
2227 .Property("boot-order", "<1>")
2228 .Property("messaging-method", "<1>")
2229 .Property("ns-interrupts-action", "<0>")
2230 .Build();
2231
2232 /* clang-format on */
2233 spkg_1.init(dtb1);
2234 spkg_2.init(dtb2);
2235
2236 /* clang-format off */
2237 std::vector<char> core_dtb = ManifestDtBuilder()
2238 .StartChild("hypervisor")
2239 .Compatible()
2240 .StartChild("vm1")
2241 .DebugName("ffa_partition_1")
2242 .FfaPartition()
2243 .LoadAddress((uint64_t)&spkg_1)
2244 .VcpuCount(1)
2245 .MemSize(0x10000000)
2246 .EndChild()
2247 .StartChild("vm2")
2248 .DebugName("ffa_partition_2")
2249 .FfaPartition()
2250 .LoadAddress((uint64_t)&spkg_2)
2251 .VcpuCount(1)
2252 .MemSize(0x10000000)
2253 .EndChild()
2254 .EndChild()
2255 .Build();
2256 /* clang-format on */
2257
2258 boot_params_init(&params, nullptr);
2259 memiter_init(&it, core_dtb.data(), core_dtb.size());
2260 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2261 MANIFEST_ERROR_INVALID_BOOT_ORDER);
Karl Meakin0f506a12025-02-08 23:28:45 +00002262
2263 mm_unlock_stage1(&mm_stage1_locked);
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002264}
Daniel Boulby941ef342023-11-21 13:47:15 +00002265
Kathleen Capella422b10b2023-06-30 18:28:27 -04002266TEST_F(manifest, ffa_valid_multiple_uuids)
2267{
2268 struct manifest_vm *vm;
2269 struct_manifest *m;
2270
2271 /* clang-format off */
2272 std::vector<char> dtb = ManifestDtBuilder()
2273 .Compatible({ "arm,ffa-manifest-1.0" })
2274 .Property("ffa-version", "<0x10002>")
2275 .Property("uuid",
2276 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,\
2277 <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2278 .Property("execution-ctx-count", "<1>")
2279 .Property("exception-level", "<2>")
2280 .Property("execution-state", "<0>")
2281 .Property("entrypoint-offset", "<0x00002000>")
2282 .Property("xlat-granule", "<0>")
2283 .Property("boot-order", "<0>")
2284 .Property("messaging-method", "<4>")
2285 .Property("ns-interrupts-action", "<1>")
2286 .Build();
2287 /* clang-format on */
2288 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2289
2290 vm = &m->vm[0];
2291 ASSERT_EQ(vm->partition.ffa_version, 0x10002);
2292 ASSERT_THAT(
2293 std::span(vm->partition.uuids[0].uuid, 4),
2294 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
2295 ASSERT_THAT(
2296 std::span(vm->partition.uuids[1].uuid, 4),
2297 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1daaa));
2298 ASSERT_EQ(vm->partition.uuid_count, 2);
2299 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2300 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2301 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2302 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2303 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2304 ASSERT_EQ(vm->partition.boot_order, 0);
2305 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2306 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
2307}
Karl Meakin45abeeb2024-08-02 16:55:44 +01002308
2309TEST_F(manifest, ffa_too_many_uuids)
2310{
2311 struct_manifest *m;
2312
2313 /* clang-format off */
2314 std::vector<char> dtb = ManifestDtBuilder()
2315 .Compatible({ "arm,ffa-manifest-1.0" })
2316 .Property("ffa-version", "<0x10002>")
2317 .Property("uuid",
2318 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,"
2319 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2320 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2321 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2322 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2323 .Property("execution-ctx-count", "<1>")
2324 .Property("exception-level", "<2>")
2325 .Property("execution-state", "<0>")
2326 .Property("entrypoint-offset", "<0x00002000>")
2327 .Property("xlat-granule", "<0>")
2328 .Property("boot-order", "<0>")
2329 .Property("messaging-method", "<4>")
2330 .Property("ns-interrupts-action", "<1>")
2331 .Build();
2332 /* clang-format on */
2333 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2334 MANIFEST_ERROR_TOO_MANY_UUIDS);
2335}
2336
Kathleen Capella422b10b2023-06-30 18:28:27 -04002337TEST_F(manifest, ffa_uuid_all_zeros)
2338{
2339 struct_manifest *m;
2340
2341 /* clang-format off */
2342 std::vector<char> dtb = ManifestDtBuilder()
2343 .Compatible({ "arm,ffa-manifest-1.0" })
2344 .Property("ffa-version", "<0x10002>")
2345 .Property("uuid",
2346 "<0x0 0x0 0x0 0x0>, <0x0 0x0 0x0 0x0>")
2347 .Property("execution-ctx-count", "<1>")
2348 .Property("exception-level", "<2>")
2349 .Property("execution-state", "<0>")
2350 .Property("entrypoint-offset", "<0x00002000>")
2351 .Property("xlat-granule", "<0>")
2352 .Property("boot-order", "<0>")
2353 .Property("messaging-method", "<4>")
2354 .Property("ns-interrupts-action", "<1>")
2355 .Build();
2356 /* clang-format on */
2357 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2358 MANIFEST_ERROR_UUID_ALL_ZEROS);
2359}
Daniel Boulby941ef342023-11-21 13:47:15 +00002360
2361/*
2362 * Test that the address space of two device region nodes specified across
2363 * different SPs cannot overlap.
2364 */
2365TEST_F(manifest, ffa_device_region_multi_sps)
2366{
2367 struct_manifest *m;
2368 struct memiter it;
Karl Meakin0f506a12025-02-08 23:28:45 +00002369 struct mm_stage1_locked mm_stage1_locked = mm_lock_stage1();
Daniel Boulby941ef342023-11-21 13:47:15 +00002370 struct boot_params params;
2371 Partition_package spkg_1;
2372 Partition_package spkg_2;
2373
2374 /* clang-format off */
2375 std::vector<char> dtb1 = ManifestDtBuilder()
2376 .Compatible({ "arm,ffa-manifest-1.0" })
2377 .Property("ffa-version", "<0x10001>")
2378 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2379 .FfaLoadAddress((uint64_t)&spkg_1)
2380 .Property("execution-ctx-count", "<1>")
2381 .Property("exception-level", "<0>")
2382 .Property("execution-state", "<0>")
2383 .Property("entrypoint-offset", "<0x0>")
2384 .Property("xlat-granule", "<0>")
2385 .Property("messaging-method", "<0x7>")
2386 .StartChild("device-regions")
2387 .Compatible({ "arm,ffa-manifest-device-regions" })
2388 .StartChild("test-device-0")
2389 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002390 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002391 .Property("pages-count", "<16>")
2392 .Property("attributes", "<3>")
2393 .EndChild()
2394 .EndChild()
2395 .Build();
2396
2397 std::vector<char> dtb2 = ManifestDtBuilder()
2398 .Compatible({ "arm,ffa-manifest-1.0" })
2399 .Property("ffa-version", "<0x10001>")
2400 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2401 .FfaLoadAddress((uint64_t)&spkg_2)
2402 .Property("execution-ctx-count", "<1>")
2403 .Property("exception-level", "<0>")
2404 .Property("execution-state", "<0>")
2405 .Property("entrypoint-offset", "<0x0>")
2406 .Property("xlat-granule", "<0>")
2407 .Property("messaging-method", "<0x7>")
2408 .StartChild("device-regions")
2409 .Compatible({ "arm,ffa-manifest-device-regions" })
2410 .StartChild("test-device-0")
2411 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002412 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002413 .Property("pages-count", "<16>")
2414 .Property("attributes", "<3>")
2415 .EndChild()
2416 .EndChild()
2417 .Build();
2418
2419 /* clang-format on */
2420 spkg_1.init(dtb1);
2421 spkg_2.init(dtb2);
2422
2423 /* clang-format off */
2424 std::vector<char> core_dtb = ManifestDtBuilder()
2425 .StartChild("hypervisor")
2426 .Compatible()
2427 .StartChild("vm1")
2428 .DebugName("ffa_partition_1")
2429 .FfaPartition()
2430 .LoadAddress((uint64_t)&spkg_1)
2431 .VcpuCount(1)
2432 .MemSize(0x4000)
2433 .EndChild()
2434 .StartChild("vm2")
2435 .DebugName("ffa_partition_2")
2436 .FfaPartition()
2437 .LoadAddress((uint64_t)&spkg_2)
2438 .VcpuCount(1)
2439 .MemSize(0x4000)
2440 .EndChild()
2441 .EndChild()
2442 .Build();
2443 /* clang-format on */
2444 boot_params_init(&params, &spkg_1);
2445 memiter_init(&it, core_dtb.data(), core_dtb.size());
2446 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2447 MANIFEST_ERROR_MEM_REGION_OVERLAP);
2448
2449 manifest_dealloc();
2450
2451 /* clang-format off */
2452 dtb1 = ManifestDtBuilder()
2453 .Compatible({ "arm,ffa-manifest-1.0" })
2454 .Property("ffa-version", "<0x10001>")
2455 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2456 .FfaLoadAddress((uint64_t)&spkg_1)
2457 .Property("execution-ctx-count", "<1>")
2458 .Property("exception-level", "<0>")
2459 .Property("execution-state", "<0>")
2460 .Property("entrypoint-offset", "<0x0>")
2461 .Property("xlat-granule", "<0>")
2462 .Property("messaging-method", "<0x7>")
2463 .StartChild("device-regions")
2464 .Compatible({ "arm,ffa-manifest-device-regions" })
2465 .StartChild("test-device-0")
2466 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002467 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002468 .Property("pages-count", "<16>")
2469 .Property("attributes", "<3>")
2470 .EndChild()
2471 .EndChild()
2472 .Build();
2473
2474 dtb2 = ManifestDtBuilder()
2475 .Compatible({ "arm,ffa-manifest-1.0" })
2476 .Property("ffa-version", "<0x10001>")
2477 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2478 .FfaLoadAddress((uint64_t)&spkg_2)
2479 .Property("execution-ctx-count", "<1>")
2480 .Property("exception-level", "<0>")
2481 .Property("execution-state", "<0>")
2482 .Property("entrypoint-offset", "<0x0>")
2483 .Property("xlat-granule", "<0>")
2484 .Property("messaging-method", "<0x7>")
2485 .StartChild("device-regions")
2486 .Compatible({ "arm,ffa-manifest-device-regions" })
2487 .StartChild("test-device-0")
2488 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002489 .Property("base-address", "<0x25000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002490 .Property("pages-count", "<16>")
2491 .Property("attributes", "<3>")
2492 .EndChild()
2493 .EndChild()
2494 .Build();
2495
2496 /* clang-format on */
2497 spkg_1.init(dtb1);
2498 spkg_2.init(dtb2);
2499
2500 /* clang-format off */
2501 core_dtb = ManifestDtBuilder()
2502 .StartChild("hypervisor")
2503 .Compatible()
2504 .StartChild("vm1")
2505 .DebugName("ffa_partition_1")
2506 .FfaPartition()
2507 .LoadAddress((uint64_t)&spkg_1)
2508 .VcpuCount(1)
2509 .MemSize(0x4000)
2510 .EndChild()
2511 .StartChild("vm2")
2512 .DebugName("ffa_partition_2")
2513 .FfaPartition()
2514 .LoadAddress((uint64_t)&spkg_2)
2515 .VcpuCount(1)
2516 .MemSize(0x4000)
2517 .EndChild()
2518 .EndChild()
2519 .Build();
2520 /* clang-format on */
2521 boot_params_init(&params, &spkg_1);
2522 memiter_init(&it, core_dtb.data(), core_dtb.size());
2523 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2524 MANIFEST_SUCCESS);
Karl Meakin0f506a12025-02-08 23:28:45 +00002525
2526 mm_unlock_stage1(&mm_stage1_locked);
Daniel Boulby941ef342023-11-21 13:47:15 +00002527}
Madhukar Pappireddy99c5eff2024-07-08 15:07:41 -05002528
2529/*
2530 * Tests to trigger various error conditions while parsing dma related
2531 * properties of memory region nodes.
2532 */
2533TEST_F(manifest, ffa_memory_region_invalid_dma_properties)
2534{
2535 struct_manifest *m;
2536
2537 /*
2538 * SMMU ID must be specified if the partition specifies Stream IDs for
2539 * any device upstream of SMMU.
2540 */
2541 /* clang-format off */
2542 std::vector<char> dtb = ManifestDtBuilder()
2543 .FfaValidManifest()
2544 .StartChild("memory-regions")
2545 .Compatible({ "arm,ffa-manifest-memory-regions" })
2546 .StartChild("test-memory")
2547 .Description("test-memory")
2548 .Property("base-address", "<0x7100000>")
2549 .Property("pages-count", "<16>")
2550 .Property("attributes", "<3>")
2551 .Property("stream-ids", "<0 1>")
2552 .Property("interrupts", "<2 3>, <4 5>")
2553 .EndChild()
2554 .EndChild()
2555 .Build();
2556 /* clang-format on */
2557
2558 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2559 MANIFEST_ERROR_MISSING_SMMU_ID);
2560 manifest_dealloc();
2561
2562 /*
2563 * All stream ids belonging to a dma device must specify the same access
2564 * permissions.
2565 */
2566 /* clang-format off */
2567 dtb = ManifestDtBuilder()
2568 .FfaValidManifest()
2569 .StartChild("memory-regions")
2570 .Compatible({ "arm,ffa-manifest-memory-regions" })
2571 .StartChild("test-memory")
2572 .Description("test-memory")
2573 .Property("base-address", "<0x7100000>")
2574 .Property("pages-count", "<16>")
2575 .Property("attributes", "<3>")
2576 .Property("smmu-id", "<1>")
2577 .Property("stream-ids", "<0 1>")
2578 .Property("stream-ids-access-permissions", "<0x3 0xb>")
2579 .Property("interrupts", "<2 3>, <4 5>")
2580 .EndChild()
2581 .EndChild()
2582 .Build();
2583 /* clang-format on */
2584
2585 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2586 MANIFEST_ERROR_MISMATCH_DMA_ACCESS_PERMISSIONS);
2587 manifest_dealloc();
2588
2589 /*
2590 * DMA device stream ID count exceeds predefined limit.
2591 */
2592 /* clang-format off */
2593 dtb = ManifestDtBuilder()
2594 .FfaValidManifest()
2595 .StartChild("memory-regions")
2596 .Compatible({ "arm,ffa-manifest-memory-regions" })
2597 .StartChild("test-memory")
2598 .Description("test-memory")
2599 .Property("base-address", "<0x7100000>")
2600 .Property("pages-count", "<16>")
2601 .Property("attributes", "<3>")
2602 .Property("smmu-id", "<1>")
2603 .Property("stream-ids", "<0 1 4 9 12 >")
2604 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3>")
2605 .EndChild()
2606 .EndChild()
2607 .Build();
2608 /* clang-format on */
2609
2610 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2611 MANIFEST_ERROR_STREAM_IDS_OVERFLOW);
2612 manifest_dealloc();
2613
2614 /*
2615 * DMA access permissions count exceeds predefined limit
2616 */
2617 /* clang-format off */
2618 dtb = ManifestDtBuilder()
2619 .FfaValidManifest()
2620 .StartChild("memory-regions")
2621 .Compatible({ "arm,ffa-manifest-memory-regions" })
2622 .StartChild("test-memory")
2623 .Description("test-memory")
2624 .Property("base-address", "<0x7100000>")
2625 .Property("pages-count", "<16>")
2626 .Property("attributes", "<3>")
2627 .Property("smmu-id", "<1>")
2628 .Property("stream-ids", "<0 1>")
2629 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3 0x3 0x3>")
2630 .EndChild()
2631 .EndChild()
2632 .Build();
2633 /* clang-format on */
2634
2635 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2636 MANIFEST_ERROR_DMA_ACCESS_PERMISSIONS_OVERFLOW);
2637}
2638
2639/*
2640 * Tests to trigger various error conditions while parsing dma related
2641 * properties of device region nodes.
2642 */
2643TEST_F(manifest, ffa_device_region_invalid_dma_properties)
2644{
2645 struct_manifest *m;
2646
2647 /*
2648 * SMMU ID must be specified if the partition specifies Stream IDs for
2649 * any device upstream of SMMU.
2650 */
2651 /* clang-format off */
2652 std::vector<char> dtb = ManifestDtBuilder()
2653 .FfaValidManifest()
2654 .StartChild("device-regions")
2655 .Compatible({ "arm,ffa-manifest-device-regions" })
2656 .StartChild("test-device")
2657 .Description("test-device")
2658 .Property("base-address", "<0x24000000>")
2659 .Property("pages-count", "<16>")
2660 .Property("attributes", "<3>")
2661 .Property("stream-ids", "<0 1>")
2662 .Property("interrupts", "<2 3>, <4 5>")
2663 .EndChild()
2664 .EndChild()
2665 .Build();
2666 /* clang-format on */
2667
2668 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2669 MANIFEST_ERROR_MISSING_SMMU_ID);
2670 manifest_dealloc();
2671
2672 /*
2673 * Dma devices defined through device region nodes exceed predefined
2674 * limit.
2675 */
2676 /* clang-format off */
2677 dtb = ManifestDtBuilder()
2678 .FfaValidManifest()
2679 .StartChild("device-regions")
2680 .Compatible({ "arm,ffa-manifest-device-regions" })
2681 .StartChild("test-device-0")
2682 .Description("test-device-0")
2683 .Property("base-address", "<0x27000000>")
2684 .Property("pages-count", "<16>")
2685 .Property("attributes", "<3>")
2686 .Property("smmu-id", "<1>")
2687 .Property("stream-ids", "<0 1>")
2688 .EndChild()
2689 .StartChild("test-device-1")
2690 .Description("test-device-1")
2691 .Property("base-address", "<0x25000000>")
2692 .Property("pages-count", "<16>")
2693 .Property("attributes", "<3>")
2694 .Property("smmu-id", "<1>")
2695 .Property("stream-ids", "<2 3>")
2696 .EndChild()
2697 .StartChild("test-device-2")
2698 .Description("test-device-2")
2699 .Property("base-address", "<0x26000000>")
2700 .Property("pages-count", "<16>")
2701 .Property("attributes", "<3>")
2702 .Property("smmu-id", "<1>")
2703 .Property("stream-ids", "<4 5>")
2704 .EndChild()
2705 .EndChild()
2706 .Build();
2707 /* clang-format on */
2708
2709 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2710 MANIFEST_ERROR_DMA_DEVICE_OVERFLOW);
2711}
David Brazdil7a462ec2019-08-15 12:27:47 +01002712} /* namespace */