Skip to main content

flowey_lib_hvlite/_jobs/
local_build_opentmk.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! A local-only job that supports the `cargo xflowey build-opentmk` CLI
5
6use flowey::node::prelude::*;
7
8flowey_request! {
9    pub struct Params {
10        pub artifact_dir: ReadVar<PathBuf>,
11        pub done: WriteVar<SideEffect>,
12
13        pub arch: crate::common::CommonArch,
14        pub release: bool,
15        /// Custom name for the output `.efi`, `.vhd`, and `.pdb`. Defaults to "opentmk".
16        pub name: Option<String>,
17        /// Optional JSON test-selection config to embed in the built VHD.
18        pub config: Option<PathBuf>,
19    }
20}
21
22new_simple_flow_node!(struct Node);
23
24impl SimpleFlowNode for Node {
25    type Request = Params;
26
27    fn imports(ctx: &mut ImportCtx<'_>) {
28        ctx.import::<crate::build_opentmk::Node>();
29    }
30
31    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
32        let Params {
33            artifact_dir,
34            done,
35            arch,
36            release,
37            name,
38            config,
39        } = request;
40
41        let profile = if release {
42            crate::common::CommonProfile::Release
43        } else {
44            crate::common::CommonProfile::Debug
45        };
46
47        let name = name.unwrap_or_else(|| "opentmk".to_string());
48
49        let opentmk_output = ctx.reqv(|v| crate::build_opentmk::Request {
50            arch,
51            profile,
52            out_name: Some(name.clone()),
53            opentmk: v,
54        });
55
56        ctx.emit_rust_step("package opentmk into VHD", |ctx| {
57            done.claim(ctx);
58            let artifact_dir = artifact_dir.claim(ctx);
59            let opentmk_output = opentmk_output.claim(ctx);
60            move |rt| {
61                let crate::build_opentmk::OpentmkOutput { efi, pdb } = rt.read(opentmk_output);
62
63                let output_dir = rt.read(artifact_dir);
64                let output_dir = output_dir.absolute()?;
65                fs_err::create_dir_all(&output_dir)?;
66
67                // Build the bootable VHD, patching in the test config if one was given.
68                let disk_arch = match arch {
69                    crate::common::CommonArch::X86_64 => opentmk_disk::Arch::X86_64,
70                    crate::common::CommonArch::Aarch64 => opentmk_disk::Arch::Aarch64,
71                };
72                let efi_bytes = fs_err::read(&efi)?;
73                let vhd_path = output_dir.join(format!("{name}.vhd"));
74                let image = if let Some(cfg_path) = &config {
75                    let config_json = fs_err::read(cfg_path.absolute()?)?;
76                    opentmk_disk::build_opentmk_vhd_with_config(
77                        &efi_bytes,
78                        disk_arch,
79                        &config_json,
80                    )?
81                } else {
82                    opentmk_disk::build_opentmk_vhd(&efi_bytes, disk_arch)?
83                };
84                if vhd_path.exists() {
85                    fs_err::remove_file(&vhd_path)?;
86                }
87                image.persist(&vhd_path)?;
88
89                fs_err::copy(&efi, output_dir.join(format!("{name}.efi")))?;
90                fs_err::copy(&pdb, output_dir.join(format!("{name}.pdb")))?;
91
92                log::info!("EFI: {}", output_dir.join(format!("{name}.efi")).display());
93                log::info!("VHD: {}", vhd_path.display());
94                log::info!("PDB: {}", output_dir.join(format!("{name}.pdb")).display());
95
96                Ok(())
97            }
98        });
99
100        Ok(())
101    }
102}