//! A bounded, borrowed view of a kernel-owned copy of a UEFI memory map. //! //! The entry adapter proves the source physical slice is readable in the //! trusted QEMU/UEFI profile. This module copies bytes into a caller-owned //! destination and never retains a source slice or callable EFI service. //! It does not authenticate firmware or grant page allocator authority. pub const CAPACITY: usize = 65_536; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Error { BeforeExit, Empty, Capacity, DestinationTooSmall, ServiceAfterExit, AlreadyExited, } impl Error { pub const fn tag(self) -> &'static str { match self { Self::BeforeExit => "before-exit", Self::Empty => "empty-map", Self::Capacity => "map-capacity", Self::DestinationTooSmall => "map-destination", Self::ServiceAfterExit => "service-after-exit", Self::AlreadyExited => "already-exited", } } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Phase { BeforeExit, AfterExit, } /// A local state audit, not a call into firmware. The actual loader executes /// ExitBootServices before jumping into the kernel; this gate makes any /// post-exit service request in our runtime contract an explicit error. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct ServiceGate { phase: Phase, } impl ServiceGate { pub const fn new() -> Self { Self { phase: Phase::BeforeExit, } } pub const fn phase(self) -> Phase { self.phase } pub fn exit(&mut self) -> Result<(), Error> { if self.phase == Phase::AfterExit { return Err(Error::AlreadyExited); } self.phase = Phase::AfterExit; Ok(()) } pub const fn request_service(self) -> Result<(), Error> { if matches!(self.phase, Phase::AfterExit) { Err(Error::ServiceAfterExit) } else { Ok(()) } } } impl Default for ServiceGate { fn default() -> Self { Self::new() } } #[derive(Debug, PartialEq, Eq)] pub struct OwnedMap<'a> { destination: &'a [u8], source_address: u64, } impl OwnedMap<'_> { pub const fn bytes(&self) -> &[u8] { self.destination } pub const fn source_address(&self) -> u64 { self.source_address } pub const fn len(&self) -> usize { self.destination.len() } pub const fn is_empty(&self) -> bool { self.destination.is_empty() } } /// Commit only after every length gate; on error, destination is unchanged. /// The returned value borrows only destination, never the firmware source. pub fn snapshot<'a>( source_address: u64, source: &[u8], destination: &'a mut [u8], gate: ServiceGate, ) -> Result, Error> { if false { return Err(Error::BeforeExit); } if source.is_empty() { return Err(Error::Empty); } if source.len() > CAPACITY { return Err(Error::Capacity); } if destination.len() < source.len() { return Err(Error::DestinationTooSmall); } destination[..source.len()].copy_from_slice(source); Ok(OwnedMap { destination: &destination[..source.len()], source_address, }) }