uefi: add missing ExtendedInformation to ProcessorInformation

The PI spec defines EFI_PROCESSOR_INFORMATION with a trailing
EXTENDED_PROCESSOR_INFORMATION member (a union whose only member is
the 24-byte EFI_CPU_PHYSICAL_LOCATION2), making the struct 48 bytes.
The Rust struct was only 24 bytes.

get_processor_info passes the processor number through unvalidated,
so a caller could already set CPU_V2_EXTENDED_TOPOLOGY (bit 24) and
make the firmware write the extended topology 24 bytes past the
stack-allocated struct. Firmware performing a whole-struct copy
overflowed it even without that flag.

Add the missing field plus the CPU_V2_EXTENDED_TOPOLOGY constant so
the extended topology is actually usable.
This commit is contained in:
Philipp Schuster 2026-08-23 12:22:34 +02:00
parent 16666496e5
commit 23e1b8ec71
2 changed files with 42 additions and 0 deletions

View file

@ -1,6 +1,8 @@
# uefi - [Unreleased]
## Added
- Added `proto::pi::mp::{CpuPhysicalLocation2, CPU_V2_EXTENDED_TOPOLOGY}` for
the extended processor topology.
## Changed
- Made memory map types `#[repr(C)]`
@ -17,6 +19,9 @@
- `proto::network::pxe::DiscoverInfo::new_in_buffer` now accounts for the
alignment padding before the server list in its buffer size check.
Previously, an exactly-sized buffer was written 2 bytes out of bounds.
- **Breaking:** `proto::pi::mp::ProcessorInformation` now contains the
`extended_information` field mandated by the PI specification. Previously,
the struct was 24 bytes too small, which firmware could write past.
## Removed

View file

@ -49,6 +49,12 @@ pub struct ProcessorCount {
pub enabled: usize,
}
/// Flag for [`MpServices::get_processor_info`] requesting the extended
/// topology in [`ProcessorInformation::extended_information`].
///
/// Corresponds to `CPU_V2_EXTENDED_TOPOLOGY` in the PI specification.
pub const CPU_V2_EXTENDED_TOPOLOGY: usize = 1 << 24;
/// Information about processor on the platform.
#[repr(C)]
#[derive(Default, Debug)]
@ -59,6 +65,13 @@ pub struct ProcessorInformation {
status_flag: StatusFlag,
/// Physical location of the processor.
pub location: CpuPhysicalLocation,
/// Extended physical location of the processor.
///
/// Only filled by the firmware if [`CPU_V2_EXTENDED_TOPOLOGY`] is set in
/// the processor number passed to [`MpServices::get_processor_info`].
// The PI spec wraps this in EXTENDED_PROCESSOR_INFORMATION, a union with
// Location2 as its only member; the wrapper is skipped here.
pub extended_information: CpuPhysicalLocation2,
}
impl ProcessorInformation {
@ -95,6 +108,27 @@ pub struct CpuPhysicalLocation {
pub thread: u32,
}
/// Information about the 6-level physical location of the processor.
///
/// Corresponds to `EFI_CPU_PHYSICAL_LOCATION2` in the PI specification.
#[repr(C)]
#[derive(Default, Debug)]
pub struct CpuPhysicalLocation2 {
/// Zero-based physical package number that identifies
/// the cartridge of the processor.
pub package: u32,
/// Zero-based physical module number within package of the processor.
pub module: u32,
/// Zero-based physical tile number within module of the processor.
pub tile: u32,
/// Zero-based physical die number within tile of the processor.
pub die: u32,
/// Zero-based physical core number within die of the processor.
pub core: u32,
/// Zero-based logical thread number within core of the processor.
pub thread: u32,
}
/// MP Services [`Protocol`].
///
/// Protocol that provides services needed for multi-processor management.
@ -156,6 +190,9 @@ impl MpServices {
}
/// Gets detailed information on the requested processor at the instant this call is made.
///
/// Set [`CPU_V2_EXTENDED_TOPOLOGY`] in `processor_number` to also
/// retrieve [`ProcessorInformation::extended_information`].
pub fn get_processor_info(&self, processor_number: usize) -> Result<ProcessorInformation> {
let mut pi: ProcessorInformation = Default::default();
(self.get_processor_info)(self, processor_number, &mut pi).to_result_with_val(|| pi)