Skip to content

Move various memory types to uefi-raw and re-export in uefi #791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 142 additions & 0 deletions uefi-raw/src/table/boot.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,147 @@
//! UEFI services available during boot.

use crate::{PhysicalAddress, VirtualAddress};
use bitflags::bitflags;

bitflags! {
/// Flags describing the capabilities of a memory range.
#[repr(transparent)]
pub struct MemoryAttribute: u64 {
/// Supports marking as uncacheable.
const UNCACHEABLE = 0x1;
/// Supports write-combining.
const WRITE_COMBINE = 0x2;
/// Supports write-through.
const WRITE_THROUGH = 0x4;
/// Support write-back.
const WRITE_BACK = 0x8;
/// Supports marking as uncacheable, exported and
/// supports the "fetch and add" semaphore mechanism.
const UNCACHABLE_EXPORTED = 0x10;
/// Supports write-protection.
const WRITE_PROTECT = 0x1000;
/// Supports read-protection.
const READ_PROTECT = 0x2000;
/// Supports disabling code execution.
const EXECUTE_PROTECT = 0x4000;
/// Persistent memory.
const NON_VOLATILE = 0x8000;
/// This memory region is more reliable than other memory.
const MORE_RELIABLE = 0x10000;
/// This memory range can be set as read-only.
const READ_ONLY = 0x20000;
/// This memory is earmarked for specific purposes such as for specific
/// device drivers or applications. This serves as a hint to the OS to
/// avoid this memory for core OS data or code that cannot be relocated.
const SPECIAL_PURPOSE = 0x4_0000;
/// This memory region is capable of being protected with the CPU's memory
/// cryptography capabilities.
const CPU_CRYPTO = 0x8_0000;
/// This memory must be mapped by the OS when a runtime service is called.
const RUNTIME = 0x8000_0000_0000_0000;
/// This memory region is described with additional ISA-specific memory
/// attributes as specified in `MemoryAttribute::ISA_MASK`.
const ISA_VALID = 0x4000_0000_0000_0000;
/// These bits are reserved for describing optional ISA-specific cache-
/// ability attributes that are not covered by the standard UEFI Memory
/// Attribute cacheability bits such as `UNCACHEABLE`, `WRITE_COMBINE`,
/// `WRITE_THROUGH`, `WRITE_BACK`, and `UNCACHEABLE_EXPORTED`.
///
/// See Section 2.3 "Calling Conventions" in the UEFI Specification
/// for further information on each ISA that takes advantage of this.
const ISA_MASK = 0x0FFF_F000_0000_0000;
}
}

/// A structure describing a region of memory.
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct MemoryDescriptor {
/// Type of memory occupying this range.
pub ty: MemoryType,
/// Starting physical address.
pub phys_start: PhysicalAddress,
/// Starting virtual address.
pub virt_start: VirtualAddress,
/// Number of 4 KiB pages contained in this range.
pub page_count: u64,
/// The capability attributes of this memory range.
pub att: MemoryAttribute,
}

impl MemoryDescriptor {
/// Memory descriptor version number.
pub const VERSION: u32 = 1;
}

impl Default for MemoryDescriptor {
fn default() -> MemoryDescriptor {
MemoryDescriptor {
ty: MemoryType::RESERVED,
phys_start: 0,
virt_start: 0,
page_count: 0,
att: MemoryAttribute::empty(),
}
}
}

