stage1: return sorted memory map

This commit is contained in:
anna 2023-05-31 20:55:08 +02:00
parent 21d33b6047
commit 326997330b
Signed by: fef
GPG key ID: 2585C2DC6D79B485

View file

@ -1,6 +1,7 @@
use crate::asm::{do_bios_int, BiosIntRegs};
use core::cmp::Ordering;
use core::mem::size_of;
use core::ptr::slice_from_raw_parts_mut;
#[derive(Eq, PartialEq)]
#[repr(C)]
@ -14,26 +15,28 @@ pub struct MemMapEntry {
const SMAP: u32 = 0x534d4150;
/// Use int15/e820 to detect the entire installed system memory.
/// The entries are sorted by ascending start address.
///
/// ## Safety
///
/// `dest` must be aligned to at least 8 bytes, accessible from real mode,
/// and have enough capacity to store the entire memory map. In practice,
/// we use a 64 K segment, which should be way more than sufficient.
pub unsafe fn read_bios_mmap(mut dest: *mut MemMapEntry) -> usize {
pub unsafe fn read_bios_mmap(dest: *mut MemMapEntry) -> usize {
let mut offset: u32 = 0;
let mut count: usize = 0;
debug_assert!((dest as *mut MemMapEntry as usize) < 0x10_0000);
let mut pos = dest;
loop {
dest.as_mut().unwrap_unchecked().acpi30_ext = 1;
pos.as_mut().unwrap_unchecked().acpi30_ext = 1;
let regs = BiosIntRegs {
eax: 0xe820,
ecx: size_of::<MemMapEntry>() as u32,
edx: SMAP,
ebx: offset,
edi: ((dest as usize) % 0x10) as u32,
es: ((dest as usize) / 0x10) as u16,
edi: ((pos as usize) % 0x10) as u32,
es: ((pos as usize) / 0x10) as u16,
..Default::default()
};
let result = match do_bios_int(0x15, regs) {
@ -42,13 +45,13 @@ pub unsafe fn read_bios_mmap(mut dest: *mut MemMapEntry) -> usize {
};
if result.ecx < size_of::<MemMapEntry>() as u32 {
dest.as_mut().unwrap_unchecked().acpi30_ext = 1;
pos.as_mut().unwrap_unchecked().acpi30_ext = 1;
}
if result.eax != SMAP {
break;
}
count += 1;
dest = dest.add(1);
pos = pos.add(1);
if result.ebx == 0 {
break;
} else {
@ -56,6 +59,11 @@ pub unsafe fn read_bios_mmap(mut dest: *mut MemMapEntry) -> usize {
}
}
let mmap_mut = slice_from_raw_parts_mut(dest, count)
.as_mut()
.unwrap_unchecked();
mmap_mut.sort_unstable();
count
}