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, 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    // 收集需要移除的 reserved 区域的索引
81    let mut indices_to_remove: heapless::Vec<usize, 16> = heapless::Vec::new();
82
83    // 遍历现有的 reserved 区域,调整新区域的范围以排除重叠部分
84    for (i, r) in MEMORY_REGIONS.iter().enumerate() {
85        if !matches!(r.kind, MemoryRegionKind::Reserved) {
86            continue;
87        }
88
89        // 检查是否有重叠
90        if !(end <= r.start || start >= r.end) {
91            // 如果现有 reserved 区域完全包含了新区域,则无需添加
92            if r.start <= start && r.end >= end {
93                return;
94            }
95
96            // 如果现有 reserved 区域完全在新区域中间,标记移除
97            if r.start >= start && r.end <= end {
98                let _ = indices_to_remove.push(i);
99                continue;
100            }
101
102            // 如果现有 reserved 区域与新区域的开始部分重叠
103            if r.start <= start && r.end > start && r.end < end {
104                start = r.end;
105            }
106
107            // 如果现有 reserved 区域与新区域的结束部分重叠
108            if r.start > start && r.start < end && r.end >= end {
109                end = r.start;
110            }
111        }
112    }
113
114    // 从后往前移除标记的区域(避免索引变化问题)
115    for &i in indices_to_remove.iter().rev() {
116        MEMORY_REGIONS.as_mut().swap_remove(i);
117    }
118
119    // 检查调整后的区域是否仍然有效
120    if start >= end {
121        return;
122    }
123
124    // 添加新的 reserved 区域
125    let _ = MEMORY_REGIONS.as_mut().push(MemoryRegion {
126        kind: MemoryRegionKind::Reserved,
127        start,
128        end,
129    });
130}