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, ReadVar<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, ReadVar<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 local_paths.contains_key(&arch) {
49 anyhow::bail!("Duplicate LocalPath requests for {:?}", arch,);
50 }
51 local_paths.insert(arch, path);
52 }
53 Request::GetMsvmFd { arch, msvm_fd } => reqs.entry(arch).or_default().push(msvm_fd),
54 }
55 }
56
57 if version.is_some() && !local_paths.is_empty() {
58 anyhow::bail!("Cannot specify both Version and LocalPath requests");
59 }
60
61 if version.is_none() && local_paths.is_empty() {
62 anyhow::bail!("Must specify a Version or LocalPath request");
63 }
64
65 if reqs.is_empty() {
68 return Ok(());
69 }
70
71 if !local_paths.is_empty() {
72 ctx.emit_rust_step("use local mu_msvm UEFI", |ctx| {
73 let reqs = reqs.claim(ctx);
74 let local_paths: BTreeMap<_, _> = local_paths
75 .into_iter()
76 .map(|(arch, var)| (arch, var.claim(ctx)))
77 .collect();
78 move |rt| {
79 for (arch, out_vars) in reqs {
80 let msvm_fd_var = local_paths.get(&arch).ok_or_else(|| {
81 anyhow::anyhow!("No local path specified for architecture {:?}", arch)
82 })?;
83 let msvm_fd = rt.read(msvm_fd_var.clone());
84 for var in out_vars {
85 log::info!(
86 "using local uefi for {} at path {:?}",
87 match arch {
88 MuMsvmArch::X86_64 => "x64",
89 MuMsvmArch::Aarch64 => "aarch64",
90 },
91 msvm_fd
92 );
93 rt.write(var, &msvm_fd);
94 }
95 }
96 Ok(())
97 }
98 });
99
100 return Ok(());
101 }
102
103 let version = version.expect("local paths handled above");
104 let extract_zip_deps = flowey_lib_common::_util::extract::extract_zip_if_new_deps(ctx);
105
106 for (arch, out_vars) in reqs {
107 let file_name = match arch {
108 MuMsvmArch::X86_64 => "RELEASE-X64-artifacts.zip",
109 MuMsvmArch::Aarch64 => "RELEASE-AARCH64-artifacts.zip",
110 };
111
112 let mu_msvm_zip = ctx.reqv(|v| flowey_lib_common::download_gh_release::Request {
113 repo_owner: "microsoft".into(),
114 repo_name: "mu_msvm".into(),
115 needs_auth: false,
116 tag: format!("v{version}"),
117 file_name: file_name.into(),
118 path: v,
119 });
120
121 let zip_file_version = format!("{version}-{file_name}");
122
123 ctx.emit_rust_step(
124 {
125 format!(
126 "unpack mu_msvm package ({})",
127 match arch {
128 MuMsvmArch::X86_64 => "x64",
129 MuMsvmArch::Aarch64 => "aarch64",
130 },
131 )
132 },
133 |ctx| {
134 let extract_zip_deps = extract_zip_deps.clone().claim(ctx);
135 let out_vars = out_vars.claim(ctx);
136 let mu_msvm_zip = mu_msvm_zip.claim(ctx);
137 move |rt| {
138 let mu_msvm_zip = rt.read(mu_msvm_zip);
139
140 let extract_dir = flowey_lib_common::_util::extract::extract_zip_if_new(
141 rt,
142 extract_zip_deps,
143 &mu_msvm_zip,
144 &zip_file_version,
145 )?;
146
147 let msvm_fd = extract_dir.join("FV/MSVM.fd");
148
149 for var in out_vars {
150 rt.write(var, &msvm_fd)
151 }
152
153 Ok(())
154 }
155 },
156 );
157 }
158
159 Ok(())
160 }
161}