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 //! Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
16 //! provided by crosvm, and won't work with real hardware.
17 
18 use core::fmt::{self, Write};
19 
20 /// Minimal driver for an 8250 UART. This only implements enough to work with the emulated 8250
21 /// provided by crosvm, and won't work with real hardware.
22 pub struct Uart {
23     base_address: *mut u8,
24 }
25 
26 impl Uart {
27     /// Constructs a new instance of the UART driver for a device at the given base address.
28     ///
29     /// # Safety
30     ///
31     /// The given base address must point to the 8 MMIO control registers of an appropriate UART
32     /// device, which must be mapped into the address space of the process as device memory and not
33     /// have any other aliases.
new(base_address: usize) -> Self34     pub unsafe fn new(base_address: usize) -> Self {
35         Self { base_address: base_address as *mut u8 }
36     }
37 
38     /// Writes a single byte to the UART.
write_byte(&self, byte: u8)39     pub fn write_byte(&self, byte: u8) {
40         // SAFETY: We know that the base address points to the control registers of a UART device
41         // which is appropriately mapped.
42         unsafe {
43             core::arch::asm!(
44                 "strb {value:w}, [{ptr}]",
45                 value = in(reg) byte,
46                 ptr = in(reg) self.base_address,
47             );
48         }
49     }
50 }
51 
52 impl Write for Uart {
write_str(&mut self, s: &str) -> fmt::Result53     fn write_str(&mut self, s: &str) -> fmt::Result {
54         for c in s.as_bytes() {
55             self.write_byte(*c);
56         }
57         Ok(())
58     }
59 }
60 
61 // SAFETY: `Uart` just contains a pointer to device memory, which can be accessed from any context.
62 unsafe impl Send for Uart {}
63