1b5b571e0SLoGin use core::{hint::spin_loop, intrinsics::unlikely, mem::size_of}; 27a29d4fcSLoGin 3*2eab6dd7S曾俊 use log::{error, info, warn}; 47a29d4fcSLoGin use system_error::SystemError; 592849878SLoGin use uefi_raw::table::boot::{MemoryAttribute, MemoryType}; 67a29d4fcSLoGin 77a29d4fcSLoGin use crate::{ 892849878SLoGin arch::MMArch, 9471d65cfSLoGin driver::{ 10471d65cfSLoGin firmware::efi::{esrt::efi_esrt_init, EFIInitFlags}, 11471d65cfSLoGin open_firmware::fdt::open_firmware_fdt_driver, 12471d65cfSLoGin }, 1392849878SLoGin libs::align::{page_align_down, page_align_up}, 1492849878SLoGin mm::{ 1592849878SLoGin allocator::page_frame::PhysPageFrame, early_ioremap::EarlyIoRemap, 1692849878SLoGin memblock::mem_block_manager, MemoryManagementArch, PhysAddr, VirtAddr, 1792849878SLoGin }, 187a29d4fcSLoGin }; 197a29d4fcSLoGin 207a29d4fcSLoGin use super::efi_manager; 217a29d4fcSLoGin 227a29d4fcSLoGin #[allow(dead_code)] 237a29d4fcSLoGin #[inline(never)] 247a29d4fcSLoGin pub fn efi_init() { 25*2eab6dd7S曾俊 info!("Initializing efi..."); 267a29d4fcSLoGin let data_from_fdt = efi_manager() 277a29d4fcSLoGin .get_fdt_params() 287a29d4fcSLoGin .expect("Failed to get fdt params"); 297a29d4fcSLoGin 307a29d4fcSLoGin if data_from_fdt.systable.is_none() { 31*2eab6dd7S曾俊 error!("Failed to get systable from fdt"); 327a29d4fcSLoGin return; 337a29d4fcSLoGin } 347a29d4fcSLoGin 35*2eab6dd7S曾俊 // debug!("to map memory table"); 367a29d4fcSLoGin 377a29d4fcSLoGin // 映射mmap table 387a29d4fcSLoGin if efi_manager().memmap_init_early(&data_from_fdt).is_err() { 397a29d4fcSLoGin // 如果我们通过UEFI进行引导, 407a29d4fcSLoGin // 那么 UEFI memory map 就是我们拥有的关于内存的唯一描述, 417a29d4fcSLoGin // 所以如果我们无法访问它,那么继续进行下去就没有什么意义了 427a29d4fcSLoGin 43*2eab6dd7S曾俊 error!("Failed to initialize early memory map"); 44b5b571e0SLoGin loop { 45b5b571e0SLoGin spin_loop(); 46b5b571e0SLoGin } 477a29d4fcSLoGin } 48*2eab6dd7S曾俊 // debug!("NNNN"); 49*2eab6dd7S曾俊 // warn!("BBBB, e:{:?}", SystemError::EINVAL); 507a29d4fcSLoGin 517a29d4fcSLoGin let desc_version = efi_manager().desc_version(); 527a29d4fcSLoGin 537a29d4fcSLoGin if unlikely(desc_version != 1) { 54*2eab6dd7S曾俊 warn!("Unexpected EFI memory map version: {}", desc_version); 557a29d4fcSLoGin } 567a29d4fcSLoGin 577a29d4fcSLoGin let r = uefi_init(PhysAddr::new(data_from_fdt.systable.unwrap() as usize)); 5892849878SLoGin if let Err(e) = r { 59*2eab6dd7S曾俊 error!("Failed to initialize UEFI: {:?}", e); 6092849878SLoGin efi_manager().efi_memmap_unmap(); 6192849878SLoGin return; 627a29d4fcSLoGin } 637a29d4fcSLoGin 6492849878SLoGin reserve_memory_regions(); 6592849878SLoGin // todo: 由于上面的`uefi_init`里面,按照UEFI的数据,初始化了内存块, 6692849878SLoGin // 但是UEFI给的数据可能不全,这里Linux会再次从设备树检测可用内存,从而填补完全相应的内存信息 6792849878SLoGin 6892849878SLoGin // 并且,Linux还对EFI BootService提供的Mokvar表进行了检测以及空间保留。 6992849878SLoGin 7092849878SLoGin // todo: 模仿Linux的行为,做好接下来的几步工作: 7192849878SLoGin // 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/efi-init.c#217 7292849878SLoGin 73471d65cfSLoGin // todo: early_init_dt_check_for_usable_mem_range 74471d65cfSLoGin 75471d65cfSLoGin efi_find_mirror(); 76471d65cfSLoGin efi_esrt_init(); 77471d65cfSLoGin 7892849878SLoGin // 保留mmap table的内存 7992849878SLoGin let base = page_align_down(data_from_fdt.mmap_base.unwrap() as usize); 8092849878SLoGin let offset = data_from_fdt.mmap_base.unwrap() as usize - base; 8192849878SLoGin 8292849878SLoGin mem_block_manager() 8392849878SLoGin .reserve_block( 8492849878SLoGin PhysAddr::new(base), 8592849878SLoGin data_from_fdt.mmap_size.unwrap() as usize + offset, 8692849878SLoGin ) 8792849878SLoGin .expect("Failed to reserve memory for EFI mmap table"); 8892849878SLoGin 89453452ccSLoGin // 保留内核的内存 90471d65cfSLoGin if let Some(info) = efi_manager().inner_read().dragonstub_load_info { 91453452ccSLoGin mem_block_manager() 92453452ccSLoGin .reserve_block( 93453452ccSLoGin PhysAddr::new(info.paddr as usize), 94453452ccSLoGin page_align_up(info.size as usize), 95453452ccSLoGin ) 96453452ccSLoGin .expect("Failed to reserve kernel itself memory"); 97453452ccSLoGin } 98453452ccSLoGin 9992849878SLoGin // todo: Initialize screen info 10092849878SLoGin 101*2eab6dd7S曾俊 info!("UEFI init done!"); 1027a29d4fcSLoGin } 1037a29d4fcSLoGin 104471d65cfSLoGin fn efi_find_mirror() { 105471d65cfSLoGin let efi_guard = efi_manager().inner_read(); 106471d65cfSLoGin let mut total_size = 0; 107471d65cfSLoGin let mut mirror_size = 0; 108471d65cfSLoGin for md in efi_guard.mmap.iter() { 109471d65cfSLoGin let start = PhysAddr::new(md.phys_start as usize); 110471d65cfSLoGin let size = (md.page_count << (MMArch::PAGE_SHIFT as u64)) as usize; 111471d65cfSLoGin 112471d65cfSLoGin if md.att.contains(MemoryAttribute::MORE_RELIABLE) { 113471d65cfSLoGin mem_block_manager().mark_mirror(start, size).unwrap(); 114471d65cfSLoGin mirror_size += size; 115471d65cfSLoGin } 116471d65cfSLoGin 117471d65cfSLoGin total_size += size; 118471d65cfSLoGin } 119471d65cfSLoGin 120471d65cfSLoGin if mirror_size > 0 { 121*2eab6dd7S曾俊 info!( 122471d65cfSLoGin "Memory: {}M/{}M mirrored memory", 123471d65cfSLoGin mirror_size >> 20, 124471d65cfSLoGin total_size >> 20 125471d65cfSLoGin ); 126471d65cfSLoGin } 127471d65cfSLoGin } 128471d65cfSLoGin 1297a29d4fcSLoGin #[inline(never)] 1307a29d4fcSLoGin fn uefi_init(system_table: PhysAddr) -> Result<(), SystemError> { 1317a29d4fcSLoGin // 定义错误处理函数 1327a29d4fcSLoGin 1337a29d4fcSLoGin // 错误处理:取消systable的映射 1347a29d4fcSLoGin let err_unmap_systable = |st_vaddr: VirtAddr| { 1357a29d4fcSLoGin EarlyIoRemap::unmap(st_vaddr) 1367a29d4fcSLoGin .map_err(|e| { 137*2eab6dd7S曾俊 error!("Failed to unmap system table: {e:?}"); 1387a29d4fcSLoGin }) 1397a29d4fcSLoGin .ok(); 1407a29d4fcSLoGin }; 1417a29d4fcSLoGin 1427a29d4fcSLoGin // 映射system table 1437a29d4fcSLoGin 1447a29d4fcSLoGin let st_size = size_of::<uefi_raw::table::system::SystemTable>(); 1457a29d4fcSLoGin 14692849878SLoGin let st_vaddr = EarlyIoRemap::map_not_aligned(system_table, st_size, true).map_err(|e| { 147*2eab6dd7S曾俊 warn!("Unable to map EFI system table, e:{e:?}"); 1487a29d4fcSLoGin e 1497a29d4fcSLoGin })?; 1507a29d4fcSLoGin 1517a29d4fcSLoGin efi_manager() 1527a29d4fcSLoGin .inner 1537a29d4fcSLoGin .write() 1547a29d4fcSLoGin .init_flags 1557a29d4fcSLoGin .set(EFIInitFlags::BOOT, true); 1567a29d4fcSLoGin 1577a29d4fcSLoGin efi_manager() 1587a29d4fcSLoGin .inner 1597a29d4fcSLoGin .write() 1607a29d4fcSLoGin .init_flags 1617a29d4fcSLoGin .set(EFIInitFlags::EFI_64BIT, true); 1627a29d4fcSLoGin 1637a29d4fcSLoGin if st_vaddr.is_null() { 1647a29d4fcSLoGin return Err(SystemError::EINVAL); 1657a29d4fcSLoGin } 1667a29d4fcSLoGin 1677a29d4fcSLoGin // 解析system table 1687a29d4fcSLoGin let st_ptr = st_vaddr.data() as *const uefi_raw::table::system::SystemTable; 1697a29d4fcSLoGin efi_manager() 1707a29d4fcSLoGin .check_system_table_header(unsafe { &st_ptr.as_ref().unwrap().header }, 2) 1717a29d4fcSLoGin .map_err(|e| { 1727a29d4fcSLoGin err_unmap_systable(st_vaddr); 1737a29d4fcSLoGin e 1747a29d4fcSLoGin })?; 1757a29d4fcSLoGin 1767a29d4fcSLoGin let st_ref = unsafe { st_ptr.as_ref().unwrap() }; 17792849878SLoGin 17892849878SLoGin let runtime_service_paddr = efi_vaddr_2_paddr(st_ref.runtime_services as usize); 179471d65cfSLoGin let mut inner_write_guard = efi_manager().inner_write(); 18092849878SLoGin inner_write_guard.runtime_paddr = Some(runtime_service_paddr); 1817a29d4fcSLoGin inner_write_guard.runtime_service_version = Some(st_ref.header.revision); 1827a29d4fcSLoGin 18392849878SLoGin drop(inner_write_guard); 18492849878SLoGin efi_manager().report_systable_header( 18592849878SLoGin &st_ref.header, 18692849878SLoGin efi_vaddr_2_paddr(st_ref.firmware_vendor as usize), 1877a29d4fcSLoGin ); 1887a29d4fcSLoGin 18992849878SLoGin { 19092849878SLoGin // 映射configuration table 19192849878SLoGin let table_size = st_ref.number_of_configuration_table_entries 19292849878SLoGin * size_of::<uefi_raw::table::configuration::ConfigurationTable>(); 19392849878SLoGin let config_table_vaddr = EarlyIoRemap::map_not_aligned( 19492849878SLoGin efi_vaddr_2_paddr(st_ref.configuration_table as usize), 19592849878SLoGin table_size, 19692849878SLoGin true, 19792849878SLoGin ) 19892849878SLoGin .map_err(|e| { 199*2eab6dd7S曾俊 warn!("Unable to map EFI configuration table, e:{e:?}"); 20092849878SLoGin err_unmap_systable(st_vaddr); 20192849878SLoGin e 20292849878SLoGin })?; 20392849878SLoGin let cfg_tables = unsafe { 20492849878SLoGin core::slice::from_raw_parts( 20592849878SLoGin config_table_vaddr.data() 20692849878SLoGin as *const uefi_raw::table::configuration::ConfigurationTable, 20792849878SLoGin st_ref.number_of_configuration_table_entries, 20892849878SLoGin ) 20992849878SLoGin }; 21092849878SLoGin // 解析configuration table 21192849878SLoGin let r = efi_manager().parse_config_tables(cfg_tables); 21292849878SLoGin 21392849878SLoGin EarlyIoRemap::unmap(config_table_vaddr).expect("Failed to unmap EFI config table"); 21492849878SLoGin return r; 21592849878SLoGin } 21692849878SLoGin } 21792849878SLoGin 21892849878SLoGin /// 把EFI固件提供的虚拟地址转换为物理地址。 21992849878SLoGin /// 22092849878SLoGin /// 因为在调用SetVirtualAddressMap()之后,`EFI SystemTable` 的一些数据成员会被虚拟重映射 22192849878SLoGin /// 22292849878SLoGin /// ## 锁 22392849878SLoGin /// 22492849878SLoGin /// 在进入该函数前,请不要持有`efi_manager().inner`的写锁 22592849878SLoGin fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr { 226471d65cfSLoGin let guard = efi_manager().inner_read(); 22792849878SLoGin let mmap = &guard.mmap; 22892849878SLoGin 22992849878SLoGin let efi_vaddr: u64 = efi_vaddr as u64; 23092849878SLoGin for md in mmap.iter() { 23192849878SLoGin if !md.att.contains(MemoryAttribute::RUNTIME) { 23292849878SLoGin continue; 23392849878SLoGin } 23492849878SLoGin 23592849878SLoGin if md.virt_start == 0 { 23692849878SLoGin // no virtual mapping has been installed by the DragonStub 23792849878SLoGin break; 23892849878SLoGin } 23992849878SLoGin 24092849878SLoGin if md.virt_start <= efi_vaddr 24192849878SLoGin && ((efi_vaddr - md.virt_start) < (md.page_count << (MMArch::PAGE_SHIFT as u64))) 24292849878SLoGin { 24392849878SLoGin return PhysAddr::new((md.phys_start + (efi_vaddr - md.virt_start)) as usize); 24492849878SLoGin } 24592849878SLoGin } 24692849878SLoGin 24792849878SLoGin return PhysAddr::new(efi_vaddr as usize); 24892849878SLoGin } 24992849878SLoGin 25092849878SLoGin /// 根据UEFI提供的内存描述符的信息,填写内存区域信息 25192849878SLoGin fn reserve_memory_regions() { 25292849878SLoGin // 忽略之前已经发现的任何内存块。因为之前发现的内存块来自平坦设备树, 25392849878SLoGin // 但是UEFI有自己的内存映射表,我们以UEFI提供的为准 25492849878SLoGin mem_block_manager() 25592849878SLoGin .remove_block(PhysAddr::new(0), PhysAddr::MAX.data()) 25692849878SLoGin .expect("Failed to remove all memblocks!"); 25792849878SLoGin 25892849878SLoGin let inner_guard = efi_manager().inner.read_irqsave(); 25992849878SLoGin for md in inner_guard.mmap.iter() { 26092849878SLoGin let page_count = (PhysPageFrame::new(PhysAddr::new(page_align_up( 261453452ccSLoGin (md.phys_start + (md.page_count << (MMArch::PAGE_SHIFT as u64))) as usize, 26292849878SLoGin ))) 26392849878SLoGin .ppn() 26492849878SLoGin - PhysPageFrame::new(PhysAddr::new(page_align_down(md.phys_start as usize))).ppn()) 26592849878SLoGin as u64; 26692849878SLoGin let phys_start = page_align_down(md.phys_start as usize); 26792849878SLoGin let size = (page_count << (MMArch::PAGE_SHIFT as u64)) as usize; 26892849878SLoGin 269*2eab6dd7S曾俊 // debug!("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); 27092849878SLoGin if md.is_memory() { 27192849878SLoGin open_firmware_fdt_driver().early_init_dt_add_memory(phys_start as u64, size as u64); 27292849878SLoGin if !md.is_usable_memory() { 273*2eab6dd7S曾俊 // debug!( 274471d65cfSLoGin // "Marking non-usable memory as nomap: {:#x}-{:#x}", 275471d65cfSLoGin // phys_start, 276471d65cfSLoGin // phys_start + size 277471d65cfSLoGin // ); 27892849878SLoGin mem_block_manager() 27992849878SLoGin .mark_nomap(PhysAddr::new(phys_start), size) 28092849878SLoGin .unwrap(); 28192849878SLoGin } 28292849878SLoGin 28392849878SLoGin // keep ACPI reclaim memory intact for kexec etc. 28492849878SLoGin if md.ty == MemoryType::ACPI_RECLAIM { 28592849878SLoGin mem_block_manager() 28692849878SLoGin .reserve_block(PhysAddr::new(phys_start), size) 28792849878SLoGin .unwrap(); 28892849878SLoGin } 28992849878SLoGin } 29092849878SLoGin } 2917a29d4fcSLoGin } 292