From 1e26230f3a490a7955d2ea9fe7855af5498ced70 Mon Sep 17 00:00:00 2001 From: "Jorge E. Moreira" Date: Thu, 1 Aug 2019 14:40:03 -0700 Subject: Allow to connect standard input to a serial port other than the guest console Before this change, setting console=true on a serial port caused that port to be the one connected to the crosvm process' standard input. By adding an extra 'stdin' argument to the serial parameters it's possible to make those concepts independent. Just as with the console argument, stdin defaults to serial port 1 (ttyS0) when not provided and it's possible to set no serial port connected to stdin (or set as the console) by defining the first serial port without the stdin (console) argument. BUG=b/138616941 TEST=boot debian guest in debian host, boot cuttlefish in debian host Change-Id: I7273e6860218521073df93a4ad71e31c7da522a5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1731139 Reviewed-by: Dylan Reid Reviewed-by: Zach Reizner Auto-Submit: Jorge Moreira Broche Tested-by: kokoro Commit-Queue: Zach Reizner --- arch/src/lib.rs | 3 +++ devices/src/serial.rs | 5 +++++ src/main.rs | 30 ++++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/arch/src/lib.rs b/arch/src/lib.rs index 71e4327..28f1168 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -271,6 +271,9 @@ pub fn add_serial_devices( if param.console { stdio_serial_num = Some(x + 1); + } + + if param.stdin { stdio_serial = Some(com.clone()); } } diff --git a/devices/src/serial.rs b/devices/src/serial.rs index 0bf5642..5ecefd7 100644 --- a/devices/src/serial.rs +++ b/devices/src/serial.rs @@ -127,6 +127,7 @@ pub struct SerialParameters { pub path: Option, pub num: u8, pub console: bool, + pub stdin: bool, } impl SerialParameters { @@ -169,24 +170,28 @@ pub const DEFAULT_SERIAL_PARAMS: [SerialParameters; 4] = [ path: None, num: 1, console: true, + stdin: true, }, SerialParameters { type_: SerialType::Sink, path: None, num: 2, console: false, + stdin: false, }, SerialParameters { type_: SerialType::Sink, path: None, num: 3, console: false, + stdin: false, }, SerialParameters { type_: SerialType::Sink, path: None, num: 4, console: false, + stdin: false, }, ]; diff --git a/src/main.rs b/src/main.rs index 81f20a7..78dfbf2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -251,6 +251,7 @@ fn parse_serial_options(s: &str) -> argument::Result { path: None, num: 1, console: false, + stdin: false, }; let opts = s @@ -285,6 +286,11 @@ fn parse_serial_options(s: &str) -> argument::Result { )) })? } + "stdin" => { + serial_setting.stdin = v.parse::().map_err(|e| { + argument::Error::Syntax(format!("serial device stdin is not parseable: {}", e)) + })? + } "path" => serial_setting.path = Some(PathBuf::from(v)), _ => { return Err(argument::Error::UnknownArgument(format!( @@ -409,6 +415,15 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: } } + if serial_params.stdin { + if let Some(previous_stdin) = cfg.serial_parameters.values().find(|sp| sp.stdin) { + return Err(argument::Error::TooManyArguments(format!( + "serial device {} already connected to standard input", + previous_stdin.num + ))); + } + } + cfg.serial_parameters.insert(num, serial_params); } "syslog-tag" => { @@ -840,13 +855,14 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> { Argument::flag("cras-capture", "Enable capturing audio from CRAS server to the cras-audio device"), Argument::flag("null-audio", "Add an audio device to the VM that plays samples to /dev/null"), Argument::value("serial", - "type=TYPE,[num=NUM,path=PATH,console]", + "type=TYPE,[num=NUM,path=PATH,console,stdin]", "Comma seperated key=value pairs for setting up serial devices. Can be given more than once. Possible key values: type=(stdout,syslog,sink,file) - Where to route the serial device num=(1,2,3,4) - Serial Device Number. If not provided, num will default to 1. path=PATH - The path to the file to write to when type=file console - Use this serial device as the guest console. Can only be given once. Will default to first serial port if not provided. + stdin - Direct standard input to this serial device. Can only be given once. Will default to first serial port if not provided. "), Argument::value("syslog-tag", "TAG", "When logging to syslog, use the provided tag."), Argument::value("wayland-sock", "PATH", "Path to the Wayland socket to use."), @@ -1423,7 +1439,8 @@ mod tests { #[test] fn parse_serial_vaild() { - parse_serial_options("type=syslog,num=1,console=true").expect("parse should have succeded"); + parse_serial_options("type=syslog,num=1,console=true,stdin=true") + .expect("parse should have succeded"); } #[test] @@ -1455,4 +1472,13 @@ mod tests { fn parse_serial_invalid_option() { parse_serial_options("type=syslog,speed=lightspeed").expect_err("parse should have failed"); } + + #[test] + fn parse_serial_invalid_two_stdin() { + let mut config = Config::default(); + set_argument(&mut config, "serial", Some("num=1,type=stdout,stdin=true")) + .expect("should parse the first serial argument"); + set_argument(&mut config, "serial", Some("num=2,type=stdout,stdin=true")) + .expect_err("should fail to parse a second serial port connected to stdin"); + } } -- cgit 1.4.1