sparreal_kernel/platform/
mod.rs1use 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 }
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
245impl 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}