blob: 03b6a5653e9877344678ffab3b64641c3dadb11d [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 {
Andrew Scull5dc089e2019-11-04 13:21:03 +0000256 dts_ << name << ";" << std::endl;
257 return *this;
Andrew Scullae9962e2019-10-03 16:51:16 +0100258 }
259
David Brazdil52256ff2019-08-23 15:15:15 +0100260 std::stringstream dts_;
261};
262
David Brazdil0dbb41f2019-09-09 18:03:35 +0100263static bool get_fdt_root(const std::vector<char> &dtb,
264 struct fdt_node *fdt_root)
265{
266 const struct fdt_header *fdt_header;
267
268 fdt_header = reinterpret_cast<const struct fdt_header *>(dtb.data());
269 return fdt_root_node(fdt_root, fdt_header) &&
270 fdt_find_child(fdt_root, "");
271}
272
David Brazdil52256ff2019-08-23 15:15:15 +0100273TEST(manifest, no_hypervisor_node)
David Brazdil7a462ec2019-08-15 12:27:47 +0100274{
275 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100276 struct fdt_node fdt_root;
David Brazdil52256ff2019-08-23 15:15:15 +0100277 std::vector<char> dtb = ManifestDtBuilder().Build();
David Brazdil7a462ec2019-08-15 12:27:47 +0100278
David Brazdil0dbb41f2019-09-09 18:03:35 +0100279 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
280 ASSERT_EQ(manifest_init(&m, &fdt_root),
David Brazdil7a462ec2019-08-15 12:27:47 +0100281 MANIFEST_ERROR_NO_HYPERVISOR_FDT_NODE);
282}
283
David Brazdil74e9c3b2019-08-28 11:09:08 +0100284TEST(manifest, no_compatible_property)
David Brazdil7a462ec2019-08-15 12:27:47 +0100285{
286 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100287 struct fdt_node fdt_root;
David Brazdil7a462ec2019-08-15 12:27:47 +0100288
David Brazdil52256ff2019-08-23 15:15:15 +0100289 /* clang-format off */
290 std::vector<char> dtb = ManifestDtBuilder()
291 .StartChild("hypervisor")
292 .EndChild()
293 .Build();
294 /* clang-format on */
295
David Brazdil0dbb41f2019-09-09 18:03:35 +0100296 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
297 ASSERT_EQ(manifest_init(&m, &fdt_root),
298 MANIFEST_ERROR_PROPERTY_NOT_FOUND);
David Brazdil7a462ec2019-08-15 12:27:47 +0100299}
300
David Brazdil74e9c3b2019-08-28 11:09:08 +0100301TEST(manifest, not_compatible)
David Brazdil7a462ec2019-08-15 12:27:47 +0100302{
303 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100304 struct fdt_node fdt_root;
David Brazdil7a462ec2019-08-15 12:27:47 +0100305
David Brazdil52256ff2019-08-23 15:15:15 +0100306 /* clang-format off */
307 std::vector<char> dtb = ManifestDtBuilder()
308 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100309 .Compatible({ "foo,bar" })
310 .EndChild()
311 .Build();
312 /* clang-format on */
313
David Brazdil0dbb41f2019-09-09 18:03:35 +0100314 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
315 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_NOT_COMPATIBLE);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100316}
317
318TEST(manifest, compatible_one_of_many)
319{
320 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100321 struct fdt_node fdt_root;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100322
323 /* clang-format off */
324 std::vector<char> dtb = ManifestDtBuilder()
325 .StartChild("hypervisor")
326 .Compatible({ "foo,bar", "hafnium,hafnium" })
327 .StartChild("vm1")
328 .DebugName("primary")
329 .EndChild()
330 .EndChild()
331 .Build();
332 /* clang-format on */
333
David Brazdil0dbb41f2019-09-09 18:03:35 +0100334 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
335 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100336}
337
338TEST(manifest, no_vm_nodes)
339{
340 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100341 struct fdt_node fdt_root;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100342
343 /* clang-format off */
344 std::vector<char> dtb = ManifestDtBuilder()
345 .StartChild("hypervisor")
346 .Compatible()
347 .EndChild()
348 .Build();
349 /* clang-format on */
350
David Brazdil0dbb41f2019-09-09 18:03:35 +0100351 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
352 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_NO_PRIMARY_VM);
353}
354
355static std::vector<char> gen_long_string_dtb(bool valid)
356{
357 const char last_valid[] = "1234567890123456789012345678901";
358 const char first_invalid[] = "12345678901234567890123456789012";
David Brazdil136f2942019-09-23 14:11:03 +0100359 static_assert(sizeof(last_valid) == STRING_MAX_SIZE);
360 static_assert(sizeof(first_invalid) == STRING_MAX_SIZE + 1);
David Brazdil0dbb41f2019-09-09 18:03:35 +0100361
362 /* clang-format off */
363 return ManifestDtBuilder()
364 .StartChild("hypervisor")
365 .Compatible()
366 .StartChild("vm1")
367 .DebugName(valid ? last_valid : first_invalid)
368 .EndChild()
369 .EndChild()
370 .Build();
371 /* clang-format on */
372}
373
374TEST(manifest, long_string)
375{
376 struct manifest m;
377 struct fdt_node fdt_root;
378
379 std::vector<char> dtb_last_valid = gen_long_string_dtb(true);
380 std::vector<char> dtb_first_invalid = gen_long_string_dtb(false);
381
382 ASSERT_TRUE(get_fdt_root(dtb_last_valid, &fdt_root));
383 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
384
385 ASSERT_TRUE(get_fdt_root(dtb_first_invalid, &fdt_root));
386 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_STRING_TOO_LONG);
David Brazdil74e9c3b2019-08-28 11:09:08 +0100387}
388
389TEST(manifest, reserved_vm_id)
390{
391 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100392 struct fdt_node fdt_root;
David Brazdil74e9c3b2019-08-28 11:09:08 +0100393
394 /* clang-format off */
395 std::vector<char> dtb = ManifestDtBuilder()
396 .StartChild("hypervisor")
397 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100398 .StartChild("vm1")
399 .DebugName("primary_vm")
400 .EndChild()
401 .StartChild("vm0")
402 .DebugName("reserved_vm")
403 .VcpuCount(1)
404 .MemSize(0x1000)
405 .KernelFilename("kernel")
406 .EndChild()
407 .EndChild()
408 .Build();
409 /* clang-format on */
410
David Brazdil0dbb41f2019-09-09 18:03:35 +0100411 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
412 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_ERROR_RESERVED_VM_ID);
David Brazdil7a462ec2019-08-15 12:27:47 +0100413}
414
Andrew Scullae9962e2019-10-03 16:51:16 +0100415static std::vector<char> gen_vcpu_count_limit_dtb(uint32_t vcpu_count)
David Brazdil52256ff2019-08-23 15:15:15 +0100416{
417 /* clang-format off */
418 return ManifestDtBuilder()
419 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100420 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100421 .StartChild("vm1")
422 .DebugName("primary_vm")
423 .EndChild()
424 .StartChild("vm2")
425 .DebugName("secondary_vm")
426 .VcpuCount(vcpu_count)
427 .MemSize(0x1000)
428 .KernelFilename("kernel")
429 .EndChild()
430 .EndChild()
431 .Build();
432 /* clang-format on */
433}
David Brazdil7a462ec2019-08-15 12:27:47 +0100434
435TEST(manifest, vcpu_count_limit)
436{
437 struct manifest m;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100438 struct fdt_node fdt_root;
David Brazdil52256ff2019-08-23 15:15:15 +0100439 std::vector<char> dtb_last_valid = gen_vcpu_count_limit_dtb(UINT16_MAX);
440 std::vector<char> dtb_first_invalid =
441 gen_vcpu_count_limit_dtb(UINT16_MAX + 1);
David Brazdil7a462ec2019-08-15 12:27:47 +0100442
David Brazdil0dbb41f2019-09-09 18:03:35 +0100443 ASSERT_TRUE(get_fdt_root(dtb_last_valid, &fdt_root));
444 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100445 ASSERT_EQ(m.vm_count, 2);
David Brazdil7a462ec2019-08-15 12:27:47 +0100446 ASSERT_EQ(m.vm[1].secondary.vcpu_count, UINT16_MAX);
447
David Brazdil0dbb41f2019-09-09 18:03:35 +0100448 ASSERT_TRUE(get_fdt_root(dtb_first_invalid, &fdt_root));
449 ASSERT_EQ(manifest_init(&m, &fdt_root),
450 MANIFEST_ERROR_INTEGER_OVERFLOW);
David Brazdil7a462ec2019-08-15 12:27:47 +0100451}
452
David Brazdile6f83222019-09-23 14:47:37 +0100453TEST(manifest, no_ramdisk_primary)
454{
455 struct manifest m;
456 struct fdt_node fdt_root;
457
458 /* clang-format off */
459 std::vector<char> dtb = ManifestDtBuilder()
460 .StartChild("hypervisor")
461 .Compatible()
462 .StartChild("vm1")
463 .DebugName("primary_vm")
464 .EndChild()
465 .EndChild()
466 .Build();
467 /* clang-format on */
468
469 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
470 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
471 ASSERT_EQ(m.vm_count, 1);
472 ASSERT_STREQ(string_data(&m.vm[0].debug_name), "primary_vm");
473 ASSERT_STREQ(string_data(&m.vm[0].primary.ramdisk_filename), "");
474}
475
Andrew Scull5dc089e2019-11-04 13:21:03 +0000476TEST(manifest, true_booleans_with_values)
Andrew Scullae9962e2019-10-03 16:51:16 +0100477{
478 struct manifest m;
Andrew Scullae9962e2019-10-03 16:51:16 +0100479 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()
Andrew Scull5dc089e2019-11-04 13:21:03 +0000501 .StartChild("vm4")
502 .DebugName("tertiary_secondary_vm")
503 .VcpuCount(44)
504 .MemSize(0x55)
505 .Property("smc_whitelist_permissive", "<1>")
506 .EndChild()
Andrew Scullae9962e2019-10-03 16:51:16 +0100507 .EndChild()
508 .Build();
509 /* clang-format on */
510
511 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
512
513 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
Andrew Scull5dc089e2019-11-04 13:21:03 +0000514 ASSERT_EQ(m.vm_count, 4);
Andrew Scullae9962e2019-10-03 16:51:16 +0100515
Andrew Scull5dc089e2019-11-04 13:21:03 +0000516 ASSERT_TRUE(m.vm[0].smc_whitelist.permissive);
517 ASSERT_TRUE(m.vm[1].smc_whitelist.permissive);
518 ASSERT_TRUE(m.vm[2].smc_whitelist.permissive);
519 ASSERT_TRUE(m.vm[3].smc_whitelist.permissive);
Andrew Scullae9962e2019-10-03 16:51:16 +0100520}
521
David Brazdil7a462ec2019-08-15 12:27:47 +0100522TEST(manifest, valid)
523{
524 struct manifest m;
525 struct manifest_vm *vm;
David Brazdil0dbb41f2019-09-09 18:03:35 +0100526 struct fdt_node fdt_root;
David Brazdil7a462ec2019-08-15 12:27:47 +0100527
David Brazdil52256ff2019-08-23 15:15:15 +0100528 /* clang-format off */
529 std::vector<char> dtb = ManifestDtBuilder()
530 .StartChild("hypervisor")
David Brazdil74e9c3b2019-08-28 11:09:08 +0100531 .Compatible()
David Brazdil52256ff2019-08-23 15:15:15 +0100532 .StartChild("vm1")
533 .DebugName("primary_vm")
Andrew Scull72b43c02019-09-18 13:53:45 +0100534 .KernelFilename("primary_kernel")
David Brazdile6f83222019-09-23 14:47:37 +0100535 .RamdiskFilename("primary_ramdisk")
Andrew Scullae9962e2019-10-03 16:51:16 +0100536 .SmcWhitelist({0x32000000, 0x33001111})
David Brazdil52256ff2019-08-23 15:15:15 +0100537 .EndChild()
538 .StartChild("vm3")
539 .DebugName("second_secondary_vm")
540 .VcpuCount(43)
541 .MemSize(0x12345)
Andrew Scull72b43c02019-09-18 13:53:45 +0100542 .KernelFilename("second_secondary_kernel")
David Brazdil52256ff2019-08-23 15:15:15 +0100543 .EndChild()
544 .StartChild("vm2")
545 .DebugName("first_secondary_vm")
546 .VcpuCount(42)
547 .MemSize(12345)
Andrew Scullae9962e2019-10-03 16:51:16 +0100548 .SmcWhitelist({0x04000000, 0x30002222, 0x31445566})
549 .SmcWhitelistPermissive()
David Brazdil52256ff2019-08-23 15:15:15 +0100550 .EndChild()
551 .EndChild()
552 .Build();
553 /* clang-format on */
554
David Brazdil0dbb41f2019-09-09 18:03:35 +0100555 ASSERT_TRUE(get_fdt_root(dtb, &fdt_root));
David Brazdil7a462ec2019-08-15 12:27:47 +0100556
David Brazdil0dbb41f2019-09-09 18:03:35 +0100557 ASSERT_EQ(manifest_init(&m, &fdt_root), MANIFEST_SUCCESS);
David Brazdil0251b942019-09-10 15:59:50 +0100558 ASSERT_EQ(m.vm_count, 3);
David Brazdil7a462ec2019-08-15 12:27:47 +0100559
560 vm = &m.vm[0];
David Brazdil136f2942019-09-23 14:11:03 +0100561 ASSERT_STREQ(string_data(&vm->debug_name), "primary_vm");
562 ASSERT_STREQ(string_data(&vm->kernel_filename), "primary_kernel");
David Brazdile6f83222019-09-23 14:47:37 +0100563 ASSERT_STREQ(string_data(&vm->primary.ramdisk_filename),
564 "primary_ramdisk");
Andrew Scullae9962e2019-10-03 16:51:16 +0100565 ASSERT_THAT(
566 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
567 ElementsAre(0x32000000, 0x33001111));
568 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100569
570 vm = &m.vm[1];
David Brazdil136f2942019-09-23 14:11:03 +0100571 ASSERT_STREQ(string_data(&vm->debug_name), "first_secondary_vm");
572 ASSERT_STREQ(string_data(&vm->kernel_filename), "");
David Brazdil7a462ec2019-08-15 12:27:47 +0100573 ASSERT_EQ(vm->secondary.vcpu_count, 42);
574 ASSERT_EQ(vm->secondary.mem_size, 12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100575 ASSERT_THAT(
576 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
577 ElementsAre(0x04000000, 0x30002222, 0x31445566));
578 ASSERT_TRUE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100579
580 vm = &m.vm[2];
David Brazdil136f2942019-09-23 14:11:03 +0100581 ASSERT_STREQ(string_data(&vm->debug_name), "second_secondary_vm");
582 ASSERT_STREQ(string_data(&vm->kernel_filename),
583 "second_secondary_kernel");
David Brazdil7a462ec2019-08-15 12:27:47 +0100584 ASSERT_EQ(vm->secondary.vcpu_count, 43);
585 ASSERT_EQ(vm->secondary.mem_size, 0x12345);
Andrew Scullae9962e2019-10-03 16:51:16 +0100586 ASSERT_THAT(
587 std::span(vm->smc_whitelist.smcs, vm->smc_whitelist.smc_count),
588 IsEmpty());
589 ASSERT_FALSE(vm->smc_whitelist.permissive);
David Brazdil7a462ec2019-08-15 12:27:47 +0100590}
591
592} /* namespace */