Skip to content

Commit 4be8221

Browse files
authored
Merge pull request #1980 from rust-osdev/improvements2
uefi: various smaller memory map related fixes and improvements
2 parents 68b5782 + 3b65174 commit 4be8221

2 files changed

Lines changed: 120 additions & 6 deletions

File tree

uefi/src/mem/memory_map/impl_.rs

Lines changed: 119 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@ use core::ptr;
1111
use core::ptr::NonNull;
1212
use uefi_raw::PhysicalAddress;
1313

14+
const fn validate_meta(meta: MemoryMapMeta) -> Result<usize, MemoryMapError> {
15+
if meta.desc_size < size_of::<MemoryDescriptor>()
16+
|| !meta
17+
.desc_size
18+
.is_multiple_of(align_of::<MemoryDescriptor>())
19+
|| !meta.map_size.is_multiple_of(meta.desc_size)
20+
{
21+
Err(MemoryMapError::InvalidSize)
22+
} else {
23+
Ok(meta.map_size / meta.desc_size)
24+
}
25+
}
26+
1427
/// Errors that may happen when constructing a [`MemoryMapRef`] or
1528
/// [`MemoryMapRefMut`].
1629
#[derive(Copy, Clone, Debug)]
@@ -50,10 +63,11 @@ impl<'a> MemoryMapRef<'a> {
5063
if buffer.len() < meta.map_size {
5164
return Err(MemoryMapError::InvalidSize);
5265
}
66+
let len = validate_meta(meta)?;
5367
Ok(Self {
5468
buf: buffer,
5569
meta,
56-
len: meta.entry_count(),
70+
len,
5771
})
5872
}
5973
}
@@ -112,10 +126,11 @@ impl<'a> MemoryMapRefMut<'a> {
112126
if buffer.len() < meta.map_size {
113127
return Err(MemoryMapError::InvalidSize);
114128
}
129+
let len = validate_meta(meta)?;
115130
Ok(Self {
116131
buf: buffer,
117132
meta,
118-
len: meta.entry_count(),
133+
len,
119134
})
120135
}
121136
}
@@ -147,7 +162,9 @@ impl MemoryMap for MemoryMapRefMut<'_> {
147162

148163
impl MemoryMapMut for MemoryMapRefMut<'_> {
149164
fn sort(&mut self) {
150-
self.qsort(0, self.len - 1);
165+
if self.len > 1 {
166+
self.qsort(0, self.len - 1);
167+
}
151168
}
152169

153170
unsafe fn buffer_mut(&mut self) -> &mut [u8] {
@@ -281,6 +298,12 @@ impl MemoryMapBackingMemory {
281298
let memory_map_meta = boot::memory_map_size();
282299
let len = Self::safe_allocation_size_hint(memory_map_meta);
283300
let ptr = boot::allocate_pool(memory_type, len)?.as_ptr();
301+
// Initialize all bytes.
302+
//
303+
// SAFETY: Pointer is valid.
304+
unsafe {
305+
ptr.write_bytes(0, len);
306+
};
284307

285308
// Should be fine as UEFI always has allocations with a guaranteed
286309
// alignment of 8 bytes.
@@ -329,12 +352,14 @@ impl MemoryMapBackingMemory {
329352
/// Returns a slice to the underlying memory.
330353
#[must_use]
331354
pub const fn as_slice(&self) -> &[u8] {
355+
// SAFETY: Memory is valid and initialized.
332356
unsafe { self.0.as_ref() }
333357
}
334358

335359
/// Returns a mutable slice to the underlying memory.
336360
#[must_use]
337361
pub const fn as_mut_slice(&mut self) -> &mut [u8] {
362+
// SAFETY: Memory is valid and initialized.
338363
unsafe { self.0.as_mut() }
339364
}
340365
}
@@ -389,7 +414,7 @@ impl MemoryMap for MemoryMapOwned {
389414
}
390415

391416
fn buffer(&self) -> &[u8] {
392-
self.buf.as_slice()
417+
&self.buf.as_slice()[..self.meta.map_size]
393418
}
394419

395420
fn entries(&self) -> MemoryMapIter<'_> {
@@ -411,7 +436,7 @@ impl MemoryMapMut for MemoryMapOwned {
411436
}
412437

413438
unsafe fn buffer_mut(&mut self) -> &mut [u8] {
414-
self.buf.as_mut_slice()
439+
&mut self.buf.as_mut_slice()[..self.meta.map_size]
415440
}
416441
}
417442

@@ -490,6 +515,10 @@ mod tests {
490515
mmap.entries().copied().collect::<Vec<_>>().as_slice(),
491516
&BASE_MMAP_UNSORTED
492517
);
518+
let mut entries = mmap.entries();
519+
assert_eq!(entries.len(), 3);
520+
assert!(entries.next().is_some());
521+
assert_eq!(entries.len(), 2);
493522
assert!(!mmap.is_sorted());
494523
}
495524

