• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The ChromiumOS Authors
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 std::fs::File;
6 use std::fs::OpenOptions;
7 use std::os::windows::fs::OpenOptionsExt;
8 
9 use anyhow::bail;
10 use anyhow::Context;
11 use argh::FromArgs;
12 use base::enable_high_res_timers;
13 use base::info;
14 use base::Event;
15 use base::RawDescriptor;
16 use broker_ipc::common_child_setup;
17 use broker_ipc::CommonChildStartupArgs;
18 use cros_async::sys::windows::ExecutorKindSys;
19 use cros_async::Executor;
20 use crosvm_cli::sys::windows::exit::Exit;
21 use crosvm_cli::sys::windows::exit::ExitContext;
22 use crosvm_cli::sys::windows::exit::ExitContextAnyhow;
23 use hypervisor::ProtectionType;
24 use tube_transporter::TubeToken;
25 
26 use crate::virtio::base_features;
27 use crate::virtio::block::DiskOption;
28 use crate::virtio::vhost::user::device::block::BlockBackend;
29 use crate::virtio::vhost::user::device::handler::sys::windows::read_from_tube_transporter;
30 use crate::virtio::vhost::user::device::handler::sys::windows::run_handler;
31 use crate::virtio::vhost::user::device::VhostUserDevice;
32 use crate::virtio::vhost::user::VhostUserDeviceBuilder;
33 use crate::virtio::BlockAsync;
34 
35 #[derive(FromArgs, Debug)]
36 #[argh(subcommand, name = "block", description = "")]
37 pub struct Options {
38     #[argh(
39         option,
40         description = "pipe handle end for Tube Transporter",
41         arg_name = "HANDLE"
42     )]
43     bootstrap: usize,
44 }
45 
start_device(opts: Options) -> anyhow::Result<()>46 pub fn start_device(opts: Options) -> anyhow::Result<()> {
47     cros_tracing::init();
48 
49     let raw_transport_tube = opts.bootstrap as RawDescriptor;
50 
51     let mut tubes = read_from_tube_transporter(raw_transport_tube)?;
52 
53     let vhost_user_tube = tubes.get_tube(TubeToken::VhostUser)?;
54     let _control_tube = tubes.get_tube(TubeToken::Control)?;
55     let bootstrap_tube = tubes.get_tube(TubeToken::Bootstrap)?;
56 
57     let startup_args: CommonChildStartupArgs = bootstrap_tube.recv::<CommonChildStartupArgs>()?;
58     let _child_cleanup = common_child_setup(startup_args)?;
59 
60     let disk_option: DiskOption = bootstrap_tube.recv::<DiskOption>()?;
61     let exit_event = bootstrap_tube.recv::<Event>()?;
62 
63     // TODO(b/213146388): Replace below with `broker_ipc::common_child_setup`
64     // once `src` directory is upstreamed.
65     let _raise_timer_resolution =
66         enable_high_res_timers().context("failed to set timer resolution")?;
67 
68     info!("using {:?} executor.", disk_option.async_executor);
69 
70     let kind = disk_option.async_executor.unwrap_or_default();
71     let ex = Executor::with_executor_kind(kind).context("failed to create executor")?;
72 
73     let block = Box::new(BlockAsync::new(
74         base_features(ProtectionType::Unprotected),
75         disk_option
76             .open()
77             .exit_context(Exit::OpenDiskImage, "failed to open disk image")?,
78         &disk_option,
79         None,
80         None,
81         None,
82     )?);
83 
84     // TODO(b/213170185): Uncomment once sandbox is upstreamed.
85     //     if sandbox::is_sandbox_target() {
86     //         sandbox::TargetServices::get()
87     //             .expect("failed to get target services")
88     //             .unwrap()
89     //             .lower_token();
90     //     }
91 
92     // This is basically the event loop.
93     let handler = block.build(&ex)?;
94 
95     info!("vhost-user disk device ready, starting run loop...");
96     ex.run_until(run_handler(handler, vhost_user_tube, exit_event, &ex))
97         .context("run_until error")?
98         .context("run_handler error")
99 }
100