blob: c73f843ca5f4b7f6049200d623a0226ecede6066 [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>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100235 Property("entrypoint-offset", "<0x00001000>");
236 Property("xlat-granule", "<0>");
J-Alvesb37fd082020-10-22 12:29:21 +0100237 Property("boot-order", "<0>");
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100238 Property("messaging-method", "<4>");
Manish Pandeycb8fbb22020-08-18 00:04:43 +0100239 return *this;
240 }
241
David Brazdil52256ff2019-08-23 15:15:15 +0100242 private:
243 ManifestDtBuilder &StringProperty(const std::string_view &name,
244 const std::string_view &value)
245 {
246 dts_ << name << " = \"" << value << "\";" << std::endl;
247 return *this;
248 }
249
David Brazdil74e9c3b2019-08-28 11:09:08 +0100250 ManifestDtBuilder &StringListProperty(
251 const std::string_view &name,
252 const std::vector<std::string_view> &value)
253 {
254 bool is_first = true;
255
256 dts_ << name << " = ";
257 for (const std::string_view &entry : value) {
258 if (is_first) {
259 is_first = false;
260 } else {
261 dts_ << ", ";
262 }
263 dts_ << "\"" << entry << "\"";
264 }
265 dts_ << ";" << std::endl;
266 return *this;
267 }
268
David Brazdil52256ff2019-08-23 15:15:15 +0100269 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100270 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100271 {
272 dts_ << name << " = <" << value << ">;" << std::endl;
273 return *this;
274 }
275
David Brazdil080ee312020-02-25 15:30:30 -0800276 ManifestDtBuilder &Integer64Property(const std::string_view &name,
277 uint64_t value)
278 {
279 uint32_t high = value >> 32;
280 uint32_t low = (uint32_t)value;
281 dts_ << name << " = <" << high << " " << low << ">;"
282 << std::endl;
283 return *this;
284 }
285
Andrew Scullae9962e2019-10-03 16:51:16 +0100286 ManifestDtBuilder &IntegerListProperty(
287 const std::string_view &name,
288 const std::vector<uint32_t> &value)
289 {
290 dts_ << name << " = < ";
291 for (const uint32_t entry : value) {
292 dts_ << entry << " ";
293 }
294 dts_ << ">;" << std::endl;
295 return *this;
296 }
297
298 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
299 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000300 dts_ << name << ";" << std::endl;
301 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100302 }
303
David Brazdil52256ff2019-08-23 15:15:15 +0100304 std::stringstream dts_;
305};
306
David Brazdila2358d42020-01-27 18:51:38 +0000307static enum manifest_return_code manifest_from_vec(struct manifest *m,
308 const std::vector<char> &vec)
David Brazdil0dbb41f2019-09-09 18:03:35 +0100309{
David Brazdila2358d42020-01-27 18:51:38 +0000310 struct memiter it;
Olivier Deprez62d99e32020-01-09 15:58:07 +0100311 struct mpool ppool;
312 struct mm_stage1_locked mm_stage1_locked;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100313
David Brazdila2358d42020-01-27 18:51:38 +0000314 memiter_init(&it, vec.data(), vec.size());
Olivier Deprez62d99e32020-01-09 15:58:07 +0100315 return manifest_init(mm_stage1_locked, m, &it, &ppool);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100316}
317
David Brazdil52256ff2019-08-23 15:15:15 +0100318TEST(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100319{
320 struct manifest m;
David Brazdil52256ff2019-08-23 15:15:15 +0100321 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100322
David Brazdila2358d42020-01-27 18:51:38 +0000323 ASSERT_EQ(manifest_from_vec(&m, dtb),
David Brazdil7a462ec2019-08-15 12:27:47 +0100324 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
325}
326
David Brazdil74e9c3b2019-08-28 11:09:08 +0100327TEST(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100328{
329 struct manifest m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100330
David Brazdil52256ff2019-08-23 15:15:15 +0100331 /* clang-format off */
332 std::vector<char> dtb = ManifestDtBuilder()
333 .StartChild("hypervisor")
334 .EndChild()
335 .Build();
336 /* clang-format on */
337
David Brazdilf4925382020-03-25 13:33:51 +0000338 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil7a462ec2019-08-15 12:27:47 +0100339}
340
David Brazdil74e9c3b2019-08-28 11:09:08 +0100341TEST(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100342{
343 struct manifest m;
David Brazdil7a462ec2019-08-15 12:27:47 +0100344
David Brazdil52256ff2019-08-23 15:15:15 +0100345 /* clang-format off */
346 std::vector<char> dtb = ManifestDtBuilder()
347 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100348 .Compatible({ "foo,bar" })
349 .EndChild()
350 .Build();
351 /* clang-format on */
352
David Brazdila2358d42020-01-27 18:51:38 +0000353 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100354}
355
356TEST(manifest, compatible_one_of_many)
357{
358 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100359
360 /* clang-format off */
361 std::vector<char> dtb = ManifestDtBuilder()
362 .StartChild("hypervisor")
363 .Compatible({ "foo,bar", "hafnium,hafnium" })
364 .StartChild("vm1")
365 .DebugName("primary")
366 .EndChild()
367 .EndChild()
368 .Build();
369 /* clang-format on */
370
David Brazdila2358d42020-01-27 18:51:38 +0000371 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100372}
373
374TEST(manifest, no_vm_nodes)
375{
376 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100377
378 /* clang-format off */
379 std::vector<char> dtb = ManifestDtBuilder()
380 .StartChild("hypervisor")
381 .Compatible()
382 .EndChild()
383 .Build();
384 /* clang-format on */
385
David Brazdila2358d42020-01-27 18:51:38 +0000386 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_NO_PRIMARY_VM);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100387}
388
389static std::vector<char> gen_long_string_dtb(bool valid)
390{
391 const char last_valid[] = "1234567890123456789012345678901";
392 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100393 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
394 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100395
396 /* clang-format off */
397 return ManifestDtBuilder()
398 .StartChild("hypervisor")
399 .Compatible()
400 .StartChild("vm1")
401 .DebugName(valid ? last_valid : first_invalid)
402 .EndChild()
403 .EndChild()
404 .Build();
405 /* clang-format on */
406}
407
408TEST(manifest, long_string)
409{
410 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100411 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
412 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
413
David Brazdila2358d42020-01-27 18:51:38 +0000414 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
415 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
416 MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100417}
418
419TEST(manifest, reserved_vm_id)
420{
421 struct manifest m;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100422
423 /* clang-format off */
424 std::vector<char> dtb = ManifestDtBuilder()
425 .StartChild("hypervisor")
426 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100427 .StartChild("vm1")
428 .DebugName("primary_vm")
429 .EndChild()
430 .StartChild("vm0")
431 .DebugName("reserved_vm")
432 .VcpuCount(1)
433 .MemSize(0x1000)
434 .KernelFilename("kernel")
435 .EndChild()
436 .EndChild()
437 .Build();
438 /* clang-format on */
439
David Brazdila2358d42020-01-27 18:51:38 +0000440 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100441}
442
Andrew Scullae9962e2019-10-03 16:51:16 +0100443static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100444{
445 /* clang-format off */
446 return ManifestDtBuilder()
447 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100448 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100449 .StartChild("vm1")
450 .DebugName("primary_vm")
451 .EndChild()
452 .StartChild("vm2")
453 .DebugName("secondary_vm")
454 .VcpuCount(vcpu_count)
455 .MemSize(0x1000)
456 .KernelFilename("kernel")
457 .EndChild()
458 .EndChild()
459 .Build();
460 /* clang-format on */
461}
David Brazdil7a462ec2019-08-15 12:27:47 +0100462
463TEST(manifest, vcpu_count_limit)
464{
465 struct manifest m;
David Brazdil52256ff2019-08-23 15:15:15 +0100466 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
467 std::vector<char> dtb_first_invalid =
468 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100469
David Brazdila2358d42020-01-27 18:51:38 +0000470 ASSERT_EQ(manifest_from_vec(&m, dtb_last_valid), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100471 ASSERT_EQ(m.vm_count, 2);
David Brazdil7a462ec2019-08-15 12:27:47 +0100472 ASSERT_EQ(m.vm[1].secondary.vcpu_count, UINT16_MAX);
473
David Brazdila2358d42020-01-27 18:51:38 +0000474 ASSERT_EQ(manifest_from_vec(&m, dtb_first_invalid),
David Brazdil0dbb41f2019-09-09 18:03:35 +0100475 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100476}
477
David Brazdile6f83222019-09-23 14:47:37 +0100478TEST(manifest, no_ramdisk_primary)
479{
480 struct manifest m;
David Brazdile6f83222019-09-23 14:47:37 +0100481
482 /* clang-format off */
483 std::vector<char> dtb = ManifestDtBuilder()
484 .StartChild("hypervisor")
485 .Compatible()
486 .StartChild("vm1")
487 .DebugName("primary_vm")
488 .EndChild()
489 .EndChild()
490 .Build();
491 /* clang-format on */
492
David Brazdila2358d42020-01-27 18:51:38 +0000493 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdile6f83222019-09-23 14:47:37 +0100494 ASSERT_EQ(m.vm_count, 1);
495 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
496 ASSERT_STREQ(string_data(&m.vm[0].primary.ramdisk_filename), "");
497}
498
David Brazdil080ee312020-02-25 15:30:30 -0800499TEST(manifest, no_boot_address_primary)
500{
501 struct manifest m;
502
503 /* clang-format off */
504 std::vector<char> dtb = ManifestDtBuilder()
505 .StartChild("hypervisor")
506 .Compatible()
507 .StartChild("vm1")
508 .DebugName("primary_vm")
509 .EndChild()
510 .EndChild()
511 .Build();
512 /* clang-format on */
513
514 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
515 ASSERT_EQ(m.vm_count, 1);
516 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
517 ASSERT_EQ(m.vm[0].primary.boot_address, MANIFEST_INVALID_ADDRESS);
518}
519
520TEST(manifest, boot_address_primary)
521{
522 struct manifest m;
523 const uint64_t addr = UINT64_C(0x12345678ABCDEFEF);
524
525 /* clang-format off */
526 std::vector<char> dtb = ManifestDtBuilder()
527 .StartChild("hypervisor")
528 .Compatible()
529 .StartChild("vm1")
530 .DebugName("primary_vm")
531 .BootAddress(addr)
532 .EndChild()
533 .EndChild()
534 .Build();
535 /* clang-format on */
536
537 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
538 ASSERT_EQ(m.vm_count, 1);
539 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
540 ASSERT_EQ(m.vm[0].primary.boot_address, addr);
541}
542
Andrew Scullb2c3a242019-11-04 13:52:36 +0000543static std::vector<char> gen_malformed_boolean_dtb(
544 const std::string_view &value)
Andrew Scullae9962e2019-10-03 16:51:16 +0100545{
Andrew Scullae9962e2019-10-03 16:51:16 +0100546 /* clang-format off */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000547 return ManifestDtBuilder()
Andrew Scullae9962e2019-10-03 16:51:16 +0100548 .StartChild("hypervisor")
549 .Compatible()
550 .StartChild("vm1")
551 .DebugName("primary_vm")
Andrew Scullb2c3a242019-11-04 13:52:36 +0000552 .Property("smc_whitelist_permissive", value)
Andrew Scull5dc089e2019-11-04 13:21:03 +0000553 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100554 .EndChild()
555 .Build();
556 /* clang-format on */
Andrew Scullb2c3a242019-11-04 13:52:36 +0000557}
Andrew Scullae9962e2019-10-03 16:51:16 +0100558
Andrew Scullb2c3a242019-11-04 13:52:36 +0000559TEST(manifest, malformed_booleans)
560{
561 struct manifest m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100562
Andrew Scullb2c3a242019-11-04 13:52:36 +0000563 std::vector<char> dtb_false = gen_malformed_boolean_dtb("\"false\"");
564 std::vector<char> dtb_true = gen_malformed_boolean_dtb("\"true\"");
565 std::vector<char> dtb_0 = gen_malformed_boolean_dtb("\"<0>\"");
566 std::vector<char> dtb_1 = gen_malformed_boolean_dtb("\"<1>\"");
Andrew Scullae9962e2019-10-03 16:51:16 +0100567
David Brazdila2358d42020-01-27 18:51:38 +0000568 ASSERT_EQ(manifest_from_vec(&m, dtb_false),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000569 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000570 ASSERT_EQ(manifest_from_vec(&m, dtb_true),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000571 MANIFEST_ERROR_MALFORMED_BOOLEAN);
David Brazdila2358d42020-01-27 18:51:38 +0000572 ASSERT_EQ(manifest_from_vec(&m, dtb_0),
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_1),
Andrew Scullb2c3a242019-11-04 13:52:36 +0000575 MANIFEST_ERROR_MALFORMED_BOOLEAN);
Andrew Scullae9962e2019-10-03 16:51:16 +0100576}
577
David Brazdil7a462ec2019-08-15 12:27:47 +0100578TEST(manifest, valid)
579{
580 struct manifest m;
581 struct manifest_vm *vm;
David Brazdil7a462ec2019-08-15 12:27:47 +0100582
David Brazdil52256ff2019-08-23 15:15:15 +0100583 /* clang-format off */
584 std::vector<char> dtb = ManifestDtBuilder()
585 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100586 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100587 .StartChild("vm1")
588 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100589 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100590 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100591 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100592 .EndChild()
593 .StartChild("vm3")
594 .DebugName("second_secondary_vm")
595 .VcpuCount(43)
596 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100597 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100598 .EndChild()
599 .StartChild("vm2")
600 .DebugName("first_secondary_vm")
601 .VcpuCount(42)
602 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100603 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
604 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100605 .EndChild()
606 .EndChild()
607 .Build();
608 /* clang-format on */
609
David Brazdila2358d42020-01-27 18:51:38 +0000610 ASSERT_EQ(manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100611 ASSERT_EQ(m.vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100612
613 vm = &m.vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100614 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
615 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100616 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
617 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100618 ASSERT_THAT(
619 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
620 ElementsAre(0x32000000, 0x33001111));
621 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100622
623 vm = &m.vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100624 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
625 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100626 ASSERT_EQ(vm->secondary.vcpu_count, 42);
627 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100628 ASSERT_THAT(
629 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
630 ElementsAre(0x04000000, 0x30002222, 0x31445566));
631 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100632
633 vm = &m.vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100634 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
635 ASSERT_STREQ(string_data(&vm->kernel_filename),
636 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100637 ASSERT_EQ(vm->secondary.vcpu_count, 43);
638 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100639 ASSERT_THAT(
640 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
641 IsEmpty());
642 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100643}
644
Olivier Deprez62d99e32020-01-09 15:58:07 +0100645/**
646 * Class for programatically building a Partition package.
647 */
648class Partition_package
649{
650 public:
651 __attribute__((aligned(PAGE_SIZE))) struct sp_pkg_header spkg;
652 char manifest_dtb[PAGE_SIZE] = {};
653
654 Partition_package(const std::vector<char> &vec)
655 {
656 // Initialise header field
657 spkg.magic = SP_PKG_HEADER_MAGIC;
658 spkg.version = SP_PKG_HEADER_VERSION;
659 spkg.pm_offset = sizeof(struct sp_pkg_header);
660 spkg.pm_size = vec.size();
661
662 // Copy dtb into package
663 std::copy(vec.begin(), vec.end(), manifest_dtb);
664 }
665};
666
667static enum manifest_return_code ffa_manifest_from_vec(
668 struct manifest *m, const std::vector<char> &vec)
669{
670 struct memiter it;
671 struct mpool ppool;
672 struct mm_stage1_locked mm_stage1_locked;
673
674 Partition_package spkg(vec);
675
676 /* clang-format off */
677 std::vector<char> core_dtb = ManifestDtBuilder()
678 .StartChild("hypervisor")
679 .Compatible()
680 .StartChild("vm1")
681 .DebugName("primary_vm")
682 .FfaPartition()
683 .LoadAddress((uint64_t)&spkg)
684 .EndChild()
685 .EndChild()
686 .Build();
687 /* clang-format on */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100688 memiter_init(&it, core_dtb.data(), core_dtb.size());
689 return manifest_init(mm_stage1_locked, m, &it, &ppool);
690}
691
692TEST(manifest, ffa_not_compatible)
693{
694 struct manifest m;
695
696 /* clang-format off */
697 std::vector<char> dtb = ManifestDtBuilder()
698 .Compatible({ "arm,ffa-manifest-2.0" })
699 .Property("ffa-version", "<0x10000>")
700 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
701 .Property("execution-ctx-count", "<1>")
702 .Property("exception-level", "<2>")
703 .Property("execution-state", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100704 .Property("entrypoint-offset", "<0x00001000>")
705 .Property("xlat-granule", "<0>")
706 .Property("messaging-method", "<1>")
707 .Build();
708 /* clang-format on */
709
710 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
711 MANIFEST_ERROR_NOT_COMPATIBLE);
712}
713
714TEST(manifest, ffa_missing_property)
715{
716 struct manifest m;
717
718 /* clang-format off */
719 std::vector<char> dtb = ManifestDtBuilder()
720 .Compatible({ "arm,ffa-manifest-1.0" })
721 .Property("ffa-version", "<0x10000>")
722 .Build();
723 /* clang-format on */
724
725 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
726 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
727}
728
729TEST(manifest, ffa_validate_sanity_check)
730{
J-Alvesb37fd082020-10-22 12:29:21 +0100731 /*
732 * TODO: write test excluding all optional fields of the manifest, in
733 * accordance with specification.
734 */
Olivier Deprez62d99e32020-01-09 15:58:07 +0100735 struct manifest m;
736
737 /* Incompatible version */
738 /* clang-format off */
739 std::vector<char> dtb = ManifestDtBuilder()
740 .Compatible({ "arm,ffa-manifest-1.0" })
741 .Property("ffa-version", "<0xa1>")
742 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
743 .Property("execution-ctx-count", "<1>")
744 .Property("exception-level", "<2>")
745 .Property("execution-state", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100746 .Property("entrypoint-offset", "<0x00001000>")
747 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100748 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100749 .Property("messaging-method", "<1>")
750 .Build();
751 /* clang-format on */
752 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
753 MANIFEST_ERROR_NOT_COMPATIBLE);
754
755 /* Incompatible translation granule */
756 /* clang-format off */
757 dtb = ManifestDtBuilder()
758 .Compatible({ "arm,ffa-manifest-1.0" })
759 .Property("ffa-version", "<0x10000>")
760 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
761 .Property("execution-ctx-count", "<1>")
762 .Property("exception-level", "<2>")
763 .Property("execution-state", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100764 .Property("entrypoint-offset", "<0x00001000>")
765 .Property("xlat-granule", "<3>")
J-Alvesb37fd082020-10-22 12:29:21 +0100766 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100767 .Property("messaging-method", "<1>")
768 .Build();
769 /* clang-format on */
770 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
771 MANIFEST_ERROR_NOT_COMPATIBLE);
772
773 /* Incompatible exeption level */
774 /* clang-format off */
775 dtb = ManifestDtBuilder()
776 .Compatible({ "arm,ffa-manifest-1.0" })
777 .Property("ffa-version", "<0x10000>")
778 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
779 .Property("execution-ctx-count", "<1>")
780 .Property("exception-level", "<6>")
781 .Property("execution-state", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100782 .Property("entrypoint-offset", "<0x00001000>")
783 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100784 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100785 .Property("messaging-method", "<1>")
786 .Build();
787 /* clang-format on */
788 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
789 MANIFEST_ERROR_NOT_COMPATIBLE);
790
791 /* Incompatible execution state */
792 /* clang-format off */
793 dtb = ManifestDtBuilder()
794 .Compatible({ "arm,ffa-manifest-1.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", "<2>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100800 .Property("entrypoint-offset", "<0x00001000>")
801 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100802 .Property("boot-order", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100803 .Property("messaging-method", "<1>")
804 .Build();
805 /* clang-format on */
806 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
807 MANIFEST_ERROR_NOT_COMPATIBLE);
808
809 /* Incompatible messaging method */
810 /* clang-format off */
811 dtb = ManifestDtBuilder()
812 .Compatible({ "arm,ffa-manifest-1.0" })
813 .Property("ffa-version", "<0x10000>")
814 .Property("uuid", "<0xb4b5671e 0x4a904fe1 0xb81ffb13 0xdae1dacb>")
815 .Property("execution-ctx-count", "<1>")
816 .Property("exception-level", "<2>")
817 .Property("execution-state", "<0>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100818 .Property("entrypoint-offset", "<0x00001000>")
819 .Property("xlat-granule", "<0>")
J-Alvesb37fd082020-10-22 12:29:21 +0100820 .Property("boot-order", "<0>")
Maksims Svecovsb596eab2021-04-27 00:52:27 +0100821 .Property("messaging-method", "<16>")
Olivier Deprez62d99e32020-01-09 15:58:07 +0100822 .Build();
823 /* clang-format on */
824 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
825 MANIFEST_ERROR_NOT_COMPATIBLE);
826}
827
Manish Pandeyfa1f2912020-05-05 12:57:01 +0100828TEST(manifest, ffa_validate_rxtx_info)
829{
830 struct manifest m;
831
832 /* Not Compatible */
833 /* clang-format off */
834 std::vector<char> dtb = ManifestDtBuilder()
835 .FfaValidManifest()
836 .StartChild("rx_tx-info")
837 .Compatible({ "foo,bar" })
838 .EndChild()
839 .Build();
840 /* clang-format on */
841 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
842 MANIFEST_ERROR_NOT_COMPATIBLE);
843
844 /* Missing Properties */
845 /* clang-format off */
846 dtb = ManifestDtBuilder()
847 .FfaValidManifest()
848 .StartChild("rx_tx-info")
849 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
850 .EndChild()
851 .Build();
852 /* clang-format on */
853 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
854 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
855}
856
Manish Pandey6542f5c2020-04-27 14:37:46 +0100857TEST(manifest, ffa_validate_mem_regions)
858{
859 struct manifest m;
860
861 /* Not Compatible */
862 /* clang-format off */
863 std::vector<char> dtb = ManifestDtBuilder()
864 .FfaValidManifest()
865 .StartChild("memory-regions")
866 .Compatible({ "foo,bar" })
867 .EndChild()
868 .Build();
869 /* clang-format on */
870 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
871 MANIFEST_ERROR_NOT_COMPATIBLE);
872
873 /* Memory regions unavailable */
874 /* clang-format off */
875 dtb = ManifestDtBuilder()
876 .FfaValidManifest()
877 .StartChild("memory-regions")
878 .Compatible({ "arm,ffa-manifest-memory-regions" })
879 .EndChild()
880 .Build();
881 /* clang-format on */
882 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
883 MANIFEST_ERROR_MEMORY_REGION_NODE_EMPTY);
884
885 /* Missing Properties */
886 /* clang-format off */
887 dtb = ManifestDtBuilder()
888 .FfaValidManifest()
889 .StartChild("memory-regions")
890 .Compatible({ "arm,ffa-manifest-memory-regions" })
891 .StartChild("test-memory")
892 .Description("test-memory")
893 .EndChild()
894 .EndChild()
895 .Build();
896 /* clang-format on */
897 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
898 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
Manish Pandeyf06c9072020-09-29 15:41:58 +0100899
900 /* Different RXTX buffer sizes */
901 /* clang-format off */
902 dtb = ManifestDtBuilder()
903 .FfaValidManifest()
904 .StartChild("memory-regions")
905 .Compatible({ "arm,ffa-manifest-memory-regions" })
906 .Label("rx")
907 .StartChild("rx")
908 .Description("rx-buffer")
909 .Property("base-address", "<0x7300000>")
910 .Property("pages-count", "<1>")
911 .Property("attributes", "<1>")
912 .EndChild()
913 .Label("tx")
914 .StartChild("tx")
915 .Description("tx-buffer")
916 .Property("base-address", "<0x7310000>")
917 .Property("pages-count", "<2>")
918 .Property("attributes", "<3>")
919 .EndChild()
920 .EndChild()
921 .StartChild("rx_tx-info")
922 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
923 .Property("rx-buffer", "<&rx>")
924 .Property("tx-buffer", "<&tx>")
925 .EndChild()
926 .Build();
927 /* clang-format on */
928 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
929 MANIFEST_ERROR_RXTX_SIZE_MISMATCH);
Manish Pandey6542f5c2020-04-27 14:37:46 +0100930}
931
Manish Pandeye68e7932020-04-23 15:29:28 +0100932TEST(manifest, ffa_validate_dev_regions)
933{
934 struct manifest m;
935
936 /* Not Compatible */
937 /* clang-format off */
938 std::vector<char> dtb = ManifestDtBuilder()
939 .FfaValidManifest()
940 .StartChild("device-regions")
941 .Compatible({ "foo,bar" })
942 .EndChild()
943 .Build();
944 /* clang-format on */
945 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
946 MANIFEST_ERROR_NOT_COMPATIBLE);
947
948 /* Memory regions unavailable */
949 /* clang-format off */
950 dtb = ManifestDtBuilder()
951 .FfaValidManifest()
952 .StartChild("device-regions")
953 .Compatible({ "arm,ffa-manifest-device-regions" })
954 .EndChild()
955 .Build();
956 /* clang-format on */
957 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
958 MANIFEST_ERROR_DEVICE_REGION_NODE_EMPTY);
959
960 /* Missing Properties */
961 /* clang-format off */
962 dtb = ManifestDtBuilder()
963 .FfaValidManifest()
964 .StartChild("device-regions")
965 .Compatible({ "arm,ffa-manifest-device-regions" })
966 .StartChild("test-device")
967 .Description("test-device")
968 .EndChild()
969 .EndChild()
970 .Build();
971 /* clang-format on */
972 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
973 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
974
975 /* Malformed interrupt list pair */
976 /* clang-format off */
977 dtb = ManifestDtBuilder()
978 .FfaValidManifest()
979 .StartChild("device-regions")
980 .Compatible({ "arm,ffa-manifest-device-regions" })
981 .StartChild("test-device")
982 .Description("test-device")
983 .Property("base-address", "<0x7200000>")
984 .Property("pages-count", "<16>")
985 .Property("attributes", "<3>")
986 .Property("smmu-id", "<1>")
987 .Property("stream-ids", "<0 1>")
988 .Property("interrupts", "<2 3>, <4>")
989 .EndChild()
990 .EndChild()
991 .Build();
992 /* clang-format on */
993 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb),
994 MANIFEST_ERROR_MALFORMED_INTEGER_LIST);
995}
996
Olivier Deprez62d99e32020-01-09 15:58:07 +0100997TEST(manifest, ffa_valid)
998{
999 struct manifest m;
1000
1001 /* clang-format off */
1002 std::vector<char> dtb = ManifestDtBuilder()
Manish Pandeycb8fbb22020-08-18 00:04:43 +01001003 .FfaValidManifest()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001004 .StartChild("rx_tx-info")
1005 .Compatible({ "arm,ffa-manifest-rx_tx-buffer" })
1006 .Property("rx-buffer", "<&rx>")
1007 .Property("tx-buffer", "<&tx>")
1008 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001009 .StartChild("memory-regions")
1010 .Compatible({ "arm,ffa-manifest-memory-regions" })
1011 .StartChild("test-memory")
1012 .Description("test-memory")
1013 .Property("base-address", "<0x7100000>")
1014 .Property("pages-count", "<4>")
1015 .Property("attributes", "<7>")
1016 .EndChild()
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001017 .Label("rx")
1018 .StartChild("rx")
1019 .Description("rx-buffer")
1020 .Property("base-address", "<0x7300000>")
1021 .Property("pages-count", "<1>")
1022 .Property("attributes", "<1>")
1023 .EndChild()
1024 .Label("tx")
1025 .StartChild("tx")
1026 .Description("tx-buffer")
1027 .Property("base-address", "<0x7310000>")
1028 .Property("pages-count", "<1>")
1029 .Property("attributes", "<3>")
1030 .EndChild()
Manish Pandey6542f5c2020-04-27 14:37:46 +01001031 .EndChild()
Manish Pandeye68e7932020-04-23 15:29:28 +01001032 .StartChild("device-regions")
1033 .Compatible({ "arm,ffa-manifest-device-regions" })
1034 .StartChild("test-device")
1035 .Description("test-device")
1036 .Property("base-address", "<0x7200000>")
1037 .Property("pages-count", "<16>")
1038 .Property("attributes", "<3>")
1039 .Property("smmu-id", "<1>")
1040 .Property("stream-ids", "<0 1>")
1041 .Property("interrupts", "<2 3>, <4 5>")
1042 .EndChild()
1043 .EndChild()
Olivier Deprez62d99e32020-01-09 15:58:07 +01001044 .Build();
1045 /* clang-format on */
1046
1047 ASSERT_EQ(ffa_manifest_from_vec(&m, dtb), MANIFEST_SUCCESS);
1048
1049 ASSERT_EQ(m.vm[0].sp.ffa_version, 0x10000);
1050 ASSERT_THAT(
Fuad Tabbae4efcc32020-07-16 15:37:27 +01001051 std::span(m.vm[0].sp.uuid.uuid, 4),
Olivier Deprez62d99e32020-01-09 15:58:07 +01001052 ElementsAre(0xb4b5671e, 0x4a904fe1, 0xb81ffb13, 0xdae1dacb));
1053 ASSERT_EQ(m.vm[0].sp.execution_ctx_count, 1);
1054 ASSERT_EQ(m.vm[0].sp.run_time_el, S_EL1);
1055 ASSERT_EQ(m.vm[0].sp.execution_state, AARCH64);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001056 ASSERT_EQ(m.vm[0].sp.ep_offset, 0x00001000);
1057 ASSERT_EQ(m.vm[0].sp.xlat_granule, PAGE_4KB);
J-Alvesb37fd082020-10-22 12:29:21 +01001058 ASSERT_EQ(m.vm[0].sp.boot_order, 0);
Maksims Svecovsb596eab2021-04-27 00:52:27 +01001059 ASSERT_EQ(m.vm[0].sp.messaging_method, FFA_PARTITION_INDIRECT_MSG);
Manish Pandey6542f5c2020-04-27 14:37:46 +01001060 ASSERT_EQ(m.vm[0].sp.mem_regions[0].base_address, 0x7100000);
1061 ASSERT_EQ(m.vm[0].sp.mem_regions[0].page_count, 4);
1062 ASSERT_EQ(m.vm[0].sp.mem_regions[0].attributes, 7);
Manish Pandeyfa1f2912020-05-05 12:57:01 +01001063 ASSERT_EQ(m.vm[0].sp.rxtx.available, true);
1064 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->base_address, 0x7300000);
1065 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->page_count, 1);
1066 ASSERT_EQ(m.vm[0].sp.rxtx.rx_buffer->attributes, 1);
1067 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->base_address, 0x7310000);
1068 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->page_count, 1);
1069 ASSERT_EQ(m.vm[0].sp.rxtx.tx_buffer->attributes, 3);
Manish Pandeye68e7932020-04-23 15:29:28 +01001070 ASSERT_EQ(m.vm[0].sp.dev_regions[0].base_address, 0x7200000);
1071 ASSERT_EQ(m.vm[0].sp.dev_regions[0].page_count, 16);
1072 /* Attribute is ORed with MM_MODE_D */
1073 ASSERT_EQ(m.vm[0].sp.dev_regions[0].attributes, (3 | 8));
1074 ASSERT_EQ(m.vm[0].sp.dev_regions[0].smmu_id, 1);
1075 ASSERT_EQ(m.vm[0].sp.dev_regions[0].stream_ids[0], 0);
1076 ASSERT_EQ(m.vm[0].sp.dev_regions[0].stream_ids[1], 1);
1077 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[0].id, 2);
1078 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[0].attributes, 3);
1079 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[1].id, 4);
1080 ASSERT_EQ(m.vm[0].sp.dev_regions[0].interrupts[1].attributes, 5);
Olivier Deprez62d99e32020-01-09 15:58:07 +01001081}
1082
David Brazdil7a462ec2019-08-15 12:27:47 +01001083} /* namespace */