1b5b571e0SLoGin use core::{hint::spin_loop, 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, 8*471d65cfSLoGin driver::{ 9*471d65cfSLoGin firmware::efi::{esrt::efi_esrt_init, EFIInitFlags}, 10*471d65cfSLoGin open_firmware::fdt::open_firmware_fdt_driver, 11*471d65cfSLoGin }, 1292849878SLoGin libs::align::{page_align_down, page_align_up}, 1392849878SLoGin mm::{ 1492849878SLoGin allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap, 1592849878SLoGin memblock::mem_block_manager, MemoryManagementArch, PhysAddr, VirtAddr, 1692849878SLoGin }, 177a29d4fcSLoGin }; 187a29d4fcSLoGin 197a29d4fcSLoGin use super::efi_manager; 207a29d4fcSLoGin 217a29d4fcSLoGin #[allow(dead_code)] 227a29d4fcSLoGin #[inline(never)] 237a29d4fcSLoGin pub fn efi_init() { 2492849878SLoGin kinfo!("Initializing efi..."); 257a29d4fcSLoGin let data_from_fdt = efi_manager() 267a29d4fcSLoGin .get_fdt_params() 277a29d4fcSLoGin .expect("Failed to get fdt params"); 287a29d4fcSLoGin 297a29d4fcSLoGin if data_from_fdt.systable.is_none() { 307a29d4fcSLoGin kerror!("Failed to get systable from fdt"); 317a29d4fcSLoGin return; 327a29d4fcSLoGin } 337a29d4fcSLoGin 3492849878SLoGin // kdebug!("to map memory table"); 357a29d4fcSLoGin 367a29d4fcSLoGin // 映射mmap table 377a29d4fcSLoGin if efi_manager().memmap_init_early(&data_from_fdt).is_err() { 387a29d4fcSLoGin // 如果我们通过UEFI进行引导, 397a29d4fcSLoGin // 那么 UEFI memory map 就是我们拥有的关于内存的唯一描述, 407a29d4fcSLoGin // 所以如果我们无法访问它,那么继续进行下去就没有什么意义了 417a29d4fcSLoGin 427a29d4fcSLoGin kerror!("Failed to initialize early memory map"); 43b5b571e0SLoGin loop { 44b5b571e0SLoGin spin_loop(); 45b5b571e0SLoGin } 467a29d4fcSLoGin } 477a29d4fcSLoGin // kdebug!("NNNN"); 487a29d4fcSLoGin // kwarn!("BBBB, e:{:?}", SystemError::EINVAL); 497a29d4fcSLoGin 507a29d4fcSLoGin let desc_version = efi_manager().desc_version(); 517a29d4fcSLoGin 527a29d4fcSLoGin if unlikely(desc_version != 1) { 537a29d4fcSLoGin kwarn!("Unexpected EFI memory map version: {}", desc_version); 547a29d4fcSLoGin } 557a29d4fcSLoGin 567a29d4fcSLoGin let r = uefi_init(PhysAddr::new(data_from_fdt.systable.unwrap() as usize)); 5792849878SLoGin if let Err(e) = r { 5892849878SLoGin kerror!("Failed to initialize UEFI: {:?}", e); 5992849878SLoGin efi_manager().efi_memmap_unmap(); 6092849878SLoGin return; 617a29d4fcSLoGin } 627a29d4fcSLoGin 6392849878SLoGin reserve_memory_regions(); 6492849878SLoGin // todo: 由于上面的`uefi_init`里面,按照UEFI的数据,初始化了内存块, 6592849878SLoGin // 但是UEFI给的数据可能不全,这里Linux会再次从设备树检测可用内存,从而填补完全相应的内存信息 6692849878SLoGin 6792849878SLoGin // 并且,Linux还对EFI BootService提供的Mokvar表进行了检测以及空间保留。 6892849878SLoGin 6992849878SLoGin // todo: 模仿Linux的行为,做好接下来的几步工作: 7092849878SLoGin // 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217 7192849878SLoGin 72*471d65cfSLoGin // todo: early_init_dt_check_for_usable_mem_range 73*471d65cfSLoGin 74*471d65cfSLoGin efi_find_mirror(); 75*471d65cfSLoGin efi_esrt_init(); 76*471d65cfSLoGin 7792849878SLoGin // 保留mmap table的内存 7892849878SLoGin let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize); 7992849878SLoGin let offset = data_from_fdt.mmap_base.unwrap() as usize - base; 8092849878SLoGin 8192849878SLoGin mem_block_manager() 8292849878SLoGin .reserve_block( 8392849878SLoGin PhysAddr::new(base), 8492849878SLoGin data_from_fdt.mmap_size.unwrap() as usize + offset, 8592849878SLoGin ) 8692849878SLoGin .expect("Failed to reserve memory for EFI mmap table"); 8792849878SLoGin 88453452ccSLoGin // 保留内核的内存 89*471d65cfSLoGin if let Some(info) = efi_manager().inner_read().dragonstub_load_info { 90453452ccSLoGin mem_block_manager() 91453452ccSLoGin .reserve_block( 92453452ccSLoGin PhysAddr::new(info.paddr as usize), 93453452ccSLoGin page_align_up(info.size as usize), 94453452ccSLoGin ) 95453452ccSLoGin .expect("Failed to reserve kernel itself memory"); 96453452ccSLoGin } 97453452ccSLoGin 9892849878SLoGin // todo: Initialize screen info 9992849878SLoGin 10092849878SLoGin kinfo!("UEFI init done!"); 1017a29d4fcSLoGin } 1027a29d4fcSLoGin 103*471d65cfSLoGin fn efi_find_mirror() { 104*471d65cfSLoGin let efi_guard = efi_manager().inner_read(); 105*471d65cfSLoGin let mut total_size = 0; 106*471d65cfSLoGin let mut mirror_size = 0; 107*471d65cfSLoGin for md in efi_guard.mmap.iter() { 108*471d65cfSLoGin let start = PhysAddr::new(md.phys_start as usize); 109*471d65cfSLoGin let size = (md.page_count << (MMArch::PAGE_SHIFT as u64)) as usize; 110*471d65cfSLoGin 111*471d65cfSLoGin if md.att.contains(MemoryAttribute::MORE_RELIABLE) { 112*471d65cfSLoGin mem_block_manager().mark_mirror(start, size).unwrap(); 113*471d65cfSLoGin mirror_size += size; 114*471d65cfSLoGin } 115*471d65cfSLoGin 116*471d65cfSLoGin total_size += size; 117*471d65cfSLoGin } 118*471d65cfSLoGin 119*471d65cfSLoGin if mirror_size > 0 { 120*471d65cfSLoGin kinfo!( 121*471d65cfSLoGin "Memory: {}M/{}M mirrored memory", 122*471d65cfSLoGin mirror_size >> 20, 123*471d65cfSLoGin total_size >> 20 124*471d65cfSLoGin ); 125*471d65cfSLoGin } 126*471d65cfSLoGin } 127*471d65cfSLoGin 1287a29d4fcSLoGin #[inline(never)] 1297a29d4fcSLoGin fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> { 1307a29d4fcSLoGin // 定义错误处理函数 1317a29d4fcSLoGin 1327a29d4fcSLoGin // 错误处理:取消systable的映射 1337a29d4fcSLoGin let err_unmap_systable = |st_vaddr: VirtAddr| { 1347a29d4fcSLoGin EarlyIoRemap::unmap(st_vaddr) 1357a29d4fcSLoGin .map_err(|e| { 1367a29d4fcSLoGin kerror!("Failed to unmap system table: {e:?}"); 1377a29d4fcSLoGin }) 1387a29d4fcSLoGin .ok(); 1397a29d4fcSLoGin }; 1407a29d4fcSLoGin 1417a29d4fcSLoGin // 映射system table 1427a29d4fcSLoGin 1437a29d4fcSLoGin let st_size = size_of::<uefi_raw::table::system::SystemTable>(); 1447a29d4fcSLoGin 14592849878SLoGin let st_vaddr = EarlyIoRemap::map_not_aligned(system_table, st_size, true).map_err(|e| { 1467a29d4fcSLoGin kwarn!("Unable to map EFI system table, e:{e:?}"); 1477a29d4fcSLoGin e 1487a29d4fcSLoGin })?; 1497a29d4fcSLoGin 1507a29d4fcSLoGin efi_manager() 1517a29d4fcSLoGin .inner 1527a29d4fcSLoGin .write() 1537a29d4fcSLoGin .init_flags 1547a29d4fcSLoGin .set(EFIInitFlags::BOOT, true); 1557a29d4fcSLoGin 1567a29d4fcSLoGin efi_manager() 1577a29d4fcSLoGin .inner 1587a29d4fcSLoGin .write() 1597a29d4fcSLoGin .init_flags 1607a29d4fcSLoGin .set(EFIInitFlags::EFI_64BIT, true); 1617a29d4fcSLoGin 1627a29d4fcSLoGin if st_vaddr.is_null() { 1637a29d4fcSLoGin return Err(SystemError::EINVAL); 1647a29d4fcSLoGin } 1657a29d4fcSLoGin 1667a29d4fcSLoGin // 解析system table 1677a29d4fcSLoGin let st_ptr = st_vaddr.data() as *const uefi_raw::table::system::SystemTable; 1687a29d4fcSLoGin efi_manager() 1697a29d4fcSLoGin .check_system_table_header(unsafe { &st_ptr.as_ref().unwrap().header }, 2) 1707a29d4fcSLoGin .map_err(|e| { 1717a29d4fcSLoGin err_unmap_systable(st_vaddr); 1727a29d4fcSLoGin e 1737a29d4fcSLoGin })?; 1747a29d4fcSLoGin 1757a29d4fcSLoGin let st_ref = unsafe { st_ptr.as_ref().unwrap() }; 17692849878SLoGin 17792849878SLoGin let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize); 178*471d65cfSLoGin let mut inner_write_guard = efi_manager().inner_write(); 17992849878SLoGin inner_write_guard.runtime_paddr = Some(runtime_service_paddr); 1807a29d4fcSLoGin inner_write_guard.runtime_service_version = Some(st_ref.header.revision); 1817a29d4fcSLoGin 18292849878SLoGin drop(inner_write_guard); 18392849878SLoGin efi_manager().report_systable_header( 18492849878SLoGin &st_ref.header, 18592849878SLoGin efi_vaddr_2_paddr(st_ref.firmware_vendor as usize), 1867a29d4fcSLoGin ); 1877a29d4fcSLoGin 18892849878SLoGin { 18992849878SLoGin // 映射configuration table 19092849878SLoGin let table_size = st_ref.number_of_configuration_table_entries 19192849878SLoGin * size_of::<uefi_raw::table::configuration::ConfigurationTable>(); 19292849878SLoGin let config_table_vaddr = EarlyIoRemap::map_not_aligned( 19392849878SLoGin efi_vaddr_2_paddr(st_ref.configuration_table as usize), 19492849878SLoGin table_size, 19592849878SLoGin true, 19692849878SLoGin ) 19792849878SLoGin .map_err(|e| { 19892849878SLoGin kwarn!("Unable to map EFI configuration table, e:{e:?}"); 19992849878SLoGin err_unmap_systable(st_vaddr); 20092849878SLoGin e 20192849878SLoGin })?; 20292849878SLoGin let cfg_tables = unsafe { 20392849878SLoGin core::slice::from_raw_parts( 20492849878SLoGin config_table_vaddr.data() 20592849878SLoGin as *const uefi_raw::table::configuration::ConfigurationTable, 20692849878SLoGin st_ref.number_of_configuration_table_entries, 20792849878SLoGin ) 20892849878SLoGin }; 20992849878SLoGin // 解析configuration table 21092849878SLoGin let r = efi_manager().parse_config_tables(cfg_tables); 21192849878SLoGin 21292849878SLoGin EarlyIoRemap::unmap(config_table_vaddr).expect("Failed to unmap EFI config table"); 21392849878SLoGin return r; 21492849878SLoGin } 21592849878SLoGin } 21692849878SLoGin 21792849878SLoGin /// 把EFI固件提供的虚拟地址转换为物理地址。 21892849878SLoGin /// 21992849878SLoGin /// 因为在调用SetVirtualAddressMap()之后,`EFI SystemTable` 的一些数据成员会被虚拟重映射 22092849878SLoGin /// 22192849878SLoGin /// ## 锁 22292849878SLoGin /// 22392849878SLoGin /// 在进入该函数前,请不要持有`efi_manager().inner`的写锁 22492849878SLoGin fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr { 225*471d65cfSLoGin let guard = efi_manager().inner_read(); 22692849878SLoGin let mmap = &guard.mmap; 22792849878SLoGin 22892849878SLoGin let efi_vaddr: u64 = efi_vaddr as u64; 22992849878SLoGin for md in mmap.iter() { 23092849878SLoGin if !md.att.contains(MemoryAttribute::RUNTIME) { 23192849878SLoGin continue; 23292849878SLoGin } 23392849878SLoGin 23492849878SLoGin if md.virt_start == 0 { 23592849878SLoGin // no virtual mapping has been installed by the DragonStub 23692849878SLoGin break; 23792849878SLoGin } 23892849878SLoGin 23992849878SLoGin if md.virt_start <= efi_vaddr 24092849878SLoGin && ((efi_vaddr - md.virt_start) < (md.page_count << (MMArch::PAGE_SHIFT as u64))) 24192849878SLoGin { 24292849878SLoGin return PhysAddr::new((md.phys_start + (efi_vaddr - md.virt_start)) as usize); 24392849878SLoGin } 24492849878SLoGin } 24592849878SLoGin 24692849878SLoGin return PhysAddr::new(efi_vaddr as usize); 24792849878SLoGin } 24892849878SLoGin 24992849878SLoGin /// 根据UEFI提供的内存描述符的信息,填写内存区域信息 25092849878SLoGin fn reserve_memory_regions() { 25192849878SLoGin // 忽略之前已经发现的任何内存块。因为之前发现的内存块来自平坦设备树, 25292849878SLoGin // 但是UEFI有自己的内存映射表,我们以UEFI提供的为准 25392849878SLoGin mem_block_manager() 25492849878SLoGin .remove_block(PhysAddr::new(0), PhysAddr::MAX.data()) 25592849878SLoGin .expect("Failed to remove all memblocks!"); 25692849878SLoGin 25792849878SLoGin let inner_guard = efi_manager().inner.read_irqsave(); 25892849878SLoGin for md in inner_guard.mmap.iter() { 25992849878SLoGin let page_count = (PhysPageFrame::new(PhysAddr::new(page_align_up( 260453452ccSLoGin (md.phys_start + (md.page_count << (MMArch::PAGE_SHIFT as u64))) as usize, 26192849878SLoGin ))) 26292849878SLoGin .ppn() 26392849878SLoGin - PhysPageFrame::new(PhysAddr::new(page_align_down(md.phys_start as usize))).ppn()) 26492849878SLoGin as u64; 26592849878SLoGin let phys_start = page_align_down(md.phys_start as usize); 26692849878SLoGin let size = (page_count << (MMArch::PAGE_SHIFT as u64)) as usize; 26792849878SLoGin 268453452ccSLoGin // 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); 26992849878SLoGin if md.is_memory() { 27092849878SLoGin open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64); 27192849878SLoGin if !md.is_usable_memory() { 272*471d65cfSLoGin // kdebug!( 273*471d65cfSLoGin // "Marking non-usable memory as nomap: {:#x}-{:#x}", 274*471d65cfSLoGin // phys_start, 275*471d65cfSLoGin // phys_start + size 276*471d65cfSLoGin // ); 27792849878SLoGin mem_block_manager() 27892849878SLoGin .mark_nomap(PhysAddr::new(phys_start), size) 27992849878SLoGin .unwrap(); 28092849878SLoGin } 28192849878SLoGin 28292849878SLoGin // keep ACPI reclaim memory intact for kexec etc. 28392849878SLoGin if md.ty == MemoryType::ACPI_RECLAIM { 28492849878SLoGin mem_block_manager() 28592849878SLoGin .reserve_block(PhysAddr::new(phys_start), size) 28692849878SLoGin .unwrap(); 28792849878SLoGin } 28892849878SLoGin } 28992849878SLoGin } 2907a29d4fcSLoGin } 291