Skip to main content

flowey_lib_hvlite/
init_openvmm_magicpath_openvmm_deps.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Copy openvmm-deps files (linux test kernel, initrd, petritools erofs, etc.)
5//! into the correct "magic directory" set by the project-level `[env]` table
6//! in `.cargo/config.toml`.
7//!
8//! To add a new dep file, add an entry to `dep_files` — no other modules
9//! need to change.
10
11use crate::common::CommonArch;
12use flowey::node::prelude::*;
13use std::collections::BTreeMap;
14
15new_flow_node!(struct Node);
16
17fn dir_name(arch: CommonArch) -> &'static str {
18    match arch {
19        CommonArch::Aarch64 => "aarch64",
20        CommonArch::X86_64 => "x64",
21    }
22}
23
24flowey_request! {
25    pub struct Request {
26        pub arch: CommonArch,
27        pub done: WriteVar<SideEffect>,
28    }
29}
30
31/// A single file to copy from openvmm-deps into the magicpath.
32struct DepFile {
33    /// Which dep file to resolve from openvmm-deps.
34    dep: crate::resolve_openvmm_deps::OpenvmmDepFile,
35    /// Destination filename (relative to `underhill-deps-private/{arch}/`).
36    /// When arch-dependent, use a closure; when fixed, the `_arch` is ignored.
37    dest_filename: fn(CommonArch) -> &'static str,
38}
39
40/// The table of dep files to copy from the main openvmm-deps archive. To
41/// add a new dep, add an entry here.
42///
43/// The Linux test kernel and matching shared initrd are *not* in this table —
44/// the kernel comes from per-(arch, kver) archives via
45/// [`crate::resolve_openvmm_test_linux_kernel`], the initrd from the shared
46/// [`crate::resolve_openvmm_test_initrd`] node, and both are placed into the
47/// magicpath separately below.
48fn dep_files() -> Vec<DepFile> {
49    use crate::resolve_openvmm_deps::OpenvmmDepFile;
50    vec![DepFile {
51        dep: OpenvmmDepFile::PetritoolsErofs,
52        dest_filename: |_arch| "petritools.erofs",
53    }]
54}
55
56impl FlowNode for Node {
57    type Request = Request;
58
59    fn imports(ctx: &mut ImportCtx<'_>) {
60        ctx.import::<crate::cfg_openvmm_magicpath::Node>();
61        ctx.import::<crate::resolve_openvmm_deps::Node>();
62        ctx.import::<crate::resolve_openvmm_test_initrd::Node>();
63        ctx.import::<crate::resolve_openvmm_test_linux_kernel::Node>();
64    }
65
66    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
67        let mut by_arch: BTreeMap<CommonArch, Vec<WriteVar<SideEffect>>> = BTreeMap::new();
68        for Request { arch, done } in requests {
69            by_arch.entry(arch).or_default().push(done);
70        }
71
72        // -- end of req processing -- //
73
74        let openvmm_magicpath = ctx.reqv(crate::cfg_openvmm_magicpath::Request);
75
76        for (arch, out_vars) in by_arch {
77            // Resolve all dep files for this arch.
78            let mut resolved: Vec<(ReadVar<PathBuf>, &'static str)> = dep_files()
79                .into_iter()
80                .map(|dep_file| {
81                    let src = ctx
82                        .reqv(|v| crate::resolve_openvmm_deps::Request::Get(dep_file.dep, arch, v));
83                    let dst_name = (dep_file.dest_filename)(arch);
84                    (src, dst_name)
85                })
86                .collect();
87
88            // Resolve the Linux test kernel for this arch from the per-(arch,
89            // kver) `openvmm-test-linux` archive, and the matching guest-
90            // userland initrd from the version-independent
91            // `openvmm-test-initrd` archive.
92            use crate::resolve_openvmm_test_linux_kernel::DEFAULT_LINUX_TEST_KERNEL_VERSION as KVER;
93            use crate::resolve_openvmm_test_linux_kernel::OpenvmmTestKernelFile;
94            let kernel_src = ctx.reqv(|v| {
95                crate::resolve_openvmm_test_linux_kernel::Request::Get(
96                    OpenvmmTestKernelFile::Kernel,
97                    arch,
98                    KVER,
99                    v,
100                )
101            });
102            let kernel_dst_name = OpenvmmTestKernelFile::Kernel.filename(arch);
103            resolved.push((kernel_src, kernel_dst_name));
104            if OpenvmmTestKernelFile::BzImage.is_available_for(arch) {
105                let bzimage_src = ctx.reqv(|v| {
106                    crate::resolve_openvmm_test_linux_kernel::Request::Get(
107                        OpenvmmTestKernelFile::BzImage,
108                        arch,
109                        KVER,
110                        v,
111                    )
112                });
113                resolved.push((bzimage_src, OpenvmmTestKernelFile::BzImage.filename(arch)));
114            }
115            let initrd_src =
116                ctx.reqv(|v| crate::resolve_openvmm_test_initrd::Request::Get(arch, v));
117            resolved.push((initrd_src, "initrd"));
118
119            ctx.emit_rust_step(
120                format!("copy {arch:?} openvmm-deps files to magicpath"),
121                |ctx| {
122                    let resolved: Vec<_> = resolved
123                        .into_iter()
124                        .map(|(src, name)| (src.claim(ctx), name))
125                        .collect();
126                    let openvmm_magicpath = openvmm_magicpath.clone().claim(ctx);
127                    out_vars.claim(ctx);
128
129                    move |rt| {
130                        let magicpath = rt.read(openvmm_magicpath);
131                        let dst_dir = magicpath
132                            .join("underhill-deps-private")
133                            .join(dir_name(arch));
134                        fs_err::create_dir_all(&dst_dir)?;
135
136                        for (src, filename) in resolved {
137                            let src = rt.read(src);
138                            let dst = dst_dir.join(filename);
139                            if src.absolute()? != dst.absolute()? {
140                                fs_err::copy(&src, &dst)?;
141                            }
142                        }
143
144                        Ok(())
145                    }
146                },
147            );
148        }
149
150        Ok(())
151    }
152}