xref: /DragonOS/kernel/src/driver/firmware/efi/fdt.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
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