flowey_lib_hvlite/
download_uefi_mu_msvm.rs1use flowey::node::prelude::*;
7use std::collections::BTreeMap;
8
9#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
10pub enum MuMsvmArch {
11 X86_64,
12 Aarch64,
13}
14
15flowey_request! {
16 pub enum Request {
17 Version(String),
19 LocalPath(MuMsvmArch, PathBuf),
21 GetMsvmFd {
23 arch: MuMsvmArch,
24 msvm_fd: WriteVar<PathBuf>
25 }
26 }
27}
28
29new_flow_node!(struct Node);
30
31impl FlowNode for Node {
32 type Request = Request;
33
34 fn imports(ctx: &mut ImportCtx<'_>) {
35 ctx.import::<flowey_lib_common::install_dist_pkg::Node>();
36 ctx.import::<flowey_lib_common::download_gh_release::Node>();
37 }
38
39 fn emit(requests: Vec<Self::Request>, ctx: &mut NodeCtx<'_>) -> anyhow::Result<()> {
40 let mut version = None;
41 let mut local_paths: BTreeMap<MuMsvmArch, PathBuf> = BTreeMap::new();
42 let mut reqs: BTreeMap<MuMsvmArch, Vec<WriteVar<PathBuf>>> = BTreeMap::new();
43
44 for req in requests {
45 match req {
46 Request::Version(v) => same_across_all_reqs("Version", &mut version, v)?,
47 Request::LocalPath(arch, path) => {
48 if let Some(existing) = local_paths.get(&arch) {
49 if existing != &path {
50 anyhow::bail!(
51 "Conflicting LocalPath requests for {:?}: {:?} vs {:?}",
52 arch,
53 existing,
54 path
55 );
56 }
57 } else {
58 local_paths.insert(arch, path);
59 }
60 }
61 Request::GetMsvmFd { arch, msvm_fd } => reqs.entry(arch).or_default().push(msvm_fd),
62 }
63 }
64
65 if version.is_some() && !local_paths.is_empty() {
66 anyhow::bail!("Cannot specify both Version and LocalPath requests");
67 }
68
69 if version.is_none() && local_paths.is_empty() {
70 anyhow::bail!("Must specify a Version or LocalPath request");
71 }
72
73 if reqs.is_empty() {
76 return Ok(());
77 }
78
79 if !local_paths.is_empty() {
80 ctx.emit_rust_step("use local mu_msvm UEFI", |ctx| {
81 let reqs = reqs.claim(ctx);
82 let local_paths = local_paths.clone();
83 move |rt| {
84 for (arch, out_vars) in reqs {
85 let msvm_fd = local_paths.get(&arch).ok_or_else(|| {
86 anyhow::anyhow!("No local path specified for architecture {:?}", arch)
87 })?;
88 for var in out_vars {
89 log::info!(
90 "using local uefi for {} at path {:?}",
91 match arch {
92 MuMsvmArch::X86_64 => "x64",
93 MuMsvmArch::Aarch64 => "aarch64",
94 },
95 msvm_fd
96 );
97 rt.write(var, msvm_fd);
98 }
99 }
100 Ok(())
101 }
102 });
103
104 return Ok(());
105 }
106
107 let version = version.expect("local paths handled above");
108 let extract_zip_deps = flowey_lib_common::_util::extract::extract_zip_if_new_deps(ctx);
109
110 for (arch, out_vars) in reqs {
111 let file_name = match arch {
112 MuMsvmArch::X86_64 => "RELEASE-X64-artifacts.zip",
113 MuMsvmArch::Aarch64 => "RELEASE-AARCH64-artifacts.zip",
114 };
115
116 let mu_msvm_zip = ctx.reqv(|v| flowey_lib_common::download_gh_release::Request {
117 repo_owner: "microsoft".into(),
118 repo_name: "mu_msvm".into(),
119 needs_auth: false,
120 tag: format!("v{version}"),
121 file_name: file_name.into(),
122 path: v,
123 });
124
125 let zip_file_version = format!("{version}-{file_name}");
126
127 ctx.emit_rust_step(
128 {
129 format!(
130 "unpack mu_msvm package ({})",
131 match arch {
132 MuMsvmArch::X86_64 => "x64",
133 MuMsvmArch::Aarch64 => "aarch64",
134 },
135 )
136 },
137 |ctx| {
138 let extract_zip_deps = extract_zip_deps.clone().claim(ctx);
139 let out_vars = out_vars.claim(ctx);
140 let mu_msvm_zip = mu_msvm_zip.claim(ctx);
141 move |rt| {
142 let mu_msvm_zip = rt.read(mu_msvm_zip);
143
144 let extract_dir = flowey_lib_common::_util::extract::extract_zip_if_new(
145 rt,
146 extract_zip_deps,
147 &mu_msvm_zip,
148 &zip_file_version,
149 )?;
150
151 let msvm_fd = extract_dir.join("FV/MSVM.fd");
152
153 for var in out_vars {
154 rt.write(var, &msvm_fd)
155 }
156
157 Ok(())
158 }
159 },
160 );
161 }
162
163 Ok(())
164 }
165}