Skip to content

memory_map: support non-standard types #163

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 3 commits into from
Jul 12, 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
4 changes: 2 additions & 2 deletions integration-test/bins/multiboot2_chainloader/src/loader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use elf_rs::{ElfFile, ProgramHeaderEntry, ProgramType};
use multiboot2::{
BootLoaderNameTag, CommandLineTag, MemoryArea, MemoryAreaType, MemoryMapTag, ModuleTag,
BootLoaderNameTag, CommandLineTag, MemoryArea, MemoryAreaType, MemoryMapTag,
ModuleTag,
};

/// Loads the first module into memory. Assumes that the module is a ELF file.
Expand All @@ -26,7 +27,6 @@ pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
log::info!("Multiboot2 header:\n{hdr:#?}");
}


// Map the load segments into memory (at their corresponding link).
{
let elf = elf_rs::Elf32::from_bytes(elf_bytes).expect("Should be valid ELF");
Expand Down
5 changes: 3 additions & 2 deletions integration-test/bins/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[toolchain]
channel = "nightly-2023-06-22"
profile = "minimal"
profile = "default"
components = [
"rust-src"
"rust-src",
"rustfmt",
]
2 changes: 1 addition & 1 deletion multiboot2-header/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

mod header;
mod information_request;
pub(self) mod traits;
pub(crate) mod traits;

pub use header::HeaderBuilder;
pub use information_request::InformationRequestHeaderTagBuilder;
4 changes: 3 additions & 1 deletion multiboot2/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# CHANGELOG for crate `multiboot2`
## Unreleased
- **Breaking** Make functions of `InformationBuilder` chainable. They now consume the builder.
- **BREAKING** Make functions of `InformationBuilder` chainable. They now consume the builder.
- **BREAKING** Allow non-standard memory area types by using new pair of
corresponding types: `MemoryAreaTypeId` and `MemoryAreaType`.

## 0.16.0 (2023-06-23)
- **BREAKING** renamed `MULTIBOOT2_BOOTLOADER_MAGIC` to `MAGIC`
Expand Down
3 changes: 2 additions & 1 deletion multiboot2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub use framebuffer::{FramebufferColor, FramebufferField, FramebufferTag, Frameb
pub use image_load_addr::ImageLoadPhysAddrTag;
pub use memory_map::{
BasicMemoryInfoTag, EFIBootServicesNotExitedTag, EFIMemoryAreaType, EFIMemoryDesc,
EFIMemoryMapTag, MemoryArea, MemoryAreaType, MemoryMapTag,
EFIMemoryMapTag, MemoryArea, MemoryAreaType, MemoryAreaTypeId, MemoryMapTag,
};
pub use module::{ModuleIter, ModuleTag};
pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
Expand Down Expand Up @@ -583,6 +583,7 @@ impl<T: Pointee<Metadata = ()>> TagTrait for T {
#[cfg(test)]
mod tests {
use super::*;
use crate::memory_map::MemoryAreaType;
use core::str::Utf8Error;

#[test]
Expand Down
100 changes: 86 additions & 14 deletions multiboot2/src/memory_map.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{Tag, TagTrait, TagType, TagTypeId};
use core::convert::TryInto;
use core::fmt::Debug;
use core::fmt::{Debug, Formatter};
use core::marker::PhantomData;
use core::mem;

Expand Down Expand Up @@ -84,17 +84,17 @@ impl StructAsBytes for MemoryMapTag {
pub struct MemoryArea {
base_addr: u64,
length: u64,
typ: MemoryAreaType,
typ: MemoryAreaTypeId,
_reserved: u32,
}

impl MemoryArea {
/// Create a new MemoryArea.
pub fn new(base_addr: u64, length: u64, typ: MemoryAreaType) -> Self {
pub fn new(base_addr: u64, length: u64, typ: impl Into<MemoryAreaTypeId>) -> Self {
Self {
base_addr,
length,
typ,
typ: typ.into(),
_reserved: 0,
}
}
Expand All @@ -115,7 +115,7 @@ impl MemoryArea {
}

/// The type of the memory region.
pub fn typ(&self) -> MemoryAreaType {
pub fn typ(&self) -> MemoryAreaTypeId {
self.typ
}
}
Expand All @@ -127,28 +127,100 @@ impl StructAsBytes for MemoryArea {
}
}

/// An enum of possible reported region types.
/// Inside the Multiboot2 spec this is kind of hidden
/// inside the implementation of `struct multiboot_mmap_entry`.
/// ABI-friendly version of [`MemoryAreaType`].
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]
pub struct MemoryAreaTypeId(u32);

impl From<u32> for MemoryAreaTypeId {
fn from(value: u32) -> Self {
Self(value)
}
}

impl From<MemoryAreaTypeId> for u32 {
fn from(value: MemoryAreaTypeId) -> Self {
value.0
}
}

impl Debug for MemoryAreaTypeId {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let mt = MemoryAreaType::from(*self);
Debug::fmt(&mt, f)
}
}

/// Abstraction over defined memory types for the memory map as well as custom
/// ones. Types 1 to 5 are defined in the Multiboot2 spec and correspond to the
/// entry types of e820 memory maps.
///
/// This is not binary compatible with the Multiboot2 spec. Please use
/// [`MemoryAreaTypeId`] instead.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u32)]
pub enum MemoryAreaType {
/// Available memory free to be used by the OS.
Available = 1,
Available, /* 1 */

/// A reserved area that must not be used.
Reserved = 2,
Reserved, /* 2, */

/// Usable memory holding ACPI information.
AcpiAvailable = 3,
AcpiAvailable, /* 3, */

/// Reserved memory which needs to be preserved on hibernation.
/// Also called NVS in spec, which stands for "Non-Volatile Sleep/Storage",
/// which is part of ACPI specification.
ReservedHibernate = 4,
ReservedHibernate, /* 4, */

/// Memory which is occupied by defective RAM modules.
Defective = 5,
Defective, /* = 5, */

/// Custom memory map type.
Custom(u32),
}

impl From<MemoryAreaTypeId> for MemoryAreaType {
fn from(value: MemoryAreaTypeId) -> Self {
match value.0 {
1 => Self::Available,
2 => Self::Reserved,
3 => Self::AcpiAvailable,
4 => Self::ReservedHibernate,
5 => Self::Defective,
val => Self::Custom(val),
}
}
}

impl From<MemoryAreaType> for MemoryAreaTypeId {
fn from(value: MemoryAreaType) -> Self {
let integer = match value {
MemoryAreaType::Available => 1,
MemoryAreaType::Reserved => 2,
MemoryAreaType::AcpiAvailable => 3,
MemoryAreaType::ReservedHibernate => 4,
MemoryAreaType::Defective => 5,
MemoryAreaType::Custom(val) => val,
};
integer.into()
}
}

impl PartialEq<MemoryAreaType> for MemoryAreaTypeId {
fn eq(&self, other: &MemoryAreaType) -> bool {
let val: MemoryAreaTypeId = (*other).into();
let val: u32 = val.0;
self.0.eq(&val)
}
}

impl PartialEq<MemoryAreaTypeId> for MemoryAreaType {
fn eq(&self, other: &MemoryAreaTypeId) -> bool {
let val: MemoryAreaTypeId = (*self).into();
let val: u32 = val.0;
other.0.eq(&val)
}
}

/// Basic memory info tag.
Expand Down
9 changes: 8 additions & 1 deletion multiboot2/src/tag_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use core::str::Utf8Error;
/// Multiboot2 [`Tag`]. This type can easily be created from or converted to
/// [`TagType`].
#[repr(transparent)]
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Hash)]
#[derive(Copy, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
pub struct TagTypeId(u32);

impl TagTypeId {
Expand All @@ -29,6 +29,13 @@ impl TagTypeId {
}
}

impl Debug for TagTypeId {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
let tag_type = TagType::from(*self);
Debug::fmt(&tag_type, f)
}
}

/// Higher level abstraction for [`TagTypeId`] that assigns each possible value
/// to a specific semantic according to the specification. Additionally, it
/// allows to use the [`TagType::Custom`] variant. It is **not binary compatible**
Expand Down