newtype_enum! {
/// The type of a memory range.
///
/// UEFI allows firmwares and operating systems to introduce new memory types
/// in the 0x70000000..0xFFFFFFFF range. Therefore, we don't know the full set
/// of memory types at compile time, and it is _not_ safe to model this C enum
/// as a Rust enum.
pub enum MemoryType: u32 => {
/// This enum variant is not used.
RESERVED = 0,
/// The code portions of a loaded UEFI application.
LOADER_CODE = 1,
/// The data portions of a loaded UEFI applications,
/// as well as any memory allocated by it.
LOADER_DATA = 2,
/// Code of the boot drivers.
///
/// Can be reused after OS is loaded.
BOOT_SERVICES_CODE = 3,
/// Memory used to store boot drivers' data.
///
/// Can be reused after OS is loaded.
BOOT_SERVICES_DATA = 4,
/// Runtime drivers' code.
RUNTIME_SERVICES_CODE = 5,
/// Runtime services' code.
RUNTIME_SERVICES_DATA = 6,
/// Free usable memory.
CONVENTIONAL = 7,
/// Memory in which errors have been detected.
UNUSABLE = 8,
/// Memory that holds ACPI tables.
/// Can be reclaimed after they are parsed.
ACPI_RECLAIM = 9,
/// Firmware-reserved addresses.
ACPI_NON_VOLATILE = 10,
/// A region used for memory-mapped I/O.
MMIO = 11,
/// Address space used for memory-mapped port I/O.
MMIO_PORT_SPACE = 12,
/// Address space which is part of the processor.
PAL_CODE = 13,
/// Memory region which is usable and is also non-volatile.
PERSISTENT_MEMORY = 14,
}}

impl MemoryType {
/// Construct a custom `MemoryType`. Values in the range `0x80000000..=0xffffffff` are free for use if you are
/// an OS loader.
#[must_use]
pub const fn custom(value: u32) -> MemoryType {
assert!(value >= 0x80000000);
MemoryType(value)
}
}

