//! Text out through the board's UART. `puts_raw` is for the very first //! line, before the MMU is on (it only does byte loads: with the MMU off //! all memory is "device" memory, where an unaligned access faults, and //! `core::fmt` makes no promises about that). `print!`/`println!` are for //! after. use core::fmt::{self, Write}; use spin::Mutex; struct Console; impl Write for Console { fn write_str(&mut self, s: &str) -> fmt::Result { let uart = super::board::current().uart(); for b in s.bytes() { if b == b'\n' { uart.putc(b'\r'); } uart.putc(b); } Ok(()) } } static LOCK: Mutex<()> = Mutex::new(()); /// One line, no formatting, safe with the MMU off. pub fn puts_raw(s: &str) { let uart = super::board::current().uart(); let bytes = s.as_bytes(); let mut i = 0; while i < bytes.len() { uart.putc(bytes[i]); i += 1; } uart.putc(b'\r'); uart.putc(b'\n'); } /// The `arch` interface's text out. pub fn write_str(s: &str) { _print(format_args!("{}", s)); } #[doc(hidden)] pub fn _print(args: fmt::Arguments) { let _guard = LOCK.lock(); let _ = Console.write_fmt(args); } /// Like `print!`, to the arm64 kernel's console. #[macro_export] macro_rules! print { ($($arg:tt)*) => { $crate::arch::aarch64::console::_print(format_args!($($arg)*)) }; } /// Like `println!`, to the arm64 kernel's console. #[macro_export] macro_rules! println { () => { $crate::print!("\n") }; ($($arg:tt)*) => { $crate::arch::aarch64::console::_print(format_args!("{}\n", format_args!($($arg)*))) }; } /// For the fatal-exception path only: the interrupted code may have been /// in the middle of a `println!`, holding the lock, and it will never run /// again. pub unsafe fn force_unlock() { unsafe { LOCK.force_unlock() }; }