blob: 41dfeb347a8753e819ce8d1bc3a353d627849a90 [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>
10#include <cstdio>
Andrew Scullae9962e2019-10-03 16:51:16 +010011#include <span>
David Brazdil52256ff2019-08-23 15:15:15 +010012#include <sstream>
13
David Brazdil7a462ec2019-08-15 12:27:47 +010014#include <gmock/gmock.h>
15
16extern "C" {
J-Alves2f86c1e2022-02-23 18:44:19 +000017#include "hf/arch/std.h"
18
J-Alves77b6f4f2023-03-15 11:34:49 +000019#include "hf/boot_params.h"
David Brazdil7a462ec2019-08-15 12:27:47 +010020#include "hf/manifest.h"
J-Alves2f86c1e2022-02-23 18:44:19 +000021#include "hf/sp_pkg.h"
David Brazdil7a462ec2019-08-15 12:27:47 +010022}
23
24namespace
25{
Andrew Scullae9962e2019-10-03 16:51:16 +010026using ::testing::ElementsAre;
David Brazdil7a462ec2019-08-15 12:27:47 +010027using ::testing::Eq;
Andrew Scullae9962e2019-10-03 16:51:16 +010028using ::testing::IsEmpty;
David Brazdil7a462ec2019-08-15 12:27:47 +010029using ::testing::NotNull;
30
Daniel Boulby801f8ef2022-06-27 14:21:01 +010031using struct_manifest = struct manifest;
32
J-Alves5c0ae6f2023-06-14 15:20:21 +010033constexpr size_t TEST_HEAP_SIZE = PAGE_SIZE * 128;
Daniel Boulby801f8ef2022-06-27 14:21:01 +010034
David Brazdil52256ff2019-08-23 15:15:15 +010035template <typename T>
David Brazdil0dbb41f2019-09-09 18:03:35 +010036void exec(const char *program, const char *args[], const T &stdin,
David Brazdil52256ff2019-08-23 15:15:15 +010037 std::vector<char> *stdout)
38{
39 /* Create two pipes, one for stdin and one for stdout. */
40 int pipes[2][2];
41 pipe(pipes[0]);
42 pipe(pipes[1]);
David Brazdil7a462ec2019-08-15 12:27:47 +010043
David Brazdil52256ff2019-08-23 15:15:15 +010044 /* Assign FDs for reading/writing by the parent/child. */
45 int parent_read_fd = pipes[1][0]; /* stdout pipe, read FD */
46 int parent_write_fd = pipes[0][1]; /* stdin pipe, write FD */
47 int child_read_fd = pipes[0][0]; /* stdin pipe, read FD */
48 int child_write_fd = pipes[1][1]; /* stdout pipe, write FD */
David Brazdil7a462ec2019-08-15 12:27:47 +010049
David Brazdil52256ff2019-08-23 15:15:15 +010050 if (fork()) {
51 /* Parent process. */
52 std::array<char, 128> buf;
53 ssize_t res;
54
55 /* Close child FDs which won't be used. */
56 close(child_read_fd);
57 close(child_write_fd);
58
59 /* Write to stdin. */
60 for (size_t count = 0; count < stdin.size();) {
61 res = write(parent_write_fd, stdin.data() + count,
62 stdin.size() - count);
63 if (res < 0) {
64 std::cerr << "IO error" << std::endl;
65 exit(1);
66 }
67 count += res;
68 }
69 close(parent_write_fd);
70
71 /* Read from stdout. */
72 while (true) {
73 res = read(parent_read_fd, buf.data(), buf.size());
74 if (res == 0) {
75 /* EOF */
76 break;
77 } else if (res < 0) {
78 std::cerr << "IO error" << std::endl;
79 exit(1);
80 }
81 stdout->insert(stdout->end(), buf.begin(),
82 buf.begin() + res);
83 }
84 close(parent_read_fd);
85 } else {
86 /* Child process. */
87
88 /* Redirect stdin/stdout to read/write FDs. */
89 dup2(child_read_fd, STDIN_FILENO);
90 dup2(child_write_fd, STDOUT_FILENO);
91
92 /* Close all FDs which are now unused. */
93 close(child_read_fd);
94 close(child_write_fd);
95 close(parent_read_fd);
96 close(parent_write_fd);
97
98 /* Execute the given program. */
David Brazdil0dbb41f2019-09-09 18:03:35 +010099 execv(program, const_cast<char *const *>(args));
David Brazdil52256ff2019-08-23 15:15:15 +0100100 }
101}
102
103/**
104 * Class for programatically building a Device Tree.
105 *
106 * Usage:
107 * std::vector<char> dtb = ManifestDtBuilder()
108 * .Command1()
109 * .Command2()
110 * ...
111 * .CommandN()
112 * .Build();
113 */
114class ManifestDtBuilder
115{
116 public:
117 ManifestDtBuilder()
118 {
119 dts_ << "/dts-v1/;" << std::endl;
120 dts_ << std::endl;
121
122 /* Start root node. */
123 StartChild("/");
124 }
125
Andrew Scullae9962e2019-10-03 16:51:16 +0100126 std::vector<char> Build(bool dump = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100127 {
David Brazdil0dbb41f2019-09-09 18:03:35 +0100128 const char *program = "./build/image/dtc.py";
129 const char *dtc_args[] = {program, "compile", NULL};
David Brazdil52256ff2019-08-23 15:15:15 +0100130 std::vector<char> dtc_stdout;
131
132 /* Finish root node. */
133 EndChild();
134
Andrew Scullae9962e2019-10-03 16:51:16 +0100135 if (dump) {
136 Dump();
137 }
138
David Brazdil0dbb41f2019-09-09 18:03:35 +0100139 exec(program, dtc_args, dts_.str(), &dtc_stdout);
David Brazdil52256ff2019-08-23 15:15:15 +0100140 return dtc_stdout;
141 }
142
Andrew Scullae9962e2019-10-03 16:51:16 +0100143 void Dump()
144 {
145 std::cerr << dts_.str() << std::endl;
146 }
147
David Brazdil52256ff2019-08-23 15:15:15 +0100148 ManifestDtBuilder &StartChild(const std::string_view &name)
149 {
150 dts_ << name << " {" << std::endl;
151 return *this;
152 }
153
154 ManifestDtBuilder &EndChild()
155 {
156 dts_ << "};" << std::endl;
157 return *this;
158 }
159
David Brazdil74e9c3b2019-08-28 11:09:08 +0100160 ManifestDtBuilder &Compatible(const std::vector<std::string_view>
161 &value = {"hafnium,hafnium"})
162 {
163 return StringListProperty("compatible", value);
164 }
165
David Brazdil52256ff2019-08-23 15:15:15 +0100166 ManifestDtBuilder &DebugName(const std::string_view &value)
167 {
168 return StringProperty("debug_name", value);
169 }
170
Manish Pandey6542f5c2020-04-27 14:37:46 +0100171 ManifestDtBuilder &Description(const std::string_view &value)
172 {
173 return StringProperty("description", value);
174 }
175
David Brazdil52256ff2019-08-23 15:15:15 +0100176 ManifestDtBuilder &KernelFilename(const std::string_view &value)
177 {
178 return StringProperty("kernel_filename", value);
179 }
180
David Brazdile6f83222019-09-23 14:47:37 +0100181 ManifestDtBuilder &RamdiskFilename(const std::string_view &value)
182 {
183 return StringProperty("ramdisk_filename", value);
184 }
185
David Brazdil080ee312020-02-25 15:30:30 -0800186 ManifestDtBuilder &BootAddress(uint64_t value)
187 {
188 return Integer64Property("boot_address", value);
189 }
190
Andrew Scullae9962e2019-10-03 16:51:16 +0100191 ManifestDtBuilder &VcpuCount(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100192 {
193 return IntegerProperty("vcpu_count", value);
194 }
195
Andrew Scullae9962e2019-10-03 16:51:16 +0100196 ManifestDtBuilder &MemSize(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100197 {
198 return IntegerProperty("mem_size", value);
199 }
200
Andrew Scullae9962e2019-10-03 16:51:16 +0100201 ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
202 {
203 return IntegerListProperty("smc_whitelist", value);
204 }
205
206 ManifestDtBuilder &SmcWhitelistPermissive()
207 {
208 return BooleanProperty("smc_whitelist_permissive");
209 }
210
Olivier Deprez62d99e32020-01-09 15:58:07 +0100211 ManifestDtBuilder &LoadAddress(uint64_t value)
212 {
213 return Integer64Property("load_address", value);
214 }
215
216 ManifestDtBuilder &FfaPartition()
217 {
218 return BooleanProperty("is_ffa_partition");
219 }
220
Andrew Scullae9962e2019-10-03 16:51:16 +0100221 ManifestDtBuilder &Property(const std::string_view &name,
222 const std::string_view &value)
223 {
224 dts_ << name << " = " << value << ";" << std::endl;
225 return *this;
226 }
227
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100228 ManifestDtBuilder &Label(const std::string_view &name)
229 {
230 dts_ << name << ": ";
231 return *this;
232 }
233
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100234 ManifestDtBuilder &FfaValidManifest()
235 {
236 Compatible({"arm,ffa-manifest-1.0"});
237 Property("ffa-version", "<0x10000>");
238 Property("uuid",
239 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>");
240 Property("execution-ctx-count", "<1>");
241 Property("exception-level", "<2>");
242 Property("execution-state", "<0>");
J-Alves2f86c1e2022-02-23 18:44:19 +0000243 Property("entrypoint-offset", "<0x00002000>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100244 Property("xlat-granule", "<0>");
J-Alvesb37fd082020-10-22 12:29:21 +0100245 Property("boot-order", "<0>");
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400246 Property("messaging-method", "<0x4>");
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500247 Property("ns-interrupts-action", "<1>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100248 return *this;
249 }
250
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400251 ManifestDtBuilder &FfaLoadAddress(uint64_t value)
252 {
253 Integer64Property("load-address", value);
254 return *this;
255 }
256
David Brazdil52256ff2019-08-23 15:15:15 +0100257 private:
258 ManifestDtBuilder &StringProperty(const std::string_view &name,
259 const std::string_view &value)
260 {
261 dts_ << name << " = \"" << value << "\";" << std::endl;
262 return *this;
263 }
264
David Brazdil74e9c3b2019-08-28 11:09:08 +0100265 ManifestDtBuilder &StringListProperty(
266 const std::string_view &name,
267 const std::vector<std::string_view> &value)
268 {
269 bool is_first = true;
270
271 dts_ << name << " = ";
272 for (const std::string_view &entry : value) {
273 if (is_first) {
274 is_first = false;
275 } else {
276 dts_ << ", ";
277 }
278 dts_ << "\"" << entry << "\"";
279 }
280 dts_ << ";" << std::endl;
281 return *this;
282 }
283
David Brazdil52256ff2019-08-23 15:15:15 +0100284 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100285 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100286 {
287 dts_ << name << " = <" << value << ">;" << std::endl;
288 return *this;
289 }
290
David Brazdil080ee312020-02-25 15:30:30 -0800291 ManifestDtBuilder &Integer64Property(const std::string_view &name,
292 uint64_t value)
293 {
294 uint32_t high = value >> 32;
295 uint32_t low = (uint32_t)value;
296 dts_ << name << " = <" << high << " " << low << ">;"
297 << std::endl;
298 return *this;
299 }
300
Andrew Scullae9962e2019-10-03 16:51:16 +0100301 ManifestDtBuilder &IntegerListProperty(
302 const std::string_view &name,
303 const std::vector<uint32_t> &value)
304 {
305 dts_ << name << " = < ";
306 for (const uint32_t entry : value) {
307 dts_ << entry << " ";
308 }
309 dts_ << ">;" << std::endl;
310 return *this;
311 }
312
313 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
314 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000315 dts_ << name << ";" << std::endl;
316 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100317 }
318
David Brazdil52256ff2019-08-23 15:15:15 +0100319 std::stringstream dts_;
320};
321
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100322class manifest : public ::testing::Test
David Brazdil0dbb41f2019-09-09 18:03:35 +0100323{
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100324 void SetUp() override
325 {
326 test_heap = std::make_unique<uint8_t[]>(TEST_HEAP_SIZE);
327 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
328 mpool_add_chunk(&ppool, test_heap.get(), TEST_HEAP_SIZE);
329 }
330
Olivier Deprez93644652022-09-09 11:01:12 +0200331 void TearDown() override
332 {
333 manifest_dealloc();
334 }
335
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100336 std::unique_ptr<uint8_t[]> test_heap;
337
338 protected:
Olivier Deprez62d99e32020-01-09 15:58:07 +0100339 struct mpool ppool;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100340
Olivier Deprez93644652022-09-09 11:01:12 +0200341 void manifest_dealloc(void)
342 {
343 manifest_deinit(&ppool);
344 }
345
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100346 public:
347 /**
348 * Class for programatically building a Partition package.
349 */
350 class Partition_package
351 {
352 public:
353 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
354 __attribute__((
355 aligned(PAGE_SIZE))) char manifest_dtb[PAGE_SIZE] = {};
356 __attribute__((aligned(PAGE_SIZE))) char img[PAGE_SIZE] = {};
David Brazdil0dbb41f2019-09-09 18:03:35 +0100357
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100358 Partition_package(const std::vector<char> &vec)
359 {
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400360 init(vec);
361 }
362
363 Partition_package()
364 {
365 }
366
367 void init(const std::vector<char> &vec)
368 {
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100369 // Initialise header field
370 spkg.magic = SP_PKG_HEADER_MAGIC;
371 spkg.version = SP_PKG_HEADER_VERSION_2;
372 spkg.pm_offset = PAGE_SIZE;
373 spkg.pm_size = vec.size();
374 spkg.img_offset = 2 * PAGE_SIZE;
375 spkg.img_size = ARRAY_SIZE(img);
376
377 // Copy dtb into package
378 std::copy(vec.begin(), vec.end(), manifest_dtb);
379 }
380 };
381
J-Alves77b6f4f2023-03-15 11:34:49 +0000382 static void boot_params_init(struct boot_params *params,
383 Partition_package *pkg)
384 {
385 /*
386 * For the manifest tests we only care about the memory ranges
387 * in boot_params.
388 */
389 params->mem_ranges[0].begin = pa_init((uintpaddr_t)0x7000000);
390 params->mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
391 params->mem_ranges_count = 1;
392
393 if (pkg != nullptr) {
394 auto mem_base = (uintpaddr_t)pkg;
395 uintpaddr_t mem_end =
396 mem_base + sp_pkg_get_mem_size(&pkg->spkg);
397
398 params->mem_ranges_count++;
399
400 params->mem_ranges[1].begin = pa_init(mem_base);
401 params->mem_ranges[1].end = pa_init(mem_end);
402 }
403
404 params->ns_mem_ranges[0].begin =
405 pa_init((uintpaddr_t)0x7000000);
406 params->ns_mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
407 params->ns_mem_ranges_count = 1;
Daniel Boulby4339edc2024-02-21 14:59:00 +0000408
409 params->ns_device_mem_ranges[0].begin =
410 pa_init((uintpaddr_t)0x20000000);
411 params->ns_device_mem_ranges[0].end =
412 pa_init((uintpaddr_t)0x24000000);
413 params->ns_device_mem_ranges_count = 1;
414
415 params->device_mem_ranges[0].begin =
416 pa_init((uintpaddr_t)0x24000000);
417 params->device_mem_ranges[0].end =
418 pa_init((uintpaddr_t)0x28000000);
419 params->device_mem_ranges_count = 1;
J-Alves77b6f4f2023-03-15 11:34:49 +0000420 }
421
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100422 enum manifest_return_code manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200423 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100424 {
425 struct memiter it;
426 struct mm_stage1_locked mm_stage1_locked;
J-Alves77b6f4f2023-03-15 11:34:49 +0000427 struct boot_params params;
428
429 boot_params_init(&params, nullptr);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100430
431 memiter_init(&it, vec.data(), vec.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100432
J-Alves77b6f4f2023-03-15 11:34:49 +0000433 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100434 }
435
436 enum manifest_return_code ffa_manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200437 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100438 {
439 struct memiter it;
440 struct mm_stage1_locked mm_stage1_locked;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100441 Partition_package spkg(vec);
J-Alves77b6f4f2023-03-15 11:34:49 +0000442 struct boot_params params;
443
444 boot_params_init(&params, &spkg);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100445
446 /* clang-format off */
447 std::vector<char> core_dtb = ManifestDtBuilder()
448 .StartChild("hypervisor")
449 .Compatible()
450 .StartChild("vm1")
451 .DebugName("primary_vm")
452 .FfaPartition()
453 .LoadAddress((uint64_t)&spkg)
454 .EndChild()
455 .EndChild()
456 .Build();
457 /* clang-format on */
458 memiter_init(&it, core_dtb.data(), core_dtb.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100459
J-Alves77b6f4f2023-03-15 11:34:49 +0000460 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100461 }
462};
463
464TEST_F(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100465{
Olivier Deprez93644652022-09-09 11:01:12 +0200466 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100467 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100468
David Brazdila2358d42020-01-27 18:51:38 +0000469 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100470 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
471}
472
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100473TEST_F(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100474{
Olivier Deprez93644652022-09-09 11:01:12 +0200475 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100476
David Brazdil52256ff2019-08-23 15:15:15 +0100477 /* clang-format off */
478 std::vector<char> dtb = ManifestDtBuilder()
479 .StartChild("hypervisor")
480 .EndChild()
481 .Build();
482 /* clang-format on */
483
David Brazdilf4925382020-03-25 13:33:51 +0000484 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100485}
486
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100487TEST_F(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100488{
Olivier Deprez93644652022-09-09 11:01:12 +0200489 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100490
David Brazdil52256ff2019-08-23 15:15:15 +0100491 /* clang-format off */
492 std::vector<char> dtb = ManifestDtBuilder()
493 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100494 .Compatible({ "foo,bar" })
495 .EndChild()
496 .Build();
497 /* clang-format on */
498
David Brazdila2358d42020-01-27 18:51:38 +0000499 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100500}
501
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100502TEST_F(manifest, compatible_one_of_many)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100503{
Olivier Deprez93644652022-09-09 11:01:12 +0200504 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100505
506 /* clang-format off */
507 std::vector<char> dtb = ManifestDtBuilder()
508 .StartChild("hypervisor")
509 .Compatible({ "foo,bar", "hafnium,hafnium" })
510 .StartChild("vm1")
511 .DebugName("primary")
512 .EndChild()
513 .EndChild()
514 .Build();
515 /* clang-format on */
516
David Brazdila2358d42020-01-27 18:51:38 +0000517 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100518}
519
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100520TEST_F(manifest, no_vm_nodes)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100521{
Olivier Deprez93644652022-09-09 11:01:12 +0200522 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100523
524 /* clang-format off */
525 std::vector<char> dtb = ManifestDtBuilder()
526 .StartChild("hypervisor")
527 .Compatible()
528 .EndChild()
529 .Build();
530 /* clang-format on */
531
David Brazdila2358d42020-01-27 18:51:38 +0000532 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100533}
534
535static std::vector<char> gen_long_string_dtb(bool valid)
536{
537 const char last_valid[] = "1234567890123456789012345678901";
538 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100539 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
540 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100541
542 /* clang-format off */
543 return ManifestDtBuilder()
544 .StartChild("hypervisor")
545 .Compatible()
546 .StartChild("vm1")
547 .DebugName(valid ? last_valid : first_invalid)
548 .EndChild()
549 .EndChild()
550 .Build();
551 /* clang-format on */
552}
553
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100554TEST_F(manifest, long_string)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100555{
Olivier Deprez93644652022-09-09 11:01:12 +0200556 struct_manifest *m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100557 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
558 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
559
David Brazdila2358d42020-01-27 18:51:38 +0000560 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200561 manifest_dealloc();
562
David Brazdila2358d42020-01-27 18:51:38 +0000563 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
564 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100565}
566
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100567TEST_F(manifest, reserved_vm_id)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100568{
Olivier Deprez93644652022-09-09 11:01:12 +0200569 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100570
571 /* clang-format off */
572 std::vector<char> dtb = ManifestDtBuilder()
573 .StartChild("hypervisor")
574 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100575 .StartChild("vm1")
576 .DebugName("primary_vm")
577 .EndChild()
578 .StartChild("vm0")
579 .DebugName("reserved_vm")
580 .VcpuCount(1)
581 .MemSize(0x1000)
582 .KernelFilename("kernel")
583 .EndChild()
584 .EndChild()
585 .Build();
586 /* clang-format on */
587
David Brazdila2358d42020-01-27 18:51:38 +0000588 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100589}
590
Andrew Scullae9962e2019-10-03 16:51:16 +0100591static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100592{
593 /* clang-format off */
594 return ManifestDtBuilder()
595 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100596 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100597 .StartChild("vm1")
598 .DebugName("primary_vm")
599 .EndChild()
600 .StartChild("vm2")
601 .DebugName("secondary_vm")
602 .VcpuCount(vcpu_count)
603 .MemSize(0x1000)
604 .KernelFilename("kernel")
605 .EndChild()
606 .EndChild()
607 .Build();
608 /* clang-format on */
609}
David Brazdil7a462ec2019-08-15 12:27:47 +0100610
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100611TEST_F(manifest, vcpu_count_limit)
David Brazdil7a462ec2019-08-15 12:27:47 +0100612{
Olivier Deprez93644652022-09-09 11:01:12 +0200613 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100614 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
615 std::vector<char> dtb_first_invalid =
616 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100617
David Brazdila2358d42020-01-27 18:51:38 +0000618 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200619 ASSERT_EQ(m->vm_count, 2);
620 ASSERT_EQ(m->vm[1].secondary.vcpu_count, UINT16_MAX);
621 manifest_dealloc();
David Brazdil7a462ec2019-08-15 12:27:47 +0100622
David Brazdila2358d42020-01-27 18:51:38 +0000623 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100624 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100625}
626
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100627TEST_F(manifest, no_ramdisk_primary)
David Brazdile6f83222019-09-23 14:47:37 +0100628{
Olivier Deprez93644652022-09-09 11:01:12 +0200629 struct_manifest *m;
David Brazdile6f83222019-09-23 14:47:37 +0100630
631 /* clang-format off */
632 std::vector<char> dtb = ManifestDtBuilder()
633 .StartChild("hypervisor")
634 .Compatible()
635 .StartChild("vm1")
636 .DebugName("primary_vm")
637 .EndChild()
638 .EndChild()
639 .Build();
640 /* clang-format on */
641
David Brazdila2358d42020-01-27 18:51:38 +0000642 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200643 ASSERT_EQ(m->vm_count, 1);
644 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
645 ASSERT_STREQ(string_data(&m->vm[0].primary.ramdisk_filename), "");
David Brazdile6f83222019-09-23 14:47:37 +0100646}
647
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100648TEST_F(manifest, no_boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800649{
Olivier Deprez93644652022-09-09 11:01:12 +0200650 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800651
652 /* clang-format off */
653 std::vector<char> dtb = ManifestDtBuilder()
654 .StartChild("hypervisor")
655 .Compatible()
656 .StartChild("vm1")
657 .DebugName("primary_vm")
658 .EndChild()
659 .EndChild()
660 .Build();
661 /* clang-format on */
662
663 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200664 ASSERT_EQ(m->vm_count, 1);
665 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
666 ASSERT_EQ(m->vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
David Brazdil080ee312020-02-25 15:30:30 -0800667}
668
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100669TEST_F(manifest, boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800670{
Olivier Deprez93644652022-09-09 11:01:12 +0200671 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800672 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
673
674 /* clang-format off */
675 std::vector<char> dtb = ManifestDtBuilder()
676 .StartChild("hypervisor")
677 .Compatible()
678 .StartChild("vm1")
679 .DebugName("primary_vm")
680 .BootAddress(addr)
681 .EndChild()
682 .EndChild()
683 .Build();
684 /* clang-format on */
685
686 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200687 ASSERT_EQ(m->vm_count, 1);
688 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
689 ASSERT_EQ(m->vm[0].primary.boot_address, addr);
David Brazdil080ee312020-02-25 15:30:30 -0800690}
691
Andrew Scullb2c3a242019-11-04 13:52:36 +0000692static std::vector<char> gen_malformed_boolean_dtb(
693 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100694{
Andrew Scullae9962e2019-10-03 16:51:16 +0100695 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000696 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100697 .StartChild("hypervisor")
698 .Compatible()
699 .StartChild("vm1")
700 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000701 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000702 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100703 .EndChild()
704 .Build();
705 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000706}
Andrew Scullae9962e2019-10-03 16:51:16 +0100707
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100708TEST_F(manifest, malformed_booleans)
Andrew Scullb2c3a242019-11-04 13:52:36 +0000709{
Olivier Deprez93644652022-09-09 11:01:12 +0200710 struct_manifest *m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100711
Andrew Scullb2c3a242019-11-04 13:52:36 +0000712 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
713 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
714 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
715 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100716
David Brazdila2358d42020-01-27 18:51:38 +0000717 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000718 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200719 manifest_dealloc();
720
David Brazdila2358d42020-01-27 18:51:38 +0000721 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000722 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200723 manifest_dealloc();
724
David Brazdila2358d42020-01-27 18:51:38 +0000725 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000726 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200727 manifest_dealloc();
728
David Brazdila2358d42020-01-27 18:51:38 +0000729 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000730 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100731}
732
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100733TEST_F(manifest, valid)
David Brazdil7a462ec2019-08-15 12:27:47 +0100734{
Olivier Deprez93644652022-09-09 11:01:12 +0200735 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100736 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100737
David Brazdil52256ff2019-08-23 15:15:15 +0100738 /* clang-format off */
739 std::vector<char> dtb = ManifestDtBuilder()
740 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100741 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100742 .StartChild("vm1")
743 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100744 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100745 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100746 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100747 .EndChild()
748 .StartChild("vm3")
749 .DebugName("second_secondary_vm")
750 .VcpuCount(43)
751 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100752 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100753 .EndChild()
754 .StartChild("vm2")
755 .DebugName("first_secondary_vm")
756 .VcpuCount(42)
757 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100758 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
759 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100760 .EndChild()
761 .EndChild()
762 .Build();
763 /* clang-format on */
764
David Brazdila2358d42020-01-27 18:51:38 +0000765 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200766 ASSERT_EQ(m->vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100767
Olivier Deprez93644652022-09-09 11:01:12 +0200768 vm = &m->vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100769 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
770 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100771 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
772 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100773 ASSERT_THAT(
774 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
775 ElementsAre(0x32000000, 0x33001111));
776 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100777
Olivier Deprez93644652022-09-09 11:01:12 +0200778 vm = &m->vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100779 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
780 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100781 ASSERT_EQ(vm->secondary.vcpu_count, 42);
782 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100783 ASSERT_THAT(
784 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
785 ElementsAre(0x04000000, 0x30002222, 0x31445566));
786 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100787
Olivier Deprez93644652022-09-09 11:01:12 +0200788 vm = &m->vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100789 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
790 ASSERT_STREQ(string_data(&vm->kernel_filename),
791 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100792 ASSERT_EQ(vm->secondary.vcpu_count, 43);
793 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100794 ASSERT_THAT(
795 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
796 IsEmpty());
797 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100798}
799
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100800TEST_F(manifest, ffa_not_compatible)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100801{
Olivier Deprez93644652022-09-09 11:01:12 +0200802 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100803
804 /* clang-format off */
805 std::vector<char> dtb = ManifestDtBuilder()
806 .Compatible({ "arm,ffa-manifest-2.0" })
807 .Property("ffa-version", "<0x10000>")
808 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
809 .Property("execution-ctx-count", "<1>")
810 .Property("exception-level", "<2>")
811 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000812 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100813 .Property("xlat-granule", "<0>")
814 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500815 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100816 .Build();
817 /* clang-format on */
818
819 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
820 MANIFEST_ERROR_NOT_COMPATIBLE);
821}
822
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100823TEST_F(manifest, ffa_missing_property)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100824{
Olivier Deprez93644652022-09-09 11:01:12 +0200825 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100826
827 /* clang-format off */
828 std::vector<char> dtb = ManifestDtBuilder()
829 .Compatible({ "arm,ffa-manifest-1.0" })
830 .Property("ffa-version", "<0x10000>")
831 .Build();
832 /* clang-format on */
833
834 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
835 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
836}
837
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100838TEST_F(manifest, ffa_validate_sanity_check)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100839{
J-Alvesb37fd082020-10-22 12:29:21 +0100840 /*
841 * TODO: write test excluding all optional fields of the manifest, in
842 * accordance with specification.
843 */
Olivier Deprez93644652022-09-09 11:01:12 +0200844 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100845
846 /* Incompatible version */
847 /* clang-format off */
848 std::vector<char> dtb = ManifestDtBuilder()
849 .Compatible({ "arm,ffa-manifest-1.0" })
850 .Property("ffa-version", "<0xa1>")
851 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
852 .Property("execution-ctx-count", "<1>")
853 .Property("exception-level", "<2>")
854 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000855 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100856 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100857 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100858 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500859 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100860 .Build();
861 /* clang-format on */
862 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
863 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200864 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100865
866 /* Incompatible translation granule */
867 /* clang-format off */
868 dtb = ManifestDtBuilder()
869 .Compatible({ "arm,ffa-manifest-1.0" })
870 .Property("ffa-version", "<0x10000>")
871 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
872 .Property("execution-ctx-count", "<1>")
873 .Property("exception-level", "<2>")
874 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000875 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100876 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100877 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100878 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500879 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100880 .Build();
881 /* clang-format on */
882 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
883 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200884 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100885
886 /* Incompatible exeption level */
887 /* clang-format off */
888 dtb = ManifestDtBuilder()
889 .Compatible({ "arm,ffa-manifest-1.0" })
890 .Property("ffa-version", "<0x10000>")
891 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
892 .Property("execution-ctx-count", "<1>")
Daniel Boulby874d5432023-04-27 12:40:24 +0100893 .Property("exception-level", "<10>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100894 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000895 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100896 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100897 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100898 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500899 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100900 .Build();
901 /* clang-format on */
902 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
903 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200904 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100905
906 /* Incompatible execution state */
907 /* clang-format off */
908 dtb = ManifestDtBuilder()
909 .Compatible({ "arm,ffa-manifest-1.0" })
910 .Property("ffa-version", "<0x10000>")
911 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
912 .Property("execution-ctx-count", "<1>")
913 .Property("exception-level", "<2>")
914 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000915 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100916 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100917 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100918 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500919 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100920 .Build();
921 /* clang-format on */
922 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
923 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200924 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100925
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400926 /* Incompatible messaging method - unrecognized messaging-method. */
927 /* clang-format off */
928 dtb = ManifestDtBuilder()
929 .Compatible({ "arm,ffa-manifest-1.0" })
930 .Property("ffa-version", "<0x10002>")
931 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
932 .Property("execution-ctx-count", "<1>")
933 .Property("exception-level", "<2>")
934 .Property("execution-state", "<0>")
935 .Property("entrypoint-offset", "<0x00002000>")
936 .Property("xlat-granule", "<0>")
937 .Property("boot-order", "<0>")
938 .Property("messaging-method", "<0x272>")
939 .Property("ns-interrupts-action", "<0>")
940 .Build();
941 /* clang-format on */
942 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
943 MANIFEST_ERROR_NOT_COMPATIBLE);
944 manifest_dealloc();
945
946 /* Incompatible messaging method - only endpoints using FF-A version >=
947 * FF-A v1.2 are allowed to set FFA_PARTITION_DIRECT_REQ2_RECV and
948 * FFA_PARTITION_DIRECT_REQ2_SEND. */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100949 /* clang-format off */
950 dtb = ManifestDtBuilder()
951 .Compatible({ "arm,ffa-manifest-1.0" })
952 .Property("ffa-version", "<0x10000>")
953 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
954 .Property("execution-ctx-count", "<1>")
955 .Property("exception-level", "<2>")
956 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000957 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100958 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100959 .Property("boot-order", "<0>")
Kathleen Capellaf71dee42023-08-08 16:24:14 -0400960 .Property("messaging-method", "<0x204>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500961 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100962 .Build();
963 /* clang-format on */
964 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
965 MANIFEST_ERROR_NOT_COMPATIBLE);
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600966
967 /*
968 * No need to invoke manifest_dealloac() since manifest TearDown calls
969 * it when the test ends.
970 */
971}
972
973TEST_F(manifest, ffa_validate_interrupt_actions)
974{
975 struct_manifest *m;
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500976
977 /* Incompatible NS interrupt action */
978 /* clang-format off */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600979 std::vector<char> dtb = ManifestDtBuilder()
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500980 .Compatible({ "arm,ffa-manifest-1.0" })
981 .Property("ffa-version", "<0x10000>")
982 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
983 .Property("execution-ctx-count", "<1>")
984 .Property("exception-level", "<2>")
985 .Property("execution-state", "<0>")
986 .Property("entrypoint-offset", "<0x00002000>")
987 .Property("xlat-granule", "<0>")
988 .Property("boot-order", "<0>")
989 .Property("messaging-method", "<1>")
990 .Property("ns-interrupts-action", "<4>")
991 .Build();
992 /* clang-format on */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600993 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
994 MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
Madhukar Pappireddyee736ad2022-12-28 11:37:09 -0600995 manifest_dealloc();
996
997 /* Incompatible other-s-interrupts-action for S-EL1 partition */
998 /* clang-format off */
999 dtb = ManifestDtBuilder()
1000 .Compatible({ "arm,ffa-manifest-1.0" })
1001 .Property("ffa-version", "<0x10000>")
1002 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1003 .Property("execution-ctx-count", "<1>")
1004 .Property("exception-level", "<2>")
1005 .Property("execution-state", "<0>")
1006 .Property("entrypoint-offset", "<0x00002000>")
1007 .Property("xlat-granule", "<0>")
1008 .Property("boot-order", "<0>")
1009 .Property("messaging-method", "<1>")
1010 .Property("ns-interrupts-action", "<1>")
1011 .Property("other-s-interrupts-action", "<0>")
1012 .Build();
1013 /* clang-format on */
1014 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1015 MANIFEST_ERROR_NOT_COMPATIBLE);
1016 manifest_dealloc();
1017
1018 /*
1019 * Incompatible choice of the fields ns-interrupts-action and
1020 * other-s-interrupts-action.
1021 */
1022 /* clang-format off */
1023 dtb = ManifestDtBuilder()
1024 .Compatible({ "arm,ffa-manifest-1.0" })
1025 .Property("ffa-version", "<0x10000>")
1026 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1027 .Property("execution-ctx-count", "<1>")
1028 .Property("exception-level", "<1>")
1029 .Property("execution-state", "<0>")
1030 .Property("entrypoint-offset", "<0x00002000>")
1031 .Property("xlat-granule", "<0>")
1032 .Property("boot-order", "<0>")
1033 .Property("messaging-method", "<1>")
1034 .Property("ns-interrupts-action", "<2>")
1035 .Property("other-s-interrupts-action", "<0>")
1036 .Build();
1037 /* clang-format on */
1038 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1039 MANIFEST_ERROR_NOT_COMPATIBLE);
1040 manifest_dealloc();
1041
1042 /* Illegal value specified for the field other-s-interrupts-action. */
1043 /* clang-format off */
1044 dtb = ManifestDtBuilder()
1045 .Compatible({ "arm,ffa-manifest-1.0" })
1046 .Property("ffa-version", "<0x10000>")
1047 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1048 .Property("execution-ctx-count", "<1>")
1049 .Property("exception-level", "<1>")
1050 .Property("execution-state", "<0>")
1051 .Property("entrypoint-offset", "<0x00002000>")
1052 .Property("xlat-granule", "<0>")
1053 .Property("boot-order", "<0>")
1054 .Property("messaging-method", "<1>")
1055 .Property("other-s-interrupts-action", "<2>")
1056 .Build();
1057 /* clang-format on */
1058 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1059 MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001060}
1061
Karl Meakin18694022024-08-02 13:59:25 +01001062TEST_F(manifest, vm_availability_messages)
1063{
1064 struct manifest_vm *vm;
1065 struct_manifest *m;
1066 std::vector<char> dtb;
1067
1068 /* clang-format off */
1069 dtb = ManifestDtBuilder()
1070 .Compatible({ "arm,ffa-manifest-1.0" })
1071 .Property("ffa-version", "<0x10001>")
1072 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1073 .Property("execution-ctx-count", "<8>")
1074 .Property("exception-level", "<2>")
1075 .Property("execution-state", "<0>")
1076 .Property("entrypoint-offset", "<0x00002000>")
1077 .Property("messaging-method", "<1>")
1078 .Property("vm-availability-messages", "<0>")
1079 .Build();
1080 /* clang-format on */
1081 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1082 vm = &m->vm[0];
1083 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1084 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1085 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1086 manifest_dealloc();
1087
1088 /* clang-format off */
1089 dtb = ManifestDtBuilder()
1090 .Compatible({ "arm,ffa-manifest-1.0" })
1091 .Property("ffa-version", "<0x10001>")
1092 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1093 .Property("execution-ctx-count", "<8>")
1094 .Property("exception-level", "<2>")
1095 .Property("execution-state", "<0>")
1096 .Property("entrypoint-offset", "<0x00002000>")
1097 .Property("messaging-method", "<1>")
1098 .Property("vm-availability-messages", "<1>")
1099 .Build();
1100 /* clang-format on */
1101 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1102 vm = &m->vm[0];
1103 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1104 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1105 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1106 manifest_dealloc();
1107
1108 /* clang-format off */
1109 dtb = ManifestDtBuilder()
1110 .Compatible({ "arm,ffa-manifest-1.0" })
1111 .Property("ffa-version", "<0x10001>")
1112 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1113 .Property("execution-ctx-count", "<8>")
1114 .Property("exception-level", "<2>")
1115 .Property("execution-state", "<0>")
1116 .Property("entrypoint-offset", "<0x00002000>")
1117 .Property("messaging-method", "<1>")
1118 .Property("vm-availability-messages", "<2>")
1119 .Build();
1120 /* clang-format on */
1121 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1122 vm = &m->vm[0];
1123 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1124 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1125 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1126 manifest_dealloc();
1127
1128 /* clang-format off */
1129 dtb = ManifestDtBuilder()
1130 .Compatible({ "arm,ffa-manifest-1.0" })
1131 .Property("ffa-version", "<0x10001>")
1132 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1133 .Property("execution-ctx-count", "<8>")
1134 .Property("exception-level", "<2>")
1135 .Property("execution-state", "<0>")
1136 .Property("entrypoint-offset", "<0x00002000>")
1137 .Property("messaging-method", "<1>")
1138 .Property("vm-availability-messages", "<3>")
1139 .Build();
1140 /* clang-format on */
1141 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1142 vm = &m->vm[0];
1143 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 1);
1144 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 1);
1145 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1146 manifest_dealloc();
1147
1148 /* clang-format off */
1149 dtb = ManifestDtBuilder()
1150 .Compatible({ "arm,ffa-manifest-1.0" })
1151 .Property("ffa-version", "<0x10001>")
1152 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1153 .Property("execution-ctx-count", "<8>")
1154 .Property("exception-level", "<2>")
1155 .Property("execution-state", "<0>")
1156 .Property("entrypoint-offset", "<0x00002000>")
1157 .Property("messaging-method", "<1>")
1158 .Build();
1159 /* clang-format on */
1160 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1161 vm = &m->vm[0];
1162 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1163 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1164 ASSERT_EQ(vm->partition.vm_availability_messages.mbz, 0);
1165 manifest_dealloc();
1166
1167 /* clang-format off */
1168 dtb = ManifestDtBuilder()
1169 .Compatible({ "arm,ffa-manifest-1.0" })
1170 .Property("ffa-version", "<0x10001>")
1171 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1172 .Property("execution-ctx-count", "<8>")
1173 .Property("exception-level", "<2>")
1174 .Property("execution-state", "<0>")
1175 .Property("entrypoint-offset", "<0x00002000>")
1176 .Property("messaging-method", "<2>")
1177 .Property("vm-availability-messages", "<4>")
1178 .Build();
1179 /* clang-format on */
1180 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1181 MANIFEST_ERROR_VM_AVAILABILITY_MESSAGE_INVALID);
1182 vm = &m->vm[0];
1183 ASSERT_EQ(vm->partition.vm_availability_messages.vm_created, 0);
1184 ASSERT_EQ(vm->partition.vm_availability_messages.vm_destroyed, 0);
1185 ASSERT_NE(vm->partition.vm_availability_messages.mbz, 0);
1186 manifest_dealloc();
1187}
1188
Olivier Depreza15f2352022-09-26 09:17:24 +02001189TEST_F(manifest, power_management)
1190{
1191 struct manifest_vm *vm;
1192 struct_manifest *m;
1193
1194 /* S-EL1 partition power management field can set bit 0. */
1195 /* clang-format off */
1196 std::vector<char> dtb = ManifestDtBuilder()
1197 .Compatible({ "arm,ffa-manifest-1.0" })
1198 .Property("ffa-version", "<0x10001>")
1199 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1200 .Property("execution-ctx-count", "<8>")
1201 .Property("exception-level", "<2>")
1202 .Property("execution-state", "<0>")
1203 .Property("entrypoint-offset", "<0x00002000>")
1204 .Property("messaging-method", "<1>")
1205 .Property("power-management-messages", "<1>")
1206 .Build();
1207 /* clang-format on */
1208 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1209 vm = &m->vm[0];
1210 ASSERT_EQ(vm->partition.power_management, 1);
1211 manifest_dealloc();
1212
1213 /* S-EL1 partition power management field can set bit 3. */
1214 /* clang-format off */
1215 dtb = ManifestDtBuilder()
1216 .Compatible({ "arm,ffa-manifest-1.0" })
1217 .Property("ffa-version", "<0x10001>")
1218 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1219 .Property("execution-ctx-count", "<8>")
1220 .Property("exception-level", "<2>")
1221 .Property("execution-state", "<0>")
1222 .Property("entrypoint-offset", "<0x00002000>")
1223 .Property("messaging-method", "<1>")
1224 .Property("power-management-messages", "<8>")
1225 .Build();
1226 /* clang-format on */
1227 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1228 vm = &m->vm[0];
1229 ASSERT_EQ(vm->partition.power_management, 8);
1230 manifest_dealloc();
1231
1232 /* S-EL1 partition power management field can only set bits 0 and 3. */
1233 /* clang-format off */
1234 dtb = ManifestDtBuilder()
1235 .Compatible({ "arm,ffa-manifest-1.0" })
1236 .Property("ffa-version", "<0x10001>")
1237 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1238 .Property("execution-ctx-count", "<8>")
1239 .Property("exception-level", "<2>")
1240 .Property("execution-state", "<0>")
1241 .Property("entrypoint-offset", "<0x00002000>")
1242 .Property("messaging-method", "<1>")
1243 .Property("power-management-messages", "<0xf>")
1244 .Build();
1245 /* clang-format on */
1246 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1247 vm = &m->vm[0];
1248 ASSERT_EQ(vm->partition.power_management, 9);
1249 manifest_dealloc();
1250
1251 /* S-EL0 partition power management field is forced to 0. */
1252 /* clang-format off */
1253 dtb = ManifestDtBuilder()
1254 .Compatible({ "arm,ffa-manifest-1.0" })
1255 .Property("ffa-version", "<0x10001>")
1256 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1257 .Property("execution-ctx-count", "<1>")
1258 .Property("exception-level", "<1>")
1259 .Property("execution-state", "<0>")
1260 .Property("entrypoint-offset", "<0x00002000>")
1261 .Property("messaging-method", "<1>")
1262 .Property("power-management-messages", "<0xff>")
1263 .Build();
1264 /* clang-format on */
1265 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1266 vm = &m->vm[0];
1267 ASSERT_EQ(vm->partition.power_management, 0);
1268}
1269
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001270TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001271{
Olivier Deprez93644652022-09-09 11:01:12 +02001272 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001273
1274 /* Not Compatible */
1275 /* clang-format off */
1276 std::vector<char> dtb = ManifestDtBuilder()
1277 .FfaValidManifest()
1278 .StartChild("rx_tx-info")
1279 .Compatible({ "foo,bar" })
1280 .EndChild()
1281 .Build();
1282 /* clang-format on */
1283 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1284 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001285 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001286
1287 /* Missing Properties */
1288 /* clang-format off */
1289 dtb = ManifestDtBuilder()
1290 .FfaValidManifest()
1291 .StartChild("rx_tx-info")
1292 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1293 .EndChild()
1294 .Build();
1295 /* clang-format on */
1296 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1297 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1298}
1299
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001300TEST_F(manifest, ffa_validate_mem_regions)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001301{
Olivier Deprez93644652022-09-09 11:01:12 +02001302 struct_manifest *m;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001303
1304 /* Not Compatible */
1305 /* clang-format off */
1306 std::vector<char> dtb = ManifestDtBuilder()
1307 .FfaValidManifest()
1308 .StartChild("memory-regions")
1309 .Compatible({ "foo,bar" })
1310 .EndChild()
1311 .Build();
1312 /* clang-format on */
1313 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1314 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001315 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001316
1317 /* Memory regions unavailable */
1318 /* clang-format off */
1319 dtb = ManifestDtBuilder()
1320 .FfaValidManifest()
1321 .StartChild("memory-regions")
1322 .Compatible({ "arm,ffa-manifest-memory-regions" })
1323 .EndChild()
1324 .Build();
1325 /* clang-format on */
1326 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1327 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001328 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001329
1330 /* Missing Properties */
1331 /* clang-format off */
1332 dtb = ManifestDtBuilder()
1333 .FfaValidManifest()
1334 .StartChild("memory-regions")
1335 .Compatible({ "arm,ffa-manifest-memory-regions" })
1336 .StartChild("test-memory")
1337 .Description("test-memory")
1338 .EndChild()
1339 .EndChild()
1340 .Build();
1341 /* clang-format on */
1342 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1343 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001344 manifest_dealloc();
Manish Pandeyf06c9072020-09-29 15:41:58 +01001345
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001346 /* Empty memory region */
1347 /* clang-format off */
1348 dtb = ManifestDtBuilder()
1349 .FfaValidManifest()
1350 .StartChild("memory-regions")
1351 .Compatible({ "arm,ffa-manifest-memory-regions" })
1352 .Label("rx")
1353 .StartChild("rx")
1354 .Description("rx-buffer")
1355 .Property("base-address", "<0x7300000>")
1356 .Property("pages-count", "<0>")
1357 .Property("attributes", "<1>")
1358 .EndChild()
1359 .Label("tx")
1360 .StartChild("tx")
1361 .Description("tx-buffer")
1362 .Property("base-address", "<0x7310000>")
1363 .Property("pages-count", "<2>")
1364 .Property("attributes", "<3>")
1365 .EndChild()
1366 .EndChild()
1367 .StartChild("rx_tx-info")
1368 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1369 .Property("rx-buffer", "<&rx>")
1370 .Property("tx-buffer", "<&tx>")
1371 .EndChild()
1372 .Build();
1373 /* clang-format on */
1374 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1375 MANIFEST_ERROR_MEM_REGION_EMPTY);
1376 manifest_dealloc();
1377
Davidson K8ccd2d02024-09-03 16:10:54 +05301378 /* Mutually exclusive base-address and load-address-relative-offset
1379 * properties */
Karl Meakine92efbe2023-06-01 14:16:22 +01001380 /* clang-format off */
1381 dtb = ManifestDtBuilder()
1382 .FfaValidManifest()
1383 .StartChild("memory-regions")
1384 .Compatible({ "arm,ffa-manifest-memory-regions" })
1385 .Label("rx")
1386 .StartChild("rx")
1387 .Description("rx-buffer")
1388 .Property("base-address", "<0x7300000>")
Davidson K8ccd2d02024-09-03 16:10:54 +05301389 .Property("load-address-relative-offset", "<0x7300000>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001390 .Property("pages-count", "<1>")
1391 .Property("attributes", "<1>")
1392 .EndChild()
1393 .EndChild()
1394 .Build();
1395 /* clang-format on */
1396 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1397 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1398 manifest_dealloc();
1399 /* Relative-address overflow*/
1400 /* clang-format off */
1401 dtb = ManifestDtBuilder()
1402 .FfaValidManifest()
1403 .Property("load-address", "<0xffffff00 0xffffff00>")
1404 .StartChild("memory-regions")
1405 .Compatible({ "arm,ffa-manifest-memory-regions" })
1406 .Label("rx")
1407 .StartChild("rx")
1408 .Description("rx-buffer")
Davidson K8ccd2d02024-09-03 16:10:54 +05301409 .Property("load-address-relative-offset", "<0xffffff00 0xffffff00>")
Karl Meakine92efbe2023-06-01 14:16:22 +01001410 .Property("pages-count", "<1>")
1411 .Property("attributes", "<1>")
1412 .EndChild()
1413 .EndChild()
1414 .Build();
1415 /* clang-format on */
1416 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1417 MANIFEST_ERROR_INTEGER_OVERFLOW);
1418 manifest_dealloc();
1419
Daniel Boulby9279b552022-06-28 17:04:01 +01001420 /* Overlapping memory regions */
1421 /* clang-format off */
1422 dtb = ManifestDtBuilder()
1423 .FfaValidManifest()
1424 .StartChild("memory-regions")
1425 .Compatible({ "arm,ffa-manifest-memory-regions" })
1426 .Label("rx")
1427 .StartChild("rx")
1428 .Description("rx-buffer")
1429 .Property("base-address", "<0x7300000>")
1430 .Property("pages-count", "<1>")
1431 .Property("attributes", "<1>")
1432 .EndChild()
1433 .Label("tx")
1434 .StartChild("tx")
1435 .Description("tx-buffer")
1436 .Property("base-address", "<0x7300000>")
1437 .Property("pages-count", "<2>")
1438 .Property("attributes", "<3>")
1439 .EndChild()
1440 .EndChild()
1441 .Build();
1442 /* clang-format on */
1443 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1444 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001445 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001446
1447 /* clang-format off */
1448 dtb = ManifestDtBuilder()
1449 .FfaValidManifest()
1450 .StartChild("memory-regions")
1451 .Compatible({ "arm,ffa-manifest-memory-regions" })
1452 .Label("rx")
1453 .StartChild("rx")
1454 .Description("rx-buffer")
1455 .Property("base-address", "<0x7300000>")
1456 .Property("pages-count", "<2>")
1457 .Property("attributes", "<1>")
1458 .EndChild()
1459 .Label("tx")
1460 .StartChild("tx")
1461 .Description("tx-buffer")
1462 .Property("base-address", "<0x7301000>")
1463 .Property("pages-count", "<2>")
1464 .Property("attributes", "<3>")
1465 .EndChild()
1466 .EndChild()
1467 .Build();
1468 /* clang-format on */
1469 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1470 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001471 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001472
1473 /* clang-format off */
1474 dtb = ManifestDtBuilder()
1475 .FfaValidManifest()
1476 .StartChild("memory-regions")
1477 .Compatible({ "arm,ffa-manifest-memory-regions" })
1478 .Label("rx")
1479 .StartChild("rx")
1480 .Description("rx-buffer")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001481 .Property("base-address", "<0x7301000>")
1482 .Property("pages-count", "<1>")
1483 .Property("attributes", "<1>")
1484 .EndChild()
1485 .Label("tx")
1486 .StartChild("tx")
1487 .Description("tx-buffer")
1488 .Property("base-address", "<0x7300000>")
1489 .Property("pages-count", "<2>")
1490 .Property("attributes", "<3>")
1491 .EndChild()
1492 .EndChild()
1493 .Build();
1494 /* clang-format on */
1495 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1496 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001497 manifest_dealloc();
1498
1499 /* Unaligned memory region */
1500 /* clang-format off */
1501 dtb = ManifestDtBuilder()
1502 .FfaValidManifest()
1503 .StartChild("memory-regions")
1504 .Compatible({ "arm,ffa-manifest-memory-regions" })
1505 .Label("rx")
1506 .StartChild("rx")
1507 .Description("rx-buffer")
1508 .Property("base-address", "<0x7300FFF>")
1509 .Property("pages-count", "<2>")
1510 .Property("attributes", "<1>")
1511 .EndChild()
1512 .Label("tx")
1513 .StartChild("tx")
1514 .Description("tx-buffer")
1515 .Property("base-address", "<0x7303000>")
1516 .Property("pages-count", "<2>")
1517 .Property("attributes", "<3>")
1518 .EndChild()
1519 .EndChild()
1520 .Build();
1521 /* clang-format on */
1522 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1523 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1524 manifest_dealloc();
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001525
Manish Pandeyf06c9072020-09-29 15:41:58 +01001526 /* Different RXTX buffer sizes */
1527 /* clang-format off */
1528 dtb = ManifestDtBuilder()
1529 .FfaValidManifest()
1530 .StartChild("memory-regions")
1531 .Compatible({ "arm,ffa-manifest-memory-regions" })
1532 .Label("rx")
1533 .StartChild("rx")
1534 .Description("rx-buffer")
1535 .Property("base-address", "<0x7300000>")
1536 .Property("pages-count", "<1>")
1537 .Property("attributes", "<1>")
1538 .EndChild()
1539 .Label("tx")
1540 .StartChild("tx")
1541 .Description("tx-buffer")
1542 .Property("base-address", "<0x7310000>")
1543 .Property("pages-count", "<2>")
1544 .Property("attributes", "<3>")
1545 .EndChild()
1546 .EndChild()
1547 .StartChild("rx_tx-info")
1548 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1549 .Property("rx-buffer", "<&rx>")
1550 .Property("tx-buffer", "<&tx>")
1551 .EndChild()
1552 .Build();
1553 /* clang-format on */
1554 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1555 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001556}
1557
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001558TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001559{
Olivier Deprez93644652022-09-09 11:01:12 +02001560 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001561
1562 /* Not Compatible */
1563 /* clang-format off */
1564 std::vector<char> dtb = ManifestDtBuilder()
1565 .FfaValidManifest()
1566 .StartChild("device-regions")
1567 .Compatible({ "foo,bar" })
1568 .EndChild()
1569 .Build();
1570 /* clang-format on */
1571 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1572 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001573 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001574
1575 /* Memory regions unavailable */
1576 /* clang-format off */
1577 dtb = ManifestDtBuilder()
1578 .FfaValidManifest()
1579 .StartChild("device-regions")
1580 .Compatible({ "arm,ffa-manifest-device-regions" })
1581 .EndChild()
1582 .Build();
1583 /* clang-format on */
1584 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1585 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001586 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001587
1588 /* Missing Properties */
1589 /* clang-format off */
1590 dtb = ManifestDtBuilder()
1591 .FfaValidManifest()
1592 .StartChild("device-regions")
1593 .Compatible({ "arm,ffa-manifest-device-regions" })
1594 .StartChild("test-device")
1595 .Description("test-device")
1596 .EndChild()
1597 .EndChild()
1598 .Build();
1599 /* clang-format on */
1600 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1601 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001602 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001603
1604 /* Malformed interrupt list pair */
1605 /* clang-format off */
1606 dtb = ManifestDtBuilder()
1607 .FfaValidManifest()
1608 .StartChild("device-regions")
1609 .Compatible({ "arm,ffa-manifest-device-regions" })
1610 .StartChild("test-device")
1611 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001612 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001613 .Property("pages-count", "<16>")
1614 .Property("attributes", "<3>")
1615 .Property("smmu-id", "<1>")
1616 .Property("stream-ids", "<0 1>")
1617 .Property("interrupts", "<2 3>, <4>")
1618 .EndChild()
1619 .EndChild()
1620 .Build();
1621 /* clang-format on */
1622 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1623 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001624 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001625
1626 /* Non-unique interrupt IDs */
1627 /* clang-format off */
1628 dtb = ManifestDtBuilder()
1629 .FfaValidManifest()
1630 .StartChild("device-regions")
1631 .Compatible({ "arm,ffa-manifest-device-regions" })
1632 .StartChild("test-device-0")
1633 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001634 .Property("base-address", "<0x24000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001635 .Property("pages-count", "<16>")
1636 .Property("attributes", "<3>")
1637 .Property("interrupts", "<2 3>")
1638 .EndChild()
1639 .StartChild("test-device-1")
1640 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001641 .Property("base-address", "<0x25000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001642 .Property("pages-count", "<16>")
1643 .Property("attributes", "<3>")
1644 .Property("interrupts", "<1 3>, <2 5> ")
1645 .EndChild()
1646 .EndChild()
1647 .Build();
Daniel Boulby941ef342023-11-21 13:47:15 +00001648
Daniel Boulby667334f2022-06-27 15:23:21 +01001649 /* clang-format on */
1650 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1651 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1652 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001653 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1654 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1655 3);
1656 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1657 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1658 3);
Daniel Boulby941ef342023-11-21 13:47:15 +00001659 manifest_dealloc();
1660
1661 /* Overlapping address space between two device region nodes. */
1662 /* clang-format off */
1663 dtb = ManifestDtBuilder()
1664 .FfaValidManifest()
1665 .StartChild("device-regions")
1666 .Compatible({"arm,ffa-manifest-device-regions"})
1667 .StartChild("test-device-0")
1668 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001669 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001670 .Property("pages-count", "<16>")
1671 .Property("attributes", "<3>")
1672 .EndChild()
1673 .StartChild("test-device-1")
1674 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001675 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001676 .Property("pages-count", "<16>")
1677 .Property("attributes", "<3>")
1678 .EndChild()
Daniel Boulby4339edc2024-02-21 14:59:00 +00001679 .EndChild()
Daniel Boulby941ef342023-11-21 13:47:15 +00001680 .Build();
1681
1682 /* clang-format on */
1683 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1684 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1685 manifest_dealloc();
1686
1687 /*
Daniel Boulby4339edc2024-02-21 14:59:00 +00001688 * Device regions cannot be defined outside of the regions specified in
1689 * the spmc.
Daniel Boulby941ef342023-11-21 13:47:15 +00001690 */
1691 /* clang-format off */
1692 dtb = ManifestDtBuilder()
1693 .FfaValidManifest()
Daniel Boulby941ef342023-11-21 13:47:15 +00001694 .StartChild("device-regions")
1695 .Compatible({"arm,ffa-manifest-device-regions"})
1696 .StartChild("test-device-0")
1697 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001698 .Property("base-address", "<0x50000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001699 .Property("pages-count", "<16>")
1700 .Property("attributes", "<3>")
1701 .EndChild()
1702 .EndChild()
1703 .Build();
1704 /* clang-format on */
1705 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
Daniel Boulby4339edc2024-02-21 14:59:00 +00001706 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
1707 manifest_dealloc();
1708
1709 /*
1710 * Memory defined as NS in SPMC manifest given Secure attribute should
1711 * fail.
1712 */
1713 /* clang-format off */
1714 dtb = ManifestDtBuilder()
1715 .FfaValidManifest()
1716 .StartChild("device-regions")
1717 .Compatible({"arm,ffa-manifest-device-regions"})
1718 .StartChild("test-device-0")
1719 .Description("test-device-0")
1720 .Property("base-address", "<0x20000000>")
1721 .Property("pages-count", "<16>")
1722 .Property("attributes", "<3>")
1723 .EndChild()
1724 .EndChild()
1725 .Build();
1726 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1727 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
Manish Pandeye68e7932020-04-23 15:29:28 +01001728}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001729
1730TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001731{
Olivier Deprez93644652022-09-09 11:01:12 +02001732 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001733
1734 /* clang-format off */
1735 std::vector<char> dtb = ManifestDtBuilder()
1736 .FfaValidManifest()
1737 .StartChild("rx_tx-info")
1738 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1739 .Property("rx-buffer", "<&rx>")
1740 .Property("tx-buffer", "<&tx>")
1741 .EndChild()
1742 .StartChild("memory-regions")
1743 .Compatible({ "arm,ffa-manifest-memory-regions" })
1744 .StartChild("test-memory")
1745 .Description("test-memory")
1746 .Property("base-address", "<0x7100000>")
1747 .Property("pages-count", "<4>")
1748 .Property("attributes", "<7>")
1749 .EndChild()
1750 .Label("rx")
1751 .StartChild("rx")
1752 .Description("rx-buffer")
1753 .Property("base-address", "<0x7300000>")
1754 .Property("pages-count", "<1>")
1755 .Property("attributes", "<1>")
1756 .EndChild()
1757 .Label("tx")
1758 .StartChild("tx")
1759 .Description("tx-buffer")
1760 .Property("base-address", "<0x7310000>")
1761 .Property("pages-count", "<1>")
1762 .Property("attributes", "<3>")
1763 .EndChild()
1764 .EndChild()
1765 .Build();
1766 /* clang-format on */
1767
1768 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1769 MANIFEST_ERROR_INVALID_MEM_PERM);
1770}
1771
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001772TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001773{
Olivier Deprez93644652022-09-09 11:01:12 +02001774 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001775
1776 /* clang-format off */
1777 std::vector<char> dtb = ManifestDtBuilder()
1778 .FfaValidManifest()
1779 .StartChild("rx_tx-info")
1780 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1781 .Property("rx-buffer", "<&rx>")
1782 .Property("tx-buffer", "<&tx>")
1783 .EndChild()
1784 .StartChild("memory-regions")
1785 .Compatible({ "arm,ffa-manifest-memory-regions" })
1786 .StartChild("test-memory")
1787 .Description("test-memory")
1788 .Property("base-address", "<0x7100000>")
1789 .Property("pages-count", "<4>")
1790 .Property("attributes", "<3>")
1791 .EndChild()
1792 .Label("rx")
1793 .StartChild("rx")
1794 .Description("rx-buffer")
1795 .Property("base-address", "<0x7300000>")
1796 .Property("pages-count", "<1>")
1797 .Property("attributes", "<1>")
1798 .EndChild()
1799 .Label("tx")
1800 .StartChild("tx")
1801 .Description("tx-buffer")
1802 .Property("base-address", "<0x7310000>")
1803 .Property("pages-count", "<1>")
1804 .Property("attributes", "<3>")
1805 .EndChild()
1806 .EndChild()
1807 .StartChild("device-regions")
1808 .Compatible({ "arm,ffa-manifest-device-regions" })
1809 .StartChild("test-device")
1810 .Description("test-device")
1811 .Property("base-address", "<0x7200000>")
1812 .Property("pages-count", "<16>")
1813 .Property("attributes", "<5>")
1814 .Property("smmu-id", "<1>")
1815 .Property("stream-ids", "<0 1>")
1816 .Property("interrupts", "<2 3>, <4 5>")
1817 .EndChild()
1818 .EndChild()
1819 .Build();
1820 /* clang-format on */
1821
1822 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1823 MANIFEST_ERROR_INVALID_MEM_PERM);
1824}
Manish Pandeye68e7932020-04-23 15:29:28 +01001825
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001826TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01001827{
Olivier Deprez93644652022-09-09 11:01:12 +02001828 struct manifest_vm *vm;
1829 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01001830
1831 /* clang-format off */
1832 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001833 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001834 .StartChild("rx_tx-info")
1835 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1836 .Property("rx-buffer", "<&rx>")
1837 .Property("tx-buffer", "<&tx>")
1838 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001839 .StartChild("memory-regions")
1840 .Compatible({ "arm,ffa-manifest-memory-regions" })
Olivier Deprez035fa152022-03-14 11:19:10 +01001841 .StartChild("test-memory-ns")
1842 .Description("test-memory")
1843 .Property("base-address", "<0x7200000>")
1844 .Property("pages-count", "<1>")
1845 .Property("attributes", "<0xb>")
1846 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001847 .Label("rx")
1848 .StartChild("rx")
1849 .Description("rx-buffer")
1850 .Property("base-address", "<0x7300000>")
1851 .Property("pages-count", "<1>")
1852 .Property("attributes", "<1>")
1853 .EndChild()
1854 .Label("tx")
1855 .StartChild("tx")
1856 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001857 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001858 .Property("pages-count", "<1>")
1859 .Property("attributes", "<3>")
1860 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001861 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001862 .StartChild("device-regions")
1863 .Compatible({ "arm,ffa-manifest-device-regions" })
1864 .StartChild("test-device")
1865 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001866 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001867 .Property("pages-count", "<16>")
1868 .Property("attributes", "<3>")
1869 .Property("smmu-id", "<1>")
1870 .Property("stream-ids", "<0 1>")
1871 .Property("interrupts", "<2 3>, <4 5>")
1872 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001873 .StartChild("test-device-ns")
1874 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001875 .Property("base-address", "<0x20000000>")
Olivier Deprez035fa152022-03-14 11:19:10 +01001876 .Property("pages-count", "<1>")
1877 .Property("attributes", "<0x9>")
1878 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001879 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001880 .Build();
Daniel Boulby4339edc2024-02-21 14:59:00 +00001881
Olivier Deprez62d99e32020-01-09 15:58:07 +01001882 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01001883 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1884
Olivier Deprez93644652022-09-09 11:01:12 +02001885 vm = &m->vm[0];
1886 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001887 ASSERT_THAT(
Kathleen Capella422b10b2023-06-30 18:28:27 -04001888 std::span(vm->partition.uuids[0].uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001889 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02001890 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
1891 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
1892 ASSERT_EQ(vm->partition.execution_state, AARCH64);
1893 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
1894 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
1895 ASSERT_EQ(vm->partition.boot_order, 0);
1896 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
1897 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
Davidson K5d5f2792024-08-19 19:09:12 +05301898 ASSERT_EQ(vm->partition.mem_regions[0].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001899
Olivier Deprez93644652022-09-09 11:01:12 +02001900 ASSERT_EQ(vm->partition.rxtx.available, true);
1901 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
1902 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
1903 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
1904 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
1905 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
1906 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
1907
Daniel Boulby4339edc2024-02-21 14:59:00 +00001908 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Olivier Deprez93644652022-09-09 11:01:12 +02001909 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02001910 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05001911 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
1912 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
1913 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Olivier Deprez93644652022-09-09 11:01:12 +02001914 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1915 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1916 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1917 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
Daniel Boulby4339edc2024-02-21 14:59:00 +00001918 ASSERT_EQ(vm->partition.dev_regions[1].base_address, 0x20000000);
Olivier Deprez058ddee2024-08-27 09:22:11 +02001919 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01001920}
1921
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001922TEST_F(manifest, ffa_valid_interrupt_target_manifest)
1923{
1924 struct manifest_vm *vm;
1925 struct_manifest *m;
1926
1927 /* clang-format off */
1928 std::vector<char> dtb = ManifestDtBuilder()
1929 .FfaValidManifest()
1930 .StartChild("device-regions")
1931 .Compatible({ "arm,ffa-manifest-device-regions" })
1932 .StartChild("test-device")
1933 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001934 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001935 .Property("pages-count", "<16>")
1936 .Property("attributes", "<3>")
1937 .Property("smmu-id", "<1>")
1938 .Property("stream-ids", "<0 1>")
1939 .Property("interrupts", "<2 3>, <4 5>")
1940 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
1941 .EndChild()
1942 .EndChild()
1943 .Build();
1944 /* clang-format on */
1945
1946 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1947
1948 vm = &m->vm[0];
1949
Daniel Boulby4339edc2024-02-21 14:59:00 +00001950 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001951 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Olivier Deprez058ddee2024-08-27 09:22:11 +02001952 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05001953 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
1954 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
1955 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001956 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1957 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1958 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
1959 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
1960 0x123400005678);
1961 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1962 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
1963 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
1964 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
1965 0x1234567887654321);
1966}
1967
1968TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
1969{
1970 struct_manifest *m;
1971
1972 /* clang-format off */
1973 std::vector<char> dtb = ManifestDtBuilder()
1974 .FfaValidManifest()
1975 .StartChild("device-regions")
1976 .Compatible({ "arm,ffa-manifest-device-regions" })
1977 .StartChild("test-device")
1978 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001979 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001980 .Property("pages-count", "<16>")
1981 .Property("attributes", "<3>")
1982 .Property("smmu-id", "<1>")
1983 .Property("stream-ids", "<0 1>")
1984 .Property("interrupts", "<2 3>, <4 5>")
1985 .Property("interrupts-target", "<20 0x1234 0x5678>")
1986 .EndChild()
1987 .EndChild()
1988 .Build();
1989 /* clang-format on */
1990
1991 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1992 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
1993}
1994
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04001995TEST_F(manifest, ffa_boot_order_not_unique)
1996{
1997 struct_manifest *m;
1998 struct memiter it;
1999 struct mm_stage1_locked mm_stage1_locked;
2000 struct boot_params params;
2001 Partition_package spkg_1;
2002 Partition_package spkg_2;
2003
2004 /* clang-format off */
2005 std::vector<char> dtb1 = ManifestDtBuilder()
2006 .Compatible({ "arm,ffa-manifest-1.0" })
2007 .Property("ffa-version", "<0x10001>")
2008 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2009 .FfaLoadAddress((uint64_t)&spkg_1)
2010 .Property("execution-ctx-count", "<1>")
2011 .Property("exception-level", "<1>")
2012 .Property("execution-state", "<0>")
2013 .Property("entrypoint-offset", "<0x00002000>")
2014 .Property("xlat-granule", "<0>")
2015 .Property("boot-order", "<1>")
2016 .Property("messaging-method", "<1>")
2017 .Property("ns-interrupts-action", "<0>")
2018 .Build();
2019
2020 std::vector<char> dtb2 = ManifestDtBuilder()
2021 .Compatible({ "arm,ffa-manifest-1.0" })
2022 .Property("ffa-version", "<0x10001>")
2023 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2024 .FfaLoadAddress((uint64_t)&spkg_2)
2025 .Property("execution-ctx-count", "<1>")
2026 .Property("exception-level", "<1>")
2027 .Property("execution-state", "<0>")
2028 .Property("entrypoint-offset", "<0x00002000>")
2029 .Property("xlat-granule", "<0>")
2030 .Property("boot-order", "<1>")
2031 .Property("messaging-method", "<1>")
2032 .Property("ns-interrupts-action", "<0>")
2033 .Build();
2034
2035 /* clang-format on */
2036 spkg_1.init(dtb1);
2037 spkg_2.init(dtb2);
2038
2039 /* clang-format off */
2040 std::vector<char> core_dtb = ManifestDtBuilder()
2041 .StartChild("hypervisor")
2042 .Compatible()
2043 .StartChild("vm1")
2044 .DebugName("ffa_partition_1")
2045 .FfaPartition()
2046 .LoadAddress((uint64_t)&spkg_1)
2047 .VcpuCount(1)
2048 .MemSize(0x10000000)
2049 .EndChild()
2050 .StartChild("vm2")
2051 .DebugName("ffa_partition_2")
2052 .FfaPartition()
2053 .LoadAddress((uint64_t)&spkg_2)
2054 .VcpuCount(1)
2055 .MemSize(0x10000000)
2056 .EndChild()
2057 .EndChild()
2058 .Build();
2059 /* clang-format on */
2060
2061 boot_params_init(&params, nullptr);
2062 memiter_init(&it, core_dtb.data(), core_dtb.size());
2063 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2064 MANIFEST_ERROR_INVALID_BOOT_ORDER);
2065}
Daniel Boulby941ef342023-11-21 13:47:15 +00002066
Kathleen Capella422b10b2023-06-30 18:28:27 -04002067TEST_F(manifest, ffa_valid_multiple_uuids)
2068{
2069 struct manifest_vm *vm;
2070 struct_manifest *m;
2071
2072 /* clang-format off */
2073 std::vector<char> dtb = ManifestDtBuilder()
2074 .Compatible({ "arm,ffa-manifest-1.0" })
2075 .Property("ffa-version", "<0x10002>")
2076 .Property("uuid",
2077 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,\
2078 <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2079 .Property("execution-ctx-count", "<1>")
2080 .Property("exception-level", "<2>")
2081 .Property("execution-state", "<0>")
2082 .Property("entrypoint-offset", "<0x00002000>")
2083 .Property("xlat-granule", "<0>")
2084 .Property("boot-order", "<0>")
2085 .Property("messaging-method", "<4>")
2086 .Property("ns-interrupts-action", "<1>")
2087 .Build();
2088 /* clang-format on */
2089 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
2090
2091 vm = &m->vm[0];
2092 ASSERT_EQ(vm->partition.ffa_version, 0x10002);
2093 ASSERT_THAT(
2094 std::span(vm->partition.uuids[0].uuid, 4),
2095 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
2096 ASSERT_THAT(
2097 std::span(vm->partition.uuids[1].uuid, 4),
2098 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1daaa));
2099 ASSERT_EQ(vm->partition.uuid_count, 2);
2100 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
2101 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
2102 ASSERT_EQ(vm->partition.execution_state, AARCH64);
2103 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
2104 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
2105 ASSERT_EQ(vm->partition.boot_order, 0);
2106 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
2107 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
2108}
Karl Meakin45abeeb2024-08-02 16:55:44 +01002109
2110TEST_F(manifest, ffa_too_many_uuids)
2111{
2112 struct_manifest *m;
2113
2114 /* clang-format off */
2115 std::vector<char> dtb = ManifestDtBuilder()
2116 .Compatible({ "arm,ffa-manifest-1.0" })
2117 .Property("ffa-version", "<0x10002>")
2118 .Property("uuid",
2119 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,"
2120 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2121 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2122 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>,"
2123 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2124 .Property("execution-ctx-count", "<1>")
2125 .Property("exception-level", "<2>")
2126 .Property("execution-state", "<0>")
2127 .Property("entrypoint-offset", "<0x00002000>")
2128 .Property("xlat-granule", "<0>")
2129 .Property("boot-order", "<0>")
2130 .Property("messaging-method", "<4>")
2131 .Property("ns-interrupts-action", "<1>")
2132 .Build();
2133 /* clang-format on */
2134 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2135 MANIFEST_ERROR_TOO_MANY_UUIDS);
2136}
2137
Kathleen Capella422b10b2023-06-30 18:28:27 -04002138TEST_F(manifest, ffa_uuid_all_zeros)
2139{
2140 struct_manifest *m;
2141
2142 /* clang-format off */
2143 std::vector<char> dtb = ManifestDtBuilder()
2144 .Compatible({ "arm,ffa-manifest-1.0" })
2145 .Property("ffa-version", "<0x10002>")
2146 .Property("uuid",
2147 "<0x0 0x0 0x0 0x0>, <0x0 0x0 0x0 0x0>")
2148 .Property("execution-ctx-count", "<1>")
2149 .Property("exception-level", "<2>")
2150 .Property("execution-state", "<0>")
2151 .Property("entrypoint-offset", "<0x00002000>")
2152 .Property("xlat-granule", "<0>")
2153 .Property("boot-order", "<0>")
2154 .Property("messaging-method", "<4>")
2155 .Property("ns-interrupts-action", "<1>")
2156 .Build();
2157 /* clang-format on */
2158 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2159 MANIFEST_ERROR_UUID_ALL_ZEROS);
2160}
Daniel Boulby941ef342023-11-21 13:47:15 +00002161
2162/*
2163 * Test that the address space of two device region nodes specified across
2164 * different SPs cannot overlap.
2165 */
2166TEST_F(manifest, ffa_device_region_multi_sps)
2167{
2168 struct_manifest *m;
2169 struct memiter it;
2170 struct mm_stage1_locked mm_stage1_locked;
2171 struct boot_params params;
2172 Partition_package spkg_1;
2173 Partition_package spkg_2;
2174
2175 /* clang-format off */
2176 std::vector<char> dtb1 = ManifestDtBuilder()
2177 .Compatible({ "arm,ffa-manifest-1.0" })
2178 .Property("ffa-version", "<0x10001>")
2179 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2180 .FfaLoadAddress((uint64_t)&spkg_1)
2181 .Property("execution-ctx-count", "<1>")
2182 .Property("exception-level", "<0>")
2183 .Property("execution-state", "<0>")
2184 .Property("entrypoint-offset", "<0x0>")
2185 .Property("xlat-granule", "<0>")
2186 .Property("messaging-method", "<0x7>")
2187 .StartChild("device-regions")
2188 .Compatible({ "arm,ffa-manifest-device-regions" })
2189 .StartChild("test-device-0")
2190 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002191 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002192 .Property("pages-count", "<16>")
2193 .Property("attributes", "<3>")
2194 .EndChild()
2195 .EndChild()
2196 .Build();
2197
2198 std::vector<char> dtb2 = ManifestDtBuilder()
2199 .Compatible({ "arm,ffa-manifest-1.0" })
2200 .Property("ffa-version", "<0x10001>")
2201 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2202 .FfaLoadAddress((uint64_t)&spkg_2)
2203 .Property("execution-ctx-count", "<1>")
2204 .Property("exception-level", "<0>")
2205 .Property("execution-state", "<0>")
2206 .Property("entrypoint-offset", "<0x0>")
2207 .Property("xlat-granule", "<0>")
2208 .Property("messaging-method", "<0x7>")
2209 .StartChild("device-regions")
2210 .Compatible({ "arm,ffa-manifest-device-regions" })
2211 .StartChild("test-device-0")
2212 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002213 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002214 .Property("pages-count", "<16>")
2215 .Property("attributes", "<3>")
2216 .EndChild()
2217 .EndChild()
2218 .Build();
2219
2220 /* clang-format on */
2221 spkg_1.init(dtb1);
2222 spkg_2.init(dtb2);
2223
2224 /* clang-format off */
2225 std::vector<char> core_dtb = ManifestDtBuilder()
2226 .StartChild("hypervisor")
2227 .Compatible()
2228 .StartChild("vm1")
2229 .DebugName("ffa_partition_1")
2230 .FfaPartition()
2231 .LoadAddress((uint64_t)&spkg_1)
2232 .VcpuCount(1)
2233 .MemSize(0x4000)
2234 .EndChild()
2235 .StartChild("vm2")
2236 .DebugName("ffa_partition_2")
2237 .FfaPartition()
2238 .LoadAddress((uint64_t)&spkg_2)
2239 .VcpuCount(1)
2240 .MemSize(0x4000)
2241 .EndChild()
2242 .EndChild()
2243 .Build();
2244 /* clang-format on */
2245 boot_params_init(&params, &spkg_1);
2246 memiter_init(&it, core_dtb.data(), core_dtb.size());
2247 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2248 MANIFEST_ERROR_MEM_REGION_OVERLAP);
2249
2250 manifest_dealloc();
2251
2252 /* clang-format off */
2253 dtb1 = ManifestDtBuilder()
2254 .Compatible({ "arm,ffa-manifest-1.0" })
2255 .Property("ffa-version", "<0x10001>")
2256 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2257 .FfaLoadAddress((uint64_t)&spkg_1)
2258 .Property("execution-ctx-count", "<1>")
2259 .Property("exception-level", "<0>")
2260 .Property("execution-state", "<0>")
2261 .Property("entrypoint-offset", "<0x0>")
2262 .Property("xlat-granule", "<0>")
2263 .Property("messaging-method", "<0x7>")
2264 .StartChild("device-regions")
2265 .Compatible({ "arm,ffa-manifest-device-regions" })
2266 .StartChild("test-device-0")
2267 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002268 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002269 .Property("pages-count", "<16>")
2270 .Property("attributes", "<3>")
2271 .EndChild()
2272 .EndChild()
2273 .Build();
2274
2275 dtb2 = ManifestDtBuilder()
2276 .Compatible({ "arm,ffa-manifest-1.0" })
2277 .Property("ffa-version", "<0x10001>")
2278 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2279 .FfaLoadAddress((uint64_t)&spkg_2)
2280 .Property("execution-ctx-count", "<1>")
2281 .Property("exception-level", "<0>")
2282 .Property("execution-state", "<0>")
2283 .Property("entrypoint-offset", "<0x0>")
2284 .Property("xlat-granule", "<0>")
2285 .Property("messaging-method", "<0x7>")
2286 .StartChild("device-regions")
2287 .Compatible({ "arm,ffa-manifest-device-regions" })
2288 .StartChild("test-device-0")
2289 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002290 .Property("base-address", "<0x25000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002291 .Property("pages-count", "<16>")
2292 .Property("attributes", "<3>")
2293 .EndChild()
2294 .EndChild()
2295 .Build();
2296
2297 /* clang-format on */
2298 spkg_1.init(dtb1);
2299 spkg_2.init(dtb2);
2300
2301 /* clang-format off */
2302 core_dtb = ManifestDtBuilder()
2303 .StartChild("hypervisor")
2304 .Compatible()
2305 .StartChild("vm1")
2306 .DebugName("ffa_partition_1")
2307 .FfaPartition()
2308 .LoadAddress((uint64_t)&spkg_1)
2309 .VcpuCount(1)
2310 .MemSize(0x4000)
2311 .EndChild()
2312 .StartChild("vm2")
2313 .DebugName("ffa_partition_2")
2314 .FfaPartition()
2315 .LoadAddress((uint64_t)&spkg_2)
2316 .VcpuCount(1)
2317 .MemSize(0x4000)
2318 .EndChild()
2319 .EndChild()
2320 .Build();
2321 /* clang-format on */
2322 boot_params_init(&params, &spkg_1);
2323 memiter_init(&it, core_dtb.data(), core_dtb.size());
2324 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2325 MANIFEST_SUCCESS);
2326}
Madhukar Pappireddy99c5eff2024-07-08 15:07:41 -05002327
2328/*
2329 * Tests to trigger various error conditions while parsing dma related
2330 * properties of memory region nodes.
2331 */
2332TEST_F(manifest, ffa_memory_region_invalid_dma_properties)
2333{
2334 struct_manifest *m;
2335
2336 /*
2337 * SMMU ID must be specified if the partition specifies Stream IDs for
2338 * any device upstream of SMMU.
2339 */
2340 /* clang-format off */
2341 std::vector<char> dtb = ManifestDtBuilder()
2342 .FfaValidManifest()
2343 .StartChild("memory-regions")
2344 .Compatible({ "arm,ffa-manifest-memory-regions" })
2345 .StartChild("test-memory")
2346 .Description("test-memory")
2347 .Property("base-address", "<0x7100000>")
2348 .Property("pages-count", "<16>")
2349 .Property("attributes", "<3>")
2350 .Property("stream-ids", "<0 1>")
2351 .Property("interrupts", "<2 3>, <4 5>")
2352 .EndChild()
2353 .EndChild()
2354 .Build();
2355 /* clang-format on */
2356
2357 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2358 MANIFEST_ERROR_MISSING_SMMU_ID);
2359 manifest_dealloc();
2360
2361 /*
2362 * All stream ids belonging to a dma device must specify the same access
2363 * permissions.
2364 */
2365 /* clang-format off */
2366 dtb = ManifestDtBuilder()
2367 .FfaValidManifest()
2368 .StartChild("memory-regions")
2369 .Compatible({ "arm,ffa-manifest-memory-regions" })
2370 .StartChild("test-memory")
2371 .Description("test-memory")
2372 .Property("base-address", "<0x7100000>")
2373 .Property("pages-count", "<16>")
2374 .Property("attributes", "<3>")
2375 .Property("smmu-id", "<1>")
2376 .Property("stream-ids", "<0 1>")
2377 .Property("stream-ids-access-permissions", "<0x3 0xb>")
2378 .Property("interrupts", "<2 3>, <4 5>")
2379 .EndChild()
2380 .EndChild()
2381 .Build();
2382 /* clang-format on */
2383
2384 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2385 MANIFEST_ERROR_MISMATCH_DMA_ACCESS_PERMISSIONS);
2386 manifest_dealloc();
2387
2388 /*
2389 * DMA device stream ID count exceeds predefined limit.
2390 */
2391 /* clang-format off */
2392 dtb = ManifestDtBuilder()
2393 .FfaValidManifest()
2394 .StartChild("memory-regions")
2395 .Compatible({ "arm,ffa-manifest-memory-regions" })
2396 .StartChild("test-memory")
2397 .Description("test-memory")
2398 .Property("base-address", "<0x7100000>")
2399 .Property("pages-count", "<16>")
2400 .Property("attributes", "<3>")
2401 .Property("smmu-id", "<1>")
2402 .Property("stream-ids", "<0 1 4 9 12 >")
2403 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3>")
2404 .EndChild()
2405 .EndChild()
2406 .Build();
2407 /* clang-format on */
2408
2409 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2410 MANIFEST_ERROR_STREAM_IDS_OVERFLOW);
2411 manifest_dealloc();
2412
2413 /*
2414 * DMA access permissions count exceeds predefined limit
2415 */
2416 /* clang-format off */
2417 dtb = ManifestDtBuilder()
2418 .FfaValidManifest()
2419 .StartChild("memory-regions")
2420 .Compatible({ "arm,ffa-manifest-memory-regions" })
2421 .StartChild("test-memory")
2422 .Description("test-memory")
2423 .Property("base-address", "<0x7100000>")
2424 .Property("pages-count", "<16>")
2425 .Property("attributes", "<3>")
2426 .Property("smmu-id", "<1>")
2427 .Property("stream-ids", "<0 1>")
2428 .Property("stream-ids-access-permissions", "<0x3 0x3 0x3 0x3 0x3>")
2429 .EndChild()
2430 .EndChild()
2431 .Build();
2432 /* clang-format on */
2433
2434 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2435 MANIFEST_ERROR_DMA_ACCESS_PERMISSIONS_OVERFLOW);
2436}
2437
2438/*
2439 * Tests to trigger various error conditions while parsing dma related
2440 * properties of device region nodes.
2441 */
2442TEST_F(manifest, ffa_device_region_invalid_dma_properties)
2443{
2444 struct_manifest *m;
2445
2446 /*
2447 * SMMU ID must be specified if the partition specifies Stream IDs for
2448 * any device upstream of SMMU.
2449 */
2450 /* clang-format off */
2451 std::vector<char> dtb = ManifestDtBuilder()
2452 .FfaValidManifest()
2453 .StartChild("device-regions")
2454 .Compatible({ "arm,ffa-manifest-device-regions" })
2455 .StartChild("test-device")
2456 .Description("test-device")
2457 .Property("base-address", "<0x24000000>")
2458 .Property("pages-count", "<16>")
2459 .Property("attributes", "<3>")
2460 .Property("stream-ids", "<0 1>")
2461 .Property("interrupts", "<2 3>, <4 5>")
2462 .EndChild()
2463 .EndChild()
2464 .Build();
2465 /* clang-format on */
2466
2467 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2468 MANIFEST_ERROR_MISSING_SMMU_ID);
2469 manifest_dealloc();
2470
2471 /*
2472 * Dma devices defined through device region nodes exceed predefined
2473 * limit.
2474 */
2475 /* clang-format off */
2476 dtb = ManifestDtBuilder()
2477 .FfaValidManifest()
2478 .StartChild("device-regions")
2479 .Compatible({ "arm,ffa-manifest-device-regions" })
2480 .StartChild("test-device-0")
2481 .Description("test-device-0")
2482 .Property("base-address", "<0x27000000>")
2483 .Property("pages-count", "<16>")
2484 .Property("attributes", "<3>")
2485 .Property("smmu-id", "<1>")
2486 .Property("stream-ids", "<0 1>")
2487 .EndChild()
2488 .StartChild("test-device-1")
2489 .Description("test-device-1")
2490 .Property("base-address", "<0x25000000>")
2491 .Property("pages-count", "<16>")
2492 .Property("attributes", "<3>")
2493 .Property("smmu-id", "<1>")
2494 .Property("stream-ids", "<2 3>")
2495 .EndChild()
2496 .StartChild("test-device-2")
2497 .Description("test-device-2")
2498 .Property("base-address", "<0x26000000>")
2499 .Property("pages-count", "<16>")
2500 .Property("attributes", "<3>")
2501 .Property("smmu-id", "<1>")
2502 .Property("stream-ids", "<4 5>")
2503 .EndChild()
2504 .EndChild()
2505 .Build();
2506 /* clang-format on */
2507
2508 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2509 MANIFEST_ERROR_DMA_DEVICE_OVERFLOW);
2510}
David Brazdil7a462ec2019-08-15 12:27:47 +01002511} /* namespace */