newtype_enum! {
/// Task priority level.
///
Expand Down
143 changes: 2 additions & 141 deletions uefi/src/table/boot.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! UEFI services available during boot.

use super::{Header, Revision};
use crate::data_types::{Align, PhysicalAddress, VirtualAddress};
use crate::data_types::{Align, PhysicalAddress};
use crate::proto::device_path::{DevicePath, FfiDevicePath};
use crate::proto::{Protocol, ProtocolPointer};
use crate::{Char16, Event, Guid, Handle, Result, Status, StatusExt};
Expand All @@ -20,7 +20,7 @@ use {
::alloc::vec::Vec,
};

pub use uefi_raw::table::boot::Tpl;
pub use uefi_raw::table::boot::{MemoryAttribute, MemoryDescriptor, MemoryType, Tpl};

// TODO: this similar to `SyncUnsafeCell`. Once that is stabilized we
// can use it instead.
Expand Down Expand Up @@ -1814,151 +1814,12 @@ pub enum AllocateType {
Address(PhysicalAddress),
}

newtype_enum! {
/// The type of a memory range.
///
/// UEFI allows firmwares and operating systems to introduce new memory types
/// in the 0x70000000..0xFFFFFFFF range. Therefore, we don't know the full set
/// of memory types at compile time, and it is _not_ safe to model this C enum
/// as a Rust enum.
pub enum MemoryType: u32 => {
/// This enum variant is not used.
RESERVED = 0,
/// The code portions of a loaded UEFI application.
LOADER_CODE = 1,
/// The data portions of a loaded UEFI applications,
/// as well as any memory allocated by it.
LOADER_DATA = 2,
/// Code of the boot drivers.
///
/// Can be reused after OS is loaded.
BOOT_SERVICES_CODE = 3,
/// Memory used to store boot drivers' data.
///
/// Can be reused after OS is loaded.
BOOT_SERVICES_DATA = 4,
/// Runtime drivers' code.
RUNTIME_SERVICES_CODE = 5,
/// Runtime services' code.
RUNTIME_SERVICES_DATA = 6,
/// Free usable memory.
CONVENTIONAL = 7,
/// Memory in which errors have been detected.
UNUSABLE = 8,
/// Memory that holds ACPI tables.
/// Can be reclaimed after they are parsed.
ACPI_RECLAIM = 9,
/// Firmware-reserved addresses.
ACPI_NON_VOLATILE = 10,
/// A region used for memory-mapped I/O.
MMIO = 11,
/// Address space used for memory-mapped port I/O.
MMIO_PORT_SPACE = 12,
/// Address space which is part of the processor.
PAL_CODE = 13,
/// Memory region which is usable and is also non-volatile.
PERSISTENT_MEMORY = 14,
}}

impl MemoryType {
/// Construct a custom `MemoryType`. Values in the range `0x80000000..=0xffffffff` are free for use if you are
/// an OS loader.
#[must_use]
pub const fn custom(value: u32) -> MemoryType {
assert!(value >= 0x80000000);
MemoryType(value)
}
}

/// A structure describing a region of memory.
#[derive(Debug, Copy, Clone)]
#[repr(C)]
pub struct MemoryDescriptor {
/// Type of memory occupying this range.
pub ty: MemoryType,
/// Starting physical address.
pub phys_start: PhysicalAddress,
/// Starting virtual address.
pub virt_start: VirtualAddress,
/// Number of 4 KiB pages contained in this range.
pub page_count: u64,
/// The capability attributes of this memory range.
pub att: MemoryAttribute,
}

impl MemoryDescriptor {
/// Memory descriptor version number.
pub const VERSION: u32 = 1;
}

impl Default for MemoryDescriptor {
fn default() -> MemoryDescriptor {
MemoryDescriptor {
ty: MemoryType::RESERVED,
phys_start: 0,
virt_start: 0,
page_count: 0,
att: MemoryAttribute::empty(),
}
}
}

impl Align for MemoryDescriptor {
fn alignment() -> usize {
mem::align_of::<Self>()
}
}

bitflags! {
/// Flags describing the capabilities of a memory range.
#[repr(transparent)]
pub struct MemoryAttribute: u64 {
/// Supports marking as uncacheable.
const UNCACHEABLE = 0x1;
/// Supports write-combining.
const WRITE_COMBINE = 0x2;
/// Supports write-through.
const WRITE_THROUGH = 0x4;
/// Support write-back.
const WRITE_BACK = 0x8;
/// Supports marking as uncacheable, exported and
/// supports the "fetch and add" semaphore mechanism.
const UNCACHABLE_EXPORTED = 0x10;
/// Supports write-protection.
const WRITE_PROTECT = 0x1000;
/// Supports read-protection.
const READ_PROTECT = 0x2000;
/// Supports disabling code execution.
const EXECUTE_PROTECT = 0x4000;
/// Persistent memory.
const NON_VOLATILE = 0x8000;
/// This memory region is more reliable than other memory.
const MORE_RELIABLE = 0x10000;
/// This memory range can be set as read-only.
const READ_ONLY = 0x20000;
/// This memory is earmarked for specific purposes such as for specific
/// device drivers or applications. This serves as a hint to the OS to
/// avoid this memory for core OS data or code that cannot be relocated.
const SPECIAL_PURPOSE = 0x4_0000;
/// This memory region is capable of being protected with the CPU's memory
/// cryptography capabilities.
const CPU_CRYPTO = 0x8_0000;
/// This memory must be mapped by the OS when a runtime service is called.
const RUNTIME = 0x8000_0000_0000_0000;
/// This memory region is described with additional ISA-specific memory
/// attributes as specified in `MemoryAttribute::ISA_MASK`.
const ISA_VALID = 0x4000_0000_0000_0000;
/// These bits are reserved for describing optional ISA-specific cache-
/// ability attributes that are not covered by the standard UEFI Memory
/// Attribute cacheability bits such as `UNCACHEABLE`, `WRITE_COMBINE`,
/// `WRITE_THROUGH`, `WRITE_BACK`, and `UNCACHEABLE_EXPORTED`.
///
/// See Section 2.3 "Calling Conventions" in the UEFI Specification
/// for further information on each ISA that takes advantage of this.
const ISA_MASK = 0x0FFF_F000_0000_0000;
}
}

/// A unique identifier of a memory map.
///
/// If the memory map changes, this value is no longer valid.
Expand Down