Description
When you construct a HashMap inside a UEFI environment that does not support the RNG protocol, there will be a panic.
Here is a repo containing a minimal working repro of this issue: https://github.com/ifd3f/uefi-hashmap-panic-repro
I modified the uefi-std-example from the uefi-rs repo to construct a hashmap:
#![feature(uefi_std)]
use std::os::uefi as uefi_std;
use std::collections::HashMap;
use uefi::runtime::ResetType;
use uefi::{boot, Handle, Status};
/// Performs the necessary setup code for the `uefi` crate.
fn setup_uefi_crate() {
let st = uefi_std::env::system_table();
let ih = uefi_std::env::image_handle();
// Mandatory setup code for `uefi` crate.
unsafe {
uefi::table::set_system_table(st.as_ptr().cast());
let ih = Handle::from_ptr(ih.as_ptr().cast()).unwrap();
uefi::boot::set_image_handle(ih);
}
}
fn main() {
println!("Hello World from uefi_std");
setup_uefi_crate();
println!("UEFI-Version is {}", uefi::system::uefi_revision());
// Attach panic hook so we can actually read the errors
std::panic::set_hook(Box::new(|p| {
let backtrace = std::backtrace::Backtrace::capture();
println!("{p}");
println!("{backtrace}");
loop {
boot::stall(1_000_000_000)
}
}));
let map = HashMap::<String, String>::new();
println!("Successfully constructed a hashmap! {map:?}");
loop {
boot::stall(1_000_000_000)
}
}
Running this in QEMU with OVMF firmware, instead of constructing the HashMap and printing it, it produces the following output:
BdsDxe: loading Boot0001 "UEFI QEMU HARDDISK QM00001 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)
BdsDxe: starting Boot0001 "UEFI QEMU HARDDISK QM00001 " from PciRoot(0x0)/Pci(0x1,0x1)/Ata(Primary,Master,0x0)
Hello World from uefi_std
UEFI-Version is 2.7
panicked at library/std/src/sys/random/uefi.rs:7:53:
failed to generate random data: Os { code: 9223372036854775822, kind: NotFound, message: "The item was not found." }
disabled backtrace
Based on the panic, my understanding is that this happens because:
- HashMap uses RandomState to randomly seed itself with the environment's secure RNG
- The RNG implementation delegates to the UEFI environment's RNG protocol
OVMF (or perhaps the way I set up QEMU) does not provide an RNG protocolThe VM does not have an RNG, so the EFI environment does not advertise any RNG protocols. Adding-device virtio-rng-pci
to the QEMU invocation does allow this code to work.
This is the set of commands used to set up ESP using a virtual VFAT partition, and to launch QEMU with that ESP:
cargo build --target x86_64-unknown-uefi --release
rm -rf esp
mkdir -p esp/efi/boot
cp -r target/x86_64-unknown-uefi/release/uefi-std-example.efi esp/efi/boot/bootx64.efi
qemu-system-x86_64 \
-D ./qemu.log \
-drive if=pflash,format=raw,readonly=on,file=./OVMF_CODE.fd \
-drive if=pflash,format=raw,readonly=on,file=./OVMF_VARS.fd \
-drive format=raw,file=fat:rw:esp
Meta
rustc --version --verbose
:
rustc 1.87.0-nightly (f5a1ef712 2025-03-07)
binary: rustc
commit-hash: f5a1ef7121ad661b5a21a1d02941c8064d54ee0b
commit-date: 2025-03-07
host: x86_64-unknown-linux-gnu
release: 1.87.0-nightly
LLVM version: 20.1.0
Backtrace: I could not produce a backtrace. Setting RUST_BACKTRACE=1
doesn't exactly work the same way in UEFI after all :)