Skip to content

Commit d438f61

Browse files
authored
Merge pull request #1970 from rust-osdev/bump-ovmf
xtask: update OVMF from EDK2-STABLE202502 to EDK2-STABLE202605
2 parents b28a872 + db204a2 commit d438f61

5 files changed

Lines changed: 161 additions & 52 deletions

File tree

Cargo.lock

Lines changed: 37 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

uefi-test-runner/src/proto/network/http.rs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,55 @@ pub fn test() {
8787

8888
// hard to find web sites which still allow plain http these days ...
8989
info!("Testing HTTP");
90-
fetch_http(*h, "http://example.com/").expect("http request failed: http://example.com");
91-
92-
// FYI: not all firmware builds support modern tls versions.
93-
// request() -> ABORTED typically is a tls handshake error.
94-
// check the firmware log for details.
95-
info!("Testing HTTPS");
96-
fetch_http(
97-
*h,
98-
"https://raw.githubusercontent.com/rust-osdev/uefi-rs/refs/heads/main/Cargo.toml",
99-
)
100-
.expect("https request failed");
90+
fetch_http(*h, "http://example.com/").expect("http request to http://example.com failed");
91+
92+
// Since edk2-stable202511, the default OpenSSL security level has been
93+
// raised from 0 to 3, which rejects older RSA-based keys. Unfortunately,
94+
// the EDK2 aarch64 build forcefully disables all EC-based keys
95+
// (-DEDK2_OPENSSL_NOEC=1), effectively preventing connections to most
96+
// HTTPS/TLS hosts. Temporarily disable this test on aarch64 until
97+
// EC-based keys are supported there.
98+
//
99+
// See https://github.com/rust-osdev/uefi-rs/issues/1975
100+
#[cfg(not(target_arch = "aarch64"))]
101+
{
102+
// EDK2 uses platform-specific OpenSSL configurations, which can affect
103+
// certificate compatibility with HTTPS hosts. Because both our test
104+
// hosts and their certificates may change, try multiple candidates and
105+
// require at least one request to succeed.
106+
//
107+
// Not all firmware builds support modern tls versions.
108+
// request() -> ABORTED typically is a tls handshake error.
109+
// check the firmware log for details.
110+
let https_url_candidates = [
111+
"https://example.com/",
112+
"https://raw.githubusercontent.com/rust-osdev/uefi-rs/refs/heads/main/Cargo.toml",
113+
"https://www.cloudflare.com/",
114+
"https://www.google.com/",
115+
];
116+
117+
info!("Testing HTTPS");
118+
let https_results = https_url_candidates
119+
.iter()
120+
.map(|url| (url, fetch_http(*h, url)))
121+
.collect::<Vec<_>>();
122+
for (url, res) in &https_results {
123+
debug!(
124+
"HTTPS request to: {url}: {}",
125+
if res.is_some() { "OK" } else { "FAILED" }
126+
);
127+
}
128+
assert!(
129+
https_results.iter().any(|(_, res)| res.is_some()),
130+
"No HTTPS request succeeded"
131+
);
132+
}
133+
134+
#[cfg(target_arch = "aarch64")]
135+
{
136+
// See https://github.com/rust-osdev/uefi-rs/issues/1975
137+
warn!("Skipping HTTPS test on aarch64 (see #1975)");
138+
}
101139

102140
info!("PASSED");
103141
}

