firmware_uefi: Add version checks for EfiDiagnostics#3109
firmware_uefi: Add version checks for EfiDiagnostics#3109maheeraeron wants to merge 5 commits intomicrosoft:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the UEFI diagnostics (Advanced Logger) parsing to handle PEI log buffer relocation by following a header-provided pointer chain and validating the expected header version, so the host continues reading the correct buffer after ExitBootServices.
Changes:
- Extend the
AdvancedLoggerInfospec withnew_logger_info_addressplus constants for expected version and max chain depth. - Update diagnostics services to reset the
processedflag when the advertised diagnostics GPA changes. - Teach header parsing to validate the header version and follow
new_logger_info_addressup to a bounded depth.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| vm/devices/firmware/uefi_specs/src/hyperv/advanced_logger.rs | Adds new_logger_info_address to the shared header struct and introduces version/chain-depth constants used by the host parser. |
| vm/devices/firmware/firmware_uefi/src/service/diagnostics/mod.rs | Resets processed when the GPA changes, allowing a relocated buffer to be reprocessed. |
| vm/devices/firmware/firmware_uefi/src/service/diagnostics/header.rs | Adds version validation and implements chain-following logic to find the relocated final buffer header. |
vm/devices/firmware/firmware_uefi/src/service/diagnostics/header.rs
Outdated
Show resolved
Hide resolved
vm/devices/firmware/firmware_uefi/src/service/diagnostics/header.rs
Outdated
Show resolved
Hide resolved
vm/devices/firmware/firmware_uefi/src/service/diagnostics/header.rs
Outdated
Show resolved
Hide resolved
| // #[vmm_test_with(noagent( | ||
| // hyperv_openhcl_uefi_x64(none), | ||
| // hyperv_openhcl_uefi_aarch64(none), | ||
| // openvmm_openhcl_uefi_x64(none) | ||
| // ))] | ||
| async fn _efi_diagnostics_no_boot<T: PetriVmmBackend>( | ||
| _config: PetriVmBuilder<T>, | ||
| ) -> anyhow::Result<()> { | ||
| let vm = config.with_uefi_frontpage(true).run_without_agent().await?; | ||
| // let vm = config.with_uefi_frontpage(true).run_without_agent().await?; | ||
|
|
||
| // Expected no-boot message. | ||
| const NO_BOOT_MSG: &str = "[Bds] Unable to boot!"; | ||
| // // Expected no-boot message. | ||
| // const NO_BOOT_MSG: &str = "[Bds] Unable to boot!"; | ||
|
|
||
| // Get kmsg stream | ||
| let mut kmsg = vm.kmsg().await?; | ||
| // // Get kmsg stream | ||
| // let mut kmsg = vm.kmsg().await?; | ||
|
|
||
| // Search for the message | ||
| while let Some(data) = kmsg.next().await { | ||
| let data = data.context("reading kmsg")?; | ||
| let msg = kmsg::KmsgParsedEntry::new(&data).unwrap(); | ||
| let raw = msg.message.as_raw(); | ||
| if raw.contains(NO_BOOT_MSG) { | ||
| return Ok(()); | ||
| } | ||
| } | ||
| // // Search for the message | ||
| // while let Some(data) = kmsg.next().await { | ||
| // let data = data.context("reading kmsg")?; | ||
| // let msg = kmsg::KmsgParsedEntry::new(&data).unwrap(); | ||
| // let raw = msg.message.as_raw(); | ||
| // if raw.contains(NO_BOOT_MSG) { | ||
| // return Ok(()); | ||
| // } | ||
| // } | ||
|
|
||
| anyhow::bail!("Did not find expected message in kmsg"); | ||
| // anyhow::bail!("Did not find expected message in kmsg"); | ||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
The efi_diagnostics_no_boot test is effectively removed by commenting out the #[vmm_test_with] attribute and replacing the body with commented code + Ok(()). This makes the test logic stop being type-checked and silently reduces coverage. Prefer disabling it in a structured way (e.g., a cfg/feature gate or a supported ignore/skip mechanism in the test macro) while keeping the real body compiled, and ensure the function doesn’t introduce a dead_code warning (e.g., via #[expect(dead_code)]/#[allow(dead_code)] if it must remain present).
| pub const ADVANCED_LOGGER_INFO_VERSION: u16 = 6; | ||
|
|
||
| /// Maximum depth when following the NewLoggerInfoAddress chain | ||
| pub const MAX_LOGGER_CHAIN_DEPTH: usize = 3; |
There was a problem hiding this comment.
MAX_LOGGER_CHAIN_DEPTH is introduced here but isn’t referenced anywhere in the repository. If host-side chaining is no longer implemented, consider removing this constant (or making it private) to avoid leaving a misleading, unused API surface.
| pub const MAX_LOGGER_CHAIN_DEPTH: usize = 3; | |
| const MAX_LOGGER_CHAIN_DEPTH: usize = 3; |
NOTE: This PR adds version enforcement to EfiDiagnostics. The current UEFI consumed uses an older version of the advanced logger and would fail. Do not merge this until a new UEFI is ready to be consumed.
A UEFI submodule update to AdvLoggerPkg v6 introduced buffer relocation: at EndOfDxe, the PEI log buffer is copied from boot-services memory to reserved memory, with the old header's NewLoggerInfoAddress pointing to the new location. After ExitBootServices, the OS can reclaim the original boot-services buffer, so the host must follow the chain to the relocated buffer.
This is fixed via UEFI, but this specific OpenVMM/OpenHCL PR focuses on adding version checks to capture these issues faster.
NOTE: This PR disables the efi_diagnostics_no_boot test.