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;
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 }
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
246impl 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}