1use crate::build_openhcl_initrd::OpenhclInitrdExtraParams;
13use crate::build_openvmm_hcl::OpenvmmHclBuildProfile;
14use crate::build_openvmm_hcl::OpenvmmHclFeature;
15use crate::download_openhcl_kernel_package::OpenhclKernelPackageArch;
16use crate::download_openhcl_kernel_package::OpenhclKernelPackageKind;
17use crate::download_openvmm_deps::OpenvmmDepsArch;
18use crate::download_uefi_mu_msvm::MuMsvmArch;
19use crate::run_cargo_build::BuildProfile;
20use crate::run_cargo_build::common::CommonArch;
21use crate::run_cargo_build::common::CommonPlatform;
22use crate::run_cargo_build::common::CommonTriple;
23use flowey::node::prelude::*;
24use igvmfilegen_config::ResourceType;
25use std::collections::BTreeMap;
26use std::collections::BTreeSet;
27
28#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
29pub enum OpenhclKernelPackage {
30 Main,
32 Cvm,
34 Dev,
36 CvmDev,
38 CustomLocal(PathBuf),
40}
41
42#[derive(Serialize, Deserialize, Debug, Clone)]
44pub enum Vtl0KernelType {
45 Example,
46 LocalOnlyCustom(PathBuf),
47}
48
49#[derive(Serialize, Deserialize, Clone, Debug)]
50pub enum IgvmManifestPath {
51 InTree(String),
53 LocalOnlyCustom(PathBuf),
55}
56
57#[derive(Serialize, Deserialize, Clone, Debug)]
58pub struct OpenhclIgvmRecipeDetails {
59 pub local_only: Option<OpenhclIgvmRecipeDetailsLocalOnly>,
60
61 pub igvm_manifest: IgvmManifestPath,
62 pub openhcl_kernel_package: OpenhclKernelPackage,
63 pub openvmm_hcl_features: BTreeSet<OpenvmmHclFeature>,
64 pub target: CommonTriple,
65 pub vtl0_kernel_type: Option<Vtl0KernelType>,
66 pub with_uefi: bool,
67 pub with_interactive: bool,
68 pub with_sidecar: bool,
69}
70
71#[derive(Serialize, Deserialize, Clone, Debug)]
72pub struct OpenhclIgvmRecipeDetailsLocalOnly {
73 pub openvmm_hcl_no_strip: bool,
74 pub openhcl_initrd_extra_params: Option<OpenhclInitrdExtraParams>,
75 pub custom_openvmm_hcl: Option<PathBuf>,
76 pub custom_openhcl_boot: Option<PathBuf>,
77 pub custom_uefi: Option<PathBuf>,
78 pub custom_kernel: Option<PathBuf>,
79 pub custom_sidecar: Option<PathBuf>,
80 pub custom_extra_rootfs: Vec<PathBuf>,
81}
82
83#[expect(clippy::large_enum_variant)]
84#[derive(Debug, Serialize, Deserialize, Clone)]
85pub enum OpenhclIgvmRecipe {
86 LocalOnlyCustom(OpenhclIgvmRecipeDetails),
87 X64,
88 X64Devkern,
89 X64TestLinuxDirect,
90 X64TestLinuxDirectDevkern,
91 X64Cvm,
92 X64CvmDevkern,
93 Aarch64,
94 Aarch64Devkern,
95}
96
97impl OpenhclIgvmRecipe {
98 pub fn recipe_details(&self, profile: OpenvmmHclBuildProfile) -> OpenhclIgvmRecipeDetails {
99 let base_openvmm_hcl_features = || {
100 let mut m = BTreeSet::new();
101
102 m.insert(OpenvmmHclFeature::Tpm);
103
104 if matches!(profile, OpenvmmHclBuildProfile::Debug) {
105 m.insert(OpenvmmHclFeature::Gdb);
106 }
107
108 m
109 };
110
111 let in_repo_template = |debug_manifest: &'static str, release_manifest: &'static str| {
112 IgvmManifestPath::InTree(if matches!(profile, OpenvmmHclBuildProfile::Debug) {
113 debug_manifest.into()
114 } else {
115 release_manifest.into()
116 })
117 };
118
119 let with_interactive = matches!(profile, OpenvmmHclBuildProfile::Debug);
121
122 match self {
123 Self::LocalOnlyCustom(details) => details.clone(),
124 Self::X64 => OpenhclIgvmRecipeDetails {
125 local_only: None,
126 igvm_manifest: in_repo_template("openhcl-x64-dev.json", "openhcl-x64-release.json"),
127 openhcl_kernel_package: OpenhclKernelPackage::Main,
128 openvmm_hcl_features: base_openvmm_hcl_features(),
129 target: CommonTriple::X86_64_LINUX_MUSL,
130 vtl0_kernel_type: None,
131 with_uefi: true,
132 with_interactive,
133 with_sidecar: true,
134 },
135 Self::X64Devkern => OpenhclIgvmRecipeDetails {
136 local_only: None,
137 igvm_manifest: in_repo_template("openhcl-x64-dev.json", "openhcl-x64-release.json"),
138 openhcl_kernel_package: OpenhclKernelPackage::Dev,
139 openvmm_hcl_features: base_openvmm_hcl_features(),
140 target: CommonTriple::X86_64_LINUX_MUSL,
141 vtl0_kernel_type: None,
142 with_uefi: true,
143 with_interactive,
144 with_sidecar: true,
145 },
146 Self::X64CvmDevkern => OpenhclIgvmRecipeDetails {
147 local_only: None,
148 igvm_manifest: in_repo_template(
149 "openhcl-x64-cvm-dev.json",
150 "openhcl-x64-cvm-release.json",
151 ),
152 openhcl_kernel_package: OpenhclKernelPackage::CvmDev,
153 openvmm_hcl_features: base_openvmm_hcl_features(),
154 target: CommonTriple::X86_64_LINUX_MUSL,
155 vtl0_kernel_type: None,
156 with_uefi: true,
157 with_interactive,
158 with_sidecar: false,
159 },
160 Self::X64TestLinuxDirect => OpenhclIgvmRecipeDetails {
161 local_only: None,
162 igvm_manifest: in_repo_template(
163 "openhcl-x64-direct-dev.json",
164 "openhcl-x64-direct-release.json",
165 ),
166 openhcl_kernel_package: OpenhclKernelPackage::Main,
167 openvmm_hcl_features: base_openvmm_hcl_features(),
168 target: CommonTriple::X86_64_LINUX_MUSL,
169 vtl0_kernel_type: Some(Vtl0KernelType::Example),
170 with_uefi: false,
171 with_interactive,
172 with_sidecar: true,
173 },
174 Self::X64TestLinuxDirectDevkern => OpenhclIgvmRecipeDetails {
175 local_only: None,
176 igvm_manifest: in_repo_template(
177 "openhcl-x64-direct-dev.json",
178 "openhcl-x64-direct-release.json",
179 ),
180 openhcl_kernel_package: OpenhclKernelPackage::Dev,
181 openvmm_hcl_features: base_openvmm_hcl_features(),
182 target: CommonTriple::X86_64_LINUX_MUSL,
183 vtl0_kernel_type: Some(Vtl0KernelType::Example),
184 with_uefi: false,
185 with_interactive,
186 with_sidecar: true,
187 },
188 Self::X64Cvm => OpenhclIgvmRecipeDetails {
189 local_only: None,
190 igvm_manifest: in_repo_template(
191 "openhcl-x64-cvm-dev.json",
192 "openhcl-x64-cvm-release.json",
193 ),
194 openhcl_kernel_package: OpenhclKernelPackage::Cvm,
195 openvmm_hcl_features: base_openvmm_hcl_features(),
196 target: CommonTriple::X86_64_LINUX_MUSL,
197 vtl0_kernel_type: None,
198 with_uefi: true,
199 with_interactive,
200 with_sidecar: false,
201 },
202 Self::Aarch64 => OpenhclIgvmRecipeDetails {
203 local_only: None,
204 igvm_manifest: in_repo_template(
205 "openhcl-aarch64-dev.json",
206 "openhcl-aarch64-release.json",
207 ),
208 openhcl_kernel_package: OpenhclKernelPackage::Main,
209 openvmm_hcl_features: base_openvmm_hcl_features(),
210 target: CommonTriple::AARCH64_LINUX_MUSL,
211 vtl0_kernel_type: None,
212 with_uefi: true,
213 with_interactive: false, with_sidecar: false,
215 },
216 Self::Aarch64Devkern => OpenhclIgvmRecipeDetails {
217 local_only: None,
218 igvm_manifest: in_repo_template(
219 "openhcl-aarch64-dev.json",
220 "openhcl-aarch64-release.json",
221 ),
222 openhcl_kernel_package: OpenhclKernelPackage::Dev,
223 openvmm_hcl_features: base_openvmm_hcl_features(),
224 target: CommonTriple::AARCH64_LINUX_MUSL,
225 vtl0_kernel_type: None,
226 with_uefi: true,
227 with_interactive: false, with_sidecar: false,
229 },
230 }
231 }
232
233 pub fn to_custom_mut(&mut self, profile: OpenvmmHclBuildProfile) {
234 let details = self.recipe_details(profile);
235 *self = Self::LocalOnlyCustom(details);
236 }
237}
238
239flowey_request! {
240 pub struct Request {
241 pub profile: OpenvmmHclBuildProfile,
242 pub recipe: OpenhclIgvmRecipe,
243 pub custom_target: Option<CommonTriple>,
244
245 pub built_openvmm_hcl: WriteVar<crate::build_openvmm_hcl::OpenvmmHclOutput>,
246 pub built_openhcl_boot: WriteVar<crate::build_openhcl_boot::OpenhclBootOutput>,
247 pub built_openhcl_igvm: WriteVar<crate::run_igvmfilegen::IgvmOutput>,
248 pub built_sidecar: WriteVar<Option<crate::build_sidecar::SidecarOutput>>,
249 }
250}
251
252new_simple_flow_node!(struct Node);
253
254impl SimpleFlowNode for Node {
255 type Request = Request;
256
257 fn imports(ctx: &mut ImportCtx<'_>) {
258 ctx.import::<crate::build_igvmfilegen::Node>();
259 ctx.import::<crate::build_openhcl_boot::Node>();
260 ctx.import::<crate::build_openhcl_initrd::Node>();
261 ctx.import::<crate::build_openvmm_hcl::Node>();
262 ctx.import::<crate::build_sidecar::Node>();
263 ctx.import::<crate::download_openhcl_kernel_package::Node>();
264 ctx.import::<crate::download_openvmm_deps::Node>();
265 ctx.import::<crate::download_uefi_mu_msvm::Node>();
266 ctx.import::<crate::git_checkout_openvmm_repo::Node>();
267 ctx.import::<crate::run_igvmfilegen::Node>();
268 ctx.import::<crate::run_split_debug_info::Node>();
269 }
270
271 fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
272 let Request {
273 profile,
274 recipe,
275 custom_target,
276 built_openvmm_hcl,
277 built_openhcl_boot,
278 built_openhcl_igvm,
279 built_sidecar,
280 } = request;
281
282 let OpenhclIgvmRecipeDetails {
283 local_only,
284 igvm_manifest,
285 openhcl_kernel_package,
286 openvmm_hcl_features,
287 target,
288 vtl0_kernel_type,
289 with_uefi,
290 with_interactive,
291 with_sidecar,
292 } = recipe.recipe_details(profile);
293
294 let OpenhclIgvmRecipeDetailsLocalOnly {
295 openvmm_hcl_no_strip,
296 openhcl_initrd_extra_params,
297 custom_openvmm_hcl,
298 custom_openhcl_boot,
299 custom_uefi,
300 custom_kernel,
301 custom_sidecar,
302 custom_extra_rootfs,
303 } = local_only.unwrap_or(OpenhclIgvmRecipeDetailsLocalOnly {
304 openvmm_hcl_no_strip: false,
305 openhcl_initrd_extra_params: None,
306 custom_openvmm_hcl: None,
307 custom_openhcl_boot: None,
308 custom_uefi: None,
309 custom_kernel: None,
310 custom_sidecar: None,
311 custom_extra_rootfs: Vec::new(),
312 });
313
314 let target = custom_target.unwrap_or(target);
315 let arch = CommonArch::from_triple(&target.as_triple())
316 .ok_or_else(|| anyhow::anyhow!("cannot build openHCL from recipe on {target}"))?;
317
318 let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
319
320 let vtl2_kernel_package_root = {
321 let arch = match arch {
322 CommonArch::X86_64 => OpenhclKernelPackageArch::X86_64,
323 CommonArch::Aarch64 => OpenhclKernelPackageArch::Aarch64,
324 };
325
326 enum DownloadOrLocal {
327 Local(PathBuf),
328 Download(OpenhclKernelPackageKind),
329 }
330
331 let download_kind = match openhcl_kernel_package {
332 OpenhclKernelPackage::Main => {
333 DownloadOrLocal::Download(OpenhclKernelPackageKind::Main)
334 }
335 OpenhclKernelPackage::Cvm => {
336 DownloadOrLocal::Download(OpenhclKernelPackageKind::Cvm)
337 }
338 OpenhclKernelPackage::Dev => {
339 DownloadOrLocal::Download(OpenhclKernelPackageKind::Dev)
340 }
341 OpenhclKernelPackage::CvmDev => {
342 DownloadOrLocal::Download(OpenhclKernelPackageKind::CvmDev)
343 }
344 OpenhclKernelPackage::CustomLocal(path) => DownloadOrLocal::Local(path),
345 };
346
347 match download_kind {
348 DownloadOrLocal::Local(path) => ReadVar::from_static(path),
349 DownloadOrLocal::Download(kind) => {
350 ctx.reqv(
351 |v| crate::download_openhcl_kernel_package::Request::GetPackage {
352 kind,
353 arch,
354 pkg: v,
355 },
356 )
357 }
358 }
359 };
360
361 let uefi_resource = with_uefi.then(|| UefiResource {
362 msvm_fd: if let Some(path) = custom_uefi {
363 ReadVar::from_static(path)
364 } else {
365 ctx.reqv(|v| crate::download_uefi_mu_msvm::Request::GetMsvmFd {
366 arch: match arch {
367 CommonArch::X86_64 => MuMsvmArch::X86_64,
368 CommonArch::Aarch64 => MuMsvmArch::Aarch64,
369 },
370 msvm_fd: v,
371 })
372 },
373 });
374
375 let vtl0_kernel_resource = vtl0_kernel_type.map(|typ| {
376 let kernel = if let Vtl0KernelType::LocalOnlyCustom(path) = typ {
377 ReadVar::from_static(path)
378 } else {
379 match typ {
380 Vtl0KernelType::Example => ctx.reqv(|v| {
381 crate::download_openvmm_deps::Request::GetLinuxTestKernel(
382 match arch {
383 CommonArch::X86_64 => OpenvmmDepsArch::X86_64,
384 CommonArch::Aarch64 => OpenvmmDepsArch::Aarch64,
385 },
386 v,
387 )
388 }),
389 Vtl0KernelType::LocalOnlyCustom(_) => unreachable!("special cased above"),
390 }
391 };
392
393 let initrd = ctx.reqv(|v| {
394 crate::download_openvmm_deps::Request::GetLinuxTestInitrd(
395 match arch {
396 CommonArch::X86_64 => OpenvmmDepsArch::X86_64,
397 CommonArch::Aarch64 => OpenvmmDepsArch::Aarch64,
398 },
399 v,
400 )
401 });
402
403 Vtl0KernelResource { kernel, initrd }
404 });
405
406 let sidecar_bin = if with_sidecar {
408 let sidecar_bin = if let Some(path) = custom_sidecar {
409 ctx.emit_rust_stepv("set custom_sidecar", |_ctx| {
410 |_rt| {
411 let fake_dbg_path = std::env::current_dir()?
412 .join("fake_sidecar.dbg")
413 .absolute()?;
414 fs_err::write(&fake_dbg_path, "")?;
415
416 Ok(crate::build_sidecar::SidecarOutput {
417 bin: path,
418 dbg: fake_dbg_path,
419 })
420 }
421 })
422 } else {
423 ctx.reqv(|v| crate::build_sidecar::Request {
424 build_params: crate::build_sidecar::SidecarBuildParams {
425 arch,
426 profile: match profile {
427 OpenvmmHclBuildProfile::Debug => {
428 crate::build_sidecar::SidecarBuildProfile::Debug
429 }
430 OpenvmmHclBuildProfile::Release
431 | OpenvmmHclBuildProfile::OpenvmmHclShip => {
432 crate::build_sidecar::SidecarBuildProfile::Release
433 }
434 },
435 },
436 sidecar: v,
437 })
438 };
439 sidecar_bin.write_into(ctx, built_sidecar, Some);
440 Some(sidecar_bin)
441 } else {
442 built_sidecar.write_static(ctx, None);
443 None
444 };
445
446 let openvmm_hcl_bin = ctx.reqv(|v| {
448 crate::build_openvmm_hcl::Request {
449 build_params: crate::build_openvmm_hcl::OpenvmmHclBuildParams {
450 target: target.clone(),
451 profile,
452 features: openvmm_hcl_features,
453 no_split_dbg_info: true,
455 },
456 openvmm_hcl_output: v,
457 }
458 });
459
460 let igvmfilegen_arch = match ctx.arch() {
462 FlowArch::X86_64 => CommonArch::X86_64,
463 FlowArch::Aarch64 => CommonArch::Aarch64,
464 arch => anyhow::bail!("unsupported arch {arch}"),
465 };
466
467 let igvmfilegen = ctx.reqv(|v| crate::build_igvmfilegen::Request {
468 build_params: crate::build_igvmfilegen::IgvmfilegenBuildParams {
469 target: CommonTriple::Common {
470 arch: igvmfilegen_arch,
471 platform: CommonPlatform::LinuxGnu,
472 },
473 profile: BuildProfile::Light,
474 },
475 igvmfilegen: v,
476 });
477
478 let openhcl_boot_bin = if let Some(path) = custom_openhcl_boot {
480 ctx.emit_rust_stepv("set custom_openhcl_boot", |_ctx| {
481 |_rt| {
482 let fake_dbg_path = std::env::current_dir()?.join("fake.dbg").absolute()?;
483 fs_err::write(&fake_dbg_path, "")?;
484
485 Ok(crate::build_openhcl_boot::OpenhclBootOutput {
486 bin: path,
487 dbg: fake_dbg_path,
488 })
489 }
490 })
491 } else {
492 ctx.reqv(|v| crate::build_openhcl_boot::Request {
493 build_params: crate::build_openhcl_boot::OpenhclBootBuildParams {
494 arch,
495 profile: match profile {
496 OpenvmmHclBuildProfile::Debug => {
497 crate::build_openhcl_boot::OpenhclBootBuildProfile::Debug
498 }
499 OpenvmmHclBuildProfile::Release
500 | OpenvmmHclBuildProfile::OpenvmmHclShip => {
501 crate::build_openhcl_boot::OpenhclBootBuildProfile::Release
502 }
503 },
504 },
505 openhcl_boot: v,
506 })
507 };
508 openhcl_boot_bin.write_into(ctx, built_openhcl_boot, |x| x);
509
510 let use_stripped_openvmm_hcl = {
511 if custom_openvmm_hcl.is_some() {
512 false
515 } else {
516 !openvmm_hcl_no_strip
517 }
518 };
519
520 let openvmm_hcl_bin = if use_stripped_openvmm_hcl {
522 let (read, write) = ctx.new_var();
523 let (read_dbg, write_dbg) = ctx.new_var();
524
525 let in_bin = openvmm_hcl_bin.map(ctx, |o| o.bin);
526 ctx.req(crate::run_split_debug_info::Request {
527 arch,
528 in_bin,
529 out_bin: write,
530 out_dbg_info: write_dbg,
531 });
532
533 read.zip(ctx, read_dbg).map(ctx, |(bin, dbg)| {
534 crate::build_openvmm_hcl::OpenvmmHclOutput {
535 bin,
536 dbg: Some(dbg),
537 }
538 })
539 } else {
540 openvmm_hcl_bin
541 };
542
543 openvmm_hcl_bin.write_into(ctx, built_openvmm_hcl, |x| x);
545
546 let initrd = {
547 let rootfs_config = [openvmm_repo_path.map(ctx, |p| p.join("openhcl/rootfs.config"))]
548 .into_iter()
549 .chain(
550 custom_extra_rootfs
551 .into_iter()
552 .map(|p| ReadVar::from_static(p)),
553 )
554 .collect();
555 let openvmm_hcl_bin = openvmm_hcl_bin.map(ctx, |o| o.bin);
556
557 ctx.reqv(|v| crate::build_openhcl_initrd::Request {
558 interactive: with_interactive,
559 arch,
560 extra_params: openhcl_initrd_extra_params,
561 rootfs_config,
562 extra_env: None,
563 kernel_package_root: vtl2_kernel_package_root.clone(),
564 bin_openhcl: openvmm_hcl_bin,
565 initrd: v,
566 })
567 };
568
569 let kernel =
570 if let Some(path) = custom_kernel {
571 ReadVar::from_static(path)
572 } else {
573 match arch {
574 CommonArch::X86_64 => vtl2_kernel_package_root
575 .map(ctx, |p| p.join("build/native/bin/x64/vmlinux")),
576 CommonArch::Aarch64 => vtl2_kernel_package_root
577 .map(ctx, |p| p.join("build/native/bin/arm64/Image")),
578 }
579 };
580
581 let resources = ctx.emit_minor_rust_stepv("enumerate igvm resources", |ctx| {
582 let initrd = initrd.claim(ctx);
583 let kernel = kernel.claim(ctx);
584 let openhcl_boot_bin = openhcl_boot_bin.claim(ctx);
585 let sidecar_bin = sidecar_bin.claim(ctx);
586 let uefi_resource = uefi_resource.claim(ctx);
587 let vtl0_kernel_resource = vtl0_kernel_resource.claim(ctx);
588 |rt| {
589 let mut resources = BTreeMap::<ResourceType, PathBuf>::new();
590 resources.insert(ResourceType::UnderhillKernel, rt.read(kernel));
591 resources.insert(ResourceType::UnderhillInitrd, rt.read(initrd).initrd);
592 resources.insert(ResourceType::OpenhclBoot, rt.read(openhcl_boot_bin).bin);
593 if let Some(sidecar_bin) = sidecar_bin {
594 resources.insert(ResourceType::UnderhillSidecar, rt.read(sidecar_bin).bin);
595 }
596 if let Some(uefi_resource) = uefi_resource {
597 uefi_resource.add_to_resources(&mut resources, rt);
598 }
599 if let Some(vtl0_kernel_resource) = vtl0_kernel_resource {
600 vtl0_kernel_resource.add_to_resources(&mut resources, rt);
601 }
602 resources
603 }
604 });
605
606 let igvmfilegen = igvmfilegen.map(ctx, |o| match o {
607 crate::build_igvmfilegen::IgvmfilegenOutput::LinuxBin { bin, dbg: _ } => bin,
608 crate::build_igvmfilegen::IgvmfilegenOutput::WindowsBin { exe, pdb: _ } => exe,
609 });
610
611 let manifest = match igvm_manifest {
612 IgvmManifestPath::InTree(path) => {
613 openvmm_repo_path.map(ctx, |p| p.join("vm/loader/manifests").join(path))
614 }
615 IgvmManifestPath::LocalOnlyCustom(p) => ReadVar::from_static(p),
616 };
617
618 ctx.req(crate::run_igvmfilegen::Request {
619 igvmfilegen,
620 manifest,
621 resources,
622 igvm: built_openhcl_igvm,
623 });
624
625 Ok(())
626 }
627}
628
629#[derive(Debug)]
630pub struct UefiResource<C = VarNotClaimed> {
631 pub msvm_fd: ReadVar<PathBuf, C>,
632}
633
634impl ClaimVar for UefiResource {
635 type Claimed = UefiResource<VarClaimed>;
636
637 fn claim(self, ctx: &mut StepCtx<'_>) -> UefiResource<VarClaimed> {
638 UefiResource {
639 msvm_fd: self.msvm_fd.claim(ctx),
640 }
641 }
642}
643
644impl UefiResource<VarClaimed> {
645 pub fn add_to_resources(
646 self,
647 resources: &mut BTreeMap<ResourceType, PathBuf>,
648 rt: &mut RustRuntimeServices<'_>,
649 ) {
650 let path = rt.read(self.msvm_fd);
651 resources.insert(ResourceType::Uefi, path);
652 }
653}
654
655pub struct Vtl0KernelResource<C = VarNotClaimed> {
656 pub kernel: ReadVar<PathBuf, C>,
657 pub initrd: ReadVar<PathBuf, C>,
658}
659
660impl ClaimVar for Vtl0KernelResource {
661 type Claimed = Vtl0KernelResource<VarClaimed>;
662
663 fn claim(self, ctx: &mut StepCtx<'_>) -> Vtl0KernelResource<VarClaimed> {
664 Vtl0KernelResource {
665 kernel: self.kernel.claim(ctx),
666 initrd: self.initrd.claim(ctx),
667 }
668 }
669}
670
671impl Vtl0KernelResource<VarClaimed> {
672 pub fn add_to_resources(
673 self,
674 resources: &mut BTreeMap<ResourceType, PathBuf>,
675 rt: &mut RustRuntimeServices<'_>,
676 ) {
677 let kernel = rt.read(self.kernel);
678 let initrd = rt.read(self.initrd);
679 resources.insert(ResourceType::LinuxKernel, kernel);
680 resources.insert(ResourceType::LinuxInitrd, initrd);
681 }
682}