blob: f2b501825de4940312b282a992c24bb38df4d8e8 [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
Olivier Depreza15f2352022-09-26 09:17:24 +02001062TEST_F(manifest, power_management)
1063{
1064 struct manifest_vm *vm;
1065 struct_manifest *m;
1066
1067 /* S-EL1 partition power management field can set bit 0. */
1068 /* clang-format off */
1069 std::vector<char> 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("power-management-messages", "<1>")
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.power_management, 1);
1084 manifest_dealloc();
1085
1086 /* S-EL1 partition power management field can set bit 3. */
1087 /* clang-format off */
1088 dtb = ManifestDtBuilder()
1089 .Compatible({ "arm,ffa-manifest-1.0" })
1090 .Property("ffa-version", "<0x10001>")
1091 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1092 .Property("execution-ctx-count", "<8>")
1093 .Property("exception-level", "<2>")
1094 .Property("execution-state", "<0>")
1095 .Property("entrypoint-offset", "<0x00002000>")
1096 .Property("messaging-method", "<1>")
1097 .Property("power-management-messages", "<8>")
1098 .Build();
1099 /* clang-format on */
1100 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1101 vm = &m->vm[0];
1102 ASSERT_EQ(vm->partition.power_management, 8);
1103 manifest_dealloc();
1104
1105 /* S-EL1 partition power management field can only set bits 0 and 3. */
1106 /* clang-format off */
1107 dtb = ManifestDtBuilder()
1108 .Compatible({ "arm,ffa-manifest-1.0" })
1109 .Property("ffa-version", "<0x10001>")
1110 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1111 .Property("execution-ctx-count", "<8>")
1112 .Property("exception-level", "<2>")
1113 .Property("execution-state", "<0>")
1114 .Property("entrypoint-offset", "<0x00002000>")
1115 .Property("messaging-method", "<1>")
1116 .Property("power-management-messages", "<0xf>")
1117 .Build();
1118 /* clang-format on */
1119 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1120 vm = &m->vm[0];
1121 ASSERT_EQ(vm->partition.power_management, 9);
1122 manifest_dealloc();
1123
1124 /* S-EL0 partition power management field is forced to 0. */
1125 /* clang-format off */
1126 dtb = ManifestDtBuilder()
1127 .Compatible({ "arm,ffa-manifest-1.0" })
1128 .Property("ffa-version", "<0x10001>")
1129 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1130 .Property("execution-ctx-count", "<1>")
1131 .Property("exception-level", "<1>")
1132 .Property("execution-state", "<0>")
1133 .Property("entrypoint-offset", "<0x00002000>")
1134 .Property("messaging-method", "<1>")
1135 .Property("power-management-messages", "<0xff>")
1136 .Build();
1137 /* clang-format on */
1138 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1139 vm = &m->vm[0];
1140 ASSERT_EQ(vm->partition.power_management, 0);
1141}
1142
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001143TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001144{
Olivier Deprez93644652022-09-09 11:01:12 +02001145 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001146
1147 /* Not Compatible */
1148 /* clang-format off */
1149 std::vector<char> dtb = ManifestDtBuilder()
1150 .FfaValidManifest()
1151 .StartChild("rx_tx-info")
1152 .Compatible({ "foo,bar" })
1153 .EndChild()
1154 .Build();
1155 /* clang-format on */
1156 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1157 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001158 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001159
1160 /* Missing Properties */
1161 /* clang-format off */
1162 dtb = ManifestDtBuilder()
1163 .FfaValidManifest()
1164 .StartChild("rx_tx-info")
1165 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1166 .EndChild()
1167 .Build();
1168 /* clang-format on */
1169 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1170 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1171}
1172
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001173TEST_F(manifest, ffa_validate_mem_regions)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001174{
Olivier Deprez93644652022-09-09 11:01:12 +02001175 struct_manifest *m;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001176
1177 /* Not Compatible */
1178 /* clang-format off */
1179 std::vector<char> dtb = ManifestDtBuilder()
1180 .FfaValidManifest()
1181 .StartChild("memory-regions")
1182 .Compatible({ "foo,bar" })
1183 .EndChild()
1184 .Build();
1185 /* clang-format on */
1186 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1187 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001188 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001189
1190 /* Memory regions unavailable */
1191 /* clang-format off */
1192 dtb = ManifestDtBuilder()
1193 .FfaValidManifest()
1194 .StartChild("memory-regions")
1195 .Compatible({ "arm,ffa-manifest-memory-regions" })
1196 .EndChild()
1197 .Build();
1198 /* clang-format on */
1199 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1200 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001201 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001202
1203 /* Missing Properties */
1204 /* clang-format off */
1205 dtb = ManifestDtBuilder()
1206 .FfaValidManifest()
1207 .StartChild("memory-regions")
1208 .Compatible({ "arm,ffa-manifest-memory-regions" })
1209 .StartChild("test-memory")
1210 .Description("test-memory")
1211 .EndChild()
1212 .EndChild()
1213 .Build();
1214 /* clang-format on */
1215 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1216 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001217 manifest_dealloc();
Manish Pandeyf06c9072020-09-29 15:41:58 +01001218
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001219 /* Empty memory region */
1220 /* clang-format off */
1221 dtb = ManifestDtBuilder()
1222 .FfaValidManifest()
1223 .StartChild("memory-regions")
1224 .Compatible({ "arm,ffa-manifest-memory-regions" })
1225 .Label("rx")
1226 .StartChild("rx")
1227 .Description("rx-buffer")
1228 .Property("base-address", "<0x7300000>")
1229 .Property("pages-count", "<0>")
1230 .Property("attributes", "<1>")
1231 .EndChild()
1232 .Label("tx")
1233 .StartChild("tx")
1234 .Description("tx-buffer")
1235 .Property("base-address", "<0x7310000>")
1236 .Property("pages-count", "<2>")
1237 .Property("attributes", "<3>")
1238 .EndChild()
1239 .EndChild()
1240 .StartChild("rx_tx-info")
1241 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1242 .Property("rx-buffer", "<&rx>")
1243 .Property("tx-buffer", "<&tx>")
1244 .EndChild()
1245 .Build();
1246 /* clang-format on */
1247 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1248 MANIFEST_ERROR_MEM_REGION_EMPTY);
1249 manifest_dealloc();
1250
Karl Meakine92efbe2023-06-01 14:16:22 +01001251 /* Mutually exclusive base-address and relative-address properties */
1252 /* clang-format off */
1253 dtb = ManifestDtBuilder()
1254 .FfaValidManifest()
1255 .StartChild("memory-regions")
1256 .Compatible({ "arm,ffa-manifest-memory-regions" })
1257 .Label("rx")
1258 .StartChild("rx")
1259 .Description("rx-buffer")
1260 .Property("base-address", "<0x7300000>")
1261 .Property("relative-address", "<0x7300000>")
1262 .Property("pages-count", "<1>")
1263 .Property("attributes", "<1>")
1264 .EndChild()
1265 .EndChild()
1266 .Build();
1267 /* clang-format on */
1268 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1269 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1270 manifest_dealloc();
1271 /* Relative-address overflow*/
1272 /* clang-format off */
1273 dtb = ManifestDtBuilder()
1274 .FfaValidManifest()
1275 .Property("load-address", "<0xffffff00 0xffffff00>")
1276 .StartChild("memory-regions")
1277 .Compatible({ "arm,ffa-manifest-memory-regions" })
1278 .Label("rx")
1279 .StartChild("rx")
1280 .Description("rx-buffer")
1281 .Property("relative-address", "<0xffffff00 0xffffff00>")
1282 .Property("pages-count", "<1>")
1283 .Property("attributes", "<1>")
1284 .EndChild()
1285 .EndChild()
1286 .Build();
1287 /* clang-format on */
1288 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1289 MANIFEST_ERROR_INTEGER_OVERFLOW);
1290 manifest_dealloc();
1291
Daniel Boulby9279b552022-06-28 17:04:01 +01001292 /* Overlapping memory regions */
1293 /* clang-format off */
1294 dtb = ManifestDtBuilder()
1295 .FfaValidManifest()
1296 .StartChild("memory-regions")
1297 .Compatible({ "arm,ffa-manifest-memory-regions" })
1298 .Label("rx")
1299 .StartChild("rx")
1300 .Description("rx-buffer")
1301 .Property("base-address", "<0x7300000>")
1302 .Property("pages-count", "<1>")
1303 .Property("attributes", "<1>")
1304 .EndChild()
1305 .Label("tx")
1306 .StartChild("tx")
1307 .Description("tx-buffer")
1308 .Property("base-address", "<0x7300000>")
1309 .Property("pages-count", "<2>")
1310 .Property("attributes", "<3>")
1311 .EndChild()
1312 .EndChild()
1313 .Build();
1314 /* clang-format on */
1315 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1316 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001317 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001318
1319 /* clang-format off */
1320 dtb = ManifestDtBuilder()
1321 .FfaValidManifest()
1322 .StartChild("memory-regions")
1323 .Compatible({ "arm,ffa-manifest-memory-regions" })
1324 .Label("rx")
1325 .StartChild("rx")
1326 .Description("rx-buffer")
1327 .Property("base-address", "<0x7300000>")
1328 .Property("pages-count", "<2>")
1329 .Property("attributes", "<1>")
1330 .EndChild()
1331 .Label("tx")
1332 .StartChild("tx")
1333 .Description("tx-buffer")
1334 .Property("base-address", "<0x7301000>")
1335 .Property("pages-count", "<2>")
1336 .Property("attributes", "<3>")
1337 .EndChild()
1338 .EndChild()
1339 .Build();
1340 /* clang-format on */
1341 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1342 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001343 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001344
1345 /* clang-format off */
1346 dtb = ManifestDtBuilder()
1347 .FfaValidManifest()
1348 .StartChild("memory-regions")
1349 .Compatible({ "arm,ffa-manifest-memory-regions" })
1350 .Label("rx")
1351 .StartChild("rx")
1352 .Description("rx-buffer")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001353 .Property("base-address", "<0x7301000>")
1354 .Property("pages-count", "<1>")
1355 .Property("attributes", "<1>")
1356 .EndChild()
1357 .Label("tx")
1358 .StartChild("tx")
1359 .Description("tx-buffer")
1360 .Property("base-address", "<0x7300000>")
1361 .Property("pages-count", "<2>")
1362 .Property("attributes", "<3>")
1363 .EndChild()
1364 .EndChild()
1365 .Build();
1366 /* clang-format on */
1367 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1368 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001369 manifest_dealloc();
1370
1371 /* Unaligned memory region */
1372 /* clang-format off */
1373 dtb = ManifestDtBuilder()
1374 .FfaValidManifest()
1375 .StartChild("memory-regions")
1376 .Compatible({ "arm,ffa-manifest-memory-regions" })
1377 .Label("rx")
1378 .StartChild("rx")
1379 .Description("rx-buffer")
1380 .Property("base-address", "<0x7300FFF>")
1381 .Property("pages-count", "<2>")
1382 .Property("attributes", "<1>")
1383 .EndChild()
1384 .Label("tx")
1385 .StartChild("tx")
1386 .Description("tx-buffer")
1387 .Property("base-address", "<0x7303000>")
1388 .Property("pages-count", "<2>")
1389 .Property("attributes", "<3>")
1390 .EndChild()
1391 .EndChild()
1392 .Build();
1393 /* clang-format on */
1394 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1395 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1396 manifest_dealloc();
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001397
Manish Pandeyf06c9072020-09-29 15:41:58 +01001398 /* Different RXTX buffer sizes */
1399 /* clang-format off */
1400 dtb = ManifestDtBuilder()
1401 .FfaValidManifest()
1402 .StartChild("memory-regions")
1403 .Compatible({ "arm,ffa-manifest-memory-regions" })
1404 .Label("rx")
1405 .StartChild("rx")
1406 .Description("rx-buffer")
1407 .Property("base-address", "<0x7300000>")
1408 .Property("pages-count", "<1>")
1409 .Property("attributes", "<1>")
1410 .EndChild()
1411 .Label("tx")
1412 .StartChild("tx")
1413 .Description("tx-buffer")
1414 .Property("base-address", "<0x7310000>")
1415 .Property("pages-count", "<2>")
1416 .Property("attributes", "<3>")
1417 .EndChild()
1418 .EndChild()
1419 .StartChild("rx_tx-info")
1420 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1421 .Property("rx-buffer", "<&rx>")
1422 .Property("tx-buffer", "<&tx>")
1423 .EndChild()
1424 .Build();
1425 /* clang-format on */
1426 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1427 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001428}
1429
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001430TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001431{
Olivier Deprez93644652022-09-09 11:01:12 +02001432 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001433
1434 /* Not Compatible */
1435 /* clang-format off */
1436 std::vector<char> dtb = ManifestDtBuilder()
1437 .FfaValidManifest()
1438 .StartChild("device-regions")
1439 .Compatible({ "foo,bar" })
1440 .EndChild()
1441 .Build();
1442 /* clang-format on */
1443 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1444 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001445 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001446
1447 /* Memory regions unavailable */
1448 /* clang-format off */
1449 dtb = ManifestDtBuilder()
1450 .FfaValidManifest()
1451 .StartChild("device-regions")
1452 .Compatible({ "arm,ffa-manifest-device-regions" })
1453 .EndChild()
1454 .Build();
1455 /* clang-format on */
1456 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1457 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001458 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001459
1460 /* Missing Properties */
1461 /* clang-format off */
1462 dtb = ManifestDtBuilder()
1463 .FfaValidManifest()
1464 .StartChild("device-regions")
1465 .Compatible({ "arm,ffa-manifest-device-regions" })
1466 .StartChild("test-device")
1467 .Description("test-device")
1468 .EndChild()
1469 .EndChild()
1470 .Build();
1471 /* clang-format on */
1472 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1473 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001474 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001475
1476 /* Malformed interrupt list pair */
1477 /* clang-format off */
1478 dtb = ManifestDtBuilder()
1479 .FfaValidManifest()
1480 .StartChild("device-regions")
1481 .Compatible({ "arm,ffa-manifest-device-regions" })
1482 .StartChild("test-device")
1483 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001484 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001485 .Property("pages-count", "<16>")
1486 .Property("attributes", "<3>")
1487 .Property("smmu-id", "<1>")
1488 .Property("stream-ids", "<0 1>")
1489 .Property("interrupts", "<2 3>, <4>")
1490 .EndChild()
1491 .EndChild()
1492 .Build();
1493 /* clang-format on */
1494 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1495 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001496 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001497
1498 /* Non-unique interrupt IDs */
1499 /* clang-format off */
1500 dtb = ManifestDtBuilder()
1501 .FfaValidManifest()
1502 .StartChild("device-regions")
1503 .Compatible({ "arm,ffa-manifest-device-regions" })
1504 .StartChild("test-device-0")
1505 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001506 .Property("base-address", "<0x24000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001507 .Property("pages-count", "<16>")
1508 .Property("attributes", "<3>")
1509 .Property("interrupts", "<2 3>")
1510 .EndChild()
1511 .StartChild("test-device-1")
1512 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001513 .Property("base-address", "<0x25000000>")
Daniel Boulby667334f2022-06-27 15:23:21 +01001514 .Property("pages-count", "<16>")
1515 .Property("attributes", "<3>")
1516 .Property("interrupts", "<1 3>, <2 5> ")
1517 .EndChild()
1518 .EndChild()
1519 .Build();
Daniel Boulby941ef342023-11-21 13:47:15 +00001520
Daniel Boulby667334f2022-06-27 15:23:21 +01001521 /* clang-format on */
1522 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1523 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1524 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001525 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1526 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1527 3);
1528 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1529 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1530 3);
Daniel Boulby941ef342023-11-21 13:47:15 +00001531 manifest_dealloc();
1532
1533 /* Overlapping address space between two device region nodes. */
1534 /* clang-format off */
1535 dtb = ManifestDtBuilder()
1536 .FfaValidManifest()
1537 .StartChild("device-regions")
1538 .Compatible({"arm,ffa-manifest-device-regions"})
1539 .StartChild("test-device-0")
1540 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001541 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001542 .Property("pages-count", "<16>")
1543 .Property("attributes", "<3>")
1544 .EndChild()
1545 .StartChild("test-device-1")
1546 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001547 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001548 .Property("pages-count", "<16>")
1549 .Property("attributes", "<3>")
1550 .EndChild()
Daniel Boulby4339edc2024-02-21 14:59:00 +00001551 .EndChild()
Daniel Boulby941ef342023-11-21 13:47:15 +00001552 .Build();
1553
1554 /* clang-format on */
1555 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1556 MANIFEST_ERROR_MEM_REGION_OVERLAP);
1557 manifest_dealloc();
1558
1559 /*
Daniel Boulby4339edc2024-02-21 14:59:00 +00001560 * Device regions cannot be defined outside of the regions specified in
1561 * the spmc.
Daniel Boulby941ef342023-11-21 13:47:15 +00001562 */
1563 /* clang-format off */
1564 dtb = ManifestDtBuilder()
1565 .FfaValidManifest()
Daniel Boulby941ef342023-11-21 13:47:15 +00001566 .StartChild("device-regions")
1567 .Compatible({"arm,ffa-manifest-device-regions"})
1568 .StartChild("test-device-0")
1569 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001570 .Property("base-address", "<0x50000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00001571 .Property("pages-count", "<16>")
1572 .Property("attributes", "<3>")
1573 .EndChild()
1574 .EndChild()
1575 .Build();
1576 /* clang-format on */
1577 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
Daniel Boulby4339edc2024-02-21 14:59:00 +00001578 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
1579 manifest_dealloc();
1580
1581 /*
1582 * Memory defined as NS in SPMC manifest given Secure attribute should
1583 * fail.
1584 */
1585 /* clang-format off */
1586 dtb = ManifestDtBuilder()
1587 .FfaValidManifest()
1588 .StartChild("device-regions")
1589 .Compatible({"arm,ffa-manifest-device-regions"})
1590 .StartChild("test-device-0")
1591 .Description("test-device-0")
1592 .Property("base-address", "<0x20000000>")
1593 .Property("pages-count", "<16>")
1594 .Property("attributes", "<3>")
1595 .EndChild()
1596 .EndChild()
1597 .Build();
1598 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1599 MANIFEST_ERROR_DEVICE_MEM_REGION_INVALID);
Manish Pandeye68e7932020-04-23 15:29:28 +01001600}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001601
1602TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001603{
Olivier Deprez93644652022-09-09 11:01:12 +02001604 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001605
1606 /* clang-format off */
1607 std::vector<char> dtb = ManifestDtBuilder()
1608 .FfaValidManifest()
1609 .StartChild("rx_tx-info")
1610 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1611 .Property("rx-buffer", "<&rx>")
1612 .Property("tx-buffer", "<&tx>")
1613 .EndChild()
1614 .StartChild("memory-regions")
1615 .Compatible({ "arm,ffa-manifest-memory-regions" })
1616 .StartChild("test-memory")
1617 .Description("test-memory")
1618 .Property("base-address", "<0x7100000>")
1619 .Property("pages-count", "<4>")
1620 .Property("attributes", "<7>")
1621 .EndChild()
1622 .Label("rx")
1623 .StartChild("rx")
1624 .Description("rx-buffer")
1625 .Property("base-address", "<0x7300000>")
1626 .Property("pages-count", "<1>")
1627 .Property("attributes", "<1>")
1628 .EndChild()
1629 .Label("tx")
1630 .StartChild("tx")
1631 .Description("tx-buffer")
1632 .Property("base-address", "<0x7310000>")
1633 .Property("pages-count", "<1>")
1634 .Property("attributes", "<3>")
1635 .EndChild()
1636 .EndChild()
1637 .Build();
1638 /* clang-format on */
1639
1640 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1641 MANIFEST_ERROR_INVALID_MEM_PERM);
1642}
1643
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001644TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001645{
Olivier Deprez93644652022-09-09 11:01:12 +02001646 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001647
1648 /* clang-format off */
1649 std::vector<char> dtb = ManifestDtBuilder()
1650 .FfaValidManifest()
1651 .StartChild("rx_tx-info")
1652 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1653 .Property("rx-buffer", "<&rx>")
1654 .Property("tx-buffer", "<&tx>")
1655 .EndChild()
1656 .StartChild("memory-regions")
1657 .Compatible({ "arm,ffa-manifest-memory-regions" })
1658 .StartChild("test-memory")
1659 .Description("test-memory")
1660 .Property("base-address", "<0x7100000>")
1661 .Property("pages-count", "<4>")
1662 .Property("attributes", "<3>")
1663 .EndChild()
1664 .Label("rx")
1665 .StartChild("rx")
1666 .Description("rx-buffer")
1667 .Property("base-address", "<0x7300000>")
1668 .Property("pages-count", "<1>")
1669 .Property("attributes", "<1>")
1670 .EndChild()
1671 .Label("tx")
1672 .StartChild("tx")
1673 .Description("tx-buffer")
1674 .Property("base-address", "<0x7310000>")
1675 .Property("pages-count", "<1>")
1676 .Property("attributes", "<3>")
1677 .EndChild()
1678 .EndChild()
1679 .StartChild("device-regions")
1680 .Compatible({ "arm,ffa-manifest-device-regions" })
1681 .StartChild("test-device")
1682 .Description("test-device")
1683 .Property("base-address", "<0x7200000>")
1684 .Property("pages-count", "<16>")
1685 .Property("attributes", "<5>")
1686 .Property("smmu-id", "<1>")
1687 .Property("stream-ids", "<0 1>")
1688 .Property("interrupts", "<2 3>, <4 5>")
1689 .EndChild()
1690 .EndChild()
1691 .Build();
1692 /* clang-format on */
1693
1694 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1695 MANIFEST_ERROR_INVALID_MEM_PERM);
1696}
Manish Pandeye68e7932020-04-23 15:29:28 +01001697
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001698TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01001699{
Olivier Deprez93644652022-09-09 11:01:12 +02001700 struct manifest_vm *vm;
1701 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01001702
1703 /* clang-format off */
1704 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001705 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001706 .StartChild("rx_tx-info")
1707 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1708 .Property("rx-buffer", "<&rx>")
1709 .Property("tx-buffer", "<&tx>")
1710 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001711 .StartChild("memory-regions")
1712 .Compatible({ "arm,ffa-manifest-memory-regions" })
1713 .StartChild("test-memory")
1714 .Description("test-memory")
Karl Meakine92efbe2023-06-01 14:16:22 +01001715 .Property("relative-address", "<0x7100000>")
Manish Pandey6542f5c2020-04-27 14:37:46 +01001716 .Property("pages-count", "<4>")
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001717 .Property("attributes", "<3>")
Manish Pandey6542f5c2020-04-27 14:37:46 +01001718 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001719 .StartChild("test-memory-ns")
1720 .Description("test-memory")
1721 .Property("base-address", "<0x7200000>")
1722 .Property("pages-count", "<1>")
1723 .Property("attributes", "<0xb>")
1724 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001725 .Label("rx")
1726 .StartChild("rx")
1727 .Description("rx-buffer")
1728 .Property("base-address", "<0x7300000>")
1729 .Property("pages-count", "<1>")
1730 .Property("attributes", "<1>")
1731 .EndChild()
1732 .Label("tx")
1733 .StartChild("tx")
1734 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001735 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001736 .Property("pages-count", "<1>")
1737 .Property("attributes", "<3>")
1738 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001739 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001740 .StartChild("device-regions")
1741 .Compatible({ "arm,ffa-manifest-device-regions" })
1742 .StartChild("test-device")
1743 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001744 .Property("base-address", "<0x24000000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001745 .Property("pages-count", "<16>")
1746 .Property("attributes", "<3>")
1747 .Property("smmu-id", "<1>")
1748 .Property("stream-ids", "<0 1>")
1749 .Property("interrupts", "<2 3>, <4 5>")
1750 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001751 .StartChild("test-device-ns")
1752 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001753 .Property("base-address", "<0x20000000>")
Olivier Deprez035fa152022-03-14 11:19:10 +01001754 .Property("pages-count", "<1>")
1755 .Property("attributes", "<0x9>")
1756 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001757 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001758 .Build();
Daniel Boulby4339edc2024-02-21 14:59:00 +00001759
Olivier Deprez62d99e32020-01-09 15:58:07 +01001760 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01001761 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1762
Olivier Deprez93644652022-09-09 11:01:12 +02001763 vm = &m->vm[0];
1764 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001765 ASSERT_THAT(
Kathleen Capella422b10b2023-06-30 18:28:27 -04001766 std::span(vm->partition.uuids[0].uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001767 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02001768 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
1769 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
1770 ASSERT_EQ(vm->partition.execution_state, AARCH64);
1771 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
1772 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
1773 ASSERT_EQ(vm->partition.boot_order, 0);
1774 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
1775 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
1776 ASSERT_EQ(vm->partition.mem_regions[0].base_address, 0x7100000);
1777 ASSERT_EQ(vm->partition.mem_regions[0].page_count, 4);
1778 ASSERT_EQ(vm->partition.mem_regions[0].attributes, 3);
1779 ASSERT_EQ(vm->partition.mem_regions[1].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001780
Olivier Deprez93644652022-09-09 11:01:12 +02001781 ASSERT_EQ(vm->partition.rxtx.available, true);
1782 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
1783 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
1784 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
1785 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
1786 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
1787 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
1788
Daniel Boulby4339edc2024-02-21 14:59:00 +00001789 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Olivier Deprez93644652022-09-09 11:01:12 +02001790 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Daniel Boulby4339edc2024-02-21 14:59:00 +00001791 ASSERT_EQ(vm->partition.dev_regions[0].attributes, (16 | 3));
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05001792 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
1793 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
1794 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Olivier Deprez93644652022-09-09 11:01:12 +02001795 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1796 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1797 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1798 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
Daniel Boulby4339edc2024-02-21 14:59:00 +00001799 ASSERT_EQ(vm->partition.dev_regions[1].base_address, 0x20000000);
1800 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (16 | 8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01001801}
1802
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001803TEST_F(manifest, ffa_valid_interrupt_target_manifest)
1804{
1805 struct manifest_vm *vm;
1806 struct_manifest *m;
1807
1808 /* clang-format off */
1809 std::vector<char> dtb = ManifestDtBuilder()
1810 .FfaValidManifest()
1811 .StartChild("device-regions")
1812 .Compatible({ "arm,ffa-manifest-device-regions" })
1813 .StartChild("test-device")
1814 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001815 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001816 .Property("pages-count", "<16>")
1817 .Property("attributes", "<3>")
1818 .Property("smmu-id", "<1>")
1819 .Property("stream-ids", "<0 1>")
1820 .Property("interrupts", "<2 3>, <4 5>")
1821 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
1822 .EndChild()
1823 .EndChild()
1824 .Build();
1825 /* clang-format on */
1826
1827 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1828
1829 vm = &m->vm[0];
1830
Daniel Boulby4339edc2024-02-21 14:59:00 +00001831 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x24000000);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001832 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
Daniel Boulby4339edc2024-02-21 14:59:00 +00001833 ASSERT_EQ(vm->partition.dev_regions[0].attributes, (16 | 3));
Madhukar Pappireddy9c764b32024-06-20 14:36:55 -05001834 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.smmu_id, 1);
1835 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[0], 0);
1836 ASSERT_EQ(vm->partition.dev_regions[0].dma_prop.stream_ids[1], 1);
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001837 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1838 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1839 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
1840 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
1841 0x123400005678);
1842 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1843 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
1844 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
1845 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
1846 0x1234567887654321);
1847}
1848
1849TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
1850{
1851 struct_manifest *m;
1852
1853 /* clang-format off */
1854 std::vector<char> dtb = ManifestDtBuilder()
1855 .FfaValidManifest()
1856 .StartChild("device-regions")
1857 .Compatible({ "arm,ffa-manifest-device-regions" })
1858 .StartChild("test-device")
1859 .Description("test-device")
Daniel Boulby4339edc2024-02-21 14:59:00 +00001860 .Property("base-address", "<0x24000000>")
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001861 .Property("pages-count", "<16>")
1862 .Property("attributes", "<3>")
1863 .Property("smmu-id", "<1>")
1864 .Property("stream-ids", "<0 1>")
1865 .Property("interrupts", "<2 3>, <4 5>")
1866 .Property("interrupts-target", "<20 0x1234 0x5678>")
1867 .EndChild()
1868 .EndChild()
1869 .Build();
1870 /* clang-format on */
1871
1872 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1873 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
1874}
1875
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04001876TEST_F(manifest, ffa_boot_order_not_unique)
1877{
1878 struct_manifest *m;
1879 struct memiter it;
1880 struct mm_stage1_locked mm_stage1_locked;
1881 struct boot_params params;
1882 Partition_package spkg_1;
1883 Partition_package spkg_2;
1884
1885 /* clang-format off */
1886 std::vector<char> dtb1 = ManifestDtBuilder()
1887 .Compatible({ "arm,ffa-manifest-1.0" })
1888 .Property("ffa-version", "<0x10001>")
1889 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1890 .FfaLoadAddress((uint64_t)&spkg_1)
1891 .Property("execution-ctx-count", "<1>")
1892 .Property("exception-level", "<1>")
1893 .Property("execution-state", "<0>")
1894 .Property("entrypoint-offset", "<0x00002000>")
1895 .Property("xlat-granule", "<0>")
1896 .Property("boot-order", "<1>")
1897 .Property("messaging-method", "<1>")
1898 .Property("ns-interrupts-action", "<0>")
1899 .Build();
1900
1901 std::vector<char> dtb2 = ManifestDtBuilder()
1902 .Compatible({ "arm,ffa-manifest-1.0" })
1903 .Property("ffa-version", "<0x10001>")
1904 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
1905 .FfaLoadAddress((uint64_t)&spkg_2)
1906 .Property("execution-ctx-count", "<1>")
1907 .Property("exception-level", "<1>")
1908 .Property("execution-state", "<0>")
1909 .Property("entrypoint-offset", "<0x00002000>")
1910 .Property("xlat-granule", "<0>")
1911 .Property("boot-order", "<1>")
1912 .Property("messaging-method", "<1>")
1913 .Property("ns-interrupts-action", "<0>")
1914 .Build();
1915
1916 /* clang-format on */
1917 spkg_1.init(dtb1);
1918 spkg_2.init(dtb2);
1919
1920 /* clang-format off */
1921 std::vector<char> core_dtb = ManifestDtBuilder()
1922 .StartChild("hypervisor")
1923 .Compatible()
1924 .StartChild("vm1")
1925 .DebugName("ffa_partition_1")
1926 .FfaPartition()
1927 .LoadAddress((uint64_t)&spkg_1)
1928 .VcpuCount(1)
1929 .MemSize(0x10000000)
1930 .EndChild()
1931 .StartChild("vm2")
1932 .DebugName("ffa_partition_2")
1933 .FfaPartition()
1934 .LoadAddress((uint64_t)&spkg_2)
1935 .VcpuCount(1)
1936 .MemSize(0x10000000)
1937 .EndChild()
1938 .EndChild()
1939 .Build();
1940 /* clang-format on */
1941
1942 boot_params_init(&params, nullptr);
1943 memiter_init(&it, core_dtb.data(), core_dtb.size());
1944 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
1945 MANIFEST_ERROR_INVALID_BOOT_ORDER);
1946}
Daniel Boulby941ef342023-11-21 13:47:15 +00001947
Kathleen Capella422b10b2023-06-30 18:28:27 -04001948TEST_F(manifest, ffa_valid_multiple_uuids)
1949{
1950 struct manifest_vm *vm;
1951 struct_manifest *m;
1952
1953 /* clang-format off */
1954 std::vector<char> dtb = ManifestDtBuilder()
1955 .Compatible({ "arm,ffa-manifest-1.0" })
1956 .Property("ffa-version", "<0x10002>")
1957 .Property("uuid",
1958 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>,\
1959 <0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
1960 .Property("execution-ctx-count", "<1>")
1961 .Property("exception-level", "<2>")
1962 .Property("execution-state", "<0>")
1963 .Property("entrypoint-offset", "<0x00002000>")
1964 .Property("xlat-granule", "<0>")
1965 .Property("boot-order", "<0>")
1966 .Property("messaging-method", "<4>")
1967 .Property("ns-interrupts-action", "<1>")
1968 .Build();
1969 /* clang-format on */
1970 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1971
1972 vm = &m->vm[0];
1973 ASSERT_EQ(vm->partition.ffa_version, 0x10002);
1974 ASSERT_THAT(
1975 std::span(vm->partition.uuids[0].uuid, 4),
1976 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
1977 ASSERT_THAT(
1978 std::span(vm->partition.uuids[1].uuid, 4),
1979 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1daaa));
1980 ASSERT_EQ(vm->partition.uuid_count, 2);
1981 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
1982 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
1983 ASSERT_EQ(vm->partition.execution_state, AARCH64);
1984 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
1985 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
1986 ASSERT_EQ(vm->partition.boot_order, 0);
1987 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
1988 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
1989}
1990TEST_F(manifest, ffa_uuid_all_zeros)
1991{
1992 struct_manifest *m;
1993
1994 /* clang-format off */
1995 std::vector<char> dtb = ManifestDtBuilder()
1996 .Compatible({ "arm,ffa-manifest-1.0" })
1997 .Property("ffa-version", "<0x10002>")
1998 .Property("uuid",
1999 "<0x0 0x0 0x0 0x0>, <0x0 0x0 0x0 0x0>")
2000 .Property("execution-ctx-count", "<1>")
2001 .Property("exception-level", "<2>")
2002 .Property("execution-state", "<0>")
2003 .Property("entrypoint-offset", "<0x00002000>")
2004 .Property("xlat-granule", "<0>")
2005 .Property("boot-order", "<0>")
2006 .Property("messaging-method", "<4>")
2007 .Property("ns-interrupts-action", "<1>")
2008 .Build();
2009 /* clang-format on */
2010 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
2011 MANIFEST_ERROR_UUID_ALL_ZEROS);
2012}
Daniel Boulby941ef342023-11-21 13:47:15 +00002013
2014/*
2015 * Test that the address space of two device region nodes specified across
2016 * different SPs cannot overlap.
2017 */
2018TEST_F(manifest, ffa_device_region_multi_sps)
2019{
2020 struct_manifest *m;
2021 struct memiter it;
2022 struct mm_stage1_locked mm_stage1_locked;
2023 struct boot_params params;
2024 Partition_package spkg_1;
2025 Partition_package spkg_2;
2026
2027 /* clang-format off */
2028 std::vector<char> dtb1 = ManifestDtBuilder()
2029 .Compatible({ "arm,ffa-manifest-1.0" })
2030 .Property("ffa-version", "<0x10001>")
2031 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2032 .FfaLoadAddress((uint64_t)&spkg_1)
2033 .Property("execution-ctx-count", "<1>")
2034 .Property("exception-level", "<0>")
2035 .Property("execution-state", "<0>")
2036 .Property("entrypoint-offset", "<0x0>")
2037 .Property("xlat-granule", "<0>")
2038 .Property("messaging-method", "<0x7>")
2039 .StartChild("device-regions")
2040 .Compatible({ "arm,ffa-manifest-device-regions" })
2041 .StartChild("test-device-0")
2042 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002043 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002044 .Property("pages-count", "<16>")
2045 .Property("attributes", "<3>")
2046 .EndChild()
2047 .EndChild()
2048 .Build();
2049
2050 std::vector<char> dtb2 = ManifestDtBuilder()
2051 .Compatible({ "arm,ffa-manifest-1.0" })
2052 .Property("ffa-version", "<0x10001>")
2053 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2054 .FfaLoadAddress((uint64_t)&spkg_2)
2055 .Property("execution-ctx-count", "<1>")
2056 .Property("exception-level", "<0>")
2057 .Property("execution-state", "<0>")
2058 .Property("entrypoint-offset", "<0x0>")
2059 .Property("xlat-granule", "<0>")
2060 .Property("messaging-method", "<0x7>")
2061 .StartChild("device-regions")
2062 .Compatible({ "arm,ffa-manifest-device-regions" })
2063 .StartChild("test-device-0")
2064 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002065 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002066 .Property("pages-count", "<16>")
2067 .Property("attributes", "<3>")
2068 .EndChild()
2069 .EndChild()
2070 .Build();
2071
2072 /* clang-format on */
2073 spkg_1.init(dtb1);
2074 spkg_2.init(dtb2);
2075
2076 /* clang-format off */
2077 std::vector<char> core_dtb = ManifestDtBuilder()
2078 .StartChild("hypervisor")
2079 .Compatible()
2080 .StartChild("vm1")
2081 .DebugName("ffa_partition_1")
2082 .FfaPartition()
2083 .LoadAddress((uint64_t)&spkg_1)
2084 .VcpuCount(1)
2085 .MemSize(0x4000)
2086 .EndChild()
2087 .StartChild("vm2")
2088 .DebugName("ffa_partition_2")
2089 .FfaPartition()
2090 .LoadAddress((uint64_t)&spkg_2)
2091 .VcpuCount(1)
2092 .MemSize(0x4000)
2093 .EndChild()
2094 .EndChild()
2095 .Build();
2096 /* clang-format on */
2097 boot_params_init(&params, &spkg_1);
2098 memiter_init(&it, core_dtb.data(), core_dtb.size());
2099 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2100 MANIFEST_ERROR_MEM_REGION_OVERLAP);
2101
2102 manifest_dealloc();
2103
2104 /* clang-format off */
2105 dtb1 = ManifestDtBuilder()
2106 .Compatible({ "arm,ffa-manifest-1.0" })
2107 .Property("ffa-version", "<0x10001>")
2108 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
2109 .FfaLoadAddress((uint64_t)&spkg_1)
2110 .Property("execution-ctx-count", "<1>")
2111 .Property("exception-level", "<0>")
2112 .Property("execution-state", "<0>")
2113 .Property("entrypoint-offset", "<0x0>")
2114 .Property("xlat-granule", "<0>")
2115 .Property("messaging-method", "<0x7>")
2116 .StartChild("device-regions")
2117 .Compatible({ "arm,ffa-manifest-device-regions" })
2118 .StartChild("test-device-0")
2119 .Description("test-device-0")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002120 .Property("base-address", "<0x24000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002121 .Property("pages-count", "<16>")
2122 .Property("attributes", "<3>")
2123 .EndChild()
2124 .EndChild()
2125 .Build();
2126
2127 dtb2 = ManifestDtBuilder()
2128 .Compatible({ "arm,ffa-manifest-1.0" })
2129 .Property("ffa-version", "<0x10001>")
2130 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
2131 .FfaLoadAddress((uint64_t)&spkg_2)
2132 .Property("execution-ctx-count", "<1>")
2133 .Property("exception-level", "<0>")
2134 .Property("execution-state", "<0>")
2135 .Property("entrypoint-offset", "<0x0>")
2136 .Property("xlat-granule", "<0>")
2137 .Property("messaging-method", "<0x7>")
2138 .StartChild("device-regions")
2139 .Compatible({ "arm,ffa-manifest-device-regions" })
2140 .StartChild("test-device-0")
2141 .Description("test-device-1")
Daniel Boulby4339edc2024-02-21 14:59:00 +00002142 .Property("base-address", "<0x25000000>")
Daniel Boulby941ef342023-11-21 13:47:15 +00002143 .Property("pages-count", "<16>")
2144 .Property("attributes", "<3>")
2145 .EndChild()
2146 .EndChild()
2147 .Build();
2148
2149 /* clang-format on */
2150 spkg_1.init(dtb1);
2151 spkg_2.init(dtb2);
2152
2153 /* clang-format off */
2154 core_dtb = ManifestDtBuilder()
2155 .StartChild("hypervisor")
2156 .Compatible()
2157 .StartChild("vm1")
2158 .DebugName("ffa_partition_1")
2159 .FfaPartition()
2160 .LoadAddress((uint64_t)&spkg_1)
2161 .VcpuCount(1)
2162 .MemSize(0x4000)
2163 .EndChild()
2164 .StartChild("vm2")
2165 .DebugName("ffa_partition_2")
2166 .FfaPartition()
2167 .LoadAddress((uint64_t)&spkg_2)
2168 .VcpuCount(1)
2169 .MemSize(0x4000)
2170 .EndChild()
2171 .EndChild()
2172 .Build();
2173 /* clang-format on */
2174 boot_params_init(&params, &spkg_1);
2175 memiter_init(&it, core_dtb.data(), core_dtb.size());
2176 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
2177 MANIFEST_SUCCESS);
2178}
David Brazdil7a462ec2019-08-15 12:27:47 +01002179} /* namespace */