blob: 18d6a3877e8a2943e9e70f0292e62e7534f9ba83 [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
447 enum manifest_return_code ffa_manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200448 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100449 {
450 struct memiter it;
451 struct mm_stage1_locked mm_stage1_locked;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100452 Partition_package spkg(vec);
J-Alves77b6f4f2023-03-15 11:34:49 +0000453 struct boot_params params;
454
455 boot_params_init(&params, &spkg);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100456
457 /* clang-format off */
458 std::vector<char> core_dtb = ManifestDtBuilder()
459 .StartChild("hypervisor")
460 .Compatible()
461 .StartChild("vm1")
462 .DebugName("primary_vm")
463 .FfaPartition()
464 .LoadAddress((uint64_t)&spkg)
465 .EndChild()
466 .EndChild()
467 .Build();
468 /* clang-format on */
469 memiter_init(&it, core_dtb.data(), core_dtb.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100470
J-Alves77b6f4f2023-03-15 11:34:49 +0000471 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100472 }
473};
474
475TEST_F(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100476{
Olivier Deprez93644652022-09-09 11:01:12 +0200477 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100478 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100479
David Brazdila2358d42020-01-27 18:51:38 +0000480 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100481 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
482}
483
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100484TEST_F(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100485{
Olivier Deprez93644652022-09-09 11:01:12 +0200486 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100487
David Brazdil52256ff2019-08-23 15:15:15 +0100488 /* clang-format off */
489 std::vector<char> dtb = ManifestDtBuilder()
490 .StartChild("hypervisor")
491 .EndChild()
492 .Build();
493 /* clang-format on */
494
David Brazdilf4925382020-03-25 13:33:51 +0000495 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100496}
497
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100498TEST_F(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100499{
Olivier Deprez93644652022-09-09 11:01:12 +0200500 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100501
David Brazdil52256ff2019-08-23 15:15:15 +0100502 /* clang-format off */
503 std::vector<char> dtb = ManifestDtBuilder()
504 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100505 .Compatible({ "foo,bar" })
506 .EndChild()
507 .Build();
508 /* clang-format on */
509
David Brazdila2358d42020-01-27 18:51:38 +0000510 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100511}
512
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100513TEST_F(manifest, compatible_one_of_many)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100514{
Olivier Deprez93644652022-09-09 11:01:12 +0200515 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100516
517 /* clang-format off */
518 std::vector<char> dtb = ManifestDtBuilder()
519 .StartChild("hypervisor")
520 .Compatible({ "foo,bar", "hafnium,hafnium" })
521 .StartChild("vm1")
522 .DebugName("primary")
523 .EndChild()
524 .EndChild()
525 .Build();
526 /* clang-format on */
527
David Brazdila2358d42020-01-27 18:51:38 +0000528 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100529}
530
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100531TEST_F(manifest, no_vm_nodes)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100532{
Olivier Deprez93644652022-09-09 11:01:12 +0200533 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100534
535 /* clang-format off */
536 std::vector<char> dtb = ManifestDtBuilder()
537 .StartChild("hypervisor")
538 .Compatible()
539 .EndChild()
540 .Build();
541 /* clang-format on */
542
David Brazdila2358d42020-01-27 18:51:38 +0000543 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100544}
545
546static std::vector<char> gen_long_string_dtb(bool valid)
547{
548 const char last_valid[] = "1234567890123456789012345678901";
549 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100550 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
551 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100552
553 /* clang-format off */
554 return ManifestDtBuilder()
555 .StartChild("hypervisor")
556 .Compatible()
557 .StartChild("vm1")
558 .DebugName(valid ? last_valid : first_invalid)
559 .EndChild()
560 .EndChild()
561 .Build();
562 /* clang-format on */
563}
564
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100565TEST_F(manifest, long_string)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100566{
Olivier Deprez93644652022-09-09 11:01:12 +0200567 struct_manifest *m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100568 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
569 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
570
David Brazdila2358d42020-01-27 18:51:38 +0000571 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200572 manifest_dealloc();
573
David Brazdila2358d42020-01-27 18:51:38 +0000574 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
575 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100576}
577
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100578TEST_F(manifest, reserved_vm_id)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100579{
Olivier Deprez93644652022-09-09 11:01:12 +0200580 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100581
582 /* clang-format off */
583 std::vector<char> dtb = ManifestDtBuilder()
584 .StartChild("hypervisor")
585 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100586 .StartChild("vm1")
587 .DebugName("primary_vm")
588 .EndChild()
589 .StartChild("vm0")
590 .DebugName("reserved_vm")
591 .VcpuCount(1)
592 .MemSize(0x1000)
593 .KernelFilename("kernel")
594 .EndChild()
595 .EndChild()
596 .Build();
597 /* clang-format on */
598
David Brazdila2358d42020-01-27 18:51:38 +0000599 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100600}
601
Andrew Scullae9962e2019-10-03 16:51:16 +0100602static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100603{
604 /* clang-format off */
605 return ManifestDtBuilder()
606 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100607 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100608 .StartChild("vm1")
609 .DebugName("primary_vm")
610 .EndChild()
611 .StartChild("vm2")
612 .DebugName("secondary_vm")
613 .VcpuCount(vcpu_count)
614 .MemSize(0x1000)
615 .KernelFilename("kernel")
616 .EndChild()
617 .EndChild()
618 .Build();
619 /* clang-format on */
620}
David Brazdil7a462ec2019-08-15 12:27:47 +0100621
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100622TEST_F(manifest, vcpu_count_limit)
David Brazdil7a462ec2019-08-15 12:27:47 +0100623{
Olivier Deprez93644652022-09-09 11:01:12 +0200624 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100625 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
626 std::vector<char> dtb_first_invalid =
627 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100628
David Brazdila2358d42020-01-27 18:51:38 +0000629 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200630 ASSERT_EQ(m->vm_count, 2);
631 ASSERT_EQ(m->vm[1].secondary.vcpu_count, UINT16_MAX);
632 manifest_dealloc();
David Brazdil7a462ec2019-08-15 12:27:47 +0100633
David Brazdila2358d42020-01-27 18:51:38 +0000634 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100635 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100636}
637
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100638TEST_F(manifest, no_ramdisk_primary)
David Brazdile6f83222019-09-23 14:47:37 +0100639{
Olivier Deprez93644652022-09-09 11:01:12 +0200640 struct_manifest *m;
David Brazdile6f83222019-09-23 14:47:37 +0100641
642 /* clang-format off */
643 std::vector<char> dtb = ManifestDtBuilder()
644 .StartChild("hypervisor")
645 .Compatible()
646 .StartChild("vm1")
647 .DebugName("primary_vm")
648 .EndChild()
649 .EndChild()
650 .Build();
651 /* clang-format on */
652
David Brazdila2358d42020-01-27 18:51:38 +0000653 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200654 ASSERT_EQ(m->vm_count, 1);
655 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
656 ASSERT_STREQ(string_data(&m->vm[0].primary.ramdisk_filename), "");
David Brazdile6f83222019-09-23 14:47:37 +0100657}
658
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100659TEST_F(manifest, no_boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800660{
Olivier Deprez93644652022-09-09 11:01:12 +0200661 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800662
663 /* clang-format off */
664 std::vector<char> dtb = ManifestDtBuilder()
665 .StartChild("hypervisor")
666 .Compatible()
667 .StartChild("vm1")
668 .DebugName("primary_vm")
669 .EndChild()
670 .EndChild()
671 .Build();
672 /* clang-format on */
673
674 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200675 ASSERT_EQ(m->vm_count, 1);
676 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
677 ASSERT_EQ(m->vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
David Brazdil080ee312020-02-25 15:30:30 -0800678}
679
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100680TEST_F(manifest, boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800681{
Olivier Deprez93644652022-09-09 11:01:12 +0200682 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800683 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
684
685 /* clang-format off */
686 std::vector<char> dtb = ManifestDtBuilder()
687 .StartChild("hypervisor")
688 .Compatible()
689 .StartChild("vm1")
690 .DebugName("primary_vm")
691 .BootAddress(addr)
692 .EndChild()
693 .EndChild()
694 .Build();
695 /* clang-format on */
696
697 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200698 ASSERT_EQ(m->vm_count, 1);
699 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
700 ASSERT_EQ(m->vm[0].primary.boot_address, addr);
David Brazdil080ee312020-02-25 15:30:30 -0800701}
702
Andrew Scullb2c3a242019-11-04 13:52:36 +0000703static std::vector<char> gen_malformed_boolean_dtb(
704 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100705{
Andrew Scullae9962e2019-10-03 16:51:16 +0100706 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000707 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100708 .StartChild("hypervisor")
709 .Compatible()
710 .StartChild("vm1")
711 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000712 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000713 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100714 .EndChild()
715 .Build();
716 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000717}
Andrew Scullae9962e2019-10-03 16:51:16 +0100718
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100719TEST_F(manifest, malformed_booleans)
Andrew Scullb2c3a242019-11-04 13:52:36 +0000720{
Olivier Deprez93644652022-09-09 11:01:12 +0200721 struct_manifest *m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100722
Andrew Scullb2c3a242019-11-04 13:52:36 +0000723 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
724 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
725 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
726 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100727
David Brazdila2358d42020-01-27 18:51:38 +0000728 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000729 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200730 manifest_dealloc();
731
David Brazdila2358d42020-01-27 18:51:38 +0000732 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000733 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200734 manifest_dealloc();
735
David Brazdila2358d42020-01-27 18:51:38 +0000736 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000737 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200738 manifest_dealloc();
739
David Brazdila2358d42020-01-27 18:51:38 +0000740 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000741 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100742}
743
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100744TEST_F(manifest, valid)
David Brazdil7a462ec2019-08-15 12:27:47 +0100745{
Olivier Deprez93644652022-09-09 11:01:12 +0200746 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100747 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100748
David Brazdil52256ff2019-08-23 15:15:15 +0100749 /* clang-format off */
750 std::vector<char> dtb = ManifestDtBuilder()
751 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100752 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100753 .StartChild("vm1")
754 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100755 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100756 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100757 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100758 .EndChild()
759 .StartChild("vm3")
760 .DebugName("second_secondary_vm")
761 .VcpuCount(43)
762 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100763 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100764 .EndChild()
765 .StartChild("vm2")
766 .DebugName("first_secondary_vm")
767 .VcpuCount(42)
768 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100769 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
770 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100771 .EndChild()
772 .EndChild()
773 .Build();
774 /* clang-format on */
775
David Brazdila2358d42020-01-27 18:51:38 +0000776 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200777 ASSERT_EQ(m->vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100778
Olivier Deprez93644652022-09-09 11:01:12 +0200779 vm = &m->vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100780 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
781 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100782 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
783 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100784 ASSERT_THAT(
785 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
786 ElementsAre(0x32000000, 0x33001111));
787 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100788
Olivier Deprez93644652022-09-09 11:01:12 +0200789 vm = &m->vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100790 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
791 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100792 ASSERT_EQ(vm->secondary.vcpu_count, 42);
793 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100794 ASSERT_THAT(
795 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
796 ElementsAre(0x04000000, 0x30002222, 0x31445566));
797 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100798
Olivier Deprez93644652022-09-09 11:01:12 +0200799 vm = &m->vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100800 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
801 ASSERT_STREQ(string_data(&vm->kernel_filename),
802 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100803 ASSERT_EQ(vm->secondary.vcpu_count, 43);
804 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100805 ASSERT_THAT(
806 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
807 IsEmpty());
808 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100809}
810
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100811TEST_F(manifest, ffa_not_compatible)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100812{
Olivier Deprez93644652022-09-09 11:01:12 +0200813 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100814
815 /* clang-format off */
816 std::vector<char> dtb = ManifestDtBuilder()
817 .Compatible({ "arm,ffa-manifest-2.0" })
818 .Property("ffa-version", "<0x10000>")
819 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
820 .Property("execution-ctx-count", "<1>")
821 .Property("exception-level", "<2>")
822 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000823 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100824 .Property("xlat-granule", "<0>")
825 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500826 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100827 .Build();
828 /* clang-format on */
829
830 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
831 MANIFEST_ERROR_NOT_COMPATIBLE);
832}
833
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100834TEST_F(manifest, ffa_missing_property)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100835{
Olivier Deprez93644652022-09-09 11:01:12 +0200836 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100837
838 /* clang-format off */
839 std::vector<char> dtb = ManifestDtBuilder()
840 .Compatible({ "arm,ffa-manifest-1.0" })
841 .Property("ffa-version", "<0x10000>")
842 .Build();
843 /* clang-format on */
844
845 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
846 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
847}
848
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100849TEST_F(manifest, ffa_validate_sanity_check)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100850{
J-Alvesb37fd082020-10-22 12:29:21 +0100851 /*
852 * TODO: write test excluding all optional fields of the manifest, in
853 * accordance with specification.
854 */
Olivier Deprez93644652022-09-09 11:01:12 +0200855 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100856
857 /* Incompatible version */
858 /* clang-format off */
859 std::vector<char> dtb = ManifestDtBuilder()
860 .Compatible({ "arm,ffa-manifest-1.0" })
861 .Property("ffa-version", "<0xa1>")
862 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
863 .Property("execution-ctx-count", "<1>")
864 .Property("exception-level", "<2>")
865 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000866 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100867 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100868 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100869 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500870 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100871 .Build();
872 /* clang-format on */
873 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
874 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200875 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100876
877 /* Incompatible translation granule */
878 /* clang-format off */
879 dtb = ManifestDtBuilder()
880 .Compatible({ "arm,ffa-manifest-1.0" })
881 .Property("ffa-version", "<0x10000>")
882 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
883 .Property("execution-ctx-count", "<1>")
884 .Property("exception-level", "<2>")
885 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000886 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100887 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100888 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100889 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500890 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100891 .Build();
892 /* clang-format on */
893 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
894 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200895 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100896
897 /* Incompatible exeption level */
898 /* clang-format off */
899 dtb = ManifestDtBuilder()
900 .Compatible({ "arm,ffa-manifest-1.0" })
901 .Property("ffa-version", "<0x10000>")
902 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
903 .Property("execution-ctx-count", "<1>")
Daniel Boulby874d5432023-04-27 12:40:24 +0100904 .Property("exception-level", "<10>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100905 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000906 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100907 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100908 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100909 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500910 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100911 .Build();
912 /* clang-format on */
913 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
914 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200915 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100916
917 /* Incompatible execution state */
918 /* clang-format off */
919 dtb = ManifestDtBuilder()
920 .Compatible({ "arm,ffa-manifest-1.0" })
921 .Property("ffa-version", "<0x10000>")
922 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
923 .Property("execution-ctx-count", "<1>")
924 .Property("exception-level", "<2>")
925 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000926 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100927 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100928 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100929 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500930 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100931 .Build();
932 /* clang-format on */
933 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
934 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200935 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100936
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400937 /* Incompatible messaging method - unrecognized messaging-method. */
938 /* clang-format off */
939 dtb = ManifestDtBuilder()
940 .Compatible({ "arm,ffa-manifest-1.0" })
941 .Property("ffa-version", "<0x10002>")
942 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
943 .Property("execution-ctx-count", "<1>")
944 .Property("exception-level", "<2>")
945 .Property("execution-state", "<0>")
946 .Property("entrypoint-offset", "<0x00002000>")
947 .Property("xlat-granule", "<0>")
948 .Property("boot-order", "<0>")
949 .Property("messaging-method", "<0x272>")
950 .Property("ns-interrupts-action", "<0>")
951 .Build();
952 /* clang-format on */
953 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
954 MANIFEST_ERROR_NOT_COMPATIBLE);
955 manifest_dealloc();
956
957 /* Incompatible messaging method - only endpoints using FF-A version >=
958 * FF-A v1.2 are allowed to set FFA_PARTITION_DIRECT_REQ2_RECV and
959 * FFA_PARTITION_DIRECT_REQ2_SEND. */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100960 /* clang-format off */
961 dtb = ManifestDtBuilder()
962 .Compatible({ "arm,ffa-manifest-1.0" })
963 .Property("ffa-version", "<0x10000>")
964 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
965 .Property("execution-ctx-count", "<1>")
966 .Property("exception-level", "<2>")
967 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000968 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100969 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100970 .Property("boot-order", "<0>")
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400971 .Property("messaging-method", "<0x204>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500972 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100973 .Build();
974 /* clang-format on */
975 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
976 MANIFEST_ERROR_NOT_COMPATIBLE);
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600977
978 /*
979 * No need to invoke manifest_dealloac() since manifest TearDown calls
980 * it when the test ends.
981 */
982}
983
984TEST_F(manifest, ffa_validate_interrupt_actions)
985{
986 struct_manifest *m;
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500987
988 /* Incompatible NS interrupt action */
989 /* clang-format off */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600990 std::vector<char> dtb = ManifestDtBuilder()
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500991 .Compatible({ "arm,ffa-manifest-1.0" })
992 .Property("ffa-version", "<0x10000>")
993 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
994 .Property("execution-ctx-count", "<1>")
995 .Property("exception-level", "<2>")
996 .Property("execution-state", "<0>")
997 .Property("entrypoint-offset", "<0x00002000>")
998 .Property("xlat-granule", "<0>")
999 .Property("boot-order", "<0>")
1000 .Property("messaging-method", "<1>")
1001 .Property("ns-interrupts-action", "<4>")
1002 .Build();
1003 /* clang-format on */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -06001004 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1005 MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
Madhukar Pappireddyee736ad2022-12-28 11:37:09 -06001006 manifest_dealloc();
1007
1008 /* Incompatible other-s-interrupts-action for S-EL1 partition */
1009 /* clang-format off */
1010 dtb = ManifestDtBuilder()
1011 .Compatible({ "arm,ffa-manifest-1.0" })
1012 .Property("ffa-version", "<0x10000>")
1013 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1014 .Property("execution-ctx-count", "<1>")
1015 .Property("exception-level", "<2>")
1016 .Property("execution-state", "<0>")
1017 .Property("entrypoint-offset", "<0x00002000>")
1018 .Property("xlat-granule", "<0>")
1019 .Property("boot-order", "<0>")
1020 .Property("messaging-method", "<1>")
1021 .Property("ns-interrupts-action", "<1>")
1022 .Property("other-s-interrupts-action", "<0>")
1023 .Build();
1024 /* clang-format on */
1025 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1026 MANIFEST_ERROR_NOT_COMPATIBLE);
1027 manifest_dealloc();
1028
1029 /*
1030 * Incompatible choice of the fields ns-interrupts-action and
1031 * other-s-interrupts-action.
1032 */
1033 /* clang-format off */
1034 dtb = ManifestDtBuilder()
1035 .Compatible({ "arm,ffa-manifest-1.0" })
1036 .Property("ffa-version", "<0x10000>")
1037 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1038 .Property("execution-ctx-count", "<1>")
1039 .Property("exception-level", "<1>")
1040 .Property("execution-state", "<0>")
1041 .Property("entrypoint-offset", "<0x00002000>")
1042 .Property("xlat-granule", "<0>")
1043 .Property("boot-order", "<0>")
1044 .Property("messaging-method", "<1>")
1045 .Property("ns-interrupts-action", "<2>")
1046 .Property("other-s-interrupts-action", "<0>")
1047 .Build();
1048 /* clang-format on */
1049 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1050 MANIFEST_ERROR_NOT_COMPATIBLE);
1051 manifest_dealloc();
1052
1053 /* Illegal value specified for the field other-s-interrupts-action. */
1054 /* clang-format off */
1055 dtb = ManifestDtBuilder()
1056 .Compatible({ "arm,ffa-manifest-1.0" })
1057 .Property("ffa-version", "<0x10000>")
1058 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1059 .Property("execution-ctx-count", "<1>")
1060 .Property("exception-level", "<1>")
1061 .Property("execution-state", "<0>")
1062 .Property("entrypoint-offset", "<0x00002000>")
1063 .Property("xlat-granule", "<0>")
1064 .Property("boot-order", "<0>")
1065 .Property("messaging-method", "<1>")
1066 .Property("other-s-interrupts-action", "<2>")
1067 .Build();
1068 /* clang-format on */
1069 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1070 MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001071}
1072
Karl Meakin18694022024-08-02 13:59:25 +01001073TEST_F(manifest, vm_availability_messages)
1074{
1075 struct manifest_vm *vm;
1076 struct_manifest *m;
1077 std::vector<char> dtb;
1078
1079 /* clang-format off */
1080 dtb = ManifestDtBuilder()
1081 .Compatible({ "arm,ffa-manifest-1.0" })
1082 .Property("ffa-version", "<0x10001>")
1083 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1084 .Property("execution-ctx-count", "<8>")
1085 .Property("exception-level", "<2>")
1086 .Property("execution-state", "<0>")
1087 .Property("entrypoint-offset", "<0x00002000>")
1088 .Property("messaging-method", "<1>")
1089 .Property("vm-availability-messages", "<0>")
1090 .Build();
1091 /* clang-format on */
1092 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1093 vm = &m->vm[0];
1094 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1095 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1096 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1097 manifest_dealloc();
1098
1099 /* clang-format off */
1100 dtb = ManifestDtBuilder()
1101 .Compatible({ "arm,ffa-manifest-1.0" })
1102 .Property("ffa-version", "<0x10001>")
1103 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1104 .Property("execution-ctx-count", "<8>")
1105 .Property("exception-level", "<2>")
1106 .Property("execution-state", "<0>")
1107 .Property("entrypoint-offset", "<0x00002000>")
1108 .Property("messaging-method", "<1>")
1109 .Property("vm-availability-messages", "<1>")
1110 .Build();
1111 /* clang-format on */
1112 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1113 vm = &m->vm[0];
1114 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1115 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1116 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1117 manifest_dealloc();
1118
1119 /* clang-format off */
1120 dtb = ManifestDtBuilder()
1121 .Compatible({ "arm,ffa-manifest-1.0" })
1122 .Property("ffa-version", "<0x10001>")
1123 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1124 .Property("execution-ctx-count", "<8>")
1125 .Property("exception-level", "<2>")
1126 .Property("execution-state", "<0>")
1127 .Property("entrypoint-offset", "<0x00002000>")
1128 .Property("messaging-method", "<1>")
1129 .Property("vm-availability-messages", "<2>")
1130 .Build();
1131 /* clang-format on */
1132 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1133 vm = &m->vm[0];
1134 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1135 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1136 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1137 manifest_dealloc();
1138
1139 /* clang-format off */
1140 dtb = ManifestDtBuilder()
1141 .Compatible({ "arm,ffa-manifest-1.0" })
1142 .Property("ffa-version", "<0x10001>")
1143 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1144 .Property("execution-ctx-count", "<8>")
1145 .Property("exception-level", "<2>")
1146 .Property("execution-state", "<0>")
1147 .Property("entrypoint-offset", "<0x00002000>")
1148 .Property("messaging-method", "<1>")
1149 .Property("vm-availability-messages", "<3>")
1150 .Build();
1151 /* clang-format on */
1152 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1153 vm = &m->vm[0];
1154 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1155 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1156 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1157 manifest_dealloc();
1158
1159 /* clang-format off */
1160 dtb = ManifestDtBuilder()
1161 .Compatible({ "arm,ffa-manifest-1.0" })
1162 .Property("ffa-version", "<0x10001>")
1163 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1164 .Property("execution-ctx-count", "<8>")
1165 .Property("exception-level", "<2>")
1166 .Property("execution-state", "<0>")
1167 .Property("entrypoint-offset", "<0x00002000>")
1168 .Property("messaging-method", "<1>")
1169 .Build();
1170 /* clang-format on */
1171 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1172 vm = &m->vm[0];
1173 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1174 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1175 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1176 manifest_dealloc();
1177
1178 /* clang-format off */
1179 dtb = ManifestDtBuilder()
1180 .Compatible({ "arm,ffa-manifest-1.0" })
1181 .Property("ffa-version", "<0x10001>")
1182 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1183 .Property("execution-ctx-count", "<8>")
1184 .Property("exception-level", "<2>")
1185 .Property("execution-state", "<0>")
1186 .Property("entrypoint-offset", "<0x00002000>")
1187 .Property("messaging-method", "<2>")
1188 .Property("vm-availability-messages", "<4>")
1189 .Build();
1190 /* clang-format on */
1191 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1192 MANIFEST_ERROR_VM_AVAILABILITY_MESSAGE_INVALID);
1193 vm = &m->vm[0];
1194 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1195 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1196 ASSERT_NE(vm->partition.vm_availability_messages.mbz, 0);
1197 manifest_dealloc();
1198}
1199
Olivier Depreza15f2352022-09-26 09:17:24 +02001200TEST_F(manifest, power_management)
1201{
1202 struct manifest_vm *vm;
1203 struct_manifest *m;
1204
1205 /* S-EL1 partition power management field can set bit 0. */
1206 /* clang-format off */
1207 std::vector<char> dtb = ManifestDtBuilder()
1208 .Compatible({ "arm,ffa-manifest-1.0" })
1209 .Property("ffa-version", "<0x10001>")
1210 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1211 .Property("execution-ctx-count", "<8>")
1212 .Property("exception-level", "<2>")
1213 .Property("execution-state", "<0>")
1214 .Property("entrypoint-offset", "<0x00002000>")
1215 .Property("messaging-method", "<1>")
1216 .Property("power-management-messages", "<1>")
1217 .Build();
1218 /* clang-format on */
1219 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1220 vm = &m->vm[0];
1221 ASSERT_EQ(vm->partition.power_management, 1);
1222 manifest_dealloc();
1223
1224 /* S-EL1 partition power management field can set bit 3. */
1225 /* clang-format off */
1226 dtb = ManifestDtBuilder()
1227 .Compatible({ "arm,ffa-manifest-1.0" })
1228 .Property("ffa-version", "<0x10001>")
1229 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1230 .Property("execution-ctx-count", "<8>")
1231 .Property("exception-level", "<2>")
1232 .Property("execution-state", "<0>")
1233 .Property("entrypoint-offset", "<0x00002000>")
1234 .Property("messaging-method", "<1>")
1235 .Property("power-management-messages", "<8>")
1236 .Build();
1237 /* clang-format on */
1238 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1239 vm = &m->vm[0];
1240 ASSERT_EQ(vm->partition.power_management, 8);
1241 manifest_dealloc();
1242
1243 /* S-EL1 partition power management field can only set bits 0 and 3. */
1244 /* clang-format off */
1245 dtb = ManifestDtBuilder()
1246 .Compatible({ "arm,ffa-manifest-1.0" })
1247 .Property("ffa-version", "<0x10001>")
1248 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1249 .Property("execution-ctx-count", "<8>")
1250 .Property("exception-level", "<2>")
1251 .Property("execution-state", "<0>")
1252 .Property("entrypoint-offset", "<0x00002000>")
1253 .Property("messaging-method", "<1>")
1254 .Property("power-management-messages", "<0xf>")
1255 .Build();
1256 /* clang-format on */
1257 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1258 vm = &m->vm[0];
1259 ASSERT_EQ(vm->partition.power_management, 9);
1260 manifest_dealloc();
1261
1262 /* S-EL0 partition power management field is forced to 0. */
1263 /* clang-format off */
1264 dtb = ManifestDtBuilder()
1265 .Compatible({ "arm,ffa-manifest-1.0" })
1266 .Property("ffa-version", "<0x10001>")
1267 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1268 .Property("execution-ctx-count", "<1>")
1269 .Property("exception-level", "<1>")
1270 .Property("execution-state", "<0>")
1271 .Property("entrypoint-offset", "<0x00002000>")
1272 .Property("messaging-method", "<1>")
1273 .Property("power-management-messages", "<0xff>")
1274 .Build();
1275 /* clang-format on */
1276 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1277 vm = &m->vm[0];
1278 ASSERT_EQ(vm->partition.power_management, 0);
1279}
1280
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001281TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001282{
Olivier Deprez93644652022-09-09 11:01:12 +02001283 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001284
1285 /* Not Compatible */
1286 /* clang-format off */
1287 std::vector<char> dtb = ManifestDtBuilder()
1288 .FfaValidManifest()
1289 .StartChild("rx_tx-info")
1290 .Compatible({ "foo,bar" })
1291 .EndChild()
1292 .Build();
1293 /* clang-format on */
1294 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1295 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001296 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001297
1298 /* Missing Properties */
1299 /* clang-format off */
1300 dtb = ManifestDtBuilder()
1301 .FfaValidManifest()
1302 .StartChild("rx_tx-info")
1303 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1304 .EndChild()
1305 .Build();
1306 /* clang-format on */
1307 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1308 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1309}
1310
Karl Meakinf955dbe2024-11-18 16:38:58 +00001311TEST_F(manifest, ffa_validate_mem_regions_not_compatible)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001312{
Olivier Deprez93644652022-09-09 11:01:12 +02001313 struct_manifest *m;
Karl Meakinf955dbe2024-11-18 16:38:58 +00001314 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001315
1316 /* Not Compatible */
1317 /* clang-format off */
Karl Meakinf955dbe2024-11-18 16:38:58 +00001318 dtb = ManifestDtBuilder()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001319 .FfaValidManifest()
1320 .StartChild("memory-regions")
1321 .Compatible({ "foo,bar" })
1322 .EndChild()
1323 .Build();
1324 /* clang-format on */
1325 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1326 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001327 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001328}
1329
1330TEST_F(manifest, ffa_validate_mem_regions_unavailable)
1331{
1332 struct_manifest *m;
1333 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001334
1335 /* Memory regions unavailable */
1336 /* clang-format off */
1337 dtb = ManifestDtBuilder()
1338 .FfaValidManifest()
1339 .StartChild("memory-regions")
1340 .Compatible({ "arm,ffa-manifest-memory-regions" })
1341 .EndChild()
1342 .Build();
1343 /* clang-format on */
1344 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1345 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001346 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001347}
1348
1349TEST_F(manifest, ffa_validate_mem_regions_missing_properties)
1350{
1351 struct_manifest *m;
1352 std::vector<char> dtb;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001353
1354 /* Missing Properties */
1355 /* clang-format off */
1356 dtb = ManifestDtBuilder()
1357 .FfaValidManifest()
1358 .StartChild("memory-regions")
1359 .Compatible({ "arm,ffa-manifest-memory-regions" })
1360 .StartChild("test-memory")
1361 .Description("test-memory")
1362 .EndChild()
1363 .EndChild()
1364 .Build();
1365 /* clang-format on */
1366 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1367 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001368 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001369}
1370
1371TEST_F(manifest, ffa_validate_mem_regions_empty_region)
1372{
1373 struct_manifest *m;
1374 std::vector<char> dtb;
Manish Pandeyf06c9072020-09-29 15:41:58 +01001375
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001376 /* Empty memory region */
1377 /* clang-format off */
1378 dtb = ManifestDtBuilder()
1379 .FfaValidManifest()
1380 .StartChild("memory-regions")
1381 .Compatible({ "arm,ffa-manifest-memory-regions" })
1382 .Label("rx")
1383 .StartChild("rx")
1384 .Description("rx-buffer")
1385 .Property("base-address", "<0x7300000>")
1386 .Property("pages-count", "<0>")
1387 .Property("attributes", "<1>")
1388 .EndChild()
1389 .Label("tx")
1390 .StartChild("tx")
1391 .Description("tx-buffer")
1392 .Property("base-address", "<0x7310000>")
1393 .Property("pages-count", "<2>")
1394 .Property("attributes", "<3>")
1395 .EndChild()
1396 .EndChild()
1397 .StartChild("rx_tx-info")
1398 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1399 .Property("rx-buffer", "<&rx>")
1400 .Property("tx-buffer", "<&tx>")
1401 .EndChild()
1402 .Build();
1403 /* clang-format on */
1404 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1405 MANIFEST_ERROR_MEM_REGION_EMPTY);
1406 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001407}
1408
1409TEST_F(manifest, ffa_validate_mem_regions_base_address_and_relative_offset)
1410{
1411 struct_manifest *m;
1412 std::vector<char> dtb;
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001413
Davidson K8ccd2d02024-09-03 16:10:54 +05301414 /* Mutually exclusive base-address and load-address-relative-offset
1415 * properties */
Karl Meakine92efbe2023-06-01 14:16:22 +01001416 /* clang-format off */
1417 dtb = ManifestDtBuilder()
1418 .FfaValidManifest()
1419 .StartChild("memory-regions")
1420 .Compatible({ "arm,ffa-manifest-memory-regions" })
1421 .Label("rx")
1422 .StartChild("rx")
1423 .Description("rx-buffer")
1424 .Property("base-address", "<0x7300000>")
Davidson K8ccd2d02024-09-03 16:10:54 +05301425 .Property("load-address-relative-offset", "<0x7300000>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001426 .Property("pages-count", "<1>")
1427 .Property("attributes", "<1>")
1428 .EndChild()
1429 .EndChild()
1430 .Build();
1431 /* clang-format on */
1432 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1433 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1434 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001435}
1436
1437TEST_F(manifest, ffa_validate_mem_regions_relative_address_overflow)
1438{
1439 struct_manifest *m;
1440 std::vector<char> dtb;
1441
Karl Meakine92efbe2023-06-01 14:16:22 +01001442 /* Relative-address overflow*/
1443 /* clang-format off */
1444 dtb = ManifestDtBuilder()
1445 .FfaValidManifest()
1446 .Property("load-address", "<0xffffff00 0xffffff00>")
1447 .StartChild("memory-regions")
1448 .Compatible({ "arm,ffa-manifest-memory-regions" })
1449 .Label("rx")
1450 .StartChild("rx")
1451 .Description("rx-buffer")
Davidson K8ccd2d02024-09-03 16:10:54 +05301452 .Property("load-address-relative-offset", "<0xffffff00 0xffffff00>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001453 .Property("pages-count", "<1>")
1454 .Property("attributes", "<1>")
1455 .EndChild()
1456 .EndChild()
1457 .Build();
1458 /* clang-format on */
1459 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1460 MANIFEST_ERROR_INTEGER_OVERFLOW);
1461 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001462}
1463
1464TEST_F(manifest, ffa_validate_mem_regions_relative_offset_valid)
1465{
1466 struct_manifest *m;
1467 std::vector<char> dtb;
1468
1469 /* valid relative offset */
1470 /* clang-format off */
1471 dtb = ManifestDtBuilder()
1472 .FfaValidManifest()
1473 .Property("load-address", "<0xffffff00 0xffffff00>")
1474 .StartChild("memory-regions")
1475 .Compatible({ "arm,ffa-manifest-memory-regions" })
1476 .Label("rx")
1477 .StartChild("rx")
1478 .Description("rx-buffer")
1479 .Property("load-address-relative-offset", "<0x1000>")
1480 .Property("pages-count", "<1>")
1481 .Property("attributes", "<1>")
1482 .EndChild()
1483 .EndChild()
1484 .Build();
1485 /* clang-format on */
1486 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1487 manifest_dealloc();
1488}
1489
1490TEST_F(manifest, ffa_validate_mem_regions_overlapping)
1491{
1492 struct_manifest *m;
1493 std::vector<char> dtb;
Karl Meakine92efbe2023-06-01 14:16:22 +01001494
Daniel Boulby9279b552022-06-28 17:04:01 +01001495 /* Overlapping memory regions */
1496 /* clang-format off */
1497 dtb = ManifestDtBuilder()
1498 .FfaValidManifest()
1499 .StartChild("memory-regions")
1500 .Compatible({ "arm,ffa-manifest-memory-regions" })
1501 .Label("rx")
1502 .StartChild("rx")
1503 .Description("rx-buffer")
1504 .Property("base-address", "<0x7300000>")
1505 .Property("pages-count", "<1>")
1506 .Property("attributes", "<1>")
1507 .EndChild()
1508 .Label("tx")
1509 .StartChild("tx")
1510 .Description("tx-buffer")
1511 .Property("base-address", "<0x7300000>")
1512 .Property("pages-count", "<2>")
1513 .Property("attributes", "<3>")
1514 .EndChild()
1515 .EndChild()
1516 .Build();
1517 /* clang-format on */
1518 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1519 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001520 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001521
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", "<2>")
1532 .Property("attributes", "<1>")
1533 .EndChild()
1534 .Label("tx")
1535 .StartChild("tx")
1536 .Description("tx-buffer")
1537 .Property("base-address", "<0x7301000>")
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")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001556 .Property("base-address", "<0x7301000>")
1557 .Property("pages-count", "<1>")
1558 .Property("attributes", "<1>")
1559 .EndChild()
1560 .Label("tx")
1561 .StartChild("tx")
1562 .Description("tx-buffer")
1563 .Property("base-address", "<0x7300000>")
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);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001572 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001573}
1574
1575TEST_F(manifest, ffa_validate_mem_regions_unaligned)
1576{
1577 struct_manifest *m;
1578 std::vector<char> dtb;
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001579
1580 /* Unaligned memory region */
1581 /* clang-format off */
1582 dtb = ManifestDtBuilder()
1583 .FfaValidManifest()
1584 .StartChild("memory-regions")
1585 .Compatible({ "arm,ffa-manifest-memory-regions" })
1586 .Label("rx")
1587 .StartChild("rx")
1588 .Description("rx-buffer")
1589 .Property("base-address", "<0x7300FFF>")
1590 .Property("pages-count", "<2>")
1591 .Property("attributes", "<1>")
1592 .EndChild()
1593 .Label("tx")
1594 .StartChild("tx")
1595 .Description("tx-buffer")
1596 .Property("base-address", "<0x7303000>")
1597 .Property("pages-count", "<2>")
1598 .Property("attributes", "<3>")
1599 .EndChild()
1600 .EndChild()
1601 .Build();
1602 /* clang-format on */
1603 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1604 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1605 manifest_dealloc();
Karl Meakinf955dbe2024-11-18 16:38:58 +00001606}
1607
1608TEST_F(manifest, ffa_validate_mem_regions_different_rxtx_sizes)
1609{
1610 struct_manifest *m;
1611 std::vector<char> dtb;
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001612
Manish Pandeyf06c9072020-09-29 15:41:58 +01001613 /* Different RXTX buffer sizes */
1614 /* clang-format off */
1615 dtb = ManifestDtBuilder()
1616 .FfaValidManifest()
1617 .StartChild("memory-regions")
1618 .Compatible({ "arm,ffa-manifest-memory-regions" })
1619 .Label("rx")
1620 .StartChild("rx")
1621 .Description("rx-buffer")
1622 .Property("base-address", "<0x7300000>")
1623 .Property("pages-count", "<1>")
1624 .Property("attributes", "<1>")
1625 .EndChild()
1626 .Label("tx")
1627 .StartChild("tx")
1628 .Description("tx-buffer")
1629 .Property("base-address", "<0x7310000>")
1630 .Property("pages-count", "<2>")
1631 .Property("attributes", "<3>")
1632 .EndChild()
1633 .EndChild()
1634 .StartChild("rx_tx-info")
1635 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1636 .Property("rx-buffer", "<&rx>")
1637 .Property("tx-buffer", "<&tx>")
1638 .EndChild()
1639 .Build();
1640 /* clang-format on */
1641 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1642 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001643}
1644
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001645TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001646{
Olivier Deprez93644652022-09-09 11:01:12 +02001647 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001648
1649 /* Not Compatible */
1650 /* clang-format off */
1651 std::vector<char> dtb = ManifestDtBuilder()
1652 .FfaValidManifest()
1653 .StartChild("device-regions")
1654 .Compatible({ "foo,bar" })
1655 .EndChild()
1656 .Build();
1657 /* clang-format on */
1658 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1659 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001660 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001661
1662 /* Memory regions unavailable */
1663 /* clang-format off */
1664 dtb = ManifestDtBuilder()
1665 .FfaValidManifest()
1666 .StartChild("device-regions")
1667 .Compatible({ "arm,ffa-manifest-device-regions" })
1668 .EndChild()
1669 .Build();
1670 /* clang-format on */
1671 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1672 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001673 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001674
1675 /* Missing Properties */
1676 /* clang-format off */
1677 dtb = ManifestDtBuilder()
1678 .FfaValidManifest()
1679 .StartChild("device-regions")
1680 .Compatible({ "arm,ffa-manifest-device-regions" })
1681 .StartChild("test-device")
1682 .Description("test-device")
1683 .EndChild()
1684 .EndChild()
1685 .Build();
1686 /* clang-format on */
1687 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1688 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001689 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001690
1691 /* Malformed interrupt list pair */
1692 /* clang-format off */
1693 dtb = ManifestDtBuilder()
1694 .FfaValidManifest()
1695 .StartChild("device-regions")
1696 .Compatible({ "arm,ffa-manifest-device-regions" })
1697 .StartChild("test-device")
1698 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001699 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001700 .Property("pages-count", "<16>")
1701 .Property("attributes", "<3>")
1702 .Property("smmu-id", "<1>")
1703 .Property("stream-ids", "<0 1>")
1704 .Property("interrupts", "<2 3>, <4>")
1705 .EndChild()
1706 .EndChild()
1707 .Build();
1708 /* clang-format on */
1709 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1710 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001711 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001712
1713 /* Non-unique interrupt IDs */
1714 /* clang-format off */
1715 dtb = ManifestDtBuilder()
1716 .FfaValidManifest()
1717 .StartChild("device-regions")
1718 .Compatible({ "arm,ffa-manifest-device-regions" })
1719 .StartChild("test-device-0")
1720 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001721 .Property("base-address", "<0x24000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001722 .Property("pages-count", "<16>")
1723 .Property("attributes", "<3>")
1724 .Property("interrupts", "<2 3>")
1725 .EndChild()
1726 .StartChild("test-device-1")
1727 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001728 .Property("base-address", "<0x25000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001729 .Property("pages-count", "<16>")
1730 .Property("attributes", "<3>")
1731 .Property("interrupts", "<1 3>, <2 5> ")
1732 .EndChild()
1733 .EndChild()
1734 .Build();
Daniel Boulby941ef342023-11-21 13:47:15 +00001735
Daniel Boulby667334f2022-06-27 15:23:21 +01001736 /* clang-format on */
1737 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1738 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1739 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001740 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1741 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1742 3);
1743 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1744 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1745 3);
Daniel Boulby941ef342023-11-21 13:47:15 +00001746 manifest_dealloc();
1747
1748 /* Overlapping address space between two device region nodes. */
1749 /* clang-format off */
1750 dtb = ManifestDtBuilder()
1751 .FfaValidManifest()
1752 .StartChild("device-regions")
1753 .Compatible({"arm,ffa-manifest-device-regions"})
1754 .StartChild("test-device-0")
1755 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001756 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001757 .Property("pages-count", "<16>")
1758 .Property("attributes", "<3>")
1759 .EndChild()
1760 .StartChild("test-device-1")
1761 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001762 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001763 .Property("pages-count", "<16>")
1764 .Property("attributes", "<3>")
1765 .EndChild()
Daniel Boulby4339edc2024-02-21 14:59:00 +00001766 .EndChild()
Daniel Boulby941ef342023-11-21 13:47:15 +00001767 .Build();
1768
1769 /* clang-format on */
1770 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1771 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1772 manifest_dealloc();
1773
1774 /*
Daniel Boulby4339edc2024-02-21 14:59:00 +00001775 * Device regions cannot be defined outside of the regions specified in
1776 * the spmc.
Daniel Boulby941ef342023-11-21 13:47:15 +00001777 */
1778 /* clang-format off */
1779 dtb = ManifestDtBuilder()
1780 .FfaValidManifest()
Daniel Boulby941ef342023-11-21 13:47:15 +00001781 .StartChild("device-regions")
1782 .Compatible({"arm,ffa-manifest-device-regions"})
1783 .StartChild("test-device-0")
1784 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001785 .Property("base-address", "<0x50000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001786 .Property("pages-count", "<16>")
1787 .Property("attributes", "<3>")
1788 .EndChild()
1789 .EndChild()
1790 .Build();
1791 /* clang-format on */
1792 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
Daniel Boulby4339edc2024-02-21 14:59:00 +00001793 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
1794 manifest_dealloc();
1795
1796 /*
1797 * Memory defined as NS in SPMC manifest given Secure attribute should
1798 * fail.
1799 */
1800 /* clang-format off */
1801 dtb = ManifestDtBuilder()
1802 .FfaValidManifest()
1803 .StartChild("device-regions")
1804 .Compatible({"arm,ffa-manifest-device-regions"})
1805 .StartChild("test-device-0")
1806 .Description("test-device-0")
1807 .Property("base-address", "<0x20000000>")
1808 .Property("pages-count", "<16>")
1809 .Property("attributes", "<3>")
1810 .EndChild()
1811 .EndChild()
1812 .Build();
1813 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1814 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
Manish Pandeye68e7932020-04-23 15:29:28 +01001815}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001816
1817TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001818{
Olivier Deprez93644652022-09-09 11:01:12 +02001819 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001820
1821 /* clang-format off */
1822 std::vector<char> dtb = ManifestDtBuilder()
1823 .FfaValidManifest()
1824 .StartChild("rx_tx-info")
1825 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1826 .Property("rx-buffer", "<&rx>")
1827 .Property("tx-buffer", "<&tx>")
1828 .EndChild()
1829 .StartChild("memory-regions")
1830 .Compatible({ "arm,ffa-manifest-memory-regions" })
1831 .StartChild("test-memory")
1832 .Description("test-memory")
1833 .Property("base-address", "<0x7100000>")
1834 .Property("pages-count", "<4>")
1835 .Property("attributes", "<7>")
1836 .EndChild()
1837 .Label("rx")
1838 .StartChild("rx")
1839 .Description("rx-buffer")
1840 .Property("base-address", "<0x7300000>")
1841 .Property("pages-count", "<1>")
1842 .Property("attributes", "<1>")
1843 .EndChild()
1844 .Label("tx")
1845 .StartChild("tx")
1846 .Description("tx-buffer")
1847 .Property("base-address", "<0x7310000>")
1848 .Property("pages-count", "<1>")
1849 .Property("attributes", "<3>")
1850 .EndChild()
1851 .EndChild()
1852 .Build();
1853 /* clang-format on */
1854
1855 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1856 MANIFEST_ERROR_INVALID_MEM_PERM);
1857}
1858
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001859TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001860{
Olivier Deprez93644652022-09-09 11:01:12 +02001861 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001862
1863 /* clang-format off */
1864 std::vector<char> dtb = ManifestDtBuilder()
1865 .FfaValidManifest()
1866 .StartChild("rx_tx-info")
1867 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1868 .Property("rx-buffer", "<&rx>")
1869 .Property("tx-buffer", "<&tx>")
1870 .EndChild()
1871 .StartChild("memory-regions")
1872 .Compatible({ "arm,ffa-manifest-memory-regions" })
1873 .StartChild("test-memory")
1874 .Description("test-memory")
1875 .Property("base-address", "<0x7100000>")
1876 .Property("pages-count", "<4>")
1877 .Property("attributes", "<3>")
1878 .EndChild()
1879 .Label("rx")
1880 .StartChild("rx")
1881 .Description("rx-buffer")
1882 .Property("base-address", "<0x7300000>")
1883 .Property("pages-count", "<1>")
1884 .Property("attributes", "<1>")
1885 .EndChild()
1886 .Label("tx")
1887 .StartChild("tx")
1888 .Description("tx-buffer")
1889 .Property("base-address", "<0x7310000>")
1890 .Property("pages-count", "<1>")
1891 .Property("attributes", "<3>")
1892 .EndChild()
1893 .EndChild()
1894 .StartChild("device-regions")
1895 .Compatible({ "arm,ffa-manifest-device-regions" })
1896 .StartChild("test-device")
1897 .Description("test-device")
1898 .Property("base-address", "<0x7200000>")
1899 .Property("pages-count", "<16>")
1900 .Property("attributes", "<5>")
1901 .Property("smmu-id", "<1>")
1902 .Property("stream-ids", "<0 1>")
1903 .Property("interrupts", "<2 3>, <4 5>")
1904 .EndChild()
1905 .EndChild()
1906 .Build();
1907 /* clang-format on */
1908
1909 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1910 MANIFEST_ERROR_INVALID_MEM_PERM);
1911}
Manish Pandeye68e7932020-04-23 15:29:28 +01001912
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001913TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01001914{
Olivier Deprez93644652022-09-09 11:01:12 +02001915 struct manifest_vm *vm;
1916 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01001917
1918 /* clang-format off */
1919 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001920 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001921 .StartChild("rx_tx-info")
1922 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1923 .Property("rx-buffer", "<&rx>")
1924 .Property("tx-buffer", "<&tx>")
1925 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001926 .StartChild("memory-regions")
1927 .Compatible({ "arm,ffa-manifest-memory-regions" })
Olivier Deprez035fa152022-03-14 11:19:10 +01001928 .StartChild("test-memory-ns")
1929 .Description("test-memory")
1930 .Property("base-address", "<0x7200000>")
1931 .Property("pages-count", "<1>")
1932 .Property("attributes", "<0xb>")
1933 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001934 .Label("rx")
1935 .StartChild("rx")
1936 .Description("rx-buffer")
1937 .Property("base-address", "<0x7300000>")
1938 .Property("pages-count", "<1>")
1939 .Property("attributes", "<1>")
1940 .EndChild()
1941 .Label("tx")
1942 .StartChild("tx")
1943 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001944 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001945 .Property("pages-count", "<1>")
1946 .Property("attributes", "<3>")
1947 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001948 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001949 .StartChild("device-regions")
1950 .Compatible({ "arm,ffa-manifest-device-regions" })
1951 .StartChild("test-device")
1952 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001953 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001954 .Property("pages-count", "<16>")
1955 .Property("attributes", "<3>")
1956 .Property("smmu-id", "<1>")
1957 .Property("stream-ids", "<0 1>")
1958 .Property("interrupts", "<2 3>, <4 5>")
1959 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001960 .StartChild("test-device-ns")
1961 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001962 .Property("base-address", "<0x20000000>")
Olivier Deprez035fa152022-03-14 11:19:10 +01001963 .Property("pages-count", "<1>")
1964 .Property("attributes", "<0x9>")
1965 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001966 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001967 .Build();
Daniel Boulby4339edc2024-02-21 14:59:00 +00001968
Olivier Deprez62d99e32020-01-09 15:58:07 +01001969 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01001970 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1971
Olivier Deprez93644652022-09-09 11:01:12 +02001972 vm = &m->vm[0];
1973 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001974 ASSERT_THAT(
Kathleen Capella422b10b2023-06-30 18:28:27 -04001975 std::span(vm->partition.uuids[0].uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001976 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02001977 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
1978 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
1979 ASSERT_EQ(vm->partition.execution_state, AARCH64);
1980 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
1981 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
1982 ASSERT_EQ(vm->partition.boot_order, 0);
1983 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
1984 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
Davidson K5d5f2792024-08-19 19:09:12 +05301985 ASSERT_EQ(vm->partition.mem_regions[0].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001986
Olivier Deprez93644652022-09-09 11:01:12 +02001987 ASSERT_EQ(vm->partition.rxtx.available, true);
1988 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
1989 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
1990 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
1991 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
1992 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
1993 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
1994
Daniel Boulby4339edc2024-02-21 14:59:00 +00001995 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Olivier Deprez93644652022-09-09 11:01:12 +02001996 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02001997 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05001998 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
1999 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2000 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Olivier Deprez93644652022-09-09 11:01:12 +02002001 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2002 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2003 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2004 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
Daniel Boulby4339edc2024-02-21 14:59:00 +00002005 ASSERT_EQ(vm->partition.dev_regions[1].base_address, 0x20000000);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002006 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01002007}
2008
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002009TEST_F(manifest, ffa_valid_interrupt_target_manifest)
2010{
2011 struct manifest_vm *vm;
2012 struct_manifest *m;
2013
2014 /* clang-format off */
2015 std::vector<char> dtb = ManifestDtBuilder()
2016 .FfaValidManifest()
2017 .StartChild("device-regions")
2018 .Compatible({ "arm,ffa-manifest-device-regions" })
2019 .StartChild("test-device")
2020 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002021 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002022 .Property("pages-count", "<16>")
2023 .Property("attributes", "<3>")
2024 .Property("smmu-id", "<1>")
2025 .Property("stream-ids", "<0 1>")
2026 .Property("interrupts", "<2 3>, <4 5>")
2027 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
2028 .EndChild()
2029 .EndChild()
2030 .Build();
2031 /* clang-format on */
2032
2033 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2034
2035 vm = &m->vm[0];
2036
Daniel Boulby4339edc2024-02-21 14:59:00 +00002037 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002038 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02002039 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05002040 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
2041 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
2042 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002043 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
2044 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
2045 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
2046 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
2047 0x123400005678);
2048 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
2049 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
2050 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
2051 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
2052 0x1234567887654321);
2053}
2054
2055TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
2056{
2057 struct_manifest *m;
2058
2059 /* clang-format off */
2060 std::vector<char> dtb = ManifestDtBuilder()
2061 .FfaValidManifest()
2062 .StartChild("device-regions")
2063 .Compatible({ "arm,ffa-manifest-device-regions" })
2064 .StartChild("test-device")
2065 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002066 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07002067 .Property("pages-count", "<16>")
2068 .Property("attributes", "<3>")
2069 .Property("smmu-id", "<1>")
2070 .Property("stream-ids", "<0 1>")
2071 .Property("interrupts", "<2 3>, <4 5>")
2072 .Property("interrupts-target", "<20 0x1234 0x5678>")
2073 .EndChild()
2074 .EndChild()
2075 .Build();
2076 /* clang-format on */
2077
2078 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2079 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
2080}
2081
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04002082TEST_F(manifest, ffa_boot_order_not_unique)
2083{
2084 struct_manifest *m;
2085 struct memiter it;
2086 struct mm_stage1_locked mm_stage1_locked;
2087 struct boot_params params;
2088 Partition_package spkg_1;
2089 Partition_package spkg_2;
2090
2091 /* clang-format off */
2092 std::vector<char> dtb1 = ManifestDtBuilder()
2093 .Compatible({ "arm,ffa-manifest-1.0" })
2094 .Property("ffa-version", "<0x10001>")
2095 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2096 .FfaLoadAddress((uint64_t)&spkg_1)
2097 .Property("execution-ctx-count", "<1>")
2098 .Property("exception-level", "<1>")
2099 .Property("execution-state", "<0>")
2100 .Property("entrypoint-offset", "<0x00002000>")
2101 .Property("xlat-granule", "<0>")
2102 .Property("boot-order", "<1>")
2103 .Property("messaging-method", "<1>")
2104 .Property("ns-interrupts-action", "<0>")
2105 .Build();
2106
2107 std::vector<char> dtb2 = ManifestDtBuilder()
2108 .Compatible({ "arm,ffa-manifest-1.0" })
2109 .Property("ffa-version", "<0x10001>")
2110 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2111 .FfaLoadAddress((uint64_t)&spkg_2)
2112 .Property("execution-ctx-count", "<1>")
2113 .Property("exception-level", "<1>")
2114 .Property("execution-state", "<0>")
2115 .Property("entrypoint-offset", "<0x00002000>")
2116 .Property("xlat-granule", "<0>")
2117 .Property("boot-order", "<1>")
2118 .Property("messaging-method", "<1>")
2119 .Property("ns-interrupts-action", "<0>")
2120 .Build();
2121
2122 /* clang-format on */
2123 spkg_1.init(dtb1);
2124 spkg_2.init(dtb2);
2125
2126 /* clang-format off */
2127 std::vector<char> core_dtb = ManifestDtBuilder()
2128 .StartChild("hypervisor")
2129 .Compatible()
2130 .StartChild("vm1")
2131 .DebugName("ffa_partition_1")
2132 .FfaPartition()
2133 .LoadAddress((uint64_t)&spkg_1)
2134 .VcpuCount(1)
2135 .MemSize(0x10000000)
2136 .EndChild()
2137 .StartChild("vm2")
2138 .DebugName("ffa_partition_2")
2139 .FfaPartition()
2140 .LoadAddress((uint64_t)&spkg_2)
2141 .VcpuCount(1)
2142 .MemSize(0x10000000)
2143 .EndChild()
2144 .EndChild()
2145 .Build();
2146 /* clang-format on */
2147
2148 boot_params_init(&params, nullptr);
2149 memiter_init(&it, core_dtb.data(), core_dtb.size());
2150 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2151 MANIFEST_ERROR_INVALID_BOOT_ORDER);
2152}
Daniel Boulby941ef342023-11-21 13:47:15 +00002153
Kathleen Capella422b10b2023-06-30 18:28:27 -04002154TEST_F(manifest, ffa_valid_multiple_uuids)
2155{
2156 struct manifest_vm *vm;
2157 struct_manifest *m;
2158
2159 /* clang-format off */
2160 std::vector<char> dtb = ManifestDtBuilder()
2161 .Compatible({ "arm,ffa-manifest-1.0" })
2162 .Property("ffa-version", "<0x10002>")
2163 .Property("uuid",
2164 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,\
2165 <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2166 .Property("execution-ctx-count", "<1>")
2167 .Property("exception-level", "<2>")
2168 .Property("execution-state", "<0>")
2169 .Property("entrypoint-offset", "<0x00002000>")
2170 .Property("xlat-granule", "<0>")
2171 .Property("boot-order", "<0>")
2172 .Property("messaging-method", "<4>")
2173 .Property("ns-interrupts-action", "<1>")
2174 .Build();
2175 /* clang-format on */
2176 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2177
2178 vm = &m->vm[0];
2179 ASSERT_EQ(vm->partition.ffa_version, 0x10002);
2180 ASSERT_THAT(
2181 std::span(vm->partition.uuids[0].uuid, 4),
2182 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
2183 ASSERT_THAT(
2184 std::span(vm->partition.uuids[1].uuid, 4),
2185 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1daaa));
2186 ASSERT_EQ(vm->partition.uuid_count, 2);
2187 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2188 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2189 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2190 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2191 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2192 ASSERT_EQ(vm->partition.boot_order, 0);
2193 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2194 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
2195}
Karl Meakin45abeeb2024-08-02 16:55:44 +01002196
2197TEST_F(manifest, ffa_too_many_uuids)
2198{
2199 struct_manifest *m;
2200
2201 /* clang-format off */
2202 std::vector<char> dtb = ManifestDtBuilder()
2203 .Compatible({ "arm,ffa-manifest-1.0" })
2204 .Property("ffa-version", "<0x10002>")
2205 .Property("uuid",
2206 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,"
2207 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2208 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2209 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2210 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2211 .Property("execution-ctx-count", "<1>")
2212 .Property("exception-level", "<2>")
2213 .Property("execution-state", "<0>")
2214 .Property("entrypoint-offset", "<0x00002000>")
2215 .Property("xlat-granule", "<0>")
2216 .Property("boot-order", "<0>")
2217 .Property("messaging-method", "<4>")
2218 .Property("ns-interrupts-action", "<1>")
2219 .Build();
2220 /* clang-format on */
2221 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2222 MANIFEST_ERROR_TOO_MANY_UUIDS);
2223}
2224
Kathleen Capella422b10b2023-06-30 18:28:27 -04002225TEST_F(manifest, ffa_uuid_all_zeros)
2226{
2227 struct_manifest *m;
2228
2229 /* clang-format off */
2230 std::vector<char> dtb = ManifestDtBuilder()
2231 .Compatible({ "arm,ffa-manifest-1.0" })
2232 .Property("ffa-version", "<0x10002>")
2233 .Property("uuid",
2234 "<0x0 0x0 0x0 0x0>, <0x0 0x0 0x0 0x0>")
2235 .Property("execution-ctx-count", "<1>")
2236 .Property("exception-level", "<2>")
2237 .Property("execution-state", "<0>")
2238 .Property("entrypoint-offset", "<0x00002000>")
2239 .Property("xlat-granule", "<0>")
2240 .Property("boot-order", "<0>")
2241 .Property("messaging-method", "<4>")
2242 .Property("ns-interrupts-action", "<1>")
2243 .Build();
2244 /* clang-format on */
2245 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2246 MANIFEST_ERROR_UUID_ALL_ZEROS);
2247}
Daniel Boulby941ef342023-11-21 13:47:15 +00002248
2249/*
2250 * Test that the address space of two device region nodes specified across
2251 * different SPs cannot overlap.
2252 */
2253TEST_F(manifest, ffa_device_region_multi_sps)
2254{
2255 struct_manifest *m;
2256 struct memiter it;
2257 struct mm_stage1_locked mm_stage1_locked;
2258 struct boot_params params;
2259 Partition_package spkg_1;
2260 Partition_package spkg_2;
2261
2262 /* clang-format off */
2263 std::vector<char> dtb1 = ManifestDtBuilder()
2264 .Compatible({ "arm,ffa-manifest-1.0" })
2265 .Property("ffa-version", "<0x10001>")
2266 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2267 .FfaLoadAddress((uint64_t)&spkg_1)
2268 .Property("execution-ctx-count", "<1>")
2269 .Property("exception-level", "<0>")
2270 .Property("execution-state", "<0>")
2271 .Property("entrypoint-offset", "<0x0>")
2272 .Property("xlat-granule", "<0>")
2273 .Property("messaging-method", "<0x7>")
2274 .StartChild("device-regions")
2275 .Compatible({ "arm,ffa-manifest-device-regions" })
2276 .StartChild("test-device-0")
2277 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002278 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002279 .Property("pages-count", "<16>")
2280 .Property("attributes", "<3>")
2281 .EndChild()
2282 .EndChild()
2283 .Build();
2284
2285 std::vector<char> dtb2 = ManifestDtBuilder()
2286 .Compatible({ "arm,ffa-manifest-1.0" })
2287 .Property("ffa-version", "<0x10001>")
2288 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2289 .FfaLoadAddress((uint64_t)&spkg_2)
2290 .Property("execution-ctx-count", "<1>")
2291 .Property("exception-level", "<0>")
2292 .Property("execution-state", "<0>")
2293 .Property("entrypoint-offset", "<0x0>")
2294 .Property("xlat-granule", "<0>")
2295 .Property("messaging-method", "<0x7>")
2296 .StartChild("device-regions")
2297 .Compatible({ "arm,ffa-manifest-device-regions" })
2298 .StartChild("test-device-0")
2299 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002300 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002301 .Property("pages-count", "<16>")
2302 .Property("attributes", "<3>")
2303 .EndChild()
2304 .EndChild()
2305 .Build();
2306
2307 /* clang-format on */
2308 spkg_1.init(dtb1);
2309 spkg_2.init(dtb2);
2310
2311 /* clang-format off */
2312 std::vector<char> core_dtb = ManifestDtBuilder()
2313 .StartChild("hypervisor")
2314 .Compatible()
2315 .StartChild("vm1")
2316 .DebugName("ffa_partition_1")
2317 .FfaPartition()
2318 .LoadAddress((uint64_t)&spkg_1)
2319 .VcpuCount(1)
2320 .MemSize(0x4000)
2321 .EndChild()
2322 .StartChild("vm2")
2323 .DebugName("ffa_partition_2")
2324 .FfaPartition()
2325 .LoadAddress((uint64_t)&spkg_2)
2326 .VcpuCount(1)
2327 .MemSize(0x4000)
2328 .EndChild()
2329 .EndChild()
2330 .Build();
2331 /* clang-format on */
2332 boot_params_init(&params, &spkg_1);
2333 memiter_init(&it, core_dtb.data(), core_dtb.size());
2334 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2335 MANIFEST_ERROR_MEM_REGION_OVERLAP);
2336
2337 manifest_dealloc();
2338
2339 /* clang-format off */
2340 dtb1 = ManifestDtBuilder()
2341 .Compatible({ "arm,ffa-manifest-1.0" })
2342 .Property("ffa-version", "<0x10001>")
2343 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2344 .FfaLoadAddress((uint64_t)&spkg_1)
2345 .Property("execution-ctx-count", "<1>")
2346 .Property("exception-level", "<0>")
2347 .Property("execution-state", "<0>")
2348 .Property("entrypoint-offset", "<0x0>")
2349 .Property("xlat-granule", "<0>")
2350 .Property("messaging-method", "<0x7>")
2351 .StartChild("device-regions")
2352 .Compatible({ "arm,ffa-manifest-device-regions" })
2353 .StartChild("test-device-0")
2354 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002355 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002356 .Property("pages-count", "<16>")
2357 .Property("attributes", "<3>")
2358 .EndChild()
2359 .EndChild()
2360 .Build();
2361
2362 dtb2 = ManifestDtBuilder()
2363 .Compatible({ "arm,ffa-manifest-1.0" })
2364 .Property("ffa-version", "<0x10001>")
2365 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2366 .FfaLoadAddress((uint64_t)&spkg_2)
2367 .Property("execution-ctx-count", "<1>")
2368 .Property("exception-level", "<0>")
2369 .Property("execution-state", "<0>")
2370 .Property("entrypoint-offset", "<0x0>")
2371 .Property("xlat-granule", "<0>")
2372 .Property("messaging-method", "<0x7>")
2373 .StartChild("device-regions")
2374 .Compatible({ "arm,ffa-manifest-device-regions" })
2375 .StartChild("test-device-0")
2376 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002377 .Property("base-address", "<0x25000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002378 .Property("pages-count", "<16>")
2379 .Property("attributes", "<3>")
2380 .EndChild()
2381 .EndChild()
2382 .Build();
2383
2384 /* clang-format on */
2385 spkg_1.init(dtb1);
2386 spkg_2.init(dtb2);
2387
2388 /* clang-format off */
2389 core_dtb = ManifestDtBuilder()
2390 .StartChild("hypervisor")
2391 .Compatible()
2392 .StartChild("vm1")
2393 .DebugName("ffa_partition_1")
2394 .FfaPartition()
2395 .LoadAddress((uint64_t)&spkg_1)
2396 .VcpuCount(1)
2397 .MemSize(0x4000)
2398 .EndChild()
2399 .StartChild("vm2")
2400 .DebugName("ffa_partition_2")
2401 .FfaPartition()
2402 .LoadAddress((uint64_t)&spkg_2)
2403 .VcpuCount(1)
2404 .MemSize(0x4000)
2405 .EndChild()
2406 .EndChild()
2407 .Build();
2408 /* clang-format on */
2409 boot_params_init(&params, &spkg_1);
2410 memiter_init(&it, core_dtb.data(), core_dtb.size());
2411 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2412 MANIFEST_SUCCESS);
2413}
Madhukar Pappireddy99c5eff2024-07-08 15:07:41 -05002414
2415/*
2416 * Tests to trigger various error conditions while parsing dma related
2417 * properties of memory region nodes.
2418 */
2419TEST_F(manifest, ffa_memory_region_invalid_dma_properties)
2420{
2421 struct_manifest *m;
2422
2423 /*
2424 * SMMU ID must be specified if the partition specifies Stream IDs for
2425 * any device upstream of SMMU.
2426 */
2427 /* clang-format off */
2428 std::vector<char> dtb = ManifestDtBuilder()
2429 .FfaValidManifest()
2430 .StartChild("memory-regions")
2431 .Compatible({ "arm,ffa-manifest-memory-regions" })
2432 .StartChild("test-memory")
2433 .Description("test-memory")
2434 .Property("base-address", "<0x7100000>")
2435 .Property("pages-count", "<16>")
2436 .Property("attributes", "<3>")
2437 .Property("stream-ids", "<0 1>")
2438 .Property("interrupts", "<2 3>, <4 5>")
2439 .EndChild()
2440 .EndChild()
2441 .Build();
2442 /* clang-format on */
2443
2444 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2445 MANIFEST_ERROR_MISSING_SMMU_ID);
2446 manifest_dealloc();
2447
2448 /*
2449 * All stream ids belonging to a dma device must specify the same access
2450 * permissions.
2451 */
2452 /* clang-format off */
2453 dtb = ManifestDtBuilder()
2454 .FfaValidManifest()
2455 .StartChild("memory-regions")
2456 .Compatible({ "arm,ffa-manifest-memory-regions" })
2457 .StartChild("test-memory")
2458 .Description("test-memory")
2459 .Property("base-address", "<0x7100000>")
2460 .Property("pages-count", "<16>")
2461 .Property("attributes", "<3>")
2462 .Property("smmu-id", "<1>")
2463 .Property("stream-ids", "<0 1>")
2464 .Property("stream-ids-access-permissions", "<0x3 0xb>")
2465 .Property("interrupts", "<2 3>, <4 5>")
2466 .EndChild()
2467 .EndChild()
2468 .Build();
2469 /* clang-format on */
2470
2471 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2472 MANIFEST_ERROR_MISMATCH_DMA_ACCESS_PERMISSIONS);
2473 manifest_dealloc();
2474
2475 /*
2476 * DMA device stream ID count exceeds predefined limit.
2477 */
2478 /* clang-format off */
2479 dtb = ManifestDtBuilder()
2480 .FfaValidManifest()
2481 .StartChild("memory-regions")
2482 .Compatible({ "arm,ffa-manifest-memory-regions" })
2483 .StartChild("test-memory")
2484 .Description("test-memory")
2485 .Property("base-address", "<0x7100000>")
2486 .Property("pages-count", "<16>")
2487 .Property("attributes", "<3>")
2488 .Property("smmu-id", "<1>")
2489 .Property("stream-ids", "<0 1 4 9 12 >")
2490 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3>")
2491 .EndChild()
2492 .EndChild()
2493 .Build();
2494 /* clang-format on */
2495
2496 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2497 MANIFEST_ERROR_STREAM_IDS_OVERFLOW);
2498 manifest_dealloc();
2499
2500 /*
2501 * DMA access permissions count exceeds predefined limit
2502 */
2503 /* clang-format off */
2504 dtb = ManifestDtBuilder()
2505 .FfaValidManifest()
2506 .StartChild("memory-regions")
2507 .Compatible({ "arm,ffa-manifest-memory-regions" })
2508 .StartChild("test-memory")
2509 .Description("test-memory")
2510 .Property("base-address", "<0x7100000>")
2511 .Property("pages-count", "<16>")
2512 .Property("attributes", "<3>")
2513 .Property("smmu-id", "<1>")
2514 .Property("stream-ids", "<0 1>")
2515 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3 0x3 0x3>")
2516 .EndChild()
2517 .EndChild()
2518 .Build();
2519 /* clang-format on */
2520
2521 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2522 MANIFEST_ERROR_DMA_ACCESS_PERMISSIONS_OVERFLOW);
2523}
2524
2525/*
2526 * Tests to trigger various error conditions while parsing dma related
2527 * properties of device region nodes.
2528 */
2529TEST_F(manifest, ffa_device_region_invalid_dma_properties)
2530{
2531 struct_manifest *m;
2532
2533 /*
2534 * SMMU ID must be specified if the partition specifies Stream IDs for
2535 * any device upstream of SMMU.
2536 */
2537 /* clang-format off */
2538 std::vector<char> dtb = ManifestDtBuilder()
2539 .FfaValidManifest()
2540 .StartChild("device-regions")
2541 .Compatible({ "arm,ffa-manifest-device-regions" })
2542 .StartChild("test-device")
2543 .Description("test-device")
2544 .Property("base-address", "<0x24000000>")
2545 .Property("pages-count", "<16>")
2546 .Property("attributes", "<3>")
2547 .Property("stream-ids", "<0 1>")
2548 .Property("interrupts", "<2 3>, <4 5>")
2549 .EndChild()
2550 .EndChild()
2551 .Build();
2552 /* clang-format on */
2553
2554 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2555 MANIFEST_ERROR_MISSING_SMMU_ID);
2556 manifest_dealloc();
2557
2558 /*
2559 * Dma devices defined through device region nodes exceed predefined
2560 * limit.
2561 */
2562 /* clang-format off */
2563 dtb = ManifestDtBuilder()
2564 .FfaValidManifest()
2565 .StartChild("device-regions")
2566 .Compatible({ "arm,ffa-manifest-device-regions" })
2567 .StartChild("test-device-0")
2568 .Description("test-device-0")
2569 .Property("base-address", "<0x27000000>")
2570 .Property("pages-count", "<16>")
2571 .Property("attributes", "<3>")
2572 .Property("smmu-id", "<1>")
2573 .Property("stream-ids", "<0 1>")
2574 .EndChild()
2575 .StartChild("test-device-1")
2576 .Description("test-device-1")
2577 .Property("base-address", "<0x25000000>")
2578 .Property("pages-count", "<16>")
2579 .Property("attributes", "<3>")
2580 .Property("smmu-id", "<1>")
2581 .Property("stream-ids", "<2 3>")
2582 .EndChild()
2583 .StartChild("test-device-2")
2584 .Description("test-device-2")
2585 .Property("base-address", "<0x26000000>")
2586 .Property("pages-count", "<16>")
2587 .Property("attributes", "<3>")
2588 .Property("smmu-id", "<1>")
2589 .Property("stream-ids", "<4 5>")
2590 .EndChild()
2591 .EndChild()
2592 .Build();
2593 /* clang-format on */
2594
2595 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2596 MANIFEST_ERROR_DMA_DEVICE_OVERFLOW);
2597}
David Brazdil7a462ec2019-08-15 12:27:47 +01002598} /* namespace */