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