mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-25 05:03:05 +00:00
arch, devices: move serial creation to arch
Split the serial code into two parts: - Configuration and setup: arch/src/serial.rs - Serial device emulation: devices/src/serial.rs No change in functionality - this is just preparation for generalizing the command line parsing/setup code so that it can be used with virtio console devices as well. BUG=chromium:1059924 TEST=emerge-nami crosvm TEST=emerge-kevin crosvm Change-Id: I0aaf9dd6f8096eac4a17077ab5bf569f57d64ff5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2127319 Reviewed-by: Dylan Reid <dgreid@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
2c1417b43a
commit
fbd6122f0b
10 changed files with 291 additions and 282 deletions
|
@ -10,7 +10,8 @@ use arch::fdt::{
|
|||
begin_node, end_node, finish_fdt, generate_prop32, generate_prop64, property, property_cstring,
|
||||
property_null, property_string, property_u32, property_u64, start_fdt, Error, Result,
|
||||
};
|
||||
use devices::{PciInterruptPin, SERIAL_ADDR};
|
||||
use arch::SERIAL_ADDR;
|
||||
use devices::PciInterruptPin;
|
||||
use sys_util::{GuestAddress, GuestMemory};
|
||||
|
||||
// This is the start of DRAM in the physical address space.
|
||||
|
|
|
@ -11,11 +11,8 @@ use std::io;
|
|||
use std::os::unix::io::FromRawFd;
|
||||
use std::sync::Arc;
|
||||
|
||||
use arch::{RunnableLinuxVm, VmComponents, VmImage};
|
||||
use devices::{
|
||||
get_serial_tty_string, Bus, BusError, PciConfigMmio, PciDevice, PciInterruptPin,
|
||||
SerialParameters,
|
||||
};
|
||||
use arch::{get_serial_tty_string, RunnableLinuxVm, SerialParameters, VmComponents, VmImage};
|
||||
use devices::{Bus, BusError, PciConfigMmio, PciDevice, PciInterruptPin};
|
||||
use io_jail::Minijail;
|
||||
use remain::sorted;
|
||||
use resources::SystemAllocator;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
pub mod android;
|
||||
pub mod fdt;
|
||||
pub mod pstore;
|
||||
pub mod serial;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::error::Error as StdError;
|
||||
|
@ -19,7 +20,6 @@ use devices::split_irqchip_common::GsiRelay;
|
|||
use devices::virtio::VirtioDevice;
|
||||
use devices::{
|
||||
Bus, BusDevice, BusError, PciDevice, PciDeviceError, PciInterruptPin, PciRoot, ProxyDevice,
|
||||
SerialParameters, DEFAULT_SERIAL_PARAMS, SERIAL_ADDR,
|
||||
};
|
||||
use io_jail::Minijail;
|
||||
use kvm::{IoeventAddress, Kvm, Vcpu, Vm};
|
||||
|
@ -28,6 +28,10 @@ use sync::Mutex;
|
|||
use sys_util::{syslog, EventFd, GuestAddress, GuestMemory, GuestMemoryError};
|
||||
use vm_control::VmIrqRequestSocket;
|
||||
|
||||
pub use serial::{
|
||||
add_serial_devices, get_serial_tty_string, SerialParameters, SerialType, SERIAL_ADDR,
|
||||
};
|
||||
|
||||
pub enum VmImage {
|
||||
Kernel(File),
|
||||
Bios(File),
|
||||
|
@ -119,7 +123,7 @@ pub enum DeviceRegistrationError {
|
|||
// Unable to create a pipe.
|
||||
CreatePipe(sys_util::Error),
|
||||
// Unable to create serial device from serial parameters
|
||||
CreateSerialDevice(devices::SerialError),
|
||||
CreateSerialDevice(serial::Error),
|
||||
/// Could not clone an event fd.
|
||||
EventFdClone(sys_util::Error),
|
||||
/// Could not create an event fd.
|
||||
|
@ -258,70 +262,6 @@ pub fn generate_pci_root(
|
|||
Ok((root, pci_irqs, pid_labels))
|
||||
}
|
||||
|
||||
/// Adds serial devices to the provided bus based on the serial parameters given. Returns the serial
|
||||
/// port number and serial device to be used for stdout if defined.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `io_bus` - Bus to add the devices to
|
||||
/// * `com_evt_1_3` - eventfd for com1 and com3
|
||||
/// * `com_evt_1_4` - eventfd for com2 and com4
|
||||
/// * `io_bus` - Bus to add the devices to
|
||||
/// * `serial_parameters` - definitions of serial parameter configuationis. If a setting is not
|
||||
/// provided for a port, then it will use the default configuation.
|
||||
pub fn add_serial_devices(
|
||||
io_bus: &mut Bus,
|
||||
com_evt_1_3: &EventFd,
|
||||
com_evt_2_4: &EventFd,
|
||||
serial_parameters: &BTreeMap<u8, SerialParameters>,
|
||||
serial_jail: Option<Minijail>,
|
||||
) -> Result<Option<u8>, DeviceRegistrationError> {
|
||||
let mut stdio_serial_num = None;
|
||||
|
||||
for x in 0..=3 {
|
||||
let com_evt = match x {
|
||||
0 => com_evt_1_3,
|
||||
1 => com_evt_2_4,
|
||||
2 => com_evt_1_3,
|
||||
3 => com_evt_2_4,
|
||||
_ => com_evt_1_3,
|
||||
};
|
||||
|
||||
let param = serial_parameters
|
||||
.get(&(x + 1))
|
||||
.unwrap_or(&DEFAULT_SERIAL_PARAMS[x as usize]);
|
||||
|
||||
if param.console {
|
||||
stdio_serial_num = Some(x + 1);
|
||||
}
|
||||
|
||||
let mut preserved_fds = Vec::new();
|
||||
let com = param
|
||||
.create_serial_device(&com_evt, &mut preserved_fds)
|
||||
.map_err(DeviceRegistrationError::CreateSerialDevice)?;
|
||||
|
||||
match serial_jail.as_ref() {
|
||||
Some(jail) => {
|
||||
let com = Arc::new(Mutex::new(
|
||||
ProxyDevice::new(com, &jail, preserved_fds)
|
||||
.map_err(DeviceRegistrationError::ProxyDeviceCreation)?,
|
||||
));
|
||||
io_bus
|
||||
.insert(com.clone(), SERIAL_ADDR[x as usize], 0x8, false)
|
||||
.unwrap();
|
||||
}
|
||||
None => {
|
||||
let com = Arc::new(Mutex::new(com));
|
||||
io_bus
|
||||
.insert(com.clone(), SERIAL_ADDR[x as usize], 0x8, false)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(stdio_serial_num)
|
||||
}
|
||||
|
||||
/// Errors for image loading.
|
||||
#[derive(Debug)]
|
||||
pub enum LoadImageError {
|
||||
|
|
269
arch/src/serial.rs
Normal file
269
arch/src/serial.rs
Normal file
|
@ -0,0 +1,269 @@
|
|||
// Copyright 2020 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::{self, Display};
|
||||
use std::fs::File;
|
||||
use std::io::{self, stdin, stdout};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use devices::{Bus, ProxyDevice, Serial};
|
||||
use io_jail::Minijail;
|
||||
use sync::Mutex;
|
||||
use sys_util::{read_raw_stdin, syslog, EventFd};
|
||||
|
||||
use crate::DeviceRegistrationError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
CloneEventFd(sys_util::Error),
|
||||
FileError(std::io::Error),
|
||||
InvalidSerialType(String),
|
||||
PathRequired,
|
||||
Unimplemented(SerialType),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::Error::*;
|
||||
|
||||
match self {
|
||||
CloneEventFd(e) => write!(f, "unable to clone an EventFd: {}", e),
|
||||
FileError(e) => write!(f, "unable to open/create file: {}", e),
|
||||
InvalidSerialType(e) => write!(f, "invalid serial type: {}", e),
|
||||
PathRequired => write!(f, "serial device type file requires a path"),
|
||||
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,
|
||||
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" => Ok(SerialType::File),
|
||||
"stdout" | "Stdout" => Ok(SerialType::Stdout),
|
||||
"sink" | "Sink" => Ok(SerialType::Sink),
|
||||
"syslog" | "Syslog" => Ok(SerialType::Syslog),
|
||||
"unix" | "UnixSocket" => 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 input: Option<PathBuf>,
|
||||
pub num: u8,
|
||||
pub console: bool,
|
||||
pub stdin: bool,
|
||||
}
|
||||
|
||||
impl SerialParameters {
|
||||
/// Helper function to create a serial device from the defined parameters.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `evt_fd` - eventfd used for interrupt events
|
||||
/// * `keep_fds` - Vector of FDs required by this device if it were sandboxed in a child
|
||||
/// process. `evt_fd` will always be added to this vector by this function.
|
||||
pub fn create_serial_device(
|
||||
&self,
|
||||
evt_fd: &EventFd,
|
||||
keep_fds: &mut Vec<RawFd>,
|
||||
) -> std::result::Result<Serial, Error> {
|
||||
let evt_fd = evt_fd.try_clone().map_err(Error::CloneEventFd)?;
|
||||
keep_fds.push(evt_fd.as_raw_fd());
|
||||
let input: Option<Box<dyn io::Read + Send>> = if let Some(input_path) = &self.input {
|
||||
let input_file = File::open(input_path.as_path()).map_err(Error::FileError)?;
|
||||
keep_fds.push(input_file.as_raw_fd());
|
||||
Some(Box::new(input_file))
|
||||
} else if self.stdin {
|
||||
keep_fds.push(stdin().as_raw_fd());
|
||||
// This wrapper is used in place of the libstd native version because we don't want
|
||||
// buffering for stdin.
|
||||
struct StdinWrapper;
|
||||
impl io::Read for StdinWrapper {
|
||||
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
|
||||
read_raw_stdin(out).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
Some(Box::new(StdinWrapper))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match self.type_ {
|
||||
SerialType::Stdout => {
|
||||
keep_fds.push(stdout().as_raw_fd());
|
||||
Ok(Serial::new(evt_fd, input, Some(Box::new(stdout()))))
|
||||
}
|
||||
SerialType::Sink => Ok(Serial::new(evt_fd, input, None)),
|
||||
SerialType::Syslog => {
|
||||
syslog::push_fds(keep_fds);
|
||||
Ok(Serial::new(
|
||||
evt_fd,
|
||||
input,
|
||||
Some(Box::new(syslog::Syslogger::new(
|
||||
syslog::Priority::Info,
|
||||
syslog::Facility::Daemon,
|
||||
))),
|
||||
))
|
||||
}
|
||||
SerialType::File => match &self.path {
|
||||
Some(path) => {
|
||||
let file = File::create(path.as_path()).map_err(Error::FileError)?;
|
||||
keep_fds.push(file.as_raw_fd());
|
||||
Ok(Serial::new(evt_fd, input, Some(Box::new(file))))
|
||||
}
|
||||
_ => Err(Error::PathRequired),
|
||||
},
|
||||
SerialType::UnixSocket => Err(Error::Unimplemented(SerialType::UnixSocket)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Structure for holding the default configuration of the serial devices.
|
||||
const DEFAULT_SERIAL_PARAMS: [SerialParameters; 4] = [
|
||||
SerialParameters {
|
||||
type_: SerialType::Stdout,
|
||||
path: None,
|
||||
input: None,
|
||||
num: 1,
|
||||
console: true,
|
||||
stdin: true,
|
||||
},
|
||||
SerialParameters {
|
||||
type_: SerialType::Sink,
|
||||
path: None,
|
||||
input: None,
|
||||
num: 2,
|
||||
console: false,
|
||||
stdin: false,
|
||||
},
|
||||
SerialParameters {
|
||||
type_: SerialType::Sink,
|
||||
path: None,
|
||||
input: None,
|
||||
num: 3,
|
||||
console: false,
|
||||
stdin: false,
|
||||
},
|
||||
SerialParameters {
|
||||
type_: SerialType::Sink,
|
||||
path: None,
|
||||
input: None,
|
||||
num: 4,
|
||||
console: false,
|
||||
stdin: false,
|
||||
},
|
||||
];
|
||||
|
||||
/// Address for Serial ports in x86
|
||||
pub const SERIAL_ADDR: [u64; 4] = [0x3f8, 0x2f8, 0x3e8, 0x2e8];
|
||||
|
||||
/// String representations of serial devices
|
||||
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 {
|
||||
stdio_serial_num
|
||||
.checked_sub(1)
|
||||
.and_then(|i| SERIAL_TTY_STRINGS.get(i as usize))
|
||||
.unwrap_or(&SERIAL_TTY_STRINGS[0])
|
||||
.to_string()
|
||||
}
|
||||
|
||||
/// Adds serial devices to the provided bus based on the serial parameters given. Returns the serial
|
||||
/// port number and serial device to be used for stdout if defined.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `io_bus` - Bus to add the devices to
|
||||
/// * `com_evt_1_3` - eventfd for com1 and com3
|
||||
/// * `com_evt_1_4` - eventfd for com2 and com4
|
||||
/// * `io_bus` - Bus to add the devices to
|
||||
/// * `serial_parameters` - definitions of serial parameter configuationis. If a setting is not
|
||||
/// provided for a port, then it will use the default configuation.
|
||||
pub fn add_serial_devices(
|
||||
io_bus: &mut Bus,
|
||||
com_evt_1_3: &EventFd,
|
||||
com_evt_2_4: &EventFd,
|
||||
serial_parameters: &BTreeMap<u8, SerialParameters>,
|
||||
serial_jail: Option<Minijail>,
|
||||
) -> Result<Option<u8>, DeviceRegistrationError> {
|
||||
let mut stdio_serial_num = None;
|
||||
|
||||
for x in 0..=3 {
|
||||
let com_evt = match x {
|
||||
0 => com_evt_1_3,
|
||||
1 => com_evt_2_4,
|
||||
2 => com_evt_1_3,
|
||||
3 => com_evt_2_4,
|
||||
_ => com_evt_1_3,
|
||||
};
|
||||
|
||||
let param = serial_parameters
|
||||
.get(&(x + 1))
|
||||
.unwrap_or(&DEFAULT_SERIAL_PARAMS[x as usize]);
|
||||
|
||||
if param.console {
|
||||
stdio_serial_num = Some(x + 1);
|
||||
}
|
||||
|
||||
let mut preserved_fds = Vec::new();
|
||||
let com = param
|
||||
.create_serial_device(&com_evt, &mut preserved_fds)
|
||||
.map_err(DeviceRegistrationError::CreateSerialDevice)?;
|
||||
|
||||
match serial_jail.as_ref() {
|
||||
Some(jail) => {
|
||||
let com = Arc::new(Mutex::new(
|
||||
ProxyDevice::new(com, &jail, preserved_fds)
|
||||
.map_err(DeviceRegistrationError::ProxyDeviceCreation)?,
|
||||
));
|
||||
io_bus
|
||||
.insert(com.clone(), SERIAL_ADDR[x as usize], 0x8, false)
|
||||
.unwrap();
|
||||
}
|
||||
None => {
|
||||
let com = Arc::new(Mutex::new(com));
|
||||
io_bus
|
||||
.insert(com.clone(), SERIAL_ADDR[x as usize], 0x8, false)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(stdio_serial_num)
|
||||
}
|
|
@ -38,10 +38,7 @@ pub use self::pit::{Pit, PitError};
|
|||
pub use self::pl030::Pl030;
|
||||
pub use self::proxy::Error as ProxyError;
|
||||
pub use self::proxy::ProxyDevice;
|
||||
pub use self::serial::Error as SerialError;
|
||||
pub use self::serial::{
|
||||
get_serial_tty_string, Serial, SerialParameters, SerialType, DEFAULT_SERIAL_PARAMS, SERIAL_ADDR,
|
||||
};
|
||||
pub use self::serial::Serial;
|
||||
pub use self::usb::host_backend::host_backend_device_provider::HostBackendDeviceProvider;
|
||||
pub use self::usb::xhci::xhci_controller::XhciController;
|
||||
pub use self::vfio::{VfioContainer, VfioDevice};
|
||||
|
|
|
@ -3,18 +3,13 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt::{self, Display};
|
||||
use std::fs::File;
|
||||
use std::io::{self, stdin, stdout, Read, Write};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
use std::io::{self, Write};
|
||||
use std::sync::atomic::{AtomicU8, Ordering};
|
||||
use std::sync::mpsc::{channel, Receiver, TryRecvError};
|
||||
use std::sync::Arc;
|
||||
use std::thread::{self};
|
||||
|
||||
use sys_util::{error, read_raw_stdin, syslog, EventFd, Result};
|
||||
use sys_util::{error, EventFd, Result};
|
||||
|
||||
use crate::BusDevice;
|
||||
|
||||
|
@ -62,196 +57,6 @@ const DEFAULT_MODEM_CONTROL: u8 = MCR_OUT2_BIT;
|
|||
const DEFAULT_MODEM_STATUS: u8 = MSR_DSR_BIT | MSR_CTS_BIT | MSR_DCD_BIT;
|
||||
const DEFAULT_BAUD_DIVISOR: u16 = 12; // 9600 bps
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
CloneEventFd(sys_util::Error),
|
||||
InvalidSerialType(String),
|
||||
PathRequired,
|
||||
FileError(std::io::Error),
|
||||
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),
|
||||
FileError(e) => write!(f, "Unable to open/create file: {}", e),
|
||||
InvalidSerialType(e) => write!(f, "invalid serial type: {}", e),
|
||||
PathRequired => write!(f, "serial device type file requires a path"),
|
||||
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,
|
||||
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" => Ok(SerialType::File),
|
||||
"stdout" | "Stdout" => Ok(SerialType::Stdout),
|
||||
"sink" | "Sink" => Ok(SerialType::Sink),
|
||||
"syslog" | "Syslog" => Ok(SerialType::Syslog),
|
||||
"unix" | "UnixSocket" => 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 input: Option<PathBuf>,
|
||||
pub num: u8,
|
||||
pub console: bool,
|
||||
pub stdin: bool,
|
||||
}
|
||||
|
||||
impl SerialParameters {
|
||||
/// Helper function to create a serial device from the defined parameters.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `evt_fd` - eventfd used for interrupt events
|
||||
/// * `keep_fds` - Vector of FDs required by this device if it were sandboxed in a child
|
||||
/// process. `evt_fd` will always be added to this vector by this function.
|
||||
pub fn create_serial_device(
|
||||
&self,
|
||||
evt_fd: &EventFd,
|
||||
keep_fds: &mut Vec<RawFd>,
|
||||
) -> std::result::Result<Serial, Error> {
|
||||
let evt_fd = evt_fd.try_clone().map_err(Error::CloneEventFd)?;
|
||||
keep_fds.push(evt_fd.as_raw_fd());
|
||||
let input: Option<Box<dyn io::Read + Send>> = if let Some(input_path) = &self.input {
|
||||
let input_file = File::open(input_path.as_path()).map_err(Error::FileError)?;
|
||||
keep_fds.push(input_file.as_raw_fd());
|
||||
Some(Box::new(input_file))
|
||||
} else if self.stdin {
|
||||
keep_fds.push(stdin().as_raw_fd());
|
||||
// This wrapper is used in place of the libstd native version because we don't want
|
||||
// buffering for stdin.
|
||||
struct StdinWrapper;
|
||||
impl io::Read for StdinWrapper {
|
||||
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
|
||||
read_raw_stdin(out).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
Some(Box::new(StdinWrapper))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match self.type_ {
|
||||
SerialType::Stdout => {
|
||||
keep_fds.push(stdout().as_raw_fd());
|
||||
Ok(Serial::new(evt_fd, input, Some(Box::new(stdout()))))
|
||||
}
|
||||
SerialType::Sink => Ok(Serial::new(evt_fd, input, None)),
|
||||
SerialType::Syslog => {
|
||||
syslog::push_fds(keep_fds);
|
||||
Ok(Serial::new(
|
||||
evt_fd,
|
||||
input,
|
||||
Some(Box::new(syslog::Syslogger::new(
|
||||
syslog::Priority::Info,
|
||||
syslog::Facility::Daemon,
|
||||
))),
|
||||
))
|
||||
}
|
||||
SerialType::File => match &self.path {
|
||||
Some(path) => {
|
||||
let file = File::create(path.as_path()).map_err(Error::FileError)?;
|
||||
keep_fds.push(file.as_raw_fd());
|
||||
Ok(Serial::new(evt_fd, input, Some(Box::new(file))))
|
||||
}
|
||||
_ => Err(Error::PathRequired),
|
||||
},
|
||||
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,
|
||||
input: None,
|
||||
num: 1,
|
||||
console: true,
|
||||
stdin: true,
|
||||
},
|
||||
SerialParameters {
|
||||
type_: SerialType::Sink,
|
||||
path: None,
|
||||
input: None,
|
||||
num: 2,
|
||||
console: false,
|
||||
stdin: false,
|
||||
},
|
||||
SerialParameters {
|
||||
type_: SerialType::Sink,
|
||||
path: None,
|
||||
input: None,
|
||||
num: 3,
|
||||
console: false,
|
||||
stdin: false,
|
||||
},
|
||||
SerialParameters {
|
||||
type_: SerialType::Sink,
|
||||
path: None,
|
||||
input: None,
|
||||
num: 4,
|
||||
console: false,
|
||||
stdin: 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
|
||||
|
@ -277,7 +82,7 @@ pub struct Serial {
|
|||
}
|
||||
|
||||
impl Serial {
|
||||
fn new(
|
||||
pub fn new(
|
||||
interrupt_evt: EventFd,
|
||||
input: Option<Box<dyn io::Read + Send>>,
|
||||
out: Option<Box<dyn io::Write + Send>>,
|
||||
|
|
|
@ -16,11 +16,11 @@ use std::os::unix::io::RawFd;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
|
||||
use arch::Pstore;
|
||||
use arch::{Pstore, SerialParameters};
|
||||
use devices::virtio::fs::passthrough;
|
||||
#[cfg(feature = "gpu")]
|
||||
use devices::virtio::gpu::GpuParameters;
|
||||
use devices::{Ac97Parameters, SerialParameters};
|
||||
use devices::Ac97Parameters;
|
||||
use libc::{getegid, geteuid};
|
||||
|
||||
static SECCOMP_POLICY_DIR: &str = "/usr/share/policy/crosvm";
|
||||
|
|
|
@ -17,7 +17,7 @@ use std::string::String;
|
|||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
||||
use arch::Pstore;
|
||||
use arch::{Pstore, SerialParameters, SerialType};
|
||||
use audio_streams::StreamEffect;
|
||||
use crosvm::{
|
||||
argument::{self, print_help, set_arguments, Argument},
|
||||
|
@ -25,7 +25,7 @@ use crosvm::{
|
|||
};
|
||||
#[cfg(feature = "gpu")]
|
||||
use devices::virtio::gpu::{GpuMode, GpuParameters};
|
||||
use devices::{Ac97Backend, Ac97Parameters, SerialParameters, SerialType};
|
||||
use devices::{Ac97Backend, Ac97Parameters};
|
||||
use disk::QcowFile;
|
||||
use msg_socket::{MsgReceiver, MsgSender, MsgSocket};
|
||||
use sys_util::{
|
||||
|
|
|
@ -13,8 +13,8 @@ use std::sync::Once;
|
|||
|
||||
use libc::{cpu_set_t, sched_getaffinity};
|
||||
|
||||
use arch::{SerialParameters, SerialType};
|
||||
use crosvm::{linux, Config, Executable};
|
||||
use devices::{SerialParameters, SerialType};
|
||||
use sys_util::syslog;
|
||||
|
||||
const CHROOT_KERNEL_PATH: &str = "/mnt/host/source/src/third_party/kernel/v4.19/";
|
||||
|
|
|
@ -54,11 +54,11 @@ use std::mem;
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::bootparam::boot_params;
|
||||
use arch::{RunnableLinuxVm, VmComponents, VmImage};
|
||||
use arch::{get_serial_tty_string, RunnableLinuxVm, SerialParameters, VmComponents, VmImage};
|
||||
use devices::split_irqchip_common::GsiRelay;
|
||||
use devices::{
|
||||
get_serial_tty_string, Ioapic, PciConfigIo, PciDevice, PciInterruptPin, Pic, SerialParameters,
|
||||
IOAPIC_BASE_ADDRESS, IOAPIC_MEM_LENGTH_BYTES,
|
||||
Ioapic, PciConfigIo, PciDevice, PciInterruptPin, Pic, IOAPIC_BASE_ADDRESS,
|
||||
IOAPIC_MEM_LENGTH_BYTES,
|
||||
};
|
||||
use io_jail::Minijail;
|
||||
use kvm::*;
|
||||
|
|
Loading…
Reference in a new issue