flowey_lib_hvlite/_jobs/
cfg_nix.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! A configuration node that resolves dependency paths from the Nix environment.
5//!
6//! When running inside a `nix-shell`, all external dependencies (protoc,
7//! openvmm-deps, kernel packages, UEFI firmware) are provided by Nix at
8//! well-known paths exposed via environment variables. This node reads those
9//! paths at runtime, writes them to a [`NixConfig`] struct, and issues the
10//! corresponding [`cfg_versions::Request`] overrides so that downstream nodes
11//! use the Nix-provided artifacts instead of downloading them.
12
13use crate::_jobs::cfg_versions;
14use crate::resolve_openhcl_kernel_package::OpenhclKernelPackageKind;
15use crate::run_cargo_build::common::CommonArch;
16use flowey::node::prelude::*;
17
18/// Resolved dependency paths from the Nix environment.
19#[derive(Serialize, Deserialize)]
20pub struct NixConfig {
21    pub openvmm_deps: PathBuf,
22    pub protoc: PathBuf,
23    pub kernel: PathBuf,
24    pub kernel_modules: PathBuf,
25    pub uefi: PathBuf,
26}
27
28flowey_request! {
29    pub struct Params {
30        pub arch: CommonArch,
31        pub kernel_kind: OpenhclKernelPackageKind,
32    }
33}
34
35new_simple_flow_node!(struct Node);
36
37impl SimpleFlowNode for Node {
38    type Request = Params;
39
40    fn imports(ctx: &mut ImportCtx<'_>) {
41        ctx.import::<cfg_versions::Node>();
42    }
43
44    fn process_request(request: Self::Request, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
45        let Params { arch, kernel_kind } = request;
46
47        // aarch64 CVM kernels don't exist - only x64 has CVM variants
48        if matches!(arch, CommonArch::Aarch64)
49            && matches!(
50                kernel_kind,
51                OpenhclKernelPackageKind::Cvm | OpenhclKernelPackageKind::CvmDev
52            )
53        {
54            anyhow::bail!(
55                "aarch64 does not have a CVM kernel variant (requested {:?})",
56                kernel_kind
57            );
58        }
59
60        let arch_suffix = match arch {
61            CommonArch::X86_64 => "X64",
62            CommonArch::Aarch64 => "AARCH64",
63        };
64        let kernel_suffix = match kernel_kind {
65            OpenhclKernelPackageKind::Main => "",
66            OpenhclKernelPackageKind::Cvm => "_CVM",
67            OpenhclKernelPackageKind::Dev => "_DEV",
68            OpenhclKernelPackageKind::CvmDev => "_CVM_DEV",
69        };
70        let openvmm_deps_env = format!("OPENVMM_DEPS_{arch_suffix}");
71        let kernel_env = format!("NIX_KERNEL_{arch_suffix}{kernel_suffix}");
72        let uefi_env = format!("NIX_UEFI_{arch_suffix}");
73        let kernel_file = match arch {
74            CommonArch::X86_64 => "vmlinux",
75            CommonArch::Aarch64 => "Image",
76        };
77
78        let (nix_config_read, nix_config_write) = ctx.new_var::<NixConfig>();
79
80        ctx.emit_rust_step("resolve nix dependency paths", |ctx| {
81            let nix_config_write = nix_config_write.claim(ctx);
82            move |rt| {
83                let openvmm_deps =
84                    PathBuf::from(flowey::shell_cmd!(rt, "printenv {openvmm_deps_env}").read()?);
85                let protoc = PathBuf::from(flowey::shell_cmd!(rt, "printenv NIX_PROTOC").read()?);
86                let kernel_pkg =
87                    PathBuf::from(flowey::shell_cmd!(rt, "printenv {kernel_env}").read()?);
88                let uefi = PathBuf::from(flowey::shell_cmd!(rt, "printenv {uefi_env}").read()?);
89
90                let kernel = kernel_pkg.join(kernel_file);
91                let kernel_modules = kernel_pkg.join("modules");
92
93                log::info!("resolved nix paths:");
94                log::info!("  openvmm_deps: {}", openvmm_deps.display());
95                log::info!("  protoc:       {}", protoc.display());
96                log::info!("  kernel:       {}", kernel.display());
97                log::info!("  modules:      {}", kernel_modules.display());
98                log::info!("  uefi:         {}", uefi.display());
99
100                rt.write(
101                    nix_config_write,
102                    &NixConfig {
103                        openvmm_deps,
104                        protoc,
105                        kernel,
106                        kernel_modules,
107                        uefi,
108                    },
109                );
110
111                Ok(())
112            }
113        });
114
115        let openvmm_deps = nix_config_read.map(ctx, |cfg| cfg.openvmm_deps);
116        let protoc = nix_config_read.map(ctx, |cfg| cfg.protoc);
117        let kernel = nix_config_read.map(ctx, |cfg| cfg.kernel);
118        let kernel_modules = nix_config_read.map(ctx, |cfg| cfg.kernel_modules);
119        let uefi = nix_config_read.map(ctx, |cfg| cfg.uefi);
120
121        // Set the cfg_versions overrides to use all "local" paths
122        ctx.req(cfg_versions::Request::Init);
123        ctx.req(cfg_versions::Request::LocalOpenvmmDeps(arch, openvmm_deps));
124        ctx.req(cfg_versions::Request::LocalProtoc(protoc));
125        ctx.req(cfg_versions::Request::LocalKernel {
126            arch,
127            kernel,
128            modules: kernel_modules,
129        });
130        ctx.req(cfg_versions::Request::LocalUefi(arch, uefi));
131
132        Ok(())
133    }
134}