xref: /DragonOS/kernel/src/driver/firmware/efi/memmap.rs (revision a381e482cbe742b2e4bbeaacae134a8131bf3f91)
1 use system_error::SystemError;
2 
3 use crate::{
4     driver::firmware::efi::EFIInitFlags,
5     libs::align::page_align_down,
6     mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr},
7 };
8 
9 use super::{fdt::EFIFdtParams, EFIManager};
10 
11 #[derive(Debug)]
12 pub struct EFIMemoryMapInfo {
13     /// EFI Memory Map的物理地址
14     pub(super) paddr: Option<PhysAddr>,
15     /// EFI Memory Map的虚拟地址
16     pub(super) vaddr: Option<VirtAddr>,
17     /// EFI Memory Map的大小
18     pub(super) size: usize,
19     /// 映射的描述信息的数量
20     pub(super) nr_map: usize,
21     /// EFI Memory Map的描述信息的大小
22     pub(super) desc_size: usize,
23     /// EFI Memory Map的描述信息的版本
24     pub(super) desc_version: usize,
25 }
26 
27 impl EFIMemoryMapInfo {
28     pub const DEFAULT: Self = EFIMemoryMapInfo {
29         paddr: None,
30         vaddr: None,
31         size: 0,
32         nr_map: 0,
33         desc_size: 0,
34         desc_version: 0,
35     };
36 
37     /// 获取EFI Memory Map的虚拟的结束地址
38     #[allow(dead_code)]
39     pub fn map_end_vaddr(&self) -> Option<VirtAddr> {
40         return self.vaddr.map(|v| v + self.size);
41     }
42 }
43 
44 impl EFIManager {
45     /// Map the EFI memory map data structure
46     ///
47     /// 进入当前函数前,不应持有efi_manager.inner的锁
48     #[inline(never)]
49     pub(super) fn memmap_init_early(&self, data: &EFIFdtParams) -> Result<(), SystemError> {
50         return self.do_efi_memmap_init(data, true);
51     }
52 
53     /// 映射 EFI memory map
54     ///
55     /// 该函数在内核启动过程中使用
56     ///
57     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/memmap.c?fi=efi_memmap_init_early#104
58     #[inline(never)]
59     fn do_efi_memmap_init(&self, data: &EFIFdtParams, early: bool) -> Result<(), SystemError> {
60         let paddr = data.mmap_base.expect("mmap_base is not set");
61         let paddr = PhysAddr::new(paddr as usize);
62         kdebug!("do_efi_memmap_init: paddr={paddr:?}");
63         let mut inner_guard = self.inner.write();
64         if early {
65             let offset = paddr.data() - page_align_down(paddr.data());
66             let map_size = data.mmap_size.unwrap() as usize + offset;
67 
68             kdebug!("do_efi_memmap_init: map_size={map_size:#x}");
69             // 映射内存
70             let mut vaddr = EarlyIoRemap::map(
71                 PhysAddr::new(page_align_down(paddr.data())),
72                 map_size,
73                 false,
74             )
75             .map(|(vaddr, _)| vaddr)?;
76 
77             vaddr += offset;
78 
79             inner_guard.mmap.vaddr = Some(vaddr);
80         } else {
81             unimplemented!("efi_memmap_init_late")
82         }
83 
84         if inner_guard.mmap.vaddr.is_none() {
85             kerror!("Cannot map the EFI memory map!");
86             return Err(SystemError::ENOMEM);
87         }
88 
89         inner_guard.mmap.paddr = Some(paddr);
90         inner_guard.mmap.size = data.mmap_size.unwrap() as usize;
91         inner_guard.mmap.nr_map =
92             data.mmap_size.unwrap() as usize / data.mmap_desc_size.unwrap() as usize;
93         inner_guard.mmap.desc_size = data.mmap_desc_size.unwrap() as usize;
94         inner_guard.mmap.desc_version = data.mmap_desc_version.unwrap() as usize;
95 
96         inner_guard.init_flags.set(EFIInitFlags::MEMMAP, true);
97 
98         return Ok(());
99     }
100 }
101