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