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