Skip to main content

flowey_lib_hvlite/
download_uefi_mu_msvm.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Download pre-built mu_msvm package from its GitHub Release.
5
6use crate::common::CommonArch;
7use flowey::node::prelude::*;
8use std::collections::BTreeMap;
9
10flowey_config! {
11    /// Config for the download_uefi_mu_msvm node.
12    pub struct Config {
13        /// Specify version of mu_msvm to use
14        pub version: Option<String>,
15        /// Use a local MSVM.fd path, keyed by architecture
16        pub local_paths: BTreeMap<CommonArch, ConfigVar<PathBuf>>,
17    }
18}
19
20flowey_request! {
21    pub enum Request {
22        /// Download the mu_msvm package for the given arch
23        GetMsvmFd {
24            arch: CommonArch,
25            msvm_fd: WriteVar<PathBuf>
26        }
27    }
28}
29
30new_flow_node_with_config!(struct Node);
31
32impl FlowNodeWithConfig for Node {
33    type Request = Request;
34    type Config = Config;
35
36    fn imports(ctx: &mut ImportCtx<'_>) {
37        ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
38        ctx.import::<flowey_lib_common::download_gh_release::Node>();
39    }
40
41    fn emit(
42        config: Config,
43        requests: Vec<Self::Request>,
44        ctx: &mut NodeCtx<'_>,
45    ) -> anyhow::Result<()> {
46        let version = config.version;
47        let local_paths = config.local_paths;
48        let mut reqs: BTreeMap<CommonArch, Vec<WriteVar<PathBuf>>> = BTreeMap::new();
49
50        for req in requests {
51            match req {
52                Request::GetMsvmFd { arch, msvm_fd } => reqs.entry(arch).or_default().push(msvm_fd),
53            }
54        }
55
56        if version.is_some() && !local_paths.is_empty() {
57            anyhow::bail!("Cannot specify both Version and LocalPath requests");
58        }
59
60        if version.is_none() && local_paths.is_empty() {
61            anyhow::bail!("Must specify a Version or LocalPath request");
62        }
63
64        // -- end of req processing -- //
65
66        if reqs.is_empty() {
67            return Ok(());
68        }
69
70        if !local_paths.is_empty() {
71            ctx.emit_rust_step("use local mu_msvm UEFI", |ctx| {
72                let reqs = reqs.claim(ctx);
73                let local_paths: BTreeMap<_, _> = local_paths
74                    .into_iter()
75                    .map(|(arch, var)| (arch, var.claim(ctx)))
76                    .collect();
77                move |rt| {
78                    for (arch, out_vars) in reqs {
79                        let msvm_fd_var = local_paths.get(&arch).ok_or_else(|| {
80                            anyhow::anyhow!("No local path specified for architecture {:?}", arch)
81                        })?;
82                        let msvm_fd = rt.read(msvm_fd_var.clone());
83                        for var in out_vars {
84                            log::info!(
85                                "using local uefi for {} at path {:?}",
86                                match arch {
87                                    CommonArch::X86_64 => "x64",
88                                    CommonArch::Aarch64 => "aarch64",
89                                },
90                                msvm_fd
91                            );
92                            rt.write(var, &msvm_fd);
93                        }
94                    }
95                    Ok(())
96                }
97            });
98
99            return Ok(());
100        }
101
102        let version = version.expect("local paths handled above");
103        let extract_archive_deps = flowey_lib_common::_util::extract::extract_zip_if_new_deps(ctx);
104
105        for (arch, out_vars) in reqs {
106            let file_name = match arch {
107                CommonArch::X86_64 => "RELEASE-X64-VS2022-artifacts.tar.gz",
108                CommonArch::Aarch64 => "RELEASE-AARCH64-CLANGPDB-artifacts.tar.gz",
109            };
110
111            let mu_msvm_archive = ctx.reqv(|v| flowey_lib_common::download_gh_release::Request {
112                repo_owner: "microsoft".into(),
113                repo_name: "mu_msvm".into(),
114                needs_auth: false,
115                tag: format!("v{version}"),
116                file_name: file_name.into(),
117                path: v,
118            });
119
120            let archive_file_version = format!("{version}-{file_name}");
121
122            ctx.emit_rust_step(
123                {
124                    format!(
125                        "unpack mu_msvm package ({})",
126                        match arch {
127                            CommonArch::X86_64 => "x64",
128                            CommonArch::Aarch64 => "aarch64",
129                        },
130                    )
131                },
132                |ctx| {
133                    let extract_archive_deps = extract_archive_deps.clone().claim(ctx);
134                    let out_vars = out_vars.claim(ctx);
135                    let mu_msvm_archive = mu_msvm_archive.claim(ctx);
136                    move |rt| {
137                        let mu_msvm_archive = rt.read(mu_msvm_archive);
138
139                        let extract_dir = flowey_lib_common::_util::extract::extract_zip_if_new(
140                            rt,
141                            extract_archive_deps,
142                            &mu_msvm_archive,
143                            &archive_file_version,
144                        )?;
145
146                        let msvm_fd = extract_dir.join("FV/MSVM.fd");
147
148                        for var in out_vars {
149                            rt.write(var, &msvm_fd)
150                        }
151
152                        Ok(())
153                    }
154                },
155            );
156        }
157
158        Ok(())
159    }
160}