Skip to content

Commit 5c33ca8

Browse files
committed
memory_map: support non-standard types
1 parent ed11590 commit 5c33ca8

File tree

5 files changed

+88
-19
lines changed

5 files changed

+88
-19
lines changed

integration-test/bins/multiboot2_chainloader/src/loader.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use elf_rs::{ElfFile, ProgramHeaderEntry, ProgramType};
22
use multiboot2::{
3-
BootLoaderNameTag, CommandLineTag, MemoryArea, MemoryAreaType, MemoryMapTag, ModuleTag,
3+
BootLoaderNameTag, CommandLineTag, MemoryArea, MemoryAreaType, MemoryAreaTypeId, MemoryMapTag,
4+
ModuleTag,
45
};
56

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

29-
3030
// Map the load segments into memory (at their corresponding link).
3131
{
3232
let elf = elf_rs::Elf32::from_bytes(elf_bytes).expect("Should be valid ELF");
+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
[toolchain]
22
channel = "nightly-2023-06-22"
3-
profile = "minimal"
3+
profile = "default"
44
components = [
5-
"rust-src"
5+
"rust-src",
6+
"rustfmt",
67
]

multiboot2/Changelog.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# CHANGELOG for crate `multiboot2`
22
## Unreleased
3-
- **Breaking** Make functions of `InformationBuilder` chainable. They now consume the builder.
3+
- **BREAKING** Make functions of `InformationBuilder` chainable. They now consume the builder.
4+
- **BREAKING** Allow non-standard memory area types by using new pair of
5+
corresponding types: `MemoryAreaTypeId` and `MemoryAreaType`.
46

57
## 0.16.0 (2023-06-23)
68
- **BREAKING** renamed `MULTIBOOT2_BOOTLOADER_MAGIC` to `MAGIC`

multiboot2/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub use framebuffer::{FramebufferColor, FramebufferField, FramebufferTag, Frameb
6262
pub use image_load_addr::ImageLoadPhysAddrTag;
6363
pub use memory_map::{
6464
BasicMemoryInfoTag, EFIBootServicesNotExitedTag, EFIMemoryAreaType, EFIMemoryDesc,
65-
EFIMemoryMapTag, MemoryArea, MemoryAreaType, MemoryMapTag,
65+
EFIMemoryMapTag, MemoryArea, MemoryAreaType, MemoryAreaTypeId, MemoryMapTag,
6666
};
6767
pub use module::{ModuleIter, ModuleTag};
6868
pub use rsdp::{RsdpV1Tag, RsdpV2Tag};
@@ -584,6 +584,7 @@ impl<T: Pointee<Metadata = ()>> TagTrait for T {
584584
#[cfg(test)]
585585
mod tests {
586586
use super::*;
587+
use crate::memory_map::MemoryAreaType;
587588
use core::str::Utf8Error;
588589

589590
#[test]

multiboot2/src/memory_map.rs

+78-13
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,17 @@ impl StructAsBytes for MemoryMapTag {
8484
pub struct MemoryArea {
8585
base_addr: u64,
8686
length: u64,
87-
typ: MemoryAreaType,
87+
typ: MemoryAreaTypeId,
8888
_reserved: u32,
8989
}
9090

9191
impl MemoryArea {
9292
/// Create a new MemoryArea.
93-
pub fn new(base_addr: u64, length: u64, typ: MemoryAreaType) -> Self {
93+
pub fn new(base_addr: u64, length: u64, typ: impl Into<MemoryAreaTypeId>) -> Self {
9494
Self {
9595
base_addr,
9696
length,
97-
typ,
97+
typ: typ.into(),
9898
_reserved: 0,
9999
}
100100
}
@@ -115,7 +115,7 @@ impl MemoryArea {
115115
}
116116

117117
/// The type of the memory region.
118-
pub fn typ(&self) -> MemoryAreaType {
118+
pub fn typ(&self) -> MemoryAreaTypeId {
119119
self.typ
120120
}
121121
}
@@ -127,28 +127,93 @@ impl StructAsBytes for MemoryArea {
127127
}
128128
}
129129

130-
/// An enum of possible reported region types.
131-
/// Inside the Multiboot2 spec this is kind of hidden
132-
/// inside the implementation of `struct multiboot_mmap_entry`.
130+
/// ABI-friendly version of [`MemoryAreaType`].
131+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
132+
#[repr(C)]
133+
pub struct MemoryAreaTypeId(u32);
134+
135+
impl From<u32> for MemoryAreaTypeId {
136+
fn from(value: u32) -> Self {
137+
Self(value)
138+
}
139+
}
140+
141+
impl From<MemoryAreaTypeId> for u32 {
142+
fn from(value: MemoryAreaTypeId) -> Self {
143+
value.0
144+
}
145+
}
146+
147+
/// Abstraction over defined memory types for the memory map as well as custom
148+
/// ones. Types 1 to 5 are defined in the Multiboot2 spec and correspond to the
149+
/// entry types of e820 memory maps.
150+
///
151+
/// This is not binary compatible with the Multiboot2 spec. Please use
152+
/// [`MemoryAreaTypeId`] instead.
133153
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
134-
#[repr(u32)]
135154
pub enum MemoryAreaType {
136155
/// Available memory free to be used by the OS.
137-
Available = 1,
156+
Available, /* 1 */
138157

139158
/// A reserved area that must not be used.
140-
Reserved = 2,
159+
Reserved, /* 2, */
141160

142161
/// Usable memory holding ACPI information.
143-
AcpiAvailable = 3,
162+
AcpiAvailable, /* 3, */
144163

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

150169
/// Memory which is occupied by defective RAM modules.
151-
Defective = 5,
170+
Defective, /* = 5, */
171+
172+
/// Custom memory map type.
173+
Custom(u32),
174+
}
175+
176+
impl From<MemoryAreaTypeId> for MemoryAreaType {
177+
fn from(value: MemoryAreaTypeId) -> Self {
178+
match value.0 {
179+
1 => Self::Available,
180+
2 => Self::Reserved,
181+
3 => Self::AcpiAvailable,
182+
4 => Self::ReservedHibernate,
183+
5 => Self::Defective,
184+
val => Self::Custom(val),
185+
}
186+
}
187+
}
188+
189+
impl From<MemoryAreaType> for MemoryAreaTypeId {
190+
fn from(value: MemoryAreaType) -> Self {
191+
let integer = match value {
192+
MemoryAreaType::Available => 1,
193+
MemoryAreaType::Reserved => 2,
194+
MemoryAreaType::AcpiAvailable => 3,
195+
MemoryAreaType::ReservedHibernate => 4,
196+
MemoryAreaType::Defective => 5,
197+
MemoryAreaType::Custom(val) => val,
198+
};
199+
integer.into()
200+
}
201+
}
202+
203+
impl PartialEq<MemoryAreaType> for MemoryAreaTypeId {
204+
fn eq(&self, other: &MemoryAreaType) -> bool {
205+
let val: MemoryAreaTypeId = (*other).into();
206+
let val: u32 = val.0;
207+
self.0.eq(&val)
208+
}
209+
}
210+
211+
impl PartialEq<MemoryAreaTypeId> for MemoryAreaType {
212+
fn eq(&self, other: &MemoryAreaTypeId) -> bool {
213+
let val: MemoryAreaTypeId = (*self).into();
214+
let val: u32 = val.0;
215+
other.0.eq(&val)
216+
}
152217
}
153218

154219
/// Basic memory info tag.

0 commit comments

Comments
 (0)