diff options
author | Trent Begin <tbegin@google.com> | 2019-04-17 13:51:25 -0600 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-05-15 13:36:25 -0700 |
commit | 17ccaadc24b7eaeedac578b87ddca4491c48b25f (patch) | |
tree | 653850131a0dc267b16aa7f60ded7306f146608d /devices/src/serial.rs | |
parent | 6868c0a72ffc556fcd9c48006b673f5774d0d35b (diff) | |
download | crosvm-17ccaadc24b7eaeedac578b87ddca4491c48b25f.tar crosvm-17ccaadc24b7eaeedac578b87ddca4491c48b25f.tar.gz crosvm-17ccaadc24b7eaeedac578b87ddca4491c48b25f.tar.bz2 crosvm-17ccaadc24b7eaeedac578b87ddca4491c48b25f.tar.lz crosvm-17ccaadc24b7eaeedac578b87ddca4491c48b25f.tar.xz crosvm-17ccaadc24b7eaeedac578b87ddca4491c48b25f.tar.zst crosvm-17ccaadc24b7eaeedac578b87ddca4491c48b25f.zip |
crosvm: add cmdline flags for configuring serial outputs in guest machine
This change allows an output to be set for each serial device for a guest machine (stdout, syslog, or sink). BUG=chromium:953983 TEST=FEATURES=test emerge-sarien crosvm; cd sys_util; cargo test; ./build_test; manual testing on x86_64 and aarch_64 Change-Id: I9e7fcb0b296c0f8a5aa8d54b1a74ae801f6badc8 Reviewed-on: https://chromium-review.googlesource.com/1572813 Commit-Ready: Trent Begin <tbegin@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Tested-by: Trent Begin <tbegin@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'devices/src/serial.rs')
-rw-r--r-- | devices/src/serial.rs | 148 |
1 files changed, 146 insertions, 2 deletions
diff --git a/devices/src/serial.rs b/devices/src/serial.rs index 7cb7611..4d12512 100644 --- a/devices/src/serial.rs +++ b/devices/src/serial.rs @@ -3,9 +3,12 @@ // found in the LICENSE file. use std::collections::VecDeque; -use std::io; +use std::fmt::{self, Display}; +use std::io::{self, stdout}; +use std::path::PathBuf; +use std::str::FromStr; -use sys_util::{error, EventFd, Result}; +use sys_util::{error, syslog, EventFd, Result}; use crate::BusDevice; @@ -44,6 +47,147 @@ const DEFAULT_MODEM_CONTROL: u8 = 0x8; // Auxiliary output 2 const DEFAULT_MODEM_STATUS: u8 = 0x20 | 0x10 | 0x80; // data ready, clear to send, carrier detect const DEFAULT_BAUD_DIVISOR: u16 = 12; // 9600 bps +#[derive(Debug)] +pub enum Error { + CloneEventFd(sys_util::Error), + InvalidSerialType(String), + Unimplemented(SerialType), +} + +impl Display for Error { + #[remain::check] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use self::Error::*; + + #[sorted] + match self { + CloneEventFd(e) => write!(f, "unable to clone an EventFd: {}", e), + InvalidSerialType(e) => write!(f, "invalid serial type: {}", e), + Unimplemented(e) => write!(f, "serial device type {} not implemented", e.to_string()), + } + } +} + +/// Enum for possible type of serial devices +#[derive(Debug)] +pub enum SerialType { + File, // NOT IMPLEMENTED + Stdout, + Sink, + Syslog, + UnixSocket, // NOT IMPLEMENTED +} + +impl Display for SerialType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let s = match &self { + SerialType::File => "File".to_string(), + SerialType::Stdout => "Stdout".to_string(), + SerialType::Sink => "Sink".to_string(), + SerialType::Syslog => "Syslog".to_string(), + SerialType::UnixSocket => "UnixSocket".to_string(), + }; + + write!(f, "{}", s) + } +} + +impl FromStr for SerialType { + type Err = Error; + fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { + match s { + "file" | "File" => return Ok(SerialType::File), + "stdout" | "Stdout" => return Ok(SerialType::Stdout), + "sink" | "Sink" => return Ok(SerialType::Sink), + "syslog" | "Syslog" => return Ok(SerialType::Syslog), + "unix" | "UnixSocket" => return Ok(SerialType::UnixSocket), + _ => Err(Error::InvalidSerialType(s.to_string())), + } + } +} + +/// Holds the parameters for a serial device +#[derive(Debug)] +pub struct SerialParameters { + pub type_: SerialType, + pub path: Option<PathBuf>, + pub num: u8, + pub console: bool, +} + +impl SerialParameters { + /// Helper function to create a serial device from the defined parameters. + /// + /// # Arguments + /// * `evt_fd` - eventfd used for interrupt events + pub fn create_serial_device(&self, evt_fd: &EventFd) -> std::result::Result<Serial, Error> { + match self.type_ { + SerialType::Stdout => Ok(Serial::new_out( + evt_fd.try_clone().map_err(Error::CloneEventFd)?, + Box::new(stdout()), + )), + SerialType::Sink => Ok(Serial::new_sink( + evt_fd.try_clone().map_err(Error::CloneEventFd)?, + )), + SerialType::Syslog => Ok(Serial::new_out( + evt_fd.try_clone().map_err(Error::CloneEventFd)?, + Box::new(syslog::Syslogger::new( + syslog::Priority::Info, + syslog::Facility::Daemon, + )), + )), + SerialType::File => Err(Error::Unimplemented(SerialType::File)), + SerialType::UnixSocket => Err(Error::Unimplemented(SerialType::UnixSocket)), + } + } +} + +// Structure for holding the default configuration of the serial devices. +pub const DEFAULT_SERIAL_PARAMS: [SerialParameters; 4] = [ + SerialParameters { + type_: SerialType::Stdout, + path: None, + num: 1, + console: true, + }, + SerialParameters { + type_: SerialType::Sink, + path: None, + num: 2, + console: false, + }, + SerialParameters { + type_: SerialType::Sink, + path: None, + num: 3, + console: false, + }, + SerialParameters { + type_: SerialType::Sink, + path: None, + num: 4, + console: false, + }, +]; + +/// Address for Serial ports in x86 +pub const SERIAL_ADDR: [u64; 4] = [0x3f8, 0x2f8, 0x3e8, 0x2e8]; + +/// String representations of serial devices +pub const SERIAL_TTY_STRINGS: [&str; 4] = ["ttyS0", "ttyS1", "ttyS2", "ttyS3"]; + +/// Helper function to get the tty string of a serial device based on the port number. Will default +/// to ttyS0 if an invalid number is given. +pub fn get_serial_tty_string(stdio_serial_num: u8) -> String { + match stdio_serial_num { + 1 => SERIAL_TTY_STRINGS[0].to_string(), + 2 => SERIAL_TTY_STRINGS[1].to_string(), + 3 => SERIAL_TTY_STRINGS[2].to_string(), + 4 => SERIAL_TTY_STRINGS[3].to_string(), + _ => SERIAL_TTY_STRINGS[0].to_string(), + } +} + /// Emulates serial COM ports commonly seen on x86 I/O ports 0x3f8/0x2f8/0x3e8/0x2e8. /// /// This can optionally write the guest's output to a Write trait object. To send input to the |