blob: a4e9d33db2e017a6a2641dc24f3b5240496da537 [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
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400251 ManifestDtBuilder &FfaLoadAddress(uint64_t value)
252 {
253 Integer64Property("load-address", value);
254 return *this;
255 }
256
David Brazdil52256ff2019-08-23 15:15:15 +0100257 private:
258 ManifestDtBuilder &StringProperty(const std::string_view &name,
259 const std::string_view &value)
260 {
261 dts_ << name << " = \"" << value << "\";" << std::endl;
262 return *this;
263 }
264
David Brazdil74e9c3b2019-08-28 11:09:08 +0100265 ManifestDtBuilder &StringListProperty(
266 const std::string_view &name,
267 const std::vector<std::string_view> &value)
268 {
269 bool is_first = true;
270
271 dts_ << name << " = ";
272 for (const std::string_view &entry : value) {
273 if (is_first) {
274 is_first = false;
275 } else {
276 dts_ << ", ";
277 }
278 dts_ << "\"" << entry << "\"";
279 }
280 dts_ << ";" << std::endl;
281 return *this;
282 }
283
David Brazdil52256ff2019-08-23 15:15:15 +0100284 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100285 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100286 {
287 dts_ << name << " = <" << value << ">;" << std::endl;
288 return *this;
289 }
290
David Brazdil080ee312020-02-25 15:30:30 -0800291 ManifestDtBuilder &Integer64Property(const std::string_view &name,
292 uint64_t value)
293 {
294 uint32_t high = value >> 32;
295 uint32_t low = (uint32_t)value;
296 dts_ << name << " = <" << high << " " << low << ">;"
297 << std::endl;
298 return *this;
299 }
300
Andrew Scullae9962e2019-10-03 16:51:16 +0100301 ManifestDtBuilder &IntegerListProperty(
302 const std::string_view &name,
303 const std::vector<uint32_t> &value)
304 {
305 dts_ << name << " = < ";
306 for (const uint32_t entry : value) {
307 dts_ << entry << " ";
308 }
309 dts_ << ">;" << std::endl;
310 return *this;
311 }
312
313 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
314 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000315 dts_ << name << ";" << std::endl;
316 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100317 }
318
David Brazdil52256ff2019-08-23 15:15:15 +0100319 std::stringstream dts_;
320};
321
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100322class manifest : public ::testing::Test
David Brazdil0dbb41f2019-09-09 18:03:35 +0100323{
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100324 void SetUp() override
325 {
326 test_heap = std::make_unique<uint8_t[]>(TEST_HEAP_SIZE);
327 mpool_init(&ppool, MM_PPOOL_ENTRY_SIZE);
328 mpool_add_chunk(&ppool, test_heap.get(), TEST_HEAP_SIZE);
329 }
330
Olivier Deprez93644652022-09-09 11:01:12 +0200331 void TearDown() override
332 {
333 manifest_dealloc();
334 }
335
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100336 std::unique_ptr<uint8_t[]> test_heap;
337
338 protected:
Olivier Deprez62d99e32020-01-09 15:58:07 +0100339 struct mpool ppool;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100340
Olivier Deprez93644652022-09-09 11:01:12 +0200341 void manifest_dealloc(void)
342 {
343 manifest_deinit(&ppool);
344 }
345
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100346 public:
347 /**
348 * Class for programatically building a Partition package.
349 */
350 class Partition_package
351 {
352 public:
353 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
354 __attribute__((
355 aligned(PAGE_SIZE))) char manifest_dtb[PAGE_SIZE] = {};
356 __attribute__((aligned(PAGE_SIZE))) char img[PAGE_SIZE] = {};
David Brazdil0dbb41f2019-09-09 18:03:35 +0100357
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100358 Partition_package(const std::vector<char> &vec)
359 {
Kathleen Capella4a2a6e72023-04-21 14:43:26 -0400360 init(vec);
361 }
362
363 Partition_package()
364 {
365 }
366
367 void init(const std::vector<char> &vec)
368 {
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100369 // Initialise header field
370 spkg.magic = SP_PKG_HEADER_MAGIC;
371 spkg.version = SP_PKG_HEADER_VERSION_2;
372 spkg.pm_offset = PAGE_SIZE;
373 spkg.pm_size = vec.size();
374 spkg.img_offset = 2 * PAGE_SIZE;
375 spkg.img_size = ARRAY_SIZE(img);
376
377 // Copy dtb into package
378 std::copy(vec.begin(), vec.end(), manifest_dtb);
379 }
380 };
381
J-Alves77b6f4f2023-03-15 11:34:49 +0000382 static void boot_params_init(struct boot_params *params,
383 Partition_package *pkg)
384 {
385 /*
386 * For the manifest tests we only care about the memory ranges
387 * in boot_params.
388 */
389 params->mem_ranges[0].begin = pa_init((uintpaddr_t)0x7000000);
390 params->mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
391 params->mem_ranges_count = 1;
392
393 if (pkg != nullptr) {
394 auto mem_base = (uintpaddr_t)pkg;
395 uintpaddr_t mem_end =
396 mem_base + sp_pkg_get_mem_size(&pkg->spkg);
397
398 params->mem_ranges_count++;
399
400 params->mem_ranges[1].begin = pa_init(mem_base);
401 params->mem_ranges[1].end = pa_init(mem_end);
402 }
403
404 params->ns_mem_ranges[0].begin =
405 pa_init((uintpaddr_t)0x7000000);
406 params->ns_mem_ranges[0].end = pa_init((uintpaddr_t)0x8ffffff);
407 params->ns_mem_ranges_count = 1;
408 }
409
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100410 enum manifest_return_code manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200411 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100412 {
413 struct memiter it;
414 struct mm_stage1_locked mm_stage1_locked;
J-Alves77b6f4f2023-03-15 11:34:49 +0000415 struct boot_params params;
416
417 boot_params_init(&params, nullptr);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100418
419 memiter_init(&it, vec.data(), vec.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100420
J-Alves77b6f4f2023-03-15 11:34:49 +0000421 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100422 }
423
424 enum manifest_return_code ffa_manifest_from_vec(
Olivier Deprez93644652022-09-09 11:01:12 +0200425 struct_manifest **m, const std::vector<char> &vec)
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100426 {
427 struct memiter it;
428 struct mm_stage1_locked mm_stage1_locked;
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100429 Partition_package spkg(vec);
J-Alves77b6f4f2023-03-15 11:34:49 +0000430 struct boot_params params;
431
432 boot_params_init(&params, &spkg);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100433
434 /* clang-format off */
435 std::vector<char> core_dtb = ManifestDtBuilder()
436 .StartChild("hypervisor")
437 .Compatible()
438 .StartChild("vm1")
439 .DebugName("primary_vm")
440 .FfaPartition()
441 .LoadAddress((uint64_t)&spkg)
442 .EndChild()
443 .EndChild()
444 .Build();
445 /* clang-format on */
446 memiter_init(&it, core_dtb.data(), core_dtb.size());
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100447
J-Alves77b6f4f2023-03-15 11:34:49 +0000448 return manifest_init(mm_stage1_locked, m, &it, &params, &ppool);
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100449 }
450};
451
452TEST_F(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100453{
Olivier Deprez93644652022-09-09 11:01:12 +0200454 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100455 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100456
David Brazdila2358d42020-01-27 18:51:38 +0000457 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100458 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
459}
460
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100461TEST_F(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100462{
Olivier Deprez93644652022-09-09 11:01:12 +0200463 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100464
David Brazdil52256ff2019-08-23 15:15:15 +0100465 /* clang-format off */
466 std::vector<char> dtb = ManifestDtBuilder()
467 .StartChild("hypervisor")
468 .EndChild()
469 .Build();
470 /* clang-format on */
471
David Brazdilf4925382020-03-25 13:33:51 +0000472 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100473}
474
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100475TEST_F(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100476{
Olivier Deprez93644652022-09-09 11:01:12 +0200477 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100478
David Brazdil52256ff2019-08-23 15:15:15 +0100479 /* clang-format off */
480 std::vector<char> dtb = ManifestDtBuilder()
481 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100482 .Compatible({ "foo,bar" })
483 .EndChild()
484 .Build();
485 /* clang-format on */
486
David Brazdila2358d42020-01-27 18:51:38 +0000487 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100488}
489
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100490TEST_F(manifest, compatible_one_of_many)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100491{
Olivier Deprez93644652022-09-09 11:01:12 +0200492 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100493
494 /* clang-format off */
495 std::vector<char> dtb = ManifestDtBuilder()
496 .StartChild("hypervisor")
497 .Compatible({ "foo,bar", "hafnium,hafnium" })
498 .StartChild("vm1")
499 .DebugName("primary")
500 .EndChild()
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_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100506}
507
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100508TEST_F(manifest, no_vm_nodes)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100509{
Olivier Deprez93644652022-09-09 11:01:12 +0200510 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100511
512 /* clang-format off */
513 std::vector<char> dtb = ManifestDtBuilder()
514 .StartChild("hypervisor")
515 .Compatible()
516 .EndChild()
517 .Build();
518 /* clang-format on */
519
David Brazdila2358d42020-01-27 18:51:38 +0000520 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100521}
522
523static std::vector<char> gen_long_string_dtb(bool valid)
524{
525 const char last_valid[] = "1234567890123456789012345678901";
526 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100527 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
528 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100529
530 /* clang-format off */
531 return ManifestDtBuilder()
532 .StartChild("hypervisor")
533 .Compatible()
534 .StartChild("vm1")
535 .DebugName(valid ? last_valid : first_invalid)
536 .EndChild()
537 .EndChild()
538 .Build();
539 /* clang-format on */
540}
541
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100542TEST_F(manifest, long_string)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100543{
Olivier Deprez93644652022-09-09 11:01:12 +0200544 struct_manifest *m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100545 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
546 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
547
David Brazdila2358d42020-01-27 18:51:38 +0000548 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200549 manifest_dealloc();
550
David Brazdila2358d42020-01-27 18:51:38 +0000551 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
552 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100553}
554
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100555TEST_F(manifest, reserved_vm_id)
David Brazdil74e9c3b2019-08-28 11:09:08 +0100556{
Olivier Deprez93644652022-09-09 11:01:12 +0200557 struct_manifest *m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100558
559 /* clang-format off */
560 std::vector<char> dtb = ManifestDtBuilder()
561 .StartChild("hypervisor")
562 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100563 .StartChild("vm1")
564 .DebugName("primary_vm")
565 .EndChild()
566 .StartChild("vm0")
567 .DebugName("reserved_vm")
568 .VcpuCount(1)
569 .MemSize(0x1000)
570 .KernelFilename("kernel")
571 .EndChild()
572 .EndChild()
573 .Build();
574 /* clang-format on */
575
David Brazdila2358d42020-01-27 18:51:38 +0000576 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100577}
578
Andrew Scullae9962e2019-10-03 16:51:16 +0100579static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100580{
581 /* clang-format off */
582 return ManifestDtBuilder()
583 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100584 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100585 .StartChild("vm1")
586 .DebugName("primary_vm")
587 .EndChild()
588 .StartChild("vm2")
589 .DebugName("secondary_vm")
590 .VcpuCount(vcpu_count)
591 .MemSize(0x1000)
592 .KernelFilename("kernel")
593 .EndChild()
594 .EndChild()
595 .Build();
596 /* clang-format on */
597}
David Brazdil7a462ec2019-08-15 12:27:47 +0100598
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100599TEST_F(manifest, vcpu_count_limit)
David Brazdil7a462ec2019-08-15 12:27:47 +0100600{
Olivier Deprez93644652022-09-09 11:01:12 +0200601 struct_manifest *m;
David Brazdil52256ff2019-08-23 15:15:15 +0100602 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
603 std::vector<char> dtb_first_invalid =
604 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100605
David Brazdila2358d42020-01-27 18:51:38 +0000606 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200607 ASSERT_EQ(m->vm_count, 2);
608 ASSERT_EQ(m->vm[1].secondary.vcpu_count, UINT16_MAX);
609 manifest_dealloc();
David Brazdil7a462ec2019-08-15 12:27:47 +0100610
David Brazdila2358d42020-01-27 18:51:38 +0000611 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100612 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100613}
614
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100615TEST_F(manifest, no_ramdisk_primary)
David Brazdile6f83222019-09-23 14:47:37 +0100616{
Olivier Deprez93644652022-09-09 11:01:12 +0200617 struct_manifest *m;
David Brazdile6f83222019-09-23 14:47:37 +0100618
619 /* clang-format off */
620 std::vector<char> dtb = ManifestDtBuilder()
621 .StartChild("hypervisor")
622 .Compatible()
623 .StartChild("vm1")
624 .DebugName("primary_vm")
625 .EndChild()
626 .EndChild()
627 .Build();
628 /* clang-format on */
629
David Brazdila2358d42020-01-27 18:51:38 +0000630 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200631 ASSERT_EQ(m->vm_count, 1);
632 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
633 ASSERT_STREQ(string_data(&m->vm[0].primary.ramdisk_filename), "");
David Brazdile6f83222019-09-23 14:47:37 +0100634}
635
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100636TEST_F(manifest, no_boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800637{
Olivier Deprez93644652022-09-09 11:01:12 +0200638 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800639
640 /* clang-format off */
641 std::vector<char> dtb = ManifestDtBuilder()
642 .StartChild("hypervisor")
643 .Compatible()
644 .StartChild("vm1")
645 .DebugName("primary_vm")
646 .EndChild()
647 .EndChild()
648 .Build();
649 /* clang-format on */
650
651 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200652 ASSERT_EQ(m->vm_count, 1);
653 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
654 ASSERT_EQ(m->vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
David Brazdil080ee312020-02-25 15:30:30 -0800655}
656
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100657TEST_F(manifest, boot_address_primary)
David Brazdil080ee312020-02-25 15:30:30 -0800658{
Olivier Deprez93644652022-09-09 11:01:12 +0200659 struct_manifest *m;
David Brazdil080ee312020-02-25 15:30:30 -0800660 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
661
662 /* clang-format off */
663 std::vector<char> dtb = ManifestDtBuilder()
664 .StartChild("hypervisor")
665 .Compatible()
666 .StartChild("vm1")
667 .DebugName("primary_vm")
668 .BootAddress(addr)
669 .EndChild()
670 .EndChild()
671 .Build();
672 /* clang-format on */
673
674 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200675 ASSERT_EQ(m->vm_count, 1);
676 ASSERT_STREQ(string_data(&m->vm[0].debug_name), "primary_vm");
677 ASSERT_EQ(m->vm[0].primary.boot_address, addr);
David Brazdil080ee312020-02-25 15:30:30 -0800678}
679
Andrew Scullb2c3a242019-11-04 13:52:36 +0000680static std::vector<char> gen_malformed_boolean_dtb(
681 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100682{
Andrew Scullae9962e2019-10-03 16:51:16 +0100683 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000684 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100685 .StartChild("hypervisor")
686 .Compatible()
687 .StartChild("vm1")
688 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000689 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000690 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100691 .EndChild()
692 .Build();
693 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000694}
Andrew Scullae9962e2019-10-03 16:51:16 +0100695
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100696TEST_F(manifest, malformed_booleans)
Andrew Scullb2c3a242019-11-04 13:52:36 +0000697{
Olivier Deprez93644652022-09-09 11:01:12 +0200698 struct_manifest *m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100699
Andrew Scullb2c3a242019-11-04 13:52:36 +0000700 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
701 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
702 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
703 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100704
David Brazdila2358d42020-01-27 18:51:38 +0000705 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000706 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200707 manifest_dealloc();
708
David Brazdila2358d42020-01-27 18:51:38 +0000709 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000710 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200711 manifest_dealloc();
712
David Brazdila2358d42020-01-27 18:51:38 +0000713 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000714 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Olivier Deprez93644652022-09-09 11:01:12 +0200715 manifest_dealloc();
716
David Brazdila2358d42020-01-27 18:51:38 +0000717 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000718 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100719}
720
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100721TEST_F(manifest, valid)
David Brazdil7a462ec2019-08-15 12:27:47 +0100722{
Olivier Deprez93644652022-09-09 11:01:12 +0200723 struct_manifest *m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100724 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100725
David Brazdil52256ff2019-08-23 15:15:15 +0100726 /* clang-format off */
727 std::vector<char> dtb = ManifestDtBuilder()
728 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100729 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100730 .StartChild("vm1")
731 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100732 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100733 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100734 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100735 .EndChild()
736 .StartChild("vm3")
737 .DebugName("second_secondary_vm")
738 .VcpuCount(43)
739 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100740 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100741 .EndChild()
742 .StartChild("vm2")
743 .DebugName("first_secondary_vm")
744 .VcpuCount(42)
745 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100746 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
747 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100748 .EndChild()
749 .EndChild()
750 .Build();
751 /* clang-format on */
752
David Brazdila2358d42020-01-27 18:51:38 +0000753 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
Olivier Deprez93644652022-09-09 11:01:12 +0200754 ASSERT_EQ(m->vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100755
Olivier Deprez93644652022-09-09 11:01:12 +0200756 vm = &m->vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100757 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
758 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100759 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
760 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100761 ASSERT_THAT(
762 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
763 ElementsAre(0x32000000, 0x33001111));
764 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100765
Olivier Deprez93644652022-09-09 11:01:12 +0200766 vm = &m->vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100767 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
768 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100769 ASSERT_EQ(vm->secondary.vcpu_count, 42);
770 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100771 ASSERT_THAT(
772 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
773 ElementsAre(0x04000000, 0x30002222, 0x31445566));
774 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100775
Olivier Deprez93644652022-09-09 11:01:12 +0200776 vm = &m->vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100777 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
778 ASSERT_STREQ(string_data(&vm->kernel_filename),
779 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100780 ASSERT_EQ(vm->secondary.vcpu_count, 43);
781 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100782 ASSERT_THAT(
783 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
784 IsEmpty());
785 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100786}
787
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100788TEST_F(manifest, ffa_not_compatible)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100789{
Olivier Deprez93644652022-09-09 11:01:12 +0200790 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100791
792 /* clang-format off */
793 std::vector<char> dtb = ManifestDtBuilder()
794 .Compatible({ "arm,ffa-manifest-2.0" })
795 .Property("ffa-version", "<0x10000>")
796 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
797 .Property("execution-ctx-count", "<1>")
798 .Property("exception-level", "<2>")
799 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000800 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100801 .Property("xlat-granule", "<0>")
802 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500803 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100804 .Build();
805 /* clang-format on */
806
807 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
808 MANIFEST_ERROR_NOT_COMPATIBLE);
809}
810
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100811TEST_F(manifest, ffa_missing_property)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100812{
Olivier Deprez93644652022-09-09 11:01:12 +0200813 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100814
815 /* clang-format off */
816 std::vector<char> dtb = ManifestDtBuilder()
817 .Compatible({ "arm,ffa-manifest-1.0" })
818 .Property("ffa-version", "<0x10000>")
819 .Build();
820 /* clang-format on */
821
822 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
823 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
824}
825
Daniel Boulby801f8ef2022-06-27 14:21:01 +0100826TEST_F(manifest, ffa_validate_sanity_check)
Olivier Deprez62d99e32020-01-09 15:58:07 +0100827{
J-Alvesb37fd082020-10-22 12:29:21 +0100828 /*
829 * TODO: write test excluding all optional fields of the manifest, in
830 * accordance with specification.
831 */
Olivier Deprez93644652022-09-09 11:01:12 +0200832 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100833
834 /* Incompatible version */
835 /* clang-format off */
836 std::vector<char> dtb = ManifestDtBuilder()
837 .Compatible({ "arm,ffa-manifest-1.0" })
838 .Property("ffa-version", "<0xa1>")
839 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
840 .Property("execution-ctx-count", "<1>")
841 .Property("exception-level", "<2>")
842 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000843 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100844 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100845 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100846 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500847 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100848 .Build();
849 /* clang-format on */
850 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
851 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200852 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100853
854 /* Incompatible translation granule */
855 /* clang-format off */
856 dtb = ManifestDtBuilder()
857 .Compatible({ "arm,ffa-manifest-1.0" })
858 .Property("ffa-version", "<0x10000>")
859 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
860 .Property("execution-ctx-count", "<1>")
861 .Property("exception-level", "<2>")
862 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000863 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100864 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100865 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100866 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500867 .Property("ns-interrupts-action", "<1>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100868 .Build();
869 /* clang-format on */
870 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
871 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200872 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100873
874 /* Incompatible exeption level */
875 /* clang-format off */
876 dtb = ManifestDtBuilder()
877 .Compatible({ "arm,ffa-manifest-1.0" })
878 .Property("ffa-version", "<0x10000>")
879 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
880 .Property("execution-ctx-count", "<1>")
881 .Property("exception-level", "<6>")
882 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000883 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100884 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100885 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100886 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500887 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100888 .Build();
889 /* clang-format on */
890 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
891 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200892 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100893
894 /* Incompatible execution state */
895 /* clang-format off */
896 dtb = ManifestDtBuilder()
897 .Compatible({ "arm,ffa-manifest-1.0" })
898 .Property("ffa-version", "<0x10000>")
899 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
900 .Property("execution-ctx-count", "<1>")
901 .Property("exception-level", "<2>")
902 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000903 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100904 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100905 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100906 .Property("messaging-method", "<1>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500907 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100908 .Build();
909 /* clang-format on */
910 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
911 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +0200912 manifest_dealloc();
Olivier Deprez62d99e32020-01-09 15:58:07 +0100913
914 /* Incompatible messaging method */
915 /* clang-format off */
916 dtb = ManifestDtBuilder()
917 .Compatible({ "arm,ffa-manifest-1.0" })
918 .Property("ffa-version", "<0x10000>")
919 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
920 .Property("execution-ctx-count", "<1>")
921 .Property("exception-level", "<2>")
922 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000923 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100924 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100925 .Property("boot-order", "<0>")
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100926 .Property("messaging-method", "<16>")
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500927 .Property("ns-interrupts-action", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100928 .Build();
929 /* clang-format on */
930 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
931 MANIFEST_ERROR_NOT_COMPATIBLE);
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600932
933 /*
934 * No need to invoke manifest_dealloac() since manifest TearDown calls
935 * it when the test ends.
936 */
937}
938
939TEST_F(manifest, ffa_validate_interrupt_actions)
940{
941 struct_manifest *m;
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500942
943 /* Incompatible NS interrupt action */
944 /* clang-format off */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600945 std::vector<char> dtb = ManifestDtBuilder()
Madhukar Pappireddy84154052022-06-21 18:30:25 -0500946 .Compatible({ "arm,ffa-manifest-1.0" })
947 .Property("ffa-version", "<0x10000>")
948 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
949 .Property("execution-ctx-count", "<1>")
950 .Property("exception-level", "<2>")
951 .Property("execution-state", "<0>")
952 .Property("entrypoint-offset", "<0x00002000>")
953 .Property("xlat-granule", "<0>")
954 .Property("boot-order", "<0>")
955 .Property("messaging-method", "<1>")
956 .Property("ns-interrupts-action", "<4>")
957 .Build();
958 /* clang-format on */
Madhukar Pappireddy5c04a382022-12-28 11:29:26 -0600959 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
960 MANIFEST_ERROR_ILLEGAL_NS_INT_ACTION);
Madhukar Pappireddyee736ad2022-12-28 11:37:09 -0600961 manifest_dealloc();
962
963 /* Incompatible other-s-interrupts-action for S-EL1 partition */
964 /* clang-format off */
965 dtb = ManifestDtBuilder()
966 .Compatible({ "arm,ffa-manifest-1.0" })
967 .Property("ffa-version", "<0x10000>")
968 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
969 .Property("execution-ctx-count", "<1>")
970 .Property("exception-level", "<2>")
971 .Property("execution-state", "<0>")
972 .Property("entrypoint-offset", "<0x00002000>")
973 .Property("xlat-granule", "<0>")
974 .Property("boot-order", "<0>")
975 .Property("messaging-method", "<1>")
976 .Property("ns-interrupts-action", "<1>")
977 .Property("other-s-interrupts-action", "<0>")
978 .Build();
979 /* clang-format on */
980 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
981 MANIFEST_ERROR_NOT_COMPATIBLE);
982 manifest_dealloc();
983
984 /*
985 * Incompatible choice of the fields ns-interrupts-action and
986 * other-s-interrupts-action.
987 */
988 /* clang-format off */
989 dtb = ManifestDtBuilder()
990 .Compatible({ "arm,ffa-manifest-1.0" })
991 .Property("ffa-version", "<0x10000>")
992 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
993 .Property("execution-ctx-count", "<1>")
994 .Property("exception-level", "<1>")
995 .Property("execution-state", "<0>")
996 .Property("entrypoint-offset", "<0x00002000>")
997 .Property("xlat-granule", "<0>")
998 .Property("boot-order", "<0>")
999 .Property("messaging-method", "<1>")
1000 .Property("ns-interrupts-action", "<2>")
1001 .Property("other-s-interrupts-action", "<0>")
1002 .Build();
1003 /* clang-format on */
1004 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1005 MANIFEST_ERROR_NOT_COMPATIBLE);
1006 manifest_dealloc();
1007
1008 /* Illegal value specified for the field other-s-interrupts-action. */
1009 /* clang-format off */
1010 dtb = ManifestDtBuilder()
1011 .Compatible({ "arm,ffa-manifest-1.0" })
1012 .Property("ffa-version", "<0x10000>")
1013 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1014 .Property("execution-ctx-count", "<1>")
1015 .Property("exception-level", "<1>")
1016 .Property("execution-state", "<0>")
1017 .Property("entrypoint-offset", "<0x00002000>")
1018 .Property("xlat-granule", "<0>")
1019 .Property("boot-order", "<0>")
1020 .Property("messaging-method", "<1>")
1021 .Property("other-s-interrupts-action", "<2>")
1022 .Build();
1023 /* clang-format on */
1024 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1025 MANIFEST_ERROR_ILLEGAL_OTHER_S_INT_ACTION);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001026}
1027
Olivier Depreza15f2352022-09-26 09:17:24 +02001028TEST_F(manifest, power_management)
1029{
1030 struct manifest_vm *vm;
1031 struct_manifest *m;
1032
1033 /* S-EL1 partition power management field can set bit 0. */
1034 /* clang-format off */
1035 std::vector<char> dtb = ManifestDtBuilder()
1036 .Compatible({ "arm,ffa-manifest-1.0" })
1037 .Property("ffa-version", "<0x10001>")
1038 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1039 .Property("execution-ctx-count", "<8>")
1040 .Property("exception-level", "<2>")
1041 .Property("execution-state", "<0>")
1042 .Property("entrypoint-offset", "<0x00002000>")
1043 .Property("messaging-method", "<1>")
1044 .Property("power-management-messages", "<1>")
1045 .Build();
1046 /* clang-format on */
1047 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1048 vm = &m->vm[0];
1049 ASSERT_EQ(vm->partition.power_management, 1);
1050 manifest_dealloc();
1051
1052 /* S-EL1 partition power management field can set bit 3. */
1053 /* clang-format off */
1054 dtb = ManifestDtBuilder()
1055 .Compatible({ "arm,ffa-manifest-1.0" })
1056 .Property("ffa-version", "<0x10001>")
1057 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1058 .Property("execution-ctx-count", "<8>")
1059 .Property("exception-level", "<2>")
1060 .Property("execution-state", "<0>")
1061 .Property("entrypoint-offset", "<0x00002000>")
1062 .Property("messaging-method", "<1>")
1063 .Property("power-management-messages", "<8>")
1064 .Build();
1065 /* clang-format on */
1066 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1067 vm = &m->vm[0];
1068 ASSERT_EQ(vm->partition.power_management, 8);
1069 manifest_dealloc();
1070
1071 /* S-EL1 partition power management field can only set bits 0 and 3. */
1072 /* clang-format off */
1073 dtb = ManifestDtBuilder()
1074 .Compatible({ "arm,ffa-manifest-1.0" })
1075 .Property("ffa-version", "<0x10001>")
1076 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1077 .Property("execution-ctx-count", "<8>")
1078 .Property("exception-level", "<2>")
1079 .Property("execution-state", "<0>")
1080 .Property("entrypoint-offset", "<0x00002000>")
1081 .Property("messaging-method", "<1>")
1082 .Property("power-management-messages", "<0xf>")
1083 .Build();
1084 /* clang-format on */
1085 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1086 vm = &m->vm[0];
1087 ASSERT_EQ(vm->partition.power_management, 9);
1088 manifest_dealloc();
1089
1090 /* S-EL0 partition power management field is forced to 0. */
1091 /* clang-format off */
1092 dtb = ManifestDtBuilder()
1093 .Compatible({ "arm,ffa-manifest-1.0" })
1094 .Property("ffa-version", "<0x10001>")
1095 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1096 .Property("execution-ctx-count", "<1>")
1097 .Property("exception-level", "<1>")
1098 .Property("execution-state", "<0>")
1099 .Property("entrypoint-offset", "<0x00002000>")
1100 .Property("messaging-method", "<1>")
1101 .Property("power-management-messages", "<0xff>")
1102 .Build();
1103 /* clang-format on */
1104 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1105 vm = &m->vm[0];
1106 ASSERT_EQ(vm->partition.power_management, 0);
1107}
1108
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001109TEST_F(manifest, ffa_validate_rxtx_info)
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001110{
Olivier Deprez93644652022-09-09 11:01:12 +02001111 struct_manifest *m;
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001112
1113 /* Not Compatible */
1114 /* clang-format off */
1115 std::vector<char> dtb = ManifestDtBuilder()
1116 .FfaValidManifest()
1117 .StartChild("rx_tx-info")
1118 .Compatible({ "foo,bar" })
1119 .EndChild()
1120 .Build();
1121 /* clang-format on */
1122 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1123 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001124 manifest_dealloc();
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001125
1126 /* Missing Properties */
1127 /* clang-format off */
1128 dtb = ManifestDtBuilder()
1129 .FfaValidManifest()
1130 .StartChild("rx_tx-info")
1131 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1132 .EndChild()
1133 .Build();
1134 /* clang-format on */
1135 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1136 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
1137}
1138
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001139TEST_F(manifest, ffa_validate_mem_regions)
Manish Pandey6542f5c2020-04-27 14:37:46 +01001140{
Olivier Deprez93644652022-09-09 11:01:12 +02001141 struct_manifest *m;
Manish Pandey6542f5c2020-04-27 14:37:46 +01001142
1143 /* Not Compatible */
1144 /* clang-format off */
1145 std::vector<char> dtb = ManifestDtBuilder()
1146 .FfaValidManifest()
1147 .StartChild("memory-regions")
1148 .Compatible({ "foo,bar" })
1149 .EndChild()
1150 .Build();
1151 /* clang-format on */
1152 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1153 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001154 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001155
1156 /* Memory regions unavailable */
1157 /* clang-format off */
1158 dtb = ManifestDtBuilder()
1159 .FfaValidManifest()
1160 .StartChild("memory-regions")
1161 .Compatible({ "arm,ffa-manifest-memory-regions" })
1162 .EndChild()
1163 .Build();
1164 /* clang-format on */
1165 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1166 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001167 manifest_dealloc();
Manish Pandey6542f5c2020-04-27 14:37:46 +01001168
1169 /* Missing Properties */
1170 /* clang-format off */
1171 dtb = ManifestDtBuilder()
1172 .FfaValidManifest()
1173 .StartChild("memory-regions")
1174 .Compatible({ "arm,ffa-manifest-memory-regions" })
1175 .StartChild("test-memory")
1176 .Description("test-memory")
1177 .EndChild()
1178 .EndChild()
1179 .Build();
1180 /* clang-format on */
1181 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1182 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001183 manifest_dealloc();
Manish Pandeyf06c9072020-09-29 15:41:58 +01001184
Varun Wadekar4afbfd72022-10-13 14:30:18 +01001185 /* Empty memory region */
1186 /* clang-format off */
1187 dtb = ManifestDtBuilder()
1188 .FfaValidManifest()
1189 .StartChild("memory-regions")
1190 .Compatible({ "arm,ffa-manifest-memory-regions" })
1191 .Label("rx")
1192 .StartChild("rx")
1193 .Description("rx-buffer")
1194 .Property("base-address", "<0x7300000>")
1195 .Property("pages-count", "<0>")
1196 .Property("attributes", "<1>")
1197 .EndChild()
1198 .Label("tx")
1199 .StartChild("tx")
1200 .Description("tx-buffer")
1201 .Property("base-address", "<0x7310000>")
1202 .Property("pages-count", "<2>")
1203 .Property("attributes", "<3>")
1204 .EndChild()
1205 .EndChild()
1206 .StartChild("rx_tx-info")
1207 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1208 .Property("rx-buffer", "<&rx>")
1209 .Property("tx-buffer", "<&tx>")
1210 .EndChild()
1211 .Build();
1212 /* clang-format on */
1213 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1214 MANIFEST_ERROR_MEM_REGION_EMPTY);
1215 manifest_dealloc();
1216
Karl Meakine92efbe2023-06-01 14:16:22 +01001217 /* Mutually exclusive base-address and relative-address properties */
1218 /* clang-format off */
1219 dtb = ManifestDtBuilder()
1220 .FfaValidManifest()
1221 .StartChild("memory-regions")
1222 .Compatible({ "arm,ffa-manifest-memory-regions" })
1223 .Label("rx")
1224 .StartChild("rx")
1225 .Description("rx-buffer")
1226 .Property("base-address", "<0x7300000>")
1227 .Property("relative-address", "<0x7300000>")
1228 .Property("pages-count", "<1>")
1229 .Property("attributes", "<1>")
1230 .EndChild()
1231 .EndChild()
1232 .Build();
1233 /* clang-format on */
1234 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1235 MANIFEST_ERROR_BASE_ADDRESS_AND_RELATIVE_ADDRESS);
1236 manifest_dealloc();
1237 /* Relative-address overflow*/
1238 /* clang-format off */
1239 dtb = ManifestDtBuilder()
1240 .FfaValidManifest()
1241 .Property("load-address", "<0xffffff00 0xffffff00>")
1242 .StartChild("memory-regions")
1243 .Compatible({ "arm,ffa-manifest-memory-regions" })
1244 .Label("rx")
1245 .StartChild("rx")
1246 .Description("rx-buffer")
1247 .Property("relative-address", "<0xffffff00 0xffffff00>")
1248 .Property("pages-count", "<1>")
1249 .Property("attributes", "<1>")
1250 .EndChild()
1251 .EndChild()
1252 .Build();
1253 /* clang-format on */
1254 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1255 MANIFEST_ERROR_INTEGER_OVERFLOW);
1256 manifest_dealloc();
1257
Daniel Boulby9279b552022-06-28 17:04:01 +01001258 /* Overlapping memory regions */
1259 /* clang-format off */
1260 dtb = ManifestDtBuilder()
1261 .FfaValidManifest()
1262 .StartChild("memory-regions")
1263 .Compatible({ "arm,ffa-manifest-memory-regions" })
1264 .Label("rx")
1265 .StartChild("rx")
1266 .Description("rx-buffer")
1267 .Property("base-address", "<0x7300000>")
1268 .Property("pages-count", "<1>")
1269 .Property("attributes", "<1>")
1270 .EndChild()
1271 .Label("tx")
1272 .StartChild("tx")
1273 .Description("tx-buffer")
1274 .Property("base-address", "<0x7300000>")
1275 .Property("pages-count", "<2>")
1276 .Property("attributes", "<3>")
1277 .EndChild()
1278 .EndChild()
1279 .Build();
1280 /* clang-format on */
1281 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1282 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001283 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001284
1285 /* clang-format off */
1286 dtb = ManifestDtBuilder()
1287 .FfaValidManifest()
1288 .StartChild("memory-regions")
1289 .Compatible({ "arm,ffa-manifest-memory-regions" })
1290 .Label("rx")
1291 .StartChild("rx")
1292 .Description("rx-buffer")
1293 .Property("base-address", "<0x7300000>")
1294 .Property("pages-count", "<2>")
1295 .Property("attributes", "<1>")
1296 .EndChild()
1297 .Label("tx")
1298 .StartChild("tx")
1299 .Description("tx-buffer")
1300 .Property("base-address", "<0x7301000>")
1301 .Property("pages-count", "<2>")
1302 .Property("attributes", "<3>")
1303 .EndChild()
1304 .EndChild()
1305 .Build();
1306 /* clang-format on */
1307 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1308 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Olivier Deprez93644652022-09-09 11:01:12 +02001309 manifest_dealloc();
Daniel Boulby9279b552022-06-28 17:04:01 +01001310
1311 /* clang-format off */
1312 dtb = ManifestDtBuilder()
1313 .FfaValidManifest()
1314 .StartChild("memory-regions")
1315 .Compatible({ "arm,ffa-manifest-memory-regions" })
1316 .Label("rx")
1317 .StartChild("rx")
1318 .Description("rx-buffer")
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001319 .Property("base-address", "<0x7301000>")
1320 .Property("pages-count", "<1>")
1321 .Property("attributes", "<1>")
1322 .EndChild()
1323 .Label("tx")
1324 .StartChild("tx")
1325 .Description("tx-buffer")
1326 .Property("base-address", "<0x7300000>")
1327 .Property("pages-count", "<2>")
1328 .Property("attributes", "<3>")
1329 .EndChild()
1330 .EndChild()
1331 .Build();
1332 /* clang-format on */
1333 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1334 MANIFEST_ERROR_MEM_REGION_OVERLAP);
Daniel Boulbyc1a613d2022-10-18 11:26:17 +01001335 manifest_dealloc();
1336
1337 /* Unaligned memory region */
1338 /* clang-format off */
1339 dtb = ManifestDtBuilder()
1340 .FfaValidManifest()
1341 .StartChild("memory-regions")
1342 .Compatible({ "arm,ffa-manifest-memory-regions" })
1343 .Label("rx")
1344 .StartChild("rx")
1345 .Description("rx-buffer")
1346 .Property("base-address", "<0x7300FFF>")
1347 .Property("pages-count", "<2>")
1348 .Property("attributes", "<1>")
1349 .EndChild()
1350 .Label("tx")
1351 .StartChild("tx")
1352 .Description("tx-buffer")
1353 .Property("base-address", "<0x7303000>")
1354 .Property("pages-count", "<2>")
1355 .Property("attributes", "<3>")
1356 .EndChild()
1357 .EndChild()
1358 .Build();
1359 /* clang-format on */
1360 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1361 MANIFEST_ERROR_MEM_REGION_UNALIGNED);
1362 manifest_dealloc();
Varun Wadekarae9aeaa2022-10-13 14:23:58 +01001363
Manish Pandeyf06c9072020-09-29 15:41:58 +01001364 /* Different RXTX buffer sizes */
1365 /* clang-format off */
1366 dtb = ManifestDtBuilder()
1367 .FfaValidManifest()
1368 .StartChild("memory-regions")
1369 .Compatible({ "arm,ffa-manifest-memory-regions" })
1370 .Label("rx")
1371 .StartChild("rx")
1372 .Description("rx-buffer")
1373 .Property("base-address", "<0x7300000>")
1374 .Property("pages-count", "<1>")
1375 .Property("attributes", "<1>")
1376 .EndChild()
1377 .Label("tx")
1378 .StartChild("tx")
1379 .Description("tx-buffer")
1380 .Property("base-address", "<0x7310000>")
1381 .Property("pages-count", "<2>")
1382 .Property("attributes", "<3>")
1383 .EndChild()
1384 .EndChild()
1385 .StartChild("rx_tx-info")
1386 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1387 .Property("rx-buffer", "<&rx>")
1388 .Property("tx-buffer", "<&tx>")
1389 .EndChild()
1390 .Build();
1391 /* clang-format on */
1392 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1393 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001394}
1395
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001396TEST_F(manifest, ffa_validate_dev_regions)
Manish Pandeye68e7932020-04-23 15:29:28 +01001397{
Olivier Deprez93644652022-09-09 11:01:12 +02001398 struct_manifest *m;
Manish Pandeye68e7932020-04-23 15:29:28 +01001399
1400 /* Not Compatible */
1401 /* clang-format off */
1402 std::vector<char> dtb = ManifestDtBuilder()
1403 .FfaValidManifest()
1404 .StartChild("device-regions")
1405 .Compatible({ "foo,bar" })
1406 .EndChild()
1407 .Build();
1408 /* clang-format on */
1409 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1410 MANIFEST_ERROR_NOT_COMPATIBLE);
Olivier Deprez93644652022-09-09 11:01:12 +02001411 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001412
1413 /* Memory regions unavailable */
1414 /* clang-format off */
1415 dtb = ManifestDtBuilder()
1416 .FfaValidManifest()
1417 .StartChild("device-regions")
1418 .Compatible({ "arm,ffa-manifest-device-regions" })
1419 .EndChild()
1420 .Build();
1421 /* clang-format on */
1422 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1423 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
Olivier Deprez93644652022-09-09 11:01:12 +02001424 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001425
1426 /* Missing Properties */
1427 /* clang-format off */
1428 dtb = ManifestDtBuilder()
1429 .FfaValidManifest()
1430 .StartChild("device-regions")
1431 .Compatible({ "arm,ffa-manifest-device-regions" })
1432 .StartChild("test-device")
1433 .Description("test-device")
1434 .EndChild()
1435 .EndChild()
1436 .Build();
1437 /* clang-format on */
1438 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1439 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Olivier Deprez93644652022-09-09 11:01:12 +02001440 manifest_dealloc();
Manish Pandeye68e7932020-04-23 15:29:28 +01001441
1442 /* Malformed interrupt list pair */
1443 /* clang-format off */
1444 dtb = ManifestDtBuilder()
1445 .FfaValidManifest()
1446 .StartChild("device-regions")
1447 .Compatible({ "arm,ffa-manifest-device-regions" })
1448 .StartChild("test-device")
1449 .Description("test-device")
1450 .Property("base-address", "<0x7200000>")
1451 .Property("pages-count", "<16>")
1452 .Property("attributes", "<3>")
1453 .Property("smmu-id", "<1>")
1454 .Property("stream-ids", "<0 1>")
1455 .Property("interrupts", "<2 3>, <4>")
1456 .EndChild()
1457 .EndChild()
1458 .Build();
1459 /* clang-format on */
1460 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1461 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
Olivier Deprez93644652022-09-09 11:01:12 +02001462 manifest_dealloc();
Daniel Boulby667334f2022-06-27 15:23:21 +01001463
1464 /* Non-unique interrupt IDs */
1465 /* clang-format off */
1466 dtb = ManifestDtBuilder()
1467 .FfaValidManifest()
1468 .StartChild("device-regions")
1469 .Compatible({ "arm,ffa-manifest-device-regions" })
1470 .StartChild("test-device-0")
1471 .Description("test-device-0")
1472 .Property("base-address", "<0x7200000>")
1473 .Property("pages-count", "<16>")
1474 .Property("attributes", "<3>")
1475 .Property("interrupts", "<2 3>")
1476 .EndChild()
1477 .StartChild("test-device-1")
1478 .Description("test-device-1")
1479 .Property("base-address", "<0x8200000>")
1480 .Property("pages-count", "<16>")
1481 .Property("attributes", "<3>")
1482 .Property("interrupts", "<1 3>, <2 5> ")
1483 .EndChild()
1484 .EndChild()
1485 .Build();
1486 /* clang-format on */
1487 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1488 MANIFEST_ERROR_INTERRUPT_ID_REPEATED);
1489 /* Check valid interrupts were still mapped */
Olivier Deprez93644652022-09-09 11:01:12 +02001490 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1491 ASSERT_EQ(m->vm[0].partition.dev_regions[0].interrupts[0].attributes,
1492 3);
1493 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].id, 1);
1494 ASSERT_EQ(m->vm[0].partition.dev_regions[1].interrupts[0].attributes,
1495 3);
Manish Pandeye68e7932020-04-23 15:29:28 +01001496}
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001497
1498TEST_F(manifest, ffa_invalid_memory_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001499{
Olivier Deprez93644652022-09-09 11:01:12 +02001500 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001501
1502 /* clang-format off */
1503 std::vector<char> dtb = ManifestDtBuilder()
1504 .FfaValidManifest()
1505 .StartChild("rx_tx-info")
1506 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1507 .Property("rx-buffer", "<&rx>")
1508 .Property("tx-buffer", "<&tx>")
1509 .EndChild()
1510 .StartChild("memory-regions")
1511 .Compatible({ "arm,ffa-manifest-memory-regions" })
1512 .StartChild("test-memory")
1513 .Description("test-memory")
1514 .Property("base-address", "<0x7100000>")
1515 .Property("pages-count", "<4>")
1516 .Property("attributes", "<7>")
1517 .EndChild()
1518 .Label("rx")
1519 .StartChild("rx")
1520 .Description("rx-buffer")
1521 .Property("base-address", "<0x7300000>")
1522 .Property("pages-count", "<1>")
1523 .Property("attributes", "<1>")
1524 .EndChild()
1525 .Label("tx")
1526 .StartChild("tx")
1527 .Description("tx-buffer")
1528 .Property("base-address", "<0x7310000>")
1529 .Property("pages-count", "<1>")
1530 .Property("attributes", "<3>")
1531 .EndChild()
1532 .EndChild()
1533 .Build();
1534 /* clang-format on */
1535
1536 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1537 MANIFEST_ERROR_INVALID_MEM_PERM);
1538}
1539
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001540TEST_F(manifest, ffa_invalid_device_region_attributes)
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001541{
Olivier Deprez93644652022-09-09 11:01:12 +02001542 struct_manifest *m;
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001543
1544 /* clang-format off */
1545 std::vector<char> dtb = ManifestDtBuilder()
1546 .FfaValidManifest()
1547 .StartChild("rx_tx-info")
1548 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1549 .Property("rx-buffer", "<&rx>")
1550 .Property("tx-buffer", "<&tx>")
1551 .EndChild()
1552 .StartChild("memory-regions")
1553 .Compatible({ "arm,ffa-manifest-memory-regions" })
1554 .StartChild("test-memory")
1555 .Description("test-memory")
1556 .Property("base-address", "<0x7100000>")
1557 .Property("pages-count", "<4>")
1558 .Property("attributes", "<3>")
1559 .EndChild()
1560 .Label("rx")
1561 .StartChild("rx")
1562 .Description("rx-buffer")
1563 .Property("base-address", "<0x7300000>")
1564 .Property("pages-count", "<1>")
1565 .Property("attributes", "<1>")
1566 .EndChild()
1567 .Label("tx")
1568 .StartChild("tx")
1569 .Description("tx-buffer")
1570 .Property("base-address", "<0x7310000>")
1571 .Property("pages-count", "<1>")
1572 .Property("attributes", "<3>")
1573 .EndChild()
1574 .EndChild()
1575 .StartChild("device-regions")
1576 .Compatible({ "arm,ffa-manifest-device-regions" })
1577 .StartChild("test-device")
1578 .Description("test-device")
1579 .Property("base-address", "<0x7200000>")
1580 .Property("pages-count", "<16>")
1581 .Property("attributes", "<5>")
1582 .Property("smmu-id", "<1>")
1583 .Property("stream-ids", "<0 1>")
1584 .Property("interrupts", "<2 3>, <4 5>")
1585 .EndChild()
1586 .EndChild()
1587 .Build();
1588 /* clang-format on */
1589
1590 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1591 MANIFEST_ERROR_INVALID_MEM_PERM);
1592}
Manish Pandeye68e7932020-04-23 15:29:28 +01001593
Daniel Boulby801f8ef2022-06-27 14:21:01 +01001594TEST_F(manifest, ffa_valid)
Olivier Deprez62d99e32020-01-09 15:58:07 +01001595{
Olivier Deprez93644652022-09-09 11:01:12 +02001596 struct manifest_vm *vm;
1597 struct_manifest *m;
Olivier Deprez62d99e32020-01-09 15:58:07 +01001598
1599 /* clang-format off */
1600 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001601 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001602 .StartChild("rx_tx-info")
1603 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1604 .Property("rx-buffer", "<&rx>")
1605 .Property("tx-buffer", "<&tx>")
1606 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001607 .StartChild("memory-regions")
1608 .Compatible({ "arm,ffa-manifest-memory-regions" })
1609 .StartChild("test-memory")
1610 .Description("test-memory")
Karl Meakine92efbe2023-06-01 14:16:22 +01001611 .Property("relative-address", "<0x7100000>")
Manish Pandey6542f5c2020-04-27 14:37:46 +01001612 .Property("pages-count", "<4>")
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001613 .Property("attributes", "<3>")
Manish Pandey6542f5c2020-04-27 14:37:46 +01001614 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001615 .StartChild("test-memory-ns")
1616 .Description("test-memory")
1617 .Property("base-address", "<0x7200000>")
1618 .Property("pages-count", "<1>")
1619 .Property("attributes", "<0xb>")
1620 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001621 .Label("rx")
1622 .StartChild("rx")
1623 .Description("rx-buffer")
1624 .Property("base-address", "<0x7300000>")
1625 .Property("pages-count", "<1>")
1626 .Property("attributes", "<1>")
1627 .EndChild()
1628 .Label("tx")
1629 .StartChild("tx")
1630 .Description("tx-buffer")
Daniel Boulby9279b552022-06-28 17:04:01 +01001631 .Property("base-address", "<0x7301000>")
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001632 .Property("pages-count", "<1>")
1633 .Property("attributes", "<3>")
1634 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001635 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001636 .StartChild("device-regions")
1637 .Compatible({ "arm,ffa-manifest-device-regions" })
1638 .StartChild("test-device")
1639 .Description("test-device")
Olivier Deprez035fa152022-03-14 11:19:10 +01001640 .Property("base-address", "<0x7400000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001641 .Property("pages-count", "<16>")
1642 .Property("attributes", "<3>")
1643 .Property("smmu-id", "<1>")
1644 .Property("stream-ids", "<0 1>")
1645 .Property("interrupts", "<2 3>, <4 5>")
1646 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001647 .StartChild("test-device-ns")
1648 .Description("test-device")
1649 .Property("base-address", "<0x7500000>")
1650 .Property("pages-count", "<1>")
1651 .Property("attributes", "<0x9>")
1652 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001653 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001654 .Build();
1655 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +01001656 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1657
Olivier Deprez93644652022-09-09 11:01:12 +02001658 vm = &m->vm[0];
1659 ASSERT_EQ(vm->partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001660 ASSERT_THAT(
Olivier Deprez93644652022-09-09 11:01:12 +02001661 std::span(vm->partition.uuid.uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001662 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Olivier Deprez93644652022-09-09 11:01:12 +02001663 ASSERT_EQ(vm->partition.execution_ctx_count, 1);
1664 ASSERT_EQ(vm->partition.run_time_el, S_EL1);
1665 ASSERT_EQ(vm->partition.execution_state, AARCH64);
1666 ASSERT_EQ(vm->partition.ep_offset, 0x00002000);
1667 ASSERT_EQ(vm->partition.xlat_granule, PAGE_4KB);
1668 ASSERT_EQ(vm->partition.boot_order, 0);
1669 ASSERT_EQ(vm->partition.messaging_method, FFA_PARTITION_INDIRECT_MSG);
1670 ASSERT_EQ(vm->partition.ns_interrupts_action, NS_ACTION_ME);
1671 ASSERT_EQ(vm->partition.mem_regions[0].base_address, 0x7100000);
1672 ASSERT_EQ(vm->partition.mem_regions[0].page_count, 4);
1673 ASSERT_EQ(vm->partition.mem_regions[0].attributes, 3);
1674 ASSERT_EQ(vm->partition.mem_regions[1].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001675
Olivier Deprez93644652022-09-09 11:01:12 +02001676 ASSERT_EQ(vm->partition.rxtx.available, true);
1677 ASSERT_EQ(vm->partition.rxtx.rx_buffer->base_address, 0x7300000);
1678 ASSERT_EQ(vm->partition.rxtx.rx_buffer->page_count, 1);
1679 ASSERT_EQ(vm->partition.rxtx.rx_buffer->attributes, 1);
1680 ASSERT_EQ(vm->partition.rxtx.tx_buffer->base_address, 0x7301000);
1681 ASSERT_EQ(vm->partition.rxtx.tx_buffer->page_count, 1);
1682 ASSERT_EQ(vm->partition.rxtx.tx_buffer->attributes, 3);
1683
1684 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x7400000);
1685 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
1686 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
1687 ASSERT_EQ(vm->partition.dev_regions[0].smmu_id, 1);
1688 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[0], 0);
1689 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[1], 1);
1690 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1691 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1692 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1693 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
1694 ASSERT_EQ(vm->partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01001695}
1696
Raghu Krishnamurthy98da1ca2022-10-04 08:59:01 -07001697TEST_F(manifest, ffa_valid_interrupt_target_manifest)
1698{
1699 struct manifest_vm *vm;
1700 struct_manifest *m;
1701
1702 /* clang-format off */
1703 std::vector<char> dtb = ManifestDtBuilder()
1704 .FfaValidManifest()
1705 .StartChild("device-regions")
1706 .Compatible({ "arm,ffa-manifest-device-regions" })
1707 .StartChild("test-device")
1708 .Description("test-device")
1709 .Property("base-address", "<0x7400000>")
1710 .Property("pages-count", "<16>")
1711 .Property("attributes", "<3>")
1712 .Property("smmu-id", "<1>")
1713 .Property("stream-ids", "<0 1>")
1714 .Property("interrupts", "<2 3>, <4 5>")
1715 .Property("interrupts-target", "<2 0x1234 0x5678>, <4 0x12345678 0x87654321>")
1716 .EndChild()
1717 .EndChild()
1718 .Build();
1719 /* clang-format on */
1720
1721 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1722
1723 vm = &m->vm[0];
1724
1725 ASSERT_EQ(vm->partition.dev_regions[0].base_address, 0x7400000);
1726 ASSERT_EQ(vm->partition.dev_regions[0].page_count, 16);
1727 ASSERT_EQ(vm->partition.dev_regions[0].attributes, 3);
1728 ASSERT_EQ(vm->partition.dev_regions[0].smmu_id, 1);
1729 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[0], 0);
1730 ASSERT_EQ(vm->partition.dev_regions[0].stream_ids[1], 1);
1731 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].id, 2);
1732 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].attributes, 3);
1733 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr_valid, true);
1734 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[0].mpidr,
1735 0x123400005678);
1736 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].id, 4);
1737 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].attributes, 5);
1738 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr_valid, true);
1739 ASSERT_EQ(vm->partition.dev_regions[0].interrupts[1].mpidr,
1740 0x1234567887654321);
1741}
1742
1743TEST_F(manifest, ffa_invalid_interrupt_target_manifest)
1744{
1745 struct_manifest *m;
1746
1747 /* clang-format off */
1748 std::vector<char> dtb = ManifestDtBuilder()
1749 .FfaValidManifest()
1750 .StartChild("device-regions")
1751 .Compatible({ "arm,ffa-manifest-device-regions" })
1752 .StartChild("test-device")
1753 .Description("test-device")
1754 .Property("base-address", "<0x7400000>")
1755 .Property("pages-count", "<16>")
1756 .Property("attributes", "<3>")
1757 .Property("smmu-id", "<1>")
1758 .Property("stream-ids", "<0 1>")
1759 .Property("interrupts", "<2 3>, <4 5>")
1760 .Property("interrupts-target", "<20 0x1234 0x5678>")
1761 .EndChild()
1762 .EndChild()
1763 .Build();
1764 /* clang-format on */
1765
1766 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1767 MANIFEST_ERROR_INTERRUPT_ID_NOT_IN_LIST);
1768}
1769
Kathleen Capella4a2a6e72023-04-21 14:43:26 -04001770TEST_F(manifest, ffa_boot_order_not_unique)
1771{
1772 struct_manifest *m;
1773 struct memiter it;
1774 struct mm_stage1_locked mm_stage1_locked;
1775 struct boot_params params;
1776 Partition_package spkg_1;
1777 Partition_package spkg_2;
1778
1779 /* clang-format off */
1780 std::vector<char> dtb1 = ManifestDtBuilder()
1781 .Compatible({ "arm,ffa-manifest-1.0" })
1782 .Property("ffa-version", "<0x10001>")
1783 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
1784 .FfaLoadAddress((uint64_t)&spkg_1)
1785 .Property("execution-ctx-count", "<1>")
1786 .Property("exception-level", "<1>")
1787 .Property("execution-state", "<0>")
1788 .Property("entrypoint-offset", "<0x00002000>")
1789 .Property("xlat-granule", "<0>")
1790 .Property("boot-order", "<1>")
1791 .Property("messaging-method", "<1>")
1792 .Property("ns-interrupts-action", "<0>")
1793 .Build();
1794
1795 std::vector<char> dtb2 = ManifestDtBuilder()
1796 .Compatible({ "arm,ffa-manifest-1.0" })
1797 .Property("ffa-version", "<0x10001>")
1798 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1daaa>")
1799 .FfaLoadAddress((uint64_t)&spkg_2)
1800 .Property("execution-ctx-count", "<1>")
1801 .Property("exception-level", "<1>")
1802 .Property("execution-state", "<0>")
1803 .Property("entrypoint-offset", "<0x00002000>")
1804 .Property("xlat-granule", "<0>")
1805 .Property("boot-order", "<1>")
1806 .Property("messaging-method", "<1>")
1807 .Property("ns-interrupts-action", "<0>")
1808 .Build();
1809
1810 /* clang-format on */
1811 spkg_1.init(dtb1);
1812 spkg_2.init(dtb2);
1813
1814 /* clang-format off */
1815 std::vector<char> core_dtb = ManifestDtBuilder()
1816 .StartChild("hypervisor")
1817 .Compatible()
1818 .StartChild("vm1")
1819 .DebugName("ffa_partition_1")
1820 .FfaPartition()
1821 .LoadAddress((uint64_t)&spkg_1)
1822 .VcpuCount(1)
1823 .MemSize(0x10000000)
1824 .EndChild()
1825 .StartChild("vm2")
1826 .DebugName("ffa_partition_2")
1827 .FfaPartition()
1828 .LoadAddress((uint64_t)&spkg_2)
1829 .VcpuCount(1)
1830 .MemSize(0x10000000)
1831 .EndChild()
1832 .EndChild()
1833 .Build();
1834 /* clang-format on */
1835
1836 boot_params_init(&params, nullptr);
1837 memiter_init(&it, core_dtb.data(), core_dtb.size());
1838 ASSERT_EQ(manifest_init(mm_stage1_locked, &m, &it, &params, &ppool),
1839 MANIFEST_ERROR_INVALID_BOOT_ORDER);
1840}
David Brazdil7a462ec2019-08-15 12:27:47 +01001841} /* namespace */