Skip to content
Snippets Groups Projects
Verified Commit 134a27a5 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Ensure boot services is exited and use SetVirtualAddressMap

parent 7ab8990f
No related branches found
No related tags found
No related merge requests found
...@@ -23,7 +23,7 @@ pub unsafe fn paging_create< ...@@ -23,7 +23,7 @@ pub unsafe fn paging_create<
D: Disk, D: Disk,
M: Iterator<Item=OsMemoryEntry>, M: Iterator<Item=OsMemoryEntry>,
V: Iterator<Item=OsVideoMode> V: Iterator<Item=OsVideoMode>
>(os: &mut dyn Os<D, M, V>, kernel_phys: usize) -> Option<usize> { >(os: &mut dyn Os<D, M, V>, kernel_phys: usize, kernel_base: usize) -> Option<usize> {
log::error!("paging_create not implemented for aarch64"); log::error!("paging_create not implemented for aarch64");
None None
} }
...@@ -9,7 +9,6 @@ use crate::{ ...@@ -9,7 +9,6 @@ use crate::{
use super::super::{ use super::super::{
OsEfi, OsEfi,
exit_boot_services,
acpi::{ acpi::{
RSDPS_AREA, RSDPS_AREA,
find_acpi_table_pointers, find_acpi_table_pointers,
...@@ -35,8 +34,12 @@ unsafe extern "C" fn kernel_entry( ...@@ -35,8 +34,12 @@ unsafe extern "C" fn kernel_entry(
args: *const KernelArgs, args: *const KernelArgs,
) -> ! { ) -> ! {
// Read memory map and exit boot services // Read memory map and exit boot services
let key = memory_map(); {
exit_boot_services(key); let mut memory_iter = memory_map();
memory_iter.exit_boot_services();
memory_iter.set_virtual_address_map(PHYS_OFFSET);
mem::forget(memory_iter);
}
// Disable interrupts // Disable interrupts
asm!("msr daifset, #2"); asm!("msr daifset, #2");
......
...@@ -9,7 +9,6 @@ use crate::{ ...@@ -9,7 +9,6 @@ use crate::{
use super::super::{ use super::super::{
OsEfi, OsEfi,
exit_boot_services,
acpi::{ acpi::{
RSDPS_AREA, RSDPS_AREA,
find_acpi_table_pointers, find_acpi_table_pointers,
...@@ -30,8 +29,12 @@ unsafe extern "C" fn kernel_entry( ...@@ -30,8 +29,12 @@ unsafe extern "C" fn kernel_entry(
args: *const KernelArgs, args: *const KernelArgs,
) -> ! { ) -> ! {
// Read memory map and exit boot services // Read memory map and exit boot services
let key = memory_map(); {
exit_boot_services(key); let mut memory_iter = memory_map();
memory_iter.exit_boot_services();
memory_iter.set_virtual_address_map(PHYS_OFFSET);
mem::forget(memory_iter);
}
// Disable interrupts // Disable interrupts
llvm_asm!("cli" : : : "memory" : "intel", "volatile"); llvm_asm!("cli" : : : "memory" : "intel", "volatile");
......
use alloc::boxed::Box; use alloc::vec::Vec;
use core::{mem, ptr}; use core::{mem, ptr};
use log::error;
use uefi::memory::{MemoryDescriptor, MemoryType}; use uefi::memory::{MemoryDescriptor, MemoryType};
use crate::os::{OsMemoryEntry, OsMemoryKind}; use crate::os::{OsMemoryEntry, OsMemoryKind};
use super::status_to_result; use super::status_to_result;
const EFI_MEMORY_RUNTIME: u64 = 0x8000000000000000;
pub struct MemoryMapIter { pub struct MemoryMapIter {
map: Box<[u8]>, map: Vec<u8>,
map_key: usize, map_key: usize,
descriptor_size: usize, descriptor_size: usize,
descriptor_version: u32,
i: usize, i: usize,
} }
...@@ -30,63 +32,99 @@ impl MemoryMapIter { ...@@ -30,63 +32,99 @@ impl MemoryMapIter {
&mut descriptor_size, &mut descriptor_size,
&mut descriptor_version &mut descriptor_version
)).expect("Failed to get UEFI memory map"); )).expect("Failed to get UEFI memory map");
// Ensure descriptor size is usable
assert!(descriptor_size >= mem::size_of::<MemoryDescriptor>());
// Ensure descriptor version is supported
assert_eq!(descriptor_version, 1);
// Reduce map size to returned value
map.truncate(map_size); map.truncate(map_size);
Self { Self {
map: map.into_boxed_slice(), map,
map_key, map_key,
descriptor_size, descriptor_size,
descriptor_version,
i: 0, i: 0,
} }
} }
pub fn exit_boot_services(&self) {
let handle = std::handle();
let uefi = std::system_table();
status_to_result((uefi.BootServices.ExitBootServices)(
handle,
self.map_key
)).expect("Failed to exit UEFI boot services");
}
pub fn set_virtual_address_map(&mut self, phys_offset: u64) {
let uefi = std::system_table();
for i in 0..self.map.len()/self.descriptor_size {
let descriptor_ptr = unsafe { self.map.as_mut_ptr().add(i * self.descriptor_size) };
let descriptor = unsafe { &mut *(descriptor_ptr as *mut MemoryDescriptor) };
if descriptor.Attribute & EFI_MEMORY_RUNTIME == EFI_MEMORY_RUNTIME {
descriptor.VirtualStart.0 = descriptor.PhysicalStart.0 + phys_offset;
}
}
status_to_result((uefi.RuntimeServices.SetVirtualAddressMap)(
self.map.len(),
self.descriptor_size,
self.descriptor_version,
self.map.as_ptr() as *const MemoryDescriptor
)).expect("Failed to set UEFI runtime services virtual address map");
}
} }
impl Iterator for MemoryMapIter { impl Iterator for MemoryMapIter {
type Item=OsMemoryEntry; type Item=OsMemoryEntry;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.descriptor_size >= mem::size_of::<MemoryDescriptor>() { if self.i < self.map.len()/self.descriptor_size {
if self.i < self.map.len()/self.descriptor_size { let descriptor_ptr = unsafe { self.map.as_ptr().add(self.i * self.descriptor_size) };
let descriptor_ptr = unsafe { self.map.as_ptr().add(self.i * self.descriptor_size) }; self.i += 1;
self.i += 1;
let descriptor = unsafe { ptr::read(descriptor_ptr as *const MemoryDescriptor) };
let descriptor = unsafe { ptr::read(descriptor_ptr as *const MemoryDescriptor) }; let descriptor_type: MemoryType = unsafe { mem::transmute(descriptor.Type) };
let descriptor_type: MemoryType = unsafe { mem::transmute(descriptor.Type) };
Some(OsMemoryEntry {
Some(OsMemoryEntry { base: descriptor.PhysicalStart.0,
base: descriptor.PhysicalStart.0, //TODO: do not hard code page size
//TODO: do not hard code page size size: descriptor.NumberOfPages * 4096,
size: descriptor.NumberOfPages * 4096, kind: match descriptor_type {
kind: match descriptor_type { MemoryType::EfiLoaderCode |
MemoryType::EfiLoaderCode | MemoryType::EfiLoaderData |
MemoryType::EfiLoaderData | MemoryType::EfiBootServicesCode |
MemoryType::EfiBootServicesCode | MemoryType::EfiBootServicesData |
MemoryType::EfiBootServicesData | MemoryType::EfiConventionalMemory => {
MemoryType::EfiConventionalMemory => { OsMemoryKind::Free
OsMemoryKind::Free },
}, //TODO: mark ACPI memory as reclaim
//TODO: mark ACPI memory as reclaim _ => {
_ => { OsMemoryKind::Reserved
OsMemoryKind::Reserved
}
} }
}) }
} else { })
None
}
} else { } else {
error!("Unknown memory descriptor size: {}", self.descriptor_size);
None None
} }
} }
} }
pub unsafe fn memory_map() -> usize { pub unsafe fn memory_map() -> MemoryMapIter {
let iter = MemoryMapIter::new(); let mut iter = MemoryMapIter::new();
let map_key = iter.map_key;
for (i, entry) in iter.enumerate() { // Using next to avoid consuming iterator
crate::AREAS[i] = entry; while let Some(entry) = iter.next() {
crate::AREAS[iter.i] = entry;
} }
map_key // Rewind iterator
iter.i = 0;
iter
} }
...@@ -202,13 +202,6 @@ impl Os< ...@@ -202,13 +202,6 @@ impl Os<
} }
} }
unsafe fn exit_boot_services(key: usize) {
let handle = std::handle();
let uefi = std::system_table();
let _ = (uefi.BootServices.ExitBootServices)(handle, key);
}
fn status_to_result(status: Status) -> Result<usize> { fn status_to_result(status: Status) -> Result<usize> {
match status.branch() { match status.branch() {
ControlFlow::Continue(ok) => Ok(ok), ControlFlow::Continue(ok) => Ok(ok),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment