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