flowey_lib_hvlite/
resolve_openvmm_deps.rs1use crate::common::CommonArch;
7use flowey::node::prelude::*;
8use std::collections::BTreeMap;
9
10#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
12pub enum OpenvmmDepFile {
13 OpenhclCpioDbgrd,
14 OpenhclCpioShell,
15 OpenhclSysroot,
16 PetritoolsErofs,
17}
18
19impl OpenvmmDepFile {
20 pub fn filename(self) -> &'static str {
21 match self {
22 Self::OpenhclCpioDbgrd => "dbgrd.cpio.gz",
23 Self::OpenhclCpioShell => "shell.cpio.gz",
24 Self::OpenhclSysroot => "sysroot.tar.gz",
25 Self::PetritoolsErofs => "petritools.erofs",
26 }
27 }
28}
29
30flowey_config! {
31 pub struct Config {
33 pub version: Option<String>,
35 pub local_paths: BTreeMap<CommonArch, ConfigVar<PathBuf>>,
37 }
38}
39
40flowey_request! {
41 pub enum Request {
42 Get(OpenvmmDepFile, CommonArch, WriteVar<PathBuf>),
44 }
45}
46
47new_flow_node_with_config!(struct Node);
48
49impl FlowNodeWithConfig for Node {
50 type Request = Request;
51 type Config = Config;
52
53 fn imports(ctx: &mut ImportCtx<'_>) {
54 ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
55 ctx.import::<flowey_lib_common::download_gh_release::Node>();
56 }
57
58 fn emit(
59 config: Config,
60 requests: Vec<Self::Request>,
61 ctx: &mut NodeCtx<'_>,
62 ) -> anyhow::Result<()> {
63 let version = config.version;
64 let local_paths = config.local_paths;
65 let mut deps: BTreeMap<(OpenvmmDepFile, CommonArch), Vec<WriteVar<PathBuf>>> =
66 BTreeMap::new();
67
68 for req in requests {
69 match req {
70 Request::Get(dep, arch, var) => {
71 deps.entry((dep, arch)).or_default().push(var);
72 }
73 }
74 }
75
76 if version.is_some() && !local_paths.is_empty() {
77 anyhow::bail!("Cannot specify both Version and LocalPath requests");
78 }
79
80 if version.is_none() && local_paths.is_empty() {
81 anyhow::bail!("Must specify a Version or LocalPath request");
82 }
83
84 if deps.is_empty() {
87 return Ok(());
88 }
89
90 let needs_arch = |arch: CommonArch| deps.keys().any(|(_, a)| *a == arch);
92
93 if !local_paths.is_empty() {
94 ctx.emit_rust_step("use local openvmm-deps", |ctx| {
95 let deps = deps.claim(ctx);
96 let local_paths: BTreeMap<_, _> = local_paths
97 .into_iter()
98 .map(|(arch, var)| (arch, var.claim(ctx)))
99 .collect();
100 move |rt| {
101 let resolved_paths: BTreeMap<CommonArch, PathBuf> = local_paths
102 .into_iter()
103 .map(|(arch, var)| (arch, rt.read(var)))
104 .collect();
105
106 for ((dep, arch), vars) in deps {
107 let base_dir = resolved_paths.get(&arch).ok_or_else(|| {
108 anyhow::anyhow!("No local path specified for architecture {:?}", arch)
109 })?;
110 let path = base_dir.join(dep.filename());
111 rt.write_all(vars, &path)
112 }
113
114 Ok(())
115 }
116 });
117
118 return Ok(());
119 }
120
121 let extract_tar_gz_persistent_dir = ctx.persistent_dir();
122
123 let download_archive = |arch: CommonArch, ctx: &mut NodeCtx<'_>| {
124 let version = version.clone().expect("local requests handled above");
125 let arch_str = match arch {
126 CommonArch::X86_64 => "x86_64",
127 CommonArch::Aarch64 => "aarch64",
128 };
129 ctx.reqv(|v| flowey_lib_common::download_gh_release::Request {
130 repo_owner: "microsoft".into(),
131 repo_name: "openvmm-deps".into(),
132 needs_auth: false,
133 tag: version.clone(),
134 file_name: format!("openvmm-deps.{arch_str}.{version}.tar.gz"),
135 path: v,
136 })
137 };
138
139 let openvmm_deps_tar_gz_x64 =
140 needs_arch(CommonArch::X86_64).then(|| download_archive(CommonArch::X86_64, ctx));
141 let openvmm_deps_tar_gz_aarch64 =
142 needs_arch(CommonArch::Aarch64).then(|| download_archive(CommonArch::Aarch64, ctx));
143
144 ctx.emit_rust_step("unpack openvmm-deps archive", |ctx| {
145 let extract_tar_gz_persistent_dir = extract_tar_gz_persistent_dir.claim(ctx);
146 let openvmm_deps_tar_gz_x64 = openvmm_deps_tar_gz_x64.claim(ctx);
147 let openvmm_deps_tar_gz_aarch64 = openvmm_deps_tar_gz_aarch64.claim(ctx);
148 let deps = deps.claim(ctx);
149 let version = version.clone().expect("local requests handled above");
150 move |rt| {
151 let persistent_dir = extract_tar_gz_persistent_dir.map(|d| rt.read(d));
152 let extract_dir_x64 = openvmm_deps_tar_gz_x64
153 .map(|file| {
154 let file = rt.read(file);
155 flowey_lib_common::_util::extract::extract_tar_gz_if_new(
156 rt,
157 persistent_dir.as_deref(),
158 &file,
159 &version,
160 )
161 })
162 .transpose()?;
163 let extract_dir_aarch64 = openvmm_deps_tar_gz_aarch64
164 .map(|file| {
165 let file = rt.read(file);
166 flowey_lib_common::_util::extract::extract_tar_gz_if_new(
167 rt,
168 persistent_dir.as_deref(),
169 &file,
170 &version,
171 )
172 })
173 .transpose()?;
174
175 let base_dir = |arch| match arch {
176 CommonArch::X86_64 => extract_dir_x64.clone().unwrap(),
177 CommonArch::Aarch64 => extract_dir_aarch64.clone().unwrap(),
178 };
179
180 for ((dep, arch), vars) in deps {
181 let path = base_dir(arch).join(dep.filename());
182 rt.write_all(vars, &path)
183 }
184
185 Ok(())
186 }
187 });
188
189 Ok(())
190 }
191}