// src/main.rs #![no_std] #![no_main] #![feature(naked_functions)] use core::panic::PanicInfo; mod heap; mod uart; #[naked] #[no_mangle] #[link_section = ".text.init"] unsafe extern "C" fn _enter() -> ! { use core::arch::asm; asm!( // before we use the `la` pseudo-instruction for the first time, // we need to set `gp` (google linker relaxation) ".option push", ".option norelax", "la gp, _global_pointer", ".option pop", // set the stack pointer "la sp, _init_stack_top", // clear the BSS "la t0, _bss_start", "la t1, _bss_end", "bgeu t0, t1, 2f", "1:", "sb zero, 0(t0)", "addi t0, t0, 1", "bne t0, t1, 1b", "2:", // BSS is clear! // "tail-call" to {start} (call without saving a return address) "tail {start}", start = sym start, // {start} refers to the function [start] below options(noreturn) // we must handle "returning" from assembly ); } extern "C" fn start() -> ! { // UNSAFE: Called exactly once, right here. unsafe { heap::init() }; // Now we're free to use dynamic allocation! { extern crate alloc; use alloc::boxed::Box; let _my_heap_pointer = Box::new(10); // _my_heap_pointer lives on the heap! } println!("This should not print because the console is not initialised."); unsafe { uart::init_console(0x1000_0000) }; println!("Hello, world!"); loop { let c = uart::CONSOLE.lock().as_mut().and_then(uart::Device::get); if let Some(c) = c { print!("{}", c as char); } } } #[panic_handler] fn on_panic(info: &PanicInfo) -> ! { println!("{}", info); loop {} } // TODO unit testing