blob: cc78660b7e8ee40288eb3c1e441eae07dd0f5950 [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
David Brazdil7a462ec2019-08-15 12:27:47 +010019#include "hf/manifest.h"
J-Alves2f86c1e2022-02-23 18:44:19 +000020#include "hf/sp_pkg.h"
David Brazdil7a462ec2019-08-15 12:27:47 +010021}
22
23namespace
24{
Andrew Scullae9962e2019-10-03 16:51:16 +010025using ::testing::ElementsAre;
David Brazdil7a462ec2019-08-15 12:27:47 +010026using ::testing::Eq;
Andrew Scullae9962e2019-10-03 16:51:16 +010027using ::testing::IsEmpty;
David Brazdil7a462ec2019-08-15 12:27:47 +010028using ::testing::NotNull;
29
Daniel Boulby801f8ef2022-06-27 14:21:01 +010030using struct_manifest = struct manifest;
31
32constexpr size_t TEST_HEAP_SIZE = PAGE_SIZE * 32;
33
David Brazdil52256ff2019-08-23 15:15:15 +010034template <typename T>
David Brazdil0dbb41f2019-09-09 18:03:35 +010035void exec(const char *program, const char *args[], const T &stdin,
David Brazdil52256ff2019-08-23 15:15:15 +010036 std::vector<char> *stdout)
37{
38 /* Create two pipes, one for stdin and one for stdout. */
39 int pipes[2][2];
40 pipe(pipes[0]);
41 pipe(pipes[1]);
David Brazdil7a462ec2019-08-15 12:27:47 +010042
David Brazdil52256ff2019-08-23 15:15:15 +010043 /* Assign FDs for reading/writing by the parent/child. */
44 int parent_read_fd = pipes[1][0]; /* stdout pipe, read FD */
45 int parent_write_fd = pipes[0][1]; /* stdin pipe, write FD */
46 int child_read_fd = pipes[0][0]; /* stdin pipe, read FD */
47 int child_write_fd = pipes[1][1]; /* stdout pipe, write FD */
David Brazdil7a462ec2019-08-15 12:27:47 +010048
David Brazdil52256ff2019-08-23 15:15:15 +010049 if (fork()) {
50 /* Parent process. */
51 std::array<char, 128> buf;
52 ssize_t res;
53
54 /* Close child FDs which won't be used. */
55 close(child_read_fd);
56 close(child_write_fd);
57
58 /* Write to stdin. */
59 for (size_t count = 0; count < stdin.size();) {
60 res = write(parent_write_fd, stdin.data() + count,
61 stdin.size() - count);
62 if (res < 0) {
63 std::cerr << "IO error" << std::endl;
64 exit(1);
65 }
66 count += res;
67 }
68 close(parent_write_fd);
69
70 /* Read from stdout. */
71 while (true) {
72 res = read(parent_read_fd, buf.data(), buf.size());
73 if (res == 0) {
74 /* EOF */
75 break;
76 } else if (res < 0) {
77 std::cerr << "IO error" << std::endl;
78 exit(1);
79 }
80 stdout->insert(stdout->end(), buf.begin(),
81 buf.begin() + res);
82 }
83 close(parent_read_fd);
84 } else {
85 /* Child process. */
86
87 /* Redirect stdin/stdout to read/write FDs. */
88 dup2(child_read_fd, STDIN_FILENO);
89 dup2(child_write_fd, STDOUT_FILENO);
90
91 /* Close all FDs which are now unused. */
92 close(child_read_fd);
93 close(child_write_fd);
94 close(parent_read_fd);
95 close(parent_write_fd);
96
97 /* Execute the given program. */
David Brazdil0dbb41f2019-09-09 18:03:35 +010098 execv(program, const_cast<char *const *>(args));
David Brazdil52256ff2019-08-23 15:15:15 +010099 }
100}
101
102/**
103 * Class for programatically building a Device Tree.
104 *
105 * Usage:
106 * std::vector<char> dtb = ManifestDtBuilder()
107 * .Command1()
108 * .Command2()
109 * ...
110 * .CommandN()
111 * .Build();
112 */
113class ManifestDtBuilder
114{
115 public:
116 ManifestDtBuilder()
117 {
118 dts_ << "/dts-v1/;" << std::endl;
119 dts_ << std::endl;
120
121 /* Start root node. */
122 StartChild("/");
123 }
124
Andrew Scullae9962e2019-10-03 16:51:16 +0100125 std::vector<char> Build(bool dump = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100126 {
David Brazdil0dbb41f2019-09-09 18:03:35 +0100127 const char *program = "./build/image/dtc.py";
128 const char *dtc_args[] = {program, "compile", NULL};
David Brazdil52256ff2019-08-23 15:15:15 +0100129 std::vector<char> dtc_stdout;
130
131 /* Finish root node. */
132 EndChild();
133
Andrew Scullae9962e2019-10-03 16:51:16 +0100134 if (dump) {
135 Dump();
136 }
137
David Brazdil0dbb41f2019-09-09 18:03:35 +0100138 exec(program, dtc_args, dts_.str(), &dtc_stdout);
David Brazdil52256ff2019-08-23 15:15:15 +0100139 return dtc_stdout;
140 }
141
Andrew Scullae9962e2019-10-03 16:51:16 +0100142 void Dump()
143 {
144 std::cerr << dts_.str() << std::endl;
145 }
146
David Brazdil52256ff2019-08-23 15:15:15 +0100147 ManifestDtBuilder &StartChild(const std::string_view &name)
148 {
149 dts_ << name << " {" << std::endl;
150 return *this;
151 }
152
153 ManifestDtBuilder &EndChild()
154 {
155 dts_ << "};" << std::endl;
156 return *this;
157 }
158
David Brazdil74e9c3b2019-08-28 11:09:08 +0100159 ManifestDtBuilder &Compatible(const std::vector<std::string_view>
160 &value = {"hafnium,hafnium"})
161 {
162 return StringListProperty("compatible", value);
163 }
164
David Brazdil52256ff2019-08-23 15:15:15 +0100165 ManifestDtBuilder &DebugName(const std::string_view &value)
166 {
167 return StringProperty("debug_name", value);
168 }
169
Manish Pandey6542f5c2020-04-27 14:37:46 +0100170 ManifestDtBuilder &Description(const std::string_view &value)
171 {
172 return StringProperty("description", value);
173 }
174
David Brazdil52256ff2019-08-23 15:15:15 +0100175 ManifestDtBuilder &KernelFilename(const std::string_view &value)
176 {
177 return StringProperty("kernel_filename", value);
178 }
179
David Brazdile6f83222019-09-23 14:47:37 +0100180 ManifestDtBuilder &RamdiskFilename(const std::string_view &value)
181 {
182 return StringProperty("ramdisk_filename", value);
183 }
184
David Brazdil080ee312020-02-25 15:30:30 -0800185 ManifestDtBuilder &BootAddress(uint64_t value)
186 {
187 return Integer64Property("boot_address", value);
188 }
189
Andrew Scullae9962e2019-10-03 16:51:16 +0100190 ManifestDtBuilder &VcpuCount(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100191 {
192 return IntegerProperty("vcpu_count", value);
193 }
194
Andrew Scullae9962e2019-10-03 16:51:16 +0100195 ManifestDtBuilder &MemSize(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100196 {
197 return IntegerProperty("mem_size", value);
198 }
199
Andrew Scullae9962e2019-10-03 16:51:16 +0100200 ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
201 {
202 return IntegerListProperty("smc_whitelist", value);
203 }
204
205 ManifestDtBuilder &SmcWhitelistPermissive()
206 {
207 return BooleanProperty("smc_whitelist_permissive");
208 }
209
Olivier Deprez62d99e32020-01-09 15:58:07 +0100210 ManifestDtBuilder &LoadAddress(uint64_t value)
211 {
212 return Integer64Property("load_address", value);
213 }
214
215 ManifestDtBuilder &FfaPartition()
216 {
217 return BooleanProperty("is_ffa_partition");
218 }
219
Andrew Scullae9962e2019-10-03 16:51:16 +0100220 ManifestDtBuilder &Property(const std::string_view &name,
221 const std::string_view &value)
222 {
223 dts_ << name << " = " << value << ";" << std::endl;
224 return *this;
225 }
226
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100227 ManifestDtBuilder &Label(const std::string_view &name)
228 {
229 dts_ << name << ": ";
230 return *this;
231 }
232
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100233 ManifestDtBuilder &FfaValidManifest()
234 {
235 Compatible({"arm,ffa-manifest-1.0"});
236 Property("ffa-version", "<0x10000>");
237 Property("uuid",
238 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>");
239 Property("execution-ctx-count", "<1>");
240 Property("exception-level", "<2>");
241 Property("execution-state", "<0>");
J-Alves2f86c1e2022-02-23 18:44:19 +0000242 Property("entrypoint-offset", "<0x00002000>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100243 Property("xlat-granule", "<0>");
J-Alvesb37fd082020-10-22 12:29:21 +0100244 Property("boot-order", "<0>");
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100245 Property("messaging-method", "<4>");
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500246 Property("ns-interrupts-action", "<1>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100247 return *this;
248 }
249
David Brazdil52256ff2019-08-23 15:15:15 +0100250 private:
251 ManifestDtBuilder &StringProperty(const std::string_view &name,
252 const std::string_view &value)
253 {
254 dts_ << name << " = \"" << value << "\";" << std::endl;
255 return *this;
256 }
257
David Brazdil74e9c3b2019-08-28 11:09:08 +0100258 ManifestDtBuilder &StringListProperty(
259 const std::string_view &name,
260 const std::vector<std::string_view> &value)
261 {
262 bool is_first = true;
263
264 dts_ << name << " = ";
265 for (const std::string_view &entry : value) {
266 if (is_first) {
267 is_first = false;
268 } else {
269 dts_ << ", ";
270 }
271 dts_ << "\"" << entry << "\"";
272 }
273 dts_ << ";" << std::endl;
274 return *this;
275 }
276
David Brazdil52256ff2019-08-23 15:15:15 +0100277 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100278 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100279 {
280 dts_ << name << " = <" << value << ">;" << std::endl;
281 return *this;
282 }
283
David Brazdil080ee312020-02-25 15:30:30 -0800284 ManifestDtBuilder &Integer64Property(const std::string_view &name,
285 uint64_t value)
286 {
287 uint32_t high = value >> 32;
288 uint32_t low = (uint32_t)value;
289 dts_ << name << " = <" << high << " " << low << ">;"
290 << std::endl;
291 return *this;
292 }
293
Andrew Scullae9962e2019-10-03 16:51:16 +0100294 ManifestDtBuilder &IntegerListProperty(
295 const std::string_view &name,
296 const std::vector<uint32_t> &value)
297 {
298 dts_ << name << " = < ";
299 for (const uint32_t entry : value) {
300 dts_ << entry << " ";
301 }
302 dts_ << ">;" << std::endl;
303 return *this;
304 }
305
306 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
307 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000308 dts_ << name << ";" << std::endl;
309 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100310 }
311
David Brazdil52256ff2019-08-23 15:15:15 +0100312 std::stringstream dts_;
313};
314
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100315class manifest : public ::testing::Test
David Brazdil0dbb41f2019-09-09 18:03:35 +0100316{
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100317 void SetUp() override
318 {
319 test_heap = std::make_unique<uint8_t[]>(TEST_HEAP_SIZE);
320 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
321 mpool_add_chunk(&ppool, test_heap.get(), TEST_HEAP_SIZE);
322 }
323
Olivier Deprez93644652022-09-09 11:01:12 +0200324 void TearDown() override
325 {
326 manifest_dealloc();
327 }
328
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100329 std::unique_ptr<uint8_t[]> test_heap;
330
331 protected:
Olivier Deprez62d99e32020-01-09 15:58:07 +0100332 struct mpool ppool;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100333
Olivier Deprez93644652022-09-09 11:01:12 +0200334 void manifest_dealloc(void)
335 {
336 manifest_deinit(&ppool);
337 }
338
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100339 public:
340 /**
341 * Class for programatically building a Partition package.
342 */
343 class Partition_package
344 {
345 public:
346 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
347 __attribute__((
348 aligned(PAGE_SIZE))) char manifest_dtb[PAGE_SIZE] = {};
349 __attribute__((aligned(PAGE_SIZE))) char img[PAGE_SIZE] = {};
David Brazdil0dbb41f2019-09-09 18:03:35 +0100350
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100351 Partition_package(const std::vector<char> &vec)
352 {
353 // Initialise header field
354 spkg.magic = SP_PKG_HEADER_MAGIC;
355 spkg.version = SP_PKG_HEADER_VERSION_2;
356 spkg.pm_offset = PAGE_SIZE;
357 spkg.pm_size = vec.size();
358 spkg.img_offset = 2 * PAGE_SIZE;
359 spkg.img_size = ARRAY_SIZE(img);
360
361 // Copy dtb into package
362 std::copy(vec.begin(), vec.end(), manifest_dtb);
363 }
364 };
365
366 enum manifest_return_code manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200367 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100368 {
369 struct memiter it;
370 struct mm_stage1_locked mm_stage1_locked;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100371
372 memiter_init(&it, vec.data(), vec.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100373
Olivier Deprez93644652022-09-09 11:01:12 +0200374 return manifest_init(mm_stage1_locked, m, &it, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100375 }
376
377 enum manifest_return_code ffa_manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200378 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100379 {
380 struct memiter it;
381 struct mm_stage1_locked mm_stage1_locked;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100382 Partition_package spkg(vec);
383
384 /* clang-format off */
385 std::vector<char> core_dtb = ManifestDtBuilder()
386 .StartChild("hypervisor")
387 .Compatible()
388 .StartChild("vm1")
389 .DebugName("primary_vm")
390 .FfaPartition()
391 .LoadAddress((uint64_t)&spkg)
392 .EndChild()
393 .EndChild()
394 .Build();
395 /* clang-format on */
396 memiter_init(&it, core_dtb.data(), core_dtb.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100397
Olivier Deprez93644652022-09-09 11:01:12 +0200398 return manifest_init(mm_stage1_locked, m, &it, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100399 }
400};
401
402TEST_F(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100403{
Olivier Deprez93644652022-09-09 11:01:12 +0200404 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100405 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100406
David Brazdila2358d42020-01-27 18:51:38 +0000407 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100408 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
409}
410
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100411TEST_F(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100412{
Olivier Deprez93644652022-09-09 11:01:12 +0200413 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100414
David Brazdil52256ff2019-08-23 15:15:15 +0100415 /* clang-format off */
416 std::vector<char> dtb = ManifestDtBuilder()
417 .StartChild("hypervisor")
418 .EndChild()
419 .Build();
420 /* clang-format on */
421
David Brazdilf4925382020-03-25 13:33:51 +0000422 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100423}
424
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100425TEST_F(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100426{
Olivier Deprez93644652022-09-09 11:01:12 +0200427 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100428
David Brazdil52256ff2019-08-23 15:15:15 +0100429 /* clang-format off */
430 std::vector<char> dtb = ManifestDtBuilder()
431 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100432 .Compatible({ "foo,bar" })
433 .EndChild()
434 .Build();
435 /* clang-format on */
436
David Brazdila2358d42020-01-27 18:51:38 +0000437 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100438}
439
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100440TEST_F(manifest, compatible_one_of_many)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100441{
Olivier Deprez93644652022-09-09 11:01:12 +0200442 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100443
444 /* clang-format off */
445 std::vector<char> dtb = ManifestDtBuilder()
446 .StartChild("hypervisor")
447 .Compatible({ "foo,bar", "hafnium,hafnium" })
448 .StartChild("vm1")
449 .DebugName("primary")
450 .EndChild()
451 .EndChild()
452 .Build();
453 /* clang-format on */
454
David Brazdila2358d42020-01-27 18:51:38 +0000455 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100456}
457
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100458TEST_F(manifest, no_vm_nodes)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100459{
Olivier Deprez93644652022-09-09 11:01:12 +0200460 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100461
462 /* clang-format off */
463 std::vector<char> dtb = ManifestDtBuilder()
464 .StartChild("hypervisor")
465 .Compatible()
466 .EndChild()
467 .Build();
468 /* clang-format on */
469
David Brazdila2358d42020-01-27 18:51:38 +0000470 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100471}
472
473static std::vector<char> gen_long_string_dtb(bool valid)
474{
475 const char last_valid[] = "1234567890123456789012345678901";
476 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100477 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
478 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100479
480 /* clang-format off */
481 return ManifestDtBuilder()
482 .StartChild("hypervisor")
483 .Compatible()
484 .StartChild("vm1")
485 .DebugName(valid ? last_valid : first_invalid)
486 .EndChild()
487 .EndChild()
488 .Build();
489 /* clang-format on */
490}
491
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100492TEST_F(manifest, long_string)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100493{
Olivier Deprez93644652022-09-09 11:01:12 +0200494 struct_manifest *m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100495 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
496 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
497
David Brazdila2358d42020-01-27 18:51:38 +0000498 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200499 manifest_dealloc();
500
David Brazdila2358d42020-01-27 18:51:38 +0000501 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
502 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100503}
504
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100505TEST_F(manifest, reserved_vm_id)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100506{
Olivier Deprez93644652022-09-09 11:01:12 +0200507 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100508
509 /* clang-format off */
510 std::vector<char> dtb = ManifestDtBuilder()
511 .StartChild("hypervisor")
512 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100513 .StartChild("vm1")
514 .DebugName("primary_vm")
515 .EndChild()
516 .StartChild("vm0")
517 .DebugName("reserved_vm")
518 .VcpuCount(1)
519 .MemSize(0x1000)
520 .KernelFilename("kernel")
521 .EndChild()
522 .EndChild()
523 .Build();
524 /* clang-format on */
525
David Brazdila2358d42020-01-27 18:51:38 +0000526 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100527}
528
Andrew Scullae9962e2019-10-03 16:51:16 +0100529static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100530{
531 /* clang-format off */
532 return ManifestDtBuilder()
533 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100534 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100535 .StartChild("vm1")
536 .DebugName("primary_vm")
537 .EndChild()
538 .StartChild("vm2")
539 .DebugName("secondary_vm")
540 .VcpuCount(vcpu_count)
541 .MemSize(0x1000)
542 .KernelFilename("kernel")
543 .EndChild()
544 .EndChild()
545 .Build();
546 /* clang-format on */
547}
David Brazdil7a462ec2019-08-15 12:27:47 +0100548
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100549TEST_F(manifest, vcpu_count_limit)
David Brazdil7a462ec2019-08-15 12:27:47 +0100550{
Olivier Deprez93644652022-09-09 11:01:12 +0200551 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100552 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
553 std::vector<char> dtb_first_invalid =
554 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100555
David Brazdila2358d42020-01-27 18:51:38 +0000556 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200557 ASSERT_EQ(m->vm_count, 2);
558 ASSERT_EQ(m->vm[1].secondary.vcpu_count, UINT16_MAX);
559 manifest_dealloc();
David Brazdil7a462ec2019-08-15 12:27:47 +0100560
David Brazdila2358d42020-01-27 18:51:38 +0000561 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100562 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100563}
564
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100565TEST_F(manifest, no_ramdisk_primary)
David Brazdile6f83222019-09-23 14:47:37 +0100566{
Olivier Deprez93644652022-09-09 11:01:12 +0200567 struct_manifest *m;
David Brazdile6f83222019-09-23 14:47:37 +0100568
569 /* clang-format off */
570 std::vector<char> dtb = ManifestDtBuilder()
571 .StartChild("hypervisor")
572 .Compatible()
573 .StartChild("vm1")
574 .DebugName("primary_vm")
575 .EndChild()
576 .EndChild()
577 .Build();
578 /* clang-format on */
579
David Brazdila2358d42020-01-27 18:51:38 +0000580 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200581 ASSERT_EQ(m->vm_count, 1);
582 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
583 ASSERT_STREQ(string_data(&m->vm[0].primary.ramdisk_filename), "");
David Brazdile6f83222019-09-23 14:47:37 +0100584}
585
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100586TEST_F(manifest, no_boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800587{
Olivier Deprez93644652022-09-09 11:01:12 +0200588 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800589
590 /* clang-format off */
591 std::vector<char> dtb = ManifestDtBuilder()
592 .StartChild("hypervisor")
593 .Compatible()
594 .StartChild("vm1")
595 .DebugName("primary_vm")
596 .EndChild()
597 .EndChild()
598 .Build();
599 /* clang-format on */
600
601 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200602 ASSERT_EQ(m->vm_count, 1);
603 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
604 ASSERT_EQ(m->vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
David Brazdil080ee312020-02-25 15:30:30 -0800605}
606
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100607TEST_F(manifest, boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800608{
Olivier Deprez93644652022-09-09 11:01:12 +0200609 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800610 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
611
612 /* clang-format off */
613 std::vector<char> dtb = ManifestDtBuilder()
614 .StartChild("hypervisor")
615 .Compatible()
616 .StartChild("vm1")
617 .DebugName("primary_vm")
618 .BootAddress(addr)
619 .EndChild()
620 .EndChild()
621 .Build();
622 /* clang-format on */
623
624 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200625 ASSERT_EQ(m->vm_count, 1);
626 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
627 ASSERT_EQ(m->vm[0].primary.boot_address, addr);
David Brazdil080ee312020-02-25 15:30:30 -0800628}
629
Andrew Scullb2c3a242019-11-04 13:52:36 +0000630static std::vector<char> gen_malformed_boolean_dtb(
631 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100632{
Andrew Scullae9962e2019-10-03 16:51:16 +0100633 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000634 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100635 .StartChild("hypervisor")
636 .Compatible()
637 .StartChild("vm1")
638 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000639 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000640 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100641 .EndChild()
642 .Build();
643 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000644}
Andrew Scullae9962e2019-10-03 16:51:16 +0100645
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100646TEST_F(manifest, malformed_booleans)
Andrew Scullb2c3a242019-11-04 13:52:36 +0000647{
Olivier Deprez93644652022-09-09 11:01:12 +0200648 struct_manifest *m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100649
Andrew Scullb2c3a242019-11-04 13:52:36 +0000650 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
651 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
652 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
653 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100654
David Brazdila2358d42020-01-27 18:51:38 +0000655 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000656 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200657 manifest_dealloc();
658
David Brazdila2358d42020-01-27 18:51:38 +0000659 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000660 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200661 manifest_dealloc();
662
David Brazdila2358d42020-01-27 18:51:38 +0000663 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000664 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200665 manifest_dealloc();
666
David Brazdila2358d42020-01-27 18:51:38 +0000667 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000668 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100669}
670
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100671TEST_F(manifest, valid)
David Brazdil7a462ec2019-08-15 12:27:47 +0100672{
Olivier Deprez93644652022-09-09 11:01:12 +0200673 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100674 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100675
David Brazdil52256ff2019-08-23 15:15:15 +0100676 /* clang-format off */
677 std::vector<char> dtb = ManifestDtBuilder()
678 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100679 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100680 .StartChild("vm1")
681 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100682 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100683 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100684 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100685 .EndChild()
686 .StartChild("vm3")
687 .DebugName("second_secondary_vm")
688 .VcpuCount(43)
689 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100690 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100691 .EndChild()
692 .StartChild("vm2")
693 .DebugName("first_secondary_vm")
694 .VcpuCount(42)
695 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100696 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
697 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100698 .EndChild()
699 .EndChild()
700 .Build();
701 /* clang-format on */
702
David Brazdila2358d42020-01-27 18:51:38 +0000703 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200704 ASSERT_EQ(m->vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100705
Olivier Deprez93644652022-09-09 11:01:12 +0200706 vm = &m->vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100707 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
708 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100709 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
710 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100711 ASSERT_THAT(
712 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
713 ElementsAre(0x32000000, 0x33001111));
714 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100715
Olivier Deprez93644652022-09-09 11:01:12 +0200716 vm = &m->vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100717 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
718 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100719 ASSERT_EQ(vm->secondary.vcpu_count, 42);
720 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100721 ASSERT_THAT(
722 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
723 ElementsAre(0x04000000, 0x30002222, 0x31445566));
724 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100725
Olivier Deprez93644652022-09-09 11:01:12 +0200726 vm = &m->vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100727 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
728 ASSERT_STREQ(string_data(&vm->kernel_filename),
729 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100730 ASSERT_EQ(vm->secondary.vcpu_count, 43);
731 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100732 ASSERT_THAT(
733 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
734 IsEmpty());
735 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100736}
737
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100738TEST_F(manifest, ffa_not_compatible)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100739{
Olivier Deprez93644652022-09-09 11:01:12 +0200740 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100741
742 /* clang-format off */
743 std::vector<char> dtb = ManifestDtBuilder()
744 .Compatible({ "arm,ffa-manifest-2.0" })
745 .Property("ffa-version", "<0x10000>")
746 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
747 .Property("execution-ctx-count", "<1>")
748 .Property("exception-level", "<2>")
749 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000750 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100751 .Property("xlat-granule", "<0>")
752 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500753 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100754 .Build();
755 /* clang-format on */
756
757 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
758 MANIFEST_ERROR_NOT_COMPATIBLE);
759}
760
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100761TEST_F(manifest, ffa_missing_property)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100762{
Olivier Deprez93644652022-09-09 11:01:12 +0200763 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100764
765 /* clang-format off */
766 std::vector<char> dtb = ManifestDtBuilder()
767 .Compatible({ "arm,ffa-manifest-1.0" })
768 .Property("ffa-version", "<0x10000>")
769 .Build();
770 /* clang-format on */
771
772 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
773 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
774}
775
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100776TEST_F(manifest, ffa_validate_sanity_check)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100777{
J-Alvesb37fd082020-10-22 12:29:21 +0100778 /*
779 * TODO: write test excluding all optional fields of the manifest, in
780 * accordance with specification.
781 */
Olivier Deprez93644652022-09-09 11:01:12 +0200782 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100783
784 /* Incompatible version */
785 /* clang-format off */
786 std::vector<char> dtb = ManifestDtBuilder()
787 .Compatible({ "arm,ffa-manifest-1.0" })
788 .Property("ffa-version", "<0xa1>")
789 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
790 .Property("execution-ctx-count", "<1>")
791 .Property("exception-level", "<2>")
792 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000793 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100794 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100795 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100796 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500797 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100798 .Build();
799 /* clang-format on */
800 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
801 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200802 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100803
804 /* Incompatible translation granule */
805 /* clang-format off */
806 dtb = ManifestDtBuilder()
807 .Compatible({ "arm,ffa-manifest-1.0" })
808 .Property("ffa-version", "<0x10000>")
809 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
810 .Property("execution-ctx-count", "<1>")
811 .Property("exception-level", "<2>")
812 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000813 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100814 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100815 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100816 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500817 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100818 .Build();
819 /* clang-format on */
820 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
821 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200822 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100823
824 /* Incompatible exeption level */
825 /* clang-format off */
826 dtb = ManifestDtBuilder()
827 .Compatible({ "arm,ffa-manifest-1.0" })
828 .Property("ffa-version", "<0x10000>")
829 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
830 .Property("execution-ctx-count", "<1>")
831 .Property("exception-level", "<6>")
832 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000833 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100834 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100835 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100836 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500837 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100838 .Build();
839 /* clang-format on */
840 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
841 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200842 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100843
844 /* Incompatible execution state */
845 /* clang-format off */
846 dtb = ManifestDtBuilder()
847 .Compatible({ "arm,ffa-manifest-1.0" })
848 .Property("ffa-version", "<0x10000>")
849 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
850 .Property("execution-ctx-count", "<1>")
851 .Property("exception-level", "<2>")
852 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000853 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100854 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100855 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100856 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500857 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100858 .Build();
859 /* clang-format on */
860 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
861 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200862 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100863
864 /* Incompatible messaging method */
865 /* clang-format off */
866 dtb = ManifestDtBuilder()
867 .Compatible({ "arm,ffa-manifest-1.0" })
868 .Property("ffa-version", "<0x10000>")
869 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
870 .Property("execution-ctx-count", "<1>")
871 .Property("exception-level", "<2>")
872 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000873 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100874 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100875 .Property("boot-order", "<0>")
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100876 .Property("messaging-method", "<16>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500877 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100878 .Build();
879 /* clang-format on */
880 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
881 MANIFEST_ERROR_NOT_COMPATIBLE);
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600882
883 /*
884 * No need to invoke manifest_dealloac() since manifest TearDown calls
885 * it when the test ends.
886 */
887}
888
889TEST_F(manifest, ffa_validate_interrupt_actions)
890{
891 struct_manifest *m;
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500892
893 /* Incompatible NS interrupt action */
894 /* clang-format off */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600895 std::vector<char> dtb = ManifestDtBuilder()
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500896 .Compatible({ "arm,ffa-manifest-1.0" })
897 .Property("ffa-version", "<0x10000>")
898 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
899 .Property("execution-ctx-count", "<1>")
900 .Property("exception-level", "<2>")
901 .Property("execution-state", "<0>")
902 .Property("entrypoint-offset", "<0x00002000>")
903 .Property("xlat-granule", "<0>")
904 .Property("boot-order", "<0>")
905 .Property("messaging-method", "<1>")
906 .Property("ns-interrupts-action", "<4>")
907 .Build();
908 /* clang-format on */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600909 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
910 MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
Madhukar Pappireddyee736ad2022-12-28 11:37:09 -0600911 manifest_dealloc();
912
913 /* Incompatible other-s-interrupts-action for S-EL1 partition */
914 /* clang-format off */
915 dtb = ManifestDtBuilder()
916 .Compatible({ "arm,ffa-manifest-1.0" })
917 .Property("ffa-version", "<0x10000>")
918 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
919 .Property("execution-ctx-count", "<1>")
920 .Property("exception-level", "<2>")
921 .Property("execution-state", "<0>")
922 .Property("entrypoint-offset", "<0x00002000>")
923 .Property("xlat-granule", "<0>")
924 .Property("boot-order", "<0>")
925 .Property("messaging-method", "<1>")
926 .Property("ns-interrupts-action", "<1>")
927 .Property("other-s-interrupts-action", "<0>")
928 .Build();
929 /* clang-format on */
930 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
931 MANIFEST_ERROR_NOT_COMPATIBLE);
932 manifest_dealloc();
933
934 /*
935 * Incompatible choice of the fields ns-interrupts-action and
936 * other-s-interrupts-action.
937 */
938 /* clang-format off */
939 dtb = ManifestDtBuilder()
940 .Compatible({ "arm,ffa-manifest-1.0" })
941 .Property("ffa-version", "<0x10000>")
942 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
943 .Property("execution-ctx-count", "<1>")
944 .Property("exception-level", "<1>")
945 .Property("execution-state", "<0>")
946 .Property("entrypoint-offset", "<0x00002000>")
947 .Property("xlat-granule", "<0>")
948 .Property("boot-order", "<0>")
949 .Property("messaging-method", "<1>")
950 .Property("ns-interrupts-action", "<2>")
951 .Property("other-s-interrupts-action", "<0>")
952 .Build();
953 /* clang-format on */
954 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
955 MANIFEST_ERROR_NOT_COMPATIBLE);
956 manifest_dealloc();
957
958 /* Illegal value specified for the field other-s-interrupts-action. */
959 /* clang-format off */
960 dtb = ManifestDtBuilder()
961 .Compatible({ "arm,ffa-manifest-1.0" })
962 .Property("ffa-version", "<0x10000>")
963 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
964 .Property("execution-ctx-count", "<1>")
965 .Property("exception-level", "<1>")
966 .Property("execution-state", "<0>")
967 .Property("entrypoint-offset", "<0x00002000>")
968 .Property("xlat-granule", "<0>")
969 .Property("boot-order", "<0>")
970 .Property("messaging-method", "<1>")
971 .Property("other-s-interrupts-action", "<2>")
972 .Build();
973 /* clang-format on */
974 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
975 MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION);
Olivier Deprez62d99e32020-01-09 15:58:07 +0100976}
977
Olivier Depreza15f2352022-09-26 09:17:24 +0200978TEST_F(manifest, power_management)
979{
980 struct manifest_vm *vm;
981 struct_manifest *m;
982
983 /* S-EL1 partition power management field can set bit 0. */
984 /* clang-format off */
985 std::vector<char> dtb = ManifestDtBuilder()
986 .Compatible({ "arm,ffa-manifest-1.0" })
987 .Property("ffa-version", "<0x10001>")
988 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
989 .Property("execution-ctx-count", "<8>")
990 .Property("exception-level", "<2>")
991 .Property("execution-state", "<0>")
992 .Property("entrypoint-offset", "<0x00002000>")
993 .Property("messaging-method", "<1>")
994 .Property("power-management-messages", "<1>")
995 .Build();
996 /* clang-format on */
997 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
998 vm = &m->vm[0];
999 ASSERT_EQ(vm->partition.power_management, 1);
1000 manifest_dealloc();
1001
1002 /* S-EL1 partition power management field can set bit 3. */
1003 /* clang-format off */
1004 dtb = ManifestDtBuilder()
1005 .Compatible({ "arm,ffa-manifest-1.0" })
1006 .Property("ffa-version", "<0x10001>")
1007 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1008 .Property("execution-ctx-count", "<8>")
1009 .Property("exception-level", "<2>")
1010 .Property("execution-state", "<0>")
1011 .Property("entrypoint-offset", "<0x00002000>")
1012 .Property("messaging-method", "<1>")
1013 .Property("power-management-messages", "<8>")
1014 .Build();
1015 /* clang-format on */
1016 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1017 vm = &m->vm[0];
1018 ASSERT_EQ(vm->partition.power_management, 8);
1019 manifest_dealloc();
1020
1021 /* S-EL1 partition power management field can only set bits 0 and 3. */
1022 /* clang-format off */
1023 dtb = ManifestDtBuilder()
1024 .Compatible({ "arm,ffa-manifest-1.0" })
1025 .Property("ffa-version", "<0x10001>")
1026 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1027 .Property("execution-ctx-count", "<8>")
1028 .Property("exception-level", "<2>")
1029 .Property("execution-state", "<0>")
1030 .Property("entrypoint-offset", "<0x00002000>")
1031 .Property("messaging-method", "<1>")
1032 .Property("power-management-messages", "<0xf>")
1033 .Build();
1034 /* clang-format on */
1035 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1036 vm = &m->vm[0];
1037 ASSERT_EQ(vm->partition.power_management, 9);
1038 manifest_dealloc();
1039
1040 /* S-EL0 partition power management field is forced to 0. */
1041 /* clang-format off */
1042 dtb = ManifestDtBuilder()
1043 .Compatible({ "arm,ffa-manifest-1.0" })
1044 .Property("ffa-version", "<0x10001>")
1045 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1046 .Property("execution-ctx-count", "<1>")
1047 .Property("exception-level", "<1>")
1048 .Property("execution-state", "<0>")
1049 .Property("entrypoint-offset", "<0x00002000>")
1050 .Property("messaging-method", "<1>")
1051 .Property("power-management-messages", "<0xff>")
1052 .Build();
1053 /* clang-format on */
1054 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1055 vm = &m->vm[0];
1056 ASSERT_EQ(vm->partition.power_management, 0);
1057}
1058
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001059TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001060{
Olivier Deprez93644652022-09-09 11:01:12 +02001061 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001062
1063 /* Not Compatible */
1064 /* clang-format off */
1065 std::vector<char> dtb = ManifestDtBuilder()
1066 .FfaValidManifest()
1067 .StartChild("rx_tx-info")
1068 .Compatible({ "foo,bar" })
1069 .EndChild()
1070 .Build();
1071 /* clang-format on */
1072 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1073 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001074 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001075
1076 /* Missing Properties */
1077 /* clang-format off */
1078 dtb = ManifestDtBuilder()
1079 .FfaValidManifest()
1080 .StartChild("rx_tx-info")
1081 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1082 .EndChild()
1083 .Build();
1084 /* clang-format on */
1085 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1086 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1087}
1088
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001089TEST_F(manifest, ffa_validate_mem_regions)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001090{
Olivier Deprez93644652022-09-09 11:01:12 +02001091 struct_manifest *m;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001092
1093 /* Not Compatible */
1094 /* clang-format off */
1095 std::vector<char> dtb = ManifestDtBuilder()
1096 .FfaValidManifest()
1097 .StartChild("memory-regions")
1098 .Compatible({ "foo,bar" })
1099 .EndChild()
1100 .Build();
1101 /* clang-format on */
1102 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1103 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001104 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001105
1106 /* Memory regions unavailable */
1107 /* clang-format off */
1108 dtb = ManifestDtBuilder()
1109 .FfaValidManifest()
1110 .StartChild("memory-regions")
1111 .Compatible({ "arm,ffa-manifest-memory-regions" })
1112 .EndChild()
1113 .Build();
1114 /* clang-format on */
1115 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1116 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001117 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001118
1119 /* Missing Properties */
1120 /* clang-format off */
1121 dtb = ManifestDtBuilder()
1122 .FfaValidManifest()
1123 .StartChild("memory-regions")
1124 .Compatible({ "arm,ffa-manifest-memory-regions" })
1125 .StartChild("test-memory")
1126 .Description("test-memory")
1127 .EndChild()
1128 .EndChild()
1129 .Build();
1130 /* clang-format on */
1131 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1132 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001133 manifest_dealloc();
Manish Pandeyf06c9072020-09-29 15:41:58 +01001134
Daniel Boulby9279b552022-06-28 17:04:01 +01001135 /* Overlapping memory regions */
1136 /* clang-format off */
1137 dtb = ManifestDtBuilder()
1138 .FfaValidManifest()
1139 .StartChild("memory-regions")
1140 .Compatible({ "arm,ffa-manifest-memory-regions" })
1141 .Label("rx")
1142 .StartChild("rx")
1143 .Description("rx-buffer")
1144 .Property("base-address", "<0x7300000>")
1145 .Property("pages-count", "<1>")
1146 .Property("attributes", "<1>")
1147 .EndChild()
1148 .Label("tx")
1149 .StartChild("tx")
1150 .Description("tx-buffer")
1151 .Property("base-address", "<0x7300000>")
1152 .Property("pages-count", "<2>")
1153 .Property("attributes", "<3>")
1154 .EndChild()
1155 .EndChild()
1156 .Build();
1157 /* clang-format on */
1158 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1159 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001160 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001161
1162 /* clang-format off */
1163 dtb = ManifestDtBuilder()
1164 .FfaValidManifest()
1165 .StartChild("memory-regions")
1166 .Compatible({ "arm,ffa-manifest-memory-regions" })
1167 .Label("rx")
1168 .StartChild("rx")
1169 .Description("rx-buffer")
1170 .Property("base-address", "<0x7300000>")
1171 .Property("pages-count", "<2>")
1172 .Property("attributes", "<1>")
1173 .EndChild()
1174 .Label("tx")
1175 .StartChild("tx")
1176 .Description("tx-buffer")
1177 .Property("base-address", "<0x7301000>")
1178 .Property("pages-count", "<2>")
1179 .Property("attributes", "<3>")
1180 .EndChild()
1181 .EndChild()
1182 .Build();
1183 /* clang-format on */
1184 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1185 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001186 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001187
1188 /* clang-format off */
1189 dtb = ManifestDtBuilder()
1190 .FfaValidManifest()
1191 .StartChild("memory-regions")
1192 .Compatible({ "arm,ffa-manifest-memory-regions" })
1193 .Label("rx")
1194 .StartChild("rx")
1195 .Description("rx-buffer")
1196 .Property("base-address", "<0x7300000>")
1197 .Property("pages-count", "<2>")
1198 .Property("attributes", "<1>")
1199 .EndChild()
1200 .Label("tx")
1201 .StartChild("tx")
1202 .Description("tx-buffer")
1203 .Property("base-address", "<0x7301FFF>")
1204 .Property("pages-count", "<2>")
1205 .Property("attributes", "<3>")
1206 .EndChild()
1207 .EndChild()
1208 .Build();
1209 /* clang-format on */
1210 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1211 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001212 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001213
Manish Pandeyf06c9072020-09-29 15:41:58 +01001214 /* Different RXTX buffer sizes */
1215 /* clang-format off */
1216 dtb = ManifestDtBuilder()
1217 .FfaValidManifest()
1218 .StartChild("memory-regions")
1219 .Compatible({ "arm,ffa-manifest-memory-regions" })
1220 .Label("rx")
1221 .StartChild("rx")
1222 .Description("rx-buffer")
1223 .Property("base-address", "<0x7300000>")
1224 .Property("pages-count", "<1>")
1225 .Property("attributes", "<1>")
1226 .EndChild()
1227 .Label("tx")
1228 .StartChild("tx")
1229 .Description("tx-buffer")
1230 .Property("base-address", "<0x7310000>")
1231 .Property("pages-count", "<2>")
1232 .Property("attributes", "<3>")
1233 .EndChild()
1234 .EndChild()
1235 .StartChild("rx_tx-info")
1236 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1237 .Property("rx-buffer", "<&rx>")
1238 .Property("tx-buffer", "<&tx>")
1239 .EndChild()
1240 .Build();
1241 /* clang-format on */
1242 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1243 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001244}
1245
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001246TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001247{
Olivier Deprez93644652022-09-09 11:01:12 +02001248 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001249
1250 /* Not Compatible */
1251 /* clang-format off */
1252 std::vector<char> dtb = ManifestDtBuilder()
1253 .FfaValidManifest()
1254 .StartChild("device-regions")
1255 .Compatible({ "foo,bar" })
1256 .EndChild()
1257 .Build();
1258 /* clang-format on */
1259 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1260 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001261 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001262
1263 /* Memory regions unavailable */
1264 /* clang-format off */
1265 dtb = ManifestDtBuilder()
1266 .FfaValidManifest()
1267 .StartChild("device-regions")
1268 .Compatible({ "arm,ffa-manifest-device-regions" })
1269 .EndChild()
1270 .Build();
1271 /* clang-format on */
1272 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1273 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001274 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001275
1276 /* Missing Properties */
1277 /* clang-format off */
1278 dtb = ManifestDtBuilder()
1279 .FfaValidManifest()
1280 .StartChild("device-regions")
1281 .Compatible({ "arm,ffa-manifest-device-regions" })
1282 .StartChild("test-device")
1283 .Description("test-device")
1284 .EndChild()
1285 .EndChild()
1286 .Build();
1287 /* clang-format on */
1288 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1289 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001290 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001291
1292 /* Malformed interrupt list pair */
1293 /* clang-format off */
1294 dtb = ManifestDtBuilder()
1295 .FfaValidManifest()
1296 .StartChild("device-regions")
1297 .Compatible({ "arm,ffa-manifest-device-regions" })
1298 .StartChild("test-device")
1299 .Description("test-device")
1300 .Property("base-address", "<0x7200000>")
1301 .Property("pages-count", "<16>")
1302 .Property("attributes", "<3>")
1303 .Property("smmu-id", "<1>")
1304 .Property("stream-ids", "<0 1>")
1305 .Property("interrupts", "<2 3>, <4>")
1306 .EndChild()
1307 .EndChild()
1308 .Build();
1309 /* clang-format on */
1310 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1311 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001312 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001313
1314 /* Non-unique interrupt IDs */
1315 /* clang-format off */
1316 dtb = ManifestDtBuilder()
1317 .FfaValidManifest()
1318 .StartChild("device-regions")
1319 .Compatible({ "arm,ffa-manifest-device-regions" })
1320 .StartChild("test-device-0")
1321 .Description("test-device-0")
1322 .Property("base-address", "<0x7200000>")
1323 .Property("pages-count", "<16>")
1324 .Property("attributes", "<3>")
1325 .Property("interrupts", "<2 3>")
1326 .EndChild()
1327 .StartChild("test-device-1")
1328 .Description("test-device-1")
1329 .Property("base-address", "<0x8200000>")
1330 .Property("pages-count", "<16>")
1331 .Property("attributes", "<3>")
1332 .Property("interrupts", "<1 3>, <2 5> ")
1333 .EndChild()
1334 .EndChild()
1335 .Build();
1336 /* clang-format on */
1337 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1338 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1339 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001340 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1341 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1342 3);
1343 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1344 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1345 3);
Manish Pandeye68e7932020-04-23 15:29:28 +01001346}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001347
1348TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001349{
Olivier Deprez93644652022-09-09 11:01:12 +02001350 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001351
1352 /* clang-format off */
1353 std::vector<char> dtb = ManifestDtBuilder()
1354 .FfaValidManifest()
1355 .StartChild("rx_tx-info")
1356 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1357 .Property("rx-buffer", "<&rx>")
1358 .Property("tx-buffer", "<&tx>")
1359 .EndChild()
1360 .StartChild("memory-regions")
1361 .Compatible({ "arm,ffa-manifest-memory-regions" })
1362 .StartChild("test-memory")
1363 .Description("test-memory")
1364 .Property("base-address", "<0x7100000>")
1365 .Property("pages-count", "<4>")
1366 .Property("attributes", "<7>")
1367 .EndChild()
1368 .Label("rx")
1369 .StartChild("rx")
1370 .Description("rx-buffer")
1371 .Property("base-address", "<0x7300000>")
1372 .Property("pages-count", "<1>")
1373 .Property("attributes", "<1>")
1374 .EndChild()
1375 .Label("tx")
1376 .StartChild("tx")
1377 .Description("tx-buffer")
1378 .Property("base-address", "<0x7310000>")
1379 .Property("pages-count", "<1>")
1380 .Property("attributes", "<3>")
1381 .EndChild()
1382 .EndChild()
1383 .Build();
1384 /* clang-format on */
1385
1386 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1387 MANIFEST_ERROR_INVALID_MEM_PERM);
1388}
1389
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001390TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001391{
Olivier Deprez93644652022-09-09 11:01:12 +02001392 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001393
1394 /* clang-format off */
1395 std::vector<char> dtb = ManifestDtBuilder()
1396 .FfaValidManifest()
1397 .StartChild("rx_tx-info")
1398 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1399 .Property("rx-buffer", "<&rx>")
1400 .Property("tx-buffer", "<&tx>")
1401 .EndChild()
1402 .StartChild("memory-regions")
1403 .Compatible({ "arm,ffa-manifest-memory-regions" })
1404 .StartChild("test-memory")
1405 .Description("test-memory")
1406 .Property("base-address", "<0x7100000>")
1407 .Property("pages-count", "<4>")
1408 .Property("attributes", "<3>")
1409 .EndChild()
1410 .Label("rx")
1411 .StartChild("rx")
1412 .Description("rx-buffer")
1413 .Property("base-address", "<0x7300000>")
1414 .Property("pages-count", "<1>")
1415 .Property("attributes", "<1>")
1416 .EndChild()
1417 .Label("tx")
1418 .StartChild("tx")
1419 .Description("tx-buffer")
1420 .Property("base-address", "<0x7310000>")
1421 .Property("pages-count", "<1>")
1422 .Property("attributes", "<3>")
1423 .EndChild()
1424 .EndChild()
1425 .StartChild("device-regions")
1426 .Compatible({ "arm,ffa-manifest-device-regions" })
1427 .StartChild("test-device")
1428 .Description("test-device")
1429 .Property("base-address", "<0x7200000>")
1430 .Property("pages-count", "<16>")
1431 .Property("attributes", "<5>")
1432 .Property("smmu-id", "<1>")
1433 .Property("stream-ids", "<0 1>")
1434 .Property("interrupts", "<2 3>, <4 5>")
1435 .EndChild()
1436 .EndChild()
1437 .Build();
1438 /* clang-format on */
1439
1440 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1441 MANIFEST_ERROR_INVALID_MEM_PERM);
1442}
Manish Pandeye68e7932020-04-23 15:29:28 +01001443
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001444TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01001445{
Olivier Deprez93644652022-09-09 11:01:12 +02001446 struct manifest_vm *vm;
1447 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01001448
1449 /* clang-format off */
1450 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001451 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001452 .StartChild("rx_tx-info")
1453 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1454 .Property("rx-buffer", "<&rx>")
1455 .Property("tx-buffer", "<&tx>")
1456 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001457 .StartChild("memory-regions")
1458 .Compatible({ "arm,ffa-manifest-memory-regions" })
1459 .StartChild("test-memory")
1460 .Description("test-memory")
1461 .Property("base-address", "<0x7100000>")
1462 .Property("pages-count", "<4>")
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001463 .Property("attributes", "<3>")
Manish Pandey6542f5c2020-04-27 14:37:46 +01001464 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001465 .StartChild("test-memory-ns")
1466 .Description("test-memory")
1467 .Property("base-address", "<0x7200000>")
1468 .Property("pages-count", "<1>")
1469 .Property("attributes", "<0xb>")
1470 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001471 .Label("rx")
1472 .StartChild("rx")
1473 .Description("rx-buffer")
1474 .Property("base-address", "<0x7300000>")
1475 .Property("pages-count", "<1>")
1476 .Property("attributes", "<1>")
1477 .EndChild()
1478 .Label("tx")
1479 .StartChild("tx")
1480 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001481 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001482 .Property("pages-count", "<1>")
1483 .Property("attributes", "<3>")
1484 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001485 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001486 .StartChild("device-regions")
1487 .Compatible({ "arm,ffa-manifest-device-regions" })
1488 .StartChild("test-device")
1489 .Description("test-device")
Olivier Deprez035fa152022-03-14 11:19:10 +01001490 .Property("base-address", "<0x7400000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001491 .Property("pages-count", "<16>")
1492 .Property("attributes", "<3>")
1493 .Property("smmu-id", "<1>")
1494 .Property("stream-ids", "<0 1>")
1495 .Property("interrupts", "<2 3>, <4 5>")
1496 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001497 .StartChild("test-device-ns")
1498 .Description("test-device")
1499 .Property("base-address", "<0x7500000>")
1500 .Property("pages-count", "<1>")
1501 .Property("attributes", "<0x9>")
1502 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001503 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001504 .Build();
1505 /* clang-format on */
1506
1507 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1508
Olivier Deprez93644652022-09-09 11:01:12 +02001509 vm = &m->vm[0];
1510 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001511 ASSERT_THAT(
Olivier Deprez93644652022-09-09 11:01:12 +02001512 std::span(vm->partition.uuid.uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001513 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02001514 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
1515 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
1516 ASSERT_EQ(vm->partition.execution_state, AARCH64);
1517 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
1518 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
1519 ASSERT_EQ(vm->partition.boot_order, 0);
1520 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
1521 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
1522 ASSERT_EQ(vm->partition.mem_regions[0].base_address, 0x7100000);
1523 ASSERT_EQ(vm->partition.mem_regions[0].page_count, 4);
1524 ASSERT_EQ(vm->partition.mem_regions[0].attributes, 3);
1525 ASSERT_EQ(vm->partition.mem_regions[1].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001526
Olivier Deprez93644652022-09-09 11:01:12 +02001527 ASSERT_EQ(vm->partition.rxtx.available, true);
1528 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
1529 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
1530 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
1531 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
1532 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
1533 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
1534
1535 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x7400000);
1536 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
1537 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
1538 ASSERT_EQ(vm->partition.dev_regions[0].smmu_id, 1);
1539 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[0], 0);
1540 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[1], 1);
1541 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1542 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1543 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1544 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
1545 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01001546}
1547
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001548TEST_F(manifest, ffa_valid_interrupt_target_manifest)
1549{
1550 struct manifest_vm *vm;
1551 struct_manifest *m;
1552
1553 /* clang-format off */
1554 std::vector<char> dtb = ManifestDtBuilder()
1555 .FfaValidManifest()
1556 .StartChild("device-regions")
1557 .Compatible({ "arm,ffa-manifest-device-regions" })
1558 .StartChild("test-device")
1559 .Description("test-device")
1560 .Property("base-address", "<0x7400000>")
1561 .Property("pages-count", "<16>")
1562 .Property("attributes", "<3>")
1563 .Property("smmu-id", "<1>")
1564 .Property("stream-ids", "<0 1>")
1565 .Property("interrupts", "<2 3>, <4 5>")
1566 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
1567 .EndChild()
1568 .EndChild()
1569 .Build();
1570 /* clang-format on */
1571
1572 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1573
1574 vm = &m->vm[0];
1575
1576 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x7400000);
1577 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
1578 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
1579 ASSERT_EQ(vm->partition.dev_regions[0].smmu_id, 1);
1580 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[0], 0);
1581 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[1], 1);
1582 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1583 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1584 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
1585 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
1586 0x123400005678);
1587 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1588 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
1589 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
1590 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
1591 0x1234567887654321);
1592}
1593
1594TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
1595{
1596 struct_manifest *m;
1597
1598 /* clang-format off */
1599 std::vector<char> dtb = ManifestDtBuilder()
1600 .FfaValidManifest()
1601 .StartChild("device-regions")
1602 .Compatible({ "arm,ffa-manifest-device-regions" })
1603 .StartChild("test-device")
1604 .Description("test-device")
1605 .Property("base-address", "<0x7400000>")
1606 .Property("pages-count", "<16>")
1607 .Property("attributes", "<3>")
1608 .Property("smmu-id", "<1>")
1609 .Property("stream-ids", "<0 1>")
1610 .Property("interrupts", "<2 3>, <4 5>")
1611 .Property("interrupts-target", "<20 0x1234 0x5678>")
1612 .EndChild()
1613 .EndChild()
1614 .Build();
1615 /* clang-format on */
1616
1617 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1618 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
1619}
1620
David Brazdil7a462ec2019-08-15 12:27:47 +01001621} /* namespace */