use crate::data_types::PhysicalAddress;
use crate::mem::memory_map::MemoryAttribute;
use crate::proto::unsafe_protocol;
use crate::{Result, StatusExt};
use core::ops::Range;
use uefi_raw::protocol::memory_protection::MemoryAttributeProtocol;
#[cfg(doc)]
use crate::Status;
#[repr(transparent)]
#[derive(Debug)]
#[unsafe_protocol(MemoryAttributeProtocol::GUID)]
pub struct MemoryProtection(MemoryAttributeProtocol);
impl MemoryProtection {
pub fn get_memory_attributes(
&self,
byte_region: Range<PhysicalAddress>,
) -> Result<MemoryAttribute> {
let mut attributes = MemoryAttribute::empty();
let (base_address, length) = range_to_base_and_len(byte_region);
unsafe {
(self.0.get_memory_attributes)(&self.0, base_address, length, &mut attributes)
.to_result_with_val(|| attributes)
}
}
pub fn set_memory_attributes(
&self,
byte_region: Range<PhysicalAddress>,
attributes: MemoryAttribute,
) -> Result {
let (base_address, length) = range_to_base_and_len(byte_region);
unsafe {
(self.0.set_memory_attributes)(&self.0, base_address, length, attributes).to_result()
}
}
pub fn clear_memory_attributes(
&self,
byte_region: Range<PhysicalAddress>,
attributes: MemoryAttribute,
) -> Result {
let (base_address, length) = range_to_base_and_len(byte_region);
unsafe {
(self.0.clear_memory_attributes)(&self.0, base_address, length, attributes).to_result()
}
}
}
const fn range_to_base_and_len(r: Range<PhysicalAddress>) -> (PhysicalAddress, PhysicalAddress) {
(r.start, r.end.checked_sub(r.start).unwrap())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_range_conversion() {
assert_eq!(range_to_base_and_len(2..5), (2, 3));
}
}