tables.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. use core::{ffi::CStr, mem::size_of};
  2. use hashbrown::Equivalent;
  3. use system_error::SystemError;
  4. use uefi_raw::table::{
  5. boot::{MemoryAttribute, MemoryType},
  6. configuration::ConfigurationTable,
  7. };
  8. use crate::{
  9. arch::MMArch,
  10. driver::firmware::efi::{
  11. efi_manager,
  12. guid::{DragonStubPayloadEFI, DRAGONSTUB_EFI_PAYLOAD_EFI_GUID},
  13. },
  14. mm::{
  15. early_ioremap::EarlyIoRemap, memblock::mem_block_manager, MemoryManagementArch, PhysAddr,
  16. VirtAddr,
  17. },
  18. };
  19. use super::{
  20. guid::{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, EFI_MEMRESERVE_TABLE_GUID},
  21. EFIManager,
  22. };
  23. /// 所有的要解析的表格的解析器
  24. static TABLE_PARSERS: &[&TableMatcher] = &[
  25. &TableMatcher::new(&MatchTableDragonStubPayloadEFI),
  26. &TableMatcher::new(&MatchTableMemoryAttributes),
  27. &TableMatcher::new(&MatchTableMemReserve),
  28. ];
  29. impl EFIManager {
  30. /// 显示EFI系统表头的信息
  31. ///
  32. /// ## 参数
  33. ///
  34. /// - header: system table表头
  35. /// - firmware_vendor: firmware vendor字符串的物理地址
  36. #[inline(never)]
  37. pub fn report_systable_header(
  38. &self,
  39. header: &uefi_raw::table::Header,
  40. firmware_vendor: PhysAddr,
  41. ) {
  42. const TMPBUF_SIZE: usize = 100;
  43. let mut tmp_buf = [0u8; TMPBUF_SIZE];
  44. let fw_ptr =
  45. EarlyIoRemap::map_not_aligned(firmware_vendor, TMPBUF_SIZE * size_of::<u16>(), true);
  46. if let Ok(fw_ptr) = fw_ptr {
  47. let slice =
  48. unsafe { core::slice::from_raw_parts(fw_ptr.data() as *const u16, TMPBUF_SIZE) };
  49. for i in 0..(TMPBUF_SIZE - 1) {
  50. let val = slice[i];
  51. if (val & 0xff) == 0 {
  52. break;
  53. }
  54. tmp_buf[i] = (val & 0xff) as u8;
  55. }
  56. EarlyIoRemap::unmap(fw_ptr).map_err(|e|{
  57. kerror!("report systable header: failed to unmap systable header, fw_ptr: {fw_ptr:?}, err: {e:?}");
  58. e
  59. }).ok();
  60. } else {
  61. kwarn!("report systable header: failed to map systable header, err: {fw_ptr:?}");
  62. }
  63. let s = CStr::from_bytes_with_nul(&tmp_buf)
  64. .unwrap_or_else(|_| CStr::from_bytes_with_nul(b"Unknown\0").unwrap());
  65. kinfo!("EFI version: {:?}, vendor: {:?}", header.revision, s);
  66. }
  67. /// 解析EFI config table
  68. pub fn parse_config_tables(&self, tables: &[ConfigurationTable]) -> Result<(), SystemError> {
  69. for table in tables {
  70. let mut flag = false;
  71. 'parser_loop: for parser in TABLE_PARSERS {
  72. if let Some(r) = parser.match_table(table) {
  73. // 有匹配结果
  74. if let Err(e) = r {
  75. kwarn!(
  76. "Failed to parse cfg table: '{}', err: {e:?}",
  77. parser.table.name()
  78. );
  79. }
  80. flag = true;
  81. break 'parser_loop;
  82. }
  83. }
  84. if !flag {
  85. kwarn!("Cannot find parser for guid: {:?}", table.vendor_guid);
  86. }
  87. }
  88. // 如果存在mem reserve table
  89. if let Some(mem_reserve) = efi_manager().inner.read().memreserve_table_paddr {
  90. let mut prev_paddr = mem_reserve;
  91. while !prev_paddr.is_null() {
  92. let vaddr = EarlyIoRemap::map_not_aligned(prev_paddr, MMArch::PAGE_SIZE, true)
  93. .map_err(|e| {
  94. kerror!(
  95. "Failed to map UEFI memreserve table, paddr: {prev_paddr:?}, err: {e:?}"
  96. );
  97. SystemError::ENOMEM
  98. })?;
  99. let p = unsafe {
  100. (vaddr.data() as *const LinuxEFIMemReserveTable)
  101. .as_ref()
  102. .unwrap()
  103. };
  104. // reserve the entry itself
  105. let psize: usize = p.size.try_into().unwrap();
  106. mem_block_manager()
  107. .reserve_block(
  108. prev_paddr,
  109. size_of::<LinuxEFIMemReserveTable>()
  110. + size_of::<LinuxEFIMemReserveEntry>() * psize,
  111. )
  112. .map_err(|e| {
  113. kerror!("Failed to reserve block, paddr: {prev_paddr:?}, err: {e:?}");
  114. EarlyIoRemap::unmap(vaddr).unwrap();
  115. e
  116. })?;
  117. let entries = unsafe {
  118. core::slice::from_raw_parts(
  119. (vaddr.data() as *const LinuxEFIMemReserveTable).add(1)
  120. as *const LinuxEFIMemReserveEntry,
  121. p.count as usize,
  122. )
  123. };
  124. // reserve the entries
  125. for entry in entries {
  126. mem_block_manager()
  127. .reserve_block(PhysAddr::new(entry.base), entry.size)
  128. .map_err(|e| {
  129. kerror!("Failed to reserve block, paddr: {prev_paddr:?}, err: {e:?}");
  130. EarlyIoRemap::unmap(vaddr).unwrap();
  131. e
  132. })?;
  133. }
  134. prev_paddr = p.next_paddr;
  135. EarlyIoRemap::unmap(vaddr).unwrap();
  136. }
  137. }
  138. return Ok(());
  139. }
  140. }
  141. /// A structure describing a region of memory.
  142. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  143. #[repr(C)]
  144. pub struct MemoryDescriptor {
  145. /// Type of memory occupying this range.
  146. pub ty: MemoryType,
  147. /// Starting physical address.
  148. pub phys_start: uefi_raw::PhysicalAddress,
  149. /// Starting virtual address.
  150. pub virt_start: uefi_raw::VirtualAddress,
  151. /// Number of 4 KiB pages contained in this range.
  152. pub page_count: u64,
  153. /// The capability attributes of this memory range.
  154. pub att: MemoryAttribute,
  155. }
  156. #[allow(dead_code)]
  157. impl MemoryDescriptor {
  158. /// Memory descriptor version number.
  159. pub const VERSION: u32 = 1;
  160. /// 当前内存描述符是否表示真实的内存
  161. #[inline]
  162. pub fn is_memory(&self) -> bool {
  163. if self.att.contains(MemoryAttribute::WRITE_BACK)
  164. || self.att.contains(MemoryAttribute::WRITE_THROUGH)
  165. || self.att.contains(MemoryAttribute::WRITE_COMBINE)
  166. {
  167. return true;
  168. }
  169. return false;
  170. }
  171. /// 判断当前内存描述符所表示的区域是否能被作为系统内存使用
  172. ///
  173. /// ## 返回
  174. ///
  175. /// - `true` - 可以
  176. /// - `false` - 不可以
  177. pub fn is_usable_memory(&self) -> bool {
  178. match self.ty {
  179. MemoryType::LOADER_CODE
  180. | MemoryType::LOADER_DATA
  181. | MemoryType::ACPI_RECLAIM
  182. | MemoryType::BOOT_SERVICES_CODE
  183. | MemoryType::BOOT_SERVICES_DATA
  184. | MemoryType::CONVENTIONAL
  185. | MemoryType::PERSISTENT_MEMORY => {
  186. // SPECIAL_PURPOSE的内存是“软保留”的,这意味着它最初被留出,
  187. // 但在启动后可以通过热插拔再次使用,或者分配给dax驱动程序。
  188. if self.att.contains(MemoryAttribute::SPECIAL_PURPOSE) {
  189. return false;
  190. }
  191. // 根据规范,在调用ExitBootServices()之后,这些区域就不再被保留了。
  192. // 然而,只有当它们可以被映射为WRITE_BACK缓存时,我们才能将它们用作系统内存
  193. return self.att.contains(MemoryAttribute::WRITE_BACK);
  194. }
  195. _ => {
  196. return false;
  197. }
  198. }
  199. }
  200. }
  201. impl Default for MemoryDescriptor {
  202. fn default() -> MemoryDescriptor {
  203. MemoryDescriptor {
  204. ty: MemoryType::RESERVED,
  205. phys_start: 0,
  206. virt_start: 0,
  207. page_count: 0,
  208. att: MemoryAttribute::empty(),
  209. }
  210. }
  211. }
  212. trait MatchTable: Send + Sync {
  213. /// 配置表名(仅用于日志显示)
  214. fn name(&self) -> &'static str;
  215. /// 当前table的guid
  216. fn guid(&self) -> &'static uefi_raw::Guid;
  217. /// 匹配阶段时,匹配器要映射vendor_table的大小。
  218. ///
  219. /// 如果为0,则不映射
  220. fn map_size(&self) -> usize;
  221. /// 当表格被映射后,调用这个函数
  222. ///
  223. /// ## 锁
  224. ///
  225. /// 进入该函数前,不得持有efi_manager().inner的任何锁
  226. fn post_process(
  227. &self,
  228. vendor_table_vaddr: Option<VirtAddr>,
  229. table_raw: &ConfigurationTable,
  230. ) -> Result<(), SystemError>;
  231. }
  232. /// `DRAGONSTUB_EFI_PAYLOAD_EFI_GUID` 的匹配器
  233. struct MatchTableDragonStubPayloadEFI;
  234. impl MatchTable for MatchTableDragonStubPayloadEFI {
  235. fn name(&self) -> &'static str {
  236. "DragonStub Payload"
  237. }
  238. fn guid(&self) -> &'static uefi_raw::Guid {
  239. &DRAGONSTUB_EFI_PAYLOAD_EFI_GUID
  240. }
  241. fn map_size(&self) -> usize {
  242. core::mem::size_of::<DragonStubPayloadEFI>()
  243. }
  244. fn post_process(
  245. &self,
  246. vendor_table_vaddr: Option<VirtAddr>,
  247. _table_raw: &ConfigurationTable,
  248. ) -> Result<(), SystemError> {
  249. let vendor_table_vaddr = vendor_table_vaddr.unwrap();
  250. let data = unsafe { *(vendor_table_vaddr.data() as *const DragonStubPayloadEFI) };
  251. efi_manager().inner.write().dragonstub_load_info = Some(data);
  252. return Ok(());
  253. }
  254. }
  255. struct MatchTableMemoryAttributes;
  256. impl MatchTable for MatchTableMemoryAttributes {
  257. fn name(&self) -> &'static str {
  258. "MemAttr"
  259. }
  260. fn guid(&self) -> &'static uefi_raw::Guid {
  261. &EFI_MEMORY_ATTRIBUTES_TABLE_GUID
  262. }
  263. fn map_size(&self) -> usize {
  264. // 不映射
  265. 0
  266. }
  267. fn post_process(
  268. &self,
  269. _vendor_table_vaddr: Option<VirtAddr>,
  270. table_raw: &ConfigurationTable,
  271. ) -> Result<(), SystemError> {
  272. efi_manager()
  273. .inner
  274. .write_irqsave()
  275. .memory_attribute_table_paddr = Some(PhysAddr::new(table_raw.vendor_table as usize));
  276. return Ok(());
  277. }
  278. }
  279. struct MatchTableMemReserve;
  280. impl MatchTable for MatchTableMemReserve {
  281. fn name(&self) -> &'static str {
  282. "MemReserve"
  283. }
  284. fn guid(&self) -> &'static uefi_raw::Guid {
  285. &EFI_MEMRESERVE_TABLE_GUID
  286. }
  287. fn map_size(&self) -> usize {
  288. // 不映射
  289. 0
  290. }
  291. fn post_process(
  292. &self,
  293. _vendor_table_vaddr: Option<VirtAddr>,
  294. table_raw: &ConfigurationTable,
  295. ) -> Result<(), SystemError> {
  296. efi_manager().inner.write_irqsave().memreserve_table_paddr =
  297. Some(PhysAddr::new(table_raw.vendor_table as usize));
  298. kdebug!(
  299. "memreserve_table_paddr: {:#x}",
  300. table_raw.vendor_table as usize
  301. );
  302. return Ok(());
  303. }
  304. }
  305. /// 用于匹配配置表的匹配器
  306. struct TableMatcher {
  307. table: &'static dyn MatchTable,
  308. }
  309. impl TableMatcher {
  310. const fn new(table: &'static dyn MatchTable) -> Self {
  311. Self { table }
  312. }
  313. /// 判断配置表与当前匹配器是否匹配
  314. #[inline(never)]
  315. fn match_table(&self, table: &ConfigurationTable) -> Option<Result<(), SystemError>> {
  316. if !table.vendor_guid.equivalent(self.table.guid()) {
  317. return None;
  318. }
  319. let table_map_size = self.table.map_size();
  320. let vendor_table_vaddr: Option<VirtAddr> = if table_map_size > 0 {
  321. let table_paddr: PhysAddr = PhysAddr::new(table.vendor_table as usize);
  322. let vaddr = EarlyIoRemap::map_not_aligned(table_paddr, table_map_size, true);
  323. if let Err(e) = vaddr {
  324. return Some(Err(e));
  325. }
  326. Some(vaddr.unwrap())
  327. } else {
  328. None
  329. };
  330. let r = self.table.post_process(vendor_table_vaddr, table);
  331. if let Some(vaddr) = vendor_table_vaddr {
  332. EarlyIoRemap::unmap(vaddr).unwrap();
  333. }
  334. return Some(r);
  335. }
  336. }
  337. #[repr(C)]
  338. #[derive(Debug)]
  339. struct LinuxEFIMemReserveTable {
  340. /// allocated size of the array
  341. size: i32,
  342. /// number of entries used
  343. count: i32,
  344. /// pa of next struct instance
  345. next_paddr: PhysAddr,
  346. entry: [LinuxEFIMemReserveEntry; 0],
  347. }
  348. #[repr(C)]
  349. #[derive(Debug)]
  350. struct LinuxEFIMemReserveEntry {
  351. base: usize,
  352. size: usize,
  353. }