1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2020 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::collections::BTreeMap;
6*bb4ee6a4SAndroid Build Coastguard Worker
7*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "seccomp_trace")]
8*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
9*bb4ee6a4SAndroid Build Coastguard Worker use base::Event;
10*bb4ee6a4SAndroid Build Coastguard Worker use devices::serial_device::SerialHardware;
11*bb4ee6a4SAndroid Build Coastguard Worker use devices::serial_device::SerialParameters;
12*bb4ee6a4SAndroid Build Coastguard Worker use devices::serial_device::SerialType;
13*bb4ee6a4SAndroid Build Coastguard Worker use devices::Bus;
14*bb4ee6a4SAndroid Build Coastguard Worker use devices::Serial;
15*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::ProtectionType;
16*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "seccomp_trace")]
17*bb4ee6a4SAndroid Build Coastguard Worker use jail::read_jail_addr;
18*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
19*bb4ee6a4SAndroid Build Coastguard Worker use jail::FakeMinijailStub as Minijail;
20*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
21*bb4ee6a4SAndroid Build Coastguard Worker use minijail::Minijail;
22*bb4ee6a4SAndroid Build Coastguard Worker use remain::sorted;
23*bb4ee6a4SAndroid Build Coastguard Worker use thiserror::Error as ThisError;
24*bb4ee6a4SAndroid Build Coastguard Worker
25*bb4ee6a4SAndroid Build Coastguard Worker use crate::DeviceRegistrationError;
26*bb4ee6a4SAndroid Build Coastguard Worker
27*bb4ee6a4SAndroid Build Coastguard Worker mod sys;
28*bb4ee6a4SAndroid Build Coastguard Worker
29*bb4ee6a4SAndroid Build Coastguard Worker /// Add the default serial parameters for serial ports that have not already been specified.
30*bb4ee6a4SAndroid Build Coastguard Worker ///
31*bb4ee6a4SAndroid Build Coastguard Worker /// This ensures that `serial_parameters` will contain parameters for each of the four PC-style
32*bb4ee6a4SAndroid Build Coastguard Worker /// serial ports (COM1-COM4).
33*bb4ee6a4SAndroid Build Coastguard Worker ///
34*bb4ee6a4SAndroid Build Coastguard Worker /// It also sets the first `SerialHardware::Serial` to be the default console device if no other
35*bb4ee6a4SAndroid Build Coastguard Worker /// serial parameters exist with console=true and the first serial device has not already been
36*bb4ee6a4SAndroid Build Coastguard Worker /// configured explicitly.
set_default_serial_parameters( serial_parameters: &mut BTreeMap<(SerialHardware, u8), SerialParameters>, is_vhost_user_console_enabled: bool, )37*bb4ee6a4SAndroid Build Coastguard Worker pub fn set_default_serial_parameters(
38*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters: &mut BTreeMap<(SerialHardware, u8), SerialParameters>,
39*bb4ee6a4SAndroid Build Coastguard Worker is_vhost_user_console_enabled: bool,
40*bb4ee6a4SAndroid Build Coastguard Worker ) {
41*bb4ee6a4SAndroid Build Coastguard Worker // If no console device exists and the first serial port has not been specified,
42*bb4ee6a4SAndroid Build Coastguard Worker // set the first serial port as a stdout+stdin console.
43*bb4ee6a4SAndroid Build Coastguard Worker let default_console = (SerialHardware::Serial, 1);
44*bb4ee6a4SAndroid Build Coastguard Worker if !serial_parameters.iter().any(|(_, p)| p.console) && !is_vhost_user_console_enabled {
45*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters
46*bb4ee6a4SAndroid Build Coastguard Worker .entry(default_console)
47*bb4ee6a4SAndroid Build Coastguard Worker .or_insert(SerialParameters {
48*bb4ee6a4SAndroid Build Coastguard Worker type_: SerialType::Stdout,
49*bb4ee6a4SAndroid Build Coastguard Worker hardware: SerialHardware::Serial,
50*bb4ee6a4SAndroid Build Coastguard Worker name: None,
51*bb4ee6a4SAndroid Build Coastguard Worker path: None,
52*bb4ee6a4SAndroid Build Coastguard Worker input: None,
53*bb4ee6a4SAndroid Build Coastguard Worker num: 1,
54*bb4ee6a4SAndroid Build Coastguard Worker console: true,
55*bb4ee6a4SAndroid Build Coastguard Worker earlycon: false,
56*bb4ee6a4SAndroid Build Coastguard Worker stdin: true,
57*bb4ee6a4SAndroid Build Coastguard Worker out_timestamp: false,
58*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
59*bb4ee6a4SAndroid Build Coastguard Worker });
60*bb4ee6a4SAndroid Build Coastguard Worker }
61*bb4ee6a4SAndroid Build Coastguard Worker
62*bb4ee6a4SAndroid Build Coastguard Worker // Ensure all four of the COM ports exist.
63*bb4ee6a4SAndroid Build Coastguard Worker // If one of these four SerialHardware::Serial port was not configured by the user,
64*bb4ee6a4SAndroid Build Coastguard Worker // set it up as a sink.
65*bb4ee6a4SAndroid Build Coastguard Worker for num in 1..=4 {
66*bb4ee6a4SAndroid Build Coastguard Worker let key = (SerialHardware::Serial, num);
67*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters.entry(key).or_insert(SerialParameters {
68*bb4ee6a4SAndroid Build Coastguard Worker type_: SerialType::Sink,
69*bb4ee6a4SAndroid Build Coastguard Worker hardware: SerialHardware::Serial,
70*bb4ee6a4SAndroid Build Coastguard Worker name: None,
71*bb4ee6a4SAndroid Build Coastguard Worker path: None,
72*bb4ee6a4SAndroid Build Coastguard Worker input: None,
73*bb4ee6a4SAndroid Build Coastguard Worker num,
74*bb4ee6a4SAndroid Build Coastguard Worker console: false,
75*bb4ee6a4SAndroid Build Coastguard Worker earlycon: false,
76*bb4ee6a4SAndroid Build Coastguard Worker stdin: false,
77*bb4ee6a4SAndroid Build Coastguard Worker out_timestamp: false,
78*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
79*bb4ee6a4SAndroid Build Coastguard Worker });
80*bb4ee6a4SAndroid Build Coastguard Worker }
81*bb4ee6a4SAndroid Build Coastguard Worker }
82*bb4ee6a4SAndroid Build Coastguard Worker
83*bb4ee6a4SAndroid Build Coastguard Worker /// Address for Serial ports in x86
84*bb4ee6a4SAndroid Build Coastguard Worker pub const SERIAL_ADDR: [u64; 4] = [0x3f8, 0x2f8, 0x3e8, 0x2e8];
85*bb4ee6a4SAndroid Build Coastguard Worker
86*bb4ee6a4SAndroid Build Coastguard Worker /// Information about a serial device (16550-style UART) created by `add_serial_devices()`.
87*bb4ee6a4SAndroid Build Coastguard Worker pub struct SerialDeviceInfo {
88*bb4ee6a4SAndroid Build Coastguard Worker /// Address of the device on the bus.
89*bb4ee6a4SAndroid Build Coastguard Worker /// This is the I/O bus on x86 machines and MMIO otherwise.
90*bb4ee6a4SAndroid Build Coastguard Worker pub address: u64,
91*bb4ee6a4SAndroid Build Coastguard Worker
92*bb4ee6a4SAndroid Build Coastguard Worker /// Size of the device's address space on the bus.
93*bb4ee6a4SAndroid Build Coastguard Worker pub size: u64,
94*bb4ee6a4SAndroid Build Coastguard Worker
95*bb4ee6a4SAndroid Build Coastguard Worker /// IRQ number of the device.
96*bb4ee6a4SAndroid Build Coastguard Worker pub irq: u32,
97*bb4ee6a4SAndroid Build Coastguard Worker }
98*bb4ee6a4SAndroid Build Coastguard Worker
99*bb4ee6a4SAndroid Build Coastguard Worker /// Adds serial devices to the provided bus based on the serial parameters given.
100*bb4ee6a4SAndroid Build Coastguard Worker ///
101*bb4ee6a4SAndroid Build Coastguard Worker /// Only devices with hardware type `SerialHardware::Serial` are added by this function.
102*bb4ee6a4SAndroid Build Coastguard Worker ///
103*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
104*bb4ee6a4SAndroid Build Coastguard Worker ///
105*bb4ee6a4SAndroid Build Coastguard Worker /// * `protection_type` - VM protection mode.
106*bb4ee6a4SAndroid Build Coastguard Worker /// * `io_bus` - Bus to add the devices to
107*bb4ee6a4SAndroid Build Coastguard Worker /// * `com_evt_1_3` - irq and event for com1 and com3
108*bb4ee6a4SAndroid Build Coastguard Worker /// * `com_evt_1_4` - irq and event for com2 and com4
109*bb4ee6a4SAndroid Build Coastguard Worker /// * `serial_parameters` - definitions of serial parameter configurations.
110*bb4ee6a4SAndroid Build Coastguard Worker /// * `serial_jail` - minijail object cloned for use with each serial device. All four of the
111*bb4ee6a4SAndroid Build Coastguard Worker /// traditional PC-style serial ports (COM1-COM4) must be specified.
add_serial_devices( protection_type: ProtectionType, io_bus: &Bus, com_evt_1_3: (u32, &Event), com_evt_2_4: (u32, &Event), serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>, #[cfg_attr(windows, allow(unused_variables))] serial_jail: Option<Minijail>, #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>, ) -> std::result::Result<Vec<SerialDeviceInfo>, DeviceRegistrationError>112*bb4ee6a4SAndroid Build Coastguard Worker pub fn add_serial_devices(
113*bb4ee6a4SAndroid Build Coastguard Worker protection_type: ProtectionType,
114*bb4ee6a4SAndroid Build Coastguard Worker io_bus: &Bus,
115*bb4ee6a4SAndroid Build Coastguard Worker com_evt_1_3: (u32, &Event),
116*bb4ee6a4SAndroid Build Coastguard Worker com_evt_2_4: (u32, &Event),
117*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
118*bb4ee6a4SAndroid Build Coastguard Worker #[cfg_attr(windows, allow(unused_variables))] serial_jail: Option<Minijail>,
119*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")] swap_controller: &mut Option<swap::SwapController>,
120*bb4ee6a4SAndroid Build Coastguard Worker ) -> std::result::Result<Vec<SerialDeviceInfo>, DeviceRegistrationError> {
121*bb4ee6a4SAndroid Build Coastguard Worker let mut devices = Vec::new();
122*bb4ee6a4SAndroid Build Coastguard Worker for com_num in 0..=3 {
123*bb4ee6a4SAndroid Build Coastguard Worker let com_evt = match com_num {
124*bb4ee6a4SAndroid Build Coastguard Worker 0 => &com_evt_1_3,
125*bb4ee6a4SAndroid Build Coastguard Worker 1 => &com_evt_2_4,
126*bb4ee6a4SAndroid Build Coastguard Worker 2 => &com_evt_1_3,
127*bb4ee6a4SAndroid Build Coastguard Worker 3 => &com_evt_2_4,
128*bb4ee6a4SAndroid Build Coastguard Worker _ => &com_evt_1_3,
129*bb4ee6a4SAndroid Build Coastguard Worker };
130*bb4ee6a4SAndroid Build Coastguard Worker
131*bb4ee6a4SAndroid Build Coastguard Worker let (irq, com_evt) = (com_evt.0, com_evt.1);
132*bb4ee6a4SAndroid Build Coastguard Worker
133*bb4ee6a4SAndroid Build Coastguard Worker let param = serial_parameters
134*bb4ee6a4SAndroid Build Coastguard Worker .get(&(SerialHardware::Serial, com_num + 1))
135*bb4ee6a4SAndroid Build Coastguard Worker .ok_or(DeviceRegistrationError::MissingRequiredSerialDevice(
136*bb4ee6a4SAndroid Build Coastguard Worker com_num + 1,
137*bb4ee6a4SAndroid Build Coastguard Worker ))?;
138*bb4ee6a4SAndroid Build Coastguard Worker
139*bb4ee6a4SAndroid Build Coastguard Worker let mut preserved_descriptors = Vec::new();
140*bb4ee6a4SAndroid Build Coastguard Worker let com = param
141*bb4ee6a4SAndroid Build Coastguard Worker .create_serial_device::<Serial>(protection_type, com_evt, &mut preserved_descriptors)
142*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::CreateSerialDevice)?;
143*bb4ee6a4SAndroid Build Coastguard Worker
144*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
145*bb4ee6a4SAndroid Build Coastguard Worker let serial_jail = if let Some(serial_jail) = serial_jail.as_ref() {
146*bb4ee6a4SAndroid Build Coastguard Worker let jail_clone = serial_jail
147*bb4ee6a4SAndroid Build Coastguard Worker .try_clone()
148*bb4ee6a4SAndroid Build Coastguard Worker .map_err(DeviceRegistrationError::CloneJail)?;
149*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "seccomp_trace")]
150*bb4ee6a4SAndroid Build Coastguard Worker debug!(
151*bb4ee6a4SAndroid Build Coastguard Worker "seccomp_trace {{\"event\": \"minijail_clone\", \"src_jail_addr\": \"0x{:x}\", \"dst_jail_addr\": \"0x{:x}\"}}",
152*bb4ee6a4SAndroid Build Coastguard Worker read_jail_addr(serial_jail),
153*bb4ee6a4SAndroid Build Coastguard Worker read_jail_addr(&jail_clone)
154*bb4ee6a4SAndroid Build Coastguard Worker );
155*bb4ee6a4SAndroid Build Coastguard Worker Some(jail_clone)
156*bb4ee6a4SAndroid Build Coastguard Worker } else {
157*bb4ee6a4SAndroid Build Coastguard Worker None
158*bb4ee6a4SAndroid Build Coastguard Worker };
159*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(windows)]
160*bb4ee6a4SAndroid Build Coastguard Worker let serial_jail = None;
161*bb4ee6a4SAndroid Build Coastguard Worker
162*bb4ee6a4SAndroid Build Coastguard Worker let com = sys::add_serial_device(
163*bb4ee6a4SAndroid Build Coastguard Worker com,
164*bb4ee6a4SAndroid Build Coastguard Worker param,
165*bb4ee6a4SAndroid Build Coastguard Worker serial_jail,
166*bb4ee6a4SAndroid Build Coastguard Worker preserved_descriptors,
167*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
168*bb4ee6a4SAndroid Build Coastguard Worker swap_controller,
169*bb4ee6a4SAndroid Build Coastguard Worker )?;
170*bb4ee6a4SAndroid Build Coastguard Worker
171*bb4ee6a4SAndroid Build Coastguard Worker let address = SERIAL_ADDR[usize::from(com_num)];
172*bb4ee6a4SAndroid Build Coastguard Worker let size = 0x8; // 16550 UART uses 8 bytes of address space.
173*bb4ee6a4SAndroid Build Coastguard Worker io_bus.insert(com, address, size).unwrap();
174*bb4ee6a4SAndroid Build Coastguard Worker devices.push(SerialDeviceInfo { address, size, irq })
175*bb4ee6a4SAndroid Build Coastguard Worker }
176*bb4ee6a4SAndroid Build Coastguard Worker
177*bb4ee6a4SAndroid Build Coastguard Worker Ok(devices)
178*bb4ee6a4SAndroid Build Coastguard Worker }
179*bb4ee6a4SAndroid Build Coastguard Worker
180*bb4ee6a4SAndroid Build Coastguard Worker #[sorted]
181*bb4ee6a4SAndroid Build Coastguard Worker #[derive(ThisError, Debug)]
182*bb4ee6a4SAndroid Build Coastguard Worker pub enum GetSerialCmdlineError {
183*bb4ee6a4SAndroid Build Coastguard Worker #[error("Error appending to cmdline: {0}")]
184*bb4ee6a4SAndroid Build Coastguard Worker KernelCmdline(kernel_cmdline::Error),
185*bb4ee6a4SAndroid Build Coastguard Worker #[error("Hardware {0} not supported as earlycon")]
186*bb4ee6a4SAndroid Build Coastguard Worker UnsupportedEarlyconHardware(SerialHardware),
187*bb4ee6a4SAndroid Build Coastguard Worker }
188*bb4ee6a4SAndroid Build Coastguard Worker
189*bb4ee6a4SAndroid Build Coastguard Worker pub type GetSerialCmdlineResult<T> = std::result::Result<T, GetSerialCmdlineError>;
190*bb4ee6a4SAndroid Build Coastguard Worker
191*bb4ee6a4SAndroid Build Coastguard Worker /// Add serial options to the provided `cmdline` based on `serial_parameters`.
192*bb4ee6a4SAndroid Build Coastguard Worker /// `serial_io_type` should be "io" if the platform uses x86-style I/O ports for serial devices
193*bb4ee6a4SAndroid Build Coastguard Worker /// or "mmio" if the serial ports are memory mapped.
194*bb4ee6a4SAndroid Build Coastguard Worker // TODO(b/227407433): Support cases where vhost-user console is specified.
get_serial_cmdline( cmdline: &mut kernel_cmdline::Cmdline, serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>, serial_io_type: &str, serial_devices: &[SerialDeviceInfo], ) -> GetSerialCmdlineResult<()>195*bb4ee6a4SAndroid Build Coastguard Worker pub fn get_serial_cmdline(
196*bb4ee6a4SAndroid Build Coastguard Worker cmdline: &mut kernel_cmdline::Cmdline,
197*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters: &BTreeMap<(SerialHardware, u8), SerialParameters>,
198*bb4ee6a4SAndroid Build Coastguard Worker serial_io_type: &str,
199*bb4ee6a4SAndroid Build Coastguard Worker serial_devices: &[SerialDeviceInfo],
200*bb4ee6a4SAndroid Build Coastguard Worker ) -> GetSerialCmdlineResult<()> {
201*bb4ee6a4SAndroid Build Coastguard Worker for serial_parameter in serial_parameters
202*bb4ee6a4SAndroid Build Coastguard Worker .iter()
203*bb4ee6a4SAndroid Build Coastguard Worker .filter(|(_, p)| p.console)
204*bb4ee6a4SAndroid Build Coastguard Worker .map(|(k, _)| k)
205*bb4ee6a4SAndroid Build Coastguard Worker {
206*bb4ee6a4SAndroid Build Coastguard Worker match serial_parameter {
207*bb4ee6a4SAndroid Build Coastguard Worker (SerialHardware::Serial, num) => {
208*bb4ee6a4SAndroid Build Coastguard Worker cmdline
209*bb4ee6a4SAndroid Build Coastguard Worker .insert("console", &format!("ttyS{}", num - 1))
210*bb4ee6a4SAndroid Build Coastguard Worker .map_err(GetSerialCmdlineError::KernelCmdline)?;
211*bb4ee6a4SAndroid Build Coastguard Worker }
212*bb4ee6a4SAndroid Build Coastguard Worker (SerialHardware::VirtioConsole, num) => {
213*bb4ee6a4SAndroid Build Coastguard Worker cmdline
214*bb4ee6a4SAndroid Build Coastguard Worker .insert("console", &format!("hvc{}", num - 1))
215*bb4ee6a4SAndroid Build Coastguard Worker .map_err(GetSerialCmdlineError::KernelCmdline)?;
216*bb4ee6a4SAndroid Build Coastguard Worker }
217*bb4ee6a4SAndroid Build Coastguard Worker (SerialHardware::Debugcon, _) => {}
218*bb4ee6a4SAndroid Build Coastguard Worker }
219*bb4ee6a4SAndroid Build Coastguard Worker }
220*bb4ee6a4SAndroid Build Coastguard Worker
221*bb4ee6a4SAndroid Build Coastguard Worker match serial_parameters
222*bb4ee6a4SAndroid Build Coastguard Worker .iter()
223*bb4ee6a4SAndroid Build Coastguard Worker .filter(|(_, p)| p.earlycon)
224*bb4ee6a4SAndroid Build Coastguard Worker .map(|(k, _)| k)
225*bb4ee6a4SAndroid Build Coastguard Worker .next()
226*bb4ee6a4SAndroid Build Coastguard Worker {
227*bb4ee6a4SAndroid Build Coastguard Worker Some((SerialHardware::Serial, num)) => {
228*bb4ee6a4SAndroid Build Coastguard Worker if let Some(serial_device) = serial_devices.get(*num as usize - 1) {
229*bb4ee6a4SAndroid Build Coastguard Worker cmdline
230*bb4ee6a4SAndroid Build Coastguard Worker .insert(
231*bb4ee6a4SAndroid Build Coastguard Worker "earlycon",
232*bb4ee6a4SAndroid Build Coastguard Worker &format!("uart8250,{},0x{:x}", serial_io_type, serial_device.address),
233*bb4ee6a4SAndroid Build Coastguard Worker )
234*bb4ee6a4SAndroid Build Coastguard Worker .map_err(GetSerialCmdlineError::KernelCmdline)?;
235*bb4ee6a4SAndroid Build Coastguard Worker }
236*bb4ee6a4SAndroid Build Coastguard Worker }
237*bb4ee6a4SAndroid Build Coastguard Worker Some((hw, _num)) => {
238*bb4ee6a4SAndroid Build Coastguard Worker return Err(GetSerialCmdlineError::UnsupportedEarlyconHardware(*hw));
239*bb4ee6a4SAndroid Build Coastguard Worker }
240*bb4ee6a4SAndroid Build Coastguard Worker None => {}
241*bb4ee6a4SAndroid Build Coastguard Worker }
242*bb4ee6a4SAndroid Build Coastguard Worker
243*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
244*bb4ee6a4SAndroid Build Coastguard Worker }
245*bb4ee6a4SAndroid Build Coastguard Worker
246*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
247*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
248*bb4ee6a4SAndroid Build Coastguard Worker use devices::BusType;
249*bb4ee6a4SAndroid Build Coastguard Worker use kernel_cmdline::Cmdline;
250*bb4ee6a4SAndroid Build Coastguard Worker
251*bb4ee6a4SAndroid Build Coastguard Worker use super::*;
252*bb4ee6a4SAndroid Build Coastguard Worker
253*bb4ee6a4SAndroid Build Coastguard Worker #[test]
get_serial_cmdline_default()254*bb4ee6a4SAndroid Build Coastguard Worker fn get_serial_cmdline_default() {
255*bb4ee6a4SAndroid Build Coastguard Worker let mut cmdline = Cmdline::new();
256*bb4ee6a4SAndroid Build Coastguard Worker let mut serial_parameters = BTreeMap::new();
257*bb4ee6a4SAndroid Build Coastguard Worker let io_bus = Bus::new(BusType::Io);
258*bb4ee6a4SAndroid Build Coastguard Worker let evt1_3 = Event::new().unwrap();
259*bb4ee6a4SAndroid Build Coastguard Worker let evt2_4 = Event::new().unwrap();
260*bb4ee6a4SAndroid Build Coastguard Worker
261*bb4ee6a4SAndroid Build Coastguard Worker set_default_serial_parameters(&mut serial_parameters, false);
262*bb4ee6a4SAndroid Build Coastguard Worker let serial_devices = add_serial_devices(
263*bb4ee6a4SAndroid Build Coastguard Worker ProtectionType::Unprotected,
264*bb4ee6a4SAndroid Build Coastguard Worker &io_bus,
265*bb4ee6a4SAndroid Build Coastguard Worker (4, &evt1_3),
266*bb4ee6a4SAndroid Build Coastguard Worker (3, &evt2_4),
267*bb4ee6a4SAndroid Build Coastguard Worker &serial_parameters,
268*bb4ee6a4SAndroid Build Coastguard Worker None,
269*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
270*bb4ee6a4SAndroid Build Coastguard Worker &mut None,
271*bb4ee6a4SAndroid Build Coastguard Worker )
272*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
273*bb4ee6a4SAndroid Build Coastguard Worker get_serial_cmdline(&mut cmdline, &serial_parameters, "io", &serial_devices)
274*bb4ee6a4SAndroid Build Coastguard Worker .expect("get_serial_cmdline failed");
275*bb4ee6a4SAndroid Build Coastguard Worker
276*bb4ee6a4SAndroid Build Coastguard Worker let cmdline_str = cmdline.as_str();
277*bb4ee6a4SAndroid Build Coastguard Worker assert!(cmdline_str.contains("console=ttyS0"));
278*bb4ee6a4SAndroid Build Coastguard Worker }
279*bb4ee6a4SAndroid Build Coastguard Worker
280*bb4ee6a4SAndroid Build Coastguard Worker #[test]
get_serial_cmdline_virtio_console()281*bb4ee6a4SAndroid Build Coastguard Worker fn get_serial_cmdline_virtio_console() {
282*bb4ee6a4SAndroid Build Coastguard Worker let mut cmdline = Cmdline::new();
283*bb4ee6a4SAndroid Build Coastguard Worker let mut serial_parameters = BTreeMap::new();
284*bb4ee6a4SAndroid Build Coastguard Worker let io_bus = Bus::new(BusType::Io);
285*bb4ee6a4SAndroid Build Coastguard Worker let evt1_3 = Event::new().unwrap();
286*bb4ee6a4SAndroid Build Coastguard Worker let evt2_4 = Event::new().unwrap();
287*bb4ee6a4SAndroid Build Coastguard Worker
288*bb4ee6a4SAndroid Build Coastguard Worker // Add a virtio-console device with console=true.
289*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters.insert(
290*bb4ee6a4SAndroid Build Coastguard Worker (SerialHardware::VirtioConsole, 1),
291*bb4ee6a4SAndroid Build Coastguard Worker SerialParameters {
292*bb4ee6a4SAndroid Build Coastguard Worker type_: SerialType::Stdout,
293*bb4ee6a4SAndroid Build Coastguard Worker hardware: SerialHardware::VirtioConsole,
294*bb4ee6a4SAndroid Build Coastguard Worker num: 1,
295*bb4ee6a4SAndroid Build Coastguard Worker console: true,
296*bb4ee6a4SAndroid Build Coastguard Worker stdin: true,
297*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
298*bb4ee6a4SAndroid Build Coastguard Worker },
299*bb4ee6a4SAndroid Build Coastguard Worker );
300*bb4ee6a4SAndroid Build Coastguard Worker
301*bb4ee6a4SAndroid Build Coastguard Worker set_default_serial_parameters(&mut serial_parameters, false);
302*bb4ee6a4SAndroid Build Coastguard Worker let serial_devices = add_serial_devices(
303*bb4ee6a4SAndroid Build Coastguard Worker ProtectionType::Unprotected,
304*bb4ee6a4SAndroid Build Coastguard Worker &io_bus,
305*bb4ee6a4SAndroid Build Coastguard Worker (4, &evt1_3),
306*bb4ee6a4SAndroid Build Coastguard Worker (3, &evt2_4),
307*bb4ee6a4SAndroid Build Coastguard Worker &serial_parameters,
308*bb4ee6a4SAndroid Build Coastguard Worker None,
309*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
310*bb4ee6a4SAndroid Build Coastguard Worker &mut None,
311*bb4ee6a4SAndroid Build Coastguard Worker )
312*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
313*bb4ee6a4SAndroid Build Coastguard Worker get_serial_cmdline(&mut cmdline, &serial_parameters, "io", &serial_devices)
314*bb4ee6a4SAndroid Build Coastguard Worker .expect("get_serial_cmdline failed");
315*bb4ee6a4SAndroid Build Coastguard Worker
316*bb4ee6a4SAndroid Build Coastguard Worker let cmdline_str = cmdline.as_str();
317*bb4ee6a4SAndroid Build Coastguard Worker assert!(cmdline_str.contains("console=hvc0"));
318*bb4ee6a4SAndroid Build Coastguard Worker }
319*bb4ee6a4SAndroid Build Coastguard Worker
320*bb4ee6a4SAndroid Build Coastguard Worker #[test]
get_serial_cmdline_virtio_console_serial_earlycon()321*bb4ee6a4SAndroid Build Coastguard Worker fn get_serial_cmdline_virtio_console_serial_earlycon() {
322*bb4ee6a4SAndroid Build Coastguard Worker let mut cmdline = Cmdline::new();
323*bb4ee6a4SAndroid Build Coastguard Worker let mut serial_parameters = BTreeMap::new();
324*bb4ee6a4SAndroid Build Coastguard Worker let io_bus = Bus::new(BusType::Io);
325*bb4ee6a4SAndroid Build Coastguard Worker let evt1_3 = Event::new().unwrap();
326*bb4ee6a4SAndroid Build Coastguard Worker let evt2_4 = Event::new().unwrap();
327*bb4ee6a4SAndroid Build Coastguard Worker
328*bb4ee6a4SAndroid Build Coastguard Worker // Add a virtio-console device with console=true.
329*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters.insert(
330*bb4ee6a4SAndroid Build Coastguard Worker (SerialHardware::VirtioConsole, 1),
331*bb4ee6a4SAndroid Build Coastguard Worker SerialParameters {
332*bb4ee6a4SAndroid Build Coastguard Worker type_: SerialType::Stdout,
333*bb4ee6a4SAndroid Build Coastguard Worker hardware: SerialHardware::VirtioConsole,
334*bb4ee6a4SAndroid Build Coastguard Worker num: 1,
335*bb4ee6a4SAndroid Build Coastguard Worker console: true,
336*bb4ee6a4SAndroid Build Coastguard Worker stdin: true,
337*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
338*bb4ee6a4SAndroid Build Coastguard Worker },
339*bb4ee6a4SAndroid Build Coastguard Worker );
340*bb4ee6a4SAndroid Build Coastguard Worker
341*bb4ee6a4SAndroid Build Coastguard Worker // Override the default COM1 with an earlycon device.
342*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters.insert(
343*bb4ee6a4SAndroid Build Coastguard Worker (SerialHardware::Serial, 1),
344*bb4ee6a4SAndroid Build Coastguard Worker SerialParameters {
345*bb4ee6a4SAndroid Build Coastguard Worker type_: SerialType::Stdout,
346*bb4ee6a4SAndroid Build Coastguard Worker hardware: SerialHardware::Serial,
347*bb4ee6a4SAndroid Build Coastguard Worker num: 1,
348*bb4ee6a4SAndroid Build Coastguard Worker earlycon: true,
349*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
350*bb4ee6a4SAndroid Build Coastguard Worker },
351*bb4ee6a4SAndroid Build Coastguard Worker );
352*bb4ee6a4SAndroid Build Coastguard Worker
353*bb4ee6a4SAndroid Build Coastguard Worker set_default_serial_parameters(&mut serial_parameters, false);
354*bb4ee6a4SAndroid Build Coastguard Worker let serial_devices = add_serial_devices(
355*bb4ee6a4SAndroid Build Coastguard Worker ProtectionType::Unprotected,
356*bb4ee6a4SAndroid Build Coastguard Worker &io_bus,
357*bb4ee6a4SAndroid Build Coastguard Worker (4, &evt1_3),
358*bb4ee6a4SAndroid Build Coastguard Worker (3, &evt2_4),
359*bb4ee6a4SAndroid Build Coastguard Worker &serial_parameters,
360*bb4ee6a4SAndroid Build Coastguard Worker None,
361*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
362*bb4ee6a4SAndroid Build Coastguard Worker &mut None,
363*bb4ee6a4SAndroid Build Coastguard Worker )
364*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
365*bb4ee6a4SAndroid Build Coastguard Worker get_serial_cmdline(&mut cmdline, &serial_parameters, "io", &serial_devices)
366*bb4ee6a4SAndroid Build Coastguard Worker .expect("get_serial_cmdline failed");
367*bb4ee6a4SAndroid Build Coastguard Worker
368*bb4ee6a4SAndroid Build Coastguard Worker let cmdline_str = cmdline.as_str();
369*bb4ee6a4SAndroid Build Coastguard Worker assert!(cmdline_str.contains("console=hvc0"));
370*bb4ee6a4SAndroid Build Coastguard Worker assert!(cmdline_str.contains("earlycon=uart8250,io,0x3f8"));
371*bb4ee6a4SAndroid Build Coastguard Worker }
372*bb4ee6a4SAndroid Build Coastguard Worker
373*bb4ee6a4SAndroid Build Coastguard Worker #[test]
get_serial_cmdline_virtio_console_invalid_earlycon()374*bb4ee6a4SAndroid Build Coastguard Worker fn get_serial_cmdline_virtio_console_invalid_earlycon() {
375*bb4ee6a4SAndroid Build Coastguard Worker let mut cmdline = Cmdline::new();
376*bb4ee6a4SAndroid Build Coastguard Worker let mut serial_parameters = BTreeMap::new();
377*bb4ee6a4SAndroid Build Coastguard Worker let io_bus = Bus::new(BusType::Io);
378*bb4ee6a4SAndroid Build Coastguard Worker let evt1_3 = Event::new().unwrap();
379*bb4ee6a4SAndroid Build Coastguard Worker let evt2_4 = Event::new().unwrap();
380*bb4ee6a4SAndroid Build Coastguard Worker
381*bb4ee6a4SAndroid Build Coastguard Worker // Try to add a virtio-console device with earlycon=true (unsupported).
382*bb4ee6a4SAndroid Build Coastguard Worker serial_parameters.insert(
383*bb4ee6a4SAndroid Build Coastguard Worker (SerialHardware::VirtioConsole, 1),
384*bb4ee6a4SAndroid Build Coastguard Worker SerialParameters {
385*bb4ee6a4SAndroid Build Coastguard Worker type_: SerialType::Stdout,
386*bb4ee6a4SAndroid Build Coastguard Worker hardware: SerialHardware::VirtioConsole,
387*bb4ee6a4SAndroid Build Coastguard Worker num: 1,
388*bb4ee6a4SAndroid Build Coastguard Worker earlycon: true,
389*bb4ee6a4SAndroid Build Coastguard Worker stdin: true,
390*bb4ee6a4SAndroid Build Coastguard Worker ..Default::default()
391*bb4ee6a4SAndroid Build Coastguard Worker },
392*bb4ee6a4SAndroid Build Coastguard Worker );
393*bb4ee6a4SAndroid Build Coastguard Worker
394*bb4ee6a4SAndroid Build Coastguard Worker set_default_serial_parameters(&mut serial_parameters, false);
395*bb4ee6a4SAndroid Build Coastguard Worker let serial_devices = add_serial_devices(
396*bb4ee6a4SAndroid Build Coastguard Worker ProtectionType::Unprotected,
397*bb4ee6a4SAndroid Build Coastguard Worker &io_bus,
398*bb4ee6a4SAndroid Build Coastguard Worker (4, &evt1_3),
399*bb4ee6a4SAndroid Build Coastguard Worker (3, &evt2_4),
400*bb4ee6a4SAndroid Build Coastguard Worker &serial_parameters,
401*bb4ee6a4SAndroid Build Coastguard Worker None,
402*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(feature = "swap")]
403*bb4ee6a4SAndroid Build Coastguard Worker &mut None,
404*bb4ee6a4SAndroid Build Coastguard Worker )
405*bb4ee6a4SAndroid Build Coastguard Worker .unwrap();
406*bb4ee6a4SAndroid Build Coastguard Worker get_serial_cmdline(&mut cmdline, &serial_parameters, "io", &serial_devices)
407*bb4ee6a4SAndroid Build Coastguard Worker .expect_err("get_serial_cmdline succeeded");
408*bb4ee6a4SAndroid Build Coastguard Worker }
409*bb4ee6a4SAndroid Build Coastguard Worker }
410