blob: 8bcef3007eea4662fdaf0c416f52738df9de82f7 [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
1231 /* S-EL1 partition power management field can set bit 0. */
1232 /* 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>")
1242 .Property("power-management-messages", "<1>")
1243 .Build();
1244 /* clang-format on */
1245 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1246 vm = &m->vm[0];
1247 ASSERT_EQ(vm->partition.power_management, 1);
1248 manifest_dealloc();
1249
1250 /* S-EL1 partition power management field can set bit 3. */
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", "<8>")
1257 .Property("exception-level", "<2>")
1258 .Property("execution-state", "<0>")
1259 .Property("entrypoint-offset", "<0x00002000>")
1260 .Property("messaging-method", "<1>")
1261 .Property("power-management-messages", "<8>")
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, 8);
1267 manifest_dealloc();
1268
1269 /* S-EL1 partition power management field can only set bits 0 and 3. */
1270 /* clang-format off */
1271 dtb = ManifestDtBuilder()
1272 .Compatible({ "arm,ffa-manifest-1.0" })
1273 .Property("ffa-version", "<0x10001>")
1274 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1275 .Property("execution-ctx-count", "<8>")
1276 .Property("exception-level", "<2>")
1277 .Property("execution-state", "<0>")
1278 .Property("entrypoint-offset", "<0x00002000>")
1279 .Property("messaging-method", "<1>")
1280 .Property("power-management-messages", "<0xf>")
1281 .Build();
1282 /* clang-format on */
1283 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1284 vm = &m->vm[0];
1285 ASSERT_EQ(vm->partition.power_management, 9);
1286 manifest_dealloc();
1287
1288 /* S-EL0 partition power management field is forced to 0. */
1289 /* clang-format off */
1290 dtb = ManifestDtBuilder()
1291 .Compatible({ "arm,ffa-manifest-1.0" })
1292 .Property("ffa-version", "<0x10001>")
1293 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1294 .Property("execution-ctx-count", "<1>")
1295 .Property("exception-level", "<1>")
1296 .Property("execution-state", "<0>")
1297 .Property("entrypoint-offset", "<0x00002000>")
1298 .Property("messaging-method", "<1>")
1299 .Property("power-management-messages", "<0xff>")
1300 .Build();
1301 /* clang-format on */
1302 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1303 vm = &m->vm[0];
1304 ASSERT_EQ(vm->partition.power_management, 0);
1305}
1306
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001307TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001308{
Olivier Deprez93644652022-09-09 11:01:12 +02001309 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001310
1311 /* Not Compatible */
1312 /* clang-format off */
1313 std::vector<char> dtb = ManifestDtBuilder()
1314 .FfaValidManifest()
1315 .StartChild("rx_tx-info")
1316 .Compatible({ "foo,bar" })
1317 .EndChild()
1318 .Build();
1319 /* clang-format on */
1320 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1321 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001322 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001323
1324 /* Missing Properties */
1325 /* clang-format off */
1326 dtb = ManifestDtBuilder()
1327 .FfaValidManifest()
1328 .StartChild("rx_tx-info")
1329 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1330 .EndChild()
1331 .Build();
1332 /* clang-format on */
1333 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1334 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1335}
1336
Karl Meakinf955dbe2024-11-18 16:38:58 +00001337TEST_F(manifest, ffa_validate_mem_regions_not_compatible)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001338{
Olivier Deprez93644652022-09-09 11:01:12 +02001339 struct_manifest *m;
Karl Meakinf955dbe2024-11-18 16:38:58 +00001340 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001341
1342 /* Not Compatible */
1343 /* clang-format off */
Karl Meakinf955dbe2024-11-18 16:38:58 +00001344 dtb = ManifestDtBuilder()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001345 .FfaValidManifest()
1346 .StartChild("memory-regions")
1347 .Compatible({ "foo,bar" })
1348 .EndChild()
1349 .Build();
1350 /* clang-format on */
1351 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1352 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001353 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001354}
1355
1356TEST_F(manifest, ffa_validate_mem_regions_unavailable)
1357{
1358 struct_manifest *m;
1359 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001360
1361 /* Memory regions unavailable */
1362 /* clang-format off */
1363 dtb = ManifestDtBuilder()
1364 .FfaValidManifest()
1365 .StartChild("memory-regions")
1366 .Compatible({ "arm,ffa-manifest-memory-regions" })
1367 .EndChild()
1368 .Build();
1369 /* clang-format on */
1370 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1371 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001372 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001373}
1374
1375TEST_F(manifest, ffa_validate_mem_regions_missing_properties)
1376{
1377 struct_manifest *m;
1378 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001379
1380 /* Missing Properties */
1381 /* clang-format off */
1382 dtb = ManifestDtBuilder()
1383 .FfaValidManifest()
1384 .StartChild("memory-regions")
1385 .Compatible({ "arm,ffa-manifest-memory-regions" })
1386 .StartChild("test-memory")
1387 .Description("test-memory")
1388 .EndChild()
1389 .EndChild()
1390 .Build();
1391 /* clang-format on */
1392 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1393 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001394 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001395}
1396
1397TEST_F(manifest, ffa_validate_mem_regions_empty_region)
1398{
1399 struct_manifest *m;
1400 std::vector<char> dtb;
Manish Pandeyf06c9072020-09-29 15:41:58 +01001401
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001402 /* Empty memory region */
1403 /* clang-format off */
1404 dtb = ManifestDtBuilder()
1405 .FfaValidManifest()
1406 .StartChild("memory-regions")
1407 .Compatible({ "arm,ffa-manifest-memory-regions" })
1408 .Label("rx")
1409 .StartChild("rx")
1410 .Description("rx-buffer")
1411 .Property("base-address", "<0x7300000>")
1412 .Property("pages-count", "<0>")
1413 .Property("attributes", "<1>")
1414 .EndChild()
1415 .Label("tx")
1416 .StartChild("tx")
1417 .Description("tx-buffer")
1418 .Property("base-address", "<0x7310000>")
1419 .Property("pages-count", "<2>")
1420 .Property("attributes", "<3>")
1421 .EndChild()
1422 .EndChild()
1423 .StartChild("rx_tx-info")
1424 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1425 .Property("rx-buffer", "<&rx>")
1426 .Property("tx-buffer", "<&tx>")
1427 .EndChild()
1428 .Build();
1429 /* clang-format on */
1430 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1431 MANIFEST_ERROR_MEM_REGION_EMPTY);
1432 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001433}
1434
1435TEST_F(manifest, ffa_validate_mem_regions_base_address_and_relative_offset)
1436{
1437 struct_manifest *m;
1438 std::vector<char> dtb;
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001439
Davidson K8ccd2d02024-09-03 16:10:54 +05301440 /* Mutually exclusive base-address and load-address-relative-offset
1441 * properties */
Karl Meakine92efbe2023-06-01 14:16:22 +01001442 /* clang-format off */
1443 dtb = ManifestDtBuilder()
1444 .FfaValidManifest()
1445 .StartChild("memory-regions")
1446 .Compatible({ "arm,ffa-manifest-memory-regions" })
1447 .Label("rx")
1448 .StartChild("rx")
1449 .Description("rx-buffer")
1450 .Property("base-address", "<0x7300000>")
Davidson K8ccd2d02024-09-03 16:10:54 +05301451 .Property("load-address-relative-offset", "<0x7300000>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001452 .Property("pages-count", "<1>")
1453 .Property("attributes", "<1>")
1454 .EndChild()
1455 .EndChild()
1456 .Build();
1457 /* clang-format on */
1458 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1459 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1460 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001461}
1462
1463TEST_F(manifest, ffa_validate_mem_regions_relative_address_overflow)
1464{
1465 struct_manifest *m;
1466 std::vector<char> dtb;
1467
Karl Meakine92efbe2023-06-01 14:16:22 +01001468 /* Relative-address overflow*/
1469 /* clang-format off */
1470 dtb = ManifestDtBuilder()
1471 .FfaValidManifest()
1472 .Property("load-address", "<0xffffff00 0xffffff00>")
1473 .StartChild("memory-regions")
1474 .Compatible({ "arm,ffa-manifest-memory-regions" })
1475 .Label("rx")
1476 .StartChild("rx")
1477 .Description("rx-buffer")
Davidson K8ccd2d02024-09-03 16:10:54 +05301478 .Property("load-address-relative-offset", "<0xffffff00 0xffffff00>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001479 .Property("pages-count", "<1>")
1480 .Property("attributes", "<1>")
1481 .EndChild()
1482 .EndChild()
1483 .Build();
1484 /* clang-format on */
1485 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1486 MANIFEST_ERROR_INTEGER_OVERFLOW);
1487 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001488}
1489
1490TEST_F(manifest, ffa_validate_mem_regions_relative_offset_valid)
1491{
1492 struct_manifest *m;
1493 std::vector<char> dtb;
1494
1495 /* valid relative offset */
1496 /* clang-format off */
1497 dtb = ManifestDtBuilder()
1498 .FfaValidManifest()
1499 .Property("load-address", "<0xffffff00 0xffffff00>")
1500 .StartChild("memory-regions")
1501 .Compatible({ "arm,ffa-manifest-memory-regions" })
1502 .Label("rx")
1503 .StartChild("rx")
1504 .Description("rx-buffer")
1505 .Property("load-address-relative-offset", "<0x1000>")
1506 .Property("pages-count", "<1>")
1507 .Property("attributes", "<1>")
1508 .EndChild()
1509 .EndChild()
1510 .Build();
1511 /* clang-format on */
1512 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1513 manifest_dealloc();
1514}
1515
1516TEST_F(manifest, ffa_validate_mem_regions_overlapping)
1517{
1518 struct_manifest *m;
1519 std::vector<char> dtb;
Karl Meakine92efbe2023-06-01 14:16:22 +01001520
Daniel Boulby9279b552022-06-28 17:04:01 +01001521 /* Overlapping memory regions */
1522 /* clang-format off */
1523 dtb = ManifestDtBuilder()
1524 .FfaValidManifest()
1525 .StartChild("memory-regions")
1526 .Compatible({ "arm,ffa-manifest-memory-regions" })
1527 .Label("rx")
1528 .StartChild("rx")
1529 .Description("rx-buffer")
1530 .Property("base-address", "<0x7300000>")
1531 .Property("pages-count", "<1>")
1532 .Property("attributes", "<1>")
1533 .EndChild()
1534 .Label("tx")
1535 .StartChild("tx")
1536 .Description("tx-buffer")
1537 .Property("base-address", "<0x7300000>")
1538 .Property("pages-count", "<2>")
1539 .Property("attributes", "<3>")
1540 .EndChild()
1541 .EndChild()
1542 .Build();
1543 /* clang-format on */
1544 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1545 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001546 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001547
1548 /* clang-format off */
1549 dtb = ManifestDtBuilder()
1550 .FfaValidManifest()
1551 .StartChild("memory-regions")
1552 .Compatible({ "arm,ffa-manifest-memory-regions" })
1553 .Label("rx")
1554 .StartChild("rx")
1555 .Description("rx-buffer")
Karl Meakin6291eb22024-11-18 12:43:47 +00001556 .Property("load-address-relative-offset", "<0x0>")
1557 .Property("pages-count", "<1>")
1558 .Property("attributes", "<1>")
1559 .EndChild()
1560 .Label("tx")
1561 .StartChild("tx")
1562 .Description("tx-buffer")
1563 .Property("load-address-relative-offset", "<0x0>")
1564 .Property("pages-count", "<2>")
1565 .Property("attributes", "<3>")
1566 .EndChild()
1567 .EndChild()
1568 .Build();
1569 /* clang-format on */
1570 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1571 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1572 manifest_dealloc();
1573
1574 /* clang-format off */
1575 dtb = ManifestDtBuilder()
1576 .FfaValidManifest()
1577 .StartChild("memory-regions")
1578 .Compatible({ "arm,ffa-manifest-memory-regions" })
1579 .Label("rx")
1580 .StartChild("rx")
1581 .Description("rx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001582 .Property("base-address", "<0x7300000>")
1583 .Property("pages-count", "<2>")
1584 .Property("attributes", "<1>")
1585 .EndChild()
1586 .Label("tx")
1587 .StartChild("tx")
1588 .Description("tx-buffer")
1589 .Property("base-address", "<0x7301000>")
1590 .Property("pages-count", "<2>")
1591 .Property("attributes", "<3>")
1592 .EndChild()
1593 .EndChild()
1594 .Build();
1595 /* clang-format on */
1596 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1597 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001598 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001599
1600 /* clang-format off */
1601 dtb = ManifestDtBuilder()
1602 .FfaValidManifest()
1603 .StartChild("memory-regions")
1604 .Compatible({ "arm,ffa-manifest-memory-regions" })
1605 .Label("rx")
1606 .StartChild("rx")
1607 .Description("rx-buffer")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001608 .Property("base-address", "<0x7301000>")
1609 .Property("pages-count", "<1>")
1610 .Property("attributes", "<1>")
1611 .EndChild()
1612 .Label("tx")
1613 .StartChild("tx")
1614 .Description("tx-buffer")
1615 .Property("base-address", "<0x7300000>")
1616 .Property("pages-count", "<2>")
1617 .Property("attributes", "<3>")
1618 .EndChild()
1619 .EndChild()
1620 .Build();
1621 /* clang-format on */
1622 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1623 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001624 manifest_dealloc();
Karl Meakin6291eb22024-11-18 12:43:47 +00001625
1626 /* clang-format off */
1627 Partition_package spkg(dtb);
1628 dtb = ManifestDtBuilder()
1629 .FfaValidManifest()
1630 .StartChild("memory-regions")
1631 .Compatible({ "arm,ffa-manifest-memory-regions" })
1632 .StartChild("test-memory")
1633 .Description("test-memory")
1634 .Integer64Property("base-address", (uint64_t)&spkg,true)
1635 .Property("pages-count", "<1>")
1636 .Property("attributes", "<1>")
1637 .EndChild()
1638 .EndChild()
1639 .Build(true);
1640 /* clang-format on */
1641 spkg.init(dtb);
1642 ASSERT_EQ(ffa_manifest_from_spkg(&m, &spkg),
1643 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1644 manifest_dealloc();
1645}
1646
1647TEST_F(manifest, ffa_validate_mem_regions_overlapping_allowed)
1648{
1649 struct_manifest *m;
1650 std::vector<char> dtb;
1651
1652 /*
1653 * Mem regions are allowed to overlap with parent `load-address` if the
1654 * `load-address-relative-offset` was specified.
1655 */
1656 /* clang-format off */
1657 dtb = ManifestDtBuilder()
1658 .FfaValidManifest()
1659 .StartChild("memory-regions")
1660 .Compatible({ "arm,ffa-manifest-memory-regions" })
1661 .Label("rx")
1662 .StartChild("rx")
1663 .Description("rx-buffer")
1664 .Property("load-address-relative-offset", "<0x1000>")
1665 .Property("pages-count", "<1>")
1666 .Property("attributes", "<1>")
1667 .EndChild()
1668 .Label("tx")
1669 .StartChild("tx")
1670 .Description("tx-buffer")
1671 .Property("base-address", "<0x7300000>")
1672 .Property("pages-count", "<2>")
1673 .Property("attributes", "<3>")
1674 .EndChild()
1675 .EndChild()
1676 .Build();
1677 /* clang-format on */
1678 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1679 ASSERT_EQ(m->vm[0].partition.mem_regions[0].is_relative, true);
1680 ASSERT_EQ(m->vm[0].partition.mem_regions[0].base_address,
1681 m->vm[0].partition.load_addr + 0x1000);
1682 manifest_dealloc();
1683
1684 /* clang-format off */
1685 dtb = ManifestDtBuilder()
1686 .FfaValidManifest()
1687 .StartChild("memory-regions")
1688 .Compatible({ "arm,ffa-manifest-memory-regions" })
1689 .Label("rx")
1690 .StartChild("rx")
1691 .Description("rx-buffer")
1692 .Property("base-address", "<0x7300000>")
1693 .Property("pages-count", "<1>")
1694 .Property("attributes", "<1>")
1695 .EndChild()
1696 .Label("tx")
1697 .StartChild("tx")
1698 .Description("tx-buffer")
1699 .Property("load-address-relative-offset", "<0x1000>")
1700 .Property("pages-count", "<2>")
1701 .Property("attributes", "<3>")
1702 .EndChild()
1703 .EndChild()
1704 .Build();
1705 /* clang-format on */
1706 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1707 ASSERT_EQ(m->vm[0].partition.mem_regions[1].is_relative, true);
1708 ASSERT_EQ(m->vm[0].partition.mem_regions[1].base_address,
1709 m->vm[0].partition.load_addr + 0x1000);
1710 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001711}
1712
1713TEST_F(manifest, ffa_validate_mem_regions_unaligned)
1714{
1715 struct_manifest *m;
1716 std::vector<char> dtb;
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001717
1718 /* Unaligned memory region */
1719 /* clang-format off */
1720 dtb = ManifestDtBuilder()
1721 .FfaValidManifest()
1722 .StartChild("memory-regions")
1723 .Compatible({ "arm,ffa-manifest-memory-regions" })
1724 .Label("rx")
1725 .StartChild("rx")
1726 .Description("rx-buffer")
1727 .Property("base-address", "<0x7300FFF>")
1728 .Property("pages-count", "<2>")
1729 .Property("attributes", "<1>")
1730 .EndChild()
1731 .Label("tx")
1732 .StartChild("tx")
1733 .Description("tx-buffer")
1734 .Property("base-address", "<0x7303000>")
1735 .Property("pages-count", "<2>")
1736 .Property("attributes", "<3>")
1737 .EndChild()
1738 .EndChild()
1739 .Build();
1740 /* clang-format on */
1741 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1742 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1743 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001744}
1745
1746TEST_F(manifest, ffa_validate_mem_regions_different_rxtx_sizes)
1747{
1748 struct_manifest *m;
1749 std::vector<char> dtb;
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001750
Manish Pandeyf06c9072020-09-29 15:41:58 +01001751 /* Different RXTX buffer sizes */
1752 /* clang-format off */
1753 dtb = ManifestDtBuilder()
1754 .FfaValidManifest()
1755 .StartChild("memory-regions")
1756 .Compatible({ "arm,ffa-manifest-memory-regions" })
1757 .Label("rx")
1758 .StartChild("rx")
1759 .Description("rx-buffer")
1760 .Property("base-address", "<0x7300000>")
1761 .Property("pages-count", "<1>")
1762 .Property("attributes", "<1>")
1763 .EndChild()
1764 .Label("tx")
1765 .StartChild("tx")
1766 .Description("tx-buffer")
1767 .Property("base-address", "<0x7310000>")
1768 .Property("pages-count", "<2>")
1769 .Property("attributes", "<3>")
1770 .EndChild()
1771 .EndChild()
1772 .StartChild("rx_tx-info")
1773 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1774 .Property("rx-buffer", "<&rx>")
1775 .Property("tx-buffer", "<&tx>")
1776 .EndChild()
1777 .Build();
1778 /* clang-format on */
1779 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1780 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001781}
1782
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001783TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001784{
Olivier Deprez93644652022-09-09 11:01:12 +02001785 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001786
1787 /* Not Compatible */
1788 /* clang-format off */
1789 std::vector<char> dtb = ManifestDtBuilder()
1790 .FfaValidManifest()
1791 .StartChild("device-regions")
1792 .Compatible({ "foo,bar" })
1793 .EndChild()
1794 .Build();
1795 /* clang-format on */
1796 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1797 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001798 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001799
1800 /* Memory regions unavailable */
1801 /* clang-format off */
1802 dtb = ManifestDtBuilder()
1803 .FfaValidManifest()
1804 .StartChild("device-regions")
1805 .Compatible({ "arm,ffa-manifest-device-regions" })
1806 .EndChild()
1807 .Build();
1808 /* clang-format on */
1809 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1810 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001811 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001812
1813 /* Missing Properties */
1814 /* clang-format off */
1815 dtb = ManifestDtBuilder()
1816 .FfaValidManifest()
1817 .StartChild("device-regions")
1818 .Compatible({ "arm,ffa-manifest-device-regions" })
1819 .StartChild("test-device")
1820 .Description("test-device")
1821 .EndChild()
1822 .EndChild()
1823 .Build();
1824 /* clang-format on */
1825 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1826 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001827 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001828
1829 /* Malformed interrupt list pair */
1830 /* clang-format off */
1831 dtb = ManifestDtBuilder()
1832 .FfaValidManifest()
1833 .StartChild("device-regions")
1834 .Compatible({ "arm,ffa-manifest-device-regions" })
1835 .StartChild("test-device")
1836 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001837 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001838 .Property("pages-count", "<16>")
1839 .Property("attributes", "<3>")
1840 .Property("smmu-id", "<1>")
1841 .Property("stream-ids", "<0 1>")
1842 .Property("interrupts", "<2 3>, <4>")
1843 .EndChild()
1844 .EndChild()
1845 .Build();
1846 /* clang-format on */
1847 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1848 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001849 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001850
1851 /* Non-unique interrupt IDs */
1852 /* clang-format off */
1853 dtb = ManifestDtBuilder()
1854 .FfaValidManifest()
1855 .StartChild("device-regions")
1856 .Compatible({ "arm,ffa-manifest-device-regions" })
1857 .StartChild("test-device-0")
1858 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001859 .Property("base-address", "<0x24000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001860 .Property("pages-count", "<16>")
1861 .Property("attributes", "<3>")
1862 .Property("interrupts", "<2 3>")
1863 .EndChild()
1864 .StartChild("test-device-1")
1865 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001866 .Property("base-address", "<0x25000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001867 .Property("pages-count", "<16>")
1868 .Property("attributes", "<3>")
1869 .Property("interrupts", "<1 3>, <2 5> ")
1870 .EndChild()
1871 .EndChild()
1872 .Build();
Daniel Boulby941ef342023-11-21 13:47:15 +00001873
Daniel Boulby667334f2022-06-27 15:23:21 +01001874 /* clang-format on */
1875 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1876 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1877 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001878 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1879 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1880 3);
1881 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1882 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1883 3);
Daniel Boulby941ef342023-11-21 13:47:15 +00001884 manifest_dealloc();
1885
1886 /* Overlapping address space between two device region nodes. */
1887 /* clang-format off */
1888 dtb = ManifestDtBuilder()
1889 .FfaValidManifest()
1890 .StartChild("device-regions")
1891 .Compatible({"arm,ffa-manifest-device-regions"})
1892 .StartChild("test-device-0")
1893 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001894 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001895 .Property("pages-count", "<16>")
1896 .Property("attributes", "<3>")
1897 .EndChild()
1898 .StartChild("test-device-1")
1899 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001900 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001901 .Property("pages-count", "<16>")
1902 .Property("attributes", "<3>")
1903 .EndChild()
Daniel Boulby4339edc2024-02-21 14:59:00 +00001904 .EndChild()
Daniel Boulby941ef342023-11-21 13:47:15 +00001905 .Build();
1906
1907 /* clang-format on */
1908 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1909 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1910 manifest_dealloc();
1911
1912 /*
Daniel Boulby4339edc2024-02-21 14:59:00 +00001913 * Device regions cannot be defined outside of the regions specified in
1914 * the spmc.
Daniel Boulby941ef342023-11-21 13:47:15 +00001915 */
1916 /* clang-format off */
1917 dtb = ManifestDtBuilder()
1918 .FfaValidManifest()
Daniel Boulby941ef342023-11-21 13:47:15 +00001919 .StartChild("device-regions")
1920 .Compatible({"arm,ffa-manifest-device-regions"})
1921 .StartChild("test-device-0")
1922 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001923 .Property("base-address", "<0x50000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001924 .Property("pages-count", "<16>")
1925 .Property("attributes", "<3>")
1926 .EndChild()
1927 .EndChild()
1928 .Build();
1929 /* clang-format on */
1930 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
Daniel Boulby4339edc2024-02-21 14:59:00 +00001931 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
1932 manifest_dealloc();
1933
1934 /*
1935 * Memory defined as NS in SPMC manifest given Secure attribute should
1936 * fail.
1937 */
1938 /* clang-format off */
1939 dtb = ManifestDtBuilder()
1940 .FfaValidManifest()
1941 .StartChild("device-regions")
1942 .Compatible({"arm,ffa-manifest-device-regions"})
1943 .StartChild("test-device-0")
1944 .Description("test-device-0")
1945 .Property("base-address", "<0x20000000>")
1946 .Property("pages-count", "<16>")
1947 .Property("attributes", "<3>")
1948 .EndChild()
1949 .EndChild()
1950 .Build();
1951 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1952 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
Manish Pandeye68e7932020-04-23 15:29:28 +01001953}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001954
1955TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001956{
Olivier Deprez93644652022-09-09 11:01:12 +02001957 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001958
1959 /* clang-format off */
1960 std::vector<char> dtb = ManifestDtBuilder()
1961 .FfaValidManifest()
1962 .StartChild("rx_tx-info")
1963 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1964 .Property("rx-buffer", "<&rx>")
1965 .Property("tx-buffer", "<&tx>")
1966 .EndChild()
1967 .StartChild("memory-regions")
1968 .Compatible({ "arm,ffa-manifest-memory-regions" })
1969 .StartChild("test-memory")
1970 .Description("test-memory")
1971 .Property("base-address", "<0x7100000>")
1972 .Property("pages-count", "<4>")
1973 .Property("attributes", "<7>")
1974 .EndChild()
1975 .Label("rx")
1976 .StartChild("rx")
1977 .Description("rx-buffer")
1978 .Property("base-address", "<0x7300000>")
1979 .Property("pages-count", "<1>")
1980 .Property("attributes", "<1>")
1981 .EndChild()
1982 .Label("tx")
1983 .StartChild("tx")
1984 .Description("tx-buffer")
1985 .Property("base-address", "<0x7310000>")
1986 .Property("pages-count", "<1>")
1987 .Property("attributes", "<3>")
1988 .EndChild()
1989 .EndChild()
1990 .Build();
1991 /* clang-format on */
1992
1993 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1994 MANIFEST_ERROR_INVALID_MEM_PERM);
1995}
1996
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001997TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001998{
Olivier Deprez93644652022-09-09 11:01:12 +02001999 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07002000
2001 /* clang-format off */
2002 std::vector<char> dtb = ManifestDtBuilder()
2003 .FfaValidManifest()
2004 .StartChild("rx_tx-info")
2005 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
2006 .Property("rx-buffer", "<&rx>")
2007 .Property("tx-buffer", "<&tx>")
2008 .EndChild()
2009 .StartChild("memory-regions")
2010 .Compatible({ "arm,ffa-manifest-memory-regions" })
2011 .StartChild("test-memory")
2012 .Description("test-memory")
2013 .Property("base-address", "<0x7100000>")
2014 .Property("pages-count", "<4>")
2015 .Property("attributes", "<3>")
2016 .EndChild()
2017 .Label("rx")
2018 .StartChild("rx")
2019 .Description("rx-buffer")
2020 .Property("base-address", "<0x7300000>")
2021 .Property("pages-count", "<1>")
2022 .Property("attributes", "<1>")
2023 .EndChild()
2024 .Label("tx")
2025 .StartChild("tx")
2026 .Description("tx-buffer")
2027 .Property("base-address", "<0x7310000>")
2028 .Property("pages-count", "<1>")
2029 .Property("attributes", "<3>")
2030 .EndChild()
2031 .EndChild()
2032 .StartChild("device-regions")
2033 .Compatible({ "arm,ffa-manifest-device-regions" })
2034 .StartChild("test-device")
2035 .Description("test-device")
2036 .Property("base-address", "<0x7200000>")
2037 .Property("pages-count", "<16>")
2038 .Property("attributes", "<5>")
2039 .Property("smmu-id", "<1>")
2040 .Property("stream-ids", "<0 1>")
2041 .Property("interrupts", "<2 3>, <4 5>")
2042 .EndChild()
2043 .EndChild()
2044 .Build();
2045 /* clang-format on */
2046
2047 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2048 MANIFEST_ERROR_INVALID_MEM_PERM);
2049}
Manish Pandeye68e7932020-04-23 15:29:28 +01002050
Daniel Boulby801f8ef2022-06-27 14:21:01 +01002051TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01002052{
Olivier Deprez93644652022-09-09 11:01:12 +02002053 struct manifest_vm *vm;
2054 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01002055
2056 /* clang-format off */
2057 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01002058 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002059 .StartChild("rx_tx-info")
2060 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
2061 .Property("rx-buffer", "<&rx>")
2062 .Property("tx-buffer", "<&tx>")
2063 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01002064 .StartChild("memory-regions")
2065 .Compatible({ "arm,ffa-manifest-memory-regions" })
Olivier Deprez035fa152022-03-14 11:19:10 +01002066 .StartChild("test-memory-ns")
2067 .Description("test-memory")
2068 .Property("base-address", "<0x7200000>")
2069 .Property("pages-count", "<1>")
2070 .Property("attributes", "<0xb>")
2071 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002072 .Label("rx")
2073 .StartChild("rx")
2074 .Description("rx-buffer")
2075 .Property("base-address", "<0x7300000>")
2076 .Property("pages-count", "<1>")
2077 .Property("attributes", "<1>")
2078 .EndChild()
2079 .Label("tx")
2080 .StartChild("tx")
2081 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01002082 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01002083 .Property("pages-count", "<1>")
2084 .Property("attributes", "<3>")
2085 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01002086 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01002087 .StartChild("device-regions")
2088 .Compatible({ "arm,ffa-manifest-device-regions" })
2089 .StartChild("test-device")
2090 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002091 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01002092 .Property("pages-count", "<16>")
2093 .Property("attributes", "<3>")
2094 .Property("smmu-id", "<1>")
2095 .Property("stream-ids", "<0 1>")
2096 .Property("interrupts", "<2 3>, <4 5>")
2097 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01002098 .StartChild("test-device-ns")
2099 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002100 .Property("base-address", "<0x20000000>")
Olivier Deprez035fa152022-03-14 11:19:10 +01002101 .Property("pages-count", "<1>")
2102 .Property("attributes", "<0x9>")
2103 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01002104 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01002105 .Build();
Daniel Boulby4339edc2024-02-21 14:59:00 +00002106
Olivier Deprez62d99e32020-01-09 15:58:07 +01002107 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01002108 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2109
Olivier Deprez93644652022-09-09 11:01:12 +02002110 vm = &m->vm[0];
2111 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01002112 ASSERT_THAT(
Kathleen Capella422b10b2023-06-30 18:28:27 -04002113 std::span(vm->partition.uuids[0].uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01002114 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02002115 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2116 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2117 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2118 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2119 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2120 ASSERT_EQ(vm->partition.boot_order, 0);
2121 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2122 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
Davidson K5d5f2792024-08-19 19:09:12 +05302123 ASSERT_EQ(vm->partition.mem_regions[0].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07002124
Olivier Deprez93644652022-09-09 11:01:12 +02002125 ASSERT_EQ(vm->partition.rxtx.available, true);
2126 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
2127 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
2128 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
2129 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
2130 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
2131 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
2132
Daniel Boulby4339edc2024-02-21 14:59:00 +00002133 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Olivier Deprez93644652022-09-09 11:01:12 +02002134 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002135 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002136 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2137 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2138 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Olivier Deprez93644652022-09-09 11:01:12 +02002139 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2140 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2141 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2142 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
Daniel Boulby4339edc2024-02-21 14:59:00 +00002143 ASSERT_EQ(vm->partition.dev_regions[1].base_address, 0x20000000);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002144 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01002145}
2146
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002147TEST_F(manifest, ffa_valid_interrupt_target_manifest)
2148{
2149 struct manifest_vm *vm;
2150 struct_manifest *m;
2151
2152 /* clang-format off */
2153 std::vector<char> dtb = ManifestDtBuilder()
2154 .FfaValidManifest()
2155 .StartChild("device-regions")
2156 .Compatible({ "arm,ffa-manifest-device-regions" })
2157 .StartChild("test-device")
2158 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002159 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002160 .Property("pages-count", "<16>")
2161 .Property("attributes", "<3>")
2162 .Property("smmu-id", "<1>")
2163 .Property("stream-ids", "<0 1>")
2164 .Property("interrupts", "<2 3>, <4 5>")
2165 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
2166 .EndChild()
2167 .EndChild()
2168 .Build();
2169 /* clang-format on */
2170
2171 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2172
2173 vm = &m->vm[0];
2174
Daniel Boulby4339edc2024-02-21 14:59:00 +00002175 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002176 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002177 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002178 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2179 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2180 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002181 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2182 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2183 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
2184 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
2185 0x123400005678);
2186 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2187 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
2188 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
2189 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
2190 0x1234567887654321);
2191}
2192
2193TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
2194{
2195 struct_manifest *m;
2196
2197 /* clang-format off */
2198 std::vector<char> dtb = ManifestDtBuilder()
2199 .FfaValidManifest()
2200 .StartChild("device-regions")
2201 .Compatible({ "arm,ffa-manifest-device-regions" })
2202 .StartChild("test-device")
2203 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002204 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002205 .Property("pages-count", "<16>")
2206 .Property("attributes", "<3>")
2207 .Property("smmu-id", "<1>")
2208 .Property("stream-ids", "<0 1>")
2209 .Property("interrupts", "<2 3>, <4 5>")
2210 .Property("interrupts-target", "<20 0x1234 0x5678>")
2211 .EndChild()
2212 .EndChild()
2213 .Build();
2214 /* clang-format on */
2215
2216 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2217 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
2218}
2219
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002220TEST_F(manifest, ffa_boot_order_not_unique)
2221{
2222 struct_manifest *m;
2223 struct memiter it;
2224 struct mm_stage1_locked mm_stage1_locked;
2225 struct boot_params params;
2226 Partition_package spkg_1;
2227 Partition_package spkg_2;
2228
2229 /* clang-format off */
2230 std::vector<char> dtb1 = ManifestDtBuilder()
2231 .Compatible({ "arm,ffa-manifest-1.0" })
2232 .Property("ffa-version", "<0x10001>")
2233 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2234 .FfaLoadAddress((uint64_t)&spkg_1)
2235 .Property("execution-ctx-count", "<1>")
2236 .Property("exception-level", "<1>")
2237 .Property("execution-state", "<0>")
2238 .Property("entrypoint-offset", "<0x00002000>")
2239 .Property("xlat-granule", "<0>")
2240 .Property("boot-order", "<1>")
2241 .Property("messaging-method", "<1>")
2242 .Property("ns-interrupts-action", "<0>")
2243 .Build();
2244
2245 std::vector<char> dtb2 = ManifestDtBuilder()
2246 .Compatible({ "arm,ffa-manifest-1.0" })
2247 .Property("ffa-version", "<0x10001>")
2248 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2249 .FfaLoadAddress((uint64_t)&spkg_2)
2250 .Property("execution-ctx-count", "<1>")
2251 .Property("exception-level", "<1>")
2252 .Property("execution-state", "<0>")
2253 .Property("entrypoint-offset", "<0x00002000>")
2254 .Property("xlat-granule", "<0>")
2255 .Property("boot-order", "<1>")
2256 .Property("messaging-method", "<1>")
2257 .Property("ns-interrupts-action", "<0>")
2258 .Build();
2259
2260 /* clang-format on */
2261 spkg_1.init(dtb1);
2262 spkg_2.init(dtb2);
2263
2264 /* clang-format off */
2265 std::vector<char> core_dtb = ManifestDtBuilder()
2266 .StartChild("hypervisor")
2267 .Compatible()
2268 .StartChild("vm1")
2269 .DebugName("ffa_partition_1")
2270 .FfaPartition()
2271 .LoadAddress((uint64_t)&spkg_1)
2272 .VcpuCount(1)
2273 .MemSize(0x10000000)
2274 .EndChild()
2275 .StartChild("vm2")
2276 .DebugName("ffa_partition_2")
2277 .FfaPartition()
2278 .LoadAddress((uint64_t)&spkg_2)
2279 .VcpuCount(1)
2280 .MemSize(0x10000000)
2281 .EndChild()
2282 .EndChild()
2283 .Build();
2284 /* clang-format on */
2285
2286 boot_params_init(&params, nullptr);
2287 memiter_init(&it, core_dtb.data(), core_dtb.size());
2288 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2289 MANIFEST_ERROR_INVALID_BOOT_ORDER);
2290}
Daniel Boulby941ef342023-11-21 13:47:15 +00002291
Kathleen Capella422b10b2023-06-30 18:28:27 -04002292TEST_F(manifest, ffa_valid_multiple_uuids)
2293{
2294 struct manifest_vm *vm;
2295 struct_manifest *m;
2296
2297 /* clang-format off */
2298 std::vector<char> dtb = ManifestDtBuilder()
2299 .Compatible({ "arm,ffa-manifest-1.0" })
2300 .Property("ffa-version", "<0x10002>")
2301 .Property("uuid",
2302 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,\
2303 <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2304 .Property("execution-ctx-count", "<1>")
2305 .Property("exception-level", "<2>")
2306 .Property("execution-state", "<0>")
2307 .Property("entrypoint-offset", "<0x00002000>")
2308 .Property("xlat-granule", "<0>")
2309 .Property("boot-order", "<0>")
2310 .Property("messaging-method", "<4>")
2311 .Property("ns-interrupts-action", "<1>")
2312 .Build();
2313 /* clang-format on */
2314 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2315
2316 vm = &m->vm[0];
2317 ASSERT_EQ(vm->partition.ffa_version, 0x10002);
2318 ASSERT_THAT(
2319 std::span(vm->partition.uuids[0].uuid, 4),
2320 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
2321 ASSERT_THAT(
2322 std::span(vm->partition.uuids[1].uuid, 4),
2323 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1daaa));
2324 ASSERT_EQ(vm->partition.uuid_count, 2);
2325 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2326 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2327 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2328 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2329 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2330 ASSERT_EQ(vm->partition.boot_order, 0);
2331 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2332 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
2333}
Karl Meakin45abeeb2024-08-02 16:55:44 +01002334
2335TEST_F(manifest, ffa_too_many_uuids)
2336{
2337 struct_manifest *m;
2338
2339 /* clang-format off */
2340 std::vector<char> dtb = ManifestDtBuilder()
2341 .Compatible({ "arm,ffa-manifest-1.0" })
2342 .Property("ffa-version", "<0x10002>")
2343 .Property("uuid",
2344 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,"
2345 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2346 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2347 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2348 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2349 .Property("execution-ctx-count", "<1>")
2350 .Property("exception-level", "<2>")
2351 .Property("execution-state", "<0>")
2352 .Property("entrypoint-offset", "<0x00002000>")
2353 .Property("xlat-granule", "<0>")
2354 .Property("boot-order", "<0>")
2355 .Property("messaging-method", "<4>")
2356 .Property("ns-interrupts-action", "<1>")
2357 .Build();
2358 /* clang-format on */
2359 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2360 MANIFEST_ERROR_TOO_MANY_UUIDS);
2361}
2362
Kathleen Capella422b10b2023-06-30 18:28:27 -04002363TEST_F(manifest, ffa_uuid_all_zeros)
2364{
2365 struct_manifest *m;
2366
2367 /* clang-format off */
2368 std::vector<char> dtb = ManifestDtBuilder()
2369 .Compatible({ "arm,ffa-manifest-1.0" })
2370 .Property("ffa-version", "<0x10002>")
2371 .Property("uuid",
2372 "<0x0 0x0 0x0 0x0>, <0x0 0x0 0x0 0x0>")
2373 .Property("execution-ctx-count", "<1>")
2374 .Property("exception-level", "<2>")
2375 .Property("execution-state", "<0>")
2376 .Property("entrypoint-offset", "<0x00002000>")
2377 .Property("xlat-granule", "<0>")
2378 .Property("boot-order", "<0>")
2379 .Property("messaging-method", "<4>")
2380 .Property("ns-interrupts-action", "<1>")
2381 .Build();
2382 /* clang-format on */
2383 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2384 MANIFEST_ERROR_UUID_ALL_ZEROS);
2385}
Daniel Boulby941ef342023-11-21 13:47:15 +00002386
2387/*
2388 * Test that the address space of two device region nodes specified across
2389 * different SPs cannot overlap.
2390 */
2391TEST_F(manifest, ffa_device_region_multi_sps)
2392{
2393 struct_manifest *m;
2394 struct memiter it;
2395 struct mm_stage1_locked mm_stage1_locked;
2396 struct boot_params params;
2397 Partition_package spkg_1;
2398 Partition_package spkg_2;
2399
2400 /* clang-format off */
2401 std::vector<char> dtb1 = ManifestDtBuilder()
2402 .Compatible({ "arm,ffa-manifest-1.0" })
2403 .Property("ffa-version", "<0x10001>")
2404 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2405 .FfaLoadAddress((uint64_t)&spkg_1)
2406 .Property("execution-ctx-count", "<1>")
2407 .Property("exception-level", "<0>")
2408 .Property("execution-state", "<0>")
2409 .Property("entrypoint-offset", "<0x0>")
2410 .Property("xlat-granule", "<0>")
2411 .Property("messaging-method", "<0x7>")
2412 .StartChild("device-regions")
2413 .Compatible({ "arm,ffa-manifest-device-regions" })
2414 .StartChild("test-device-0")
2415 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002416 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002417 .Property("pages-count", "<16>")
2418 .Property("attributes", "<3>")
2419 .EndChild()
2420 .EndChild()
2421 .Build();
2422
2423 std::vector<char> dtb2 = ManifestDtBuilder()
2424 .Compatible({ "arm,ffa-manifest-1.0" })
2425 .Property("ffa-version", "<0x10001>")
2426 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2427 .FfaLoadAddress((uint64_t)&spkg_2)
2428 .Property("execution-ctx-count", "<1>")
2429 .Property("exception-level", "<0>")
2430 .Property("execution-state", "<0>")
2431 .Property("entrypoint-offset", "<0x0>")
2432 .Property("xlat-granule", "<0>")
2433 .Property("messaging-method", "<0x7>")
2434 .StartChild("device-regions")
2435 .Compatible({ "arm,ffa-manifest-device-regions" })
2436 .StartChild("test-device-0")
2437 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002438 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002439 .Property("pages-count", "<16>")
2440 .Property("attributes", "<3>")
2441 .EndChild()
2442 .EndChild()
2443 .Build();
2444
2445 /* clang-format on */
2446 spkg_1.init(dtb1);
2447 spkg_2.init(dtb2);
2448
2449 /* clang-format off */
2450 std::vector<char> core_dtb = ManifestDtBuilder()
2451 .StartChild("hypervisor")
2452 .Compatible()
2453 .StartChild("vm1")
2454 .DebugName("ffa_partition_1")
2455 .FfaPartition()
2456 .LoadAddress((uint64_t)&spkg_1)
2457 .VcpuCount(1)
2458 .MemSize(0x4000)
2459 .EndChild()
2460 .StartChild("vm2")
2461 .DebugName("ffa_partition_2")
2462 .FfaPartition()
2463 .LoadAddress((uint64_t)&spkg_2)
2464 .VcpuCount(1)
2465 .MemSize(0x4000)
2466 .EndChild()
2467 .EndChild()
2468 .Build();
2469 /* clang-format on */
2470 boot_params_init(&params, &spkg_1);
2471 memiter_init(&it, core_dtb.data(), core_dtb.size());
2472 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2473 MANIFEST_ERROR_MEM_REGION_OVERLAP);
2474
2475 manifest_dealloc();
2476
2477 /* clang-format off */
2478 dtb1 = ManifestDtBuilder()
2479 .Compatible({ "arm,ffa-manifest-1.0" })
2480 .Property("ffa-version", "<0x10001>")
2481 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2482 .FfaLoadAddress((uint64_t)&spkg_1)
2483 .Property("execution-ctx-count", "<1>")
2484 .Property("exception-level", "<0>")
2485 .Property("execution-state", "<0>")
2486 .Property("entrypoint-offset", "<0x0>")
2487 .Property("xlat-granule", "<0>")
2488 .Property("messaging-method", "<0x7>")
2489 .StartChild("device-regions")
2490 .Compatible({ "arm,ffa-manifest-device-regions" })
2491 .StartChild("test-device-0")
2492 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002493 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002494 .Property("pages-count", "<16>")
2495 .Property("attributes", "<3>")
2496 .EndChild()
2497 .EndChild()
2498 .Build();
2499
2500 dtb2 = ManifestDtBuilder()
2501 .Compatible({ "arm,ffa-manifest-1.0" })
2502 .Property("ffa-version", "<0x10001>")
2503 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2504 .FfaLoadAddress((uint64_t)&spkg_2)
2505 .Property("execution-ctx-count", "<1>")
2506 .Property("exception-level", "<0>")
2507 .Property("execution-state", "<0>")
2508 .Property("entrypoint-offset", "<0x0>")
2509 .Property("xlat-granule", "<0>")
2510 .Property("messaging-method", "<0x7>")
2511 .StartChild("device-regions")
2512 .Compatible({ "arm,ffa-manifest-device-regions" })
2513 .StartChild("test-device-0")
2514 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002515 .Property("base-address", "<0x25000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002516 .Property("pages-count", "<16>")
2517 .Property("attributes", "<3>")
2518 .EndChild()
2519 .EndChild()
2520 .Build();
2521
2522 /* clang-format on */
2523 spkg_1.init(dtb1);
2524 spkg_2.init(dtb2);
2525
2526 /* clang-format off */
2527 core_dtb = ManifestDtBuilder()
2528 .StartChild("hypervisor")
2529 .Compatible()
2530 .StartChild("vm1")
2531 .DebugName("ffa_partition_1")
2532 .FfaPartition()
2533 .LoadAddress((uint64_t)&spkg_1)
2534 .VcpuCount(1)
2535 .MemSize(0x4000)
2536 .EndChild()
2537 .StartChild("vm2")
2538 .DebugName("ffa_partition_2")
2539 .FfaPartition()
2540 .LoadAddress((uint64_t)&spkg_2)
2541 .VcpuCount(1)
2542 .MemSize(0x4000)
2543 .EndChild()
2544 .EndChild()
2545 .Build();
2546 /* clang-format on */
2547 boot_params_init(&params, &spkg_1);
2548 memiter_init(&it, core_dtb.data(), core_dtb.size());
2549 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2550 MANIFEST_SUCCESS);
2551}
Madhukar Pappireddy99c5eff2024-07-08 15:07:41 -05002552
2553/*
2554 * Tests to trigger various error conditions while parsing dma related
2555 * properties of memory region nodes.
2556 */
2557TEST_F(manifest, ffa_memory_region_invalid_dma_properties)
2558{
2559 struct_manifest *m;
2560
2561 /*
2562 * SMMU ID must be specified if the partition specifies Stream IDs for
2563 * any device upstream of SMMU.
2564 */
2565 /* clang-format off */
2566 std::vector<char> dtb = ManifestDtBuilder()
2567 .FfaValidManifest()
2568 .StartChild("memory-regions")
2569 .Compatible({ "arm,ffa-manifest-memory-regions" })
2570 .StartChild("test-memory")
2571 .Description("test-memory")
2572 .Property("base-address", "<0x7100000>")
2573 .Property("pages-count", "<16>")
2574 .Property("attributes", "<3>")
2575 .Property("stream-ids", "<0 1>")
2576 .Property("interrupts", "<2 3>, <4 5>")
2577 .EndChild()
2578 .EndChild()
2579 .Build();
2580 /* clang-format on */
2581
2582 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2583 MANIFEST_ERROR_MISSING_SMMU_ID);
2584 manifest_dealloc();
2585
2586 /*
2587 * All stream ids belonging to a dma device must specify the same access
2588 * permissions.
2589 */
2590 /* clang-format off */
2591 dtb = ManifestDtBuilder()
2592 .FfaValidManifest()
2593 .StartChild("memory-regions")
2594 .Compatible({ "arm,ffa-manifest-memory-regions" })
2595 .StartChild("test-memory")
2596 .Description("test-memory")
2597 .Property("base-address", "<0x7100000>")
2598 .Property("pages-count", "<16>")
2599 .Property("attributes", "<3>")
2600 .Property("smmu-id", "<1>")
2601 .Property("stream-ids", "<0 1>")
2602 .Property("stream-ids-access-permissions", "<0x3 0xb>")
2603 .Property("interrupts", "<2 3>, <4 5>")
2604 .EndChild()
2605 .EndChild()
2606 .Build();
2607 /* clang-format on */
2608
2609 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2610 MANIFEST_ERROR_MISMATCH_DMA_ACCESS_PERMISSIONS);
2611 manifest_dealloc();
2612
2613 /*
2614 * DMA device stream ID count exceeds predefined limit.
2615 */
2616 /* clang-format off */
2617 dtb = ManifestDtBuilder()
2618 .FfaValidManifest()
2619 .StartChild("memory-regions")
2620 .Compatible({ "arm,ffa-manifest-memory-regions" })
2621 .StartChild("test-memory")
2622 .Description("test-memory")
2623 .Property("base-address", "<0x7100000>")
2624 .Property("pages-count", "<16>")
2625 .Property("attributes", "<3>")
2626 .Property("smmu-id", "<1>")
2627 .Property("stream-ids", "<0 1 4 9 12 >")
2628 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3>")
2629 .EndChild()
2630 .EndChild()
2631 .Build();
2632 /* clang-format on */
2633
2634 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2635 MANIFEST_ERROR_STREAM_IDS_OVERFLOW);
2636 manifest_dealloc();
2637
2638 /*
2639 * DMA access permissions count exceeds predefined limit
2640 */
2641 /* clang-format off */
2642 dtb = ManifestDtBuilder()
2643 .FfaValidManifest()
2644 .StartChild("memory-regions")
2645 .Compatible({ "arm,ffa-manifest-memory-regions" })
2646 .StartChild("test-memory")
2647 .Description("test-memory")
2648 .Property("base-address", "<0x7100000>")
2649 .Property("pages-count", "<16>")
2650 .Property("attributes", "<3>")
2651 .Property("smmu-id", "<1>")
2652 .Property("stream-ids", "<0 1>")
2653 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3 0x3 0x3>")
2654 .EndChild()
2655 .EndChild()
2656 .Build();
2657 /* clang-format on */
2658
2659 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2660 MANIFEST_ERROR_DMA_ACCESS_PERMISSIONS_OVERFLOW);
2661}
2662
2663/*
2664 * Tests to trigger various error conditions while parsing dma related
2665 * properties of device region nodes.
2666 */
2667TEST_F(manifest, ffa_device_region_invalid_dma_properties)
2668{
2669 struct_manifest *m;
2670
2671 /*
2672 * SMMU ID must be specified if the partition specifies Stream IDs for
2673 * any device upstream of SMMU.
2674 */
2675 /* clang-format off */
2676 std::vector<char> dtb = ManifestDtBuilder()
2677 .FfaValidManifest()
2678 .StartChild("device-regions")
2679 .Compatible({ "arm,ffa-manifest-device-regions" })
2680 .StartChild("test-device")
2681 .Description("test-device")
2682 .Property("base-address", "<0x24000000>")
2683 .Property("pages-count", "<16>")
2684 .Property("attributes", "<3>")
2685 .Property("stream-ids", "<0 1>")
2686 .Property("interrupts", "<2 3>, <4 5>")
2687 .EndChild()
2688 .EndChild()
2689 .Build();
2690 /* clang-format on */
2691
2692 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2693 MANIFEST_ERROR_MISSING_SMMU_ID);
2694 manifest_dealloc();
2695
2696 /*
2697 * Dma devices defined through device region nodes exceed predefined
2698 * limit.
2699 */
2700 /* clang-format off */
2701 dtb = ManifestDtBuilder()
2702 .FfaValidManifest()
2703 .StartChild("device-regions")
2704 .Compatible({ "arm,ffa-manifest-device-regions" })
2705 .StartChild("test-device-0")
2706 .Description("test-device-0")
2707 .Property("base-address", "<0x27000000>")
2708 .Property("pages-count", "<16>")
2709 .Property("attributes", "<3>")
2710 .Property("smmu-id", "<1>")
2711 .Property("stream-ids", "<0 1>")
2712 .EndChild()
2713 .StartChild("test-device-1")
2714 .Description("test-device-1")
2715 .Property("base-address", "<0x25000000>")
2716 .Property("pages-count", "<16>")
2717 .Property("attributes", "<3>")
2718 .Property("smmu-id", "<1>")
2719 .Property("stream-ids", "<2 3>")
2720 .EndChild()
2721 .StartChild("test-device-2")
2722 .Description("test-device-2")
2723 .Property("base-address", "<0x26000000>")
2724 .Property("pages-count", "<16>")
2725 .Property("attributes", "<3>")
2726 .Property("smmu-id", "<1>")
2727 .Property("stream-ids", "<4 5>")
2728 .EndChild()
2729 .EndChild()
2730 .Build();
2731 /* clang-format on */
2732
2733 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2734 MANIFEST_ERROR_DMA_DEVICE_OVERFLOW);
2735}
David Brazdil7a462ec2019-08-15 12:27:47 +01002736} /* namespace */