flowey_lib_hvlite/
build_openhcl_igvm_from_recipe.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Build an OpenHCL IGVM file using a particular known-good "recipe", which
5//! encodes the precise features / build parameters used by each constituent
6//! component.
7//!
8//! By having a clearly enumerated list of recipes, it is possible for multiple
9//! pipelines / flows to depend on _precisely_ the same IGVM file, without
10//! having to duplicate the non-trivial OpenHCL IGVM build chain.
11
12use 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    /// Kernel from the hcl-main branch
31    Main,
32    /// CVM kernel from the hcl-main branch
33    Cvm,
34    /// Kernel from the hcl-dev branch
35    Dev,
36    /// CVM kernel from the hcl-dev brnach
37    CvmDev,
38    /// Path to a custom local package
39    CustomLocal(PathBuf),
40}
41
42/// Vtl0 kernel type
43#[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    /// Name of an in-tree manifest (located under `vm/loader/manifests`)
52    InTree(String),
53    /// An absolute path to a custom manifest (for local use only)
54    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, release_cfg: bool) -> OpenhclIgvmRecipeDetails {
99        let base_openvmm_hcl_features = || {
100            let mut m = BTreeSet::new();
101
102            m.insert(OpenvmmHclFeature::Tpm);
103
104            if !release_cfg {
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 release_cfg {
113                release_manifest.into()
114            } else {
115                debug_manifest.into()
116            })
117        };
118
119        // Debug configurations include --interactive by default, for busybox, gdbserver, and perf.
120        let with_interactive = !release_cfg;
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, // #1234
214                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, // #1234
228                with_sidecar: false,
229            },
230        }
231    }
232}
233
234flowey_request! {
235    pub struct Request {
236        pub build_profile: OpenvmmHclBuildProfile,
237        pub release_cfg: bool,
238        pub recipe: OpenhclIgvmRecipe,
239        pub custom_target: Option<CommonTriple>,
240
241        pub built_openvmm_hcl: WriteVar<crate::build_openvmm_hcl::OpenvmmHclOutput>,
242        pub built_openhcl_boot: WriteVar<crate::build_openhcl_boot::OpenhclBootOutput>,
243        pub built_openhcl_igvm: WriteVar<crate::run_igvmfilegen::IgvmOutput>,
244        pub built_sidecar: WriteVar<Option<crate::build_sidecar::SidecarOutput>>,
245    }
246}
247
248new_simple_flow_node!(struct Node);
249
250impl SimpleFlowNode for Node {
251    type Request = Request;
252
253    fn imports(ctx: &mut ImportCtx<'_>) {
254        ctx.import::<crate::build_igvmfilegen::Node>();
255        ctx.import::<crate::build_openhcl_boot::Node>();
256        ctx.import::<crate::build_openhcl_initrd::Node>();
257        ctx.import::<crate::build_openvmm_hcl::Node>();
258        ctx.import::<crate::build_sidecar::Node>();
259        ctx.import::<crate::download_openhcl_kernel_package::Node>();
260        ctx.import::<crate::download_openvmm_deps::Node>();
261        ctx.import::<crate::download_uefi_mu_msvm::Node>();
262        ctx.import::<crate::git_checkout_openvmm_repo::Node>();
263        ctx.import::<crate::run_igvmfilegen::Node>();
264        ctx.import::<crate::run_split_debug_info::Node>();
265    }
266
267    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
268        let Request {
269            build_profile,
270            release_cfg,
271            recipe,
272            custom_target,
273            built_openvmm_hcl,
274            built_openhcl_boot,
275            built_openhcl_igvm,
276            built_sidecar,
277        } = request;
278
279        let OpenhclIgvmRecipeDetails {
280            local_only,
281            igvm_manifest,
282            openhcl_kernel_package,
283            openvmm_hcl_features,
284            target,
285            vtl0_kernel_type,
286            with_uefi,
287            with_interactive,
288            with_sidecar,
289        } = recipe.recipe_details(release_cfg);
290
291        let OpenhclIgvmRecipeDetailsLocalOnly {
292            openvmm_hcl_no_strip,
293            openhcl_initrd_extra_params,
294            custom_openvmm_hcl,
295            custom_openhcl_boot,
296            custom_uefi,
297            custom_kernel,
298            custom_sidecar,
299            custom_extra_rootfs,
300        } = local_only.unwrap_or(OpenhclIgvmRecipeDetailsLocalOnly {
301            openvmm_hcl_no_strip: false,
302            openhcl_initrd_extra_params: None,
303            custom_openvmm_hcl: None,
304            custom_openhcl_boot: None,
305            custom_uefi: None,
306            custom_kernel: None,
307            custom_sidecar: None,
308            custom_extra_rootfs: Vec::new(),
309        });
310
311        let target = custom_target.unwrap_or(target);
312        let arch = CommonArch::from_triple(&target.as_triple())
313            .ok_or_else(|| anyhow::anyhow!("cannot build openHCL from recipe on {target}"))?;
314
315        let openvmm_repo_path = ctx.reqv(crate::git_checkout_openvmm_repo::req::GetRepoDir);
316
317        let vtl2_kernel_package_root = {
318            let arch = match arch {
319                CommonArch::X86_64 => OpenhclKernelPackageArch::X86_64,
320                CommonArch::Aarch64 => OpenhclKernelPackageArch::Aarch64,
321            };
322
323            enum DownloadOrLocal {
324                Local(PathBuf),
325                Download(OpenhclKernelPackageKind),
326            }
327
328            let download_kind = match openhcl_kernel_package {
329                OpenhclKernelPackage::Main => {
330                    DownloadOrLocal::Download(OpenhclKernelPackageKind::Main)
331                }
332                OpenhclKernelPackage::Cvm => {
333                    DownloadOrLocal::Download(OpenhclKernelPackageKind::Cvm)
334                }
335                OpenhclKernelPackage::Dev => {
336                    DownloadOrLocal::Download(OpenhclKernelPackageKind::Dev)
337                }
338                OpenhclKernelPackage::CvmDev => {
339                    DownloadOrLocal::Download(OpenhclKernelPackageKind::CvmDev)
340                }
341                OpenhclKernelPackage::CustomLocal(path) => DownloadOrLocal::Local(path),
342            };
343
344            match download_kind {
345                DownloadOrLocal::Local(path) => ReadVar::from_static(path),
346                DownloadOrLocal::Download(kind) => {
347                    ctx.reqv(
348                        |v| crate::download_openhcl_kernel_package::Request::GetPackage {
349                            kind,
350                            arch,
351                            pkg: v,
352                        },
353                    )
354                }
355            }
356        };
357
358        let uefi_resource = with_uefi.then(|| UefiResource {
359            msvm_fd: if let Some(path) = custom_uefi {
360                ReadVar::from_static(path)
361            } else {
362                ctx.reqv(|v| crate::download_uefi_mu_msvm::Request::GetMsvmFd {
363                    arch: match arch {
364                        CommonArch::X86_64 => MuMsvmArch::X86_64,
365                        CommonArch::Aarch64 => MuMsvmArch::Aarch64,
366                    },
367                    msvm_fd: v,
368                })
369            },
370        });
371
372        let vtl0_kernel_resource = vtl0_kernel_type.map(|typ| {
373            let kernel = if let Vtl0KernelType::LocalOnlyCustom(path) = typ {
374                ReadVar::from_static(path)
375            } else {
376                match typ {
377                    Vtl0KernelType::Example => ctx.reqv(|v| {
378                        crate::download_openvmm_deps::Request::GetLinuxTestKernel(
379                            match arch {
380                                CommonArch::X86_64 => OpenvmmDepsArch::X86_64,
381                                CommonArch::Aarch64 => OpenvmmDepsArch::Aarch64,
382                            },
383                            v,
384                        )
385                    }),
386                    Vtl0KernelType::LocalOnlyCustom(_) => unreachable!("special cased above"),
387                }
388            };
389
390            let initrd = ctx.reqv(|v| {
391                crate::download_openvmm_deps::Request::GetLinuxTestInitrd(
392                    match arch {
393                        CommonArch::X86_64 => OpenvmmDepsArch::X86_64,
394                        CommonArch::Aarch64 => OpenvmmDepsArch::Aarch64,
395                    },
396                    v,
397                )
398            });
399
400            Vtl0KernelResource { kernel, initrd }
401        });
402
403        // build sidecar
404        let sidecar_bin = if with_sidecar {
405            let sidecar_bin = if let Some(path) = custom_sidecar {
406                ctx.emit_rust_stepv("set custom_sidecar", |_ctx| {
407                    |_rt| {
408                        let fake_dbg_path = std::env::current_dir()?
409                            .join("fake_sidecar.dbg")
410                            .absolute()?;
411                        fs_err::write(&fake_dbg_path, "")?;
412
413                        Ok(crate::build_sidecar::SidecarOutput {
414                            bin: path,
415                            dbg: fake_dbg_path,
416                        })
417                    }
418                })
419            } else {
420                ctx.reqv(|v| crate::build_sidecar::Request {
421                    build_params: crate::build_sidecar::SidecarBuildParams {
422                        arch,
423                        profile: match build_profile {
424                            OpenvmmHclBuildProfile::Debug => {
425                                crate::build_sidecar::SidecarBuildProfile::Debug
426                            }
427                            OpenvmmHclBuildProfile::Release
428                            | OpenvmmHclBuildProfile::OpenvmmHclShip => {
429                                crate::build_sidecar::SidecarBuildProfile::Release
430                            }
431                        },
432                    },
433                    sidecar: v,
434                })
435            };
436            sidecar_bin.write_into(ctx, built_sidecar, Some);
437            Some(sidecar_bin)
438        } else {
439            built_sidecar.write_static(ctx, None);
440            None
441        };
442
443        // build openvmm_hcl bin
444        let openvmm_hcl_bin = ctx.reqv(|v| {
445            crate::build_openvmm_hcl::Request {
446                build_params: crate::build_openvmm_hcl::OpenvmmHclBuildParams {
447                    target: target.clone(),
448                    profile: build_profile,
449                    features: openvmm_hcl_features,
450                    // manually strip later, depending on provided igvm flags
451                    no_split_dbg_info: true,
452                },
453                openvmm_hcl_output: v,
454            }
455        });
456
457        // build igvmfilegen (always built for host arch)
458        let igvmfilegen_arch = match ctx.arch() {
459            FlowArch::X86_64 => CommonArch::X86_64,
460            FlowArch::Aarch64 => CommonArch::Aarch64,
461            arch => anyhow::bail!("unsupported arch {arch}"),
462        };
463
464        let igvmfilegen = ctx.reqv(|v| crate::build_igvmfilegen::Request {
465            build_params: crate::build_igvmfilegen::IgvmfilegenBuildParams {
466                target: CommonTriple::Common {
467                    arch: igvmfilegen_arch,
468                    platform: CommonPlatform::LinuxGnu,
469                },
470                profile: BuildProfile::Light,
471            },
472            igvmfilegen: v,
473        });
474
475        // build openhcl_boot
476        let openhcl_boot_bin = if let Some(path) = custom_openhcl_boot {
477            ctx.emit_rust_stepv("set custom_openhcl_boot", |_ctx| {
478                |_rt| {
479                    let fake_dbg_path = std::env::current_dir()?.join("fake.dbg").absolute()?;
480                    fs_err::write(&fake_dbg_path, "")?;
481
482                    Ok(crate::build_openhcl_boot::OpenhclBootOutput {
483                        bin: path,
484                        dbg: fake_dbg_path,
485                    })
486                }
487            })
488        } else {
489            ctx.reqv(|v| crate::build_openhcl_boot::Request {
490                build_params: crate::build_openhcl_boot::OpenhclBootBuildParams {
491                    arch,
492                    profile: match build_profile {
493                        OpenvmmHclBuildProfile::Debug => {
494                            crate::build_openhcl_boot::OpenhclBootBuildProfile::Debug
495                        }
496                        OpenvmmHclBuildProfile::Release
497                        | OpenvmmHclBuildProfile::OpenvmmHclShip => {
498                            crate::build_openhcl_boot::OpenhclBootBuildProfile::Release
499                        }
500                    },
501                },
502                openhcl_boot: v,
503            })
504        };
505        openhcl_boot_bin.write_into(ctx, built_openhcl_boot, |x| x);
506
507        let use_stripped_openvmm_hcl = {
508            if custom_openvmm_hcl.is_some() {
509                // trust the user knows what they are doing if they specified a
510                // custom bin
511                false
512            } else {
513                !openvmm_hcl_no_strip
514            }
515        };
516
517        // use the stripped or unstripped openvmm_hcl as requested
518        let openvmm_hcl_bin = if use_stripped_openvmm_hcl {
519            let (read, write) = ctx.new_var();
520            let (read_dbg, write_dbg) = ctx.new_var();
521
522            let in_bin = openvmm_hcl_bin.map(ctx, |o| o.bin);
523            ctx.req(crate::run_split_debug_info::Request {
524                arch,
525                in_bin,
526                out_bin: write,
527                out_dbg_info: write_dbg,
528            });
529
530            read.zip(ctx, read_dbg).map(ctx, |(bin, dbg)| {
531                crate::build_openvmm_hcl::OpenvmmHclOutput {
532                    bin,
533                    dbg: Some(dbg),
534                }
535            })
536        } else {
537            openvmm_hcl_bin
538        };
539
540        // report the built openvmm_hcl
541        openvmm_hcl_bin.write_into(ctx, built_openvmm_hcl, |x| x);
542
543        let initrd = {
544            let rootfs_config = [openvmm_repo_path.map(ctx, |p| p.join("openhcl/rootfs.config"))]
545                .into_iter()
546                .chain(
547                    custom_extra_rootfs
548                        .into_iter()
549                        .map(|p| ReadVar::from_static(p)),
550                )
551                .collect();
552            let openvmm_hcl_bin = openvmm_hcl_bin.map(ctx, |o| o.bin);
553
554            ctx.reqv(|v| crate::build_openhcl_initrd::Request {
555                interactive: with_interactive,
556                arch,
557                extra_params: openhcl_initrd_extra_params,
558                rootfs_config,
559                extra_env: None,
560                kernel_package_root: vtl2_kernel_package_root.clone(),
561                bin_openhcl: openvmm_hcl_bin,
562                initrd: v,
563            })
564        };
565
566        let kernel =
567            if let Some(path) = custom_kernel {
568                ReadVar::from_static(path)
569            } else {
570                match arch {
571                    CommonArch::X86_64 => vtl2_kernel_package_root
572                        .map(ctx, |p| p.join("build/native/bin/x64/vmlinux")),
573                    CommonArch::Aarch64 => vtl2_kernel_package_root
574                        .map(ctx, |p| p.join("build/native/bin/arm64/Image")),
575                }
576            };
577
578        let resources = ctx.emit_minor_rust_stepv("enumerate igvm resources", |ctx| {
579            let initrd = initrd.claim(ctx);
580            let kernel = kernel.claim(ctx);
581            let openhcl_boot_bin = openhcl_boot_bin.claim(ctx);
582            let sidecar_bin = sidecar_bin.claim(ctx);
583            let uefi_resource = uefi_resource.claim(ctx);
584            let vtl0_kernel_resource = vtl0_kernel_resource.claim(ctx);
585            |rt| {
586                let mut resources = BTreeMap::<ResourceType, PathBuf>::new();
587                resources.insert(ResourceType::UnderhillKernel, rt.read(kernel));
588                resources.insert(ResourceType::UnderhillInitrd, rt.read(initrd).initrd);
589                resources.insert(ResourceType::OpenhclBoot, rt.read(openhcl_boot_bin).bin);
590                if let Some(sidecar_bin) = sidecar_bin {
591                    resources.insert(ResourceType::UnderhillSidecar, rt.read(sidecar_bin).bin);
592                }
593                if let Some(uefi_resource) = uefi_resource {
594                    uefi_resource.add_to_resources(&mut resources, rt);
595                }
596                if let Some(vtl0_kernel_resource) = vtl0_kernel_resource {
597                    vtl0_kernel_resource.add_to_resources(&mut resources, rt);
598                }
599                resources
600            }
601        });
602
603        let igvmfilegen = igvmfilegen.map(ctx, |o| match o {
604            crate::build_igvmfilegen::IgvmfilegenOutput::LinuxBin { bin, dbg: _ } => bin,
605            crate::build_igvmfilegen::IgvmfilegenOutput::WindowsBin { exe, pdb: _ } => exe,
606        });
607
608        let manifest = match igvm_manifest {
609            IgvmManifestPath::InTree(path) => {
610                openvmm_repo_path.map(ctx, |p| p.join("vm/loader/manifests").join(path))
611            }
612            IgvmManifestPath::LocalOnlyCustom(p) => ReadVar::from_static(p),
613        };
614
615        ctx.req(crate::run_igvmfilegen::Request {
616            igvmfilegen,
617            manifest,
618            resources,
619            igvm: built_openhcl_igvm,
620        });
621
622        Ok(())
623    }
624}
625
626#[derive(Debug)]
627pub struct UefiResource<C = VarNotClaimed> {
628    pub msvm_fd: ReadVar<PathBuf, C>,
629}
630
631impl ClaimVar for UefiResource {
632    type Claimed = UefiResource<VarClaimed>;
633
634    fn claim(self, ctx: &mut StepCtx<'_>) -> UefiResource<VarClaimed> {
635        UefiResource {
636            msvm_fd: self.msvm_fd.claim(ctx),
637        }
638    }
639}
640
641impl UefiResource<VarClaimed> {
642    pub fn add_to_resources(
643        self,
644        resources: &mut BTreeMap<ResourceType, PathBuf>,
645        rt: &mut RustRuntimeServices<'_>,
646    ) {
647        let path = rt.read(self.msvm_fd);
648        resources.insert(ResourceType::Uefi, path);
649    }
650}
651
652pub struct Vtl0KernelResource<C = VarNotClaimed> {
653    pub kernel: ReadVar<PathBuf, C>,
654    pub initrd: ReadVar<PathBuf, C>,
655}
656
657impl ClaimVar for Vtl0KernelResource {
658    type Claimed = Vtl0KernelResource<VarClaimed>;
659
660    fn claim(self, ctx: &mut StepCtx<'_>) -> Vtl0KernelResource<VarClaimed> {
661        Vtl0KernelResource {
662            kernel: self.kernel.claim(ctx),
663            initrd: self.initrd.claim(ctx),
664        }
665    }
666}
667
668impl Vtl0KernelResource<VarClaimed> {
669    pub fn add_to_resources(
670        self,
671        resources: &mut BTreeMap<ResourceType, PathBuf>,
672        rt: &mut RustRuntimeServices<'_>,
673    ) {
674        let kernel = rt.read(self.kernel);
675        let initrd = rt.read(self.initrd);
676        resources.insert(ResourceType::LinuxKernel, kernel);
677        resources.insert(ResourceType::LinuxInitrd, initrd);
678    }
679}