123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- use core::marker::PhantomData;
- /// This Tag provides an initial host memory map.
- ///
- /// The map provided is guaranteed to list all standard RAM that should be
- /// available for normal use. This type however includes the regions occupied
- /// by kernel, mbi, segments and modules. Kernel must take care not to
- /// overwrite these regions.
- ///
- /// This tag may not be provided by some boot loaders on EFI platforms if EFI
- /// boot services are enabled and available for the loaded image (The EFI boot
- /// services tag may exist in the Multiboot2 boot information structure).
- #[derive(Debug)]
- #[repr(C)]
- pub struct MemoryMapTag {
- typ: u32,
- size: u32,
- entry_size: u32,
- entry_version: u32,
- first_area: MemoryArea,
- }
- impl MemoryMapTag {
- /// Return an iterator over all AVAILABLE marked memory areas.
- pub fn memory_areas(&self) -> MemoryAreaIter {
- let self_ptr = self as *const MemoryMapTag;
- let start_area = (&self.first_area) as *const MemoryArea;
- MemoryAreaIter {
- current_area: start_area as u64,
- last_area: (self_ptr as u64 + (self.size - self.entry_size) as u64),
- entry_size: self.entry_size,
- phantom: PhantomData,
- }
- }
- }
- /// A memory area entry descriptor.
- #[derive(Debug)]
- #[repr(C)]
- pub struct MemoryArea {
- base_addr: u64,
- length: u64,
- typ: u32,
- _reserved: u32,
- }
- impl MemoryArea {
- /// The start address of the memory region.
- pub fn start_address(&self) -> u64 {
- self.base_addr
- }
- /// The end address of the memory region.
- pub fn end_address(&self) -> u64 {
- self.base_addr + self.length
- }
- /// The size, in bytes, of the memory region.
- pub fn size(&self) -> u64 {
- self.length
- }
- /// The type of the memory region.
- pub fn typ(&self) -> MemoryAreaType {
- match self.typ {
- 1 => MemoryAreaType::Available,
- 3 => MemoryAreaType::AcpiAvailable,
- 4 => MemoryAreaType::ReservedHibernate,
- 5 => MemoryAreaType::Defective,
- _ => MemoryAreaType::Reserved,
- }
- }
- }
- /// An enum of possible reported region types.
- #[derive(Debug, PartialEq, Eq)]
- pub enum MemoryAreaType {
- /// A reserved area that must not be used.
- Reserved,
- /// Available memory free to be used by the OS.
- Available,
- /// Usable memory holding ACPI information.
- AcpiAvailable,
- /// Reserved memory which needs to be preserved on hibernation.
- ReservedHibernate,
- /// Memory which is occupied by defective RAM modules.
- Defective,
- }
- /// An iterator over Available memory areas.
- #[derive(Clone, Debug)]
- pub struct MemoryAreaIter<'a> {
- current_area: u64,
- last_area: u64,
- entry_size: u32,
- phantom: PhantomData<&'a MemoryArea>,
- }
- impl<'a> Iterator for MemoryAreaIter<'a> {
- type Item = &'a MemoryArea;
- fn next(&mut self) -> Option<&'a MemoryArea> {
- if self.current_area > self.last_area {
- None
- } else {
- let area = unsafe{&*(self.current_area as *const MemoryArea)};
- self.current_area = self.current_area + (self.entry_size as u64);
- if area.typ == 1 {
- Some(area)
- } else {self.next()}
- }
- }
- }
- /// EFI memory map as per EFI specification.
- #[derive(Debug)]
- #[repr(C)]
- pub struct EFIMemoryMapTag {
- typ: u32,
- size: u32,
- desc_size: u32,
- desc_version: u32,
- first_desc: EFIMemoryDesc,
- }
- impl EFIMemoryMapTag {
- /// Return an iterator over ALL marked memory areas.
- ///
- /// This differs from `MemoryMapTag` as for UEFI, the OS needs some non-
- /// available memory areas for tables and such.
- pub fn memory_areas(&self) -> EFIMemoryAreaIter {
- let self_ptr = self as *const EFIMemoryMapTag;
- let start_area = (&self.first_desc) as *const EFIMemoryDesc;
- EFIMemoryAreaIter {
- current_area: start_area as u64,
- last_area: (self_ptr as u64 + self.size as u64),
- entry_size: self.desc_size,
- phantom: PhantomData,
- }
- }
- }
- /// EFI Boot Memory Map Descriptor
- #[derive(Debug)]
- #[repr(C)]
- pub struct EFIMemoryDesc {
- typ: u32,
- _padding: u32,
- phys_addr: u64,
- virt_addr: u64,
- num_pages: u64,
- attr: u64,
- }
- /// An enum of possible reported region types.
- #[derive(Debug, PartialEq, Eq)]
- pub enum EFIMemoryAreaType {
- /// Unusable.
- EfiReservedMemoryType,
- /// Code area of a UEFI application.
- EfiLoaderCode,
- /// Data area of a UEFI application.
- EfiLoaderData,
- /// Code area of a UEFI Boot Service Driver.
- EfiBootServicesCode,
- /// Data area of a UEFI Boot Service Driver.
- EfiBootServicesData,
- /// Code area of a UEFI Runtime Driver.
- ///
- /// Must be preserved in working and ACPI S1-S3 states.
- EfiRuntimeServicesCode,
- /// Data area of a UEFI Runtime Driver.
- ///
- /// Must be preserved in working and ACPI S1-S3 states.
- EfiRuntimeServicesData,
- /// Available memory.
- EfiConventionalMemory,
- /// Memory with errors, treat as unusable.
- EfiUnusableMemory,
- /// Memory containing the ACPI tables.
- ///
- /// Must be preserved in working and ACPI S1-S3 states.
- EfiACPIReclaimMemory,
- /// Memory reserved by firmware.
- ///
- /// Must be preserved in working and ACPI S1-S3 states.
- EfiACPIMemoryNVS,
- /// Memory used by firmware for requesting memory mapping of IO.
- ///
- /// Should not be used by the OS. Use the ACPI tables for memory mapped IO
- /// information.
- EfiMemoryMappedIO,
- /// Memory used to translate memory cycles to IO cycles.
- ///
- /// Should not be used by the OS. Use the ACPI tables for memory mapped IO
- /// information.
- EfiMemoryMappedIOPortSpace,
- /// Memory used by the processor.
- ///
- /// Must be preserved in working and ACPI S1-S4 states. Processor defined
- /// otherwise.
- EfiPalCode,
- /// Available memory supporting byte-addressable non-volatility.
- EfiPersistentMemory,
- /// Unknown region type, treat as unusable.
- EfiUnknown,
- }
- impl EFIMemoryDesc {
- /// The physical address of the memory region.
- pub fn physical_address(&self) -> u64 {
- self.phys_addr
- }
- /// The virtual address of the memory region.
- pub fn virtual_address(&self) -> u64 {
- self.virt_addr
- }
- /// The size in bytes of the memory region.
- pub fn size(&self, page_size: u64) -> usize {
- (self.num_pages * page_size) as usize
- }
- /// The type of the memory region.
- pub fn typ(&self) -> EFIMemoryAreaType {
- match self.typ {
- 0 => EFIMemoryAreaType::EfiReservedMemoryType,
- 1 => EFIMemoryAreaType::EfiLoaderCode,
- 2 => EFIMemoryAreaType::EfiLoaderData,
- 3 => EFIMemoryAreaType::EfiBootServicesCode,
- 4 => EFIMemoryAreaType::EfiBootServicesData,
- 5 => EFIMemoryAreaType::EfiRuntimeServicesCode,
- 6 => EFIMemoryAreaType::EfiRuntimeServicesData,
- 7 => EFIMemoryAreaType::EfiConventionalMemory,
- 8 => EFIMemoryAreaType::EfiUnusableMemory,
- 9 => EFIMemoryAreaType::EfiACPIReclaimMemory,
- 10 => EFIMemoryAreaType::EfiACPIMemoryNVS,
- 11 => EFIMemoryAreaType::EfiMemoryMappedIO,
- 12 => EFIMemoryAreaType::EfiMemoryMappedIOPortSpace,
- 13 => EFIMemoryAreaType::EfiPalCode,
- 14 => EFIMemoryAreaType::EfiPersistentMemory,
- _ => EFIMemoryAreaType::EfiUnknown,
- }
- }
- }
- /// EFI ExitBootServices was not called
- #[derive(Debug)]
- #[repr(C)]
- pub struct EFIBootServicesNotExited {
- typ: u32,
- size: u32,
- }
- /// Contains pointer to boot loader image handle.
- #[derive(Debug)]
- #[repr(C)]
- pub struct EFIImageHandle32 {
- typ: u32,
- size: u32,
- pointer: u32,
- }
- /// Contains pointer to boot loader image handle.
- #[derive(Debug)]
- #[repr(C)]
- pub struct EFIImageHandle64 {
- typ: u32,
- size: u32,
- pointer: u64,
- }
- /// If the image has relocatable header tag, this tag contains the image's
- /// base physical address.
- #[derive(Debug)]
- #[repr(C)]
- pub struct ImageLoadPhysAddr {
- typ: u32,
- size: u32,
- load_base_addr: u32,
- }
- /// An iterator over All EFI memory areas.
- #[derive(Clone, Debug)]
- pub struct EFIMemoryAreaIter<'a> {
- current_area: u64,
- last_area: u64,
- entry_size: u32,
- phantom: PhantomData<&'a EFIMemoryDesc>,
- }
- impl<'a> Iterator for EFIMemoryAreaIter<'a> {
- type Item = &'a EFIMemoryDesc;
- fn next(&mut self) -> Option<&'a EFIMemoryDesc> {
- if self.current_area > self.last_area {
- None
- } else {
- let area = unsafe{&*(self.current_area as *const EFIMemoryDesc)};
- self.current_area = self.current_area + (self.entry_size as u64);
- if area.typ() == EFIMemoryAreaType::EfiConventionalMemory {
- Some(area)
- } else {self.next()}
- }
- }
- }
|