1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker use std::io; 6*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write; 7*bb4ee6a4SAndroid Build Coastguard Worker 8*bb4ee6a4SAndroid Build Coastguard Worker use base::error; 9*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] 10*bb4ee6a4SAndroid Build Coastguard Worker use base::named_pipes; 11*bb4ee6a4SAndroid Build Coastguard Worker use base::Event; 12*bb4ee6a4SAndroid Build Coastguard Worker use base::FileSync; 13*bb4ee6a4SAndroid Build Coastguard Worker use base::RawDescriptor; 14*bb4ee6a4SAndroid Build Coastguard Worker use base::Result; 15*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::ProtectionType; 16*bb4ee6a4SAndroid Build Coastguard Worker 17*bb4ee6a4SAndroid Build Coastguard Worker use crate::pci::CrosvmDeviceId; 18*bb4ee6a4SAndroid Build Coastguard Worker use crate::serial_device::SerialInput; 19*bb4ee6a4SAndroid Build Coastguard Worker use crate::serial_device::SerialOptions; 20*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusAccessInfo; 21*bb4ee6a4SAndroid Build Coastguard Worker use crate::BusDevice; 22*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceId; 23*bb4ee6a4SAndroid Build Coastguard Worker use crate::SerialDevice; 24*bb4ee6a4SAndroid Build Coastguard Worker use crate::Suspendable; 25*bb4ee6a4SAndroid Build Coastguard Worker 26*bb4ee6a4SAndroid Build Coastguard Worker const BOCHS_DEBUGCON_READBACK: u8 = 0xe9; 27*bb4ee6a4SAndroid Build Coastguard Worker 28*bb4ee6a4SAndroid Build Coastguard Worker pub struct Debugcon { 29*bb4ee6a4SAndroid Build Coastguard Worker out: Option<Box<dyn io::Write + Send>>, 30*bb4ee6a4SAndroid Build Coastguard Worker } 31*bb4ee6a4SAndroid Build Coastguard Worker 32*bb4ee6a4SAndroid Build Coastguard Worker impl SerialDevice for Debugcon { new( _protection_type: ProtectionType, _interrupt_evt: Event, _input: Option<Box<dyn SerialInput>>, out: Option<Box<dyn io::Write + Send>>, _sync: Option<Box<dyn FileSync + Send>>, _options: SerialOptions, _keep_rds: Vec<RawDescriptor>, ) -> Debugcon33*bb4ee6a4SAndroid Build Coastguard Worker fn new( 34*bb4ee6a4SAndroid Build Coastguard Worker _protection_type: ProtectionType, 35*bb4ee6a4SAndroid Build Coastguard Worker _interrupt_evt: Event, 36*bb4ee6a4SAndroid Build Coastguard Worker _input: Option<Box<dyn SerialInput>>, 37*bb4ee6a4SAndroid Build Coastguard Worker out: Option<Box<dyn io::Write + Send>>, 38*bb4ee6a4SAndroid Build Coastguard Worker _sync: Option<Box<dyn FileSync + Send>>, 39*bb4ee6a4SAndroid Build Coastguard Worker _options: SerialOptions, 40*bb4ee6a4SAndroid Build Coastguard Worker _keep_rds: Vec<RawDescriptor>, 41*bb4ee6a4SAndroid Build Coastguard Worker ) -> Debugcon { 42*bb4ee6a4SAndroid Build Coastguard Worker Debugcon { out } 43*bb4ee6a4SAndroid Build Coastguard Worker } 44*bb4ee6a4SAndroid Build Coastguard Worker 45*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)] new_with_pipe( _protection_type: ProtectionType, _interrupt_evt: Event, _pipe_in: named_pipes::PipeConnection, _pipe_out: named_pipes::PipeConnection, _options: SerialOptions, _keep_rds: Vec<RawDescriptor>, ) -> Debugcon46*bb4ee6a4SAndroid Build Coastguard Worker fn new_with_pipe( 47*bb4ee6a4SAndroid Build Coastguard Worker _protection_type: ProtectionType, 48*bb4ee6a4SAndroid Build Coastguard Worker _interrupt_evt: Event, 49*bb4ee6a4SAndroid Build Coastguard Worker _pipe_in: named_pipes::PipeConnection, 50*bb4ee6a4SAndroid Build Coastguard Worker _pipe_out: named_pipes::PipeConnection, 51*bb4ee6a4SAndroid Build Coastguard Worker _options: SerialOptions, 52*bb4ee6a4SAndroid Build Coastguard Worker _keep_rds: Vec<RawDescriptor>, 53*bb4ee6a4SAndroid Build Coastguard Worker ) -> Debugcon { 54*bb4ee6a4SAndroid Build Coastguard Worker unimplemented!("new_with_pipe unimplemented for Debugcon"); 55*bb4ee6a4SAndroid Build Coastguard Worker } 56*bb4ee6a4SAndroid Build Coastguard Worker } 57*bb4ee6a4SAndroid Build Coastguard Worker 58*bb4ee6a4SAndroid Build Coastguard Worker impl BusDevice for Debugcon { device_id(&self) -> DeviceId59*bb4ee6a4SAndroid Build Coastguard Worker fn device_id(&self) -> DeviceId { 60*bb4ee6a4SAndroid Build Coastguard Worker CrosvmDeviceId::DebugConsole.into() 61*bb4ee6a4SAndroid Build Coastguard Worker } 62*bb4ee6a4SAndroid Build Coastguard Worker debug_label(&self) -> String63*bb4ee6a4SAndroid Build Coastguard Worker fn debug_label(&self) -> String { 64*bb4ee6a4SAndroid Build Coastguard Worker "debugcon".to_owned() 65*bb4ee6a4SAndroid Build Coastguard Worker } 66*bb4ee6a4SAndroid Build Coastguard Worker write(&mut self, _info: BusAccessInfo, data: &[u8])67*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, _info: BusAccessInfo, data: &[u8]) { 68*bb4ee6a4SAndroid Build Coastguard Worker if data.len() != 1 { 69*bb4ee6a4SAndroid Build Coastguard Worker return; 70*bb4ee6a4SAndroid Build Coastguard Worker } 71*bb4ee6a4SAndroid Build Coastguard Worker if let Err(e) = self.handle_write(data) { 72*bb4ee6a4SAndroid Build Coastguard Worker error!("debugcon failed write: {}", e); 73*bb4ee6a4SAndroid Build Coastguard Worker } 74*bb4ee6a4SAndroid Build Coastguard Worker } 75*bb4ee6a4SAndroid Build Coastguard Worker read(&mut self, _info: BusAccessInfo, data: &mut [u8])76*bb4ee6a4SAndroid Build Coastguard Worker fn read(&mut self, _info: BusAccessInfo, data: &mut [u8]) { 77*bb4ee6a4SAndroid Build Coastguard Worker if data.len() != 1 { 78*bb4ee6a4SAndroid Build Coastguard Worker return; 79*bb4ee6a4SAndroid Build Coastguard Worker } 80*bb4ee6a4SAndroid Build Coastguard Worker data[0] = BOCHS_DEBUGCON_READBACK; 81*bb4ee6a4SAndroid Build Coastguard Worker } 82*bb4ee6a4SAndroid Build Coastguard Worker } 83*bb4ee6a4SAndroid Build Coastguard Worker 84*bb4ee6a4SAndroid Build Coastguard Worker impl Debugcon { handle_write(&mut self, data: &[u8]) -> Result<()>85*bb4ee6a4SAndroid Build Coastguard Worker fn handle_write(&mut self, data: &[u8]) -> Result<()> { 86*bb4ee6a4SAndroid Build Coastguard Worker if let Some(out) = self.out.as_mut() { 87*bb4ee6a4SAndroid Build Coastguard Worker out.write_all(data)?; 88*bb4ee6a4SAndroid Build Coastguard Worker out.flush()?; 89*bb4ee6a4SAndroid Build Coastguard Worker } 90*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 91*bb4ee6a4SAndroid Build Coastguard Worker } 92*bb4ee6a4SAndroid Build Coastguard Worker } 93*bb4ee6a4SAndroid Build Coastguard Worker 94*bb4ee6a4SAndroid Build Coastguard Worker impl Suspendable for Debugcon { sleep(&mut self) -> anyhow::Result<()>95*bb4ee6a4SAndroid Build Coastguard Worker fn sleep(&mut self) -> anyhow::Result<()> { 96*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 97*bb4ee6a4SAndroid Build Coastguard Worker } 98*bb4ee6a4SAndroid Build Coastguard Worker wake(&mut self) -> anyhow::Result<()>99*bb4ee6a4SAndroid Build Coastguard Worker fn wake(&mut self) -> anyhow::Result<()> { 100*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 101*bb4ee6a4SAndroid Build Coastguard Worker } 102*bb4ee6a4SAndroid Build Coastguard Worker snapshot(&mut self) -> anyhow::Result<serde_json::Value>103*bb4ee6a4SAndroid Build Coastguard Worker fn snapshot(&mut self) -> anyhow::Result<serde_json::Value> { 104*bb4ee6a4SAndroid Build Coastguard Worker Ok(serde_json::Value::Null) 105*bb4ee6a4SAndroid Build Coastguard Worker } 106*bb4ee6a4SAndroid Build Coastguard Worker restore(&mut self, data: serde_json::Value) -> anyhow::Result<()>107*bb4ee6a4SAndroid Build Coastguard Worker fn restore(&mut self, data: serde_json::Value) -> anyhow::Result<()> { 108*bb4ee6a4SAndroid Build Coastguard Worker anyhow::ensure!( 109*bb4ee6a4SAndroid Build Coastguard Worker data == serde_json::Value::Null, 110*bb4ee6a4SAndroid Build Coastguard Worker "unexpected snapshot data: should be null, got {}", 111*bb4ee6a4SAndroid Build Coastguard Worker data, 112*bb4ee6a4SAndroid Build Coastguard Worker ); 113*bb4ee6a4SAndroid Build Coastguard Worker Ok(()) 114*bb4ee6a4SAndroid Build Coastguard Worker } 115*bb4ee6a4SAndroid Build Coastguard Worker } 116*bb4ee6a4SAndroid Build Coastguard Worker 117*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)] 118*bb4ee6a4SAndroid Build Coastguard Worker mod tests { 119*bb4ee6a4SAndroid Build Coastguard Worker use std::io; 120*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc; 121*bb4ee6a4SAndroid Build Coastguard Worker 122*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex; 123*bb4ee6a4SAndroid Build Coastguard Worker 124*bb4ee6a4SAndroid Build Coastguard Worker use super::*; 125*bb4ee6a4SAndroid Build Coastguard Worker 126*bb4ee6a4SAndroid Build Coastguard Worker const ADDR: BusAccessInfo = BusAccessInfo { 127*bb4ee6a4SAndroid Build Coastguard Worker offset: 0, 128*bb4ee6a4SAndroid Build Coastguard Worker address: 0, 129*bb4ee6a4SAndroid Build Coastguard Worker id: 0, 130*bb4ee6a4SAndroid Build Coastguard Worker }; 131*bb4ee6a4SAndroid Build Coastguard Worker 132*bb4ee6a4SAndroid Build Coastguard Worker // XXX(gerow): copied from devices/src/serial.rs 133*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Clone)] 134*bb4ee6a4SAndroid Build Coastguard Worker struct SharedBuffer { 135*bb4ee6a4SAndroid Build Coastguard Worker buf: Arc<Mutex<Vec<u8>>>, 136*bb4ee6a4SAndroid Build Coastguard Worker } 137*bb4ee6a4SAndroid Build Coastguard Worker 138*bb4ee6a4SAndroid Build Coastguard Worker impl SharedBuffer { new() -> SharedBuffer139*bb4ee6a4SAndroid Build Coastguard Worker fn new() -> SharedBuffer { 140*bb4ee6a4SAndroid Build Coastguard Worker SharedBuffer { 141*bb4ee6a4SAndroid Build Coastguard Worker buf: Arc::new(Mutex::new(Vec::new())), 142*bb4ee6a4SAndroid Build Coastguard Worker } 143*bb4ee6a4SAndroid Build Coastguard Worker } 144*bb4ee6a4SAndroid Build Coastguard Worker } 145*bb4ee6a4SAndroid Build Coastguard Worker 146*bb4ee6a4SAndroid Build Coastguard Worker impl io::Write for SharedBuffer { write(&mut self, buf: &[u8]) -> io::Result<usize>147*bb4ee6a4SAndroid Build Coastguard Worker fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 148*bb4ee6a4SAndroid Build Coastguard Worker self.buf.lock().write(buf) 149*bb4ee6a4SAndroid Build Coastguard Worker } flush(&mut self) -> io::Result<()>150*bb4ee6a4SAndroid Build Coastguard Worker fn flush(&mut self) -> io::Result<()> { 151*bb4ee6a4SAndroid Build Coastguard Worker self.buf.lock().flush() 152*bb4ee6a4SAndroid Build Coastguard Worker } 153*bb4ee6a4SAndroid Build Coastguard Worker } 154*bb4ee6a4SAndroid Build Coastguard Worker 155*bb4ee6a4SAndroid Build Coastguard Worker #[test] write()156*bb4ee6a4SAndroid Build Coastguard Worker fn write() { 157*bb4ee6a4SAndroid Build Coastguard Worker let debugcon_out = SharedBuffer::new(); 158*bb4ee6a4SAndroid Build Coastguard Worker let mut debugcon = Debugcon::new( 159*bb4ee6a4SAndroid Build Coastguard Worker ProtectionType::Unprotected, 160*bb4ee6a4SAndroid Build Coastguard Worker Event::new().unwrap(), 161*bb4ee6a4SAndroid Build Coastguard Worker None, 162*bb4ee6a4SAndroid Build Coastguard Worker Some(Box::new(debugcon_out.clone())), 163*bb4ee6a4SAndroid Build Coastguard Worker None, 164*bb4ee6a4SAndroid Build Coastguard Worker Default::default(), 165*bb4ee6a4SAndroid Build Coastguard Worker Vec::new(), 166*bb4ee6a4SAndroid Build Coastguard Worker ); 167*bb4ee6a4SAndroid Build Coastguard Worker 168*bb4ee6a4SAndroid Build Coastguard Worker debugcon.write(ADDR, b"a"); 169*bb4ee6a4SAndroid Build Coastguard Worker debugcon.write(ADDR, b"b"); 170*bb4ee6a4SAndroid Build Coastguard Worker debugcon.write(ADDR, b"c"); 171*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(debugcon_out.buf.lock().as_slice(), b"abc"); 172*bb4ee6a4SAndroid Build Coastguard Worker } 173*bb4ee6a4SAndroid Build Coastguard Worker 174*bb4ee6a4SAndroid Build Coastguard Worker #[test] read()175*bb4ee6a4SAndroid Build Coastguard Worker fn read() { 176*bb4ee6a4SAndroid Build Coastguard Worker let mut debugcon = Debugcon::new( 177*bb4ee6a4SAndroid Build Coastguard Worker ProtectionType::Unprotected, 178*bb4ee6a4SAndroid Build Coastguard Worker Event::new().unwrap(), 179*bb4ee6a4SAndroid Build Coastguard Worker None, 180*bb4ee6a4SAndroid Build Coastguard Worker None, 181*bb4ee6a4SAndroid Build Coastguard Worker None, 182*bb4ee6a4SAndroid Build Coastguard Worker Default::default(), 183*bb4ee6a4SAndroid Build Coastguard Worker Vec::new(), 184*bb4ee6a4SAndroid Build Coastguard Worker ); 185*bb4ee6a4SAndroid Build Coastguard Worker 186*bb4ee6a4SAndroid Build Coastguard Worker let mut data = [0u8; 1]; 187*bb4ee6a4SAndroid Build Coastguard Worker debugcon.read(ADDR, &mut data[..]); 188*bb4ee6a4SAndroid Build Coastguard Worker assert_eq!(data[0], 0xe9); 189*bb4ee6a4SAndroid Build Coastguard Worker } 190*bb4ee6a4SAndroid Build Coastguard Worker } 191