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. To add a new dep, add an entry here.
41fn dep_files() -> Vec<DepFile> {
42    use crate::resolve_openvmm_deps::OpenvmmDepFile;
43    vec![
44        DepFile {
45            dep: OpenvmmDepFile::LinuxTestKernel,
46            dest_filename: |arch| match arch {
47                CommonArch::Aarch64 => "Image",
48                CommonArch::X86_64 => "vmlinux",
49            },
50        },
51        DepFile {
52            dep: OpenvmmDepFile::LinuxTestInitrd,
53            dest_filename: |_arch| "initrd",
54        },
55        DepFile {
56            dep: OpenvmmDepFile::PetritoolsErofs,
57            dest_filename: |_arch| "petritools.erofs",
58        },
59    ]
60}
61
62impl FlowNode for Node {
63    type Request = Request;
64
65    fn imports(ctx: &mut ImportCtx<'_>) {
66        ctx.import::<crate::cfg_openvmm_magicpath::Node>();
67        ctx.import::<crate::resolve_openvmm_deps::Node>();
68    }
69
70    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
71        let mut by_arch: BTreeMap<CommonArch, Vec<WriteVar<SideEffect>>> = BTreeMap::new();
72        for Request { arch, done } in requests {
73            by_arch.entry(arch).or_default().push(done);
74        }
75
76        // -- end of req processing -- //
77
78        let openvmm_magicpath = ctx.reqv(crate::cfg_openvmm_magicpath::Request);
79
80        for (arch, out_vars) in by_arch {
81            // Resolve all dep files for this arch.
82            let resolved: Vec<(ReadVar<PathBuf>, &'static str)> = dep_files()
83                .into_iter()
84                .map(|dep_file| {
85                    let src = ctx
86                        .reqv(|v| crate::resolve_openvmm_deps::Request::Get(dep_file.dep, arch, v));
87                    let dst_name = (dep_file.dest_filename)(arch);
88                    (src, dst_name)
89                })
90                .collect();
91
92            ctx.emit_rust_step(
93                format!("copy {arch:?} openvmm-deps files to magicpath"),
94                |ctx| {
95                    let resolved: Vec<_> = resolved
96                        .into_iter()
97                        .map(|(src, name)| (src.claim(ctx), name))
98                        .collect();
99                    let openvmm_magicpath = openvmm_magicpath.clone().claim(ctx);
100                    out_vars.claim(ctx);
101
102                    move |rt| {
103                        let magicpath = rt.read(openvmm_magicpath);
104                        let dst_dir = magicpath
105                            .join("underhill-deps-private")
106                            .join(dir_name(arch));
107                        fs_err::create_dir_all(&dst_dir)?;
108
109                        for (src, filename) in resolved {
110                            let src = rt.read(src);
111                            let dst = dst_dir.join(filename);
112                            if src.absolute()? != dst.absolute()? {
113                                fs_err::copy(&src, &dst)?;
114                            }
115                        }
116
117                        Ok(())
118                    }
119                },
120            );
121        }
122
123        Ok(())
124    }
125}