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