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