1#![no_std]
8
9use core::arch::global_asm;
10use core::slice;
11
12use sel4_panicking_env::abort;
13use sel4_phdrs::{PT_SEL4_RESET_REGIONS, locate_phdrs};
14use sel4_stack::{Stack, StackBottom};
15
16use sel4_phdrs_patched as _;
17
18#[cfg(not(any(
19 target_arch = "aarch64",
20 target_arch = "arm",
21 target_arch = "riscv64",
22 target_arch = "riscv32",
23 target_arch = "x86_64",
24)))]
25compile_error!("unsupported architecture");
26
27#[repr(C)]
30#[derive(Debug)]
31struct RegionMeta {
32 dst_vaddr: usize,
33 dst_size: usize,
34 src_vaddr: usize,
35 src_size: usize,
36}
37
38unsafe fn reset_memory(regions: &'static [RegionMeta]) {
39 for meta in regions {
40 let dst = unsafe { slice::from_raw_parts_mut(meta.dst_vaddr as *mut u8, meta.dst_size) };
41 let (dst_data, dst_zero) = dst.split_at_mut(meta.src_size);
42 if meta.src_vaddr != 0 {
43 let src =
44 unsafe { slice::from_raw_parts_mut(meta.src_vaddr as *mut u8, meta.src_size) };
45 dst_data.copy_from_slice(src);
46 }
47 dst_zero.fill(0);
48 }
49}
50
51unsafe fn get_regions() -> &'static [RegionMeta] {
52 unsafe {
53 let phdr = locate_phdrs()
54 .unwrap_or_else(|err| abort!("{err}"))
55 .find_by_type(PT_SEL4_RESET_REGIONS)
56 .unwrap_or_else(|| abort!("missing PT_SEL4_RESET_REGIONS program header"));
57 slice::from_raw_parts(
58 phdr.p_vaddr as *const _,
59 phdr.p_memsz / size_of::<RegionMeta>(),
60 )
61 }
62}
63
64unsafe extern "C" {
67 fn _reset(x0: usize, x1: usize, x2: usize, x3: usize) -> !;
68 fn _start(x0: usize, x1: usize, x2: usize, x3: usize) -> !;
69}
70
71pub fn reset() -> ! {
72 unsafe {
73 _reset(0, 0, 0, 0);
74 }
75}
76
77pub fn reset1(x0: usize) -> ! {
78 unsafe {
79 _reset(x0, 0, 0, 0);
80 }
81}
82
83pub fn reset2(x0: usize, x1: usize) -> ! {
84 unsafe {
85 _reset(x0, x1, 0, 0);
86 }
87}
88
89pub fn reset3(x0: usize, x1: usize, x2: usize) -> ! {
90 unsafe {
91 _reset(x0, x1, x2, 0);
92 }
93}
94
95pub fn reset4(x0: usize, x1: usize, x2: usize, x3: usize) -> ! {
96 unsafe {
97 _reset(x0, x1, x2, x3);
98 }
99}
100
101#[unsafe(no_mangle)]
102unsafe extern "C" fn __sel4_reset__rust_entrypoint(
103 x0: usize,
104 x1: usize,
105 x2: usize,
106 x3: usize,
107) -> ! {
108 unsafe {
109 reset_memory(get_regions());
110 _start(x0, x1, x2, x3)
111 }
112}
113
114const STACK_SIZE: usize = 4096;
115
116#[unsafe(link_section = ".persistent")]
117static STACK: Stack<STACK_SIZE> = Stack::new();
118
119#[unsafe(no_mangle)]
120static __sel4_reset__stack_bottom: StackBottom = STACK.bottom();
121
122global_asm! {
123 r#"
124 .extern __sel4_reset__stack_bottom
125 .extern __sel4_reset__rust_entrypoint
126
127 .global _reset
128
129 .section .text.reset, "axR", %progbits
130 _reset:
131 "#,
132 #[cfg(target_arch = "aarch64")]
133 r#"
134 ldr x9, =__sel4_reset__stack_bottom
135 ldr x9, [x9]
136 mov sp, x9
137 b __sel4_reset__rust_entrypoint
138 "#,
139 #[cfg(target_arch = "arm")]
140 r#"
141 ldr r8, =__sel4_reset__stack_bottom
142 ldr r8, [r8]
143 mov sp, r8
144 b __sel4_reset__rust_entrypoint
145 "#,
146 #[cfg(target_arch = "riscv64")]
147 r#"
148 la sp, __sel4_reset__stack_bottom
149 ld sp, (sp)
150 j __sel4_reset__rust_entrypoint
151 "#,
152 #[cfg(target_arch = "riscv32")]
153 r#"
154 la sp, __sel4_reset__stack_bottom
155 lw sp, (sp)
156 j __sel4_reset__rust_entrypoint
157 "#,
158 #[cfg(target_arch = "x86_64")]
159 r#"
160 mov rsp, __sel4_reset__stack_bottom
161 mov rbp, rsp
162 sub rsp, 0x8 // Stack must be 16-byte aligned before call
163 push rbp
164 jmp __sel4_reset__rust_entrypoint
165 "#,
166}