Verified Commit 5a9374fb authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Pass memory areas as argument instead of writing to physical memory

parent 1dfe98ef
......@@ -22,13 +22,14 @@ use alloc::{
use core::{
cmp,
fmt::{self, Write},
mem,
slice,
str,
};
use redoxfs::Disk;
use self::arch::paging_create;
use self::os::{Os, OsKey, OsMemoryEntry, OsVideoMode};
use self::os::{Os, OsKey, OsMemoryEntry, OsMemoryKind, OsVideoMode};
#[macro_use]
mod os;
......@@ -39,6 +40,13 @@ mod logger;
const KIBI: usize = 1024;
const MIBI: usize = KIBI * KIBI;
//TODO: allocate this in a more reasonable manner
pub static mut AREAS: [OsMemoryEntry; 512] = [OsMemoryEntry {
base: 0,
size: 0,
kind: OsMemoryKind::Null,
}; 512];
struct SliceWriter<'a> {
slice: &'a mut [u8],
i: usize,
......@@ -78,6 +86,9 @@ pub struct KernelArgs {
acpi_rsdps_base: u64,
/// The size of the RSDPs region.
acpi_rsdps_size: u64,
areas_base: u64,
areas_size: u64,
}
fn select_mode<
......@@ -366,6 +377,12 @@ fn main<
env_size: env_size as u64,
acpi_rsdps_base: 0,
acpi_rsdps_size: 0,
areas_base: unsafe {
AREAS.as_ptr() as u64
},
areas_size: unsafe {
(AREAS.len() * mem::size_of::<OsMemoryEntry>()) as u64
},
}
)
}
......@@ -52,6 +52,7 @@ impl Iterator for MemoryMapIter {
base: entry.base,
size: entry.size,
kind: match entry.kind {
0 => OsMemoryKind::Null,
1 => OsMemoryKind::Free,
3 => OsMemoryKind::Reclaim,
_ => OsMemoryKind::Reserved,
......@@ -62,23 +63,11 @@ impl Iterator for MemoryMapIter {
pub unsafe fn memory_map(thunk15: extern "C" fn()) -> Option<(usize, usize)> {
let mut heap_limits = None;
let mut data = ThunkData::new();
loop {
data.eax = 0xE820;
data.ecx = mem::size_of::<MemoryMapEntry>() as u32;
data.edx = 0x534D4150;
data.edi = MEMORY_MAP_ADDR as u32;
data.with(thunk15);
assert_eq!({ data.eax }, 0x534D4150);
assert_eq!({ data.ecx }, mem::size_of::<MemoryMapEntry>() as u32);
let entry = ptr::read(MEMORY_MAP_ADDR as *const MemoryMapEntry);
for (i, entry) in MemoryMapIter::new(thunk15).enumerate() {
//TODO: There is a problem with QEMU crashing if we write at about 8 MiB, so skip to 16
let heap_start = 16 * 1024 * 1024;
if
entry.kind == 1 &&
{ entry.kind } == OsMemoryKind::Free &&
entry.base <= heap_start as u64 &&
(entry.base + entry.size) >= heap_start as u64
{
......@@ -94,8 +83,7 @@ pub unsafe fn memory_map(thunk15: extern "C" fn()) -> Option<(usize, usize)> {
}
}
if data.ebx == 0 {
return heap_limits;
}
crate::AREAS[i] = entry;
}
heap_limits
}
......@@ -130,7 +130,7 @@ impl Os<
(edid[0x3B] as u32) | (((edid[0x3D] as u32) & 0xF0) << 4),
))
} else {
log::warn!("Failed to get VBE EDID: 0x{:X}", data.eax);
log::warn!("Failed to get VBE EDID: 0x{:X}", { data.eax });
None
}
}
......
......@@ -24,14 +24,17 @@ pub enum OsKey {
Other,
}
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u64)]
pub enum OsMemoryKind {
Free,
Reclaim,
Reserved,
Null = 0,
Free = 1,
Reclaim = 2,
Reserved = 3,
}
#[derive(Clone, Copy, Debug)]
#[repr(packed)]
pub struct OsMemoryEntry {
pub base: u64,
pub size: u64,
......@@ -52,7 +55,7 @@ pub trait Os<
V: Iterator<Item=OsVideoMode>
> {
fn name(&self) -> &str;
fn alloc_zeroed_page_aligned(&self, size: usize) -> *mut u8;
fn page_size(&self) -> usize;
......
use uefi::memory::MemoryDescriptor;
pub unsafe fn memory_map() -> usize {
let uefi = std::system_table();
let mut map: [u8; 65536] = [0; 65536];
let mut map_size = map.len();
let mut map_key = 0;
let mut descriptor_size = 0;
let mut descriptor_version = 0;
let _ = (uefi.BootServices.GetMemoryMap)(
&mut map_size,
map.as_mut_ptr() as *mut MemoryDescriptor,
&mut map_key,
&mut descriptor_size,
&mut descriptor_version
);
map_key
}
......@@ -14,12 +14,11 @@ use super::super::{
RSDPS_AREA,
find_acpi_table_pointers,
},
memory_map::memory_map,
};
use self::memory_map::memory_map;
use self::paging::paging;
mod memory_map;
mod paging;
static PHYS_OFFSET: u64 = 0xFFFF800000000000;
......
use core::{mem, ptr};
use uefi::memory::{MemoryDescriptor, MemoryType};
static MM_BASE: u64 = 0x500;
static MM_SIZE: u64 = 0x4B00;
/// Memory does not exist
pub const MEMORY_AREA_NULL: u32 = 0;
/// Memory is free to use
pub const MEMORY_AREA_FREE: u32 = 1;
/// Memory is reserved
pub const MEMORY_AREA_RESERVED: u32 = 2;
/// Memory is used by ACPI, and can be reclaimed
pub const MEMORY_AREA_ACPI: u32 = 3;
/// A memory map area
#[derive(Copy, Clone, Debug, Default)]
#[repr(packed)]
pub struct MemoryArea {
pub base_addr: u64,
pub length: u64,
pub _type: u32,
pub acpi: u32
}
pub unsafe fn memory_map() -> usize {
let uefi = std::system_table();
ptr::write_bytes(MM_BASE as *mut u8, 0, MM_SIZE as usize);
let mut map: [u8; 65536] = [0; 65536];
let mut map_size = map.len();
let mut map_key = 0;
let mut descriptor_size = 0;
let mut descriptor_version = 0;
let _ = (uefi.BootServices.GetMemoryMap)(
&mut map_size,
map.as_mut_ptr() as *mut MemoryDescriptor,
&mut map_key,
&mut descriptor_size,
&mut descriptor_version
);
if descriptor_size >= mem::size_of::<MemoryDescriptor>() {
for i in 0..map_size/descriptor_size {
let descriptor_ptr = map.as_ptr().offset((i * descriptor_size) as isize);
let descriptor = & *(descriptor_ptr as *const MemoryDescriptor);
let descriptor_type: MemoryType = mem::transmute(descriptor.Type);
let bios_type = match descriptor_type {
MemoryType::EfiLoaderCode |
MemoryType::EfiLoaderData |
MemoryType::EfiBootServicesCode |
MemoryType::EfiBootServicesData |
MemoryType::EfiConventionalMemory => {
MEMORY_AREA_FREE
},
_ => {
MEMORY_AREA_RESERVED
}
};
let bios_area = MemoryArea {
base_addr: descriptor.PhysicalStart.0,
length: descriptor.NumberOfPages * 4096,
_type: bios_type,
acpi: 0,
};
ptr::write((MM_BASE as *mut MemoryArea).offset(i as isize), bios_area);
}
} else {
println!("Unknown memory descriptor size: {}", descriptor_size);
}
map_key
}
......@@ -14,12 +14,11 @@ use super::super::{
RSDPS_AREA,
find_acpi_table_pointers,
},
memory_map::memory_map,
};
use self::memory_map::memory_map;
use self::paging::paging_enter;
mod memory_map;
mod paging;
static PHYS_OFFSET: u64 = 0xFFFF800000000000;
......
use alloc::boxed::Box;
use core::{mem, ptr};
use log::error;
use uefi::memory::{MemoryDescriptor, MemoryType};
use crate::os::{OsMemoryEntry, OsMemoryKind};
use super::status_to_result;
pub struct MemoryMapIter {
map: [u8; 4096],
map_size: usize,
map: Box<[u8]>,
map_key: usize,
descriptor_size: usize,
i: usize,
}
......@@ -15,22 +18,23 @@ impl MemoryMapIter {
pub fn new() -> Self {
let uefi = std::system_table();
let mut map: [u8; 4096] = [0; 4096];
let mut map = vec![0; 65536];
let mut map_size = map.len();
let mut map_key = 0;
let mut descriptor_size = 0;
let mut descriptor_version = 0;
let _ = (uefi.BootServices.GetMemoryMap)(
status_to_result((uefi.BootServices.GetMemoryMap)(
&mut map_size,
map.as_mut_ptr() as *mut MemoryDescriptor,
&mut map_key,
&mut descriptor_size,
&mut descriptor_version
);
)).expect("Failed to get UEFI memory map");
map.truncate(map_size);
Self {
map,
map_size,
map: map.into_boxed_slice(),
map_key,
descriptor_size,
i: 0,
}
......@@ -40,39 +44,49 @@ impl MemoryMapIter {
impl Iterator for MemoryMapIter {
type Item=OsMemoryEntry;
fn next(&mut self) -> Option<Self::Item> {
if
self.descriptor_size >= mem::size_of::<MemoryDescriptor>() &&
self.i < self.map_size/self.descriptor_size
{
let descriptor_ptr = unsafe { self.map.as_ptr().add(self.i * self.descriptor_size) };
self.i += 1;
if self.descriptor_size >= mem::size_of::<MemoryDescriptor>() {
if self.i < self.map.len()/self.descriptor_size {
let descriptor_ptr = unsafe { self.map.as_ptr().add(self.i * self.descriptor_size) };
self.i += 1;
let descriptor = unsafe { ptr::read(descriptor_ptr as *const MemoryDescriptor) };
let descriptor_type: MemoryType = unsafe { mem::transmute(descriptor.Type) };
let descriptor = unsafe { ptr::read(descriptor_ptr as *const MemoryDescriptor) };
let descriptor_type: MemoryType = unsafe { mem::transmute(descriptor.Type) };
Some(OsMemoryEntry {
base: descriptor.PhysicalStart.0,
//TODO: do not hard code page size
size: descriptor.NumberOfPages * 4096,
kind: match descriptor_type {
MemoryType::EfiBootServicesCode |
MemoryType::EfiBootServicesData |
MemoryType::EfiConventionalMemory => {
OsMemoryKind::Free
},
MemoryType::EfiLoaderCode |
MemoryType::EfiLoaderData |
MemoryType::EfiACPIReclaimMemory => {
OsMemoryKind::Reclaim
},
_ => {
OsMemoryKind::Reserved
Some(OsMemoryEntry {
base: descriptor.PhysicalStart.0,
//TODO: do not hard code page size
size: descriptor.NumberOfPages * 4096,
kind: match descriptor_type {
MemoryType::EfiLoaderCode |
MemoryType::EfiLoaderData |
MemoryType::EfiBootServicesCode |
MemoryType::EfiBootServicesData |
MemoryType::EfiConventionalMemory => {
OsMemoryKind::Free
},
//TODO: mark ACPI memory as reclaim
_ => {
OsMemoryKind::Reserved
}
}
}
})
})
} else {
None
}
} else {
error!("Unknown memory descriptor size: {}", self.descriptor_size);
None
}
}
}
pub unsafe fn memory_map() -> usize {
let iter = MemoryMapIter::new();
let map_key = iter.map_key;
for (i, entry) in iter.enumerate() {
crate::AREAS[i] = entry;
}
map_key
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment