blob: 4a78f594e9e9e67055d8278db8ec2853fb17c66e [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"
J-Alves2f86c1e2022-02-23 18:44:19 +000020#include "hf/sp_pkg.h"
David Brazdil7a462ec2019-08-15 12:27:47 +010021}
22
23namespace
24{
Andrew Scullae9962e2019-10-03 16:51:16 +010025using ::testing::ElementsAre;
David Brazdil7a462ec2019-08-15 12:27:47 +010026using ::testing::Eq;
Andrew Scullae9962e2019-10-03 16:51:16 +010027using ::testing::IsEmpty;
David Brazdil7a462ec2019-08-15 12:27:47 +010028using ::testing::NotNull;
29
Daniel Boulby801f8ef2022-06-27 14:21:01 +010030using struct_manifest = struct manifest;
31
J-Alves5c0ae6f2023-06-14 15:20:21 +010032constexpr size_t TEST_HEAP_SIZE = PAGE_SIZE * 128;
Daniel Boulby801f8ef2022-06-27 14:21:01 +010033
David Brazdil52256ff2019-08-23 15:15:15 +010034template <typename T>
David Brazdil0dbb41f2019-09-09 18:03:35 +010035void exec(const char *program, const char *args[], const T &stdin,
David Brazdil52256ff2019-08-23 15:15:15 +010036 std::vector<char> *stdout)
37{
38 /* Create two pipes, one for stdin and one for stdout. */
39 int pipes[2][2];
40 pipe(pipes[0]);
41 pipe(pipes[1]);
David Brazdil7a462ec2019-08-15 12:27:47 +010042
David Brazdil52256ff2019-08-23 15:15:15 +010043 /* Assign FDs for reading/writing by the parent/child. */
44 int parent_read_fd = pipes[1][0]; /* stdout pipe, read FD */
45 int parent_write_fd = pipes[0][1]; /* stdin pipe, write FD */
46 int child_read_fd = pipes[0][0]; /* stdin pipe, read FD */
47 int child_write_fd = pipes[1][1]; /* stdout pipe, write FD */
David Brazdil7a462ec2019-08-15 12:27:47 +010048
David Brazdil52256ff2019-08-23 15:15:15 +010049 if (fork()) {
50 /* Parent process. */
51 std::array<char, 128> buf;
52 ssize_t res;
53
54 /* Close child FDs which won't be used. */
55 close(child_read_fd);
56 close(child_write_fd);
57
58 /* Write to stdin. */
59 for (size_t count = 0; count < stdin.size();) {
60 res = write(parent_write_fd, stdin.data() + count,
61 stdin.size() - count);
62 if (res < 0) {
63 std::cerr << "IO error" << std::endl;
64 exit(1);
65 }
66 count += res;
67 }
68 close(parent_write_fd);
69
70 /* Read from stdout. */
71 while (true) {
72 res = read(parent_read_fd, buf.data(), buf.size());
73 if (res == 0) {
74 /* EOF */
75 break;
76 } else if (res < 0) {
77 std::cerr << "IO error" << std::endl;
78 exit(1);
79 }
80 stdout->insert(stdout->end(), buf.begin(),
81 buf.begin() + res);
82 }
83 close(parent_read_fd);
84 } else {
85 /* Child process. */
86
87 /* Redirect stdin/stdout to read/write FDs. */
88 dup2(child_read_fd, STDIN_FILENO);
89 dup2(child_write_fd, STDOUT_FILENO);
90
91 /* Close all FDs which are now unused. */
92 close(child_read_fd);
93 close(child_write_fd);
94 close(parent_read_fd);
95 close(parent_write_fd);
96
97 /* Execute the given program. */
David Brazdil0dbb41f2019-09-09 18:03:35 +010098 execv(program, const_cast<char *const *>(args));
David Brazdil52256ff2019-08-23 15:15:15 +010099 }
100}
101
102/**
103 * Class for programatically building a Device Tree.
104 *
105 * Usage:
106 * std::vector<char> dtb = ManifestDtBuilder()
107 * .Command1()
108 * .Command2()
109 * ...
110 * .CommandN()
111 * .Build();
112 */
113class ManifestDtBuilder
114{
115 public:
116 ManifestDtBuilder()
117 {
118 dts_ << "/dts-v1/;" << std::endl;
119 dts_ << std::endl;
120
121 /* Start root node. */
122 StartChild("/");
123 }
124
Andrew Scullae9962e2019-10-03 16:51:16 +0100125 std::vector<char> Build(bool dump = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100126 {
David Brazdil0dbb41f2019-09-09 18:03:35 +0100127 const char *program = "./build/image/dtc.py";
128 const char *dtc_args[] = {program, "compile", NULL};
David Brazdil52256ff2019-08-23 15:15:15 +0100129 std::vector<char> dtc_stdout;
130
131 /* Finish root node. */
132 EndChild();
133
Andrew Scullae9962e2019-10-03 16:51:16 +0100134 if (dump) {
135 Dump();
136 }
137
David Brazdil0dbb41f2019-09-09 18:03:35 +0100138 exec(program, dtc_args, dts_.str(), &dtc_stdout);
David Brazdil52256ff2019-08-23 15:15:15 +0100139 return dtc_stdout;
140 }
141
Andrew Scullae9962e2019-10-03 16:51:16 +0100142 void Dump()
143 {
144 std::cerr << dts_.str() << std::endl;
145 }
146
David Brazdil52256ff2019-08-23 15:15:15 +0100147 ManifestDtBuilder &StartChild(const std::string_view &name)
148 {
149 dts_ << name << " {" << std::endl;
150 return *this;
151 }
152
153 ManifestDtBuilder &EndChild()
154 {
155 dts_ << "};" << std::endl;
156 return *this;
157 }
158
David Brazdil74e9c3b2019-08-28 11:09:08 +0100159 ManifestDtBuilder &Compatible(const std::vector<std::string_view>
160 &value = {"hafnium,hafnium"})
161 {
162 return StringListProperty("compatible", value);
163 }
164
David Brazdil52256ff2019-08-23 15:15:15 +0100165 ManifestDtBuilder &DebugName(const std::string_view &value)
166 {
167 return StringProperty("debug_name", value);
168 }
169
Manish Pandey6542f5c2020-04-27 14:37:46 +0100170 ManifestDtBuilder &Description(const std::string_view &value)
171 {
172 return StringProperty("description", value);
173 }
174
David Brazdil52256ff2019-08-23 15:15:15 +0100175 ManifestDtBuilder &KernelFilename(const std::string_view &value)
176 {
177 return StringProperty("kernel_filename", value);
178 }
179
David Brazdile6f83222019-09-23 14:47:37 +0100180 ManifestDtBuilder &RamdiskFilename(const std::string_view &value)
181 {
182 return StringProperty("ramdisk_filename", value);
183 }
184
David Brazdil080ee312020-02-25 15:30:30 -0800185 ManifestDtBuilder &BootAddress(uint64_t value)
186 {
187 return Integer64Property("boot_address", value);
188 }
189
Andrew Scullae9962e2019-10-03 16:51:16 +0100190 ManifestDtBuilder &VcpuCount(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100191 {
192 return IntegerProperty("vcpu_count", value);
193 }
194
Andrew Scullae9962e2019-10-03 16:51:16 +0100195 ManifestDtBuilder &MemSize(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100196 {
197 return IntegerProperty("mem_size", value);
198 }
199
Andrew Scullae9962e2019-10-03 16:51:16 +0100200 ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
201 {
202 return IntegerListProperty("smc_whitelist", value);
203 }
204
205 ManifestDtBuilder &SmcWhitelistPermissive()
206 {
207 return BooleanProperty("smc_whitelist_permissive");
208 }
209
Olivier Deprez62d99e32020-01-09 15:58:07 +0100210 ManifestDtBuilder &LoadAddress(uint64_t value)
211 {
Karl Meakincedbdf92024-11-19 13:47:53 +0000212 return Integer64Property("load_address", value, true);
Olivier Deprez62d99e32020-01-09 15:58:07 +0100213 }
214
215 ManifestDtBuilder &FfaPartition()
216 {
217 return BooleanProperty("is_ffa_partition");
218 }
219
Andrew Scullae9962e2019-10-03 16:51:16 +0100220 ManifestDtBuilder &Property(const std::string_view &name,
221 const std::string_view &value)
222 {
223 dts_ << name << " = " << value << ";" << std::endl;
224 return *this;
225 }
226
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100227 ManifestDtBuilder &Label(const std::string_view &name)
228 {
229 dts_ << name << ": ";
230 return *this;
231 }
232
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100233 ManifestDtBuilder &FfaValidManifest()
234 {
235 Compatible({"arm,ffa-manifest-1.0"});
236 Property("ffa-version", "<0x10000>");
237 Property("uuid",
238 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>");
239 Property("execution-ctx-count", "<1>");
240 Property("exception-level", "<2>");
241 Property("execution-state", "<0>");
J-Alves2f86c1e2022-02-23 18:44:19 +0000242 Property("entrypoint-offset", "<0x00002000>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100243 Property("xlat-granule", "<0>");
J-Alvesb37fd082020-10-22 12:29:21 +0100244 Property("boot-order", "<0>");
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400245 Property("messaging-method", "<0x4>");
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500246 Property("ns-interrupts-action", "<1>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100247 return *this;
248 }
249
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400250 ManifestDtBuilder &FfaLoadAddress(uint64_t value)
251 {
Karl Meakincedbdf92024-11-19 13:47:53 +0000252 Integer64Property("load-address", value, true);
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400253 return *this;
254 }
255
David Brazdil52256ff2019-08-23 15:15:15 +0100256 ManifestDtBuilder &StringProperty(const std::string_view &name,
257 const std::string_view &value)
258 {
259 dts_ << name << " = \"" << value << "\";" << std::endl;
260 return *this;
261 }
262
David Brazdil74e9c3b2019-08-28 11:09:08 +0100263 ManifestDtBuilder &StringListProperty(
264 const std::string_view &name,
265 const std::vector<std::string_view> &value)
266 {
267 bool is_first = true;
268
269 dts_ << name << " = ";
270 for (const std::string_view &entry : value) {
271 if (is_first) {
272 is_first = false;
273 } else {
274 dts_ << ", ";
275 }
276 dts_ << "\"" << entry << "\"";
277 }
278 dts_ << ";" << std::endl;
279 return *this;
280 }
281
David Brazdil52256ff2019-08-23 15:15:15 +0100282 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Karl Meakincedbdf92024-11-19 13:47:53 +0000283 uint32_t value, bool hex = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100284 {
Karl Meakincedbdf92024-11-19 13:47:53 +0000285 std::ostream_iterator<char> out(dts_);
286
287 if (hex) {
288 std::format_to(out, "{} = <{:#08x}>;\n", name, value);
289 } else {
290 std::format_to(out, "{} = <{}>;\n", name, value);
291 }
David Brazdil52256ff2019-08-23 15:15:15 +0100292 return *this;
293 }
294
David Brazdil080ee312020-02-25 15:30:30 -0800295 ManifestDtBuilder &Integer64Property(const std::string_view &name,
Karl Meakincedbdf92024-11-19 13:47:53 +0000296 uint64_t value, bool hex = false)
David Brazdil080ee312020-02-25 15:30:30 -0800297 {
298 uint32_t high = value >> 32;
299 uint32_t low = (uint32_t)value;
Karl Meakincedbdf92024-11-19 13:47:53 +0000300 std::ostream_iterator<char> out(dts_);
301
302 if (hex) {
303 std::format_to(out, "{} = <{:#08x} {:#08x}>;\n", name,
304 high, low);
305 } else {
306 std::format_to(out, "{} = <{} {}>;\n", name, high, low);
307 }
308
David Brazdil080ee312020-02-25 15:30:30 -0800309 return *this;
310 }
311
Andrew Scullae9962e2019-10-03 16:51:16 +0100312 ManifestDtBuilder &IntegerListProperty(
313 const std::string_view &name,
314 const std::vector<uint32_t> &value)
315 {
316 dts_ << name << " = < ";
317 for (const uint32_t entry : value) {
318 dts_ << entry << " ";
319 }
320 dts_ << ">;" << std::endl;
321 return *this;
322 }
323
324 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
325 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000326 dts_ << name << ";" << std::endl;
327 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100328 }
329
David Brazdil52256ff2019-08-23 15:15:15 +0100330 std::stringstream dts_;
331};
332
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100333class manifest : public ::testing::Test
David Brazdil0dbb41f2019-09-09 18:03:35 +0100334{
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100335 void SetUp() override
336 {
337 test_heap = std::make_unique<uint8_t[]>(TEST_HEAP_SIZE);
338 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
339 mpool_add_chunk(&ppool, test_heap.get(), TEST_HEAP_SIZE);
340 }
341
Olivier Deprez93644652022-09-09 11:01:12 +0200342 void TearDown() override
343 {
344 manifest_dealloc();
345 }
346
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100347 std::unique_ptr<uint8_t[]> test_heap;
348
349 protected:
Olivier Deprez62d99e32020-01-09 15:58:07 +0100350 struct mpool ppool;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100351
Olivier Deprez93644652022-09-09 11:01:12 +0200352 void manifest_dealloc(void)
353 {
354 manifest_deinit(&ppool);
355 }
356
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100357 public:
358 /**
359 * Class for programatically building a Partition package.
360 */
361 class Partition_package
362 {
363 public:
364 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
365 __attribute__((
366 aligned(PAGE_SIZE))) char manifest_dtb[PAGE_SIZE] = {};
367 __attribute__((aligned(PAGE_SIZE))) char img[PAGE_SIZE] = {};
David Brazdil0dbb41f2019-09-09 18:03:35 +0100368
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100369 Partition_package(const std::vector<char> &vec)
370 {
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400371 init(vec);
372 }
373
374 Partition_package()
375 {
376 }
377
378 void init(const std::vector<char> &vec)
379 {
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100380 // Initialise header field
381 spkg.magic = SP_PKG_HEADER_MAGIC;
382 spkg.version = SP_PKG_HEADER_VERSION_2;
383 spkg.pm_offset = PAGE_SIZE;
384 spkg.pm_size = vec.size();
385 spkg.img_offset = 2 * PAGE_SIZE;
386 spkg.img_size = ARRAY_SIZE(img);
387
388 // Copy dtb into package
389 std::copy(vec.begin(), vec.end(), manifest_dtb);
390 }
391 };
392
J-Alves77b6f4f2023-03-15 11:34:49 +0000393 static void boot_params_init(struct boot_params *params,
394 Partition_package *pkg)
395 {
396 /*
397 * For the manifest tests we only care about the memory ranges
398 * in boot_params.
399 */
400 params->mem_ranges[0].begin = pa_init((uintpaddr_t)0x7000000);
401 params->mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
402 params->mem_ranges_count = 1;
403
404 if (pkg != nullptr) {
405 auto mem_base = (uintpaddr_t)pkg;
406 uintpaddr_t mem_end =
407 mem_base + sp_pkg_get_mem_size(&pkg->spkg);
408
409 params->mem_ranges_count++;
410
411 params->mem_ranges[1].begin = pa_init(mem_base);
412 params->mem_ranges[1].end = pa_init(mem_end);
413 }
414
415 params->ns_mem_ranges[0].begin =
416 pa_init((uintpaddr_t)0x7000000);
417 params->ns_mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
418 params->ns_mem_ranges_count = 1;
Daniel Boulby4339edc2024-02-21 14:59:00 +0000419
420 params->ns_device_mem_ranges[0].begin =
421 pa_init((uintpaddr_t)0x20000000);
422 params->ns_device_mem_ranges[0].end =
423 pa_init((uintpaddr_t)0x24000000);
424 params->ns_device_mem_ranges_count = 1;
425
426 params->device_mem_ranges[0].begin =
427 pa_init((uintpaddr_t)0x24000000);
428 params->device_mem_ranges[0].end =
429 pa_init((uintpaddr_t)0x28000000);
430 params->device_mem_ranges_count = 1;
J-Alves77b6f4f2023-03-15 11:34:49 +0000431 }
432
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100433 enum manifest_return_code manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200434 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100435 {
436 struct memiter it;
437 struct mm_stage1_locked mm_stage1_locked;
J-Alves77b6f4f2023-03-15 11:34:49 +0000438 struct boot_params params;
439
440 boot_params_init(&params, nullptr);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100441
442 memiter_init(&it, vec.data(), vec.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100443
J-Alves77b6f4f2023-03-15 11:34:49 +0000444 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100445 }
446
Karl Meakin6291eb22024-11-18 12:43:47 +0000447 enum manifest_return_code ffa_manifest_from_spkg(
448 struct_manifest **m, Partition_package *spkg)
449 {
450 struct memiter it;
451 struct mm_stage1_locked mm_stage1_locked;
452 struct boot_params params;
453
454 boot_params_init(&params, spkg);
455
456 /* clang-format off */
457 std::vector<char> core_dtb = ManifestDtBuilder()
458 .StartChild("hypervisor")
459 .Compatible()
460 .StartChild("vm1")
461 .DebugName("primary_vm")
462 .FfaPartition()
463 .LoadAddress((uint64_t)spkg)
464 .EndChild()
465 .EndChild()
466 .Build(true);
467 /* clang-format on */
468 memiter_init(&it, core_dtb.data(), core_dtb.size());
469
470 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
471 }
472
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100473 enum manifest_return_code ffa_manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200474 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100475 {
476 struct memiter it;
477 struct mm_stage1_locked mm_stage1_locked;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100478 Partition_package spkg(vec);
J-Alves77b6f4f2023-03-15 11:34:49 +0000479 struct boot_params params;
480
481 boot_params_init(&params, &spkg);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100482
483 /* clang-format off */
484 std::vector<char> core_dtb = ManifestDtBuilder()
485 .StartChild("hypervisor")
486 .Compatible()
487 .StartChild("vm1")
488 .DebugName("primary_vm")
489 .FfaPartition()
490 .LoadAddress((uint64_t)&spkg)
491 .EndChild()
492 .EndChild()
493 .Build();
494 /* clang-format on */
495 memiter_init(&it, core_dtb.data(), core_dtb.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100496
J-Alves77b6f4f2023-03-15 11:34:49 +0000497 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100498 }
499};
500
501TEST_F(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100502{
Olivier Deprez93644652022-09-09 11:01:12 +0200503 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100504 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100505
David Brazdila2358d42020-01-27 18:51:38 +0000506 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100507 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
508}
509
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100510TEST_F(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100511{
Olivier Deprez93644652022-09-09 11:01:12 +0200512 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100513
David Brazdil52256ff2019-08-23 15:15:15 +0100514 /* clang-format off */
515 std::vector<char> dtb = ManifestDtBuilder()
516 .StartChild("hypervisor")
517 .EndChild()
518 .Build();
519 /* clang-format on */
520
David Brazdilf4925382020-03-25 13:33:51 +0000521 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100522}
523
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100524TEST_F(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100525{
Olivier Deprez93644652022-09-09 11:01:12 +0200526 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100527
David Brazdil52256ff2019-08-23 15:15:15 +0100528 /* clang-format off */
529 std::vector<char> dtb = ManifestDtBuilder()
530 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100531 .Compatible({ "foo,bar" })
532 .EndChild()
533 .Build();
534 /* clang-format on */
535
David Brazdila2358d42020-01-27 18:51:38 +0000536 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100537}
538
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100539TEST_F(manifest, compatible_one_of_many)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100540{
Olivier Deprez93644652022-09-09 11:01:12 +0200541 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100542
543 /* clang-format off */
544 std::vector<char> dtb = ManifestDtBuilder()
545 .StartChild("hypervisor")
546 .Compatible({ "foo,bar", "hafnium,hafnium" })
547 .StartChild("vm1")
548 .DebugName("primary")
549 .EndChild()
550 .EndChild()
551 .Build();
552 /* clang-format on */
553
David Brazdila2358d42020-01-27 18:51:38 +0000554 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100555}
556
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100557TEST_F(manifest, no_vm_nodes)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100558{
Olivier Deprez93644652022-09-09 11:01:12 +0200559 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100560
561 /* clang-format off */
562 std::vector<char> dtb = ManifestDtBuilder()
563 .StartChild("hypervisor")
564 .Compatible()
565 .EndChild()
566 .Build();
567 /* clang-format on */
568
David Brazdila2358d42020-01-27 18:51:38 +0000569 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100570}
571
572static std::vector<char> gen_long_string_dtb(bool valid)
573{
574 const char last_valid[] = "1234567890123456789012345678901";
575 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100576 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
577 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100578
579 /* clang-format off */
580 return ManifestDtBuilder()
581 .StartChild("hypervisor")
582 .Compatible()
583 .StartChild("vm1")
584 .DebugName(valid ? last_valid : first_invalid)
585 .EndChild()
586 .EndChild()
587 .Build();
588 /* clang-format on */
589}
590
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100591TEST_F(manifest, long_string)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100592{
Olivier Deprez93644652022-09-09 11:01:12 +0200593 struct_manifest *m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100594 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
595 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
596
David Brazdila2358d42020-01-27 18:51:38 +0000597 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200598 manifest_dealloc();
599
David Brazdila2358d42020-01-27 18:51:38 +0000600 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
601 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100602}
603
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100604TEST_F(manifest, reserved_vm_id)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100605{
Olivier Deprez93644652022-09-09 11:01:12 +0200606 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100607
608 /* clang-format off */
609 std::vector<char> dtb = ManifestDtBuilder()
610 .StartChild("hypervisor")
611 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100612 .StartChild("vm1")
613 .DebugName("primary_vm")
614 .EndChild()
615 .StartChild("vm0")
616 .DebugName("reserved_vm")
617 .VcpuCount(1)
618 .MemSize(0x1000)
619 .KernelFilename("kernel")
620 .EndChild()
621 .EndChild()
622 .Build();
623 /* clang-format on */
624
David Brazdila2358d42020-01-27 18:51:38 +0000625 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100626}
627
Andrew Scullae9962e2019-10-03 16:51:16 +0100628static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100629{
630 /* clang-format off */
631 return ManifestDtBuilder()
632 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100633 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100634 .StartChild("vm1")
635 .DebugName("primary_vm")
636 .EndChild()
637 .StartChild("vm2")
638 .DebugName("secondary_vm")
639 .VcpuCount(vcpu_count)
640 .MemSize(0x1000)
641 .KernelFilename("kernel")
642 .EndChild()
643 .EndChild()
644 .Build();
645 /* clang-format on */
646}
David Brazdil7a462ec2019-08-15 12:27:47 +0100647
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100648TEST_F(manifest, vcpu_count_limit)
David Brazdil7a462ec2019-08-15 12:27:47 +0100649{
Olivier Deprez93644652022-09-09 11:01:12 +0200650 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100651 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
652 std::vector<char> dtb_first_invalid =
653 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100654
David Brazdila2358d42020-01-27 18:51:38 +0000655 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200656 ASSERT_EQ(m->vm_count, 2);
657 ASSERT_EQ(m->vm[1].secondary.vcpu_count, UINT16_MAX);
658 manifest_dealloc();
David Brazdil7a462ec2019-08-15 12:27:47 +0100659
David Brazdila2358d42020-01-27 18:51:38 +0000660 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100661 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100662}
663
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100664TEST_F(manifest, no_ramdisk_primary)
David Brazdile6f83222019-09-23 14:47:37 +0100665{
Olivier Deprez93644652022-09-09 11:01:12 +0200666 struct_manifest *m;
David Brazdile6f83222019-09-23 14:47:37 +0100667
668 /* clang-format off */
669 std::vector<char> dtb = ManifestDtBuilder()
670 .StartChild("hypervisor")
671 .Compatible()
672 .StartChild("vm1")
673 .DebugName("primary_vm")
674 .EndChild()
675 .EndChild()
676 .Build();
677 /* clang-format on */
678
David Brazdila2358d42020-01-27 18:51:38 +0000679 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200680 ASSERT_EQ(m->vm_count, 1);
681 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
682 ASSERT_STREQ(string_data(&m->vm[0].primary.ramdisk_filename), "");
David Brazdile6f83222019-09-23 14:47:37 +0100683}
684
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100685TEST_F(manifest, no_boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800686{
Olivier Deprez93644652022-09-09 11:01:12 +0200687 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800688
689 /* clang-format off */
690 std::vector<char> dtb = ManifestDtBuilder()
691 .StartChild("hypervisor")
692 .Compatible()
693 .StartChild("vm1")
694 .DebugName("primary_vm")
695 .EndChild()
696 .EndChild()
697 .Build();
698 /* clang-format on */
699
700 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200701 ASSERT_EQ(m->vm_count, 1);
702 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
703 ASSERT_EQ(m->vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
David Brazdil080ee312020-02-25 15:30:30 -0800704}
705
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100706TEST_F(manifest, boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800707{
Olivier Deprez93644652022-09-09 11:01:12 +0200708 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800709 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
710
711 /* clang-format off */
712 std::vector<char> dtb = ManifestDtBuilder()
713 .StartChild("hypervisor")
714 .Compatible()
715 .StartChild("vm1")
716 .DebugName("primary_vm")
717 .BootAddress(addr)
718 .EndChild()
719 .EndChild()
720 .Build();
721 /* clang-format on */
722
723 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200724 ASSERT_EQ(m->vm_count, 1);
725 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
726 ASSERT_EQ(m->vm[0].primary.boot_address, addr);
David Brazdil080ee312020-02-25 15:30:30 -0800727}
728
Andrew Scullb2c3a242019-11-04 13:52:36 +0000729static std::vector<char> gen_malformed_boolean_dtb(
730 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100731{
Andrew Scullae9962e2019-10-03 16:51:16 +0100732 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000733 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100734 .StartChild("hypervisor")
735 .Compatible()
736 .StartChild("vm1")
737 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000738 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000739 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100740 .EndChild()
741 .Build();
742 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000743}
Andrew Scullae9962e2019-10-03 16:51:16 +0100744
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100745TEST_F(manifest, malformed_booleans)
Andrew Scullb2c3a242019-11-04 13:52:36 +0000746{
Olivier Deprez93644652022-09-09 11:01:12 +0200747 struct_manifest *m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100748
Andrew Scullb2c3a242019-11-04 13:52:36 +0000749 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
750 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
751 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
752 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100753
David Brazdila2358d42020-01-27 18:51:38 +0000754 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000755 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200756 manifest_dealloc();
757
David Brazdila2358d42020-01-27 18:51:38 +0000758 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000759 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200760 manifest_dealloc();
761
David Brazdila2358d42020-01-27 18:51:38 +0000762 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000763 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200764 manifest_dealloc();
765
David Brazdila2358d42020-01-27 18:51:38 +0000766 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000767 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100768}
769
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100770TEST_F(manifest, valid)
David Brazdil7a462ec2019-08-15 12:27:47 +0100771{
Olivier Deprez93644652022-09-09 11:01:12 +0200772 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100773 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100774
David Brazdil52256ff2019-08-23 15:15:15 +0100775 /* clang-format off */
776 std::vector<char> dtb = ManifestDtBuilder()
777 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100778 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100779 .StartChild("vm1")
780 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100781 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100782 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100783 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100784 .EndChild()
785 .StartChild("vm3")
786 .DebugName("second_secondary_vm")
787 .VcpuCount(43)
788 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100789 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100790 .EndChild()
791 .StartChild("vm2")
792 .DebugName("first_secondary_vm")
793 .VcpuCount(42)
794 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100795 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
796 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100797 .EndChild()
798 .EndChild()
799 .Build();
800 /* clang-format on */
801
David Brazdila2358d42020-01-27 18:51:38 +0000802 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200803 ASSERT_EQ(m->vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100804
Olivier Deprez93644652022-09-09 11:01:12 +0200805 vm = &m->vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100806 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
807 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100808 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
809 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100810 ASSERT_THAT(
811 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
812 ElementsAre(0x32000000, 0x33001111));
813 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100814
Olivier Deprez93644652022-09-09 11:01:12 +0200815 vm = &m->vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100816 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
817 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100818 ASSERT_EQ(vm->secondary.vcpu_count, 42);
819 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100820 ASSERT_THAT(
821 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
822 ElementsAre(0x04000000, 0x30002222, 0x31445566));
823 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100824
Olivier Deprez93644652022-09-09 11:01:12 +0200825 vm = &m->vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100826 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
827 ASSERT_STREQ(string_data(&vm->kernel_filename),
828 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100829 ASSERT_EQ(vm->secondary.vcpu_count, 43);
830 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100831 ASSERT_THAT(
832 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
833 IsEmpty());
834 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100835}
836
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100837TEST_F(manifest, ffa_not_compatible)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100838{
Olivier Deprez93644652022-09-09 11:01:12 +0200839 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100840
841 /* clang-format off */
842 std::vector<char> dtb = ManifestDtBuilder()
843 .Compatible({ "arm,ffa-manifest-2.0" })
844 .Property("ffa-version", "<0x10000>")
845 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
846 .Property("execution-ctx-count", "<1>")
847 .Property("exception-level", "<2>")
848 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000849 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100850 .Property("xlat-granule", "<0>")
851 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500852 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100853 .Build();
854 /* clang-format on */
855
856 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
857 MANIFEST_ERROR_NOT_COMPATIBLE);
858}
859
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100860TEST_F(manifest, ffa_missing_property)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100861{
Olivier Deprez93644652022-09-09 11:01:12 +0200862 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100863
864 /* clang-format off */
865 std::vector<char> dtb = ManifestDtBuilder()
866 .Compatible({ "arm,ffa-manifest-1.0" })
867 .Property("ffa-version", "<0x10000>")
868 .Build();
869 /* clang-format on */
870
871 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
872 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
873}
874
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100875TEST_F(manifest, ffa_validate_sanity_check)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100876{
J-Alvesb37fd082020-10-22 12:29:21 +0100877 /*
878 * TODO: write test excluding all optional fields of the manifest, in
879 * accordance with specification.
880 */
Olivier Deprez93644652022-09-09 11:01:12 +0200881 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100882
883 /* Incompatible version */
884 /* clang-format off */
885 std::vector<char> dtb = ManifestDtBuilder()
886 .Compatible({ "arm,ffa-manifest-1.0" })
887 .Property("ffa-version", "<0xa1>")
888 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
889 .Property("execution-ctx-count", "<1>")
890 .Property("exception-level", "<2>")
891 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000892 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100893 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100894 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100895 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500896 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100897 .Build();
898 /* clang-format on */
899 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
900 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200901 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100902
903 /* Incompatible translation granule */
904 /* clang-format off */
905 dtb = ManifestDtBuilder()
906 .Compatible({ "arm,ffa-manifest-1.0" })
907 .Property("ffa-version", "<0x10000>")
908 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
909 .Property("execution-ctx-count", "<1>")
910 .Property("exception-level", "<2>")
911 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000912 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100913 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100914 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100915 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500916 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100917 .Build();
918 /* clang-format on */
919 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
920 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200921 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100922
923 /* Incompatible exeption level */
924 /* clang-format off */
925 dtb = ManifestDtBuilder()
926 .Compatible({ "arm,ffa-manifest-1.0" })
927 .Property("ffa-version", "<0x10000>")
928 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
929 .Property("execution-ctx-count", "<1>")
Daniel Boulby874d5432023-04-27 12:40:24 +0100930 .Property("exception-level", "<10>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100931 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000932 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100933 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100934 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100935 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500936 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100937 .Build();
938 /* clang-format on */
939 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
940 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200941 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100942
943 /* Incompatible execution state */
944 /* clang-format off */
945 dtb = ManifestDtBuilder()
946 .Compatible({ "arm,ffa-manifest-1.0" })
947 .Property("ffa-version", "<0x10000>")
948 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
949 .Property("execution-ctx-count", "<1>")
950 .Property("exception-level", "<2>")
951 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000952 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100953 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100954 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100955 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500956 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100957 .Build();
958 /* clang-format on */
959 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
960 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200961 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100962
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400963 /* Incompatible messaging method - unrecognized messaging-method. */
964 /* clang-format off */
965 dtb = ManifestDtBuilder()
966 .Compatible({ "arm,ffa-manifest-1.0" })
967 .Property("ffa-version", "<0x10002>")
968 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
969 .Property("execution-ctx-count", "<1>")
970 .Property("exception-level", "<2>")
971 .Property("execution-state", "<0>")
972 .Property("entrypoint-offset", "<0x00002000>")
973 .Property("xlat-granule", "<0>")
974 .Property("boot-order", "<0>")
975 .Property("messaging-method", "<0x272>")
976 .Property("ns-interrupts-action", "<0>")
977 .Build();
978 /* clang-format on */
979 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
980 MANIFEST_ERROR_NOT_COMPATIBLE);
981 manifest_dealloc();
982
983 /* Incompatible messaging method - only endpoints using FF-A version >=
984 * FF-A v1.2 are allowed to set FFA_PARTITION_DIRECT_REQ2_RECV and
985 * FFA_PARTITION_DIRECT_REQ2_SEND. */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100986 /* clang-format off */
987 dtb = ManifestDtBuilder()
988 .Compatible({ "arm,ffa-manifest-1.0" })
989 .Property("ffa-version", "<0x10000>")
990 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
991 .Property("execution-ctx-count", "<1>")
992 .Property("exception-level", "<2>")
993 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000994 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100995 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100996 .Property("boot-order", "<0>")
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400997 .Property("messaging-method", "<0x204>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500998 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100999 .Build();
1000 /* clang-format on */
1001 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1002 MANIFEST_ERROR_NOT_COMPATIBLE);
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001003
1004 /*
1005 * No need to invoke manifest_dealloac() since manifest TearDown calls
1006 * it when the test ends.
1007 */
1008}
1009
1010TEST_F(manifest, ffa_validate_interrupt_actions)
1011{
1012 struct_manifest *m;
Madhukar Pappireddy84154052022-06-21 18:30:25 -05001013
1014 /* Incompatible NS interrupt action */
1015 /* clang-format off */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001016 std::vector<char> dtb = ManifestDtBuilder()
Madhukar Pappireddy84154052022-06-21 18:30:25 -05001017 .Compatible({ "arm,ffa-manifest-1.0" })
1018 .Property("ffa-version", "<0x10000>")
1019 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1020 .Property("execution-ctx-count", "<1>")
1021 .Property("exception-level", "<2>")
1022 .Property("execution-state", "<0>")
1023 .Property("entrypoint-offset", "<0x00002000>")
1024 .Property("xlat-granule", "<0>")
1025 .Property("boot-order", "<0>")
1026 .Property("messaging-method", "<1>")
1027 .Property("ns-interrupts-action", "<4>")
1028 .Build();
1029 /* clang-format on */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001030 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1031 MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
Madhukar Pappireddyee736ad2022-12-28 11:37:09 -06001032 manifest_dealloc();
1033
1034 /* Incompatible other-s-interrupts-action for S-EL1 partition */
1035 /* clang-format off */
1036 dtb = ManifestDtBuilder()
1037 .Compatible({ "arm,ffa-manifest-1.0" })
1038 .Property("ffa-version", "<0x10000>")
1039 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1040 .Property("execution-ctx-count", "<1>")
1041 .Property("exception-level", "<2>")
1042 .Property("execution-state", "<0>")
1043 .Property("entrypoint-offset", "<0x00002000>")
1044 .Property("xlat-granule", "<0>")
1045 .Property("boot-order", "<0>")
1046 .Property("messaging-method", "<1>")
1047 .Property("ns-interrupts-action", "<1>")
1048 .Property("other-s-interrupts-action", "<0>")
1049 .Build();
1050 /* clang-format on */
1051 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1052 MANIFEST_ERROR_NOT_COMPATIBLE);
1053 manifest_dealloc();
1054
1055 /*
1056 * Incompatible choice of the fields ns-interrupts-action and
1057 * other-s-interrupts-action.
1058 */
1059 /* clang-format off */
1060 dtb = ManifestDtBuilder()
1061 .Compatible({ "arm,ffa-manifest-1.0" })
1062 .Property("ffa-version", "<0x10000>")
1063 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1064 .Property("execution-ctx-count", "<1>")
1065 .Property("exception-level", "<1>")
1066 .Property("execution-state", "<0>")
1067 .Property("entrypoint-offset", "<0x00002000>")
1068 .Property("xlat-granule", "<0>")
1069 .Property("boot-order", "<0>")
1070 .Property("messaging-method", "<1>")
1071 .Property("ns-interrupts-action", "<2>")
1072 .Property("other-s-interrupts-action", "<0>")
1073 .Build();
1074 /* clang-format on */
1075 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1076 MANIFEST_ERROR_NOT_COMPATIBLE);
1077 manifest_dealloc();
1078
1079 /* Illegal value specified for the field other-s-interrupts-action. */
1080 /* clang-format off */
1081 dtb = ManifestDtBuilder()
1082 .Compatible({ "arm,ffa-manifest-1.0" })
1083 .Property("ffa-version", "<0x10000>")
1084 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1085 .Property("execution-ctx-count", "<1>")
1086 .Property("exception-level", "<1>")
1087 .Property("execution-state", "<0>")
1088 .Property("entrypoint-offset", "<0x00002000>")
1089 .Property("xlat-granule", "<0>")
1090 .Property("boot-order", "<0>")
1091 .Property("messaging-method", "<1>")
1092 .Property("other-s-interrupts-action", "<2>")
1093 .Build();
1094 /* clang-format on */
1095 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1096 MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001097}
1098
Karl Meakin18694022024-08-02 13:59:25 +01001099TEST_F(manifest, vm_availability_messages)
1100{
1101 struct manifest_vm *vm;
1102 struct_manifest *m;
1103 std::vector<char> dtb;
1104
1105 /* clang-format off */
1106 dtb = ManifestDtBuilder()
1107 .Compatible({ "arm,ffa-manifest-1.0" })
1108 .Property("ffa-version", "<0x10001>")
1109 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1110 .Property("execution-ctx-count", "<8>")
1111 .Property("exception-level", "<2>")
1112 .Property("execution-state", "<0>")
1113 .Property("entrypoint-offset", "<0x00002000>")
1114 .Property("messaging-method", "<1>")
1115 .Property("vm-availability-messages", "<0>")
1116 .Build();
1117 /* clang-format on */
1118 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1119 vm = &m->vm[0];
1120 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1121 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1122 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1123 manifest_dealloc();
1124
1125 /* clang-format off */
1126 dtb = ManifestDtBuilder()
1127 .Compatible({ "arm,ffa-manifest-1.0" })
1128 .Property("ffa-version", "<0x10001>")
1129 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1130 .Property("execution-ctx-count", "<8>")
1131 .Property("exception-level", "<2>")
1132 .Property("execution-state", "<0>")
1133 .Property("entrypoint-offset", "<0x00002000>")
1134 .Property("messaging-method", "<1>")
1135 .Property("vm-availability-messages", "<1>")
1136 .Build();
1137 /* clang-format on */
1138 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1139 vm = &m->vm[0];
1140 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1141 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1142 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1143 manifest_dealloc();
1144
1145 /* clang-format off */
1146 dtb = ManifestDtBuilder()
1147 .Compatible({ "arm,ffa-manifest-1.0" })
1148 .Property("ffa-version", "<0x10001>")
1149 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1150 .Property("execution-ctx-count", "<8>")
1151 .Property("exception-level", "<2>")
1152 .Property("execution-state", "<0>")
1153 .Property("entrypoint-offset", "<0x00002000>")
1154 .Property("messaging-method", "<1>")
1155 .Property("vm-availability-messages", "<2>")
1156 .Build();
1157 /* clang-format on */
1158 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1159 vm = &m->vm[0];
1160 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1161 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1162 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1163 manifest_dealloc();
1164
1165 /* clang-format off */
1166 dtb = ManifestDtBuilder()
1167 .Compatible({ "arm,ffa-manifest-1.0" })
1168 .Property("ffa-version", "<0x10001>")
1169 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1170 .Property("execution-ctx-count", "<8>")
1171 .Property("exception-level", "<2>")
1172 .Property("execution-state", "<0>")
1173 .Property("entrypoint-offset", "<0x00002000>")
1174 .Property("messaging-method", "<1>")
1175 .Property("vm-availability-messages", "<3>")
1176 .Build();
1177 /* clang-format on */
1178 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1179 vm = &m->vm[0];
1180 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1181 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1182 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1183 manifest_dealloc();
1184
1185 /* clang-format off */
1186 dtb = ManifestDtBuilder()
1187 .Compatible({ "arm,ffa-manifest-1.0" })
1188 .Property("ffa-version", "<0x10001>")
1189 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1190 .Property("execution-ctx-count", "<8>")
1191 .Property("exception-level", "<2>")
1192 .Property("execution-state", "<0>")
1193 .Property("entrypoint-offset", "<0x00002000>")
1194 .Property("messaging-method", "<1>")
1195 .Build();
1196 /* clang-format on */
1197 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1198 vm = &m->vm[0];
1199 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1200 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1201 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1202 manifest_dealloc();
1203
1204 /* clang-format off */
1205 dtb = ManifestDtBuilder()
1206 .Compatible({ "arm,ffa-manifest-1.0" })
1207 .Property("ffa-version", "<0x10001>")
1208 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1209 .Property("execution-ctx-count", "<8>")
1210 .Property("exception-level", "<2>")
1211 .Property("execution-state", "<0>")
1212 .Property("entrypoint-offset", "<0x00002000>")
1213 .Property("messaging-method", "<2>")
1214 .Property("vm-availability-messages", "<4>")
1215 .Build();
1216 /* clang-format on */
1217 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1218 MANIFEST_ERROR_VM_AVAILABILITY_MESSAGE_INVALID);
1219 vm = &m->vm[0];
1220 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1221 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1222 ASSERT_NE(vm->partition.vm_availability_messages.mbz, 0);
1223 manifest_dealloc();
1224}
1225
Olivier Depreza15f2352022-09-26 09:17:24 +02001226TEST_F(manifest, power_management)
1227{
1228 struct manifest_vm *vm;
1229 struct_manifest *m;
1230
Madhukar Pappireddy958c8412024-11-25 09:54:17 -06001231 /* S-EL1 partition power management field can only set bit 0. */
Olivier Depreza15f2352022-09-26 09:17:24 +02001232 /* clang-format off */
1233 std::vector<char> dtb = ManifestDtBuilder()
1234 .Compatible({ "arm,ffa-manifest-1.0" })
1235 .Property("ffa-version", "<0x10001>")
1236 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1237 .Property("execution-ctx-count", "<8>")
1238 .Property("exception-level", "<2>")
1239 .Property("execution-state", "<0>")
1240 .Property("entrypoint-offset", "<0x00002000>")
1241 .Property("messaging-method", "<1>")
Olivier Depreza15f2352022-09-26 09:17:24 +02001242 .Property("power-management-messages", "<0xf>")
1243 .Build();
1244 /* clang-format on */
1245 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1246 vm = &m->vm[0];
Madhukar Pappireddy958c8412024-11-25 09:54:17 -06001247 ASSERT_EQ(vm->partition.power_management, 1);
Olivier Depreza15f2352022-09-26 09:17:24 +02001248 manifest_dealloc();
1249
1250 /* S-EL0 partition power management field is forced to 0. */
1251 /* clang-format off */
1252 dtb = ManifestDtBuilder()
1253 .Compatible({ "arm,ffa-manifest-1.0" })
1254 .Property("ffa-version", "<0x10001>")
1255 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1256 .Property("execution-ctx-count", "<1>")
1257 .Property("exception-level", "<1>")
1258 .Property("execution-state", "<0>")
1259 .Property("entrypoint-offset", "<0x00002000>")
1260 .Property("messaging-method", "<1>")
1261 .Property("power-management-messages", "<0xff>")
1262 .Build();
1263 /* clang-format on */
1264 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1265 vm = &m->vm[0];
1266 ASSERT_EQ(vm->partition.power_management, 0);
1267}
1268
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001269TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001270{
Olivier Deprez93644652022-09-09 11:01:12 +02001271 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001272
1273 /* Not Compatible */
1274 /* clang-format off */
1275 std::vector<char> dtb = ManifestDtBuilder()
1276 .FfaValidManifest()
1277 .StartChild("rx_tx-info")
1278 .Compatible({ "foo,bar" })
1279 .EndChild()
1280 .Build();
1281 /* clang-format on */
1282 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1283 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001284 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001285
1286 /* Missing Properties */
1287 /* clang-format off */
1288 dtb = ManifestDtBuilder()
1289 .FfaValidManifest()
1290 .StartChild("rx_tx-info")
1291 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1292 .EndChild()
1293 .Build();
1294 /* clang-format on */
1295 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1296 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1297}
1298
Karl Meakinf955dbe2024-11-18 16:38:58 +00001299TEST_F(manifest, ffa_validate_mem_regions_not_compatible)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001300{
Olivier Deprez93644652022-09-09 11:01:12 +02001301 struct_manifest *m;
Karl Meakinf955dbe2024-11-18 16:38:58 +00001302 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001303
1304 /* Not Compatible */
1305 /* clang-format off */
Karl Meakinf955dbe2024-11-18 16:38:58 +00001306 dtb = ManifestDtBuilder()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001307 .FfaValidManifest()
1308 .StartChild("memory-regions")
1309 .Compatible({ "foo,bar" })
1310 .EndChild()
1311 .Build();
1312 /* clang-format on */
1313 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1314 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001315 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001316}
1317
1318TEST_F(manifest, ffa_validate_mem_regions_unavailable)
1319{
1320 struct_manifest *m;
1321 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001322
1323 /* Memory regions unavailable */
1324 /* clang-format off */
1325 dtb = ManifestDtBuilder()
1326 .FfaValidManifest()
1327 .StartChild("memory-regions")
1328 .Compatible({ "arm,ffa-manifest-memory-regions" })
1329 .EndChild()
1330 .Build();
1331 /* clang-format on */
1332 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1333 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001334 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001335}
1336
1337TEST_F(manifest, ffa_validate_mem_regions_missing_properties)
1338{
1339 struct_manifest *m;
1340 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001341
1342 /* Missing Properties */
1343 /* clang-format off */
1344 dtb = ManifestDtBuilder()
1345 .FfaValidManifest()
1346 .StartChild("memory-regions")
1347 .Compatible({ "arm,ffa-manifest-memory-regions" })
1348 .StartChild("test-memory")
1349 .Description("test-memory")
1350 .EndChild()
1351 .EndChild()
1352 .Build();
1353 /* clang-format on */
1354 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1355 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001356 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001357}
1358
1359TEST_F(manifest, ffa_validate_mem_regions_empty_region)
1360{
1361 struct_manifest *m;
1362 std::vector<char> dtb;
Manish Pandeyf06c9072020-09-29 15:41:58 +01001363
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001364 /* Empty memory region */
1365 /* clang-format off */
1366 dtb = ManifestDtBuilder()
1367 .FfaValidManifest()
1368 .StartChild("memory-regions")
1369 .Compatible({ "arm,ffa-manifest-memory-regions" })
1370 .Label("rx")
1371 .StartChild("rx")
1372 .Description("rx-buffer")
1373 .Property("base-address", "<0x7300000>")
1374 .Property("pages-count", "<0>")
1375 .Property("attributes", "<1>")
1376 .EndChild()
1377 .Label("tx")
1378 .StartChild("tx")
1379 .Description("tx-buffer")
1380 .Property("base-address", "<0x7310000>")
1381 .Property("pages-count", "<2>")
1382 .Property("attributes", "<3>")
1383 .EndChild()
1384 .EndChild()
1385 .StartChild("rx_tx-info")
1386 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1387 .Property("rx-buffer", "<&rx>")
1388 .Property("tx-buffer", "<&tx>")
1389 .EndChild()
1390 .Build();
1391 /* clang-format on */
1392 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1393 MANIFEST_ERROR_MEM_REGION_EMPTY);
1394 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001395}
1396
1397TEST_F(manifest, ffa_validate_mem_regions_base_address_and_relative_offset)
1398{
1399 struct_manifest *m;
1400 std::vector<char> dtb;
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001401
Davidson K8ccd2d02024-09-03 16:10:54 +05301402 /* Mutually exclusive base-address and load-address-relative-offset
1403 * properties */
Karl Meakine92efbe2023-06-01 14:16:22 +01001404 /* clang-format off */
1405 dtb = ManifestDtBuilder()
1406 .FfaValidManifest()
1407 .StartChild("memory-regions")
1408 .Compatible({ "arm,ffa-manifest-memory-regions" })
1409 .Label("rx")
1410 .StartChild("rx")
1411 .Description("rx-buffer")
1412 .Property("base-address", "<0x7300000>")
Davidson K8ccd2d02024-09-03 16:10:54 +05301413 .Property("load-address-relative-offset", "<0x7300000>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001414 .Property("pages-count", "<1>")
1415 .Property("attributes", "<1>")
1416 .EndChild()
1417 .EndChild()
1418 .Build();
1419 /* clang-format on */
1420 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1421 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1422 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001423}
1424
1425TEST_F(manifest, ffa_validate_mem_regions_relative_address_overflow)
1426{
1427 struct_manifest *m;
1428 std::vector<char> dtb;
1429
Karl Meakine92efbe2023-06-01 14:16:22 +01001430 /* Relative-address overflow*/
1431 /* clang-format off */
1432 dtb = ManifestDtBuilder()
1433 .FfaValidManifest()
1434 .Property("load-address", "<0xffffff00 0xffffff00>")
1435 .StartChild("memory-regions")
1436 .Compatible({ "arm,ffa-manifest-memory-regions" })
1437 .Label("rx")
1438 .StartChild("rx")
1439 .Description("rx-buffer")
Davidson K8ccd2d02024-09-03 16:10:54 +05301440 .Property("load-address-relative-offset", "<0xffffff00 0xffffff00>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001441 .Property("pages-count", "<1>")
1442 .Property("attributes", "<1>")
1443 .EndChild()
1444 .EndChild()
1445 .Build();
1446 /* clang-format on */
1447 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1448 MANIFEST_ERROR_INTEGER_OVERFLOW);
1449 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001450}
1451
1452TEST_F(manifest, ffa_validate_mem_regions_relative_offset_valid)
1453{
1454 struct_manifest *m;
1455 std::vector<char> dtb;
1456
1457 /* valid relative offset */
1458 /* clang-format off */
1459 dtb = ManifestDtBuilder()
1460 .FfaValidManifest()
1461 .Property("load-address", "<0xffffff00 0xffffff00>")
1462 .StartChild("memory-regions")
1463 .Compatible({ "arm,ffa-manifest-memory-regions" })
1464 .Label("rx")
1465 .StartChild("rx")
1466 .Description("rx-buffer")
1467 .Property("load-address-relative-offset", "<0x1000>")
1468 .Property("pages-count", "<1>")
1469 .Property("attributes", "<1>")
1470 .EndChild()
1471 .EndChild()
1472 .Build();
1473 /* clang-format on */
1474 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1475 manifest_dealloc();
1476}
1477
1478TEST_F(manifest, ffa_validate_mem_regions_overlapping)
1479{
1480 struct_manifest *m;
1481 std::vector<char> dtb;
Karl Meakine92efbe2023-06-01 14:16:22 +01001482
Daniel Boulby9279b552022-06-28 17:04:01 +01001483 /* Overlapping memory regions */
1484 /* clang-format off */
1485 dtb = ManifestDtBuilder()
1486 .FfaValidManifest()
1487 .StartChild("memory-regions")
1488 .Compatible({ "arm,ffa-manifest-memory-regions" })
1489 .Label("rx")
1490 .StartChild("rx")
1491 .Description("rx-buffer")
1492 .Property("base-address", "<0x7300000>")
1493 .Property("pages-count", "<1>")
1494 .Property("attributes", "<1>")
1495 .EndChild()
1496 .Label("tx")
1497 .StartChild("tx")
1498 .Description("tx-buffer")
1499 .Property("base-address", "<0x7300000>")
1500 .Property("pages-count", "<2>")
1501 .Property("attributes", "<3>")
1502 .EndChild()
1503 .EndChild()
1504 .Build();
1505 /* clang-format on */
1506 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1507 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001508 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001509
1510 /* clang-format off */
1511 dtb = ManifestDtBuilder()
1512 .FfaValidManifest()
1513 .StartChild("memory-regions")
1514 .Compatible({ "arm,ffa-manifest-memory-regions" })
1515 .Label("rx")
1516 .StartChild("rx")
1517 .Description("rx-buffer")
Karl Meakin6291eb22024-11-18 12:43:47 +00001518 .Property("load-address-relative-offset", "<0x0>")
1519 .Property("pages-count", "<1>")
1520 .Property("attributes", "<1>")
1521 .EndChild()
1522 .Label("tx")
1523 .StartChild("tx")
1524 .Description("tx-buffer")
1525 .Property("load-address-relative-offset", "<0x0>")
1526 .Property("pages-count", "<2>")
1527 .Property("attributes", "<3>")
1528 .EndChild()
1529 .EndChild()
1530 .Build();
1531 /* clang-format on */
1532 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1533 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1534 manifest_dealloc();
1535
1536 /* clang-format off */
1537 dtb = ManifestDtBuilder()
1538 .FfaValidManifest()
1539 .StartChild("memory-regions")
1540 .Compatible({ "arm,ffa-manifest-memory-regions" })
1541 .Label("rx")
1542 .StartChild("rx")
1543 .Description("rx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001544 .Property("base-address", "<0x7300000>")
1545 .Property("pages-count", "<2>")
1546 .Property("attributes", "<1>")
1547 .EndChild()
1548 .Label("tx")
1549 .StartChild("tx")
1550 .Description("tx-buffer")
1551 .Property("base-address", "<0x7301000>")
1552 .Property("pages-count", "<2>")
1553 .Property("attributes", "<3>")
1554 .EndChild()
1555 .EndChild()
1556 .Build();
1557 /* clang-format on */
1558 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1559 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001560 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001561
1562 /* clang-format off */
1563 dtb = ManifestDtBuilder()
1564 .FfaValidManifest()
1565 .StartChild("memory-regions")
1566 .Compatible({ "arm,ffa-manifest-memory-regions" })
1567 .Label("rx")
1568 .StartChild("rx")
1569 .Description("rx-buffer")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001570 .Property("base-address", "<0x7301000>")
1571 .Property("pages-count", "<1>")
1572 .Property("attributes", "<1>")
1573 .EndChild()
1574 .Label("tx")
1575 .StartChild("tx")
1576 .Description("tx-buffer")
1577 .Property("base-address", "<0x7300000>")
1578 .Property("pages-count", "<2>")
1579 .Property("attributes", "<3>")
1580 .EndChild()
1581 .EndChild()
1582 .Build();
1583 /* clang-format on */
1584 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1585 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001586 manifest_dealloc();
Karl Meakin6291eb22024-11-18 12:43:47 +00001587
1588 /* clang-format off */
1589 Partition_package spkg(dtb);
1590 dtb = ManifestDtBuilder()
1591 .FfaValidManifest()
1592 .StartChild("memory-regions")
1593 .Compatible({ "arm,ffa-manifest-memory-regions" })
1594 .StartChild("test-memory")
1595 .Description("test-memory")
1596 .Integer64Property("base-address", (uint64_t)&spkg,true)
1597 .Property("pages-count", "<1>")
1598 .Property("attributes", "<1>")
1599 .EndChild()
1600 .EndChild()
1601 .Build(true);
1602 /* clang-format on */
1603 spkg.init(dtb);
1604 ASSERT_EQ(ffa_manifest_from_spkg(&m, &spkg),
1605 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1606 manifest_dealloc();
1607}
1608
1609TEST_F(manifest, ffa_validate_mem_regions_overlapping_allowed)
1610{
1611 struct_manifest *m;
1612 std::vector<char> dtb;
1613
1614 /*
1615 * Mem regions are allowed to overlap with parent `load-address` if the
1616 * `load-address-relative-offset` was specified.
1617 */
1618 /* clang-format off */
1619 dtb = ManifestDtBuilder()
1620 .FfaValidManifest()
1621 .StartChild("memory-regions")
1622 .Compatible({ "arm,ffa-manifest-memory-regions" })
1623 .Label("rx")
1624 .StartChild("rx")
1625 .Description("rx-buffer")
1626 .Property("load-address-relative-offset", "<0x1000>")
1627 .Property("pages-count", "<1>")
1628 .Property("attributes", "<1>")
1629 .EndChild()
1630 .Label("tx")
1631 .StartChild("tx")
1632 .Description("tx-buffer")
1633 .Property("base-address", "<0x7300000>")
1634 .Property("pages-count", "<2>")
1635 .Property("attributes", "<3>")
1636 .EndChild()
1637 .EndChild()
1638 .Build();
1639 /* clang-format on */
1640 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1641 ASSERT_EQ(m->vm[0].partition.mem_regions[0].is_relative, true);
1642 ASSERT_EQ(m->vm[0].partition.mem_regions[0].base_address,
1643 m->vm[0].partition.load_addr + 0x1000);
1644 manifest_dealloc();
1645
1646 /* clang-format off */
1647 dtb = ManifestDtBuilder()
1648 .FfaValidManifest()
1649 .StartChild("memory-regions")
1650 .Compatible({ "arm,ffa-manifest-memory-regions" })
1651 .Label("rx")
1652 .StartChild("rx")
1653 .Description("rx-buffer")
1654 .Property("base-address", "<0x7300000>")
1655 .Property("pages-count", "<1>")
1656 .Property("attributes", "<1>")
1657 .EndChild()
1658 .Label("tx")
1659 .StartChild("tx")
1660 .Description("tx-buffer")
1661 .Property("load-address-relative-offset", "<0x1000>")
1662 .Property("pages-count", "<2>")
1663 .Property("attributes", "<3>")
1664 .EndChild()
1665 .EndChild()
1666 .Build();
1667 /* clang-format on */
1668 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1669 ASSERT_EQ(m->vm[0].partition.mem_regions[1].is_relative, true);
1670 ASSERT_EQ(m->vm[0].partition.mem_regions[1].base_address,
1671 m->vm[0].partition.load_addr + 0x1000);
1672 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001673}
1674
1675TEST_F(manifest, ffa_validate_mem_regions_unaligned)
1676{
1677 struct_manifest *m;
1678 std::vector<char> dtb;
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001679
1680 /* Unaligned memory region */
1681 /* clang-format off */
1682 dtb = ManifestDtBuilder()
1683 .FfaValidManifest()
1684 .StartChild("memory-regions")
1685 .Compatible({ "arm,ffa-manifest-memory-regions" })
1686 .Label("rx")
1687 .StartChild("rx")
1688 .Description("rx-buffer")
1689 .Property("base-address", "<0x7300FFF>")
1690 .Property("pages-count", "<2>")
1691 .Property("attributes", "<1>")
1692 .EndChild()
1693 .Label("tx")
1694 .StartChild("tx")
1695 .Description("tx-buffer")
1696 .Property("base-address", "<0x7303000>")
1697 .Property("pages-count", "<2>")
1698 .Property("attributes", "<3>")
1699 .EndChild()
1700 .EndChild()
1701 .Build();
1702 /* clang-format on */
1703 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1704 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1705 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001706}
1707
1708TEST_F(manifest, ffa_validate_mem_regions_different_rxtx_sizes)
1709{
1710 struct_manifest *m;
1711 std::vector<char> dtb;
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001712
Manish Pandeyf06c9072020-09-29 15:41:58 +01001713 /* Different RXTX buffer sizes */
1714 /* clang-format off */
1715 dtb = ManifestDtBuilder()
1716 .FfaValidManifest()
1717 .StartChild("memory-regions")
1718 .Compatible({ "arm,ffa-manifest-memory-regions" })
1719 .Label("rx")
1720 .StartChild("rx")
1721 .Description("rx-buffer")
1722 .Property("base-address", "<0x7300000>")
1723 .Property("pages-count", "<1>")
1724 .Property("attributes", "<1>")
1725 .EndChild()
1726 .Label("tx")
1727 .StartChild("tx")
1728 .Description("tx-buffer")
1729 .Property("base-address", "<0x7310000>")
1730 .Property("pages-count", "<2>")
1731 .Property("attributes", "<3>")
1732 .EndChild()
1733 .EndChild()
1734 .StartChild("rx_tx-info")
1735 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1736 .Property("rx-buffer", "<&rx>")
1737 .Property("tx-buffer", "<&tx>")
1738 .EndChild()
1739 .Build();
1740 /* clang-format on */
1741 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1742 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001743}
1744
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001745TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001746{
Olivier Deprez93644652022-09-09 11:01:12 +02001747 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001748
1749 /* Not Compatible */
1750 /* clang-format off */
1751 std::vector<char> dtb = ManifestDtBuilder()
1752 .FfaValidManifest()
1753 .StartChild("device-regions")
1754 .Compatible({ "foo,bar" })
1755 .EndChild()
1756 .Build();
1757 /* clang-format on */
1758 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1759 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001760 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001761
1762 /* Memory regions unavailable */
1763 /* clang-format off */
1764 dtb = ManifestDtBuilder()
1765 .FfaValidManifest()
1766 .StartChild("device-regions")
1767 .Compatible({ "arm,ffa-manifest-device-regions" })
1768 .EndChild()
1769 .Build();
1770 /* clang-format on */
1771 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1772 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001773 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001774
1775 /* Missing Properties */
1776 /* clang-format off */
1777 dtb = ManifestDtBuilder()
1778 .FfaValidManifest()
1779 .StartChild("device-regions")
1780 .Compatible({ "arm,ffa-manifest-device-regions" })
1781 .StartChild("test-device")
1782 .Description("test-device")
1783 .EndChild()
1784 .EndChild()
1785 .Build();
1786 /* clang-format on */
1787 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1788 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001789 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001790
1791 /* Malformed interrupt list pair */
1792 /* clang-format off */
1793 dtb = ManifestDtBuilder()
1794 .FfaValidManifest()
1795 .StartChild("device-regions")
1796 .Compatible({ "arm,ffa-manifest-device-regions" })
1797 .StartChild("test-device")
1798 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001799 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001800 .Property("pages-count", "<16>")
1801 .Property("attributes", "<3>")
1802 .Property("smmu-id", "<1>")
1803 .Property("stream-ids", "<0 1>")
1804 .Property("interrupts", "<2 3>, <4>")
1805 .EndChild()
1806 .EndChild()
1807 .Build();
1808 /* clang-format on */
1809 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1810 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001811 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001812
1813 /* Non-unique interrupt IDs */
1814 /* clang-format off */
1815 dtb = ManifestDtBuilder()
1816 .FfaValidManifest()
1817 .StartChild("device-regions")
1818 .Compatible({ "arm,ffa-manifest-device-regions" })
1819 .StartChild("test-device-0")
1820 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001821 .Property("base-address", "<0x24000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001822 .Property("pages-count", "<16>")
1823 .Property("attributes", "<3>")
1824 .Property("interrupts", "<2 3>")
1825 .EndChild()
1826 .StartChild("test-device-1")
1827 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001828 .Property("base-address", "<0x25000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001829 .Property("pages-count", "<16>")
1830 .Property("attributes", "<3>")
1831 .Property("interrupts", "<1 3>, <2 5> ")
1832 .EndChild()
1833 .EndChild()
1834 .Build();
Daniel Boulby941ef342023-11-21 13:47:15 +00001835
Daniel Boulby667334f2022-06-27 15:23:21 +01001836 /* clang-format on */
1837 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1838 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1839 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001840 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1841 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1842 3);
1843 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1844 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1845 3);
Daniel Boulby941ef342023-11-21 13:47:15 +00001846 manifest_dealloc();
1847
1848 /* Overlapping address space between two device region nodes. */
1849 /* clang-format off */
1850 dtb = ManifestDtBuilder()
1851 .FfaValidManifest()
1852 .StartChild("device-regions")
1853 .Compatible({"arm,ffa-manifest-device-regions"})
1854 .StartChild("test-device-0")
1855 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001856 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001857 .Property("pages-count", "<16>")
1858 .Property("attributes", "<3>")
1859 .EndChild()
1860 .StartChild("test-device-1")
1861 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001862 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001863 .Property("pages-count", "<16>")
1864 .Property("attributes", "<3>")
1865 .EndChild()
Daniel Boulby4339edc2024-02-21 14:59:00 +00001866 .EndChild()
Daniel Boulby941ef342023-11-21 13:47:15 +00001867 .Build();
1868
1869 /* clang-format on */
1870 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1871 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1872 manifest_dealloc();
1873
1874 /*
Daniel Boulby4339edc2024-02-21 14:59:00 +00001875 * Device regions cannot be defined outside of the regions specified in
1876 * the spmc.
Daniel Boulby941ef342023-11-21 13:47:15 +00001877 */
1878 /* clang-format off */
1879 dtb = ManifestDtBuilder()
1880 .FfaValidManifest()
Daniel Boulby941ef342023-11-21 13:47:15 +00001881 .StartChild("device-regions")
1882 .Compatible({"arm,ffa-manifest-device-regions"})
1883 .StartChild("test-device-0")
1884 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001885 .Property("base-address", "<0x50000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001886 .Property("pages-count", "<16>")
1887 .Property("attributes", "<3>")
1888 .EndChild()
1889 .EndChild()
1890 .Build();
1891 /* clang-format on */
1892 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
Daniel Boulby4339edc2024-02-21 14:59:00 +00001893 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
1894 manifest_dealloc();
1895
1896 /*
1897 * Memory defined as NS in SPMC manifest given Secure attribute should
1898 * fail.
1899 */
1900 /* clang-format off */
1901 dtb = ManifestDtBuilder()
1902 .FfaValidManifest()
1903 .StartChild("device-regions")
1904 .Compatible({"arm,ffa-manifest-device-regions"})
1905 .StartChild("test-device-0")
1906 .Description("test-device-0")
1907 .Property("base-address", "<0x20000000>")
1908 .Property("pages-count", "<16>")
1909 .Property("attributes", "<3>")
1910 .EndChild()
1911 .EndChild()
1912 .Build();
1913 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1914 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
Manish Pandeye68e7932020-04-23 15:29:28 +01001915}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001916
1917TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001918{
Olivier Deprez93644652022-09-09 11:01:12 +02001919 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001920
1921 /* clang-format off */
1922 std::vector<char> dtb = ManifestDtBuilder()
1923 .FfaValidManifest()
1924 .StartChild("rx_tx-info")
1925 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1926 .Property("rx-buffer", "<&rx>")
1927 .Property("tx-buffer", "<&tx>")
1928 .EndChild()
1929 .StartChild("memory-regions")
1930 .Compatible({ "arm,ffa-manifest-memory-regions" })
1931 .StartChild("test-memory")
1932 .Description("test-memory")
1933 .Property("base-address", "<0x7100000>")
1934 .Property("pages-count", "<4>")
1935 .Property("attributes", "<7>")
1936 .EndChild()
1937 .Label("rx")
1938 .StartChild("rx")
1939 .Description("rx-buffer")
1940 .Property("base-address", "<0x7300000>")
1941 .Property("pages-count", "<1>")
1942 .Property("attributes", "<1>")
1943 .EndChild()
1944 .Label("tx")
1945 .StartChild("tx")
1946 .Description("tx-buffer")
1947 .Property("base-address", "<0x7310000>")
1948 .Property("pages-count", "<1>")
1949 .Property("attributes", "<3>")
1950 .EndChild()
1951 .EndChild()
1952 .Build();
1953 /* clang-format on */
1954
1955 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1956 MANIFEST_ERROR_INVALID_MEM_PERM);
1957}
1958
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001959TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001960{
Olivier Deprez93644652022-09-09 11:01:12 +02001961 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001962
1963 /* clang-format off */
1964 std::vector<char> dtb = ManifestDtBuilder()
1965 .FfaValidManifest()
1966 .StartChild("rx_tx-info")
1967 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1968 .Property("rx-buffer", "<&rx>")
1969 .Property("tx-buffer", "<&tx>")
1970 .EndChild()
1971 .StartChild("memory-regions")
1972 .Compatible({ "arm,ffa-manifest-memory-regions" })
1973 .StartChild("test-memory")
1974 .Description("test-memory")
1975 .Property("base-address", "<0x7100000>")
1976 .Property("pages-count", "<4>")
1977 .Property("attributes", "<3>")
1978 .EndChild()
1979 .Label("rx")
1980 .StartChild("rx")
1981 .Description("rx-buffer")
1982 .Property("base-address", "<0x7300000>")
1983 .Property("pages-count", "<1>")
1984 .Property("attributes", "<1>")
1985 .EndChild()
1986 .Label("tx")
1987 .StartChild("tx")
1988 .Description("tx-buffer")
1989 .Property("base-address", "<0x7310000>")
1990 .Property("pages-count", "<1>")
1991 .Property("attributes", "<3>")
1992 .EndChild()
1993 .EndChild()
1994 .StartChild("device-regions")
1995 .Compatible({ "arm,ffa-manifest-device-regions" })
1996 .StartChild("test-device")
1997 .Description("test-device")
1998 .Property("base-address", "<0x7200000>")
1999 .Property("pages-count", "<16>")
2000 .Property("attributes", "<5>")
2001 .Property("smmu-id", "<1>")
2002 .Property("stream-ids", "<0 1>")
2003 .Property("interrupts", "<2 3>, <4 5>")
2004 .EndChild()
2005 .EndChild()
2006 .Build();
2007 /* clang-format on */
2008
2009 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2010 MANIFEST_ERROR_INVALID_MEM_PERM);
2011}
Manish Pandeye68e7932020-04-23 15:29:28 +01002012
Daniel Boulby801f8ef2022-06-27 14:21:01 +01002013TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01002014{
Olivier Deprez93644652022-09-09 11:01:12 +02002015 struct manifest_vm *vm;
2016 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01002017
2018 /* clang-format off */
2019 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01002020 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002021 .StartChild("rx_tx-info")
2022 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
2023 .Property("rx-buffer", "<&rx>")
2024 .Property("tx-buffer", "<&tx>")
2025 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01002026 .StartChild("memory-regions")
2027 .Compatible({ "arm,ffa-manifest-memory-regions" })
Olivier Deprez035fa152022-03-14 11:19:10 +01002028 .StartChild("test-memory-ns")
2029 .Description("test-memory")
2030 .Property("base-address", "<0x7200000>")
2031 .Property("pages-count", "<1>")
2032 .Property("attributes", "<0xb>")
2033 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002034 .Label("rx")
2035 .StartChild("rx")
2036 .Description("rx-buffer")
2037 .Property("base-address", "<0x7300000>")
2038 .Property("pages-count", "<1>")
2039 .Property("attributes", "<1>")
2040 .EndChild()
2041 .Label("tx")
2042 .StartChild("tx")
2043 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01002044 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002045 .Property("pages-count", "<1>")
2046 .Property("attributes", "<3>")
2047 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01002048 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01002049 .StartChild("device-regions")
2050 .Compatible({ "arm,ffa-manifest-device-regions" })
2051 .StartChild("test-device")
2052 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002053 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01002054 .Property("pages-count", "<16>")
2055 .Property("attributes", "<3>")
2056 .Property("smmu-id", "<1>")
2057 .Property("stream-ids", "<0 1>")
2058 .Property("interrupts", "<2 3>, <4 5>")
2059 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01002060 .StartChild("test-device-ns")
2061 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002062 .Property("base-address", "<0x20000000>")
Olivier Deprez035fa152022-03-14 11:19:10 +01002063 .Property("pages-count", "<1>")
2064 .Property("attributes", "<0x9>")
2065 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01002066 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01002067 .Build();
Daniel Boulby4339edc2024-02-21 14:59:00 +00002068
Olivier Deprez62d99e32020-01-09 15:58:07 +01002069 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01002070 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2071
Olivier Deprez93644652022-09-09 11:01:12 +02002072 vm = &m->vm[0];
2073 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01002074 ASSERT_THAT(
Kathleen Capella422b10b2023-06-30 18:28:27 -04002075 std::span(vm->partition.uuids[0].uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01002076 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02002077 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2078 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2079 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2080 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2081 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2082 ASSERT_EQ(vm->partition.boot_order, 0);
2083 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2084 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
Davidson K5d5f2792024-08-19 19:09:12 +05302085 ASSERT_EQ(vm->partition.mem_regions[0].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07002086
Olivier Deprez93644652022-09-09 11:01:12 +02002087 ASSERT_EQ(vm->partition.rxtx.available, true);
2088 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
2089 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
2090 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
2091 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
2092 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
2093 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
2094
Daniel Boulby4339edc2024-02-21 14:59:00 +00002095 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Olivier Deprez93644652022-09-09 11:01:12 +02002096 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002097 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002098 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2099 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2100 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Olivier Deprez93644652022-09-09 11:01:12 +02002101 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2102 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2103 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2104 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
Daniel Boulby4339edc2024-02-21 14:59:00 +00002105 ASSERT_EQ(vm->partition.dev_regions[1].base_address, 0x20000000);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002106 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01002107}
2108
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002109TEST_F(manifest, ffa_valid_interrupt_target_manifest)
2110{
2111 struct manifest_vm *vm;
2112 struct_manifest *m;
2113
2114 /* clang-format off */
2115 std::vector<char> dtb = ManifestDtBuilder()
2116 .FfaValidManifest()
2117 .StartChild("device-regions")
2118 .Compatible({ "arm,ffa-manifest-device-regions" })
2119 .StartChild("test-device")
2120 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002121 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002122 .Property("pages-count", "<16>")
2123 .Property("attributes", "<3>")
2124 .Property("smmu-id", "<1>")
2125 .Property("stream-ids", "<0 1>")
2126 .Property("interrupts", "<2 3>, <4 5>")
2127 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
2128 .EndChild()
2129 .EndChild()
2130 .Build();
2131 /* clang-format on */
2132
2133 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2134
2135 vm = &m->vm[0];
2136
Daniel Boulby4339edc2024-02-21 14:59:00 +00002137 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002138 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002139 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002140 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2141 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2142 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002143 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2144 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2145 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
2146 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
2147 0x123400005678);
2148 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2149 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
2150 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
2151 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
2152 0x1234567887654321);
2153}
2154
2155TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
2156{
2157 struct_manifest *m;
2158
2159 /* clang-format off */
2160 std::vector<char> dtb = ManifestDtBuilder()
2161 .FfaValidManifest()
2162 .StartChild("device-regions")
2163 .Compatible({ "arm,ffa-manifest-device-regions" })
2164 .StartChild("test-device")
2165 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002166 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002167 .Property("pages-count", "<16>")
2168 .Property("attributes", "<3>")
2169 .Property("smmu-id", "<1>")
2170 .Property("stream-ids", "<0 1>")
2171 .Property("interrupts", "<2 3>, <4 5>")
2172 .Property("interrupts-target", "<20 0x1234 0x5678>")
2173 .EndChild()
2174 .EndChild()
2175 .Build();
2176 /* clang-format on */
2177
2178 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2179 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
2180}
2181
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002182TEST_F(manifest, ffa_boot_order_not_unique)
2183{
2184 struct_manifest *m;
2185 struct memiter it;
2186 struct mm_stage1_locked mm_stage1_locked;
2187 struct boot_params params;
2188 Partition_package spkg_1;
2189 Partition_package spkg_2;
2190
2191 /* clang-format off */
2192 std::vector<char> dtb1 = ManifestDtBuilder()
2193 .Compatible({ "arm,ffa-manifest-1.0" })
2194 .Property("ffa-version", "<0x10001>")
2195 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2196 .FfaLoadAddress((uint64_t)&spkg_1)
2197 .Property("execution-ctx-count", "<1>")
2198 .Property("exception-level", "<1>")
2199 .Property("execution-state", "<0>")
2200 .Property("entrypoint-offset", "<0x00002000>")
2201 .Property("xlat-granule", "<0>")
2202 .Property("boot-order", "<1>")
2203 .Property("messaging-method", "<1>")
2204 .Property("ns-interrupts-action", "<0>")
2205 .Build();
2206
2207 std::vector<char> dtb2 = ManifestDtBuilder()
2208 .Compatible({ "arm,ffa-manifest-1.0" })
2209 .Property("ffa-version", "<0x10001>")
2210 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2211 .FfaLoadAddress((uint64_t)&spkg_2)
2212 .Property("execution-ctx-count", "<1>")
2213 .Property("exception-level", "<1>")
2214 .Property("execution-state", "<0>")
2215 .Property("entrypoint-offset", "<0x00002000>")
2216 .Property("xlat-granule", "<0>")
2217 .Property("boot-order", "<1>")
2218 .Property("messaging-method", "<1>")
2219 .Property("ns-interrupts-action", "<0>")
2220 .Build();
2221
2222 /* clang-format on */
2223 spkg_1.init(dtb1);
2224 spkg_2.init(dtb2);
2225
2226 /* clang-format off */
2227 std::vector<char> core_dtb = ManifestDtBuilder()
2228 .StartChild("hypervisor")
2229 .Compatible()
2230 .StartChild("vm1")
2231 .DebugName("ffa_partition_1")
2232 .FfaPartition()
2233 .LoadAddress((uint64_t)&spkg_1)
2234 .VcpuCount(1)
2235 .MemSize(0x10000000)
2236 .EndChild()
2237 .StartChild("vm2")
2238 .DebugName("ffa_partition_2")
2239 .FfaPartition()
2240 .LoadAddress((uint64_t)&spkg_2)
2241 .VcpuCount(1)
2242 .MemSize(0x10000000)
2243 .EndChild()
2244 .EndChild()
2245 .Build();
2246 /* clang-format on */
2247
2248 boot_params_init(&params, nullptr);
2249 memiter_init(&it, core_dtb.data(), core_dtb.size());
2250 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2251 MANIFEST_ERROR_INVALID_BOOT_ORDER);
2252}
Daniel Boulby941ef342023-11-21 13:47:15 +00002253
Kathleen Capella422b10b2023-06-30 18:28:27 -04002254TEST_F(manifest, ffa_valid_multiple_uuids)
2255{
2256 struct manifest_vm *vm;
2257 struct_manifest *m;
2258
2259 /* clang-format off */
2260 std::vector<char> dtb = ManifestDtBuilder()
2261 .Compatible({ "arm,ffa-manifest-1.0" })
2262 .Property("ffa-version", "<0x10002>")
2263 .Property("uuid",
2264 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,\
2265 <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2266 .Property("execution-ctx-count", "<1>")
2267 .Property("exception-level", "<2>")
2268 .Property("execution-state", "<0>")
2269 .Property("entrypoint-offset", "<0x00002000>")
2270 .Property("xlat-granule", "<0>")
2271 .Property("boot-order", "<0>")
2272 .Property("messaging-method", "<4>")
2273 .Property("ns-interrupts-action", "<1>")
2274 .Build();
2275 /* clang-format on */
2276 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2277
2278 vm = &m->vm[0];
2279 ASSERT_EQ(vm->partition.ffa_version, 0x10002);
2280 ASSERT_THAT(
2281 std::span(vm->partition.uuids[0].uuid, 4),
2282 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
2283 ASSERT_THAT(
2284 std::span(vm->partition.uuids[1].uuid, 4),
2285 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1daaa));
2286 ASSERT_EQ(vm->partition.uuid_count, 2);
2287 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2288 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2289 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2290 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2291 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2292 ASSERT_EQ(vm->partition.boot_order, 0);
2293 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2294 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
2295}
Karl Meakin45abeeb2024-08-02 16:55:44 +01002296
2297TEST_F(manifest, ffa_too_many_uuids)
2298{
2299 struct_manifest *m;
2300
2301 /* clang-format off */
2302 std::vector<char> dtb = ManifestDtBuilder()
2303 .Compatible({ "arm,ffa-manifest-1.0" })
2304 .Property("ffa-version", "<0x10002>")
2305 .Property("uuid",
2306 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,"
2307 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2308 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2309 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2310 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2311 .Property("execution-ctx-count", "<1>")
2312 .Property("exception-level", "<2>")
2313 .Property("execution-state", "<0>")
2314 .Property("entrypoint-offset", "<0x00002000>")
2315 .Property("xlat-granule", "<0>")
2316 .Property("boot-order", "<0>")
2317 .Property("messaging-method", "<4>")
2318 .Property("ns-interrupts-action", "<1>")
2319 .Build();
2320 /* clang-format on */
2321 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2322 MANIFEST_ERROR_TOO_MANY_UUIDS);
2323}
2324
Kathleen Capella422b10b2023-06-30 18:28:27 -04002325TEST_F(manifest, ffa_uuid_all_zeros)
2326{
2327 struct_manifest *m;
2328
2329 /* clang-format off */
2330 std::vector<char> dtb = ManifestDtBuilder()
2331 .Compatible({ "arm,ffa-manifest-1.0" })
2332 .Property("ffa-version", "<0x10002>")
2333 .Property("uuid",
2334 "<0x0 0x0 0x0 0x0>, <0x0 0x0 0x0 0x0>")
2335 .Property("execution-ctx-count", "<1>")
2336 .Property("exception-level", "<2>")
2337 .Property("execution-state", "<0>")
2338 .Property("entrypoint-offset", "<0x00002000>")
2339 .Property("xlat-granule", "<0>")
2340 .Property("boot-order", "<0>")
2341 .Property("messaging-method", "<4>")
2342 .Property("ns-interrupts-action", "<1>")
2343 .Build();
2344 /* clang-format on */
2345 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2346 MANIFEST_ERROR_UUID_ALL_ZEROS);
2347}
Daniel Boulby941ef342023-11-21 13:47:15 +00002348
2349/*
2350 * Test that the address space of two device region nodes specified across
2351 * different SPs cannot overlap.
2352 */
2353TEST_F(manifest, ffa_device_region_multi_sps)
2354{
2355 struct_manifest *m;
2356 struct memiter it;
2357 struct mm_stage1_locked mm_stage1_locked;
2358 struct boot_params params;
2359 Partition_package spkg_1;
2360 Partition_package spkg_2;
2361
2362 /* clang-format off */
2363 std::vector<char> dtb1 = ManifestDtBuilder()
2364 .Compatible({ "arm,ffa-manifest-1.0" })
2365 .Property("ffa-version", "<0x10001>")
2366 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2367 .FfaLoadAddress((uint64_t)&spkg_1)
2368 .Property("execution-ctx-count", "<1>")
2369 .Property("exception-level", "<0>")
2370 .Property("execution-state", "<0>")
2371 .Property("entrypoint-offset", "<0x0>")
2372 .Property("xlat-granule", "<0>")
2373 .Property("messaging-method", "<0x7>")
2374 .StartChild("device-regions")
2375 .Compatible({ "arm,ffa-manifest-device-regions" })
2376 .StartChild("test-device-0")
2377 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002378 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002379 .Property("pages-count", "<16>")
2380 .Property("attributes", "<3>")
2381 .EndChild()
2382 .EndChild()
2383 .Build();
2384
2385 std::vector<char> dtb2 = ManifestDtBuilder()
2386 .Compatible({ "arm,ffa-manifest-1.0" })
2387 .Property("ffa-version", "<0x10001>")
2388 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2389 .FfaLoadAddress((uint64_t)&spkg_2)
2390 .Property("execution-ctx-count", "<1>")
2391 .Property("exception-level", "<0>")
2392 .Property("execution-state", "<0>")
2393 .Property("entrypoint-offset", "<0x0>")
2394 .Property("xlat-granule", "<0>")
2395 .Property("messaging-method", "<0x7>")
2396 .StartChild("device-regions")
2397 .Compatible({ "arm,ffa-manifest-device-regions" })
2398 .StartChild("test-device-0")
2399 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002400 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002401 .Property("pages-count", "<16>")
2402 .Property("attributes", "<3>")
2403 .EndChild()
2404 .EndChild()
2405 .Build();
2406
2407 /* clang-format on */
2408 spkg_1.init(dtb1);
2409 spkg_2.init(dtb2);
2410
2411 /* clang-format off */
2412 std::vector<char> core_dtb = ManifestDtBuilder()
2413 .StartChild("hypervisor")
2414 .Compatible()
2415 .StartChild("vm1")
2416 .DebugName("ffa_partition_1")
2417 .FfaPartition()
2418 .LoadAddress((uint64_t)&spkg_1)
2419 .VcpuCount(1)
2420 .MemSize(0x4000)
2421 .EndChild()
2422 .StartChild("vm2")
2423 .DebugName("ffa_partition_2")
2424 .FfaPartition()
2425 .LoadAddress((uint64_t)&spkg_2)
2426 .VcpuCount(1)
2427 .MemSize(0x4000)
2428 .EndChild()
2429 .EndChild()
2430 .Build();
2431 /* clang-format on */
2432 boot_params_init(&params, &spkg_1);
2433 memiter_init(&it, core_dtb.data(), core_dtb.size());
2434 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2435 MANIFEST_ERROR_MEM_REGION_OVERLAP);
2436
2437 manifest_dealloc();
2438
2439 /* clang-format off */
2440 dtb1 = ManifestDtBuilder()
2441 .Compatible({ "arm,ffa-manifest-1.0" })
2442 .Property("ffa-version", "<0x10001>")
2443 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2444 .FfaLoadAddress((uint64_t)&spkg_1)
2445 .Property("execution-ctx-count", "<1>")
2446 .Property("exception-level", "<0>")
2447 .Property("execution-state", "<0>")
2448 .Property("entrypoint-offset", "<0x0>")
2449 .Property("xlat-granule", "<0>")
2450 .Property("messaging-method", "<0x7>")
2451 .StartChild("device-regions")
2452 .Compatible({ "arm,ffa-manifest-device-regions" })
2453 .StartChild("test-device-0")
2454 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002455 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002456 .Property("pages-count", "<16>")
2457 .Property("attributes", "<3>")
2458 .EndChild()
2459 .EndChild()
2460 .Build();
2461
2462 dtb2 = ManifestDtBuilder()
2463 .Compatible({ "arm,ffa-manifest-1.0" })
2464 .Property("ffa-version", "<0x10001>")
2465 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2466 .FfaLoadAddress((uint64_t)&spkg_2)
2467 .Property("execution-ctx-count", "<1>")
2468 .Property("exception-level", "<0>")
2469 .Property("execution-state", "<0>")
2470 .Property("entrypoint-offset", "<0x0>")
2471 .Property("xlat-granule", "<0>")
2472 .Property("messaging-method", "<0x7>")
2473 .StartChild("device-regions")
2474 .Compatible({ "arm,ffa-manifest-device-regions" })
2475 .StartChild("test-device-0")
2476 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002477 .Property("base-address", "<0x25000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002478 .Property("pages-count", "<16>")
2479 .Property("attributes", "<3>")
2480 .EndChild()
2481 .EndChild()
2482 .Build();
2483
2484 /* clang-format on */
2485 spkg_1.init(dtb1);
2486 spkg_2.init(dtb2);
2487
2488 /* clang-format off */
2489 core_dtb = ManifestDtBuilder()
2490 .StartChild("hypervisor")
2491 .Compatible()
2492 .StartChild("vm1")
2493 .DebugName("ffa_partition_1")
2494 .FfaPartition()
2495 .LoadAddress((uint64_t)&spkg_1)
2496 .VcpuCount(1)
2497 .MemSize(0x4000)
2498 .EndChild()
2499 .StartChild("vm2")
2500 .DebugName("ffa_partition_2")
2501 .FfaPartition()
2502 .LoadAddress((uint64_t)&spkg_2)
2503 .VcpuCount(1)
2504 .MemSize(0x4000)
2505 .EndChild()
2506 .EndChild()
2507 .Build();
2508 /* clang-format on */
2509 boot_params_init(&params, &spkg_1);
2510 memiter_init(&it, core_dtb.data(), core_dtb.size());
2511 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2512 MANIFEST_SUCCESS);
2513}
Madhukar Pappireddy99c5eff2024-07-08 15:07:41 -05002514
2515/*
2516 * Tests to trigger various error conditions while parsing dma related
2517 * properties of memory region nodes.
2518 */
2519TEST_F(manifest, ffa_memory_region_invalid_dma_properties)
2520{
2521 struct_manifest *m;
2522
2523 /*
2524 * SMMU ID must be specified if the partition specifies Stream IDs for
2525 * any device upstream of SMMU.
2526 */
2527 /* clang-format off */
2528 std::vector<char> dtb = ManifestDtBuilder()
2529 .FfaValidManifest()
2530 .StartChild("memory-regions")
2531 .Compatible({ "arm,ffa-manifest-memory-regions" })
2532 .StartChild("test-memory")
2533 .Description("test-memory")
2534 .Property("base-address", "<0x7100000>")
2535 .Property("pages-count", "<16>")
2536 .Property("attributes", "<3>")
2537 .Property("stream-ids", "<0 1>")
2538 .Property("interrupts", "<2 3>, <4 5>")
2539 .EndChild()
2540 .EndChild()
2541 .Build();
2542 /* clang-format on */
2543
2544 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2545 MANIFEST_ERROR_MISSING_SMMU_ID);
2546 manifest_dealloc();
2547
2548 /*
2549 * All stream ids belonging to a dma device must specify the same access
2550 * permissions.
2551 */
2552 /* clang-format off */
2553 dtb = ManifestDtBuilder()
2554 .FfaValidManifest()
2555 .StartChild("memory-regions")
2556 .Compatible({ "arm,ffa-manifest-memory-regions" })
2557 .StartChild("test-memory")
2558 .Description("test-memory")
2559 .Property("base-address", "<0x7100000>")
2560 .Property("pages-count", "<16>")
2561 .Property("attributes", "<3>")
2562 .Property("smmu-id", "<1>")
2563 .Property("stream-ids", "<0 1>")
2564 .Property("stream-ids-access-permissions", "<0x3 0xb>")
2565 .Property("interrupts", "<2 3>, <4 5>")
2566 .EndChild()
2567 .EndChild()
2568 .Build();
2569 /* clang-format on */
2570
2571 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2572 MANIFEST_ERROR_MISMATCH_DMA_ACCESS_PERMISSIONS);
2573 manifest_dealloc();
2574
2575 /*
2576 * DMA device stream ID count exceeds predefined limit.
2577 */
2578 /* clang-format off */
2579 dtb = ManifestDtBuilder()
2580 .FfaValidManifest()
2581 .StartChild("memory-regions")
2582 .Compatible({ "arm,ffa-manifest-memory-regions" })
2583 .StartChild("test-memory")
2584 .Description("test-memory")
2585 .Property("base-address", "<0x7100000>")
2586 .Property("pages-count", "<16>")
2587 .Property("attributes", "<3>")
2588 .Property("smmu-id", "<1>")
2589 .Property("stream-ids", "<0 1 4 9 12 >")
2590 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3>")
2591 .EndChild()
2592 .EndChild()
2593 .Build();
2594 /* clang-format on */
2595
2596 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2597 MANIFEST_ERROR_STREAM_IDS_OVERFLOW);
2598 manifest_dealloc();
2599
2600 /*
2601 * DMA access permissions count exceeds predefined limit
2602 */
2603 /* clang-format off */
2604 dtb = ManifestDtBuilder()
2605 .FfaValidManifest()
2606 .StartChild("memory-regions")
2607 .Compatible({ "arm,ffa-manifest-memory-regions" })
2608 .StartChild("test-memory")
2609 .Description("test-memory")
2610 .Property("base-address", "<0x7100000>")
2611 .Property("pages-count", "<16>")
2612 .Property("attributes", "<3>")
2613 .Property("smmu-id", "<1>")
2614 .Property("stream-ids", "<0 1>")
2615 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3 0x3 0x3>")
2616 .EndChild()
2617 .EndChild()
2618 .Build();
2619 /* clang-format on */
2620
2621 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2622 MANIFEST_ERROR_DMA_ACCESS_PERMISSIONS_OVERFLOW);
2623}
2624
2625/*
2626 * Tests to trigger various error conditions while parsing dma related
2627 * properties of device region nodes.
2628 */
2629TEST_F(manifest, ffa_device_region_invalid_dma_properties)
2630{
2631 struct_manifest *m;
2632
2633 /*
2634 * SMMU ID must be specified if the partition specifies Stream IDs for
2635 * any device upstream of SMMU.
2636 */
2637 /* clang-format off */
2638 std::vector<char> dtb = ManifestDtBuilder()
2639 .FfaValidManifest()
2640 .StartChild("device-regions")
2641 .Compatible({ "arm,ffa-manifest-device-regions" })
2642 .StartChild("test-device")
2643 .Description("test-device")
2644 .Property("base-address", "<0x24000000>")
2645 .Property("pages-count", "<16>")
2646 .Property("attributes", "<3>")
2647 .Property("stream-ids", "<0 1>")
2648 .Property("interrupts", "<2 3>, <4 5>")
2649 .EndChild()
2650 .EndChild()
2651 .Build();
2652 /* clang-format on */
2653
2654 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2655 MANIFEST_ERROR_MISSING_SMMU_ID);
2656 manifest_dealloc();
2657
2658 /*
2659 * Dma devices defined through device region nodes exceed predefined
2660 * limit.
2661 */
2662 /* clang-format off */
2663 dtb = ManifestDtBuilder()
2664 .FfaValidManifest()
2665 .StartChild("device-regions")
2666 .Compatible({ "arm,ffa-manifest-device-regions" })
2667 .StartChild("test-device-0")
2668 .Description("test-device-0")
2669 .Property("base-address", "<0x27000000>")
2670 .Property("pages-count", "<16>")
2671 .Property("attributes", "<3>")
2672 .Property("smmu-id", "<1>")
2673 .Property("stream-ids", "<0 1>")
2674 .EndChild()
2675 .StartChild("test-device-1")
2676 .Description("test-device-1")
2677 .Property("base-address", "<0x25000000>")
2678 .Property("pages-count", "<16>")
2679 .Property("attributes", "<3>")
2680 .Property("smmu-id", "<1>")
2681 .Property("stream-ids", "<2 3>")
2682 .EndChild()
2683 .StartChild("test-device-2")
2684 .Description("test-device-2")
2685 .Property("base-address", "<0x26000000>")
2686 .Property("pages-count", "<16>")
2687 .Property("attributes", "<3>")
2688 .Property("smmu-id", "<1>")
2689 .Property("stream-ids", "<4 5>")
2690 .EndChild()
2691 .EndChild()
2692 .Build();
2693 /* clang-format on */
2694
2695 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2696 MANIFEST_ERROR_DMA_DEVICE_OVERFLOW);
2697}
David Brazdil7a462ec2019-08-15 12:27:47 +01002698} /* namespace */