1#![no_std]
8
9use core::arch::global_asm;
10use core::ptr;
11use core::slice;
12
13use cfg_if::cfg_if;
14
15use sel4_stack::{Stack, StackBottom};
16
17#[repr(C)]
20#[derive(Debug)]
21struct RegionMeta {
22 vaddr: usize,
23 offset: usize,
24 filesz: usize,
25 memsz: usize,
26}
27
28struct Regions<'a> {
29 meta: &'a [RegionMeta],
30 data: &'a [u8],
31}
32
33impl Regions<'_> {
34 unsafe fn reset_memory(&self) {
35 for meta in self.meta {
36 let dst = unsafe { slice::from_raw_parts_mut(meta.vaddr as *mut _, meta.memsz) };
37 let (dst_data, dst_zero) = dst.split_at_mut(meta.filesz);
38 let src_data = &self.data[meta.offset..][..meta.filesz];
39 dst_data.copy_from_slice(src_data);
40 unsafe {
41 ptr::write_bytes(dst_zero.as_mut_ptr(), 0, dst_zero.len());
42 }
43 }
44 }
45}
46
47const STACK_SIZE: usize = 4096;
50
51#[unsafe(link_section = ".persistent")]
52static STACK: Stack<STACK_SIZE> = Stack::new();
53
54#[unsafe(no_mangle)]
55static __sel4_reset__stack_bottom: StackBottom = STACK.bottom();
56
57#[unsafe(no_mangle)]
60unsafe extern "C" fn __sel4_reset__reset_memory() {
61 unsafe {
62 get_regions().reset_memory();
63 }
64}
65
66unsafe fn get_regions() -> Regions<'static> {
67 unsafe {
68 Regions {
69 meta: slice::from_raw_parts(
70 (sel4_reset_regions_start + sel4_reset_regions_meta_offset) as *const _,
71 sel4_reset_regions_meta_count,
72 ),
73 data: slice::from_raw_parts(
74 (sel4_reset_regions_start + sel4_reset_regions_data_offset) as *const _,
75 sel4_reset_regions_data_size,
76 ),
77 }
78 }
79}
80
81macro_rules! rodata {
83 ($ident:ident) => {
84 unsafe extern "C" {
85 static $ident: usize;
86 }
87 global_asm! {
88 ".section .rodata",
89 concat!(".global ", stringify!($ident)),
90 concat!(stringify!($ident), ": ", asm_word_size!(), " 0"),
91 concat!(".size ", stringify!($ident), ", .-", stringify!($ident)),
92 }
93 };
94}
95
96cfg_if! {
97 if #[cfg(target_pointer_width = "64")] {
98 macro_rules! asm_word_size {
99 () => {
100 ".quad"
101 }
102 }
103 } else if #[cfg(target_pointer_width = "32")] {
104 macro_rules! asm_word_size {
105 () => {
106 ".word"
107 }
108 }
109 } else {
110 compile_error!("unsupported configuration");
111 }
112}
113
114rodata!(sel4_reset_regions_start);
115rodata!(sel4_reset_regions_meta_offset);
116rodata!(sel4_reset_regions_meta_count);
117rodata!(sel4_reset_regions_data_offset);
118rodata!(sel4_reset_regions_data_size);
119
120pub fn reset() -> ! {
123 unsafe {
124 _reset();
125 }
126 unreachable!()
127}
128
129unsafe extern "C" {
130 fn _reset();
131}
132
133macro_rules! common_asm_prefix {
134 () => {
135 r#"
136 .extern _start
137
138 .global _reset
139
140 .section .text
141
142 _reset:
143 "#
144 };
145}
146
147cfg_if::cfg_if! {
148 if #[cfg(target_arch = "aarch64")] {
149 global_asm! {
150 common_asm_prefix!(),
151 r#"
152 ldr x9, =__sel4_reset__stack_bottom
153 ldr x9, [x9]
154 mov sp, x9
155 bl __sel4_reset__reset_memory
156 b _start
157
158 1: b 1b
159 "#
160 }
161 } else {
162 compile_error!("unsupported architecture");
163 }
164}