1#![cfg_attr(target_os = "none", no_std)]
2#![cfg(target_os = "none")]
3
4#[cfg(target_arch = "aarch64")]
5#[path = "arch/aarch64/mod.rs"]
6mod arch;
7
8mod fdt;
9mod loader;
10mod staticcell;
11
12use heapless::Vec;
13pub use kdef_pgtable::{KIMAGE_VADDR, KLINER_OFFSET};
14use pie_boot_if::EarlyBootArgs;
15pub use pie_boot_if::{BootInfo, MemoryRegion, MemoryRegionKind, MemoryRegions};
16pub use pie_boot_macros::entry;
17#[allow(unused)]
18use pie_boot_macros::start_code;
19use staticcell::StaticCell;
20
21#[allow(unused)]
22static mut BOOT_ARGS: EarlyBootArgs = EarlyBootArgs::new();
23
24#[unsafe(link_section = ".data")]
25static BOOT_INFO: StaticCell<BootInfo> = StaticCell::new(BootInfo::new());
26#[unsafe(link_section = ".data")]
27static MEMORY_REGIONS: StaticCell<Vec<MemoryRegion, 128>> = StaticCell::new(Vec::new());
28
29unsafe extern "Rust" {
30 fn __pie_boot_main(args: &BootInfo);
31}
32
33fn virt_entry(args: &BootInfo) {
34 unsafe {
35 MEMORY_REGIONS.as_mut().clear();
36 let _ = MEMORY_REGIONS
37 .as_mut()
38 .extend_from_slice(&args.memory_regions);
39
40 *BOOT_INFO.as_mut() = args.clone();
41
42 if let Some(ptr) = BOOT_INFO.fdt {
43 fdt::setup(ptr);
44 }
45
46 mainmem_start_rsv(args);
47 let regions = core::slice::from_raw_parts_mut(
48 MEMORY_REGIONS.as_mut().as_mut_ptr(),
49 MEMORY_REGIONS.len(),
50 );
51 BOOT_INFO.as_mut().memory_regions = regions.into();
52
53 __pie_boot_main(&BOOT_INFO);
54 }
55}
56
57pub fn boot_info() -> &'static BootInfo {
58 &BOOT_INFO
59}
60
61fn mainmem_start_rsv(args: &BootInfo) {
62 let lma = args.kimage_start_lma as usize;
63
64 let mainmem = MEMORY_REGIONS.iter().find(|r| {
65 let is_ram = matches!(r.kind, MemoryRegionKind::Ram);
66 let in_range = r.start <= lma && r.end > lma;
67 is_ram && in_range
68 });
69
70 let Some(mainmem) = mainmem else {
71 return;
72 };
73
74 let mut start = mainmem.start;
75 unsafe extern "C" {
76 fn _idmap_text_end();
77 }
78 let mut end = _idmap_text_end as usize - args.kcode_offset();
79
80 let mut indices_to_remove: heapless::Vec<usize, 16> = heapless::Vec::new();
82
83 for (i, r) in MEMORY_REGIONS.iter().enumerate() {
85 if !matches!(r.kind, MemoryRegionKind::Reserved) {
86 continue;
87 }
88
89 if !(end <= r.start || start >= r.end) {
91 if r.start <= start && r.end >= end {
93 return;
94 }
95
96 if r.start >= start && r.end <= end {
98 let _ = indices_to_remove.push(i);
99 continue;
100 }
101
102 if r.start <= start && r.end > start && r.end < end {
104 start = r.end;
105 }
106
107 if r.start > start && r.start < end && r.end >= end {
109 end = r.start;
110 }
111 }
112 }
113
114 for &i in indices_to_remove.iter().rev() {
116 MEMORY_REGIONS.as_mut().swap_remove(i);
117 }
118
119 if start >= end {
121 return;
122 }
123
124 let _ = MEMORY_REGIONS.as_mut().push(MemoryRegion {
126 kind: MemoryRegionKind::Reserved,
127 start,
128 end,
129 });
130}