17a29d4fcSLoGin use core::{intrinsics::unlikely, mem::size_of}; 27a29d4fcSLoGin 37a29d4fcSLoGin use system_error::SystemError; 4*92849878SLoGin use uefi_raw::table::boot::{MemoryAttribute, MemoryType}; 57a29d4fcSLoGin 67a29d4fcSLoGin use crate::{ 7*92849878SLoGin arch::MMArch, 8*92849878SLoGin driver::{firmware::efi::EFIInitFlags, open_firmware::fdt::open_firmware_fdt_driver}, 9*92849878SLoGin libs::align::{page_align_down, page_align_up}, 10*92849878SLoGin mm::{ 11*92849878SLoGin allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap, 12*92849878SLoGin memblock::mem_block_manager, MemoryManagementArch, PhysAddr, VirtAddr, 13*92849878SLoGin }, 147a29d4fcSLoGin }; 157a29d4fcSLoGin 167a29d4fcSLoGin use super::efi_manager; 177a29d4fcSLoGin 187a29d4fcSLoGin #[allow(dead_code)] 197a29d4fcSLoGin #[inline(never)] 207a29d4fcSLoGin pub fn efi_init() { 21*92849878SLoGin 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 31*92849878SLoGin // 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)); 52*92849878SLoGin if let Err(e) = r { 53*92849878SLoGin kerror!("Failed to initialize UEFI: {:?}", e); 54*92849878SLoGin efi_manager().efi_memmap_unmap(); 55*92849878SLoGin return; 567a29d4fcSLoGin } 577a29d4fcSLoGin 58*92849878SLoGin reserve_memory_regions(); 59*92849878SLoGin // todo: 由于上面的`uefi_init`里面,按照UEFI的数据,初始化了内存块, 60*92849878SLoGin // 但是UEFI给的数据可能不全,这里Linux会再次从设备树检测可用内存,从而填补完全相应的内存信息 61*92849878SLoGin 62*92849878SLoGin // 并且,Linux还对EFI BootService提供的Mokvar表进行了检测以及空间保留。 63*92849878SLoGin 64*92849878SLoGin // todo: 模仿Linux的行为,做好接下来的几步工作: 65*92849878SLoGin // 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217 66*92849878SLoGin 67*92849878SLoGin // 保留mmap table的内存 68*92849878SLoGin let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize); 69*92849878SLoGin let offset = data_from_fdt.mmap_base.unwrap() as usize - base; 70*92849878SLoGin 71*92849878SLoGin mem_block_manager() 72*92849878SLoGin .reserve_block( 73*92849878SLoGin PhysAddr::new(base), 74*92849878SLoGin data_from_fdt.mmap_size.unwrap() as usize + offset, 75*92849878SLoGin ) 76*92849878SLoGin .expect("Failed to reserve memory for EFI mmap table"); 77*92849878SLoGin 78*92849878SLoGin // todo: Initialize screen info 79*92849878SLoGin 80*92849878SLoGin kinfo!("UEFI init done!"); 817a29d4fcSLoGin } 827a29d4fcSLoGin 837a29d4fcSLoGin #[inline(never)] 847a29d4fcSLoGin fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> { 857a29d4fcSLoGin // 定义错误处理函数 867a29d4fcSLoGin 877a29d4fcSLoGin // 错误处理:取消systable的映射 887a29d4fcSLoGin let err_unmap_systable = |st_vaddr: VirtAddr| { 897a29d4fcSLoGin EarlyIoRemap::unmap(st_vaddr) 907a29d4fcSLoGin .map_err(|e| { 917a29d4fcSLoGin kerror!("Failed to unmap system table: {e:?}"); 927a29d4fcSLoGin }) 937a29d4fcSLoGin .ok(); 947a29d4fcSLoGin }; 957a29d4fcSLoGin 967a29d4fcSLoGin // 映射system table 977a29d4fcSLoGin 987a29d4fcSLoGin let st_size = size_of::<uefi_raw::table::system::SystemTable>(); 997a29d4fcSLoGin 100*92849878SLoGin let st_vaddr = EarlyIoRemap::map_not_aligned(system_table, st_size, true).map_err(|e| { 1017a29d4fcSLoGin kwarn!("Unable to map EFI system table, e:{e:?}"); 1027a29d4fcSLoGin e 1037a29d4fcSLoGin })?; 1047a29d4fcSLoGin 1057a29d4fcSLoGin efi_manager() 1067a29d4fcSLoGin .inner 1077a29d4fcSLoGin .write() 1087a29d4fcSLoGin .init_flags 1097a29d4fcSLoGin .set(EFIInitFlags::BOOT, true); 1107a29d4fcSLoGin 1117a29d4fcSLoGin efi_manager() 1127a29d4fcSLoGin .inner 1137a29d4fcSLoGin .write() 1147a29d4fcSLoGin .init_flags 1157a29d4fcSLoGin .set(EFIInitFlags::EFI_64BIT, true); 1167a29d4fcSLoGin 1177a29d4fcSLoGin if st_vaddr.is_null() { 1187a29d4fcSLoGin return Err(SystemError::EINVAL); 1197a29d4fcSLoGin } 1207a29d4fcSLoGin 1217a29d4fcSLoGin // 解析system table 1227a29d4fcSLoGin let st_ptr = st_vaddr.data() as *const uefi_raw::table::system::SystemTable; 1237a29d4fcSLoGin efi_manager() 1247a29d4fcSLoGin .check_system_table_header(unsafe { &st_ptr.as_ref().unwrap().header }, 2) 1257a29d4fcSLoGin .map_err(|e| { 1267a29d4fcSLoGin err_unmap_systable(st_vaddr); 1277a29d4fcSLoGin e 1287a29d4fcSLoGin })?; 1297a29d4fcSLoGin 1307a29d4fcSLoGin let st_ref = unsafe { st_ptr.as_ref().unwrap() }; 131*92849878SLoGin 132*92849878SLoGin let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize); 133*92849878SLoGin let mut inner_write_guard = efi_manager().inner.write(); 134*92849878SLoGin inner_write_guard.runtime_paddr = Some(runtime_service_paddr); 1357a29d4fcSLoGin inner_write_guard.runtime_service_version = Some(st_ref.header.revision); 1367a29d4fcSLoGin 137*92849878SLoGin drop(inner_write_guard); 138*92849878SLoGin efi_manager().report_systable_header( 139*92849878SLoGin &st_ref.header, 140*92849878SLoGin efi_vaddr_2_paddr(st_ref.firmware_vendor as usize), 1417a29d4fcSLoGin ); 1427a29d4fcSLoGin 143*92849878SLoGin { 144*92849878SLoGin // 映射configuration table 145*92849878SLoGin let table_size = st_ref.number_of_configuration_table_entries 146*92849878SLoGin * size_of::<uefi_raw::table::configuration::ConfigurationTable>(); 147*92849878SLoGin let config_table_vaddr = EarlyIoRemap::map_not_aligned( 148*92849878SLoGin efi_vaddr_2_paddr(st_ref.configuration_table as usize), 149*92849878SLoGin table_size, 150*92849878SLoGin true, 151*92849878SLoGin ) 152*92849878SLoGin .map_err(|e| { 153*92849878SLoGin kwarn!("Unable to map EFI configuration table, e:{e:?}"); 154*92849878SLoGin err_unmap_systable(st_vaddr); 155*92849878SLoGin e 156*92849878SLoGin })?; 157*92849878SLoGin let cfg_tables = unsafe { 158*92849878SLoGin core::slice::from_raw_parts( 159*92849878SLoGin config_table_vaddr.data() 160*92849878SLoGin as *const uefi_raw::table::configuration::ConfigurationTable, 161*92849878SLoGin st_ref.number_of_configuration_table_entries, 162*92849878SLoGin ) 163*92849878SLoGin }; 164*92849878SLoGin // 解析configuration table 165*92849878SLoGin let r = efi_manager().parse_config_tables(cfg_tables); 166*92849878SLoGin 167*92849878SLoGin EarlyIoRemap::unmap(config_table_vaddr).expect("Failed to unmap EFI config table"); 168*92849878SLoGin return r; 169*92849878SLoGin } 170*92849878SLoGin } 171*92849878SLoGin 172*92849878SLoGin /// 把EFI固件提供的虚拟地址转换为物理地址。 173*92849878SLoGin /// 174*92849878SLoGin /// 因为在调用SetVirtualAddressMap()之后,`EFI SystemTable` 的一些数据成员会被虚拟重映射 175*92849878SLoGin /// 176*92849878SLoGin /// ## 锁 177*92849878SLoGin /// 178*92849878SLoGin /// 在进入该函数前,请不要持有`efi_manager().inner`的写锁 179*92849878SLoGin fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr { 180*92849878SLoGin let guard = efi_manager().inner.read(); 181*92849878SLoGin let mmap = &guard.mmap; 182*92849878SLoGin 183*92849878SLoGin let efi_vaddr: u64 = efi_vaddr as u64; 184*92849878SLoGin for md in mmap.iter() { 185*92849878SLoGin if !md.att.contains(MemoryAttribute::RUNTIME) { 186*92849878SLoGin continue; 187*92849878SLoGin } 188*92849878SLoGin 189*92849878SLoGin if md.virt_start == 0 { 190*92849878SLoGin // no virtual mapping has been installed by the DragonStub 191*92849878SLoGin break; 192*92849878SLoGin } 193*92849878SLoGin 194*92849878SLoGin if md.virt_start <= efi_vaddr 195*92849878SLoGin && ((efi_vaddr - md.virt_start) < (md.page_count << (MMArch::PAGE_SHIFT as u64))) 196*92849878SLoGin { 197*92849878SLoGin return PhysAddr::new((md.phys_start + (efi_vaddr - md.virt_start)) as usize); 198*92849878SLoGin } 199*92849878SLoGin } 200*92849878SLoGin 201*92849878SLoGin return PhysAddr::new(efi_vaddr as usize); 202*92849878SLoGin } 203*92849878SLoGin 204*92849878SLoGin /// 根据UEFI提供的内存描述符的信息,填写内存区域信息 205*92849878SLoGin fn reserve_memory_regions() { 206*92849878SLoGin // 忽略之前已经发现的任何内存块。因为之前发现的内存块来自平坦设备树, 207*92849878SLoGin // 但是UEFI有自己的内存映射表,我们以UEFI提供的为准 208*92849878SLoGin mem_block_manager() 209*92849878SLoGin .remove_block(PhysAddr::new(0), PhysAddr::MAX.data()) 210*92849878SLoGin .expect("Failed to remove all memblocks!"); 211*92849878SLoGin 212*92849878SLoGin let inner_guard = efi_manager().inner.read_irqsave(); 213*92849878SLoGin for md in inner_guard.mmap.iter() { 214*92849878SLoGin let page_count = (PhysPageFrame::new(PhysAddr::new(page_align_up( 215*92849878SLoGin (md.phys_start + md.page_count << (MMArch::PAGE_SHIFT as u64)) as usize, 216*92849878SLoGin ))) 217*92849878SLoGin .ppn() 218*92849878SLoGin - PhysPageFrame::new(PhysAddr::new(page_align_down(md.phys_start as usize))).ppn()) 219*92849878SLoGin as u64; 220*92849878SLoGin let phys_start = page_align_down(md.phys_start as usize); 221*92849878SLoGin let size = (page_count << (MMArch::PAGE_SHIFT as u64)) as usize; 222*92849878SLoGin 223*92849878SLoGin if md.is_memory() { 224*92849878SLoGin open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64); 225*92849878SLoGin if !md.is_usable_memory() { 226*92849878SLoGin mem_block_manager() 227*92849878SLoGin .mark_nomap(PhysAddr::new(phys_start), size) 228*92849878SLoGin .unwrap(); 229*92849878SLoGin } 230*92849878SLoGin 231*92849878SLoGin // keep ACPI reclaim memory intact for kexec etc. 232*92849878SLoGin if md.ty == MemoryType::ACPI_RECLAIM { 233*92849878SLoGin mem_block_manager() 234*92849878SLoGin .reserve_block(PhysAddr::new(phys_start), size) 235*92849878SLoGin .unwrap(); 236*92849878SLoGin } 237*92849878SLoGin } 238*92849878SLoGin } 2397a29d4fcSLoGin } 240