Repository navigation
ged: load overload UEFI images for LoadFirmware - #5064
Open
Mike Ebersol (mebersol) wants to merge 2 commits into
Open
Mike Ebersol (mebersol) wants to merge 2 commits into
Mike Ebersol (mebersol) wants to merge 2 commits into
Conversation
The GED now carries a catalog of VTL0 UEFI images keyed by LoadFirmware token. On a matching request it writes the image into guest memory at the loader's base GPA and returns the image's entry point offset; unknown tokens get INVALID_TOKEN and write failures get FAILED. The loader exposes uefi::image_layout for the per-architecture base and entry offset. OpenVMM populates the catalog from the default UEFI firmware (OPENVMM_UEFI_FIRMWARE), keyed by the token from its mu_msvm version record. Petri passes an empty catalog for now.
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical issues can leave guest memory partially overwritten after failure, accept incompatible firmware, and panic during startup on malformed images.
4 open issues
What changed in this PR
This PR enables OpenVMM’s Guest Emulation Device to load token-selected UEFI firmware for OpenHCL hibernation resume, replacing the previous acknowledgement-only behavior.
Changes:
- Adds a firmware catalog and writes matching images into guest memory, returning an entry offset or failure status.
- Adds image-layout and version-token helpers, and populates OpenVMM’s catalog from the default firmware.
- Tests successful loading, unknown tokens, and write failures; leaves Petri’s catalog empty.
| File | Description |
|---|---|
vm/loader/src/uefi/mod.rs |
Exposes image layouts and shares ARM64 load constants. |
vm/devices/get/guest_emulation_transport/src/lib.rs |
Tests firmware writes, entry offsets, and failure statuses. |
vm/devices/get/guest_emulation_device/src/test_utilities.rs |
Provides a test firmware catalog entry. |
vm/devices/get/guest_emulation_device/src/resolver.rs |
Converts resource catalog entries into device configuration. |
vm/devices/get/guest_emulation_device/src/lib.rs |
Implements token lookup, image writes, and status responses. |
vm/devices/get/get_resources/src/lib.rs |
Adds serializable firmware catalog resources. |
petri/src/vm/openvmm/construct.rs |
Initializes an empty firmware catalog. |
openvmm/openvmm_helpers/src/uefi_overload.rs |
Builds catalog entries from firmware layouts and version tokens. |
openvmm/openvmm_helpers/src/lib.rs |
Exports the overload helper module. |
openvmm/openvmm_helpers/Cargo.toml |
Adds the loader dependency. |
openvmm/openvmm_entry/src/lib.rs |
Loads the default firmware into the catalog. |
Cargo.lock |
Records the helper’s loader dependency. |
Review effort: Balanced
|
|
||
| /// Builds the GED overload image that loads `image` for `token`. | ||
| pub fn uefi_overload_image(token: u64, image: Vec<u8>) -> anyhow::Result<UefiOverloadImage> { | ||
| let layout = loader::uefi::image_layout(&image).context("invalid uefi image")?; |
| .find(|image| image.token == firmware_token); | ||
| let (status, entry_offset) = match image { | ||
| None => (get_protocol::LoadFirmwareStatus::INVALID_TOKEN, 0), | ||
| Some(image) => match self.gm.write_at(image.base_gpa, &image.image) { |
| if image.len() != IMAGE_SIZE as usize { | ||
| return Err(Error::InvalidImageSize); | ||
| } | ||
| let entry_offset = get_sec_entry_point_offset(image).ok_or(Error::NoSecEntryPoint)?; |
| Ok(UefiOverloadImage { | ||
| token, | ||
| base_gpa: layout.base_gpa, | ||
| entry_offset: layout.entry_offset, |
Also document the aarch64 entry offset (0x1000) and that a zero offset leaves the entry point unchanged. Petri gains with_uefi_overload_firmware, and the hibernate overload tests now cover both outcomes deterministically: 1.8 overloads end to end, 1.7 is rejected and falls back to the current token.
Comment on lines
+1970
to
+1973
| /// entry on x64, `0x1000` on aarch64), computed by the host. Valid only | ||
| /// when `status` is [`LoadFirmwareStatus::SUCCESS`]; the guest/paravisor | ||
| /// programs VTL0's entry point to `image_base + entry_point_image_offset`. | ||
| /// Zero leaves the entry point unchanged. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


OpenHCL asks the host to overload VTL0 firmware (
LoadFirmware) when resuming a hibernated guest whose hibernate token doesn't match the current UEFI. Until now OpenVMM's GED acknowledged every request with a zero offset without loading anything. This makes OpenVMM act like a real host.LoadFirmwaretoken (uefi_overload_images). For a matching token it writes the image into guest memory and returns the image's entry point offset. Unknown tokens getINVALID_TOKEN; a failed guest-memory write getsFAILED.loader::uefi::image_layoutreturns whereloadplaces an image and its entry point (x64:0x100000plus the SEC entry offset; aarch64:0plus0x1000). The aarch64 loader now uses the same constants.entry_point_image_offsetis now documented for aarch64 (0x1000), and zero is documented as "leave the entry point unchanged".uefi_overloadbuilds the catalog from a mu_msvm image: one entry under the token from the image's version record (major.minor), plus OpenHCL 1.8's legacy token0x0108. 1.8 shipped a 26.0 UEFI, which the default image supersedes. 1.7 (0x0107) has no entry.OPENVMM_UEFI_FIRMWARE). If that file can't be read, it logs a warning and overload requests are rejected.with_uefi_overload_firmwarebuilder method fills the GED catalog from a UEFI firmware artifact. Tests opt in; the catalog is empty by default.Tests:
INVALID_TOKENandFAILEDcases.hibernate_token_overload(VMM test) seeds0x0108, so OpenHCL requests an overload on resume, and expects0x0108to be kept. It no longer has a skip path.hibernate_token_overload_rejected(VMM test) seeds0x0107; the host has no image for it, so the test expects OpenHCL to fall back to the current token.