pub const PL011_BASE: u64 = 0x0B00_0000;
pub const PL011_SIZE: u64 = 0x1000;
pub const PL011_DR: u64 = 0x000;
pub const PL011_FR: u64 = 0x018;
pub struct Pl011 {
output: Vec<u8>,
}
impl Pl011 {
pub fn new() -> Self {
Self { output: Vec::new() }
}
pub fn contains(&self, addr: u64) -> bool {
(PL011_BASE..PL011_BASE + PL011_SIZE).contains(&addr)
}
pub fn read(&self, addr: u64, _size: usize) -> u64 {
let offset = addr - PL011_BASE;
match offset {
PL011_FR => 0,
_ => 0,
}
}
pub fn write(&mut self, addr: u64, _size: usize, value: u64) {
let offset = addr - PL011_BASE;
if offset == PL011_DR {
let byte = (value & 0xFF) as u8;
self.output.push(byte);
if byte == b'\n' {
if let Ok(line) = std::str::from_utf8(&self.output) {
tracing::info!(target: "guest_serial", "{}", line.trim_end());
}
self.output.clear();
}
}
}
#[cfg(test)]
pub fn output(&self) -> &[u8] {
&self.output
}
pub fn flush(&mut self) {
if !self.output.is_empty() {
if let Ok(line) = std::str::from_utf8(&self.output) {
tracing::info!(target: "guest_serial", "{}", line.trim_end());
}
self.output.clear();
}
}
}