1b5b571e0SLoGin use core::{hint::spin_loop, intrinsics::unlikely, mem::size_of};
27a29d4fcSLoGin
32eab6dd7S曾俊 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)]
efi_init()247a29d4fcSLoGin pub fn efi_init() {
252eab6dd7S曾俊 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() {
312eab6dd7S曾俊 error!("Failed to get systable from fdt");
327a29d4fcSLoGin return;
337a29d4fcSLoGin }
347a29d4fcSLoGin
352eab6dd7S曾俊 // 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
432eab6dd7S曾俊 error!("Failed to initialize early memory map");
44b5b571e0SLoGin loop {
45b5b571e0SLoGin spin_loop();
46b5b571e0SLoGin }
477a29d4fcSLoGin }
482eab6dd7S曾俊 // debug!("NNNN");
492eab6dd7S曾俊 // warn!("BBBB, e:{:?}", SystemError::EINVAL);
507a29d4fcSLoGin
517a29d4fcSLoGin let desc_version = efi_manager().desc_version();
527a29d4fcSLoGin
537a29d4fcSLoGin if unlikely(desc_version != 1) {
542eab6dd7S曾俊 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 {
592eab6dd7S曾俊 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
1012eab6dd7S曾俊 info!("UEFI init done!");
1027a29d4fcSLoGin }
1037a29d4fcSLoGin
efi_find_mirror()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 {
1212eab6dd7S曾俊 info!(
122471d65cfSLoGin "Memory: {}M/{}M mirrored memory",
123471d65cfSLoGin mirror_size >> 20,
124471d65cfSLoGin total_size >> 20
125471d65cfSLoGin );
126471d65cfSLoGin }
127471d65cfSLoGin }
128471d65cfSLoGin
1297a29d4fcSLoGin #[inline(never)]
uefi_init(system_table: PhysAddr) -> Result<(), SystemError>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| {
1372eab6dd7S曾俊 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| {
1472eab6dd7S曾俊 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)
171*bd70d2d1SLoGin .inspect_err(|_| {
1727a29d4fcSLoGin err_unmap_systable(st_vaddr);
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);
178471d65cfSLoGin 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| {
1982eab6dd7S曾俊 warn!("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`的写锁
efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr22492849878SLoGin fn efi_vaddr_2_paddr(efi_vaddr: usize) -> PhysAddr {
225471d65cfSLoGin 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提供的内存描述符的信息,填写内存区域信息
reserve_memory_regions()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
2682eab6dd7S曾俊 // 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);
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() {
2722eab6dd7S曾俊 // debug!(
273471d65cfSLoGin // "Marking non-usable memory as nomap: {:#x}-{:#x}",
274471d65cfSLoGin // phys_start,
275471d65cfSLoGin // phys_start + size
276471d65cfSLoGin // );
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