blob: beaf88346560f0c4cc1ba692201d8c49c48730fb [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
David Brazdil52256ff2019-08-23 15:15:15 +010030template <typename T>
David Brazdil0dbb41f2019-09-09 18:03:35 +010031void exec(const char *program, const char *args[], const T &stdin,
David Brazdil52256ff2019-08-23 15:15:15 +010032 std::vector<char> *stdout)
33{
34 /* Create two pipes, one for stdin and one for stdout. */
35 int pipes[2][2];
36 pipe(pipes[0]);
37 pipe(pipes[1]);
David Brazdil7a462ec2019-08-15 12:27:47 +010038
David Brazdil52256ff2019-08-23 15:15:15 +010039 /* Assign FDs for reading/writing by the parent/child. */
40 int parent_read_fd = pipes[1][0]; /* stdout pipe, read FD */
41 int parent_write_fd = pipes[0][1]; /* stdin pipe, write FD */
42 int child_read_fd = pipes[0][0]; /* stdin pipe, read FD */
43 int child_write_fd = pipes[1][1]; /* stdout pipe, write FD */
David Brazdil7a462ec2019-08-15 12:27:47 +010044
David Brazdil52256ff2019-08-23 15:15:15 +010045 if (fork()) {
46 /* Parent process. */
47 std::array<char, 128> buf;
48 ssize_t res;
49
50 /* Close child FDs which won't be used. */
51 close(child_read_fd);
52 close(child_write_fd);
53
54 /* Write to stdin. */
55 for (size_t count = 0; count < stdin.size();) {
56 res = write(parent_write_fd, stdin.data() + count,
57 stdin.size() - count);
58 if (res < 0) {
59 std::cerr << "IO error" << std::endl;
60 exit(1);
61 }
62 count += res;
63 }
64 close(parent_write_fd);
65
66 /* Read from stdout. */
67 while (true) {
68 res = read(parent_read_fd, buf.data(), buf.size());
69 if (res == 0) {
70 /* EOF */
71 break;
72 } else if (res < 0) {
73 std::cerr << "IO error" << std::endl;
74 exit(1);
75 }
76 stdout->insert(stdout->end(), buf.begin(),
77 buf.begin() + res);
78 }
79 close(parent_read_fd);
80 } else {
81 /* Child process. */
82
83 /* Redirect stdin/stdout to read/write FDs. */
84 dup2(child_read_fd, STDIN_FILENO);
85 dup2(child_write_fd, STDOUT_FILENO);
86
87 /* Close all FDs which are now unused. */
88 close(child_read_fd);
89 close(child_write_fd);
90 close(parent_read_fd);
91 close(parent_write_fd);
92
93 /* Execute the given program. */
David Brazdil0dbb41f2019-09-09 18:03:35 +010094 execv(program, const_cast<char *const *>(args));
David Brazdil52256ff2019-08-23 15:15:15 +010095 }
96}
97
98/**
99 * Class for programatically building a Device Tree.
100 *
101 * Usage:
102 * std::vector<char> dtb = ManifestDtBuilder()
103 * .Command1()
104 * .Command2()
105 * ...
106 * .CommandN()
107 * .Build();
108 */
109class ManifestDtBuilder
110{
111 public:
112 ManifestDtBuilder()
113 {
114 dts_ << "/dts-v1/;" << std::endl;
115 dts_ << std::endl;
116
117 /* Start root node. */
118 StartChild("/");
119 }
120
Andrew Scullae9962e2019-10-03 16:51:16 +0100121 std::vector<char> Build(bool dump = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100122 {
David Brazdil0dbb41f2019-09-09 18:03:35 +0100123 const char *program = "./build/image/dtc.py";
124 const char *dtc_args[] = {program, "compile", NULL};
David Brazdil52256ff2019-08-23 15:15:15 +0100125 std::vector<char> dtc_stdout;
126
127 /* Finish root node. */
128 EndChild();
129
Andrew Scullae9962e2019-10-03 16:51:16 +0100130 if (dump) {
131 Dump();
132 }
133
David Brazdil0dbb41f2019-09-09 18:03:35 +0100134 exec(program, dtc_args, dts_.str(), &dtc_stdout);
David Brazdil52256ff2019-08-23 15:15:15 +0100135 return dtc_stdout;
136 }
137
Andrew Scullae9962e2019-10-03 16:51:16 +0100138 void Dump()
139 {
140 std::cerr << dts_.str() << std::endl;
141 }
142
David Brazdil52256ff2019-08-23 15:15:15 +0100143 ManifestDtBuilder &StartChild(const std::string_view &name)
144 {
145 dts_ << name << " {" << std::endl;
146 return *this;
147 }
148
149 ManifestDtBuilder &EndChild()
150 {
151 dts_ << "};" << std::endl;
152 return *this;
153 }
154
David Brazdil74e9c3b2019-08-28 11:09:08 +0100155 ManifestDtBuilder &Compatible(const std::vector<std::string_view>
156 &value = {"hafnium,hafnium"})
157 {
158 return StringListProperty("compatible", value);
159 }
160
David Brazdil52256ff2019-08-23 15:15:15 +0100161 ManifestDtBuilder &DebugName(const std::string_view &value)
162 {
163 return StringProperty("debug_name", value);
164 }
165
Manish Pandey6542f5c2020-04-27 14:37:46 +0100166 ManifestDtBuilder &Description(const std::string_view &value)
167 {
168 return StringProperty("description", value);
169 }
170
David Brazdil52256ff2019-08-23 15:15:15 +0100171 ManifestDtBuilder &KernelFilename(const std::string_view &value)
172 {
173 return StringProperty("kernel_filename", value);
174 }
175
David Brazdile6f83222019-09-23 14:47:37 +0100176 ManifestDtBuilder &RamdiskFilename(const std::string_view &value)
177 {
178 return StringProperty("ramdisk_filename", value);
179 }
180
David Brazdil080ee312020-02-25 15:30:30 -0800181 ManifestDtBuilder &BootAddress(uint64_t value)
182 {
183 return Integer64Property("boot_address", value);
184 }
185
Andrew Scullae9962e2019-10-03 16:51:16 +0100186 ManifestDtBuilder &VcpuCount(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100187 {
188 return IntegerProperty("vcpu_count", value);
189 }
190
Andrew Scullae9962e2019-10-03 16:51:16 +0100191 ManifestDtBuilder &MemSize(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100192 {
193 return IntegerProperty("mem_size", value);
194 }
195
Andrew Scullae9962e2019-10-03 16:51:16 +0100196 ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
197 {
198 return IntegerListProperty("smc_whitelist", value);
199 }
200
201 ManifestDtBuilder &SmcWhitelistPermissive()
202 {
203 return BooleanProperty("smc_whitelist_permissive");
204 }
205
Olivier Deprez62d99e32020-01-09 15:58:07 +0100206 ManifestDtBuilder &LoadAddress(uint64_t value)
207 {
208 return Integer64Property("load_address", value);
209 }
210
211 ManifestDtBuilder &FfaPartition()
212 {
213 return BooleanProperty("is_ffa_partition");
214 }
215
Andrew Scullae9962e2019-10-03 16:51:16 +0100216 ManifestDtBuilder &Property(const std::string_view &name,
217 const std::string_view &value)
218 {
219 dts_ << name << " = " << value << ";" << std::endl;
220 return *this;
221 }
222
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100223 ManifestDtBuilder &Label(const std::string_view &name)
224 {
225 dts_ << name << ": ";
226 return *this;
227 }
228
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100229 ManifestDtBuilder &FfaValidManifest()
230 {
231 Compatible({"arm,ffa-manifest-1.0"});
232 Property("ffa-version", "<0x10000>");
233 Property("uuid",
234 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>");
235 Property("execution-ctx-count", "<1>");
236 Property("exception-level", "<2>");
237 Property("execution-state", "<0>");
J-Alves2f86c1e2022-02-23 18:44:19 +0000238 Property("entrypoint-offset", "<0x00002000>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100239 Property("xlat-granule", "<0>");
J-Alvesb37fd082020-10-22 12:29:21 +0100240 Property("boot-order", "<0>");
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100241 Property("messaging-method", "<4>");
Maksims Svecovs9ddf86a2021-05-06 17:17:21 +0100242 BooleanProperty("managed-exit");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100243 return *this;
244 }
245
David Brazdil52256ff2019-08-23 15:15:15 +0100246 private:
247 ManifestDtBuilder &StringProperty(const std::string_view &name,
248 const std::string_view &value)
249 {
250 dts_ << name << " = \"" << value << "\";" << std::endl;
251 return *this;
252 }
253
David Brazdil74e9c3b2019-08-28 11:09:08 +0100254 ManifestDtBuilder &StringListProperty(
255 const std::string_view &name,
256 const std::vector<std::string_view> &value)
257 {
258 bool is_first = true;
259
260 dts_ << name << " = ";
261 for (const std::string_view &entry : value) {
262 if (is_first) {
263 is_first = false;
264 } else {
265 dts_ << ", ";
266 }
267 dts_ << "\"" << entry << "\"";
268 }
269 dts_ << ";" << std::endl;
270 return *this;
271 }
272
David Brazdil52256ff2019-08-23 15:15:15 +0100273 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100274 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100275 {
276 dts_ << name << " = <" << value << ">;" << std::endl;
277 return *this;
278 }
279
David Brazdil080ee312020-02-25 15:30:30 -0800280 ManifestDtBuilder &Integer64Property(const std::string_view &name,
281 uint64_t value)
282 {
283 uint32_t high = value >> 32;
284 uint32_t low = (uint32_t)value;
285 dts_ << name << " = <" << high << " " << low << ">;"
286 << std::endl;
287 return *this;
288 }
289
Andrew Scullae9962e2019-10-03 16:51:16 +0100290 ManifestDtBuilder &IntegerListProperty(
291 const std::string_view &name,
292 const std::vector<uint32_t> &value)
293 {
294 dts_ << name << " = < ";
295 for (const uint32_t entry : value) {
296 dts_ << entry << " ";
297 }
298 dts_ << ">;" << std::endl;
299 return *this;
300 }
301
302 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
303 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000304 dts_ << name << ";" << std::endl;
305 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100306 }
307
David Brazdil52256ff2019-08-23 15:15:15 +0100308 std::stringstream dts_;
309};
310
David Brazdila2358d42020-01-27 18:51:38 +0000311static enum manifest_return_code manifest_from_vec(struct manifest *m,
312 const std::vector<char> &vec)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100313{
David Brazdila2358d42020-01-27 18:51:38 +0000314 struct memiter it;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100315 struct mpool ppool;
316 struct mm_stage1_locked mm_stage1_locked;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100317
David Brazdila2358d42020-01-27 18:51:38 +0000318 memiter_init(&it, vec.data(), vec.size());
Olivier Deprez62d99e32020-01-09 15:58:07 +0100319 return manifest_init(mm_stage1_locked, m, &it, &ppool);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100320}
321
David Brazdil52256ff2019-08-23 15:15:15 +0100322TEST(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100323{
324 struct manifest m;
David Brazdil52256ff2019-08-23 15:15:15 +0100325 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100326
David Brazdila2358d42020-01-27 18:51:38 +0000327 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100328 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
329}
330
David Brazdil74e9c3b2019-08-28 11:09:08 +0100331TEST(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100332{
333 struct manifest m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100334
David Brazdil52256ff2019-08-23 15:15:15 +0100335 /* clang-format off */
336 std::vector<char> dtb = ManifestDtBuilder()
337 .StartChild("hypervisor")
338 .EndChild()
339 .Build();
340 /* clang-format on */
341
David Brazdilf4925382020-03-25 13:33:51 +0000342 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100343}
344
David Brazdil74e9c3b2019-08-28 11:09:08 +0100345TEST(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100346{
347 struct manifest m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100348
David Brazdil52256ff2019-08-23 15:15:15 +0100349 /* clang-format off */
350 std::vector<char> dtb = ManifestDtBuilder()
351 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100352 .Compatible({ "foo,bar" })
353 .EndChild()
354 .Build();
355 /* clang-format on */
356
David Brazdila2358d42020-01-27 18:51:38 +0000357 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100358}
359
360TEST(manifest, compatible_one_of_many)
361{
362 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100363
364 /* clang-format off */
365 std::vector<char> dtb = ManifestDtBuilder()
366 .StartChild("hypervisor")
367 .Compatible({ "foo,bar", "hafnium,hafnium" })
368 .StartChild("vm1")
369 .DebugName("primary")
370 .EndChild()
371 .EndChild()
372 .Build();
373 /* clang-format on */
374
David Brazdila2358d42020-01-27 18:51:38 +0000375 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100376}
377
378TEST(manifest, no_vm_nodes)
379{
380 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100381
382 /* clang-format off */
383 std::vector<char> dtb = ManifestDtBuilder()
384 .StartChild("hypervisor")
385 .Compatible()
386 .EndChild()
387 .Build();
388 /* clang-format on */
389
David Brazdila2358d42020-01-27 18:51:38 +0000390 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100391}
392
393static std::vector<char> gen_long_string_dtb(bool valid)
394{
395 const char last_valid[] = "1234567890123456789012345678901";
396 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100397 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
398 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100399
400 /* clang-format off */
401 return ManifestDtBuilder()
402 .StartChild("hypervisor")
403 .Compatible()
404 .StartChild("vm1")
405 .DebugName(valid ? last_valid : first_invalid)
406 .EndChild()
407 .EndChild()
408 .Build();
409 /* clang-format on */
410}
411
412TEST(manifest, long_string)
413{
414 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100415 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
416 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
417
David Brazdila2358d42020-01-27 18:51:38 +0000418 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
419 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
420 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100421}
422
423TEST(manifest, reserved_vm_id)
424{
425 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100426
427 /* clang-format off */
428 std::vector<char> dtb = ManifestDtBuilder()
429 .StartChild("hypervisor")
430 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100431 .StartChild("vm1")
432 .DebugName("primary_vm")
433 .EndChild()
434 .StartChild("vm0")
435 .DebugName("reserved_vm")
436 .VcpuCount(1)
437 .MemSize(0x1000)
438 .KernelFilename("kernel")
439 .EndChild()
440 .EndChild()
441 .Build();
442 /* clang-format on */
443
David Brazdila2358d42020-01-27 18:51:38 +0000444 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100445}
446
Andrew Scullae9962e2019-10-03 16:51:16 +0100447static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100448{
449 /* clang-format off */
450 return ManifestDtBuilder()
451 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100452 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100453 .StartChild("vm1")
454 .DebugName("primary_vm")
455 .EndChild()
456 .StartChild("vm2")
457 .DebugName("secondary_vm")
458 .VcpuCount(vcpu_count)
459 .MemSize(0x1000)
460 .KernelFilename("kernel")
461 .EndChild()
462 .EndChild()
463 .Build();
464 /* clang-format on */
465}
David Brazdil7a462ec2019-08-15 12:27:47 +0100466
467TEST(manifest, vcpu_count_limit)
468{
469 struct manifest m;
David Brazdil52256ff2019-08-23 15:15:15 +0100470 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
471 std::vector<char> dtb_first_invalid =
472 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100473
David Brazdila2358d42020-01-27 18:51:38 +0000474 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100475 ASSERT_EQ(m.vm_count, 2);
David Brazdil7a462ec2019-08-15 12:27:47 +0100476 ASSERT_EQ(m.vm[1].secondary.vcpu_count, UINT16_MAX);
477
David Brazdila2358d42020-01-27 18:51:38 +0000478 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100479 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100480}
481
David Brazdile6f83222019-09-23 14:47:37 +0100482TEST(manifest, no_ramdisk_primary)
483{
484 struct manifest m;
David Brazdile6f83222019-09-23 14:47:37 +0100485
486 /* clang-format off */
487 std::vector<char> dtb = ManifestDtBuilder()
488 .StartChild("hypervisor")
489 .Compatible()
490 .StartChild("vm1")
491 .DebugName("primary_vm")
492 .EndChild()
493 .EndChild()
494 .Build();
495 /* clang-format on */
496
David Brazdila2358d42020-01-27 18:51:38 +0000497 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdile6f83222019-09-23 14:47:37 +0100498 ASSERT_EQ(m.vm_count, 1);
499 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
500 ASSERT_STREQ(string_data(&m.vm[0].primary.ramdisk_filename), "");
501}
502
David Brazdil080ee312020-02-25 15:30:30 -0800503TEST(manifest, no_boot_address_primary)
504{
505 struct manifest m;
506
507 /* clang-format off */
508 std::vector<char> dtb = ManifestDtBuilder()
509 .StartChild("hypervisor")
510 .Compatible()
511 .StartChild("vm1")
512 .DebugName("primary_vm")
513 .EndChild()
514 .EndChild()
515 .Build();
516 /* clang-format on */
517
518 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
519 ASSERT_EQ(m.vm_count, 1);
520 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
521 ASSERT_EQ(m.vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
522}
523
524TEST(manifest, boot_address_primary)
525{
526 struct manifest m;
527 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
528
529 /* clang-format off */
530 std::vector<char> dtb = ManifestDtBuilder()
531 .StartChild("hypervisor")
532 .Compatible()
533 .StartChild("vm1")
534 .DebugName("primary_vm")
535 .BootAddress(addr)
536 .EndChild()
537 .EndChild()
538 .Build();
539 /* clang-format on */
540
541 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
542 ASSERT_EQ(m.vm_count, 1);
543 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
544 ASSERT_EQ(m.vm[0].primary.boot_address, addr);
545}
546
Andrew Scullb2c3a242019-11-04 13:52:36 +0000547static std::vector<char> gen_malformed_boolean_dtb(
548 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100549{
Andrew Scullae9962e2019-10-03 16:51:16 +0100550 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000551 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100552 .StartChild("hypervisor")
553 .Compatible()
554 .StartChild("vm1")
555 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000556 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000557 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100558 .EndChild()
559 .Build();
560 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000561}
Andrew Scullae9962e2019-10-03 16:51:16 +0100562
Andrew Scullb2c3a242019-11-04 13:52:36 +0000563TEST(manifest, malformed_booleans)
564{
565 struct manifest m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100566
Andrew Scullb2c3a242019-11-04 13:52:36 +0000567 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
568 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
569 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
570 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100571
David Brazdila2358d42020-01-27 18:51:38 +0000572 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000573 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000574 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000575 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000576 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000577 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000578 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000579 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100580}
581
David Brazdil7a462ec2019-08-15 12:27:47 +0100582TEST(manifest, valid)
583{
584 struct manifest m;
585 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100586
David Brazdil52256ff2019-08-23 15:15:15 +0100587 /* clang-format off */
588 std::vector<char> dtb = ManifestDtBuilder()
589 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100590 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100591 .StartChild("vm1")
592 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100593 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100594 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100595 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100596 .EndChild()
597 .StartChild("vm3")
598 .DebugName("second_secondary_vm")
599 .VcpuCount(43)
600 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100601 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100602 .EndChild()
603 .StartChild("vm2")
604 .DebugName("first_secondary_vm")
605 .VcpuCount(42)
606 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100607 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
608 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100609 .EndChild()
610 .EndChild()
611 .Build();
612 /* clang-format on */
613
David Brazdila2358d42020-01-27 18:51:38 +0000614 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100615 ASSERT_EQ(m.vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100616
617 vm = &m.vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100618 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
619 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100620 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
621 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100622 ASSERT_THAT(
623 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
624 ElementsAre(0x32000000, 0x33001111));
625 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100626
627 vm = &m.vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100628 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
629 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100630 ASSERT_EQ(vm->secondary.vcpu_count, 42);
631 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100632 ASSERT_THAT(
633 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
634 ElementsAre(0x04000000, 0x30002222, 0x31445566));
635 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100636
637 vm = &m.vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100638 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
639 ASSERT_STREQ(string_data(&vm->kernel_filename),
640 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100641 ASSERT_EQ(vm->secondary.vcpu_count, 43);
642 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100643 ASSERT_THAT(
644 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
645 IsEmpty());
646 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100647}
648
Olivier Deprez62d99e32020-01-09 15:58:07 +0100649/**
650 * Class for programatically building a Partition package.
651 */
652class Partition_package
653{
654 public:
655 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
J-Alves2f86c1e2022-02-23 18:44:19 +0000656 __attribute__((aligned(PAGE_SIZE))) char manifest_dtb[PAGE_SIZE] = {};
657 __attribute__((aligned(PAGE_SIZE))) char img[PAGE_SIZE] = {};
Olivier Deprez62d99e32020-01-09 15:58:07 +0100658
659 Partition_package(const std::vector<char> &vec)
660 {
661 // Initialise header field
662 spkg.magic = SP_PKG_HEADER_MAGIC;
J-Alves60984ce2022-04-27 15:27:29 +0100663 spkg.version = SP_PKG_HEADER_VERSION_2;
J-Alves2f86c1e2022-02-23 18:44:19 +0000664 spkg.pm_offset = PAGE_SIZE;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100665 spkg.pm_size = vec.size();
J-Alves2f86c1e2022-02-23 18:44:19 +0000666 spkg.img_offset = 2 * PAGE_SIZE;
667 spkg.img_size = ARRAY_SIZE(img);
Olivier Deprez62d99e32020-01-09 15:58:07 +0100668
669 // Copy dtb into package
670 std::copy(vec.begin(), vec.end(), manifest_dtb);
671 }
672};
673
674static enum manifest_return_code ffa_manifest_from_vec(
675 struct manifest *m, const std::vector<char> &vec)
676{
677 struct memiter it;
678 struct mpool ppool;
679 struct mm_stage1_locked mm_stage1_locked;
680
681 Partition_package spkg(vec);
682
683 /* clang-format off */
684 std::vector<char> core_dtb = ManifestDtBuilder()
685 .StartChild("hypervisor")
686 .Compatible()
687 .StartChild("vm1")
688 .DebugName("primary_vm")
689 .FfaPartition()
690 .LoadAddress((uint64_t)&spkg)
691 .EndChild()
692 .EndChild()
693 .Build();
694 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100695 memiter_init(&it, core_dtb.data(), core_dtb.size());
696 return manifest_init(mm_stage1_locked, m, &it, &ppool);
697}
698
699TEST(manifest, ffa_not_compatible)
700{
701 struct manifest m;
702
703 /* clang-format off */
704 std::vector<char> dtb = ManifestDtBuilder()
705 .Compatible({ "arm,ffa-manifest-2.0" })
706 .Property("ffa-version", "<0x10000>")
707 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
708 .Property("execution-ctx-count", "<1>")
709 .Property("exception-level", "<2>")
710 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000711 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100712 .Property("xlat-granule", "<0>")
713 .Property("messaging-method", "<1>")
714 .Build();
715 /* clang-format on */
716
717 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
718 MANIFEST_ERROR_NOT_COMPATIBLE);
719}
720
721TEST(manifest, ffa_missing_property)
722{
723 struct manifest m;
724
725 /* clang-format off */
726 std::vector<char> dtb = ManifestDtBuilder()
727 .Compatible({ "arm,ffa-manifest-1.0" })
728 .Property("ffa-version", "<0x10000>")
729 .Build();
730 /* clang-format on */
731
732 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
733 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
734}
735
736TEST(manifest, ffa_validate_sanity_check)
737{
J-Alvesb37fd082020-10-22 12:29:21 +0100738 /*
739 * TODO: write test excluding all optional fields of the manifest, in
740 * accordance with specification.
741 */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100742 struct manifest m;
743
744 /* Incompatible version */
745 /* clang-format off */
746 std::vector<char> dtb = ManifestDtBuilder()
747 .Compatible({ "arm,ffa-manifest-1.0" })
748 .Property("ffa-version", "<0xa1>")
749 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
750 .Property("execution-ctx-count", "<1>")
751 .Property("exception-level", "<2>")
752 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000753 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100754 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100755 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100756 .Property("messaging-method", "<1>")
757 .Build();
758 /* clang-format on */
759 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
760 MANIFEST_ERROR_NOT_COMPATIBLE);
761
762 /* Incompatible translation granule */
763 /* clang-format off */
764 dtb = ManifestDtBuilder()
765 .Compatible({ "arm,ffa-manifest-1.0" })
766 .Property("ffa-version", "<0x10000>")
767 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
768 .Property("execution-ctx-count", "<1>")
769 .Property("exception-level", "<2>")
770 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000771 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100772 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100773 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100774 .Property("messaging-method", "<1>")
775 .Build();
776 /* clang-format on */
777 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
778 MANIFEST_ERROR_NOT_COMPATIBLE);
779
780 /* Incompatible exeption level */
781 /* clang-format off */
782 dtb = ManifestDtBuilder()
783 .Compatible({ "arm,ffa-manifest-1.0" })
784 .Property("ffa-version", "<0x10000>")
785 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
786 .Property("execution-ctx-count", "<1>")
787 .Property("exception-level", "<6>")
788 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000789 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100790 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100791 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100792 .Property("messaging-method", "<1>")
793 .Build();
794 /* clang-format on */
795 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
796 MANIFEST_ERROR_NOT_COMPATIBLE);
797
798 /* Incompatible execution state */
799 /* clang-format off */
800 dtb = ManifestDtBuilder()
801 .Compatible({ "arm,ffa-manifest-1.0" })
802 .Property("ffa-version", "<0x10000>")
803 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
804 .Property("execution-ctx-count", "<1>")
805 .Property("exception-level", "<2>")
806 .Property("execution-state", "<2>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000807 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100808 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100809 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100810 .Property("messaging-method", "<1>")
811 .Build();
812 /* clang-format on */
813 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
814 MANIFEST_ERROR_NOT_COMPATIBLE);
815
816 /* Incompatible messaging method */
817 /* clang-format off */
818 dtb = ManifestDtBuilder()
819 .Compatible({ "arm,ffa-manifest-1.0" })
820 .Property("ffa-version", "<0x10000>")
821 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
822 .Property("execution-ctx-count", "<1>")
823 .Property("exception-level", "<2>")
824 .Property("execution-state", "<0>")
J-Alves2f86c1e2022-02-23 18:44:19 +0000825 .Property("entrypoint-offset", "<0x00002000>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100826 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100827 .Property("boot-order", "<0>")
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100828 .Property("messaging-method", "<16>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100829 .Build();
830 /* clang-format on */
831 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
832 MANIFEST_ERROR_NOT_COMPATIBLE);
833}
834
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100835TEST(manifest, ffa_validate_rxtx_info)
836{
837 struct manifest m;
838
839 /* Not Compatible */
840 /* clang-format off */
841 std::vector<char> dtb = ManifestDtBuilder()
842 .FfaValidManifest()
843 .StartChild("rx_tx-info")
844 .Compatible({ "foo,bar" })
845 .EndChild()
846 .Build();
847 /* clang-format on */
848 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
849 MANIFEST_ERROR_NOT_COMPATIBLE);
850
851 /* Missing Properties */
852 /* clang-format off */
853 dtb = ManifestDtBuilder()
854 .FfaValidManifest()
855 .StartChild("rx_tx-info")
856 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
857 .EndChild()
858 .Build();
859 /* clang-format on */
860 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
861 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
862}
863
Manish Pandey6542f5c2020-04-27 14:37:46 +0100864TEST(manifest, ffa_validate_mem_regions)
865{
866 struct manifest m;
867
868 /* Not Compatible */
869 /* clang-format off */
870 std::vector<char> dtb = ManifestDtBuilder()
871 .FfaValidManifest()
872 .StartChild("memory-regions")
873 .Compatible({ "foo,bar" })
874 .EndChild()
875 .Build();
876 /* clang-format on */
877 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
878 MANIFEST_ERROR_NOT_COMPATIBLE);
879
880 /* Memory regions unavailable */
881 /* clang-format off */
882 dtb = ManifestDtBuilder()
883 .FfaValidManifest()
884 .StartChild("memory-regions")
885 .Compatible({ "arm,ffa-manifest-memory-regions" })
886 .EndChild()
887 .Build();
888 /* clang-format on */
889 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
890 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
891
892 /* Missing Properties */
893 /* clang-format off */
894 dtb = ManifestDtBuilder()
895 .FfaValidManifest()
896 .StartChild("memory-regions")
897 .Compatible({ "arm,ffa-manifest-memory-regions" })
898 .StartChild("test-memory")
899 .Description("test-memory")
900 .EndChild()
901 .EndChild()
902 .Build();
903 /* clang-format on */
904 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
905 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Manish Pandeyf06c9072020-09-29 15:41:58 +0100906
907 /* Different RXTX buffer sizes */
908 /* clang-format off */
909 dtb = ManifestDtBuilder()
910 .FfaValidManifest()
911 .StartChild("memory-regions")
912 .Compatible({ "arm,ffa-manifest-memory-regions" })
913 .Label("rx")
914 .StartChild("rx")
915 .Description("rx-buffer")
916 .Property("base-address", "<0x7300000>")
917 .Property("pages-count", "<1>")
918 .Property("attributes", "<1>")
919 .EndChild()
920 .Label("tx")
921 .StartChild("tx")
922 .Description("tx-buffer")
923 .Property("base-address", "<0x7310000>")
924 .Property("pages-count", "<2>")
925 .Property("attributes", "<3>")
926 .EndChild()
927 .EndChild()
928 .StartChild("rx_tx-info")
929 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
930 .Property("rx-buffer", "<&rx>")
931 .Property("tx-buffer", "<&tx>")
932 .EndChild()
933 .Build();
934 /* clang-format on */
935 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
936 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +0100937}
938
Manish Pandeye68e7932020-04-23 15:29:28 +0100939TEST(manifest, ffa_validate_dev_regions)
940{
941 struct manifest m;
942
943 /* Not Compatible */
944 /* clang-format off */
945 std::vector<char> dtb = ManifestDtBuilder()
946 .FfaValidManifest()
947 .StartChild("device-regions")
948 .Compatible({ "foo,bar" })
949 .EndChild()
950 .Build();
951 /* clang-format on */
952 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
953 MANIFEST_ERROR_NOT_COMPATIBLE);
954
955 /* Memory regions unavailable */
956 /* clang-format off */
957 dtb = ManifestDtBuilder()
958 .FfaValidManifest()
959 .StartChild("device-regions")
960 .Compatible({ "arm,ffa-manifest-device-regions" })
961 .EndChild()
962 .Build();
963 /* clang-format on */
964 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
965 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
966
967 /* Missing Properties */
968 /* clang-format off */
969 dtb = ManifestDtBuilder()
970 .FfaValidManifest()
971 .StartChild("device-regions")
972 .Compatible({ "arm,ffa-manifest-device-regions" })
973 .StartChild("test-device")
974 .Description("test-device")
975 .EndChild()
976 .EndChild()
977 .Build();
978 /* clang-format on */
979 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
980 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
981
982 /* Malformed interrupt list pair */
983 /* clang-format off */
984 dtb = ManifestDtBuilder()
985 .FfaValidManifest()
986 .StartChild("device-regions")
987 .Compatible({ "arm,ffa-manifest-device-regions" })
988 .StartChild("test-device")
989 .Description("test-device")
990 .Property("base-address", "<0x7200000>")
991 .Property("pages-count", "<16>")
992 .Property("attributes", "<3>")
993 .Property("smmu-id", "<1>")
994 .Property("stream-ids", "<0 1>")
995 .Property("interrupts", "<2 3>, <4>")
996 .EndChild()
997 .EndChild()
998 .Build();
999 /* clang-format on */
1000 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1001 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
1002}
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001003TEST(manifest, ffa_invalid_memory_region_attributes)
1004{
1005 struct manifest m;
1006
1007 /* clang-format off */
1008 std::vector<char> dtb = ManifestDtBuilder()
1009 .FfaValidManifest()
1010 .StartChild("rx_tx-info")
1011 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1012 .Property("rx-buffer", "<&rx>")
1013 .Property("tx-buffer", "<&tx>")
1014 .EndChild()
1015 .StartChild("memory-regions")
1016 .Compatible({ "arm,ffa-manifest-memory-regions" })
1017 .StartChild("test-memory")
1018 .Description("test-memory")
1019 .Property("base-address", "<0x7100000>")
1020 .Property("pages-count", "<4>")
1021 .Property("attributes", "<7>")
1022 .EndChild()
1023 .Label("rx")
1024 .StartChild("rx")
1025 .Description("rx-buffer")
1026 .Property("base-address", "<0x7300000>")
1027 .Property("pages-count", "<1>")
1028 .Property("attributes", "<1>")
1029 .EndChild()
1030 .Label("tx")
1031 .StartChild("tx")
1032 .Description("tx-buffer")
1033 .Property("base-address", "<0x7310000>")
1034 .Property("pages-count", "<1>")
1035 .Property("attributes", "<3>")
1036 .EndChild()
1037 .EndChild()
1038 .Build();
1039 /* clang-format on */
1040
1041 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1042 MANIFEST_ERROR_INVALID_MEM_PERM);
1043}
1044
1045TEST(manifest, ffa_invalid_device_region_attributes)
1046{
1047 struct manifest m;
1048
1049 /* clang-format off */
1050 std::vector<char> dtb = ManifestDtBuilder()
1051 .FfaValidManifest()
1052 .StartChild("rx_tx-info")
1053 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1054 .Property("rx-buffer", "<&rx>")
1055 .Property("tx-buffer", "<&tx>")
1056 .EndChild()
1057 .StartChild("memory-regions")
1058 .Compatible({ "arm,ffa-manifest-memory-regions" })
1059 .StartChild("test-memory")
1060 .Description("test-memory")
1061 .Property("base-address", "<0x7100000>")
1062 .Property("pages-count", "<4>")
1063 .Property("attributes", "<3>")
1064 .EndChild()
1065 .Label("rx")
1066 .StartChild("rx")
1067 .Description("rx-buffer")
1068 .Property("base-address", "<0x7300000>")
1069 .Property("pages-count", "<1>")
1070 .Property("attributes", "<1>")
1071 .EndChild()
1072 .Label("tx")
1073 .StartChild("tx")
1074 .Description("tx-buffer")
1075 .Property("base-address", "<0x7310000>")
1076 .Property("pages-count", "<1>")
1077 .Property("attributes", "<3>")
1078 .EndChild()
1079 .EndChild()
1080 .StartChild("device-regions")
1081 .Compatible({ "arm,ffa-manifest-device-regions" })
1082 .StartChild("test-device")
1083 .Description("test-device")
1084 .Property("base-address", "<0x7200000>")
1085 .Property("pages-count", "<16>")
1086 .Property("attributes", "<5>")
1087 .Property("smmu-id", "<1>")
1088 .Property("stream-ids", "<0 1>")
1089 .Property("interrupts", "<2 3>, <4 5>")
1090 .EndChild()
1091 .EndChild()
1092 .Build();
1093 /* clang-format on */
1094
1095 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1096 MANIFEST_ERROR_INVALID_MEM_PERM);
1097}
Manish Pandeye68e7932020-04-23 15:29:28 +01001098
Olivier Deprez62d99e32020-01-09 15:58:07 +01001099TEST(manifest, ffa_valid)
1100{
1101 struct manifest m;
1102
1103 /* clang-format off */
1104 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001105 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001106 .StartChild("rx_tx-info")
1107 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1108 .Property("rx-buffer", "<&rx>")
1109 .Property("tx-buffer", "<&tx>")
1110 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001111 .StartChild("memory-regions")
1112 .Compatible({ "arm,ffa-manifest-memory-regions" })
1113 .StartChild("test-memory")
1114 .Description("test-memory")
1115 .Property("base-address", "<0x7100000>")
1116 .Property("pages-count", "<4>")
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001117 .Property("attributes", "<3>")
Manish Pandey6542f5c2020-04-27 14:37:46 +01001118 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001119 .StartChild("test-memory-ns")
1120 .Description("test-memory")
1121 .Property("base-address", "<0x7200000>")
1122 .Property("pages-count", "<1>")
1123 .Property("attributes", "<0xb>")
1124 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001125 .Label("rx")
1126 .StartChild("rx")
1127 .Description("rx-buffer")
1128 .Property("base-address", "<0x7300000>")
1129 .Property("pages-count", "<1>")
1130 .Property("attributes", "<1>")
1131 .EndChild()
1132 .Label("tx")
1133 .StartChild("tx")
1134 .Description("tx-buffer")
1135 .Property("base-address", "<0x7310000>")
1136 .Property("pages-count", "<1>")
1137 .Property("attributes", "<3>")
1138 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001139 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001140 .StartChild("device-regions")
1141 .Compatible({ "arm,ffa-manifest-device-regions" })
1142 .StartChild("test-device")
1143 .Description("test-device")
Olivier Deprez035fa152022-03-14 11:19:10 +01001144 .Property("base-address", "<0x7400000>")
Manish Pandeye68e7932020-04-23 15:29:28 +01001145 .Property("pages-count", "<16>")
1146 .Property("attributes", "<3>")
1147 .Property("smmu-id", "<1>")
1148 .Property("stream-ids", "<0 1>")
1149 .Property("interrupts", "<2 3>, <4 5>")
1150 .EndChild()
Olivier Deprez035fa152022-03-14 11:19:10 +01001151 .StartChild("test-device-ns")
1152 .Description("test-device")
1153 .Property("base-address", "<0x7500000>")
1154 .Property("pages-count", "<1>")
1155 .Property("attributes", "<0x9>")
1156 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001157 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001158 .Build();
1159 /* clang-format on */
1160
1161 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1162
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001163 ASSERT_EQ(m.vm[0].partition.ffa_version, 0x10000);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001164 ASSERT_THAT(
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001165 std::span(m.vm[0].partition.uuid.uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001166 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001167 ASSERT_EQ(m.vm[0].partition.execution_ctx_count, 1);
1168 ASSERT_EQ(m.vm[0].partition.run_time_el, S_EL1);
1169 ASSERT_EQ(m.vm[0].partition.execution_state, AARCH64);
J-Alves2f86c1e2022-02-23 18:44:19 +00001170 ASSERT_EQ(m.vm[0].partition.ep_offset, 0x00002000);
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001171 ASSERT_EQ(m.vm[0].partition.xlat_granule, PAGE_4KB);
1172 ASSERT_EQ(m.vm[0].partition.boot_order, 0);
1173 ASSERT_EQ(m.vm[0].partition.messaging_method,
1174 FFA_PARTITION_INDIRECT_MSG);
1175 ASSERT_EQ(m.vm[0].partition.managed_exit, true);
1176 ASSERT_EQ(m.vm[0].partition.mem_regions[0].base_address, 0x7100000);
1177 ASSERT_EQ(m.vm[0].partition.mem_regions[0].page_count, 4);
Raghu Krishnamurthy384693c2021-10-11 13:56:24 -07001178 ASSERT_EQ(m.vm[0].partition.mem_regions[0].attributes, 3);
Olivier Deprez035fa152022-03-14 11:19:10 +01001179 ASSERT_EQ(m.vm[0].partition.mem_regions[1].attributes, (8 | 3));
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001180 ASSERT_EQ(m.vm[0].partition.rxtx.available, true);
1181 ASSERT_EQ(m.vm[0].partition.rxtx.rx_buffer->base_address, 0x7300000);
1182 ASSERT_EQ(m.vm[0].partition.rxtx.rx_buffer->page_count, 1);
1183 ASSERT_EQ(m.vm[0].partition.rxtx.rx_buffer->attributes, 1);
1184 ASSERT_EQ(m.vm[0].partition.rxtx.tx_buffer->base_address, 0x7310000);
1185 ASSERT_EQ(m.vm[0].partition.rxtx.tx_buffer->page_count, 1);
1186 ASSERT_EQ(m.vm[0].partition.rxtx.tx_buffer->attributes, 3);
Olivier Deprez035fa152022-03-14 11:19:10 +01001187 ASSERT_EQ(m.vm[0].partition.dev_regions[0].base_address, 0x7400000);
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001188 ASSERT_EQ(m.vm[0].partition.dev_regions[0].page_count, 16);
1189
Olivier Deprez035fa152022-03-14 11:19:10 +01001190 ASSERT_EQ(m.vm[0].partition.dev_regions[0].attributes, 3);
Raghu Krishnamurthy8c250a92021-07-02 12:16:42 -07001191 ASSERT_EQ(m.vm[0].partition.dev_regions[0].smmu_id, 1);
1192 ASSERT_EQ(m.vm[0].partition.dev_regions[0].stream_ids[0], 0);
1193 ASSERT_EQ(m.vm[0].partition.dev_regions[0].stream_ids[1], 1);
1194 ASSERT_EQ(m.vm[0].partition.dev_regions[0].interrupts[0].id, 2);
1195 ASSERT_EQ(m.vm[0].partition.dev_regions[0].interrupts[0].attributes, 3);
1196 ASSERT_EQ(m.vm[0].partition.dev_regions[0].interrupts[1].id, 4);
1197 ASSERT_EQ(m.vm[0].partition.dev_regions[0].interrupts[1].attributes, 5);
Olivier Deprez035fa152022-03-14 11:19:10 +01001198 ASSERT_EQ(m.vm[0].partition.dev_regions[1].attributes, (8 | 1));
Olivier Deprez62d99e32020-01-09 15:58:07 +01001199}
1200
David Brazdil7a462ec2019-08-15 12:27:47 +01001201} /* namespace */