1#![no_std]
33#![deny(warnings, missing_docs)]
34
35mod app;
36
37pub use app::{AppIterator, AppMeta};
38
39pub const SCRIPT: &[u8] = b"\
41OUTPUT_ARCH(riscv)
42SECTIONS {
43 .text 0x80200000 : {
44 __start = .;
45 *(.text.entry)
46 *(.text .text.*)
47 }
48 .rodata : ALIGN(4K) {
49 __rodata = .;
50 *(.rodata .rodata.*)
51 *(.srodata .srodata.*)
52 }
53 .data : ALIGN(4K) {
54 __data = .;
55 *(.data .data.*)
56 *(.sdata .sdata.*)
57 }
58 .bss : ALIGN(8) {
59 __sbss = .;
60 *(.bss .bss.*)
61 *(.sbss .sbss.*)
62 __ebss = .;
63 }
64 .boot : ALIGN(4K) {
65 __boot = .;
66 KEEP(*(.boot.stack))
67 }
68 __end = .;
69}";
70
71pub const NOBIOS_SCRIPT: &[u8] = b"\
75OUTPUT_ARCH(riscv)
76ENTRY(_m_start)
77M_BASE_ADDRESS = 0x80000000;
78S_BASE_ADDRESS = 0x80200000;
79
80SECTIONS {
81 . = M_BASE_ADDRESS;
82
83 .text.m_entry : {
84 *(.text.m_entry)
85 }
86
87 .text.m_trap : {
88 *(.text.m_trap)
89 }
90
91 .bss.m_stack : {
92 *(.bss.m_stack)
93 }
94
95 .bss.m_data : {
96 *(.bss.m_data)
97 }
98
99 . = S_BASE_ADDRESS;
100
101 .text : {
102 __start = .;
103 *(.text.entry)
104 *(.text .text.*)
105 }
106 .rodata : ALIGN(4K) {
107 __rodata = .;
108 *(.rodata .rodata.*)
109 *(.srodata .srodata.*)
110 }
111 .data : ALIGN(4K) {
112 __data = .;
113 *(.data .data.*)
114 *(.sdata .sdata.*)
115 }
116 .bss : ALIGN(8) {
117 __sbss = .;
118 *(.bss .bss.*)
119 *(.sbss .sbss.*)
120 __ebss = .;
121 }
122 .boot : ALIGN(4K) {
123 __boot = .;
124 KEEP(*(.boot.stack))
125 }
126 __end = .;
127}";
128
129#[macro_export]
142macro_rules! boot0 {
143 ($entry:ident; stack = $stack:expr) => {
144 #[cfg(target_arch = "riscv64")]
151 #[unsafe(naked)]
152 #[no_mangle]
153 #[link_section = ".text.entry"]
154 unsafe extern "C" fn _start() -> ! {
155 #[link_section = ".boot.stack"]
156 static mut STACK: [u8; $stack] = [0u8; $stack];
157
158 core::arch::naked_asm!(
161 "la sp, __end",
162 "j {main}",
163 main = sym rust_main,
164 )
165 }
166
167 #[cfg(not(target_arch = "riscv64"))]
168 #[no_mangle]
169 unsafe extern "C" fn _start() -> ! {
170 unimplemented!("_start() is only supported on riscv64")
171 }
172 };
173}
174
175#[derive(Debug)]
177pub struct KernelLayout {
178 text: usize,
179 rodata: usize,
180 data: usize,
181 sbss: usize,
182 ebss: usize,
183 boot: usize,
184 end: usize,
185}
186
187impl KernelLayout {
188 pub const INIT: Self = Self {
190 text: usize::MAX,
191 rodata: usize::MAX,
192 data: usize::MAX,
193 sbss: usize::MAX,
194 ebss: usize::MAX,
195 boot: usize::MAX,
196 end: usize::MAX,
197 };
198
199 #[inline]
201 pub fn locate() -> Self {
202 extern "C" {
203 fn __start();
204 fn __rodata();
205 fn __data();
206 fn __sbss();
207 fn __ebss();
208 fn __boot();
209 fn __end();
210 }
211
212 Self {
213 text: __start as *const () as _,
214 rodata: __rodata as *const () as _,
215 data: __data as *const () as _,
216 sbss: __sbss as *const () as _,
217 ebss: __ebss as *const () as _,
218 boot: __boot as *const () as _,
219 end: __end as *const () as _,
220 }
221 }
222
223 #[inline]
225 pub const fn start(&self) -> usize {
226 self.text
227 }
228
229 #[inline]
231 pub const fn end(&self) -> usize {
232 self.end
233 }
234
235 #[inline]
237 pub const fn len(&self) -> usize {
238 self.end - self.text
239 }
240
241 #[inline]
250 pub unsafe fn zero_bss(&self) {
251 let mut ptr = self.sbss as *mut u8;
252 let end = self.ebss as *mut u8;
253 while ptr < end {
254 ptr.write_volatile(0);
257 ptr = ptr.offset(1);
258 }
259 }
260
261 #[inline]
263 pub fn iter(&self) -> KernelRegionIterator<'_> {
264 KernelRegionIterator {
265 layout: self,
266 next: Some(KernelRegionTitle::Text),
267 }
268 }
269}
270
271use core::{fmt, ops::Range};
272
273pub struct KernelRegionIterator<'a> {
275 layout: &'a KernelLayout,
276 next: Option<KernelRegionTitle>,
277}
278
279#[derive(Clone, Copy)]
281pub enum KernelRegionTitle {
282 Text,
284 Rodata,
286 Data,
288 Boot,
290}
291
292pub struct KernelRegion {
294 pub title: KernelRegionTitle,
296 pub range: Range<usize>,
298}
299
300impl fmt::Display for KernelRegion {
301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302 match self.title {
303 KernelRegionTitle::Text => write!(f, ".text ----> ")?,
304 KernelRegionTitle::Rodata => write!(f, ".rodata --> ")?,
305 KernelRegionTitle::Data => write!(f, ".data ----> ")?,
306 KernelRegionTitle::Boot => write!(f, ".boot ----> ")?,
307 }
308 write!(f, "{:#10x}..{:#10x}", self.range.start, self.range.end)
309 }
310}
311
312impl Iterator for KernelRegionIterator<'_> {
313 type Item = KernelRegion;
314
315 fn next(&mut self) -> Option<Self::Item> {
316 use KernelRegionTitle::*;
317 match self.next? {
318 Text => {
319 self.next = Some(Rodata);
320 Some(KernelRegion {
321 title: Text,
322 range: self.layout.text..self.layout.rodata,
323 })
324 }
325 Rodata => {
326 self.next = Some(Data);
327 Some(KernelRegion {
328 title: Rodata,
329 range: self.layout.rodata..self.layout.data,
330 })
331 }
332 Data => {
333 self.next = Some(Boot);
334 Some(KernelRegion {
335 title: Data,
336 range: self.layout.data..self.layout.ebss,
337 })
338 }
339 Boot => {
340 self.next = None;
341 Some(KernelRegion {
342 title: Boot,
343 range: self.layout.boot..self.layout.end,
344 })
345 }
346 }
347 }
348}