Skip to main content

flowey_lib_hvlite/
build_openhcl_boot.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Build `openhcl_boot` binaries
5
6use crate::common::CommonArch;
7use crate::run_cargo_build::BuildProfile;
8use flowey::node::prelude::*;
9use flowey_lib_common::_util::group_by;
10use flowey_lib_common::run_cargo_build::CargoFeatureSet;
11
12#[derive(Serialize, Deserialize)]
13pub struct OpenhclBootOutput {
14    #[serde(rename = "openhcl_boot")]
15    pub bin: PathBuf,
16    #[serde(rename = "openhcl_boot.dbg")]
17    pub dbg: PathBuf,
18}
19
20#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
21pub enum OpenhclBootBuildProfile {
22    Debug,
23    Release,
24}
25
26#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
27pub struct OpenhclBootBuildParams {
28    pub arch: CommonArch,
29    pub profile: OpenhclBootBuildProfile,
30}
31
32flowey_request! {
33    pub struct Request {
34        pub build_params: OpenhclBootBuildParams,
35        pub openhcl_boot: WriteVar<OpenhclBootOutput>,
36    }
37}
38
39new_flow_node!(struct Node);
40
41impl FlowNode for Node {
42    type Request = Request;
43
44    fn imports(ctx: &mut ImportCtx<'_>) {
45        ctx.import::<crate::run_cargo_build::Node>();
46    }
47
48    fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
49        let requests = group_by(
50            requests
51                .into_iter()
52                .map(|r| (r.build_params, r.openhcl_boot)),
53        );
54
55        for (OpenhclBootBuildParams { arch, profile }, openhcl_boot) in requests {
56            let target = arch.minimal_rt_triple();
57
58            // We use special profiles for boot, convert from the standard ones:
59            let profile = match profile {
60                OpenhclBootBuildProfile::Debug => BuildProfile::BootDev,
61                OpenhclBootBuildProfile::Release => BuildProfile::BootRelease,
62            };
63
64            // Enable cvm_boot_log in debug builds to include TDX/SNP
65            // serial logging support.
66            let features = if matches!(profile, BuildProfile::BootDev) {
67                CargoFeatureSet::Specific(vec!["cvm_boot_log".into()])
68            } else {
69                CargoFeatureSet::None
70            };
71
72            let mut extra_env = crate::common::openhcl_build_env();
73            extra_env.insert("RUSTC_BOOTSTRAP".into(), "1".into());
74
75            let output = ctx.reqv(|v| crate::run_cargo_build::Request {
76                crate_name: "openhcl_boot".into(),
77                out_name: "openhcl_boot".into(),
78                crate_type: flowey_lib_common::run_cargo_build::CargoCrateType::Bin,
79                profile,
80                features,
81                target,
82                no_split_dbg_info: false,
83                extra_env: Some(ReadVar::from_static(extra_env)),
84                pre_build_deps: Vec::new(),
85                output: v,
86            });
87
88            ctx.emit_minor_rust_step("report built openhcl_boot", |ctx| {
89                let openhcl_boot = openhcl_boot.claim(ctx);
90                let output = output.claim(ctx);
91                move |rt| {
92                    let output = match rt.read(output) {
93                        crate::run_cargo_build::CargoBuildOutput::ElfBin { bin, dbg } => {
94                            OpenhclBootOutput {
95                                bin,
96                                dbg: dbg.unwrap(),
97                            }
98                        }
99                        _ => unreachable!(),
100                    };
101
102                    rt.write_all(openhcl_boot, &output);
103                }
104            });
105        }
106
107        Ok(())
108    }
109}