Skip to content

Commit 678bcc1

Browse files
authored
Merge pull request #127 from rust-osdev/iterator-fix
multiboot2: convenience and safety fixes (0.15.1)
2 parents 2e72979 + d45a558 commit 678bcc1

File tree

6 files changed

+55
-32
lines changed

6 files changed

+55
-32
lines changed

multiboot2/Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Multiboot2-compliant bootloaders, like GRUB. It supports all tags from the speci
66
including full support for the sections of ELF-64. This library is `no_std` and can be
77
used in a Multiboot2-kernel.
88
"""
9-
version = "0.15.0"
9+
version = "0.15.1"
1010
authors = [
1111
"Philipp Oppermann <[email protected]>",
1212
"Calvin Lee <[email protected]>",
@@ -38,4 +38,5 @@ unstable = []
3838

3939
[dependencies]
4040
bitflags = "1"
41-
derive_more = { version = "0.99.17", default-features = false, features = ["display"] }
41+
derive_more = { version = "0.99", default-features = false, features = ["display"] }
42+
log = { version = "0.4", default-features = false }

multiboot2/Changelog.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# CHANGELOG for crate `multiboot2`
22

3+
## 0.15.1 (2023-03-18)
4+
- **BREAKING** `MemoryMapTag::all_memory_areas()` was renamed to `memory_areas`
5+
and now returns `MemoryAreaIter` instead of
6+
`impl Iterator<Item = &MemoryArea>`. Experience showed that its better to
7+
return the specific iterator whenever possible.
8+
- **BREAKING** `MemoryMapTag::memory_areas()` was renamed to
9+
`available_memory_areas`
10+
(_Sorry for the breaking changes in a minor release, but I just stumbled upon
11+
this und since the last breaking release was just yesterday, users have to
12+
deal with changes anyway._)
13+
- **BREAKING** `ElfSection::name()` now returns a Result instead of just the
14+
value. This prevents possible panics.
15+
- fix: prevent a possible panic in `ElfSection::section_type()`
16+
317
## 0.15.0 (2023-03-17)
418
- **BREAKING** MSRV is 1.56.1
519
- **BREAKING** fixed lifetime issues: `VBEInfoTag` is no longer `&static`

multiboot2/src/elf_sections.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::tag_type::Tag;
22
use crate::TagType;
33
use core::fmt::{Debug, Formatter};
4+
use core::str::Utf8Error;
45

56
/// This tag contains section header table from an ELF kernel.
67
///
@@ -178,7 +179,13 @@ impl ElfSection {
178179
11 => ElfSectionType::DynamicLoaderSymbolTable,
179180
0x6000_0000..=0x6FFF_FFFF => ElfSectionType::EnvironmentSpecific,
180181
0x7000_0000..=0x7FFF_FFFF => ElfSectionType::ProcessorSpecific,
181-
_ => panic!(),
182+
e => {
183+
log::warn!(
184+
"Unknown section type {:x}. Treating as ElfSectionType::Unused",
185+
e
186+
);
187+
ElfSectionType::Unused
188+
}
182189
}
183190
}
184191

@@ -188,7 +195,7 @@ impl ElfSection {
188195
}
189196

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

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

205-
str::from_utf8(unsafe { slice::from_raw_parts(name_ptr, strlen) }).unwrap()
212+
str::from_utf8(unsafe { slice::from_raw_parts(name_ptr, strlen) })
206213
}
207214

208215
/// Get the physical start address of the section.
@@ -246,15 +253,15 @@ impl ElfSection {
246253
match self.entry_size {
247254
40 => unsafe { &*(self.inner as *const ElfSectionInner32) },
248255
64 => unsafe { &*(self.inner as *const ElfSectionInner64) },
249-
_ => panic!(),
256+
s => panic!("Unexpected entry size: {}", s),
250257
}
251258
}
252259

253260
unsafe fn string_table(&self) -> *const u8 {
254261
let addr = match self.entry_size {
255262
40 => (*(self.string_section as *const ElfSectionInner32)).addr as usize,
256263
64 => (*(self.string_section as *const ElfSectionInner64)).addr as usize,
257-
_ => panic!(),
264+
s => panic!("Unexpected entry size: {}", s),
258265
};
259266
(addr + self.offset) as *const _
260267
}

multiboot2/src/framebuffer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ pub struct FramebufferColor {
9393

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

9999
#[cfg(feature = "unstable")]

multiboot2/src/lib.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -1188,15 +1188,15 @@ mod tests {
11881188
assert_eq!(bytes.len(), bi.total_size());
11891189
let es = bi.elf_sections_tag().unwrap();
11901190
let mut s = es.sections();
1191-
let s1 = s.next().unwrap();
1192-
assert_eq!(".rodata", s1.name());
1191+
let s1 = s.next().expect("Should have one more section");
1192+
assert_eq!(".rodata", s1.name().expect("Should be valid utf-8"));
11931193
assert_eq!(0xFFFF_8000_0010_0000, s1.start_address());
11941194
assert_eq!(0xFFFF_8000_0010_3000, s1.end_address());
11951195
assert_eq!(0x0000_0000_0000_3000, s1.size());
11961196
assert_eq!(ElfSectionFlags::ALLOCATED, s1.flags());
11971197
assert_eq!(ElfSectionType::ProgramSection, s1.section_type());
1198-
let s2 = s.next().unwrap();
1199-
assert_eq!(".text", s2.name());
1198+
let s2 = s.next().expect("Should have one more section");
1199+
assert_eq!(".text", s2.name().expect("Should be valid utf-8"));
12001200
assert_eq!(0xFFFF_8000_0010_3000, s2.start_address());
12011201
assert_eq!(0xFFFF_8000_0010_C000, s2.end_address());
12021202
assert_eq!(0x0000_0000_0000_9000, s2.size());
@@ -1205,8 +1205,8 @@ mod tests {
12051205
s2.flags()
12061206
);
12071207
assert_eq!(ElfSectionType::ProgramSection, s2.section_type());
1208-
let s3 = s.next().unwrap();
1209-
assert_eq!(".data", s3.name());
1208+
let s3 = s.next().expect("Should have one more section");
1209+
assert_eq!(".data", s3.name().expect("Should be valid utf-8"));
12101210
assert_eq!(0xFFFF_8000_0010_C000, s3.start_address());
12111211
assert_eq!(0xFFFF_8000_0010_E000, s3.end_address());
12121212
assert_eq!(0x0000_0000_0000_2000, s3.size());
@@ -1215,8 +1215,8 @@ mod tests {
12151215
s3.flags()
12161216
);
12171217
assert_eq!(ElfSectionType::ProgramSection, s3.section_type());
1218-
let s4 = s.next().unwrap();
1219-
assert_eq!(".bss", s4.name());
1218+
let s4 = s.next().expect("Should have one more section");
1219+
assert_eq!(".bss", s4.name().expect("Should be valid utf-8"));
12201220
assert_eq!(0xFFFF_8000_0010_E000, s4.start_address());
12211221
assert_eq!(0xFFFF_8000_0011_3000, s4.end_address());
12221222
assert_eq!(0x0000_0000_0000_5000, s4.size());
@@ -1225,8 +1225,8 @@ mod tests {
12251225
s4.flags()
12261226
);
12271227
assert_eq!(ElfSectionType::Uninitialized, s4.section_type());
1228-
let s5 = s.next().unwrap();
1229-
assert_eq!(".data.rel.ro", s5.name());
1228+
let s5 = s.next().expect("Should have one more section");
1229+
assert_eq!(".data.rel.ro", s5.name().expect("Should be valid utf-8"));
12301230
assert_eq!(0xFFFF_8000_0011_3000, s5.start_address());
12311231
assert_eq!(0xFFFF_8000_0011_3000, s5.end_address());
12321232
assert_eq!(0x0000_0000_0000_0000, s5.size());
@@ -1235,29 +1235,29 @@ mod tests {
12351235
s5.flags()
12361236
);
12371237
assert_eq!(ElfSectionType::ProgramSection, s5.section_type());
1238-
let s6 = s.next().unwrap();
1239-
assert_eq!(".symtab", s6.name());
1238+
let s6 = s.next().expect("Should have one more section");
1239+
assert_eq!(".symtab", s6.name().expect("Should be valid utf-8"));
12401240
assert_eq!(0x0000_0000_0011_3000, s6.start_address());
12411241
assert_eq!(0x0000_0000_0011_5BE0, s6.end_address());
12421242
assert_eq!(0x0000_0000_0000_2BE0, s6.size());
12431243
assert_eq!(ElfSectionFlags::empty(), s6.flags());
12441244
assert_eq!(ElfSectionType::LinkerSymbolTable, s6.section_type());
1245-
let s7 = s.next().unwrap();
1246-
assert_eq!(".strtab", s7.name());
1245+
let s7 = s.next().expect("Should have one more section");
1246+
assert_eq!(".strtab", s7.name().expect("Should be valid utf-8"));
12471247
assert_eq!(0x0000_0000_0011_5BE0, s7.start_address());
12481248
assert_eq!(0x0000_0000_0011_9371, s7.end_address());
12491249
assert_eq!(0x0000_0000_0000_3791, s7.size());
12501250
assert_eq!(ElfSectionFlags::empty(), s7.flags());
12511251
assert_eq!(ElfSectionType::StringTable, s7.section_type());
1252-
let s8 = s.next().unwrap();
1253-
assert_eq!(".shstrtab", s8.name());
1252+
let s8 = s.next().expect("Should have one more section");
1253+
assert_eq!(".shstrtab", s8.name().expect("Should be valid utf-8"));
12541254
assert_eq!(string_addr, s8.start_address());
12551255
assert_eq!(string_addr + string_bytes.len() as u64, s8.end_address());
12561256
assert_eq!(string_bytes.len() as u64, s8.size());
12571257
assert_eq!(ElfSectionFlags::empty(), s8.flags());
12581258
assert_eq!(ElfSectionType::StringTable, s8.section_type());
12591259
assert!(s.next().is_none());
1260-
let mut mm = bi.memory_map_tag().unwrap().memory_areas();
1260+
let mut mm = bi.memory_map_tag().unwrap().available_memory_areas();
12611261
let mm1 = mm.next().unwrap();
12621262
assert_eq!(0x00000000, mm1.start_address());
12631263
assert_eq!(0x009_FC00, mm1.end_address());
@@ -1373,8 +1373,8 @@ mod tests {
13731373
assert_eq!(bytes.0.len(), bi.total_size());
13741374
let es = bi.elf_sections_tag().unwrap();
13751375
let mut s = es.sections();
1376-
let s1 = s.next().unwrap();
1377-
assert_eq!(".shstrtab", s1.name());
1376+
let s1 = s.next().expect("Should have one more section");
1377+
assert_eq!(".shstrtab", s1.name().expect("Should be valid utf-8"));
13781378
assert_eq!(string_addr, s1.start_address());
13791379
assert_eq!(string_addr + string_bytes.0.len() as u64, s1.end_address());
13801380
assert_eq!(string_bytes.0.len() as u64, s1.size());

multiboot2/src/memory_map.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ pub struct MemoryMapTag {
2222
}
2323

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

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

0 commit comments

Comments
 (0)