17a29d4fcSLoGin use core::{intrinsics::unlikely, mem::size_of}; 27a29d4fcSLoGin 37a29d4fcSLoGin use system_error::SystemError; 492849878SLoGin use uefi_raw::table::boot::{MemoryAttribute, MemoryType}; 57a29d4fcSLoGin 67a29d4fcSLoGin use crate::{ 792849878SLoGin arch::MMArch, 892849878SLoGin driver::{firmware::efi::EFIInitFlags, open_firmware::fdt::open_firmware_fdt_driver}, 992849878SLoGin libs::align::{page_align_down, page_align_up}, 1092849878SLoGin mm::{ 1192849878SLoGin allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap, 1292849878SLoGin memblock::mem_block_manager, MemoryManagementArch, PhysAddr, VirtAddr, 1392849878SLoGin }, 147a29d4fcSLoGin }; 157a29d4fcSLoGin 167a29d4fcSLoGin use super::efi_manager; 177a29d4fcSLoGin 187a29d4fcSLoGin #[allow(dead_code)] 197a29d4fcSLoGin #[inline(never)] 207a29d4fcSLoGin pub fn efi_init() { 2192849878SLoGin kinfo!("Initializing efi..."); 227a29d4fcSLoGin let data_from_fdt = efi_manager() 237a29d4fcSLoGin .get_fdt_params() 247a29d4fcSLoGin .expect("Failed to get fdt params"); 257a29d4fcSLoGin 267a29d4fcSLoGin if data_from_fdt.systable.is_none() { 277a29d4fcSLoGin kerror!("Failed to get systable from fdt"); 287a29d4fcSLoGin return; 297a29d4fcSLoGin } 307a29d4fcSLoGin 3192849878SLoGin // kdebug!("to map memory table"); 327a29d4fcSLoGin 337a29d4fcSLoGin // 映射mmap table 347a29d4fcSLoGin if efi_manager().memmap_init_early(&data_from_fdt).is_err() { 357a29d4fcSLoGin // 如果我们通过UEFI进行引导, 367a29d4fcSLoGin // 那么 UEFI memory map 就是我们拥有的关于内存的唯一描述, 377a29d4fcSLoGin // 所以如果我们无法访问它,那么继续进行下去就没有什么意义了 387a29d4fcSLoGin 397a29d4fcSLoGin kerror!("Failed to initialize early memory map"); 407a29d4fcSLoGin loop {} 417a29d4fcSLoGin } 427a29d4fcSLoGin // kdebug!("NNNN"); 437a29d4fcSLoGin // kwarn!("BBBB, e:{:?}", SystemError::EINVAL); 447a29d4fcSLoGin 457a29d4fcSLoGin let desc_version = efi_manager().desc_version(); 467a29d4fcSLoGin 477a29d4fcSLoGin if unlikely(desc_version != 1) { 487a29d4fcSLoGin kwarn!("Unexpected EFI memory map version: {}", desc_version); 497a29d4fcSLoGin } 507a29d4fcSLoGin 517a29d4fcSLoGin let r = uefi_init(PhysAddr::new(data_from_fdt.systable.unwrap() as usize)); 5292849878SLoGin if let Err(e) = r { 5392849878SLoGin kerror!("Failed to initialize UEFI: {:?}", e); 5492849878SLoGin efi_manager().efi_memmap_unmap(); 5592849878SLoGin return; 567a29d4fcSLoGin } 577a29d4fcSLoGin 5892849878SLoGin reserve_memory_regions(); 5992849878SLoGin // todo: 由于上面的`uefi_init`里面,按照UEFI的数据,初始化了内存块, 6092849878SLoGin // 但是UEFI给的数据可能不全,这里Linux会再次从设备树检测可用内存,从而填补完全相应的内存信息 6192849878SLoGin 6292849878SLoGin // 并且,Linux还对EFI BootService提供的Mokvar表进行了检测以及空间保留。 6392849878SLoGin 6492849878SLoGin // todo: 模仿Linux的行为,做好接下来的几步工作: 6592849878SLoGin // 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217 6692849878SLoGin 6792849878SLoGin // 保留mmap table的内存 6892849878SLoGin let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize); 6992849878SLoGin let offset = data_from_fdt.mmap_base.unwrap() as usize - base; 7092849878SLoGin 7192849878SLoGin mem_block_manager() 7292849878SLoGin .reserve_block( 7392849878SLoGin PhysAddr::new(base), 7492849878SLoGin data_from_fdt.mmap_size.unwrap() as usize + offset, 7592849878SLoGin ) 7692849878SLoGin .expect("Failed to reserve memory for EFI mmap table"); 7792849878SLoGin 78*453452ccSLoGin // 保留内核的内存 79*453452ccSLoGin if let Some(info) = efi_manager().inner.read().dragonstub_load_info.clone() { 80*453452ccSLoGin mem_block_manager() 81*453452ccSLoGin .reserve_block( 82*453452ccSLoGin PhysAddr::new(info.paddr as usize), 83*453452ccSLoGin page_align_up(info.size as usize), 84*453452ccSLoGin ) 85*453452ccSLoGin .expect("Failed to reserve kernel itself memory"); 86*453452ccSLoGin } 87*453452ccSLoGin 8892849878SLoGin // todo: Initialize screen info 8992849878SLoGin 9092849878SLoGin kinfo!("UEFI init done!"); 917a29d4fcSLoGin } 927a29d4fcSLoGin 937a29d4fcSLoGin #[inline(never)] 947a29d4fcSLoGin fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> { 957a29d4fcSLoGin // 定义错误处理函数 967a29d4fcSLoGin 977a29d4fcSLoGin // 错误处理:取消systable的映射 987a29d4fcSLoGin let err_unmap_systable = |st_vaddr: VirtAddr| { 997a29d4fcSLoGin EarlyIoRemap::unmap(st_vaddr) 1007a29d4fcSLoGin .map_err(|e| { 1017a29d4fcSLoGin kerror!("Failed to unmap system table: {e:?}"); 1027a29d4fcSLoGin }) 1037a29d4fcSLoGin .ok(); 1047a29d4fcSLoGin }; 1057a29d4fcSLoGin 1067a29d4fcSLoGin // 映射system table 1077a29d4fcSLoGin 1087a29d4fcSLoGin let st_size = size_of::<uefi_raw::table::system::SystemTable>(); 1097a29d4fcSLoGin 11092849878SLoGin let st_vaddr = EarlyIoRemap::map_not_aligned(system_table, st_size, true).map_err(|e| { 1117a29d4fcSLoGin kwarn!("Unable to map EFI system table, e:{e:?}"); 1127a29d4fcSLoGin e 1137a29d4fcSLoGin })?; 1147a29d4fcSLoGin 1157a29d4fcSLoGin efi_manager() 1167a29d4fcSLoGin .inner 1177a29d4fcSLoGin .write() 1187a29d4fcSLoGin .init_flags 1197a29d4fcSLoGin .set(EFIInitFlags::BOOT, true); 1207a29d4fcSLoGin 1217a29d4fcSLoGin efi_manager() 1227a29d4fcSLoGin .inner 1237a29d4fcSLoGin .write() 1247a29d4fcSLoGin .init_flags 1257a29d4fcSLoGin .set(EFIInitFlags::EFI_64BIT, true); 1267a29d4fcSLoGin 1277a29d4fcSLoGin if st_vaddr.is_null() { 1287a29d4fcSLoGin return Err(SystemError::EINVAL); 1297a29d4fcSLoGin } 1307a29d4fcSLoGin 1317a29d4fcSLoGin // 解析system table 1327a29d4fcSLoGin let st_ptr = st_vaddr.data() as *const uefi_raw::table::system::SystemTable; 1337a29d4fcSLoGin efi_manager() 1347a29d4fcSLoGin .check_system_table_header(unsafe { &st_ptr.as_ref().unwrap().header }, 2) 1357a29d4fcSLoGin .map_err(|e| { 1367a29d4fcSLoGin err_unmap_systable(st_vaddr); 1377a29d4fcSLoGin e 1387a29d4fcSLoGin })?; 1397a29d4fcSLoGin 1407a29d4fcSLoGin let st_ref = unsafe { st_ptr.as_ref().unwrap() }; 14192849878SLoGin 14292849878SLoGin let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize); 14392849878SLoGin let mut inner_write_guard = efi_manager().inner.write(); 14492849878SLoGin inner_write_guard.runtime_paddr = Some(runtime_service_paddr); 1457a29d4fcSLoGin inner_write_guard.runtime_service_version = Some(st_ref.header.revision); 1467a29d4fcSLoGin 14792849878SLoGin drop(inner_write_guard); 14892849878SLoGin efi_manager().report_systable_header( 14992849878SLoGin &st_ref.header, 15092849878SLoGin efi_vaddr_2_paddr(st_ref.firmware_vendor as usize), 1517a29d4fcSLoGin ); 1527a29d4fcSLoGin 15392849878SLoGin { 15492849878SLoGin // 映射configuration table 15592849878SLoGin let table_size = st_ref.number_of_configuration_table_entries 15692849878SLoGin * size_of::<uefi_raw::table::configuration::ConfigurationTable>(); 15792849878SLoGin let config_table_vaddr = EarlyIoRemap::map_not_aligned( 15892849878SLoGin efi_vaddr_2_paddr(st_ref.configuration_table as usize), 15992849878SLoGin table_size, 16092849878SLoGin true, 16192849878SLoGin ) 16292849878SLoGin .map_err(|e| { 16392849878SLoGin kwarn!("Unable to map EFI configuration table, e:{e:?}"); 16492849878SLoGin err_unmap_systable(st_vaddr); 16592849878SLoGin e 16692849878SLoGin })?; 16792849878SLoGin let cfg_tables = unsafe { 16892849878SLoGin core::slice::from_raw_parts( 16992849878SLoGin config_table_vaddr.data() 17092849878SLoGin as *const uefi_raw::table::configuration::ConfigurationTable, 17192849878SLoGin st_ref.number_of_configuration_table_entries, 17292849878SLoGin ) 17392849878SLoGin }; 17492849878SLoGin // 解析configuration table 17592849878SLoGin let r = efi_manager().parse_config_tables(cfg_tables); 17692849878SLoGin 17792849878SLoGin EarlyIoRemap::unmap(config_table_vaddr).expect("Failed to unmap EFI config table"); 17892849878SLoGin return r; 17992849878SLoGin } 18092849878SLoGin } 18192849878SLoGin 18292849878SLoGin /// 把EFI固件提供的虚拟地址转换为物理地址。 18392849878SLoGin /// 18492849878SLoGin /// 因为在调用SetVirtualAddressMap()之后,`EFI SystemTable` 的一些数据成员会被虚拟重映射 18592849878SLoGin /// 18692849878SLoGin /// ## 锁 18792849878SLoGin /// 18892849878SLoGin /// 在进入该函数前,请不要持有`efi_manager().inner`的写锁 18992849878SLoGin fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr { 19092849878SLoGin let guard = efi_manager().inner.read(); 19192849878SLoGin let mmap = &guard.mmap; 19292849878SLoGin 19392849878SLoGin let efi_vaddr: u64 = efi_vaddr as u64; 19492849878SLoGin for md in mmap.iter() { 19592849878SLoGin if !md.att.contains(MemoryAttribute::RUNTIME) { 19692849878SLoGin continue; 19792849878SLoGin } 19892849878SLoGin 19992849878SLoGin if md.virt_start == 0 { 20092849878SLoGin // no virtual mapping has been installed by the DragonStub 20192849878SLoGin break; 20292849878SLoGin } 20392849878SLoGin 20492849878SLoGin if md.virt_start <= efi_vaddr 20592849878SLoGin && ((efi_vaddr - md.virt_start) < (md.page_count << (MMArch::PAGE_SHIFT as u64))) 20692849878SLoGin { 20792849878SLoGin return PhysAddr::new((md.phys_start + (efi_vaddr - md.virt_start)) as usize); 20892849878SLoGin } 20992849878SLoGin } 21092849878SLoGin 21192849878SLoGin return PhysAddr::new(efi_vaddr as usize); 21292849878SLoGin } 21392849878SLoGin 21492849878SLoGin /// 根据UEFI提供的内存描述符的信息,填写内存区域信息 21592849878SLoGin fn reserve_memory_regions() { 21692849878SLoGin // 忽略之前已经发现的任何内存块。因为之前发现的内存块来自平坦设备树, 21792849878SLoGin // 但是UEFI有自己的内存映射表,我们以UEFI提供的为准 21892849878SLoGin mem_block_manager() 21992849878SLoGin .remove_block(PhysAddr::new(0), PhysAddr::MAX.data()) 22092849878SLoGin .expect("Failed to remove all memblocks!"); 22192849878SLoGin 22292849878SLoGin let inner_guard = efi_manager().inner.read_irqsave(); 22392849878SLoGin for md in inner_guard.mmap.iter() { 22492849878SLoGin let page_count = (PhysPageFrame::new(PhysAddr::new(page_align_up( 225*453452ccSLoGin (md.phys_start + (md.page_count << (MMArch::PAGE_SHIFT as u64))) as usize, 22692849878SLoGin ))) 22792849878SLoGin .ppn() 22892849878SLoGin - PhysPageFrame::new(PhysAddr::new(page_align_down(md.phys_start as usize))).ppn()) 22992849878SLoGin as u64; 23092849878SLoGin let phys_start = page_align_down(md.phys_start as usize); 23192849878SLoGin let size = (page_count << (MMArch::PAGE_SHIFT as u64)) as usize; 23292849878SLoGin 233*453452ccSLoGin // kdebug!("Reserve memory region: {:#x}-{:#x}({:#x}), is_memory: {}, is_usable_memory:{}, type: {:?}, att: {:?}", phys_start, phys_start + size, page_count, md.is_memory(), md.is_usable_memory(), md.ty, md.att); 23492849878SLoGin if md.is_memory() { 23592849878SLoGin open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64); 23692849878SLoGin if !md.is_usable_memory() { 23792849878SLoGin mem_block_manager() 23892849878SLoGin .mark_nomap(PhysAddr::new(phys_start), size) 23992849878SLoGin .unwrap(); 24092849878SLoGin } 24192849878SLoGin 24292849878SLoGin // keep ACPI reclaim memory intact for kexec etc. 24392849878SLoGin if md.ty == MemoryType::ACPI_RECLAIM { 24492849878SLoGin mem_block_manager() 24592849878SLoGin .reserve_block(PhysAddr::new(phys_start), size) 24692849878SLoGin .unwrap(); 24792849878SLoGin } 24892849878SLoGin } 24992849878SLoGin } 2507a29d4fcSLoGin } 251