flowey_lib_hvlite/
build_openhcl_initrd.rs1use crate::resolve_openvmm_deps::OpenvmmDepsArch;
7use crate::run_cargo_build::common::CommonArch;
8use flowey::node::prelude::*;
9use std::collections::BTreeMap;
10
11#[derive(Serialize, Deserialize)]
12pub struct OpenhclInitrdOutput {
13 pub initrd: PathBuf,
14}
15
16#[derive(Default, Clone, Serialize, Deserialize, Debug)]
18pub struct OpenhclInitrdExtraParams {
19 pub extra_initrd_layers: Vec<PathBuf>,
21 pub extra_initrd_directories: Vec<PathBuf>,
23}
24
25flowey_request! {
26 pub struct Request {
27 pub arch: CommonArch,
28 pub interactive: bool,
30 pub extra_params: Option<OpenhclInitrdExtraParams>,
32 pub rootfs_config: Vec<ReadVar<PathBuf>>,
34 pub extra_env: Option<ReadVar<BTreeMap<String, String>>>,
37 pub kernel_package_root: ReadVar<PathBuf>,
39 pub kernel_modules: ReadVar<PathBuf>,
41 pub kernel_metadata: ReadVar<PathBuf>,
43 pub bin_openhcl: ReadVar<PathBuf>,
45 pub initrd: WriteVar<OpenhclInitrdOutput>,
47 }
48}
49
50new_flow_node!(struct Node);
51
52impl FlowNode for Node {
53 type Request = Request;
54
55 fn imports(ctx: &mut ImportCtx<'_>) {
56 ctx.import::<crate::resolve_openvmm_deps::Node>();
57 ctx.import::<crate::git_checkout_openvmm_repo::Node>();
58 ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
59 }
60
61 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
62 let platform = ctx.platform();
64 let python_pkg = match platform {
65 FlowPlatform::Linux(linux_distribution) => match linux_distribution {
66 FlowPlatformLinuxDistro::Fedora
67 | FlowPlatformLinuxDistro::Ubuntu
68 | FlowPlatformLinuxDistro::Nix => "python3",
69 FlowPlatformLinuxDistro::Arch => "python",
70 FlowPlatformLinuxDistro::Unknown => anyhow::bail!("Unknown Linux distribution"),
71 },
72 _ => anyhow::bail!("Unsupported platform"),
73 };
74
75 let pydeps = if !matches!(platform, FlowPlatform::Linux(FlowPlatformLinuxDistro::Nix)) {
77 Some(ctx.reqv(
78 |side_effect| flowey_lib_common::install_dist_pkg::Request::Install {
79 package_names: [python_pkg].map(Into::into).into(),
80 done: side_effect,
81 },
82 ))
83 } else {
84 None
85 };
86
87 let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
88
89 for Request {
90 arch,
91 extra_params,
92 rootfs_config,
93 kernel_package_root,
94 kernel_modules,
95 kernel_metadata,
96 extra_env,
97 bin_openhcl,
98 initrd,
99 interactive,
100 } in requests
101 {
102 let OpenhclInitrdExtraParams {
103 extra_initrd_layers,
104 extra_initrd_directories,
105 } = extra_params.unwrap_or_default();
106
107 let openvmm_deps_arch = match arch {
108 CommonArch::X86_64 => OpenvmmDepsArch::X86_64,
109 CommonArch::Aarch64 => OpenvmmDepsArch::Aarch64,
110 };
111
112 let interactive_dep = if interactive {
113 ctx.reqv(|v| {
114 crate::resolve_openvmm_deps::Request::GetOpenhclCpioDbgrd(openvmm_deps_arch, v)
115 })
116 } else {
117 ctx.reqv(|v| {
118 crate::resolve_openvmm_deps::Request::GetOpenhclCpioShell(openvmm_deps_arch, v)
119 })
120 };
121
122 if rootfs_config.is_empty() {
123 anyhow::bail!("no rootfs files provided");
124 }
125
126 ctx.emit_rust_step("building openhcl initrd", |ctx| {
127 pydeps.clone().claim(ctx);
128 let interactive_dep = interactive_dep.claim(ctx);
129 let rootfs_config = rootfs_config.claim(ctx);
130 let extra_env = extra_env.claim(ctx);
131 let bin_openhcl = bin_openhcl.claim(ctx);
132 let openvmm_repo_path = openvmm_repo_path.clone().claim(ctx);
133 let kernel_package_root = kernel_package_root.claim(ctx);
134 let kernel_modules = kernel_modules.claim(ctx);
135 let kernel_metadata = kernel_metadata.claim(ctx);
136 let initrd = initrd.claim(ctx);
137 move |rt| {
138 let interactive_dep = rt.read(interactive_dep);
139 let rootfs_config = rt.read(rootfs_config);
140 let extra_env = rt.read(extra_env);
141 let bin_openhcl = rt.read(bin_openhcl);
142 let openvmm_repo_path = rt.read(openvmm_repo_path);
143 let kernel_package_root = rt.read(kernel_package_root);
144 let kernel_metadata = rt.read(kernel_metadata);
145
146 let sh = xshell::Shell::new()?;
147
148 let initrd_path = sh.current_dir().join("openhcl.cpio.gz");
149
150 let initrd_contents = {
151 let mut v = Vec::new();
152
153 if interactive {
154 v.push("--interactive".to_string());
156 } else {
157 v.push("--min-interactive".to_string());
159 }
160
161 for dir in extra_initrd_layers {
162 v.push("--layer".into());
163 v.push(dir.display().to_string());
164 }
165
166 for dir in extra_initrd_directories {
167 v.push("--add-dir".into());
168 v.push(dir.display().to_string());
169 }
170
171 v
172 };
173
174 let rootfs_py_arch = match arch {
175 CommonArch::X86_64 => "x86_64",
176 CommonArch::Aarch64 => "aarch64",
177 };
178
179 let kernel_modules = rt.read(kernel_modules);
180
181 match arch {
186 CommonArch::X86_64 => {
187 sh.set_var("OPENVMM_DEPS_X64", interactive_dep.parent().unwrap());
188 }
189 CommonArch::Aarch64 => {
190 sh.set_var("OPENVMM_DEPS_AARCH64", interactive_dep.parent().unwrap());
191 }
192 }
193
194 for (k, v) in extra_env.into_iter().flatten() {
195 sh.set_var(k, v);
196 }
197
198 sh.change_dir(openvmm_repo_path);
201
202 let rootfs_config = rootfs_config
203 .iter()
204 .flat_map(|x| ["--rootfs-config".as_ref(), x.as_os_str()]);
205
206 xshell::cmd!(
207 sh,
208 "python3 openhcl/update-rootfs.py
209 {bin_openhcl}
210 {initrd_path}
211 --arch {rootfs_py_arch}
212 --package-root {kernel_package_root}
213 --kernel-modules {kernel_modules}
214 --kernel-metadata {kernel_metadata}
215 {rootfs_config...}
216 {initrd_contents...}
217 "
218 )
219 .run()?;
220
221 rt.write(
222 initrd,
223 &OpenhclInitrdOutput {
224 initrd: initrd_path,
225 },
226 );
227
228 Ok(())
229 }
230 });
231 }
232
233 Ok(())
234 }
235}