sparreal_kernel/platform/
mod.rs

1use alloc::{string::String, vec::Vec};
2use arrayvec::ArrayVec;
3use core::hint::spin_loop;
4use core::iter;
5use core::{ffi::CStr, fmt::Display, ops::Range};
6use log::error;
7use rdrive::driver;
8
9use fdt::Fdt;
10use rdrive::register::DriverRegister;
11
12use crate::globals::global_val;
13use crate::mem::PhysAddr;
14use crate::mem::mmu::BootRegion;
15use crate::{hal_al, platform};
16
17pub mod mmu {
18    pub use crate::hal_al::mmu::{AccessSetting, CacheSetting, PagingError, mmu::*};
19}
20
21pub use crate::hal_al::{CacheOp, hal::*};
22
23pub mod fdt;
24
25#[derive(Clone)]
26pub enum PlatformInfoKind {
27    DeviceTree(Fdt),
28}
29
30unsafe impl Send for PlatformInfoKind {}
31
32impl PlatformInfoKind {
33    pub fn new_fdt(addr: PhysAddr) -> Self {
34        PlatformInfoKind::DeviceTree(Fdt::new(addr))
35    }
36
37    pub fn memorys(&self) -> impl Iterator<Item = Range<PhysAddr>> {
38        let mut out: [Option<Range<PhysAddr>>; 24] =
39            unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
40        let mut len = 0;
41
42        match self {
43            PlatformInfoKind::DeviceTree(fdt) => {
44                for (i, m) in fdt
45                    .get()
46                    .memory()
47                    .flat_map(|m| m.regions())
48                    .map(|r| {
49                        let start = PhysAddr::from(r.address as usize);
50                        start..start + r.size
51                    })
52                    .enumerate()
53                {
54                    if i >= out.len() {
55                        break;
56                    }
57                    out[i] = Some(m);
58                    len += 1;
59                }
60            }
61        }
62
63        let mut iter = 0;
64        core::iter::from_fn(move || {
65            if iter >= len {
66                None
67            } else {
68                let m = out[iter].take().unwrap();
69                iter += 1;
70                Some(m)
71            }
72        })
73    }
74
75    pub fn debugcon(&self) -> Option<SerialPort> {
76        match self {
77            Self::DeviceTree(fdt) => fdt.debugcon(),
78        }
79    }
80}
81
82pub fn page_size() -> usize {
83    hal_al::mmu::mmu::page_size()
84}
85
86pub fn cpu_list() -> Vec<CPUInfo> {
87    match &global_val().platform_info {
88        PlatformInfoKind::DeviceTree(fdt) => fdt.cpus(),
89    }
90}
91
92pub fn cpu_hard_id() -> CPUHardId {
93    CPUHardId(platform::cpu_id())
94}
95
96pub fn platform_name() -> String {
97    match &global_val().platform_info {
98        PlatformInfoKind::DeviceTree(fdt) => fdt.model_name().unwrap_or_default(),
99    }
100}
101
102pub fn memory_main_available(
103    platform_info: &PlatformInfoKind,
104) -> Result<Range<PhysAddr>, &'static str> {
105    let text = boot_regions()
106        .into_iter()
107        .find(|o| o.name().eq(".text"))
108        .ok_or("can not find .text")?;
109    let text_end = text.range.end;
110
111    let main_memory = platform_info
112        .memorys()
113        .find(|m| m.contains(&text_end))
114        .ok_or("can not find main memory")?;
115
116    let mut start = PhysAddr::new(0);
117    for rsv in boot_regions() {
118        if main_memory.contains(&rsv.range.end) && rsv.range.end > start {
119            start = rsv.range.end;
120        }
121    }
122    start = start.align_up(0x1000);
123    Ok(start..main_memory.end)
124}
125
126pub fn boot_regions() -> impl Iterator<Item = BootRegion> {
127    let mut index: usize = 0;
128
129    iter::from_fn(move || {
130        let r = platform::boot_region_by_index(index);
131        if r.is_some() {
132            index += 1;
133        }
134        r
135    })
136}
137
138pub fn phys_memorys() -> ArrayVec<Range<PhysAddr>, 12> {
139    match &global_val().platform_info {
140        PlatformInfoKind::DeviceTree(fdt) => fdt.memorys(),
141    }
142}
143
144pub fn shutdown() -> ! {
145    if let Some(power) = rdrive::get_one::<driver::Power>() {
146        power.lock().unwrap().shutdown();
147        loop {
148            spin_loop();
149        }
150    } else {
151        error!("no power driver");
152        loop {
153            wait_for_interrupt();
154        }
155    }
156
157    // PlatformImpl::shutdown()
158}
159
160pub fn app_main() {
161    unsafe extern "C" {
162        fn __sparreal_rt_main();
163    }
164    unsafe { __sparreal_rt_main() }
165}
166
167#[derive(Debug)]
168pub struct CPUInfo {
169    pub cpu_id: CPUHardId,
170}
171
172#[derive(Debug, Clone, Copy)]
173pub struct SerialPort {
174    pub addr: PhysAddr,
175    pub size: Option<usize>,
176    compatible: [Option<[u8; 128]>; 4],
177}
178
179impl SerialPort {
180    pub fn new<'a>(
181        addr: PhysAddr,
182        size: Option<usize>,
183        compatibles: impl Iterator<Item = &'a str>,
184    ) -> Self {
185        let mut compatible_out = [None; 4];
186
187        for (i, c) in compatibles.enumerate() {
188            if i == compatible_out.len() {
189                break;
190            }
191            let bytes = c.as_bytes();
192            let mut bytes_out = [0u8; 128];
193            bytes_out[..bytes.len()].copy_from_slice(bytes);
194            compatible_out[i] = Some(bytes_out);
195        }
196
197        Self {
198            addr,
199            size,
200            compatible: compatible_out,
201        }
202    }
203
204    pub fn compatibles(&self) -> impl Iterator<Item = &str> {
205        let mut iter = 0;
206
207        core::iter::from_fn(move || {
208            if iter >= self.compatible.len() {
209                None
210            } else {
211                let bytes = self.compatible[iter].as_ref()?;
212                iter += 1;
213                CStr::from_bytes_until_nul(bytes).ok()?.to_str().ok()
214            }
215        })
216    }
217}
218
219pub fn module_registers() -> Vec<DriverRegister> {
220    platform::driver_registers().as_slice().to_vec()
221}
222
223#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
224#[repr(transparent)]
225pub struct CPUId(usize);
226impl Display for CPUId {
227    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
228        write!(f, "{:?}", self.0)
229    }
230}
231impl From<CPUId> for usize {
232    fn from(value: CPUId) -> Self {
233        value.0
234    }
235}
236impl From<usize> for CPUId {
237    fn from(value: usize) -> Self {
238        Self(value)
239    }
240}
241
242#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
243#[repr(transparent)]
244pub struct CPUHardId(usize);
245
246// impl CPUHardId {
247//     pub(crate) unsafe fn new(id: usize) -> Self {
248//         Self(id)
249//     }
250// }
251
252impl Display for CPUHardId {
253    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
254        write!(f, "{:#x}", self.0)
255    }
256}
257
258impl From<rdrive::driver::intc::CpuId> for CPUHardId {
259    fn from(value: rdrive::driver::intc::CpuId) -> Self {
260        Self(value.into())
261    }
262}
263
264impl From<CPUHardId> for rdrive::driver::intc::CpuId {
265    fn from(value: CPUHardId) -> Self {
266        Self::from(value.0)
267    }
268}