Skip to content

Commit

Permalink
Merge pull request #127 from rust-osdev/iterator-fix
Browse files Browse the repository at this point in the history
multiboot2: convenience and safety fixes (0.15.1)
  • Loading branch information
phip1611 authored Mar 18, 2023
2 parents 2e72979 + d45a558 commit 678bcc1
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 32 deletions.
5 changes: 3 additions & 2 deletions multiboot2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Multiboot2-compliant bootloaders, like GRUB. It supports all tags from the speci
including full support for the sections of ELF-64. This library is `no_std` and can be
used in a Multiboot2-kernel.
"""
version = "0.15.0"
version = "0.15.1"
authors = [
"Philipp Oppermann <[email protected]>",
"Calvin Lee <[email protected]>",
Expand Down Expand Up @@ -38,4 +38,5 @@ unstable = []

[dependencies]
bitflags = "1"
derive_more = { version = "0.99.17", default-features = false, features = ["display"] }
derive_more = { version = "0.99", default-features = false, features = ["display"] }
log = { version = "0.4", default-features = false }
14 changes: 14 additions & 0 deletions multiboot2/Changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# CHANGELOG for crate `multiboot2`

## 0.15.1 (2023-03-18)
- **BREAKING** `MemoryMapTag::all_memory_areas()` was renamed to `memory_areas`
and now returns `MemoryAreaIter` instead of
`impl Iterator<Item = &MemoryArea>`. Experience showed that its better to
return the specific iterator whenever possible.
- **BREAKING** `MemoryMapTag::memory_areas()` was renamed to
`available_memory_areas`
(_Sorry for the breaking changes in a minor release, but I just stumbled upon
this und since the last breaking release was just yesterday, users have to
deal with changes anyway._)
- **BREAKING** `ElfSection::name()` now returns a Result instead of just the
value. This prevents possible panics.
- fix: prevent a possible panic in `ElfSection::section_type()`

## 0.15.0 (2023-03-17)
- **BREAKING** MSRV is 1.56.1
- **BREAKING** fixed lifetime issues: `VBEInfoTag` is no longer `&static`
Expand Down
17 changes: 12 additions & 5 deletions multiboot2/src/elf_sections.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::tag_type::Tag;
use crate::TagType;
use core::fmt::{Debug, Formatter};
use core::str::Utf8Error;

/// This tag contains section header table from an ELF kernel.
///
Expand Down Expand Up @@ -178,7 +179,13 @@ impl ElfSection {
11 => ElfSectionType::DynamicLoaderSymbolTable,
0x6000_0000..=0x6FFF_FFFF => ElfSectionType::EnvironmentSpecific,
0x7000_0000..=0x7FFF_FFFF => ElfSectionType::ProcessorSpecific,
_ => panic!(),
e => {
log::warn!(
"Unknown section type {:x}. Treating as ElfSectionType::Unused",
e
);
ElfSectionType::Unused
}
}
}

Expand All @@ -188,7 +195,7 @@ impl ElfSection {
}

/// Read the name of the section.
pub fn name(&self) -> &str {
pub fn name(&self) -> Result<&str, Utf8Error> {
use core::{slice, str};

let name_ptr = unsafe { self.string_table().offset(self.get().name_index() as isize) };
Expand All @@ -202,7 +209,7 @@ impl ElfSection {
len as usize
};

str::from_utf8(unsafe { slice::from_raw_parts(name_ptr, strlen) }).unwrap()
str::from_utf8(unsafe { slice::from_raw_parts(name_ptr, strlen) })
}

/// Get the physical start address of the section.
Expand Down Expand Up @@ -246,15 +253,15 @@ impl ElfSection {
match self.entry_size {
40 => unsafe { &*(self.inner as *const ElfSectionInner32) },
64 => unsafe { &*(self.inner as *const ElfSectionInner64) },
_ => panic!(),
s => panic!("Unexpected entry size: {}", s),
}
}

unsafe fn string_table(&self) -> *const u8 {
let addr = match self.entry_size {
40 => (*(self.string_section as *const ElfSectionInner32)).addr as usize,
64 => (*(self.string_section as *const ElfSectionInner64)).addr as usize,
_ => panic!(),
s => panic!("Unexpected entry size: {}", s),
};
(addr + self.offset) as *const _
}
Expand Down
2 changes: 1 addition & 1 deletion multiboot2/src/framebuffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub struct FramebufferColor {

/// Error when an unknown [`FramebufferTypeId`] is found.
#[derive(Debug, Copy, Clone, Display, PartialEq, Eq)]
#[display(fmt = "Unknown framebuffer type _0")]
#[display(fmt = "Unknown framebuffer type {}", _0)]
pub struct UnknownFramebufferType(u8);

#[cfg(feature = "unstable")]
Expand Down
38 changes: 19 additions & 19 deletions multiboot2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1188,15 +1188,15 @@ mod tests {
assert_eq!(bytes.len(), bi.total_size());
let es = bi.elf_sections_tag().unwrap();
let mut s = es.sections();
let s1 = s.next().unwrap();
assert_eq!(".rodata", s1.name());
let s1 = s.next().expect("Should have one more section");
assert_eq!(".rodata", s1.name().expect("Should be valid utf-8"));
assert_eq!(0xFFFF_8000_0010_0000, s1.start_address());
assert_eq!(0xFFFF_8000_0010_3000, s1.end_address());
assert_eq!(0x0000_0000_0000_3000, s1.size());
assert_eq!(ElfSectionFlags::ALLOCATED, s1.flags());
assert_eq!(ElfSectionType::ProgramSection, s1.section_type());
let s2 = s.next().unwrap();
assert_eq!(".text", s2.name());
let s2 = s.next().expect("Should have one more section");
assert_eq!(".text", s2.name().expect("Should be valid utf-8"));
assert_eq!(0xFFFF_8000_0010_3000, s2.start_address());
assert_eq!(0xFFFF_8000_0010_C000, s2.end_address());
assert_eq!(0x0000_0000_0000_9000, s2.size());
Expand All @@ -1205,8 +1205,8 @@ mod tests {
s2.flags()
);
assert_eq!(ElfSectionType::ProgramSection, s2.section_type());
let s3 = s.next().unwrap();
assert_eq!(".data", s3.name());
let s3 = s.next().expect("Should have one more section");
assert_eq!(".data", s3.name().expect("Should be valid utf-8"));
assert_eq!(0xFFFF_8000_0010_C000, s3.start_address());
assert_eq!(0xFFFF_8000_0010_E000, s3.end_address());
assert_eq!(0x0000_0000_0000_2000, s3.size());
Expand All @@ -1215,8 +1215,8 @@ mod tests {
s3.flags()
);
assert_eq!(ElfSectionType::ProgramSection, s3.section_type());
let s4 = s.next().unwrap();
assert_eq!(".bss", s4.name());
let s4 = s.next().expect("Should have one more section");
assert_eq!(".bss", s4.name().expect("Should be valid utf-8"));
assert_eq!(0xFFFF_8000_0010_E000, s4.start_address());
assert_eq!(0xFFFF_8000_0011_3000, s4.end_address());
assert_eq!(0x0000_0000_0000_5000, s4.size());
Expand All @@ -1225,8 +1225,8 @@ mod tests {
s4.flags()
);
assert_eq!(ElfSectionType::Uninitialized, s4.section_type());
let s5 = s.next().unwrap();
assert_eq!(".data.rel.ro", s5.name());
let s5 = s.next().expect("Should have one more section");
assert_eq!(".data.rel.ro", s5.name().expect("Should be valid utf-8"));
assert_eq!(0xFFFF_8000_0011_3000, s5.start_address());
assert_eq!(0xFFFF_8000_0011_3000, s5.end_address());
assert_eq!(0x0000_0000_0000_0000, s5.size());
Expand All @@ -1235,29 +1235,29 @@ mod tests {
s5.flags()
);
assert_eq!(ElfSectionType::ProgramSection, s5.section_type());
let s6 = s.next().unwrap();
assert_eq!(".symtab", s6.name());
let s6 = s.next().expect("Should have one more section");
assert_eq!(".symtab", s6.name().expect("Should be valid utf-8"));
assert_eq!(0x0000_0000_0011_3000, s6.start_address());
assert_eq!(0x0000_0000_0011_5BE0, s6.end_address());
assert_eq!(0x0000_0000_0000_2BE0, s6.size());
assert_eq!(ElfSectionFlags::empty(), s6.flags());
assert_eq!(ElfSectionType::LinkerSymbolTable, s6.section_type());
let s7 = s.next().unwrap();
assert_eq!(".strtab", s7.name());
let s7 = s.next().expect("Should have one more section");
assert_eq!(".strtab", s7.name().expect("Should be valid utf-8"));
assert_eq!(0x0000_0000_0011_5BE0, s7.start_address());
assert_eq!(0x0000_0000_0011_9371, s7.end_address());
assert_eq!(0x0000_0000_0000_3791, s7.size());
assert_eq!(ElfSectionFlags::empty(), s7.flags());
assert_eq!(ElfSectionType::StringTable, s7.section_type());
let s8 = s.next().unwrap();
assert_eq!(".shstrtab", s8.name());
let s8 = s.next().expect("Should have one more section");
assert_eq!(".shstrtab", s8.name().expect("Should be valid utf-8"));
assert_eq!(string_addr, s8.start_address());
assert_eq!(string_addr + string_bytes.len() as u64, s8.end_address());
assert_eq!(string_bytes.len() as u64, s8.size());
assert_eq!(ElfSectionFlags::empty(), s8.flags());
assert_eq!(ElfSectionType::StringTable, s8.section_type());
assert!(s.next().is_none());
let mut mm = bi.memory_map_tag().unwrap().memory_areas();
let mut mm = bi.memory_map_tag().unwrap().available_memory_areas();
let mm1 = mm.next().unwrap();
assert_eq!(0x00000000, mm1.start_address());
assert_eq!(0x009_FC00, mm1.end_address());
Expand Down Expand Up @@ -1373,8 +1373,8 @@ mod tests {
assert_eq!(bytes.0.len(), bi.total_size());
let es = bi.elf_sections_tag().unwrap();
let mut s = es.sections();
let s1 = s.next().unwrap();
assert_eq!(".shstrtab", s1.name());
let s1 = s.next().expect("Should have one more section");
assert_eq!(".shstrtab", s1.name().expect("Should be valid utf-8"));
assert_eq!(string_addr, s1.start_address());
assert_eq!(string_addr + string_bytes.0.len() as u64, s1.end_address());
assert_eq!(string_bytes.0.len() as u64, s1.size());
Expand Down
11 changes: 6 additions & 5 deletions multiboot2/src/memory_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ pub struct MemoryMapTag {
}

impl MemoryMapTag {
/// Return an iterator over all AVAILABLE marked memory areas.
pub fn memory_areas(&self) -> impl Iterator<Item = &MemoryArea> {
self.all_memory_areas()
/// Return an iterator over all memory areas that have the type
/// [`MemoryAreaType::Available`].
pub fn available_memory_areas(&self) -> impl Iterator<Item = &MemoryArea> {
self.memory_areas()
.filter(|entry| matches!(entry.typ, MemoryAreaType::Available))
}

/// Return an iterator over all marked memory areas.
pub fn all_memory_areas(&self) -> impl Iterator<Item = &MemoryArea> {
/// Return an iterator over all memory areas.
pub fn memory_areas(&self) -> MemoryAreaIter {
let self_ptr = self as *const MemoryMapTag;
let start_area = self.first_area.as_ptr();

Expand Down

0 comments on commit 678bcc1

Please sign in to comment.