xref: /DragonOS/kernel/src/driver/firmware/efi/tables.rs (revision 9284987850c1da2ce607a539eeae8a353a8f6df9)
1 use core::{ffi::CStr, mem::size_of};
2 
3 use hashbrown::Equivalent;
4 use system_error::SystemError;
5 use uefi_raw::table::{
6     boot::{MemoryAttribute, MemoryType},
7     configuration::ConfigurationTable,
8 };
9 
10 use crate::{
11     driver::firmware::efi::{
12         efi_manager,
13         guid::{DragonStubPayloadEFI, DRAGONSTUB_EFI_PAYLOAD_EFI_GUID},
14     },
15     mm::{early_ioremap::EarlyIoRemap, PhysAddr},
16 };
17 
18 use super::EFIManager;
19 
20 impl EFIManager {
21     /// 显示EFI系统表头的信息
22     ///
23     /// ## 参数
24     ///
25     /// - header: system table表头
26     /// - firmware_vendor: firmware vendor字符串的物理地址
27     #[inline(never)]
28     pub fn report_systable_header(
29         &self,
30         header: &uefi_raw::table::Header,
31         firmware_vendor: PhysAddr,
32     ) {
33         const TMPBUF_SIZE: usize = 100;
34 
35         let mut tmp_buf = [0u8; TMPBUF_SIZE];
36 
37         let fw_ptr =
38             EarlyIoRemap::map_not_aligned(firmware_vendor, TMPBUF_SIZE * size_of::<u16>(), true);
39         if let Ok(fw_ptr) = fw_ptr {
40             let slice =
41                 unsafe { core::slice::from_raw_parts(fw_ptr.data() as *const u16, TMPBUF_SIZE) };
42             for i in 0..(TMPBUF_SIZE - 1) {
43                 let val = slice[i];
44 
45                 if (val & 0xff) == 0 {
46                     break;
47                 }
48                 tmp_buf[i] = (val & 0xff) as u8;
49             }
50 
51             EarlyIoRemap::unmap(fw_ptr).map_err(|e|{
52                 kerror!("report systable header: failed to unmap systable header, fw_ptr: {fw_ptr:?}, err: {e:?}");
53                 e
54             }).ok();
55         } else {
56             kwarn!("report systable header: failed to map systable header, err: {fw_ptr:?}");
57         }
58 
59         let s = CStr::from_bytes_with_nul(&tmp_buf)
60             .unwrap_or_else(|_| CStr::from_bytes_with_nul(b"Unknown\0").unwrap());
61         kinfo!("EFI version: {:?}, vendor: {:?}", header.revision, s);
62     }
63 
64     /// 解析EFI config table
65     pub fn parse_config_tables(&self, tables: &[ConfigurationTable]) -> Result<(), SystemError> {
66         for table in tables {
67             if table
68                 .vendor_guid
69                 .equivalent(&DRAGONSTUB_EFI_PAYLOAD_EFI_GUID)
70             {
71                 let table_paddr: PhysAddr = PhysAddr::new(table.vendor_table as usize);
72                 let vaddr = EarlyIoRemap::map_not_aligned(
73                     table_paddr,
74                     size_of::<DragonStubPayloadEFI>(),
75                     true,
76                 )?;
77 
78                 let data = unsafe { *(vaddr.data() as *const DragonStubPayloadEFI) };
79 
80                 efi_manager().inner.write().dragonstub_load_info = Some(data);
81 
82                 EarlyIoRemap::unmap(vaddr).unwrap();
83             }
84         }
85 
86         return Ok(());
87     }
88 }
89 
90 /// A structure describing a region of memory.
91 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
92 #[repr(C)]
93 pub struct MemoryDescriptor {
94     /// Type of memory occupying this range.
95     pub ty: MemoryType,
96     /// Starting physical address.
97     pub phys_start: uefi_raw::PhysicalAddress,
98     /// Starting virtual address.
99     pub virt_start: uefi_raw::VirtualAddress,
100     /// Number of 4 KiB pages contained in this range.
101     pub page_count: u64,
102     /// The capability attributes of this memory range.
103     pub att: MemoryAttribute,
104 }
105 
106 #[allow(dead_code)]
107 impl MemoryDescriptor {
108     /// Memory descriptor version number.
109     pub const VERSION: u32 = 1;
110 
111     /// 当前内存描述符是否表示真实的内存
112     #[inline]
113     pub fn is_memory(&self) -> bool {
114         if self.att.contains(
115             MemoryAttribute::WRITE_BACK
116                 | MemoryAttribute::WRITE_THROUGH
117                 | MemoryAttribute::WRITE_COMBINE,
118         ) {
119             return true;
120         }
121 
122         return false;
123     }
124 
125     /// 判断当前内存描述符所表示的区域是否能被作为系统内存使用
126     ///
127     /// ## 返回
128     ///
129     /// - `true` - 可以
130     /// - `false` - 不可以
131     pub fn is_usable_memory(&self) -> bool {
132         match self.ty {
133             MemoryType::LOADER_CODE
134             | MemoryType::LOADER_DATA
135             | MemoryType::ACPI_RECLAIM
136             | MemoryType::BOOT_SERVICES_CODE
137             | MemoryType::BOOT_SERVICES_DATA
138             | MemoryType::CONVENTIONAL
139             | MemoryType::PERSISTENT_MEMORY => {
140                 // SPECIAL_PURPOSE的内存是“软保留”的,这意味着它最初被留出,
141                 // 但在启动后可以通过热插拔再次使用,或者分配给dax驱动程序。
142                 if self.att.contains(MemoryAttribute::SPECIAL_PURPOSE) {
143                     return false;
144                 }
145 
146                 // 根据规范,在调用ExitBootServices()之后,这些区域就不再被保留了。
147                 // 然而,只有当它们可以被映射为WRITE_BACK缓存时,我们才能将它们用作系统内存
148                 return self.att.contains(MemoryAttribute::WRITE_BACK);
149             }
150             _ => {
151                 return false;
152             }
153         }
154     }
155 }
156 
157 impl Default for MemoryDescriptor {
158     fn default() -> MemoryDescriptor {
159         MemoryDescriptor {
160             ty: MemoryType::RESERVED,
161             phys_start: 0,
162             virt_start: 0,
163             page_count: 0,
164             att: MemoryAttribute::empty(),
165         }
166     }
167 }
168