xref: /DragonOS/kernel/src/driver/firmware/efi/init.rs (revision 453452cc02e2766a28d87dd47bdee37caddc4c44)
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