17a29d4fcSLoGin //! 与UEFI相关的fdt操作 27a29d4fcSLoGin 37a29d4fcSLoGin use core::fmt::Debug; 47a29d4fcSLoGin 57a29d4fcSLoGin use fdt::Fdt; 6*2eab6dd7S曾俊 use log::error; 77a29d4fcSLoGin use system_error::SystemError; 87a29d4fcSLoGin 97a29d4fcSLoGin use crate::init::boot_params; 107a29d4fcSLoGin 117a29d4fcSLoGin use super::EFIManager; 127a29d4fcSLoGin 137a29d4fcSLoGin // 由于代码涉及转换,因此这里每个的大小都是8字节 147a29d4fcSLoGin #[derive(Default)] 157a29d4fcSLoGin pub struct EFIFdtParams { 167a29d4fcSLoGin // systable 177a29d4fcSLoGin pub systable: Option<u64>, 187a29d4fcSLoGin // mmap_base 197a29d4fcSLoGin pub mmap_base: Option<u64>, 207a29d4fcSLoGin // mmap_size 217a29d4fcSLoGin pub mmap_size: Option<u64>, 227a29d4fcSLoGin // mmap_desc_size 237a29d4fcSLoGin pub mmap_desc_size: Option<u64>, 247a29d4fcSLoGin // mmap_desc_version 257a29d4fcSLoGin pub mmap_desc_version: Option<u64>, 267a29d4fcSLoGin } 277a29d4fcSLoGin 287a29d4fcSLoGin impl Debug for EFIFdtParams { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result297a29d4fcSLoGin fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 307a29d4fcSLoGin // 十六进制输出 317a29d4fcSLoGin f.debug_struct("EFIFdtParams") 327a29d4fcSLoGin .field("systable", &format_args!("{:#x?}", self.systable)) 337a29d4fcSLoGin .field("mmap_base", &format_args!("{:#x?}", self.mmap_base)) 347a29d4fcSLoGin .field("mmap_size", &format_args!("{:#x?}", self.mmap_size)) 357a29d4fcSLoGin .field( 367a29d4fcSLoGin "mmap_desc_size", 377a29d4fcSLoGin &format_args!("{:#x?}", self.mmap_desc_size), 387a29d4fcSLoGin ) 397a29d4fcSLoGin .field( 407a29d4fcSLoGin "mmap_desc_version", 417a29d4fcSLoGin &format_args!("{:#x?}", self.mmap_desc_version), 427a29d4fcSLoGin ) 437a29d4fcSLoGin .finish() 447a29d4fcSLoGin } 457a29d4fcSLoGin } 467a29d4fcSLoGin 477a29d4fcSLoGin /// 要从FDT中获取的属性 487a29d4fcSLoGin #[derive(Debug, Clone, Copy)] 497a29d4fcSLoGin enum FdtPropType { 507a29d4fcSLoGin SystemTable, 517a29d4fcSLoGin MMBase, 527a29d4fcSLoGin MMSize, 537a29d4fcSLoGin DescSize, 547a29d4fcSLoGin DescVersion, 557a29d4fcSLoGin } 567a29d4fcSLoGin 577a29d4fcSLoGin impl FdtPropType { 587a29d4fcSLoGin /// 获取属性对应的fdt属性名 prop_name(&self) -> &'static str597a29d4fcSLoGin fn prop_name(&self) -> &'static str { 60b5b571e0SLoGin (*self).into() 617a29d4fcSLoGin } 627a29d4fcSLoGin } 637a29d4fcSLoGin 64b5b571e0SLoGin impl From<FdtPropType> for &'static str { from(value: FdtPropType) -> Self65b5b571e0SLoGin fn from(value: FdtPropType) -> Self { 66b5b571e0SLoGin match value { 677a29d4fcSLoGin FdtPropType::SystemTable => "linux,uefi-system-table", 687a29d4fcSLoGin FdtPropType::MMBase => "linux,uefi-mmap-start", 697a29d4fcSLoGin FdtPropType::MMSize => "linux,uefi-mmap-size", 707a29d4fcSLoGin FdtPropType::DescSize => "linux,uefi-mmap-desc-size", 717a29d4fcSLoGin FdtPropType::DescVersion => "linux,uefi-mmap-desc-ver", 727a29d4fcSLoGin } 737a29d4fcSLoGin } 747a29d4fcSLoGin } 757a29d4fcSLoGin 767a29d4fcSLoGin impl TryFrom<&str> for FdtPropType { 777a29d4fcSLoGin type Error = SystemError; 787a29d4fcSLoGin try_from(value: &str) -> Result<Self, Self::Error>797a29d4fcSLoGin fn try_from(value: &str) -> Result<Self, Self::Error> { 807a29d4fcSLoGin match value { 817a29d4fcSLoGin "linux,uefi-system-table" => Ok(FdtPropType::SystemTable), 827a29d4fcSLoGin "linux,uefi-mmap-start" => Ok(FdtPropType::MMBase), 837a29d4fcSLoGin "linux,uefi-mmap-size" => Ok(FdtPropType::MMSize), 847a29d4fcSLoGin "linux,uefi-mmap-desc-size" => Ok(FdtPropType::DescSize), 857a29d4fcSLoGin "linux,uefi-mmap-desc-ver" => Ok(FdtPropType::DescVersion), 867a29d4fcSLoGin _ => Err(SystemError::EINVAL), 877a29d4fcSLoGin } 887a29d4fcSLoGin } 897a29d4fcSLoGin } 907a29d4fcSLoGin 917a29d4fcSLoGin struct ParamToRead { 927a29d4fcSLoGin /// FDT节点路径 937a29d4fcSLoGin path: &'static str, 947a29d4fcSLoGin /// 当前节点下要读取的属性 957a29d4fcSLoGin properties: &'static [FdtPropType], 967a29d4fcSLoGin } 977a29d4fcSLoGin 987a29d4fcSLoGin static PARAM_TO_READ: &[ParamToRead] = &[ParamToRead { 997a29d4fcSLoGin path: "/chosen", 1007a29d4fcSLoGin properties: &[ 1017a29d4fcSLoGin FdtPropType::SystemTable, 1027a29d4fcSLoGin FdtPropType::MMBase, 1037a29d4fcSLoGin FdtPropType::MMSize, 1047a29d4fcSLoGin FdtPropType::DescSize, 1057a29d4fcSLoGin FdtPropType::DescVersion, 1067a29d4fcSLoGin ], 1077a29d4fcSLoGin }]; 1087a29d4fcSLoGin 1097a29d4fcSLoGin impl EFIManager { get_fdt_params(&self) -> Result<EFIFdtParams, SystemError>1107a29d4fcSLoGin pub(super) fn get_fdt_params(&self) -> Result<EFIFdtParams, SystemError> { 1117a29d4fcSLoGin let fdt = unsafe { 1127a29d4fcSLoGin Fdt::from_ptr( 1137a29d4fcSLoGin boot_params() 1147a29d4fcSLoGin .read() 1157a29d4fcSLoGin .fdt() 1167a29d4fcSLoGin .ok_or(SystemError::ENODEV)? 1177a29d4fcSLoGin .data() as *const u8, 1187a29d4fcSLoGin ) 1197a29d4fcSLoGin } 1207a29d4fcSLoGin .map_err(|e| { 121*2eab6dd7S曾俊 error!("failed to parse fdt, err={:?}", e); 1227a29d4fcSLoGin SystemError::EINVAL 1237a29d4fcSLoGin })?; 1247a29d4fcSLoGin 1257a29d4fcSLoGin let mut ret = EFIFdtParams::default(); 1267a29d4fcSLoGin 1277a29d4fcSLoGin for param in PARAM_TO_READ { 1287a29d4fcSLoGin let node = fdt.find_node(param.path); 1297a29d4fcSLoGin if node.is_none() { 1307a29d4fcSLoGin continue; 1317a29d4fcSLoGin } 1327a29d4fcSLoGin let node = node.unwrap(); 1337a29d4fcSLoGin 1347a29d4fcSLoGin for prop in param.properties { 1357a29d4fcSLoGin let prop = node.property(prop.prop_name()); 1367a29d4fcSLoGin if prop.is_none() { 1377a29d4fcSLoGin continue; 1387a29d4fcSLoGin } 1397a29d4fcSLoGin let prop = prop.unwrap(); 1407a29d4fcSLoGin let prop_type = FdtPropType::try_from(prop.name); 1417a29d4fcSLoGin if prop_type.is_err() { 1427a29d4fcSLoGin continue; 1437a29d4fcSLoGin } 1447a29d4fcSLoGin 1457a29d4fcSLoGin let prop_type = prop_type.unwrap(); 1467a29d4fcSLoGin 1477a29d4fcSLoGin self.do_get_fdt_prop(prop_type, &prop, &mut ret) 1487a29d4fcSLoGin .unwrap_or_else(|e| { 149*2eab6dd7S曾俊 error!("Failed to get fdt prop: {prop_type:?}, error: {e:?}"); 1507a29d4fcSLoGin }) 1517a29d4fcSLoGin } 1527a29d4fcSLoGin } 1537a29d4fcSLoGin 1547a29d4fcSLoGin return Ok(ret); 1557a29d4fcSLoGin } 1567a29d4fcSLoGin do_get_fdt_prop( &self, prop_type: FdtPropType, prop: &fdt::node::NodeProperty<'_>, target: &mut EFIFdtParams, ) -> Result<(), SystemError>1577a29d4fcSLoGin fn do_get_fdt_prop( 1587a29d4fcSLoGin &self, 1597a29d4fcSLoGin prop_type: FdtPropType, 1607a29d4fcSLoGin prop: &fdt::node::NodeProperty<'_>, 1617a29d4fcSLoGin target: &mut EFIFdtParams, 1627a29d4fcSLoGin ) -> Result<(), SystemError> { 163b5b571e0SLoGin let val = if prop.value.len() == 4 { 164b5b571e0SLoGin u32::from_be_bytes(prop.value[0..4].try_into().unwrap()) as u64 1657a29d4fcSLoGin } else { 166b5b571e0SLoGin u64::from_be_bytes(prop.value[0..8].try_into().unwrap()) 167b5b571e0SLoGin }; 1687a29d4fcSLoGin 1697a29d4fcSLoGin match prop_type { 1707a29d4fcSLoGin FdtPropType::SystemTable => { 1717a29d4fcSLoGin target.systable = Some(val); 1727a29d4fcSLoGin } 1737a29d4fcSLoGin FdtPropType::MMBase => { 1747a29d4fcSLoGin target.mmap_base = Some(val); 1757a29d4fcSLoGin } 1767a29d4fcSLoGin FdtPropType::MMSize => { 1777a29d4fcSLoGin target.mmap_size = Some(val); 1787a29d4fcSLoGin } 1797a29d4fcSLoGin FdtPropType::DescSize => { 1807a29d4fcSLoGin target.mmap_desc_size = Some(val); 1817a29d4fcSLoGin } 1827a29d4fcSLoGin FdtPropType::DescVersion => { 1837a29d4fcSLoGin target.mmap_desc_version = Some(val); 1847a29d4fcSLoGin } 1857a29d4fcSLoGin } 1867a29d4fcSLoGin 1877a29d4fcSLoGin return Ok(()); 1887a29d4fcSLoGin } 1897a29d4fcSLoGin } 190