blob: 890ab26fa02ac9481a009cc40edf19bfe1ad0657 [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" {
17#include "hf/manifest.h"
18}
19
20namespace
21{
Andrew Scullae9962e2019-10-03 16:51:16 +010022using ::testing::ElementsAre;
David Brazdil7a462ec2019-08-15 12:27:47 +010023using ::testing::Eq;
Andrew Scullae9962e2019-10-03 16:51:16 +010024using ::testing::IsEmpty;
David Brazdil7a462ec2019-08-15 12:27:47 +010025using ::testing::NotNull;
26
David Brazdil52256ff2019-08-23 15:15:15 +010027template <typename T>
David Brazdil0dbb41f2019-09-09 18:03:35 +010028void exec(const char *program, const char *args[], const T &stdin,
David Brazdil52256ff2019-08-23 15:15:15 +010029 std::vector<char> *stdout)
30{
31 /* Create two pipes, one for stdin and one for stdout. */
32 int pipes[2][2];
33 pipe(pipes[0]);
34 pipe(pipes[1]);
David Brazdil7a462ec2019-08-15 12:27:47 +010035
David Brazdil52256ff2019-08-23 15:15:15 +010036 /* Assign FDs for reading/writing by the parent/child. */
37 int parent_read_fd = pipes[1][0]; /* stdout pipe, read FD */
38 int parent_write_fd = pipes[0][1]; /* stdin pipe, write FD */
39 int child_read_fd = pipes[0][0]; /* stdin pipe, read FD */
40 int child_write_fd = pipes[1][1]; /* stdout pipe, write FD */
David Brazdil7a462ec2019-08-15 12:27:47 +010041
David Brazdil52256ff2019-08-23 15:15:15 +010042 if (fork()) {
43 /* Parent process. */
44 std::array<char, 128> buf;
45 ssize_t res;
46
47 /* Close child FDs which won't be used. */
48 close(child_read_fd);
49 close(child_write_fd);
50
51 /* Write to stdin. */
52 for (size_t count = 0; count < stdin.size();) {
53 res = write(parent_write_fd, stdin.data() + count,
54 stdin.size() - count);
55 if (res < 0) {
56 std::cerr << "IO error" << std::endl;
57 exit(1);
58 }
59 count += res;
60 }
61 close(parent_write_fd);
62
63 /* Read from stdout. */
64 while (true) {
65 res = read(parent_read_fd, buf.data(), buf.size());
66 if (res == 0) {
67 /* EOF */
68 break;
69 } else if (res < 0) {
70 std::cerr << "IO error" << std::endl;
71 exit(1);
72 }
73 stdout->insert(stdout->end(), buf.begin(),
74 buf.begin() + res);
75 }
76 close(parent_read_fd);
77 } else {
78 /* Child process. */
79
80 /* Redirect stdin/stdout to read/write FDs. */
81 dup2(child_read_fd, STDIN_FILENO);
82 dup2(child_write_fd, STDOUT_FILENO);
83
84 /* Close all FDs which are now unused. */
85 close(child_read_fd);
86 close(child_write_fd);
87 close(parent_read_fd);
88 close(parent_write_fd);
89
90 /* Execute the given program. */
David Brazdil0dbb41f2019-09-09 18:03:35 +010091 execv(program, const_cast<char *const *>(args));
David Brazdil52256ff2019-08-23 15:15:15 +010092 }
93}
94
95/**
96 * Class for programatically building a Device Tree.
97 *
98 * Usage:
99 * std::vector<char> dtb = ManifestDtBuilder()
100 * .Command1()
101 * .Command2()
102 * ...
103 * .CommandN()
104 * .Build();
105 */
106class ManifestDtBuilder
107{
108 public:
109 ManifestDtBuilder()
110 {
111 dts_ << "/dts-v1/;" << std::endl;
112 dts_ << std::endl;
113
114 /* Start root node. */
115 StartChild("/");
116 }
117
Andrew Scullae9962e2019-10-03 16:51:16 +0100118 std::vector<char> Build(bool dump = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100119 {
David Brazdil0dbb41f2019-09-09 18:03:35 +0100120 const char *program = "./build/image/dtc.py";
121 const char *dtc_args[] = {program, "compile", NULL};
David Brazdil52256ff2019-08-23 15:15:15 +0100122 std::vector<char> dtc_stdout;
123
124 /* Finish root node. */
125 EndChild();
126
Andrew Scullae9962e2019-10-03 16:51:16 +0100127 if (dump) {
128 Dump();
129 }
130
David Brazdil0dbb41f2019-09-09 18:03:35 +0100131 exec(program, dtc_args, dts_.str(), &dtc_stdout);
David Brazdil52256ff2019-08-23 15:15:15 +0100132 return dtc_stdout;
133 }
134
Andrew Scullae9962e2019-10-03 16:51:16 +0100135 void Dump()
136 {
137 std::cerr << dts_.str() << std::endl;
138 }
139
David Brazdil52256ff2019-08-23 15:15:15 +0100140 ManifestDtBuilder &StartChild(const std::string_view &name)
141 {
142 dts_ << name << " {" << std::endl;
143 return *this;
144 }
145
146 ManifestDtBuilder &EndChild()
147 {
148 dts_ << "};" << std::endl;
149 return *this;
150 }
151
David Brazdil74e9c3b2019-08-28 11:09:08 +0100152 ManifestDtBuilder &Compatible(const std::vector<std::string_view>
153 &value = {"hafnium,hafnium"})
154 {
155 return StringListProperty("compatible", value);
156 }
157
David Brazdil52256ff2019-08-23 15:15:15 +0100158 ManifestDtBuilder &DebugName(const std::string_view &value)
159 {
160 return StringProperty("debug_name", value);
161 }
162
Manish Pandey6542f5c2020-04-27 14:37:46 +0100163 ManifestDtBuilder &Description(const std::string_view &value)
164 {
165 return StringProperty("description", value);
166 }
167
David Brazdil52256ff2019-08-23 15:15:15 +0100168 ManifestDtBuilder &KernelFilename(const std::string_view &value)
169 {
170 return StringProperty("kernel_filename", value);
171 }
172
David Brazdile6f83222019-09-23 14:47:37 +0100173 ManifestDtBuilder &RamdiskFilename(const std::string_view &value)
174 {
175 return StringProperty("ramdisk_filename", value);
176 }
177
David Brazdil080ee312020-02-25 15:30:30 -0800178 ManifestDtBuilder &BootAddress(uint64_t value)
179 {
180 return Integer64Property("boot_address", value);
181 }
182
Andrew Scullae9962e2019-10-03 16:51:16 +0100183 ManifestDtBuilder &VcpuCount(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100184 {
185 return IntegerProperty("vcpu_count", value);
186 }
187
Andrew Scullae9962e2019-10-03 16:51:16 +0100188 ManifestDtBuilder &MemSize(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100189 {
190 return IntegerProperty("mem_size", value);
191 }
192
Andrew Scullae9962e2019-10-03 16:51:16 +0100193 ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
194 {
195 return IntegerListProperty("smc_whitelist", value);
196 }
197
198 ManifestDtBuilder &SmcWhitelistPermissive()
199 {
200 return BooleanProperty("smc_whitelist_permissive");
201 }
202
Olivier Deprez62d99e32020-01-09 15:58:07 +0100203 ManifestDtBuilder &LoadAddress(uint64_t value)
204 {
205 return Integer64Property("load_address", value);
206 }
207
208 ManifestDtBuilder &FfaPartition()
209 {
210 return BooleanProperty("is_ffa_partition");
211 }
212
Andrew Scullae9962e2019-10-03 16:51:16 +0100213 ManifestDtBuilder &Property(const std::string_view &name,
214 const std::string_view &value)
215 {
216 dts_ << name << " = " << value << ";" << std::endl;
217 return *this;
218 }
219
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100220 ManifestDtBuilder &Label(const std::string_view &name)
221 {
222 dts_ << name << ": ";
223 return *this;
224 }
225
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100226 ManifestDtBuilder &FfaValidManifest()
227 {
228 Compatible({"arm,ffa-manifest-1.0"});
229 Property("ffa-version", "<0x10000>");
230 Property("uuid",
231 "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>");
232 Property("execution-ctx-count", "<1>");
233 Property("exception-level", "<2>");
234 Property("execution-state", "<0>");
235 Property("load-address", "<0x7000000>");
236 Property("entrypoint-offset", "<0x00001000>");
237 Property("xlat-granule", "<0>");
J-Alvesb37fd082020-10-22 12:29:21 +0100238 Property("boot-order", "<0>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100239 Property("messaging-method", "<1>");
240 return *this;
241 }
242
David Brazdil52256ff2019-08-23 15:15:15 +0100243 private:
244 ManifestDtBuilder &StringProperty(const std::string_view &name,
245 const std::string_view &value)
246 {
247 dts_ << name << " = \"" << value << "\";" << std::endl;
248 return *this;
249 }
250
David Brazdil74e9c3b2019-08-28 11:09:08 +0100251 ManifestDtBuilder &StringListProperty(
252 const std::string_view &name,
253 const std::vector<std::string_view> &value)
254 {
255 bool is_first = true;
256
257 dts_ << name << " = ";
258 for (const std::string_view &entry : value) {
259 if (is_first) {
260 is_first = false;
261 } else {
262 dts_ << ", ";
263 }
264 dts_ << "\"" << entry << "\"";
265 }
266 dts_ << ";" << std::endl;
267 return *this;
268 }
269
David Brazdil52256ff2019-08-23 15:15:15 +0100270 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100271 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100272 {
273 dts_ << name << " = <" << value << ">;" << std::endl;
274 return *this;
275 }
276
David Brazdil080ee312020-02-25 15:30:30 -0800277 ManifestDtBuilder &Integer64Property(const std::string_view &name,
278 uint64_t value)
279 {
280 uint32_t high = value >> 32;
281 uint32_t low = (uint32_t)value;
282 dts_ << name << " = <" << high << " " << low << ">;"
283 << std::endl;
284 return *this;
285 }
286
Andrew Scullae9962e2019-10-03 16:51:16 +0100287 ManifestDtBuilder &IntegerListProperty(
288 const std::string_view &name,
289 const std::vector<uint32_t> &value)
290 {
291 dts_ << name << " = < ";
292 for (const uint32_t entry : value) {
293 dts_ << entry << " ";
294 }
295 dts_ << ">;" << std::endl;
296 return *this;
297 }
298
299 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
300 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000301 dts_ << name << ";" << std::endl;
302 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100303 }
304
David Brazdil52256ff2019-08-23 15:15:15 +0100305 std::stringstream dts_;
306};
307
David Brazdila2358d42020-01-27 18:51:38 +0000308static enum manifest_return_code manifest_from_vec(struct manifest *m,
309 const std::vector<char> &vec)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100310{
David Brazdila2358d42020-01-27 18:51:38 +0000311 struct memiter it;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100312 struct mpool ppool;
313 struct mm_stage1_locked mm_stage1_locked;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100314
David Brazdila2358d42020-01-27 18:51:38 +0000315 memiter_init(&it, vec.data(), vec.size());
Olivier Deprez62d99e32020-01-09 15:58:07 +0100316 return manifest_init(mm_stage1_locked, m, &it, &ppool);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100317}
318
David Brazdil52256ff2019-08-23 15:15:15 +0100319TEST(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100320{
321 struct manifest m;
David Brazdil52256ff2019-08-23 15:15:15 +0100322 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100323
David Brazdila2358d42020-01-27 18:51:38 +0000324 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100325 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
326}
327
David Brazdil74e9c3b2019-08-28 11:09:08 +0100328TEST(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100329{
330 struct manifest m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100331
David Brazdil52256ff2019-08-23 15:15:15 +0100332 /* clang-format off */
333 std::vector<char> dtb = ManifestDtBuilder()
334 .StartChild("hypervisor")
335 .EndChild()
336 .Build();
337 /* clang-format on */
338
David Brazdilf4925382020-03-25 13:33:51 +0000339 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100340}
341
David Brazdil74e9c3b2019-08-28 11:09:08 +0100342TEST(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100343{
344 struct manifest m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100345
David Brazdil52256ff2019-08-23 15:15:15 +0100346 /* clang-format off */
347 std::vector<char> dtb = ManifestDtBuilder()
348 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100349 .Compatible({ "foo,bar" })
350 .EndChild()
351 .Build();
352 /* clang-format on */
353
David Brazdila2358d42020-01-27 18:51:38 +0000354 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100355}
356
357TEST(manifest, compatible_one_of_many)
358{
359 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100360
361 /* clang-format off */
362 std::vector<char> dtb = ManifestDtBuilder()
363 .StartChild("hypervisor")
364 .Compatible({ "foo,bar", "hafnium,hafnium" })
365 .StartChild("vm1")
366 .DebugName("primary")
367 .EndChild()
368 .EndChild()
369 .Build();
370 /* clang-format on */
371
David Brazdila2358d42020-01-27 18:51:38 +0000372 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100373}
374
375TEST(manifest, no_vm_nodes)
376{
377 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100378
379 /* clang-format off */
380 std::vector<char> dtb = ManifestDtBuilder()
381 .StartChild("hypervisor")
382 .Compatible()
383 .EndChild()
384 .Build();
385 /* clang-format on */
386
David Brazdila2358d42020-01-27 18:51:38 +0000387 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100388}
389
390static std::vector<char> gen_long_string_dtb(bool valid)
391{
392 const char last_valid[] = "1234567890123456789012345678901";
393 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100394 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
395 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100396
397 /* clang-format off */
398 return ManifestDtBuilder()
399 .StartChild("hypervisor")
400 .Compatible()
401 .StartChild("vm1")
402 .DebugName(valid ? last_valid : first_invalid)
403 .EndChild()
404 .EndChild()
405 .Build();
406 /* clang-format on */
407}
408
409TEST(manifest, long_string)
410{
411 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100412 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
413 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
414
David Brazdila2358d42020-01-27 18:51:38 +0000415 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
416 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
417 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100418}
419
420TEST(manifest, reserved_vm_id)
421{
422 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100423
424 /* clang-format off */
425 std::vector<char> dtb = ManifestDtBuilder()
426 .StartChild("hypervisor")
427 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100428 .StartChild("vm1")
429 .DebugName("primary_vm")
430 .EndChild()
431 .StartChild("vm0")
432 .DebugName("reserved_vm")
433 .VcpuCount(1)
434 .MemSize(0x1000)
435 .KernelFilename("kernel")
436 .EndChild()
437 .EndChild()
438 .Build();
439 /* clang-format on */
440
David Brazdila2358d42020-01-27 18:51:38 +0000441 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100442}
443
Andrew Scullae9962e2019-10-03 16:51:16 +0100444static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100445{
446 /* clang-format off */
447 return ManifestDtBuilder()
448 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100449 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100450 .StartChild("vm1")
451 .DebugName("primary_vm")
452 .EndChild()
453 .StartChild("vm2")
454 .DebugName("secondary_vm")
455 .VcpuCount(vcpu_count)
456 .MemSize(0x1000)
457 .KernelFilename("kernel")
458 .EndChild()
459 .EndChild()
460 .Build();
461 /* clang-format on */
462}
David Brazdil7a462ec2019-08-15 12:27:47 +0100463
464TEST(manifest, vcpu_count_limit)
465{
466 struct manifest m;
David Brazdil52256ff2019-08-23 15:15:15 +0100467 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
468 std::vector<char> dtb_first_invalid =
469 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100470
David Brazdila2358d42020-01-27 18:51:38 +0000471 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100472 ASSERT_EQ(m.vm_count, 2);
David Brazdil7a462ec2019-08-15 12:27:47 +0100473 ASSERT_EQ(m.vm[1].secondary.vcpu_count, UINT16_MAX);
474
David Brazdila2358d42020-01-27 18:51:38 +0000475 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100476 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100477}
478
David Brazdile6f83222019-09-23 14:47:37 +0100479TEST(manifest, no_ramdisk_primary)
480{
481 struct manifest m;
David Brazdile6f83222019-09-23 14:47:37 +0100482
483 /* clang-format off */
484 std::vector<char> dtb = ManifestDtBuilder()
485 .StartChild("hypervisor")
486 .Compatible()
487 .StartChild("vm1")
488 .DebugName("primary_vm")
489 .EndChild()
490 .EndChild()
491 .Build();
492 /* clang-format on */
493
David Brazdila2358d42020-01-27 18:51:38 +0000494 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdile6f83222019-09-23 14:47:37 +0100495 ASSERT_EQ(m.vm_count, 1);
496 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
497 ASSERT_STREQ(string_data(&m.vm[0].primary.ramdisk_filename), "");
498}
499
David Brazdil080ee312020-02-25 15:30:30 -0800500TEST(manifest, no_boot_address_primary)
501{
502 struct manifest m;
503
504 /* clang-format off */
505 std::vector<char> dtb = ManifestDtBuilder()
506 .StartChild("hypervisor")
507 .Compatible()
508 .StartChild("vm1")
509 .DebugName("primary_vm")
510 .EndChild()
511 .EndChild()
512 .Build();
513 /* clang-format on */
514
515 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
516 ASSERT_EQ(m.vm_count, 1);
517 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
518 ASSERT_EQ(m.vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
519}
520
521TEST(manifest, boot_address_primary)
522{
523 struct manifest m;
524 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
525
526 /* clang-format off */
527 std::vector<char> dtb = ManifestDtBuilder()
528 .StartChild("hypervisor")
529 .Compatible()
530 .StartChild("vm1")
531 .DebugName("primary_vm")
532 .BootAddress(addr)
533 .EndChild()
534 .EndChild()
535 .Build();
536 /* clang-format on */
537
538 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
539 ASSERT_EQ(m.vm_count, 1);
540 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
541 ASSERT_EQ(m.vm[0].primary.boot_address, addr);
542}
543
Andrew Scullb2c3a242019-11-04 13:52:36 +0000544static std::vector<char> gen_malformed_boolean_dtb(
545 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100546{
Andrew Scullae9962e2019-10-03 16:51:16 +0100547 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000548 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100549 .StartChild("hypervisor")
550 .Compatible()
551 .StartChild("vm1")
552 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000553 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000554 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100555 .EndChild()
556 .Build();
557 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000558}
Andrew Scullae9962e2019-10-03 16:51:16 +0100559
Andrew Scullb2c3a242019-11-04 13:52:36 +0000560TEST(manifest, malformed_booleans)
561{
562 struct manifest m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100563
Andrew Scullb2c3a242019-11-04 13:52:36 +0000564 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
565 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
566 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
567 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100568
David Brazdila2358d42020-01-27 18:51:38 +0000569 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000570 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000571 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000572 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000573 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000574 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000575 ASSERT_EQ(manifest_from_vec(&m, dtb_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000576 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100577}
578
David Brazdil7a462ec2019-08-15 12:27:47 +0100579TEST(manifest, valid)
580{
581 struct manifest m;
582 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100583
David Brazdil52256ff2019-08-23 15:15:15 +0100584 /* clang-format off */
585 std::vector<char> dtb = ManifestDtBuilder()
586 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100587 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100588 .StartChild("vm1")
589 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100590 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100591 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100592 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100593 .EndChild()
594 .StartChild("vm3")
595 .DebugName("second_secondary_vm")
596 .VcpuCount(43)
597 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100598 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100599 .EndChild()
600 .StartChild("vm2")
601 .DebugName("first_secondary_vm")
602 .VcpuCount(42)
603 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100604 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
605 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100606 .EndChild()
607 .EndChild()
608 .Build();
609 /* clang-format on */
610
David Brazdila2358d42020-01-27 18:51:38 +0000611 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100612 ASSERT_EQ(m.vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100613
614 vm = &m.vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100615 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
616 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100617 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
618 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100619 ASSERT_THAT(
620 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
621 ElementsAre(0x32000000, 0x33001111));
622 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100623
624 vm = &m.vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100625 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
626 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100627 ASSERT_EQ(vm->secondary.vcpu_count, 42);
628 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100629 ASSERT_THAT(
630 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
631 ElementsAre(0x04000000, 0x30002222, 0x31445566));
632 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100633
634 vm = &m.vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100635 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
636 ASSERT_STREQ(string_data(&vm->kernel_filename),
637 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100638 ASSERT_EQ(vm->secondary.vcpu_count, 43);
639 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100640 ASSERT_THAT(
641 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
642 IsEmpty());
643 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100644}
645
Olivier Deprez62d99e32020-01-09 15:58:07 +0100646/**
647 * Class for programatically building a Partition package.
648 */
649class Partition_package
650{
651 public:
652 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
653 char manifest_dtb[PAGE_SIZE] = {};
654
655 Partition_package(const std::vector<char> &vec)
656 {
657 // Initialise header field
658 spkg.magic = SP_PKG_HEADER_MAGIC;
659 spkg.version = SP_PKG_HEADER_VERSION;
660 spkg.pm_offset = sizeof(struct sp_pkg_header);
661 spkg.pm_size = vec.size();
662
663 // Copy dtb into package
664 std::copy(vec.begin(), vec.end(), manifest_dtb);
665 }
666};
667
668static enum manifest_return_code ffa_manifest_from_vec(
669 struct manifest *m, const std::vector<char> &vec)
670{
671 struct memiter it;
672 struct mpool ppool;
673 struct mm_stage1_locked mm_stage1_locked;
674
675 Partition_package spkg(vec);
676
677 /* clang-format off */
678 std::vector<char> core_dtb = ManifestDtBuilder()
679 .StartChild("hypervisor")
680 .Compatible()
681 .StartChild("vm1")
682 .DebugName("primary_vm")
683 .FfaPartition()
684 .LoadAddress((uint64_t)&spkg)
685 .EndChild()
686 .EndChild()
687 .Build();
688 /* clang-format on */
689
690 memiter_init(&it, core_dtb.data(), core_dtb.size());
691 return manifest_init(mm_stage1_locked, m, &it, &ppool);
692}
693
694TEST(manifest, ffa_not_compatible)
695{
696 struct manifest m;
697
698 /* clang-format off */
699 std::vector<char> dtb = ManifestDtBuilder()
700 .Compatible({ "arm,ffa-manifest-2.0" })
701 .Property("ffa-version", "<0x10000>")
702 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
703 .Property("execution-ctx-count", "<1>")
704 .Property("exception-level", "<2>")
705 .Property("execution-state", "<0>")
706 .Property("load-address", "<0x7000000>")
707 .Property("entrypoint-offset", "<0x00001000>")
708 .Property("xlat-granule", "<0>")
709 .Property("messaging-method", "<1>")
710 .Build();
711 /* clang-format on */
712
713 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
714 MANIFEST_ERROR_NOT_COMPATIBLE);
715}
716
717TEST(manifest, ffa_missing_property)
718{
719 struct manifest m;
720
721 /* clang-format off */
722 std::vector<char> dtb = ManifestDtBuilder()
723 .Compatible({ "arm,ffa-manifest-1.0" })
724 .Property("ffa-version", "<0x10000>")
725 .Build();
726 /* clang-format on */
727
728 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
729 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
730}
731
732TEST(manifest, ffa_validate_sanity_check)
733{
J-Alvesb37fd082020-10-22 12:29:21 +0100734 /*
735 * TODO: write test excluding all optional fields of the manifest, in
736 * accordance with specification.
737 */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100738 struct manifest m;
739
740 /* Incompatible version */
741 /* clang-format off */
742 std::vector<char> dtb = ManifestDtBuilder()
743 .Compatible({ "arm,ffa-manifest-1.0" })
744 .Property("ffa-version", "<0xa1>")
745 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
746 .Property("execution-ctx-count", "<1>")
747 .Property("exception-level", "<2>")
748 .Property("execution-state", "<0>")
749 .Property("load-address", "<0x7000000>")
750 .Property("entrypoint-offset", "<0x00001000>")
751 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100752 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100753 .Property("messaging-method", "<1>")
754 .Build();
755 /* clang-format on */
756 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
757 MANIFEST_ERROR_NOT_COMPATIBLE);
758
759 /* Incompatible translation granule */
760 /* clang-format off */
761 dtb = ManifestDtBuilder()
762 .Compatible({ "arm,ffa-manifest-1.0" })
763 .Property("ffa-version", "<0x10000>")
764 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
765 .Property("execution-ctx-count", "<1>")
766 .Property("exception-level", "<2>")
767 .Property("execution-state", "<0>")
768 .Property("load-address", "<0x7000000>")
769 .Property("entrypoint-offset", "<0x00001000>")
770 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100771 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100772 .Property("messaging-method", "<1>")
773 .Build();
774 /* clang-format on */
775 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
776 MANIFEST_ERROR_NOT_COMPATIBLE);
777
778 /* Incompatible exeption level */
779 /* clang-format off */
780 dtb = ManifestDtBuilder()
781 .Compatible({ "arm,ffa-manifest-1.0" })
782 .Property("ffa-version", "<0x10000>")
783 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
784 .Property("execution-ctx-count", "<1>")
785 .Property("exception-level", "<6>")
786 .Property("execution-state", "<0>")
787 .Property("load-address", "<0x7000000>")
788 .Property("entrypoint-offset", "<0x00001000>")
789 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100790 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100791 .Property("messaging-method", "<1>")
792 .Build();
793 /* clang-format on */
794 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
795 MANIFEST_ERROR_NOT_COMPATIBLE);
796
797 /* Incompatible execution state */
798 /* clang-format off */
799 dtb = ManifestDtBuilder()
800 .Compatible({ "arm,ffa-manifest-1.0" })
801 .Property("ffa-version", "<0x10000>")
802 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
803 .Property("execution-ctx-count", "<1>")
804 .Property("exception-level", "<2>")
805 .Property("execution-state", "<2>")
806 .Property("load-address", "<0x7000000>")
807 .Property("entrypoint-offset", "<0x00001000>")
808 .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>")
825 .Property("load-address", "<0x7000000>")
826 .Property("entrypoint-offset", "<0x00001000>")
827 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100828 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100829 .Property("messaging-method", "<3>")
830 .Build();
831 /* clang-format on */
832 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
833 MANIFEST_ERROR_NOT_COMPATIBLE);
834}
835
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100836TEST(manifest, ffa_validate_rxtx_info)
837{
838 struct manifest m;
839
840 /* Not Compatible */
841 /* clang-format off */
842 std::vector<char> dtb = ManifestDtBuilder()
843 .FfaValidManifest()
844 .StartChild("rx_tx-info")
845 .Compatible({ "foo,bar" })
846 .EndChild()
847 .Build();
848 /* clang-format on */
849 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
850 MANIFEST_ERROR_NOT_COMPATIBLE);
851
852 /* Missing Properties */
853 /* clang-format off */
854 dtb = ManifestDtBuilder()
855 .FfaValidManifest()
856 .StartChild("rx_tx-info")
857 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
858 .EndChild()
859 .Build();
860 /* clang-format on */
861 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
862 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
863}
864
Manish Pandey6542f5c2020-04-27 14:37:46 +0100865TEST(manifest, ffa_validate_mem_regions)
866{
867 struct manifest m;
868
869 /* Not Compatible */
870 /* clang-format off */
871 std::vector<char> dtb = ManifestDtBuilder()
872 .FfaValidManifest()
873 .StartChild("memory-regions")
874 .Compatible({ "foo,bar" })
875 .EndChild()
876 .Build();
877 /* clang-format on */
878 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
879 MANIFEST_ERROR_NOT_COMPATIBLE);
880
881 /* Memory regions unavailable */
882 /* clang-format off */
883 dtb = ManifestDtBuilder()
884 .FfaValidManifest()
885 .StartChild("memory-regions")
886 .Compatible({ "arm,ffa-manifest-memory-regions" })
887 .EndChild()
888 .Build();
889 /* clang-format on */
890 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
891 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
892
893 /* Missing Properties */
894 /* clang-format off */
895 dtb = ManifestDtBuilder()
896 .FfaValidManifest()
897 .StartChild("memory-regions")
898 .Compatible({ "arm,ffa-manifest-memory-regions" })
899 .StartChild("test-memory")
900 .Description("test-memory")
901 .EndChild()
902 .EndChild()
903 .Build();
904 /* clang-format on */
905 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
906 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Manish Pandeyf06c9072020-09-29 15:41:58 +0100907
908 /* Different RXTX buffer sizes */
909 /* clang-format off */
910 dtb = ManifestDtBuilder()
911 .FfaValidManifest()
912 .StartChild("memory-regions")
913 .Compatible({ "arm,ffa-manifest-memory-regions" })
914 .Label("rx")
915 .StartChild("rx")
916 .Description("rx-buffer")
917 .Property("base-address", "<0x7300000>")
918 .Property("pages-count", "<1>")
919 .Property("attributes", "<1>")
920 .EndChild()
921 .Label("tx")
922 .StartChild("tx")
923 .Description("tx-buffer")
924 .Property("base-address", "<0x7310000>")
925 .Property("pages-count", "<2>")
926 .Property("attributes", "<3>")
927 .EndChild()
928 .EndChild()
929 .StartChild("rx_tx-info")
930 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
931 .Property("rx-buffer", "<&rx>")
932 .Property("tx-buffer", "<&tx>")
933 .EndChild()
934 .Build();
935 /* clang-format on */
936 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
937 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +0100938}
939
Manish Pandeye68e7932020-04-23 15:29:28 +0100940TEST(manifest, ffa_validate_dev_regions)
941{
942 struct manifest m;
943
944 /* Not Compatible */
945 /* clang-format off */
946 std::vector<char> dtb = ManifestDtBuilder()
947 .FfaValidManifest()
948 .StartChild("device-regions")
949 .Compatible({ "foo,bar" })
950 .EndChild()
951 .Build();
952 /* clang-format on */
953 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
954 MANIFEST_ERROR_NOT_COMPATIBLE);
955
956 /* Memory regions unavailable */
957 /* clang-format off */
958 dtb = ManifestDtBuilder()
959 .FfaValidManifest()
960 .StartChild("device-regions")
961 .Compatible({ "arm,ffa-manifest-device-regions" })
962 .EndChild()
963 .Build();
964 /* clang-format on */
965 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
966 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
967
968 /* Missing Properties */
969 /* clang-format off */
970 dtb = ManifestDtBuilder()
971 .FfaValidManifest()
972 .StartChild("device-regions")
973 .Compatible({ "arm,ffa-manifest-device-regions" })
974 .StartChild("test-device")
975 .Description("test-device")
976 .EndChild()
977 .EndChild()
978 .Build();
979 /* clang-format on */
980 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
981 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
982
983 /* Malformed interrupt list pair */
984 /* clang-format off */
985 dtb = ManifestDtBuilder()
986 .FfaValidManifest()
987 .StartChild("device-regions")
988 .Compatible({ "arm,ffa-manifest-device-regions" })
989 .StartChild("test-device")
990 .Description("test-device")
991 .Property("base-address", "<0x7200000>")
992 .Property("pages-count", "<16>")
993 .Property("attributes", "<3>")
994 .Property("smmu-id", "<1>")
995 .Property("stream-ids", "<0 1>")
996 .Property("interrupts", "<2 3>, <4>")
997 .EndChild()
998 .EndChild()
999 .Build();
1000 /* clang-format on */
1001 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
1002 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
1003}
1004
Olivier Deprez62d99e32020-01-09 15:58:07 +01001005TEST(manifest, ffa_valid)
1006{
1007 struct manifest m;
1008
1009 /* clang-format off */
1010 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001011 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001012 .StartChild("rx_tx-info")
1013 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1014 .Property("rx-buffer", "<&rx>")
1015 .Property("tx-buffer", "<&tx>")
1016 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001017 .StartChild("memory-regions")
1018 .Compatible({ "arm,ffa-manifest-memory-regions" })
1019 .StartChild("test-memory")
1020 .Description("test-memory")
1021 .Property("base-address", "<0x7100000>")
1022 .Property("pages-count", "<4>")
1023 .Property("attributes", "<7>")
1024 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001025 .Label("rx")
1026 .StartChild("rx")
1027 .Description("rx-buffer")
1028 .Property("base-address", "<0x7300000>")
1029 .Property("pages-count", "<1>")
1030 .Property("attributes", "<1>")
1031 .EndChild()
1032 .Label("tx")
1033 .StartChild("tx")
1034 .Description("tx-buffer")
1035 .Property("base-address", "<0x7310000>")
1036 .Property("pages-count", "<1>")
1037 .Property("attributes", "<3>")
1038 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001039 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001040 .StartChild("device-regions")
1041 .Compatible({ "arm,ffa-manifest-device-regions" })
1042 .StartChild("test-device")
1043 .Description("test-device")
1044 .Property("base-address", "<0x7200000>")
1045 .Property("pages-count", "<16>")
1046 .Property("attributes", "<3>")
1047 .Property("smmu-id", "<1>")
1048 .Property("stream-ids", "<0 1>")
1049 .Property("interrupts", "<2 3>, <4 5>")
1050 .EndChild()
1051 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001052 .Build();
1053 /* clang-format on */
1054
1055 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1056
1057 ASSERT_EQ(m.vm[0].sp.ffa_version, 0x10000);
1058 ASSERT_THAT(
Fuad Tabbae4efcc32020-07-16 15:37:27 +01001059 std::span(m.vm[0].sp.uuid.uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001060 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
1061 ASSERT_EQ(m.vm[0].sp.execution_ctx_count, 1);
1062 ASSERT_EQ(m.vm[0].sp.run_time_el, S_EL1);
1063 ASSERT_EQ(m.vm[0].sp.execution_state, AARCH64);
1064 ASSERT_EQ(m.vm[0].sp.load_addr, 0x7000000);
1065 ASSERT_EQ(m.vm[0].sp.ep_offset, 0x00001000);
1066 ASSERT_EQ(m.vm[0].sp.xlat_granule, PAGE_4KB);
J-Alvesb37fd082020-10-22 12:29:21 +01001067 ASSERT_EQ(m.vm[0].sp.boot_order, 0);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001068 ASSERT_EQ(m.vm[0].sp.messaging_method, INDIRECT_MESSAGING);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001069 ASSERT_EQ(m.vm[0].sp.mem_regions[0].base_address, 0x7100000);
1070 ASSERT_EQ(m.vm[0].sp.mem_regions[0].page_count, 4);
1071 ASSERT_EQ(m.vm[0].sp.mem_regions[0].attributes, 7);
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001072 ASSERT_EQ(m.vm[0].sp.rxtx.available, true);
1073 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->base_address, 0x7300000);
1074 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->page_count, 1);
1075 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->attributes, 1);
1076 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->base_address, 0x7310000);
1077 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->page_count, 1);
1078 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->attributes, 3);
Manish Pandeye68e7932020-04-23 15:29:28 +01001079 ASSERT_EQ(m.vm[0].sp.dev_regions[0].base_address, 0x7200000);
1080 ASSERT_EQ(m.vm[0].sp.dev_regions[0].page_count, 16);
1081 /* Attribute is ORed with MM_MODE_D */
1082 ASSERT_EQ(m.vm[0].sp.dev_regions[0].attributes, (3 | 8));
1083 ASSERT_EQ(m.vm[0].sp.dev_regions[0].smmu_id, 1);
1084 ASSERT_EQ(m.vm[0].sp.dev_regions[0].stream_ids[0], 0);
1085 ASSERT_EQ(m.vm[0].sp.dev_regions[0].stream_ids[1], 1);
1086 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[0].id, 2);
1087 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[0].attributes, 3);
1088 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[1].id, 4);
1089 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[1].attributes, 5);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001090}
1091
David Brazdil7a462ec2019-08-15 12:27:47 +01001092} /* namespace */