1 use system_error::SystemError; 2 3 use crate::{ 4 driver::firmware::efi::EFIInitFlags, 5 libs::align::page_align_down, 6 mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr}, 7 }; 8 9 use super::{fdt::EFIFdtParams, EFIManager}; 10 11 #[derive(Debug)] 12 pub struct EFIMemoryMapInfo { 13 /// EFI Memory Map的物理地址 14 pub(super) paddr: Option<PhysAddr>, 15 /// EFI Memory Map的虚拟地址 16 pub(super) vaddr: Option<VirtAddr>, 17 /// EFI Memory Map的大小 18 pub(super) size: usize, 19 /// 映射的描述信息的数量 20 pub(super) nr_map: usize, 21 /// EFI Memory Map的描述信息的大小 22 pub(super) desc_size: usize, 23 /// EFI Memory Map的描述信息的版本 24 pub(super) desc_version: usize, 25 } 26 27 impl EFIMemoryMapInfo { 28 pub const DEFAULT: Self = EFIMemoryMapInfo { 29 paddr: None, 30 vaddr: None, 31 size: 0, 32 nr_map: 0, 33 desc_size: 0, 34 desc_version: 0, 35 }; 36 37 /// 获取EFI Memory Map的虚拟的结束地址 38 #[allow(dead_code)] 39 pub fn map_end_vaddr(&self) -> Option<VirtAddr> { 40 return self.vaddr.map(|v| v + self.size); 41 } 42 } 43 44 impl EFIManager { 45 /// Map the EFI memory map data structure 46 /// 47 /// 进入当前函数前,不应持有efi_manager.inner的锁 48 #[inline(never)] 49 pub(super) fn memmap_init_early(&self, data: &EFIFdtParams) -> Result<(), SystemError> { 50 return self.do_efi_memmap_init(data, true); 51 } 52 53 /// 映射 EFI memory map 54 /// 55 /// 该函数在内核启动过程中使用 56 /// 57 /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/memmap.c?fi=efi_memmap_init_early#104 58 #[inline(never)] 59 fn do_efi_memmap_init(&self, data: &EFIFdtParams, early: bool) -> Result<(), SystemError> { 60 let paddr = data.mmap_base.expect("mmap_base is not set"); 61 let paddr = PhysAddr::new(paddr as usize); 62 kdebug!("do_efi_memmap_init: paddr={paddr:?}"); 63 let mut inner_guard = self.inner.write(); 64 if early { 65 let offset = paddr.data() - page_align_down(paddr.data()); 66 let map_size = data.mmap_size.unwrap() as usize + offset; 67 68 kdebug!("do_efi_memmap_init: map_size={map_size:#x}"); 69 // 映射内存 70 let mut vaddr = EarlyIoRemap::map( 71 PhysAddr::new(page_align_down(paddr.data())), 72 map_size, 73 false, 74 ) 75 .map(|(vaddr, _)| vaddr)?; 76 77 vaddr += offset; 78 79 inner_guard.mmap.vaddr = Some(vaddr); 80 } else { 81 unimplemented!("efi_memmap_init_late") 82 } 83 84 if inner_guard.mmap.vaddr.is_none() { 85 kerror!("Cannot map the EFI memory map!"); 86 return Err(SystemError::ENOMEM); 87 } 88 89 inner_guard.mmap.paddr = Some(paddr); 90 inner_guard.mmap.size = data.mmap_size.unwrap() as usize; 91 inner_guard.mmap.nr_map = 92 data.mmap_size.unwrap() as usize / data.mmap_desc_size.unwrap() as usize; 93 inner_guard.mmap.desc_size = data.mmap_desc_size.unwrap() as usize; 94 inner_guard.mmap.desc_version = data.mmap_desc_version.unwrap() as usize; 95 96 inner_guard.init_flags.set(EFIInitFlags::MEMMAP, true); 97 98 return Ok(()); 99 } 100 } 101