• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Console driver for 8250 UART.
16 
17 use crate::uart::Uart;
18 use core::fmt::{write, Arguments, Write};
19 use spin::mutex::SpinMutex;
20 
21 const BASE_ADDRESS: usize = 0x3f8;
22 
23 static CONSOLE: SpinMutex<Option<Uart>> = SpinMutex::new(None);
24 
25 /// Initialises a new instance of the UART driver and returns it.
create() -> Uart26 fn create() -> Uart {
27     // Safe because BASE_ADDRESS is the base of the MMIO region for a UART and is mapped as device
28     // memory.
29     unsafe { Uart::new(BASE_ADDRESS) }
30 }
31 
32 /// Initialises the global instance of the UART driver. This must be called before using
33 /// the `print!` and `println!` macros.
init()34 pub fn init() {
35     let uart = create();
36     CONSOLE.lock().replace(uart);
37 }
38 
39 /// Writes a string to the console.
40 ///
41 /// Panics if [`init`] was not called first.
write_str(s: &str)42 pub fn write_str(s: &str) {
43     CONSOLE.lock().as_mut().unwrap().write_str(s).unwrap();
44 }
45 
46 /// Writes a formatted string to the console.
47 ///
48 /// Panics if [`init`] was not called first.
write_args(format_args: Arguments)49 pub fn write_args(format_args: Arguments) {
50     write(CONSOLE.lock().as_mut().unwrap(), format_args).unwrap();
51 }
52 
53 /// Reinitialises the UART driver and writes a string to it.
54 ///
55 /// This is intended for use in situations where the UART may be in an unknown state or the global
56 /// instance may be locked, such as in an exception handler or panic handler.
emergency_write_str(s: &str)57 pub fn emergency_write_str(s: &str) {
58     let mut uart = create();
59     let _ = uart.write_str(s);
60 }
61 
62 /// Reinitialises the UART driver and writes a formatted string to it.
63 ///
64 /// This is intended for use in situations where the UART may be in an unknown state or the global
65 /// instance may be locked, such as in an exception handler or panic handler.
emergency_write_args(format_args: Arguments)66 pub fn emergency_write_args(format_args: Arguments) {
67     let mut uart = create();
68     let _ = write(&mut uart, format_args);
69 }
70 
71 /// Prints the given string to the console.
72 ///
73 /// Panics if the console has not yet been initialised. May hang if used in an exception context;
74 /// use `eprint!` instead.
75 #[macro_export]
76 macro_rules! print {
77     ($($arg:tt)*) => ($crate::console::write_args(format_args!($($arg)*)));
78 }
79 
80 /// Prints the given formatted string to the console, followed by a newline.
81 ///
82 /// Panics if the console has not yet been initialised. May hang if used in an exception context;
83 /// use `eprintln!` instead.
84 #[macro_export]
85 macro_rules! println {
86     () => ($crate::console::write_str("\n"));
87     ($($arg:tt)*) => ({
88         $crate::console::write_args(format_args!($($arg)*))};
89         $crate::console::write_str("\n");
90     );
91 }
92 
93 /// Prints the given string to the console in an emergency, such as an exception handler.
94 ///
95 /// Never panics.
96 #[macro_export]
97 macro_rules! eprint {
98     ($($arg:tt)*) => ($crate::console::emergency_write_args(format_args!($($arg)*)));
99 }
100 
101 /// Prints the given string followed by a newline to the console in an emergency, such as an
102 /// exception handler.
103 ///
104 /// Never panics.
105 #[macro_export]
106 macro_rules! eprintln {
107     () => ($crate::console::emergency_write_str("\n"));
108     ($($arg:tt)*) => ({
109         $crate::console::emergency_write_args(format_args!($($arg)*))};
110         $crate::console::emergency_write_str("\n");
111     );
112 }
113