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