pie_boot/
lib.rs

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, KIMAGE_VSIZE, KLINER_OFFSET};
14use pie_boot_if::EarlyBootArgs;
15pub use pie_boot_if::{BootInfo, MemoryRegion, MemoryRegionKind, MemoryRegions};
16#[allow(unused)]
17use pie_boot_macros::start_code;
18pub use pie_boot_macros::{entry, secondary_entry};
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#[unsafe(link_section = ".data")]
29static mut BOOT_PT: usize = 0;
30
31unsafe extern "Rust" {
32    fn __pie_boot_main(args: &BootInfo);
33}
34
35fn virt_entry(args: &BootInfo) {
36    unsafe {
37        MEMORY_REGIONS.as_mut().clear();
38        let _ = MEMORY_REGIONS
39            .as_mut()
40            .extend_from_slice(&args.memory_regions);
41
42        *BOOT_INFO.as_mut() = args.clone();
43
44        if let Some(ptr) = BOOT_INFO.fdt {
45            fdt::setup(ptr);
46        }
47
48        mainmem_start_rsv(args);
49        let regions = core::slice::from_raw_parts_mut(
50            MEMORY_REGIONS.as_mut().as_mut_ptr(),
51            MEMORY_REGIONS.len(),
52        );
53        BOOT_INFO.as_mut().memory_regions = regions.into();
54        BOOT_PT = BOOT_INFO.pg_start as usize;
55
56        __pie_boot_main(&BOOT_INFO);
57    }
58}
59
60pub fn boot_info() -> &'static BootInfo {
61    &BOOT_INFO
62}
63
64/// secondary entry address
65/// arg0 is stack top
66pub fn secondary_entry_addr() -> usize {
67    let ptr = arch::_start_secondary as usize;
68    ptr - boot_info().kcode_offset()
69}
70
71fn mainmem_start_rsv(args: &BootInfo) {
72    let lma = args.kimage_start_lma as usize;
73
74    let mainmem = MEMORY_REGIONS.iter().find(|r| {
75        let is_ram = matches!(r.kind, MemoryRegionKind::Ram);
76        let in_range = r.start <= lma && r.end > lma;
77        is_ram && in_range
78    });
79
80    let Some(mainmem) = mainmem else {
81        return;
82    };
83
84    let mut start = mainmem.start;
85    unsafe extern "C" {
86        fn _text();
87    }
88    let mut end = _text as usize - args.kcode_offset();
89
90    // 收集需要移除的 reserved 区域的索引
91    let mut indices_to_remove: heapless::Vec<usize, 16> = heapless::Vec::new();
92
93    // 遍历现有的 reserved 区域,调整新区域的范围以排除重叠部分
94    for (i, r) in MEMORY_REGIONS.iter().enumerate() {
95        if !matches!(r.kind, MemoryRegionKind::Reserved) {
96            continue;
97        }
98
99        // 检查是否有重叠
100        if !(end <= r.start || start >= r.end) {
101            // 如果现有 reserved 区域完全包含了新区域,则无需添加
102            if r.start <= start && r.end >= end {
103                return;
104            }
105
106            // 如果现有 reserved 区域完全在新区域中间,标记移除
107            if r.start >= start && r.end <= end {
108                let _ = indices_to_remove.push(i);
109                continue;
110            }
111
112            // 如果现有 reserved 区域与新区域的开始部分重叠
113            if r.start <= start && r.end > start && r.end < end {
114                start = r.end;
115            }
116
117            // 如果现有 reserved 区域与新区域的结束部分重叠
118            if r.start > start && r.start < end && r.end >= end {
119                end = r.start;
120            }
121        }
122    }
123
124    // 从后往前移除标记的区域(避免索引变化问题)
125    for &i in indices_to_remove.iter().rev() {
126        MEMORY_REGIONS.as_mut().swap_remove(i);
127    }
128
129    // 检查调整后的区域是否仍然有效
130    if start >= end {
131        return;
132    }
133
134    // 添加新的 reserved 区域
135    let _ = MEMORY_REGIONS.as_mut().push(MemoryRegion {
136        kind: MemoryRegionKind::Reserved,
137        start,
138        end,
139    });
140}
141
142#[unsafe(no_mangle)]
143unsafe extern "C" fn __pie_boot_default_secondary(_cpu_id: usize) {}