xref: /DragonOS/kernel/src/driver/firmware/efi/memmap.rs (revision 338f6903262c5031abad3c8e361813355a27fcdb)
1 use core::{intrinsics::unlikely, mem::size_of};
2 
3 use system_error::SystemError;
4 
5 use crate::{
6     driver::firmware::efi::EFIInitFlags,
7     libs::align::page_align_down,
8     mm::{early_ioremap::EarlyIoRemap, PhysAddr, VirtAddr},
9 };
10 
11 use super::{fdt::EFIFdtParams, tables::MemoryDescriptor, EFIManager};
12 
13 #[derive(Debug)]
14 pub struct EFIMemoryMapInfo {
15     /// EFI Memory Map的物理地址
16     pub(super) paddr: Option<PhysAddr>,
17     /// EFI Memory Map的虚拟地址
18     pub(super) vaddr: Option<VirtAddr>,
19     /// EFI Memory Map的大小
20     pub(super) size: usize,
21     /// 映射的描述信息的数量
22     pub(super) nr_map: usize,
23     /// EFI Memory Map的描述信息的大小
24     pub(super) desc_size: usize,
25     /// EFI Memory Map的描述信息的版本
26     pub(super) desc_version: usize,
27     /// 当前是否在内存管理已经完成初始化后,对该结构体进行操作
28     ///
29     /// true: 内存管理已经完成初始化
30     /// false: 内存管理还未完成初始化
31     pub(super) late: bool,
32 }
33 
34 impl EFIMemoryMapInfo {
35     pub const DEFAULT: Self = EFIMemoryMapInfo {
36         paddr: None,
37         vaddr: None,
38         size: 0,
39         nr_map: 0,
40         desc_size: 0,
41         desc_version: 0,
42         late: false,
43     };
44 
45     /// 获取EFI Memory Map的虚拟的结束地址
46     #[allow(dead_code)]
47     pub fn map_end_vaddr(&self) -> Option<VirtAddr> {
48         return self.vaddr.map(|v| v + self.size);
49     }
50 
51     /// 迭代所有的内存描述符
52     pub fn iter(&self) -> EFIMemoryDescIter {
53         EFIMemoryDescIter::new(self)
54     }
55 }
56 
57 /// UEFI 内存描述符的迭代器
58 pub struct EFIMemoryDescIter<'a> {
59     inner: &'a EFIMemoryMapInfo,
60     offset: usize,
61 }
62 
63 impl<'a> EFIMemoryDescIter<'a> {
64     fn new(inner: &'a EFIMemoryMapInfo) -> Self {
65         Self { inner, offset: 0 }
66     }
67 }
68 
69 impl<'a> Iterator for EFIMemoryDescIter<'a> {
70     type Item = MemoryDescriptor;
71 
72     fn next(&mut self) -> Option<Self::Item> {
73         if self.offset + size_of::<Self::Item>() > self.inner.size {
74             return None;
75         }
76 
77         // 如果是空指针,返回None
78         if unlikely(self.inner.vaddr.unwrap_or(VirtAddr::new(0)).is_null()) {
79             return None;
80         }
81 
82         let vaddr = self.inner.vaddr? + self.offset;
83         self.offset += size_of::<Self::Item>();
84         let res = unsafe { *(vaddr.data() as *const Self::Item) };
85         return Some(res);
86     }
87 }
88 
89 impl EFIManager {
90     /// Map the EFI memory map data structure
91     ///
92     /// 进入当前函数前,不应持有efi_manager.inner的锁
93     #[inline(never)]
94     pub(super) fn memmap_init_early(&self, data: &EFIFdtParams) -> Result<(), SystemError> {
95         return self.do_efi_memmap_init(data, true);
96     }
97 
98     /// 映射 EFI memory map
99     ///
100     /// 该函数在内核启动过程中使用
101     ///
102     /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/firmware/efi/memmap.c?fi=efi_memmap_init_early#104
103     #[inline(never)]
104     fn do_efi_memmap_init(&self, data: &EFIFdtParams, early: bool) -> Result<(), SystemError> {
105         let paddr = data.mmap_base.expect("mmap_base is not set");
106         let paddr = PhysAddr::new(paddr as usize);
107 
108         let mut inner_guard = self.inner.write();
109         if early {
110             let offset = paddr.data() - page_align_down(paddr.data());
111             let map_size = data.mmap_size.unwrap() as usize + offset;
112 
113             // kdebug!("do_efi_memmap_init: map_size={map_size:#x}");
114 
115             // 映射内存
116             let mut vaddr = EarlyIoRemap::map(
117                 PhysAddr::new(page_align_down(paddr.data())),
118                 map_size,
119                 false,
120             )
121             .map(|(vaddr, _)| vaddr)?;
122 
123             vaddr += offset;
124 
125             inner_guard.mmap.vaddr = Some(vaddr);
126             inner_guard.mmap.late = false;
127         } else {
128             inner_guard.mmap.late = true;
129             unimplemented!("efi_memmap_init_late")
130         }
131 
132         if inner_guard.mmap.vaddr.is_none() {
133             kerror!("Cannot map the EFI memory map!");
134             return Err(SystemError::ENOMEM);
135         }
136 
137         inner_guard.mmap.paddr = Some(paddr);
138         inner_guard.mmap.size = data.mmap_size.unwrap() as usize;
139         inner_guard.mmap.nr_map =
140             data.mmap_size.unwrap() as usize / data.mmap_desc_size.unwrap() as usize;
141         inner_guard.mmap.desc_size = data.mmap_desc_size.unwrap() as usize;
142         inner_guard.mmap.desc_version = data.mmap_desc_version.unwrap() as usize;
143 
144         inner_guard.init_flags.set(EFIInitFlags::MEMMAP, true);
145 
146         return Ok(());
147     }
148 
149     /// 清除EFI Memory Table在内存中的映射
150     pub fn efi_memmap_unmap(&self) {
151         let mut inner_guard = self.inner.write_irqsave();
152 
153         // 没有启用memmap
154         if !inner_guard.init_flags.contains(EFIInitFlags::MEMMAP) {
155             return;
156         }
157 
158         if !inner_guard.mmap.late {
159             EarlyIoRemap::unmap(inner_guard.mmap.vaddr.take().unwrap()).unwrap();
160         } else {
161             unimplemented!("efi_memmap_unmap");
162         }
163         inner_guard.init_flags.set(EFIInitFlags::MEMMAP, false);
164     }
165 }
166