diff --git a/src/arch/aarch64/paging.rs b/src/arch/aarch64/paging.rs index 8feb1fe4fd8e1e7ab994724f6b5579b2ee092cce..0e804551ca4c319d1a78a5320845e01b1e84b600 100644 --- a/src/arch/aarch64/paging.rs +++ b/src/arch/aarch64/paging.rs @@ -23,7 +23,7 @@ pub unsafe fn paging_create< D: Disk, M: Iterator<Item=OsMemoryEntry>, 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"); None } diff --git a/src/os/uefi/arch/aarch64/mod.rs b/src/os/uefi/arch/aarch64/mod.rs index 6437f432c4b75fd4bcba682beb4723048f7ae3ba..efb901cc72d6baf4685dbcd7cf2f2b8df3e21883 100644 --- a/src/os/uefi/arch/aarch64/mod.rs +++ b/src/os/uefi/arch/aarch64/mod.rs @@ -9,7 +9,6 @@ use crate::{ use super::super::{ OsEfi, - exit_boot_services, acpi::{ RSDPS_AREA, find_acpi_table_pointers, @@ -35,8 +34,12 @@ unsafe extern "C" fn kernel_entry( args: *const KernelArgs, ) -> ! { // 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 asm!("msr daifset, #2"); diff --git a/src/os/uefi/arch/x86_64/mod.rs b/src/os/uefi/arch/x86_64/mod.rs index 7745aeb7f8b90e8f7eae6d5aafa6dfa88a3401fc..73cbf7115c6b0eb837d4b9842ce01de34ab06264 100644 --- a/src/os/uefi/arch/x86_64/mod.rs +++ b/src/os/uefi/arch/x86_64/mod.rs @@ -9,7 +9,6 @@ use crate::{ use super::super::{ OsEfi, - exit_boot_services, acpi::{ RSDPS_AREA, find_acpi_table_pointers, @@ -30,8 +29,12 @@ unsafe extern "C" fn kernel_entry( args: *const KernelArgs, ) -> ! { // 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 llvm_asm!("cli" : : : "memory" : "intel", "volatile"); diff --git a/src/os/uefi/memory_map.rs b/src/os/uefi/memory_map.rs index 6e5e250d7c4ee48c6545a7ce8a9d4b5f4571cbe0..c3256633462d64de3e06ef7a8beb3cefcdd648c8 100644 --- a/src/os/uefi/memory_map.rs +++ b/src/os/uefi/memory_map.rs @@ -1,16 +1,18 @@ -use alloc::boxed::Box; +use alloc::vec::Vec; use core::{mem, ptr}; -use log::error; use uefi::memory::{MemoryDescriptor, MemoryType}; use crate::os::{OsMemoryEntry, OsMemoryKind}; use super::status_to_result; +const EFI_MEMORY_RUNTIME: u64 = 0x8000000000000000; + pub struct MemoryMapIter { - map: Box<[u8]>, + map: Vec<u8>, map_key: usize, descriptor_size: usize, + descriptor_version: u32, i: usize, } @@ -30,63 +32,99 @@ impl MemoryMapIter { &mut descriptor_size, &mut descriptor_version )).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); Self { - map: map.into_boxed_slice(), + map, map_key, descriptor_size, + descriptor_version, 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 { type Item=OsMemoryEntry; fn next(&mut self) -> Option<Self::Item> { - 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) }; - - 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 - } + 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) }; + + 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; +pub unsafe fn memory_map() -> MemoryMapIter { + let mut iter = MemoryMapIter::new(); - for (i, entry) in iter.enumerate() { - crate::AREAS[i] = entry; + // Using next to avoid consuming iterator + while let Some(entry) = iter.next() { + crate::AREAS[iter.i] = entry; } - map_key + // Rewind iterator + iter.i = 0; + + iter } diff --git a/src/os/uefi/mod.rs b/src/os/uefi/mod.rs index 171043225d01331748bdd9d8e82e585369196ef1..0e8179e71878cf6ca1c65224a0600181ee765c9c 100644 --- a/src/os/uefi/mod.rs +++ b/src/os/uefi/mod.rs @@ -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> { match status.branch() { ControlFlow::Continue(ok) => Ok(ok),