• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Chromium OS Authors. All rights reserved.
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 crate::serial_device::{Error, SerialParameters};
6 use base::named_pipes;
7 use base::named_pipes::{BlockingMode, FramingMode};
8 use base::FileSync;
9 use base::{AsRawDescriptor, Event, RawDescriptor};
10 use hypervisor::ProtectionType;
11 use std::io::{self};
12 use std::path::Path;
13 
14 pub use base::Console as ConsoleInput;
15 
16 pub const SYSTEM_SERIAL_TYPE_NAME: &str = "NamedPipe";
17 
18 /// Abstraction over serial-like devices that can be created given an event and optional input and
19 /// output streams.
20 pub trait SerialDevice {
new( protected_vm: ProtectionType, interrupt_evt: Event, input: Option<Box<dyn io::Read + Send>>, output: Option<Box<dyn io::Write + Send>>, sync: Option<Box<dyn FileSync + Send>>, out_timestamp: bool, keep_rds: Vec<RawDescriptor>, ) -> Self21     fn new(
22         protected_vm: ProtectionType,
23         interrupt_evt: Event,
24         input: Option<Box<dyn io::Read + Send>>,
25         output: Option<Box<dyn io::Write + Send>>,
26         sync: Option<Box<dyn FileSync + Send>>,
27         out_timestamp: bool,
28         keep_rds: Vec<RawDescriptor>,
29     ) -> Self;
new_pipe( protected_vm: ProtectionType, interrupt_evt: Event, pipe_in: named_pipes::PipeConnection, pipe_out: named_pipes::PipeConnection, keep_rds: Vec<RawDescriptor>, ) -> Self30     fn new_pipe(
31         protected_vm: ProtectionType,
32         interrupt_evt: Event,
33         pipe_in: named_pipes::PipeConnection,
34         pipe_out: named_pipes::PipeConnection,
35         keep_rds: Vec<RawDescriptor>,
36     ) -> Self;
37 }
38 
create_system_type_serial_device<T: SerialDevice>( param: &SerialParameters, protected_vm: ProtectionType, evt: Event, _input: Option<Box<dyn io::Read + Send>>, keep_rds: &mut Vec<RawDescriptor>, ) -> std::result::Result<T, Error>39 pub(crate) fn create_system_type_serial_device<T: SerialDevice>(
40     param: &SerialParameters,
41     protected_vm: ProtectionType,
42     evt: Event,
43     _input: Option<Box<dyn io::Read + Send>>,
44     keep_rds: &mut Vec<RawDescriptor>,
45 ) -> std::result::Result<T, Error> {
46     match &param.path {
47         None => return Err(Error::PathRequired),
48         Some(path) => {
49             // We must create this pipe in non-blocking mode because a blocking
50             // read in one thread will block a write in another thread having a
51             // handle to the same end of the pipe, which will hang the
52             // emulator. This does mean that the event loop writing to the
53             // pipe's output will need to swallow errors caused by writing to
54             // the pipe when it's not ready; but in practice this does not seem
55             // to cause a problem.
56             let pipe_in = named_pipes::create_server_pipe(
57                 path.to_str().unwrap(),
58                 &FramingMode::Byte,
59                 &BlockingMode::NoWait,
60                 0, // default timeout
61                 named_pipes::DEFAULT_BUFFER_SIZE,
62                 false,
63             )
64             .map_err(Error::SystemTypeError)?;
65 
66             let pipe_out = pipe_in.try_clone().map_err(Error::SystemTypeError)?;
67 
68             keep_rds.push(pipe_in.as_raw_descriptor());
69             keep_rds.push(pipe_out.as_raw_descriptor());
70 
71             return Ok(T::new_pipe(
72                 protected_vm,
73                 evt,
74                 pipe_in,
75                 pipe_out,
76                 keep_rds.to_vec(),
77             ));
78         }
79     }
80 }
81