diff --git a/examples/reverse.rs b/examples/reverse.rs index f4bccf065d5be7b1375b7c49da1cec150197844b..757651fe16a180475623553cf571e29ab621d164 100644 --- a/examples/reverse.rs +++ b/examples/reverse.rs @@ -20,10 +20,12 @@ const FROM: &[u8] = b"Hello Word!"; const SIZE: usize = FROM.len(); #[no_mangle] -fn main() { +fn main() -> ! { let mut to: [u8; SIZE] = [0; SIZE]; rev(&FROM[..], &mut to); unsafe { core::ptr::read_volatile(&to); } + + loop {} } diff --git a/link.ld b/link.ld index 011a78c99fb697cd54ca5edb935cc6c26eaff36e..45d9809dd213db3557e6b401b6b34b3c269645b6 100644 --- a/link.ld +++ b/link.ld @@ -22,13 +22,20 @@ SECTIONS .data : { - *(.data*) + __sdata = .; + *(.data*); + __edata = .; } + /* LMA of .data */ + __sidata = LOADADDR(.data); + _BSS_START = .; .bss : { - *(.bss*) + __sbss = .; + *(.bss*); + __ebss = .; } _BSS_END = .; diff --git a/src/lib.rs b/src/lib.rs index 7b9304f34965ddda715166907a083a427db14143..48792c97a11cd1944b42985c55dede933adaf8c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,77 @@ #![feature(lang_items)] #![no_std] -#![no_main] + +use core::{mem, ptr, slice}; #[panic_handler] fn my_panic(_info: &core::panic::PanicInfo) -> ! { loop {} } +/// Initializes the `.data` section +/// +/// # Arguments +/// +/// - `sdata`. Pointer to the start of the `.data` section. +/// - `edata`. Pointer to the open/non-inclusive end of the `.data` section. +/// (The value behind this pointer will not be modified) +/// - `sidata`. `.data` section Load Memory Address (LMA) +/// - Use `T` to indicate the alignment of the `.data` section and its LMA. +/// +/// # Safety +/// +/// - Must be called exactly once +/// - `mem::size_of::<T>()` must be non-zero +/// - `edata >= sdata` +/// - The `sdata -> edata` region must not overlap with the `sidata -> ...` +/// region +/// - `sdata`, `edata` and `sidata` must be `T` aligned. +pub unsafe fn init_data<T>(mut sdata: *mut T, edata: *mut T, mut sidata: *const T) +where + T: Copy, +{ + while sdata < edata { + ptr::write(sdata, ptr::read(sidata)); + sdata = sdata.offset(1); + sidata = sidata.offset(1); + } +} + +pub unsafe fn run_init_array(init_array_start: &extern "C" fn(), init_array_end: &extern "C" fn()) { + let n = (init_array_end as *const _ as usize - init_array_start as *const _ as usize) + / mem::size_of::<extern "C" fn()>(); + + for f in slice::from_raw_parts(init_array_start, n) { + f(); + } +} + +/// Zeroes the `.bss` section +/// +/// # Arguments +/// +/// - `sbss`. Pointer to the start of the `.bss` section. +/// - `ebss`. Pointer to the open/non-inclusive end of the `.bss` section. +/// (The value behind this pointer will not be modified) +/// - Use `T` to indicate the alignment of the `.bss` section. +/// +/// # Safety +/// +/// - Must be called exactly once +/// - `mem::size_of::<T>()` must be non-zero +/// - `ebss >= sbss` +/// - `sbss` and `ebss` must be `T` aligned. +pub unsafe fn zero_bss<T>(mut sbss: *mut T, ebss: *mut T) +where + T: Copy, +{ + while sbss < ebss { + // NOTE(volatile) to prevent this from being transformed into `memclr` + ptr::write_volatile(sbss, mem::zeroed()); + sbss = sbss.offset(1); + } +} + // The reset vector, a pointer into the reset handler #[link_section = ".init"] #[no_mangle] @@ -28,11 +93,11 @@ pub extern "C" fn _start() -> ! { } // Initialize RAM - // r0::zero_bss(&mut __sbss, &mut __ebss); - // r0::init_data(&mut __sdata, &mut __edata, &__sidata); - - unsafe { main() } - loop {} + unsafe { + zero_bss(&mut __sbss, &mut __ebss); + init_data(&mut __sdata, &mut __edata, &__sidata); + unsafe { main() } + } } #[lang = "eh_personality"]