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