xref: /aosp_15_r20/external/crosvm/devices/src/debugcon.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
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