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