blob: ec38a56f7f549938fd794903ab7bfd97692d7bcf [file] [log] [blame]
David Brazdil7a462ec2019-08-15 12:27:47 +01001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
David Brazdil52256ff2019-08-23 15:15:15 +010017#include <array>
18#include <cstdio>
Andrew Scullae9962e2019-10-03 16:51:16 +010019#include <span>
David Brazdil52256ff2019-08-23 15:15:15 +010020#include <sstream>
21
David Brazdil7a462ec2019-08-15 12:27:47 +010022#include <gmock/gmock.h>
23
24extern "C" {
25#include "hf/manifest.h"
26}
27
28namespace
29{
Andrew Scullae9962e2019-10-03 16:51:16 +010030using ::testing::ElementsAre;
David Brazdil7a462ec2019-08-15 12:27:47 +010031using ::testing::Eq;
Andrew Scullae9962e2019-10-03 16:51:16 +010032using ::testing::IsEmpty;
David Brazdil7a462ec2019-08-15 12:27:47 +010033using ::testing::NotNull;
34
David Brazdil52256ff2019-08-23 15:15:15 +010035template <typename T>
David Brazdil0dbb41f2019-09-09 18:03:35 +010036void exec(const char *program, const char *args[], const T &stdin,
David Brazdil52256ff2019-08-23 15:15:15 +010037 std::vector<char> *stdout)
38{
39 /* Create two pipes, one for stdin and one for stdout. */
40 int pipes[2][2];
41 pipe(pipes[0]);
42 pipe(pipes[1]);
David Brazdil7a462ec2019-08-15 12:27:47 +010043
David Brazdil52256ff2019-08-23 15:15:15 +010044 /* Assign FDs for reading/writing by the parent/child. */
45 int parent_read_fd = pipes[1][0]; /* stdout pipe, read FD */
46 int parent_write_fd = pipes[0][1]; /* stdin pipe, write FD */
47 int child_read_fd = pipes[0][0]; /* stdin pipe, read FD */
48 int child_write_fd = pipes[1][1]; /* stdout pipe, write FD */
David Brazdil7a462ec2019-08-15 12:27:47 +010049
David Brazdil52256ff2019-08-23 15:15:15 +010050 if (fork()) {
51 /* Parent process. */
52 std::array<char, 128> buf;
53 ssize_t res;
54
55 /* Close child FDs which won't be used. */
56 close(child_read_fd);
57 close(child_write_fd);
58
59 /* Write to stdin. */
60 for (size_t count = 0; count < stdin.size();) {
61 res = write(parent_write_fd, stdin.data() + count,
62 stdin.size() - count);
63 if (res < 0) {
64 std::cerr << "IO error" << std::endl;
65 exit(1);
66 }
67 count += res;
68 }
69 close(parent_write_fd);
70
71 /* Read from stdout. */
72 while (true) {
73 res = read(parent_read_fd, buf.data(), buf.size());
74 if (res == 0) {
75 /* EOF */
76 break;
77 } else if (res < 0) {
78 std::cerr << "IO error" << std::endl;
79 exit(1);
80 }
81 stdout->insert(stdout->end(), buf.begin(),
82 buf.begin() + res);
83 }
84 close(parent_read_fd);
85 } else {
86 /* Child process. */
87
88 /* Redirect stdin/stdout to read/write FDs. */
89 dup2(child_read_fd, STDIN_FILENO);
90 dup2(child_write_fd, STDOUT_FILENO);
91
92 /* Close all FDs which are now unused. */
93 close(child_read_fd);
94 close(child_write_fd);
95 close(parent_read_fd);
96 close(parent_write_fd);
97
98 /* Execute the given program. */
David Brazdil0dbb41f2019-09-09 18:03:35 +010099 execv(program, const_cast<char *const *>(args));
David Brazdil52256ff2019-08-23 15:15:15 +0100100 }
101}
102
103/**
104 * Class for programatically building a Device Tree.
105 *
106 * Usage:
107 * std::vector<char> dtb = ManifestDtBuilder()
108 * .Command1()
109 * .Command2()
110 * ...
111 * .CommandN()
112 * .Build();
113 */
114class ManifestDtBuilder
115{
116 public:
117 ManifestDtBuilder()
118 {
119 dts_ << "/dts-v1/;" << std::endl;
120 dts_ << std::endl;
121
122 /* Start root node. */
123 StartChild("/");
124 }
125
Andrew Scullae9962e2019-10-03 16:51:16 +0100126 std::vector<char> Build(bool dump = false)
David Brazdil52256ff2019-08-23 15:15:15 +0100127 {
David Brazdil0dbb41f2019-09-09 18:03:35 +0100128 const char *program = "./build/image/dtc.py";
129 const char *dtc_args[] = {program, "compile", NULL};
David Brazdil52256ff2019-08-23 15:15:15 +0100130 std::vector<char> dtc_stdout;
131
132 /* Finish root node. */
133 EndChild();
134
Andrew Scullae9962e2019-10-03 16:51:16 +0100135 if (dump) {
136 Dump();
137 }
138
David Brazdil0dbb41f2019-09-09 18:03:35 +0100139 exec(program, dtc_args, dts_.str(), &dtc_stdout);
David Brazdil52256ff2019-08-23 15:15:15 +0100140 return dtc_stdout;
141 }
142
Andrew Scullae9962e2019-10-03 16:51:16 +0100143 void Dump()
144 {
145 std::cerr << dts_.str() << std::endl;
146 }
147
David Brazdil52256ff2019-08-23 15:15:15 +0100148 ManifestDtBuilder &StartChild(const std::string_view &name)
149 {
150 dts_ << name << " {" << std::endl;
151 return *this;
152 }
153
154 ManifestDtBuilder &EndChild()
155 {
156 dts_ << "};" << std::endl;
157 return *this;
158 }
159
David Brazdil74e9c3b2019-08-28 11:09:08 +0100160 ManifestDtBuilder &Compatible(const std::vector<std::string_view>
161 &value = {"hafnium,hafnium"})
162 {
163 return StringListProperty("compatible", value);
164 }
165
David Brazdil52256ff2019-08-23 15:15:15 +0100166 ManifestDtBuilder &DebugName(const std::string_view &value)
167 {
168 return StringProperty("debug_name", value);
169 }
170
171 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
Andrew Scullae9962e2019-10-03 16:51:16 +0100181 ManifestDtBuilder &VcpuCount(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100182 {
183 return IntegerProperty("vcpu_count", value);
184 }
185
Andrew Scullae9962e2019-10-03 16:51:16 +0100186 ManifestDtBuilder &MemSize(uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100187 {
188 return IntegerProperty("mem_size", value);
189 }
190
Andrew Scullae9962e2019-10-03 16:51:16 +0100191 ManifestDtBuilder &SmcWhitelist(const std::vector<uint32_t> &value)
192 {
193 return IntegerListProperty("smc_whitelist", value);
194 }
195
196 ManifestDtBuilder &SmcWhitelistPermissive()
197 {
198 return BooleanProperty("smc_whitelist_permissive");
199 }
200
201 ManifestDtBuilder &Property(const std::string_view &name,
202 const std::string_view &value)
203 {
204 dts_ << name << " = " << value << ";" << std::endl;
205 return *this;
206 }
207
David Brazdil52256ff2019-08-23 15:15:15 +0100208 private:
209 ManifestDtBuilder &StringProperty(const std::string_view &name,
210 const std::string_view &value)
211 {
212 dts_ << name << " = \"" << value << "\";" << std::endl;
213 return *this;
214 }
215
David Brazdil74e9c3b2019-08-28 11:09:08 +0100216 ManifestDtBuilder &StringListProperty(
217 const std::string_view &name,
218 const std::vector<std::string_view> &value)
219 {
220 bool is_first = true;
221
222 dts_ << name << " = ";
223 for (const std::string_view &entry : value) {
224 if (is_first) {
225 is_first = false;
226 } else {
227 dts_ << ", ";
228 }
229 dts_ << "\"" << entry << "\"";
230 }
231 dts_ << ";" << std::endl;
232 return *this;
233 }
234
David Brazdil52256ff2019-08-23 15:15:15 +0100235 ManifestDtBuilder &IntegerProperty(const std::string_view &name,
Andrew Scullae9962e2019-10-03 16:51:16 +0100236 uint32_t value)
David Brazdil52256ff2019-08-23 15:15:15 +0100237 {
238 dts_ << name << " = <" << value << ">;" << std::endl;
239 return *this;
240 }
241
Andrew Scullae9962e2019-10-03 16:51:16 +0100242 ManifestDtBuilder &IntegerListProperty(
243 const std::string_view &name,
244 const std::vector<uint32_t> &value)
245 {
246 dts_ << name << " = < ";
247 for (const uint32_t entry : value) {
248 dts_ << entry << " ";
249 }
250 dts_ << ">;" << std::endl;
251 return *this;
252 }
253
254 ManifestDtBuilder &BooleanProperty(const std::string_view &name)
255 {
256 return IntegerProperty(name, 1);
257 }
258
David Brazdil52256ff2019-08-23 15:15:15 +0100259 std::stringstream dts_;
260};
261
David Brazdil0dbb41f2019-09-09 18:03:35 +0100262static bool get_fdt_root(const std::vector<char> &dtb,
263 struct fdt_node *fdt_root)
264{
265 const struct fdt_header *fdt_header;
266
267 fdt_header = reinterpret_cast<const struct fdt_header *>(dtb.data());
268 return fdt_root_node(fdt_root, fdt_header) &&
269 fdt_find_child(fdt_root, "");
270}
271
David Brazdil52256ff2019-08-23 15:15:15 +0100272TEST(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100273{
274 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100275 struct fdt_node fdt_root;
David Brazdil52256ff2019-08-23 15:15:15 +0100276 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100277
David Brazdil0dbb41f2019-09-09 18:03:35 +0100278 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
279 ASSERT_EQ(manifest_init(&m, &fdt_root),
David Brazdil7a462ec2019-08-15 12:27:47 +0100280 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
281}
282
David Brazdil74e9c3b2019-08-28 11:09:08 +0100283TEST(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100284{
285 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100286 struct fdt_node fdt_root;
David Brazdil7a462ec2019-08-15 12:27:47 +0100287
David Brazdil52256ff2019-08-23 15:15:15 +0100288 /* clang-format off */
289 std::vector<char> dtb = ManifestDtBuilder()
290 .StartChild("hypervisor")
291 .EndChild()
292 .Build();
293 /* clang-format on */
294
David Brazdil0dbb41f2019-09-09 18:03:35 +0100295 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
296 ASSERT_EQ(manifest_init(&m, &fdt_root),
297 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
David Brazdil7a462ec2019-08-15 12:27:47 +0100298}
299
David Brazdil74e9c3b2019-08-28 11:09:08 +0100300TEST(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100301{
302 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100303 struct fdt_node fdt_root;
David Brazdil7a462ec2019-08-15 12:27:47 +0100304
David Brazdil52256ff2019-08-23 15:15:15 +0100305 /* clang-format off */
306 std::vector<char> dtb = ManifestDtBuilder()
307 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100308 .Compatible({ "foo,bar" })
309 .EndChild()
310 .Build();
311 /* clang-format on */
312
David Brazdil0dbb41f2019-09-09 18:03:35 +0100313 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
314 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100315}
316
317TEST(manifest, compatible_one_of_many)
318{
319 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100320 struct fdt_node fdt_root;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100321
322 /* clang-format off */
323 std::vector<char> dtb = ManifestDtBuilder()
324 .StartChild("hypervisor")
325 .Compatible({ "foo,bar", "hafnium,hafnium" })
326 .StartChild("vm1")
327 .DebugName("primary")
328 .EndChild()
329 .EndChild()
330 .Build();
331 /* clang-format on */
332
David Brazdil0dbb41f2019-09-09 18:03:35 +0100333 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
334 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100335}
336
337TEST(manifest, no_vm_nodes)
338{
339 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100340 struct fdt_node fdt_root;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100341
342 /* clang-format off */
343 std::vector<char> dtb = ManifestDtBuilder()
344 .StartChild("hypervisor")
345 .Compatible()
346 .EndChild()
347 .Build();
348 /* clang-format on */
349
David Brazdil0dbb41f2019-09-09 18:03:35 +0100350 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
351 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_NO_PRIMARY_VM);
352}
353
354static std::vector<char> gen_long_string_dtb(bool valid)
355{
356 const char last_valid[] = "1234567890123456789012345678901";
357 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100358 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
359 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100360
361 /* clang-format off */
362 return ManifestDtBuilder()
363 .StartChild("hypervisor")
364 .Compatible()
365 .StartChild("vm1")
366 .DebugName(valid ? last_valid : first_invalid)
367 .EndChild()
368 .EndChild()
369 .Build();
370 /* clang-format on */
371}
372
373TEST(manifest, long_string)
374{
375 struct manifest m;
376 struct fdt_node fdt_root;
377
378 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
379 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
380
381 ASSERT_TRUE(get_fdt_root(dtb_last_valid, &fdt_root));
382 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
383
384 ASSERT_TRUE(get_fdt_root(dtb_first_invalid, &fdt_root));
385 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100386}
387
388TEST(manifest, reserved_vm_id)
389{
390 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100391 struct fdt_node fdt_root;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100392
393 /* clang-format off */
394 std::vector<char> dtb = ManifestDtBuilder()
395 .StartChild("hypervisor")
396 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100397 .StartChild("vm1")
398 .DebugName("primary_vm")
399 .EndChild()
400 .StartChild("vm0")
401 .DebugName("reserved_vm")
402 .VcpuCount(1)
403 .MemSize(0x1000)
404 .KernelFilename("kernel")
405 .EndChild()
406 .EndChild()
407 .Build();
408 /* clang-format on */
409
David Brazdil0dbb41f2019-09-09 18:03:35 +0100410 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
411 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100412}
413
Andrew Scullae9962e2019-10-03 16:51:16 +0100414static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100415{
416 /* clang-format off */
417 return ManifestDtBuilder()
418 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100419 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100420 .StartChild("vm1")
421 .DebugName("primary_vm")
422 .EndChild()
423 .StartChild("vm2")
424 .DebugName("secondary_vm")
425 .VcpuCount(vcpu_count)
426 .MemSize(0x1000)
427 .KernelFilename("kernel")
428 .EndChild()
429 .EndChild()
430 .Build();
431 /* clang-format on */
432}
David Brazdil7a462ec2019-08-15 12:27:47 +0100433
434TEST(manifest, vcpu_count_limit)
435{
436 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100437 struct fdt_node fdt_root;
David Brazdil52256ff2019-08-23 15:15:15 +0100438 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
439 std::vector<char> dtb_first_invalid =
440 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100441
David Brazdil0dbb41f2019-09-09 18:03:35 +0100442 ASSERT_TRUE(get_fdt_root(dtb_last_valid, &fdt_root));
443 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100444 ASSERT_EQ(m.vm_count, 2);
David Brazdil7a462ec2019-08-15 12:27:47 +0100445 ASSERT_EQ(m.vm[1].secondary.vcpu_count, UINT16_MAX);
446
David Brazdil0dbb41f2019-09-09 18:03:35 +0100447 ASSERT_TRUE(get_fdt_root(dtb_first_invalid, &fdt_root));
448 ASSERT_EQ(manifest_init(&m, &fdt_root),
449 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100450}
451
David Brazdile6f83222019-09-23 14:47:37 +0100452TEST(manifest, no_ramdisk_primary)
453{
454 struct manifest m;
455 struct fdt_node fdt_root;
456
457 /* clang-format off */
458 std::vector<char> dtb = ManifestDtBuilder()
459 .StartChild("hypervisor")
460 .Compatible()
461 .StartChild("vm1")
462 .DebugName("primary_vm")
463 .EndChild()
464 .EndChild()
465 .Build();
466 /* clang-format on */
467
468 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
469 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
470 ASSERT_EQ(m.vm_count, 1);
471 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
472 ASSERT_STREQ(string_data(&m.vm[0].primary.ramdisk_filename), "");
473}
474
Andrew Scullae9962e2019-10-03 16:51:16 +0100475TEST(manifest, valid_true_booleans)
476{
477 struct manifest m;
478 struct manifest_vm *vm;
479 struct fdt_node fdt_root;
480
481 /* clang-format off */
482 std::vector<char> dtb = ManifestDtBuilder()
483 .StartChild("hypervisor")
484 .Compatible()
485 .StartChild("vm1")
486 .DebugName("primary_vm")
487 .Property("smc_whitelist_permissive", "\"false\"")
488 .EndChild()
489 .StartChild("vm2")
490 .DebugName("first_secondary_vm")
491 .VcpuCount(42)
492 .MemSize(12345)
493 .Property("smc_whitelist_permissive", "<0>")
494 .EndChild()
495 .StartChild("vm3")
496 .DebugName("second_secondary_vm")
497 .VcpuCount(43)
498 .MemSize(0x12345)
499 .Property("smc_whitelist_permissive", "\"true\"")
500 .EndChild()
501 .EndChild()
502 .Build();
503 /* clang-format on */
504
505 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
506
507 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
508 ASSERT_EQ(m.vm_count, 3);
509
510 vm = &m.vm[0];
511 ASSERT_TRUE(vm->smc_whitelist.permissive);
512
513 vm = &m.vm[1];
514 ASSERT_TRUE(vm->smc_whitelist.permissive);
515
516 vm = &m.vm[2];
517 ASSERT_TRUE(vm->smc_whitelist.permissive);
518}
519
David Brazdil7a462ec2019-08-15 12:27:47 +0100520TEST(manifest, valid)
521{
522 struct manifest m;
523 struct manifest_vm *vm;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100524 struct fdt_node fdt_root;
David Brazdil7a462ec2019-08-15 12:27:47 +0100525
David Brazdil52256ff2019-08-23 15:15:15 +0100526 /* clang-format off */
527 std::vector<char> dtb = ManifestDtBuilder()
528 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100529 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100530 .StartChild("vm1")
531 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100532 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100533 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100534 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100535 .EndChild()
536 .StartChild("vm3")
537 .DebugName("second_secondary_vm")
538 .VcpuCount(43)
539 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100540 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100541 .EndChild()
542 .StartChild("vm2")
543 .DebugName("first_secondary_vm")
544 .VcpuCount(42)
545 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100546 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
547 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100548 .EndChild()
549 .EndChild()
550 .Build();
551 /* clang-format on */
552
David Brazdil0dbb41f2019-09-09 18:03:35 +0100553 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
David Brazdil7a462ec2019-08-15 12:27:47 +0100554
David Brazdil0dbb41f2019-09-09 18:03:35 +0100555 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100556 ASSERT_EQ(m.vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100557
558 vm = &m.vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100559 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
560 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100561 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
562 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100563 ASSERT_THAT(
564 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
565 ElementsAre(0x32000000, 0x33001111));
566 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100567
568 vm = &m.vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100569 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
570 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100571 ASSERT_EQ(vm->secondary.vcpu_count, 42);
572 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100573 ASSERT_THAT(
574 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
575 ElementsAre(0x04000000, 0x30002222, 0x31445566));
576 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100577
578 vm = &m.vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100579 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
580 ASSERT_STREQ(string_data(&vm->kernel_filename),
581 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100582 ASSERT_EQ(vm->secondary.vcpu_count, 43);
583 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100584 ASSERT_THAT(
585 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
586 IsEmpty());
587 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100588}
589
590} /* namespace */