uefi/src/proto/network/http.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ impl Http {
4343
/// Configure HTTP Protocol. Must be called before sending HTTP requests.
4444
pub fn configure(&mut self, config_data: &HttpConfigData) -> uefi::Result<()> {
4545
let status = unsafe { (self.0.configure)(&mut self.0, config_data) };
46+
debug!("http raw: configure({config_data:?}) -> {status}");
4647
match status {
4748
Status::SUCCESS => Ok(()),
4849
_ => Err(status.into()),
@@ -52,6 +53,12 @@ impl Http {
5253
/// Send HTTP request.
5354
pub fn request(&mut self, token: &mut HttpToken) -> uefi::Result<()> {
5455
let status = unsafe { (self.0.request)(&mut self.0, token) };
56+
debug!(
57+
"http raw: request(headers={}, body_len={}) -> {status}, token.status={}",
58+
unsafe { (*token.message).header_count },
59+
unsafe { (*token.message).body_length },
60+
token.status,
61+
);
5562
match status {
5663
Status::SUCCESS => Ok(()),
5764
_ => Err(status.into()),
@@ -70,6 +77,11 @@ impl Http {
7077
/// Receive HTTP response.
7178
pub fn response(&mut self, token: &mut HttpToken) -> uefi::Result<()> {
7279
let status = unsafe { (self.0.response)(&mut self.0, token) };
80+
debug!(
81+
"http raw: response(body_len={}) -> {status}, token.status={}",
82+
unsafe { (*token.message).body_length },
83+
token.status,
84+
);
7385
match status {
7486
Status::SUCCESS => Ok(()),
7587
_ => Err(status.into()),
@@ -211,12 +223,16 @@ impl HttpHelper {
211223
) -> uefi::Result<()> {
212224
let url16 = uefi::CString16::try_from(url).unwrap();
213225

226+
let scheme = url.split(':').next().unwrap_or("<missing>");
214227
let Some(hostname) = url.split('/').nth(2) else {
215228
return Err(Status::INVALID_PARAMETER.into());
216229
};
217230
let mut c_hostname = String::from(hostname);
218231
c_hostname.push('\0');
219-
debug!("http: host: {hostname}");
232+
debug!(
233+
"http: request setup: method={method:?}, scheme={scheme}, host={hostname}, body_len={}",
234+
body.as_ref().map_or(0, |body| body.len())
235+
);
220236

221237
let mut tx_req = HttpRequestData {
222238
method,
@@ -248,12 +264,18 @@ impl HttpHelper {
248264
p.request(&mut tx_token)?;
249265
debug!("http: request sent ok");
250266

267+
let mut polls = 0;
251268
loop {
252269
if tx_token.status != Status::NOT_READY {
253270
break;
254271
}
272+
polls += 1;
255273
p.poll()?;
256274
}
275+
debug!(
276+
"http: request token completed after {polls} polls with {}",
277+
tx_token.status
278+
);
257279

258280
if tx_token.status != Status::SUCCESS {
259281
return Err(tx_token.status.into());

xtask/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ itertools = "0.14.0"
1515
log.workspace = true
1616
mbrman = "0.6.0"
1717
nix = { version = "0.31.0", default-features = false, features = ["fs"] }
18-
ovmf-prebuilt = "0.2.3"
18+
ovmf-prebuilt = "0.2.9"
1919
proc-macro2 = { version = "1.0.46", features = ["span-locations"] }
2020
quote = "1.0.21"
2121
regex = "1.10.2"

xtask/src/qemu.rs

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,25 @@ use tempfile::TempDir;
2121
use {std::fs::Permissions, std::os::unix::fs::PermissionsExt};
2222

2323
/// Name of the ovmf-prebuilt release to use by default.
24-
const OVMF_PREBUILT_SOURCE: Source = Source::EDK2_STABLE202502_R2;
24+
///
25+
/// This is typically the latest stable release.
26+
const OVMF_PREBUILT_SOURCE: Source = Source::EDK2_STABLE202605_R1;
27+
28+
/// Name of the ovmf-prebuilt release to use for IA32.
29+
///
30+
/// After EDK2_STABLE202508_R1, IA32 support was dropped in edk2.
31+
const OVMF_PREBUILT_IA32_SOURCE: Source = Source::EDK2_STABLE202508_R1;
2532

2633
/// Directory into which the prebuilts will be download (relative to the repo root).
2734
const OVMF_PREBUILT_DIR: &str = "target/ovmf";
2835

36+
fn ovmf_prebuilt_source(arch: UefiArch) -> Source {
37+
match arch {
38+
UefiArch::IA32 => OVMF_PREBUILT_IA32_SOURCE,
39+
UefiArch::AArch64 | UefiArch::X86_64 => OVMF_PREBUILT_SOURCE,
40+
}
41+
}
42+
2943
impl From<UefiArch> for ovmf_prebuilt::Arch {
3044
fn from(arch: UefiArch) -> Self {
3145
match arch {
@@ -52,6 +66,7 @@ struct OvmfPaths {
5266
code: PathBuf,
5367
vars: PathBuf,
5468
shell: PathBuf,
69+
prebuilt_source_tag: &'static str,
5570
}
5671

5772
impl OvmfPaths {
@@ -62,7 +77,12 @@ impl OvmfPaths {
6277
/// 1. Command-line arg
6378
/// 2. Environment variable
6479
/// 3. Prebuilt file (automatically downloaded)
65-
fn find_ovmf_file(file_type: FileType, opt: &QemuOpt, arch: UefiArch) -> Result<PathBuf> {
80+
fn find_ovmf_file(
81+
file_type: FileType,
82+
opt: &QemuOpt,
83+
arch: UefiArch,
84+
prebuilt: &Prebuilt,
85+
) -> Result<PathBuf> {
6686
if let Some(path) = get_user_provided_path(file_type, opt) {
6787
// The user provided an exact path to use; verify that it
6888
// exists.
@@ -76,20 +96,42 @@ impl OvmfPaths {
7696
);
7797
}
7898
} else {
79-
let prebuilt = Prebuilt::fetch(OVMF_PREBUILT_SOURCE, OVMF_PREBUILT_DIR)?;
80-
8199
Ok(prebuilt.get_file(arch.into(), file_type))
82100
}
83101
}
84102

85103
/// Find path to OVMF files by the strategy documented for
86104
/// [`Self::find_ovmf_file`].
87105
fn find(opt: &QemuOpt, arch: UefiArch) -> Result<Self> {
88-
let code = Self::find_ovmf_file(FileType::Code, opt, arch)?;
89-
let vars = Self::find_ovmf_file(FileType::Vars, opt, arch)?;
90-
let shell = Self::find_ovmf_file(FileType::Shell, opt, arch)?;
106+
let prebuilt_source = ovmf_prebuilt_source(arch);
107+
let prebuilt = Prebuilt::fetch(prebuilt_source.clone(), OVMF_PREBUILT_DIR)?;
108+
let code = Self::find_ovmf_file(FileType::Code, opt, arch, &prebuilt)?;
109+
let vars = Self::find_ovmf_file(FileType::Vars, opt, arch, &prebuilt)?;
110+
let shell = Self::find_ovmf_file(FileType::Shell, opt, arch, &prebuilt)?;
111+
112+
Ok(Self {
113+
code,
114+
vars,
115+
shell,
116+
prebuilt_source_tag: prebuilt_source.tag,
117+
})
118+
}
91119

92-
Ok(Self { code, vars, shell })
120+
fn log(&self, arch: UefiArch) {
121+
eprintln!("OVMF:");
122+
eprintln!(" version: {}", self.prebuilt_source_tag);
123+
if arch == UefiArch::IA32 {
124+
// https://github.com/tianocore/edk2/commit/1fb88ffe284782cc79e306306b8d19829b6248b7
125+
eprintln!(
126+
"{leftpadding}note: using this instead of {} as it is the last \
127+
release with IA32 support in edk2",
128+
OVMF_PREBUILT_SOURCE.tag,
129+
leftpadding = " ".repeat(11)
130+
);
131+
}
132+
eprintln!(" code : {}", self.code.display());
133+
eprintln!(" vars : {}", self.vars.display());
134+
eprintln!(" shell : {}", self.shell.display());
93135
}
94136
}
95137

@@ -422,6 +464,7 @@ pub fn run_qemu(arch: UefiArch, opt: &QemuOpt) -> Result<()> {
422464

423465
// Set up OVMF.
424466
let ovmf_paths = OvmfPaths::find(opt, arch)?;
467+
ovmf_paths.log(arch);
425468

426469
// Make a copy of the OVMF vars file so that it can be used
427470
// read+write without modifying the original. Under AArch64, some

0 commit comments

Comments
 (0)