blob: 9587459a1f270e0d129acdfed6b1ebbeba56967c [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
Varun Wadekarae9aeaa2022-10-13 14:23:58 +010033constexpr size_t TEST_HEAP_SIZE = PAGE_SIZE * 64;
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>");
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100246 Property("messaging-method", "<4>");
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
David Brazdil52256ff2019-08-23 15:15:15 +0100251 private:
252 ManifestDtBuilder &StringProperty(const std::string_view &name,
253 const std::string_view &value)
254 {
255 dts_ << name << " = \"" << value << "\";" << std::endl;
256 return *this;
257 }
258
David Brazdil74e9c3b2019-08-28 11:09:08 +0100259 ManifestDtBuilder &StringListProperty(
260 const std::string_view &name,
261 const std::vector<std::string_view> &value)
262 {
263 bool is_first = true;
264
265 dts_ << name << " = ";
266 for (const std::string_view &entry : value) {
267 if (is_first) {
268 is_first = false;
269 } else {
270 dts_ << ", ";
271 }
272 dts_ << "\"" << entry << "\"";
273 }
274 dts_ << ";" << std::endl;
275 return *this;
276 }
277
David Brazdil52256ff2019-08-23 15:15:15 +0100278 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100279 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100280 {
281 dts_ << name << " = <" << value << ">;" << std::endl;
282 return *this;
283 }
284
David Brazdil080ee312020-02-25 15:30:30 -0800285 ManifestDtBuilder &Integer64Property(const std::string_view &name,
286 uint64_t value)
287 {
288 uint32_t high = value >> 32;
289 uint32_t low = (uint32_t)value;
290 dts_ << name << " = <" << high << " " << low << ">;"
291 << std::endl;
292 return *this;
293 }
294
Andrew Scullae9962e2019-10-03 16:51:16 +0100295 ManifestDtBuilder &IntegerListProperty(
296 const std::string_view &name,
297 const std::vector<uint32_t> &value)
298 {
299 dts_ << name << " = < ";
300 for (const uint32_t entry : value) {
301 dts_ << entry << " ";
302 }
303 dts_ << ">;" << std::endl;
304 return *this;
305 }
306
307 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
308 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000309 dts_ << name << ";" << std::endl;
310 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100311 }
312
David Brazdil52256ff2019-08-23 15:15:15 +0100313 std::stringstream dts_;
314};
315
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100316class manifest : public ::testing::Test
David Brazdil0dbb41f2019-09-09 18:03:35 +0100317{
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100318 void SetUp() override
319 {
320 test_heap = std::make_unique<uint8_t[]>(TEST_HEAP_SIZE);
321 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
322 mpool_add_chunk(&ppool, test_heap.get(), TEST_HEAP_SIZE);
323 }
324
Olivier Deprez93644652022-09-09 11:01:12 +0200325 void TearDown() override
326 {
327 manifest_dealloc();
328 }
329
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100330 std::unique_ptr<uint8_t[]> test_heap;
331
332 protected:
Olivier Deprez62d99e32020-01-09 15:58:07 +0100333 struct mpool ppool;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100334
Olivier Deprez93644652022-09-09 11:01:12 +0200335 void manifest_dealloc(void)
336 {
337 manifest_deinit(&ppool);
338 }
339
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100340 public:
341 /**
342 * Class for programatically building a Partition package.
343 */
344 class Partition_package
345 {
346 public:
347 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
348 __attribute__((
349 aligned(PAGE_SIZE))) char manifest_dtb[PAGE_SIZE] = {};
350 __attribute__((aligned(PAGE_SIZE))) char img[PAGE_SIZE] = {};
David Brazdil0dbb41f2019-09-09 18:03:35 +0100351
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100352 Partition_package(const std::vector<char> &vec)
353 {
354 // Initialise header field
355 spkg.magic = SP_PKG_HEADER_MAGIC;
356 spkg.version = SP_PKG_HEADER_VERSION_2;
357 spkg.pm_offset = PAGE_SIZE;
358 spkg.pm_size = vec.size();
359 spkg.img_offset = 2 * PAGE_SIZE;
360 spkg.img_size = ARRAY_SIZE(img);
361
362 // Copy dtb into package
363 std::copy(vec.begin(), vec.end(), manifest_dtb);
364 }
365 };
366
J-Alves77b6f4f2023-03-15 11:34:49 +0000367 static void boot_params_init(struct boot_params *params,
368 Partition_package *pkg)
369 {
370 /*
371 * For the manifest tests we only care about the memory ranges
372 * in boot_params.
373 */
374 params->mem_ranges[0].begin = pa_init((uintpaddr_t)0x7000000);
375 params->mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
376 params->mem_ranges_count = 1;
377
378 if (pkg != nullptr) {
379 auto mem_base = (uintpaddr_t)pkg;
380 uintpaddr_t mem_end =
381 mem_base + sp_pkg_get_mem_size(&pkg->spkg);
382
383 params->mem_ranges_count++;
384
385 params->mem_ranges[1].begin = pa_init(mem_base);
386 params->mem_ranges[1].end = pa_init(mem_end);
387 }
388
389 params->ns_mem_ranges[0].begin =
390 pa_init((uintpaddr_t)0x7000000);
391 params->ns_mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
392 params->ns_mem_ranges_count = 1;
393 }
394
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100395 enum manifest_return_code manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200396 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100397 {
398 struct memiter it;
399 struct mm_stage1_locked mm_stage1_locked;
J-Alves77b6f4f2023-03-15 11:34:49 +0000400 struct boot_params params;
401
402 boot_params_init(&params, nullptr);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100403
404 memiter_init(&it, vec.data(), vec.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100405
J-Alves77b6f4f2023-03-15 11:34:49 +0000406 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100407 }
408
409 enum manifest_return_code ffa_manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200410 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100411 {
412 struct memiter it;
413 struct mm_stage1_locked mm_stage1_locked;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100414 Partition_package spkg(vec);
J-Alves77b6f4f2023-03-15 11:34:49 +0000415 struct boot_params params;
416
417 boot_params_init(&params, &spkg);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100418
419 /* clang-format off */
420 std::vector<char> core_dtb = ManifestDtBuilder()
421 .StartChild("hypervisor")
422 .Compatible()
423 .StartChild("vm1")
424 .DebugName("primary_vm")
425 .FfaPartition()
426 .LoadAddress((uint64_t)&spkg)
427 .EndChild()
428 .EndChild()
429 .Build();
430 /* clang-format on */
431 memiter_init(&it, core_dtb.data(), core_dtb.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
437TEST_F(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100438{
Olivier Deprez93644652022-09-09 11:01:12 +0200439 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100440 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100441
David Brazdila2358d42020-01-27 18:51:38 +0000442 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100443 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
444}
445
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100446TEST_F(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100447{
Olivier Deprez93644652022-09-09 11:01:12 +0200448 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100449
David Brazdil52256ff2019-08-23 15:15:15 +0100450 /* clang-format off */
451 std::vector<char> dtb = ManifestDtBuilder()
452 .StartChild("hypervisor")
453 .EndChild()
454 .Build();
455 /* clang-format on */
456
David Brazdilf4925382020-03-25 13:33:51 +0000457 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100458}
459
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100460TEST_F(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100461{
Olivier Deprez93644652022-09-09 11:01:12 +0200462 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100463
David Brazdil52256ff2019-08-23 15:15:15 +0100464 /* clang-format off */
465 std::vector<char> dtb = ManifestDtBuilder()
466 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100467 .Compatible({ "foo,bar" })
468 .EndChild()
469 .Build();
470 /* clang-format on */
471
David Brazdila2358d42020-01-27 18:51:38 +0000472 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100473}
474
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100475TEST_F(manifest, compatible_one_of_many)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100476{
Olivier Deprez93644652022-09-09 11:01:12 +0200477 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100478
479 /* clang-format off */
480 std::vector<char> dtb = ManifestDtBuilder()
481 .StartChild("hypervisor")
482 .Compatible({ "foo,bar", "hafnium,hafnium" })
483 .StartChild("vm1")
484 .DebugName("primary")
485 .EndChild()
486 .EndChild()
487 .Build();
488 /* clang-format on */
489
David Brazdila2358d42020-01-27 18:51:38 +0000490 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100491}
492
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100493TEST_F(manifest, no_vm_nodes)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100494{
Olivier Deprez93644652022-09-09 11:01:12 +0200495 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100496
497 /* clang-format off */
498 std::vector<char> dtb = ManifestDtBuilder()
499 .StartChild("hypervisor")
500 .Compatible()
501 .EndChild()
502 .Build();
503 /* clang-format on */
504
David Brazdila2358d42020-01-27 18:51:38 +0000505 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100506}
507
508static std::vector<char> gen_long_string_dtb(bool valid)
509{
510 const char last_valid[] = "1234567890123456789012345678901";
511 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100512 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
513 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100514
515 /* clang-format off */
516 return ManifestDtBuilder()
517 .StartChild("hypervisor")
518 .Compatible()
519 .StartChild("vm1")
520 .DebugName(valid ? last_valid : first_invalid)
521 .EndChild()
522 .EndChild()
523 .Build();
524 /* clang-format on */
525}
526
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100527TEST_F(manifest, long_string)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100528{
Olivier Deprez93644652022-09-09 11:01:12 +0200529 struct_manifest *m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100530 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
531 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
532
David Brazdila2358d42020-01-27 18:51:38 +0000533 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200534 manifest_dealloc();
535
David Brazdila2358d42020-01-27 18:51:38 +0000536 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
537 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100538}
539
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100540TEST_F(manifest, reserved_vm_id)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100541{
Olivier Deprez93644652022-09-09 11:01:12 +0200542 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100543
544 /* clang-format off */
545 std::vector<char> dtb = ManifestDtBuilder()
546 .StartChild("hypervisor")
547 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100548 .StartChild("vm1")
549 .DebugName("primary_vm")
550 .EndChild()
551 .StartChild("vm0")
552 .DebugName("reserved_vm")
553 .VcpuCount(1)
554 .MemSize(0x1000)
555 .KernelFilename("kernel")
556 .EndChild()
557 .EndChild()
558 .Build();
559 /* clang-format on */
560
David Brazdila2358d42020-01-27 18:51:38 +0000561 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100562}
563
Andrew Scullae9962e2019-10-03 16:51:16 +0100564static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100565{
566 /* clang-format off */
567 return ManifestDtBuilder()
568 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100569 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100570 .StartChild("vm1")
571 .DebugName("primary_vm")
572 .EndChild()
573 .StartChild("vm2")
574 .DebugName("secondary_vm")
575 .VcpuCount(vcpu_count)
576 .MemSize(0x1000)
577 .KernelFilename("kernel")
578 .EndChild()
579 .EndChild()
580 .Build();
581 /* clang-format on */
582}
David Brazdil7a462ec2019-08-15 12:27:47 +0100583
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100584TEST_F(manifest, vcpu_count_limit)
David Brazdil7a462ec2019-08-15 12:27:47 +0100585{
Olivier Deprez93644652022-09-09 11:01:12 +0200586 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100587 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
588 std::vector<char> dtb_first_invalid =
589 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100590
David Brazdila2358d42020-01-27 18:51:38 +0000591 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200592 ASSERT_EQ(m->vm_count, 2);
593 ASSERT_EQ(m->vm[1].secondary.vcpu_count, UINT16_MAX);
594 manifest_dealloc();
David Brazdil7a462ec2019-08-15 12:27:47 +0100595
David Brazdila2358d42020-01-27 18:51:38 +0000596 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100597 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100598}
599
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100600TEST_F(manifest, no_ramdisk_primary)
David Brazdile6f83222019-09-23 14:47:37 +0100601{
Olivier Deprez93644652022-09-09 11:01:12 +0200602 struct_manifest *m;
David Brazdile6f83222019-09-23 14:47:37 +0100603
604 /* clang-format off */
605 std::vector<char> dtb = ManifestDtBuilder()
606 .StartChild("hypervisor")
607 .Compatible()
608 .StartChild("vm1")
609 .DebugName("primary_vm")
610 .EndChild()
611 .EndChild()
612 .Build();
613 /* clang-format on */
614
David Brazdila2358d42020-01-27 18:51:38 +0000615 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200616 ASSERT_EQ(m->vm_count, 1);
617 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
618 ASSERT_STREQ(string_data(&m->vm[0].primary.ramdisk_filename), "");
David Brazdile6f83222019-09-23 14:47:37 +0100619}
620
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100621TEST_F(manifest, no_boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800622{
Olivier Deprez93644652022-09-09 11:01:12 +0200623 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800624
625 /* clang-format off */
626 std::vector<char> dtb = ManifestDtBuilder()
627 .StartChild("hypervisor")
628 .Compatible()
629 .StartChild("vm1")
630 .DebugName("primary_vm")
631 .EndChild()
632 .EndChild()
633 .Build();
634 /* clang-format on */
635
636 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200637 ASSERT_EQ(m->vm_count, 1);
638 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
639 ASSERT_EQ(m->vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
David Brazdil080ee312020-02-25 15:30:30 -0800640}
641
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100642TEST_F(manifest, boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800643{
Olivier Deprez93644652022-09-09 11:01:12 +0200644 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800645 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
646
647 /* clang-format off */
648 std::vector<char> dtb = ManifestDtBuilder()
649 .StartChild("hypervisor")
650 .Compatible()
651 .StartChild("vm1")
652 .DebugName("primary_vm")
653 .BootAddress(addr)
654 .EndChild()
655 .EndChild()
656 .Build();
657 /* clang-format on */
658
659 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200660 ASSERT_EQ(m->vm_count, 1);
661 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
662 ASSERT_EQ(m->vm[0].primary.boot_address, addr);
David Brazdil080ee312020-02-25 15:30:30 -0800663}
664
Andrew Scullb2c3a242019-11-04 13:52:36 +0000665static std::vector<char> gen_malformed_boolean_dtb(
666 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100667{
Andrew Scullae9962e2019-10-03 16:51:16 +0100668 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000669 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100670 .StartChild("hypervisor")
671 .Compatible()
672 .StartChild("vm1")
673 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000674 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000675 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100676 .EndChild()
677 .Build();
678 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000679}
Andrew Scullae9962e2019-10-03 16:51:16 +0100680
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100681TEST_F(manifest, malformed_booleans)
Andrew Scullb2c3a242019-11-04 13:52:36 +0000682{
Olivier Deprez93644652022-09-09 11:01:12 +0200683 struct_manifest *m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100684
Andrew Scullb2c3a242019-11-04 13:52:36 +0000685 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
686 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
687 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
688 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100689
David Brazdila2358d42020-01-27 18:51:38 +0000690 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000691 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200692 manifest_dealloc();
693
David Brazdila2358d42020-01-27 18:51:38 +0000694 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000695 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200696 manifest_dealloc();
697
David Brazdila2358d42020-01-27 18:51:38 +0000698 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000699 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200700 manifest_dealloc();
701
David Brazdila2358d42020-01-27 18:51:38 +0000702 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000703 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100704}
705
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100706TEST_F(manifest, valid)
David Brazdil7a462ec2019-08-15 12:27:47 +0100707{
Olivier Deprez93644652022-09-09 11:01:12 +0200708 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100709 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100710
David Brazdil52256ff2019-08-23 15:15:15 +0100711 /* clang-format off */
712 std::vector<char> dtb = ManifestDtBuilder()
713 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100714 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100715 .StartChild("vm1")
716 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100717 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100718 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100719 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100720 .EndChild()
721 .StartChild("vm3")
722 .DebugName("second_secondary_vm")
723 .VcpuCount(43)
724 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100725 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100726 .EndChild()
727 .StartChild("vm2")
728 .DebugName("first_secondary_vm")
729 .VcpuCount(42)
730 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100731 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
732 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100733 .EndChild()
734 .EndChild()
735 .Build();
736 /* clang-format on */
737
David Brazdila2358d42020-01-27 18:51:38 +0000738 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200739 ASSERT_EQ(m->vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100740
Olivier Deprez93644652022-09-09 11:01:12 +0200741 vm = &m->vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100742 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
743 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100744 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
745 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100746 ASSERT_THAT(
747 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
748 ElementsAre(0x32000000, 0x33001111));
749 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100750
Olivier Deprez93644652022-09-09 11:01:12 +0200751 vm = &m->vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100752 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
753 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100754 ASSERT_EQ(vm->secondary.vcpu_count, 42);
755 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100756 ASSERT_THAT(
757 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
758 ElementsAre(0x04000000, 0x30002222, 0x31445566));
759 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100760
Olivier Deprez93644652022-09-09 11:01:12 +0200761 vm = &m->vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100762 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
763 ASSERT_STREQ(string_data(&vm->kernel_filename),
764 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100765 ASSERT_EQ(vm->secondary.vcpu_count, 43);
766 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100767 ASSERT_THAT(
768 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
769 IsEmpty());
770 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100771}
772
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100773TEST_F(manifest, ffa_not_compatible)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100774{
Olivier Deprez93644652022-09-09 11:01:12 +0200775 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100776
777 /* clang-format off */
778 std::vector<char> dtb = ManifestDtBuilder()
779 .Compatible({ "arm,ffa-manifest-2.0" })
780 .Property("ffa-version", "<0x10000>")
781 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
782 .Property("execution-ctx-count", "<1>")
783 .Property("exception-level", "<2>")
784 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000785 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100786 .Property("xlat-granule", "<0>")
787 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500788 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100789 .Build();
790 /* clang-format on */
791
792 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
793 MANIFEST_ERROR_NOT_COMPATIBLE);
794}
795
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100796TEST_F(manifest, ffa_missing_property)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100797{
Olivier Deprez93644652022-09-09 11:01:12 +0200798 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100799
800 /* clang-format off */
801 std::vector<char> dtb = ManifestDtBuilder()
802 .Compatible({ "arm,ffa-manifest-1.0" })
803 .Property("ffa-version", "<0x10000>")
804 .Build();
805 /* clang-format on */
806
807 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
808 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
809}
810
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100811TEST_F(manifest, ffa_validate_sanity_check)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100812{
J-Alvesb37fd082020-10-22 12:29:21 +0100813 /*
814 * TODO: write test excluding all optional fields of the manifest, in
815 * accordance with specification.
816 */
Olivier Deprez93644652022-09-09 11:01:12 +0200817 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100818
819 /* Incompatible version */
820 /* clang-format off */
821 std::vector<char> dtb = ManifestDtBuilder()
822 .Compatible({ "arm,ffa-manifest-1.0" })
823 .Property("ffa-version", "<0xa1>")
824 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
825 .Property("execution-ctx-count", "<1>")
826 .Property("exception-level", "<2>")
827 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000828 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100829 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100830 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100831 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500832 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100833 .Build();
834 /* clang-format on */
835 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
836 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200837 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100838
839 /* Incompatible translation granule */
840 /* clang-format off */
841 dtb = ManifestDtBuilder()
842 .Compatible({ "arm,ffa-manifest-1.0" })
843 .Property("ffa-version", "<0x10000>")
844 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
845 .Property("execution-ctx-count", "<1>")
846 .Property("exception-level", "<2>")
847 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000848 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100849 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100850 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100851 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500852 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100853 .Build();
854 /* clang-format on */
855 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
856 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200857 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100858
859 /* Incompatible exeption level */
860 /* clang-format off */
861 dtb = ManifestDtBuilder()
862 .Compatible({ "arm,ffa-manifest-1.0" })
863 .Property("ffa-version", "<0x10000>")
864 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
865 .Property("execution-ctx-count", "<1>")
866 .Property("exception-level", "<6>")
867 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000868 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100869 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100870 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100871 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500872 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100873 .Build();
874 /* clang-format on */
875 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
876 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200877 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100878
879 /* Incompatible execution state */
880 /* clang-format off */
881 dtb = ManifestDtBuilder()
882 .Compatible({ "arm,ffa-manifest-1.0" })
883 .Property("ffa-version", "<0x10000>")
884 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
885 .Property("execution-ctx-count", "<1>")
886 .Property("exception-level", "<2>")
887 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000888 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100889 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100890 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100891 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500892 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100893 .Build();
894 /* clang-format on */
895 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
896 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200897 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100898
899 /* Incompatible messaging method */
900 /* clang-format off */
901 dtb = ManifestDtBuilder()
902 .Compatible({ "arm,ffa-manifest-1.0" })
903 .Property("ffa-version", "<0x10000>")
904 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
905 .Property("execution-ctx-count", "<1>")
906 .Property("exception-level", "<2>")
907 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000908 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100909 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100910 .Property("boot-order", "<0>")
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100911 .Property("messaging-method", "<16>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500912 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100913 .Build();
914 /* clang-format on */
915 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
916 MANIFEST_ERROR_NOT_COMPATIBLE);
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600917
918 /*
919 * No need to invoke manifest_dealloac() since manifest TearDown calls
920 * it when the test ends.
921 */
922}
923
924TEST_F(manifest, ffa_validate_interrupt_actions)
925{
926 struct_manifest *m;
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500927
928 /* Incompatible NS interrupt action */
929 /* clang-format off */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600930 std::vector<char> dtb = ManifestDtBuilder()
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500931 .Compatible({ "arm,ffa-manifest-1.0" })
932 .Property("ffa-version", "<0x10000>")
933 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
934 .Property("execution-ctx-count", "<1>")
935 .Property("exception-level", "<2>")
936 .Property("execution-state", "<0>")
937 .Property("entrypoint-offset", "<0x00002000>")
938 .Property("xlat-granule", "<0>")
939 .Property("boot-order", "<0>")
940 .Property("messaging-method", "<1>")
941 .Property("ns-interrupts-action", "<4>")
942 .Build();
943 /* clang-format on */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600944 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
945 MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
Madhukar Pappireddyee736ad2022-12-28 11:37:09 -0600946 manifest_dealloc();
947
948 /* Incompatible other-s-interrupts-action for S-EL1 partition */
949 /* 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>")
957 .Property("entrypoint-offset", "<0x00002000>")
958 .Property("xlat-granule", "<0>")
959 .Property("boot-order", "<0>")
960 .Property("messaging-method", "<1>")
961 .Property("ns-interrupts-action", "<1>")
962 .Property("other-s-interrupts-action", "<0>")
963 .Build();
964 /* clang-format on */
965 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
966 MANIFEST_ERROR_NOT_COMPATIBLE);
967 manifest_dealloc();
968
969 /*
970 * Incompatible choice of the fields ns-interrupts-action and
971 * other-s-interrupts-action.
972 */
973 /* clang-format off */
974 dtb = ManifestDtBuilder()
975 .Compatible({ "arm,ffa-manifest-1.0" })
976 .Property("ffa-version", "<0x10000>")
977 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
978 .Property("execution-ctx-count", "<1>")
979 .Property("exception-level", "<1>")
980 .Property("execution-state", "<0>")
981 .Property("entrypoint-offset", "<0x00002000>")
982 .Property("xlat-granule", "<0>")
983 .Property("boot-order", "<0>")
984 .Property("messaging-method", "<1>")
985 .Property("ns-interrupts-action", "<2>")
986 .Property("other-s-interrupts-action", "<0>")
987 .Build();
988 /* clang-format on */
989 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
990 MANIFEST_ERROR_NOT_COMPATIBLE);
991 manifest_dealloc();
992
993 /* Illegal value specified for the field other-s-interrupts-action. */
994 /* clang-format off */
995 dtb = ManifestDtBuilder()
996 .Compatible({ "arm,ffa-manifest-1.0" })
997 .Property("ffa-version", "<0x10000>")
998 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
999 .Property("execution-ctx-count", "<1>")
1000 .Property("exception-level", "<1>")
1001 .Property("execution-state", "<0>")
1002 .Property("entrypoint-offset", "<0x00002000>")
1003 .Property("xlat-granule", "<0>")
1004 .Property("boot-order", "<0>")
1005 .Property("messaging-method", "<1>")
1006 .Property("other-s-interrupts-action", "<2>")
1007 .Build();
1008 /* clang-format on */
1009 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1010 MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001011}
1012
Olivier Depreza15f2352022-09-26 09:17:24 +02001013TEST_F(manifest, power_management)
1014{
1015 struct manifest_vm *vm;
1016 struct_manifest *m;
1017
1018 /* S-EL1 partition power management field can set bit 0. */
1019 /* clang-format off */
1020 std::vector<char> dtb = ManifestDtBuilder()
1021 .Compatible({ "arm,ffa-manifest-1.0" })
1022 .Property("ffa-version", "<0x10001>")
1023 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1024 .Property("execution-ctx-count", "<8>")
1025 .Property("exception-level", "<2>")
1026 .Property("execution-state", "<0>")
1027 .Property("entrypoint-offset", "<0x00002000>")
1028 .Property("messaging-method", "<1>")
1029 .Property("power-management-messages", "<1>")
1030 .Build();
1031 /* clang-format on */
1032 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1033 vm = &m->vm[0];
1034 ASSERT_EQ(vm->partition.power_management, 1);
1035 manifest_dealloc();
1036
1037 /* S-EL1 partition power management field can set bit 3. */
1038 /* clang-format off */
1039 dtb = ManifestDtBuilder()
1040 .Compatible({ "arm,ffa-manifest-1.0" })
1041 .Property("ffa-version", "<0x10001>")
1042 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1043 .Property("execution-ctx-count", "<8>")
1044 .Property("exception-level", "<2>")
1045 .Property("execution-state", "<0>")
1046 .Property("entrypoint-offset", "<0x00002000>")
1047 .Property("messaging-method", "<1>")
1048 .Property("power-management-messages", "<8>")
1049 .Build();
1050 /* clang-format on */
1051 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1052 vm = &m->vm[0];
1053 ASSERT_EQ(vm->partition.power_management, 8);
1054 manifest_dealloc();
1055
1056 /* S-EL1 partition power management field can only set bits 0 and 3. */
1057 /* clang-format off */
1058 dtb = ManifestDtBuilder()
1059 .Compatible({ "arm,ffa-manifest-1.0" })
1060 .Property("ffa-version", "<0x10001>")
1061 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1062 .Property("execution-ctx-count", "<8>")
1063 .Property("exception-level", "<2>")
1064 .Property("execution-state", "<0>")
1065 .Property("entrypoint-offset", "<0x00002000>")
1066 .Property("messaging-method", "<1>")
1067 .Property("power-management-messages", "<0xf>")
1068 .Build();
1069 /* clang-format on */
1070 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1071 vm = &m->vm[0];
1072 ASSERT_EQ(vm->partition.power_management, 9);
1073 manifest_dealloc();
1074
1075 /* S-EL0 partition power management field is forced to 0. */
1076 /* clang-format off */
1077 dtb = ManifestDtBuilder()
1078 .Compatible({ "arm,ffa-manifest-1.0" })
1079 .Property("ffa-version", "<0x10001>")
1080 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1081 .Property("execution-ctx-count", "<1>")
1082 .Property("exception-level", "<1>")
1083 .Property("execution-state", "<0>")
1084 .Property("entrypoint-offset", "<0x00002000>")
1085 .Property("messaging-method", "<1>")
1086 .Property("power-management-messages", "<0xff>")
1087 .Build();
1088 /* clang-format on */
1089 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1090 vm = &m->vm[0];
1091 ASSERT_EQ(vm->partition.power_management, 0);
1092}
1093
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001094TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001095{
Olivier Deprez93644652022-09-09 11:01:12 +02001096 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001097
1098 /* Not Compatible */
1099 /* clang-format off */
1100 std::vector<char> dtb = ManifestDtBuilder()
1101 .FfaValidManifest()
1102 .StartChild("rx_tx-info")
1103 .Compatible({ "foo,bar" })
1104 .EndChild()
1105 .Build();
1106 /* clang-format on */
1107 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1108 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001109 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001110
1111 /* Missing Properties */
1112 /* clang-format off */
1113 dtb = ManifestDtBuilder()
1114 .FfaValidManifest()
1115 .StartChild("rx_tx-info")
1116 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1117 .EndChild()
1118 .Build();
1119 /* clang-format on */
1120 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1121 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1122}
1123
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001124TEST_F(manifest, ffa_validate_mem_regions)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001125{
Olivier Deprez93644652022-09-09 11:01:12 +02001126 struct_manifest *m;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001127
1128 /* Not Compatible */
1129 /* clang-format off */
1130 std::vector<char> dtb = ManifestDtBuilder()
1131 .FfaValidManifest()
1132 .StartChild("memory-regions")
1133 .Compatible({ "foo,bar" })
1134 .EndChild()
1135 .Build();
1136 /* clang-format on */
1137 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1138 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001139 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001140
1141 /* Memory regions unavailable */
1142 /* clang-format off */
1143 dtb = ManifestDtBuilder()
1144 .FfaValidManifest()
1145 .StartChild("memory-regions")
1146 .Compatible({ "arm,ffa-manifest-memory-regions" })
1147 .EndChild()
1148 .Build();
1149 /* clang-format on */
1150 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1151 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001152 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001153
1154 /* Missing Properties */
1155 /* clang-format off */
1156 dtb = ManifestDtBuilder()
1157 .FfaValidManifest()
1158 .StartChild("memory-regions")
1159 .Compatible({ "arm,ffa-manifest-memory-regions" })
1160 .StartChild("test-memory")
1161 .Description("test-memory")
1162 .EndChild()
1163 .EndChild()
1164 .Build();
1165 /* clang-format on */
1166 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1167 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001168 manifest_dealloc();
Manish Pandeyf06c9072020-09-29 15:41:58 +01001169
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001170 /* Empty memory region */
1171 /* clang-format off */
1172 dtb = ManifestDtBuilder()
1173 .FfaValidManifest()
1174 .StartChild("memory-regions")
1175 .Compatible({ "arm,ffa-manifest-memory-regions" })
1176 .Label("rx")
1177 .StartChild("rx")
1178 .Description("rx-buffer")
1179 .Property("base-address", "<0x7300000>")
1180 .Property("pages-count", "<0>")
1181 .Property("attributes", "<1>")
1182 .EndChild()
1183 .Label("tx")
1184 .StartChild("tx")
1185 .Description("tx-buffer")
1186 .Property("base-address", "<0x7310000>")
1187 .Property("pages-count", "<2>")
1188 .Property("attributes", "<3>")
1189 .EndChild()
1190 .EndChild()
1191 .StartChild("rx_tx-info")
1192 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1193 .Property("rx-buffer", "<&rx>")
1194 .Property("tx-buffer", "<&tx>")
1195 .EndChild()
1196 .Build();
1197 /* clang-format on */
1198 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1199 MANIFEST_ERROR_MEM_REGION_EMPTY);
1200 manifest_dealloc();
1201
Karl Meakine92efbe2023-06-01 14:16:22 +01001202 /* Mutually exclusive base-address and relative-address properties */
1203 /* clang-format off */
1204 dtb = ManifestDtBuilder()
1205 .FfaValidManifest()
1206 .StartChild("memory-regions")
1207 .Compatible({ "arm,ffa-manifest-memory-regions" })
1208 .Label("rx")
1209 .StartChild("rx")
1210 .Description("rx-buffer")
1211 .Property("base-address", "<0x7300000>")
1212 .Property("relative-address", "<0x7300000>")
1213 .Property("pages-count", "<1>")
1214 .Property("attributes", "<1>")
1215 .EndChild()
1216 .EndChild()
1217 .Build();
1218 /* clang-format on */
1219 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1220 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1221 manifest_dealloc();
1222 /* Relative-address overflow*/
1223 /* clang-format off */
1224 dtb = ManifestDtBuilder()
1225 .FfaValidManifest()
1226 .Property("load-address", "<0xffffff00 0xffffff00>")
1227 .StartChild("memory-regions")
1228 .Compatible({ "arm,ffa-manifest-memory-regions" })
1229 .Label("rx")
1230 .StartChild("rx")
1231 .Description("rx-buffer")
1232 .Property("relative-address", "<0xffffff00 0xffffff00>")
1233 .Property("pages-count", "<1>")
1234 .Property("attributes", "<1>")
1235 .EndChild()
1236 .EndChild()
1237 .Build();
1238 /* clang-format on */
1239 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1240 MANIFEST_ERROR_INTEGER_OVERFLOW);
1241 manifest_dealloc();
1242
Daniel Boulby9279b552022-06-28 17:04:01 +01001243 /* Overlapping memory regions */
1244 /* clang-format off */
1245 dtb = ManifestDtBuilder()
1246 .FfaValidManifest()
1247 .StartChild("memory-regions")
1248 .Compatible({ "arm,ffa-manifest-memory-regions" })
1249 .Label("rx")
1250 .StartChild("rx")
1251 .Description("rx-buffer")
1252 .Property("base-address", "<0x7300000>")
1253 .Property("pages-count", "<1>")
1254 .Property("attributes", "<1>")
1255 .EndChild()
1256 .Label("tx")
1257 .StartChild("tx")
1258 .Description("tx-buffer")
1259 .Property("base-address", "<0x7300000>")
1260 .Property("pages-count", "<2>")
1261 .Property("attributes", "<3>")
1262 .EndChild()
1263 .EndChild()
1264 .Build();
1265 /* clang-format on */
1266 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1267 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001268 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001269
1270 /* clang-format off */
1271 dtb = ManifestDtBuilder()
1272 .FfaValidManifest()
1273 .StartChild("memory-regions")
1274 .Compatible({ "arm,ffa-manifest-memory-regions" })
1275 .Label("rx")
1276 .StartChild("rx")
1277 .Description("rx-buffer")
1278 .Property("base-address", "<0x7300000>")
1279 .Property("pages-count", "<2>")
1280 .Property("attributes", "<1>")
1281 .EndChild()
1282 .Label("tx")
1283 .StartChild("tx")
1284 .Description("tx-buffer")
1285 .Property("base-address", "<0x7301000>")
1286 .Property("pages-count", "<2>")
1287 .Property("attributes", "<3>")
1288 .EndChild()
1289 .EndChild()
1290 .Build();
1291 /* clang-format on */
1292 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1293 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001294 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001295
1296 /* clang-format off */
1297 dtb = ManifestDtBuilder()
1298 .FfaValidManifest()
1299 .StartChild("memory-regions")
1300 .Compatible({ "arm,ffa-manifest-memory-regions" })
1301 .Label("rx")
1302 .StartChild("rx")
1303 .Description("rx-buffer")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001304 .Property("base-address", "<0x7301000>")
1305 .Property("pages-count", "<1>")
1306 .Property("attributes", "<1>")
1307 .EndChild()
1308 .Label("tx")
1309 .StartChild("tx")
1310 .Description("tx-buffer")
1311 .Property("base-address", "<0x7300000>")
1312 .Property("pages-count", "<2>")
1313 .Property("attributes", "<3>")
1314 .EndChild()
1315 .EndChild()
1316 .Build();
1317 /* clang-format on */
1318 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1319 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001320 manifest_dealloc();
1321
1322 /* Unaligned memory region */
1323 /* clang-format off */
1324 dtb = ManifestDtBuilder()
1325 .FfaValidManifest()
1326 .StartChild("memory-regions")
1327 .Compatible({ "arm,ffa-manifest-memory-regions" })
1328 .Label("rx")
1329 .StartChild("rx")
1330 .Description("rx-buffer")
1331 .Property("base-address", "<0x7300FFF>")
1332 .Property("pages-count", "<2>")
1333 .Property("attributes", "<1>")
1334 .EndChild()
1335 .Label("tx")
1336 .StartChild("tx")
1337 .Description("tx-buffer")
1338 .Property("base-address", "<0x7303000>")
1339 .Property("pages-count", "<2>")
1340 .Property("attributes", "<3>")
1341 .EndChild()
1342 .EndChild()
1343 .Build();
1344 /* clang-format on */
1345 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1346 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1347 manifest_dealloc();
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001348
Manish Pandeyf06c9072020-09-29 15:41:58 +01001349 /* Different RXTX buffer sizes */
1350 /* clang-format off */
1351 dtb = ManifestDtBuilder()
1352 .FfaValidManifest()
1353 .StartChild("memory-regions")
1354 .Compatible({ "arm,ffa-manifest-memory-regions" })
1355 .Label("rx")
1356 .StartChild("rx")
1357 .Description("rx-buffer")
1358 .Property("base-address", "<0x7300000>")
1359 .Property("pages-count", "<1>")
1360 .Property("attributes", "<1>")
1361 .EndChild()
1362 .Label("tx")
1363 .StartChild("tx")
1364 .Description("tx-buffer")
1365 .Property("base-address", "<0x7310000>")
1366 .Property("pages-count", "<2>")
1367 .Property("attributes", "<3>")
1368 .EndChild()
1369 .EndChild()
1370 .StartChild("rx_tx-info")
1371 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1372 .Property("rx-buffer", "<&rx>")
1373 .Property("tx-buffer", "<&tx>")
1374 .EndChild()
1375 .Build();
1376 /* clang-format on */
1377 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1378 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001379}
1380
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001381TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001382{
Olivier Deprez93644652022-09-09 11:01:12 +02001383 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001384
1385 /* Not Compatible */
1386 /* clang-format off */
1387 std::vector<char> dtb = ManifestDtBuilder()
1388 .FfaValidManifest()
1389 .StartChild("device-regions")
1390 .Compatible({ "foo,bar" })
1391 .EndChild()
1392 .Build();
1393 /* clang-format on */
1394 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1395 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001396 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001397
1398 /* Memory regions unavailable */
1399 /* clang-format off */
1400 dtb = ManifestDtBuilder()
1401 .FfaValidManifest()
1402 .StartChild("device-regions")
1403 .Compatible({ "arm,ffa-manifest-device-regions" })
1404 .EndChild()
1405 .Build();
1406 /* clang-format on */
1407 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1408 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001409 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001410
1411 /* Missing Properties */
1412 /* clang-format off */
1413 dtb = ManifestDtBuilder()
1414 .FfaValidManifest()
1415 .StartChild("device-regions")
1416 .Compatible({ "arm,ffa-manifest-device-regions" })
1417 .StartChild("test-device")
1418 .Description("test-device")
1419 .EndChild()
1420 .EndChild()
1421 .Build();
1422 /* clang-format on */
1423 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1424 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001425 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001426
1427 /* Malformed interrupt list pair */
1428 /* clang-format off */
1429 dtb = ManifestDtBuilder()
1430 .FfaValidManifest()
1431 .StartChild("device-regions")
1432 .Compatible({ "arm,ffa-manifest-device-regions" })
1433 .StartChild("test-device")
1434 .Description("test-device")
1435 .Property("base-address", "<0x7200000>")
1436 .Property("pages-count", "<16>")
1437 .Property("attributes", "<3>")
1438 .Property("smmu-id", "<1>")
1439 .Property("stream-ids", "<0 1>")
1440 .Property("interrupts", "<2 3>, <4>")
1441 .EndChild()
1442 .EndChild()
1443 .Build();
1444 /* clang-format on */
1445 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1446 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001447 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001448
1449 /* Non-unique interrupt IDs */
1450 /* clang-format off */
1451 dtb = ManifestDtBuilder()
1452 .FfaValidManifest()
1453 .StartChild("device-regions")
1454 .Compatible({ "arm,ffa-manifest-device-regions" })
1455 .StartChild("test-device-0")
1456 .Description("test-device-0")
1457 .Property("base-address", "<0x7200000>")
1458 .Property("pages-count", "<16>")
1459 .Property("attributes", "<3>")
1460 .Property("interrupts", "<2 3>")
1461 .EndChild()
1462 .StartChild("test-device-1")
1463 .Description("test-device-1")
1464 .Property("base-address", "<0x8200000>")
1465 .Property("pages-count", "<16>")
1466 .Property("attributes", "<3>")
1467 .Property("interrupts", "<1 3>, <2 5> ")
1468 .EndChild()
1469 .EndChild()
1470 .Build();
1471 /* clang-format on */
1472 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1473 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1474 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001475 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1476 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1477 3);
1478 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1479 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1480 3);
Manish Pandeye68e7932020-04-23 15:29:28 +01001481}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001482
1483TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001484{
Olivier Deprez93644652022-09-09 11:01:12 +02001485 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001486
1487 /* clang-format off */
1488 std::vector<char> dtb = ManifestDtBuilder()
1489 .FfaValidManifest()
1490 .StartChild("rx_tx-info")
1491 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1492 .Property("rx-buffer", "<&rx>")
1493 .Property("tx-buffer", "<&tx>")
1494 .EndChild()
1495 .StartChild("memory-regions")
1496 .Compatible({ "arm,ffa-manifest-memory-regions" })
1497 .StartChild("test-memory")
1498 .Description("test-memory")
1499 .Property("base-address", "<0x7100000>")
1500 .Property("pages-count", "<4>")
1501 .Property("attributes", "<7>")
1502 .EndChild()
1503 .Label("rx")
1504 .StartChild("rx")
1505 .Description("rx-buffer")
1506 .Property("base-address", "<0x7300000>")
1507 .Property("pages-count", "<1>")
1508 .Property("attributes", "<1>")
1509 .EndChild()
1510 .Label("tx")
1511 .StartChild("tx")
1512 .Description("tx-buffer")
1513 .Property("base-address", "<0x7310000>")
1514 .Property("pages-count", "<1>")
1515 .Property("attributes", "<3>")
1516 .EndChild()
1517 .EndChild()
1518 .Build();
1519 /* clang-format on */
1520
1521 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1522 MANIFEST_ERROR_INVALID_MEM_PERM);
1523}
1524
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001525TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001526{
Olivier Deprez93644652022-09-09 11:01:12 +02001527 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001528
1529 /* clang-format off */
1530 std::vector<char> dtb = ManifestDtBuilder()
1531 .FfaValidManifest()
1532 .StartChild("rx_tx-info")
1533 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1534 .Property("rx-buffer", "<&rx>")
1535 .Property("tx-buffer", "<&tx>")
1536 .EndChild()
1537 .StartChild("memory-regions")
1538 .Compatible({ "arm,ffa-manifest-memory-regions" })
1539 .StartChild("test-memory")
1540 .Description("test-memory")
1541 .Property("base-address", "<0x7100000>")
1542 .Property("pages-count", "<4>")
1543 .Property("attributes", "<3>")
1544 .EndChild()
1545 .Label("rx")
1546 .StartChild("rx")
1547 .Description("rx-buffer")
1548 .Property("base-address", "<0x7300000>")
1549 .Property("pages-count", "<1>")
1550 .Property("attributes", "<1>")
1551 .EndChild()
1552 .Label("tx")
1553 .StartChild("tx")
1554 .Description("tx-buffer")
1555 .Property("base-address", "<0x7310000>")
1556 .Property("pages-count", "<1>")
1557 .Property("attributes", "<3>")
1558 .EndChild()
1559 .EndChild()
1560 .StartChild("device-regions")
1561 .Compatible({ "arm,ffa-manifest-device-regions" })
1562 .StartChild("test-device")
1563 .Description("test-device")
1564 .Property("base-address", "<0x7200000>")
1565 .Property("pages-count", "<16>")
1566 .Property("attributes", "<5>")
1567 .Property("smmu-id", "<1>")
1568 .Property("stream-ids", "<0 1>")
1569 .Property("interrupts", "<2 3>, <4 5>")
1570 .EndChild()
1571 .EndChild()
1572 .Build();
1573 /* clang-format on */
1574
1575 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1576 MANIFEST_ERROR_INVALID_MEM_PERM);
1577}
Manish Pandeye68e7932020-04-23 15:29:28 +01001578
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001579TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01001580{
Olivier Deprez93644652022-09-09 11:01:12 +02001581 struct manifest_vm *vm;
1582 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01001583
1584 /* clang-format off */
1585 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001586 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001587 .StartChild("rx_tx-info")
1588 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1589 .Property("rx-buffer", "<&rx>")
1590 .Property("tx-buffer", "<&tx>")
1591 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001592 .StartChild("memory-regions")
1593 .Compatible({ "arm,ffa-manifest-memory-regions" })
1594 .StartChild("test-memory")
1595 .Description("test-memory")
Karl Meakine92efbe2023-06-01 14:16:22 +01001596 .Property("relative-address", "<0x7100000>")
Manish Pandey6542f5c2020-04-27 14:37:46 +01001597 .Property("pages-count", "<4>")
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001598 .Property("attributes", "<3>")
Manish Pandey6542f5c2020-04-27 14:37:46 +01001599 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001600 .StartChild("test-memory-ns")
1601 .Description("test-memory")
1602 .Property("base-address", "<0x7200000>")
1603 .Property("pages-count", "<1>")
1604 .Property("attributes", "<0xb>")
1605 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001606 .Label("rx")
1607 .StartChild("rx")
1608 .Description("rx-buffer")
1609 .Property("base-address", "<0x7300000>")
1610 .Property("pages-count", "<1>")
1611 .Property("attributes", "<1>")
1612 .EndChild()
1613 .Label("tx")
1614 .StartChild("tx")
1615 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001616 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001617 .Property("pages-count", "<1>")
1618 .Property("attributes", "<3>")
1619 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001620 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001621 .StartChild("device-regions")
1622 .Compatible({ "arm,ffa-manifest-device-regions" })
1623 .StartChild("test-device")
1624 .Description("test-device")
Olivier Deprez035fa152022-03-14 11:19:10 +01001625 .Property("base-address", "<0x7400000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001626 .Property("pages-count", "<16>")
1627 .Property("attributes", "<3>")
1628 .Property("smmu-id", "<1>")
1629 .Property("stream-ids", "<0 1>")
1630 .Property("interrupts", "<2 3>, <4 5>")
1631 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001632 .StartChild("test-device-ns")
1633 .Description("test-device")
1634 .Property("base-address", "<0x7500000>")
1635 .Property("pages-count", "<1>")
1636 .Property("attributes", "<0x9>")
1637 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001638 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001639 .Build();
1640 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01001641 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1642
Olivier Deprez93644652022-09-09 11:01:12 +02001643 vm = &m->vm[0];
1644 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001645 ASSERT_THAT(
Olivier Deprez93644652022-09-09 11:01:12 +02001646 std::span(vm->partition.uuid.uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001647 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02001648 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
1649 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
1650 ASSERT_EQ(vm->partition.execution_state, AARCH64);
1651 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
1652 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
1653 ASSERT_EQ(vm->partition.boot_order, 0);
1654 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
1655 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
1656 ASSERT_EQ(vm->partition.mem_regions[0].base_address, 0x7100000);
1657 ASSERT_EQ(vm->partition.mem_regions[0].page_count, 4);
1658 ASSERT_EQ(vm->partition.mem_regions[0].attributes, 3);
1659 ASSERT_EQ(vm->partition.mem_regions[1].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001660
Olivier Deprez93644652022-09-09 11:01:12 +02001661 ASSERT_EQ(vm->partition.rxtx.available, true);
1662 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
1663 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
1664 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
1665 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
1666 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
1667 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
1668
1669 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x7400000);
1670 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
1671 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
1672 ASSERT_EQ(vm->partition.dev_regions[0].smmu_id, 1);
1673 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[0], 0);
1674 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[1], 1);
1675 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1676 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1677 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1678 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
1679 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01001680}
1681
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001682TEST_F(manifest, ffa_valid_interrupt_target_manifest)
1683{
1684 struct manifest_vm *vm;
1685 struct_manifest *m;
1686
1687 /* clang-format off */
1688 std::vector<char> dtb = ManifestDtBuilder()
1689 .FfaValidManifest()
1690 .StartChild("device-regions")
1691 .Compatible({ "arm,ffa-manifest-device-regions" })
1692 .StartChild("test-device")
1693 .Description("test-device")
1694 .Property("base-address", "<0x7400000>")
1695 .Property("pages-count", "<16>")
1696 .Property("attributes", "<3>")
1697 .Property("smmu-id", "<1>")
1698 .Property("stream-ids", "<0 1>")
1699 .Property("interrupts", "<2 3>, <4 5>")
1700 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
1701 .EndChild()
1702 .EndChild()
1703 .Build();
1704 /* clang-format on */
1705
1706 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1707
1708 vm = &m->vm[0];
1709
1710 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x7400000);
1711 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
1712 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
1713 ASSERT_EQ(vm->partition.dev_regions[0].smmu_id, 1);
1714 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[0], 0);
1715 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[1], 1);
1716 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1717 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1718 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
1719 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
1720 0x123400005678);
1721 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1722 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
1723 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
1724 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
1725 0x1234567887654321);
1726}
1727
1728TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
1729{
1730 struct_manifest *m;
1731
1732 /* clang-format off */
1733 std::vector<char> dtb = ManifestDtBuilder()
1734 .FfaValidManifest()
1735 .StartChild("device-regions")
1736 .Compatible({ "arm,ffa-manifest-device-regions" })
1737 .StartChild("test-device")
1738 .Description("test-device")
1739 .Property("base-address", "<0x7400000>")
1740 .Property("pages-count", "<16>")
1741 .Property("attributes", "<3>")
1742 .Property("smmu-id", "<1>")
1743 .Property("stream-ids", "<0 1>")
1744 .Property("interrupts", "<2 3>, <4 5>")
1745 .Property("interrupts-target", "<20 0x1234 0x5678>")
1746 .EndChild()
1747 .EndChild()
1748 .Build();
1749 /* clang-format on */
1750
1751 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1752 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
1753}
1754
David Brazdil7a462ec2019-08-15 12:27:47 +01001755} /* namespace */