@@ -510,6 +539,68 @@ mod tests {
510539
assert!(mmap.is_sorted());
511540
}
512541

542+
#[test]
543+
fn memory_map_ref_mut_sorts_empty_map() {
544+
let mut memory: [MemoryDescriptor; 0] = [];
545+
let desc_size = size_of::<MemoryDescriptor>();
546+
let raw = unsafe { core::slice::from_raw_parts_mut(memory.as_mut_ptr().cast(), 0) };
547+
let meta = MemoryMapMeta {
548+
map_size: 0,
549+
desc_size,
550+
map_key: Default::default(),
551+
desc_version: MemoryDescriptor::VERSION,
552+
};
553+
554+
let mut mmap = MemoryMapRefMut::new(raw, meta).unwrap();
555+
mmap.sort();
556+
557+
assert!(mmap.is_empty());
558+
assert!(mmap.is_sorted());
559+
}
560+
561+
#[test]
562+
fn memory_map_ref_rejects_invalid_meta() {
563+
let mut memory = [MemoryDescriptor::default(); 2];
564+
let raw_len = size_of_val(&memory);
565+
let raw = unsafe { core::slice::from_raw_parts_mut(memory.as_mut_ptr().cast(), raw_len) };
566+
let desc_size = size_of::<MemoryDescriptor>();
567+
let base_meta = MemoryMapMeta {
568+
map_size: desc_size,
569+
desc_size,
570+
map_key: Default::default(),
571+
desc_version: MemoryDescriptor::VERSION,
572+
};
573+
574+
let mut meta = base_meta;
575+
meta.desc_size = 0;
576+
assert!(matches!(
577+
MemoryMapRef::new(raw, meta),
578+
Err(MemoryMapError::InvalidSize)
579+
));
580+
581+
let mut meta = base_meta;
582+
meta.desc_size = desc_size - 1;
583+
assert!(matches!(
584+
MemoryMapRef::new(raw, meta),
585+
Err(MemoryMapError::InvalidSize)
586+
));
587+
588+
let mut meta = base_meta;
589+
meta.desc_size = desc_size + 1;
590+
meta.map_size = meta.desc_size;
591+
assert!(matches!(
592+
MemoryMapRef::new(raw, meta),
593+
Err(MemoryMapError::InvalidSize)
594+
));
595+
596+
let mut meta = base_meta;
597+
meta.map_size = desc_size + 1;
598+
assert!(matches!(
599+
MemoryMapRef::new(raw, meta),
600+
Err(MemoryMapError::InvalidSize)
601+
));
602+
}
603+
513604
/// Basic sanity checks for the type [`MemoryMapOwned`].
514605
#[test]
515606
fn memory_map_owned() {
@@ -527,4 +618,27 @@ mod tests {
527618
mmap.sort();
528619
assert!(mmap.is_sorted());
529620
}
621+
622+
#[test]
623+
fn memory_map_owned_buffer_uses_map_size() {
624+
let mut memory = [MemoryDescriptor::default(); 4];
625+
memory[..BASE_MMAP_UNSORTED.len()].copy_from_slice(&BASE_MMAP_UNSORTED);
626+
627+
let desc_size = size_of::<MemoryDescriptor>();
628+
let map_size = BASE_MMAP_UNSORTED.len() * desc_size;
629+
let raw_len = size_of_val(&memory);
630+
let raw = unsafe { core::slice::from_raw_parts_mut(memory.as_mut_ptr().cast(), raw_len) };
631+
let meta = MemoryMapMeta {
632+
map_size,
633+
desc_size,
634+
map_key: Default::default(),
635+
desc_version: MemoryDescriptor::VERSION,
636+
};
637+
638+
let mmap = MemoryMapBackingMemory::from_slice(raw);
639+
let mut mmap = MemoryMapOwned::from_initialized_mem(mmap, meta);
640+
641+
assert_eq!(mmap.buffer().len(), map_size);
642+
assert_eq!(unsafe { mmap.buffer_mut() }.len(), map_size);
643+
}
530644
}

uefi/src/mem/memory_map/iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ impl<'a> Iterator for MemoryMapIter<'a> {
3333

3434
impl ExactSizeIterator for MemoryMapIter<'_> {
3535
fn len(&self) -> usize {
36-
self.memory_map.len()
36+
self.memory_map.len() - self.index
3737
}
3838
}

0 commit comments

Comments
 (0)