driver_manager_node/
start.rs1use crate::node::Node;
6use crate::types::{DriverComponent, DriverState, NodeState};
7use driver_manager_driver_host::{DriverLoadArgs, DriverStartArgs};
8use driver_manager_types::{ShutdownState, StartRequestReceiver};
9use fidl::endpoints::{ServerEnd, create_endpoints};
10use futures::StreamExt;
11use log::{debug, error, warn};
12use std::rc::Rc;
13use zx::HandleBased;
14use {
15 fidl_fuchsia_component as fcomponent, fidl_fuchsia_component_runner as frunner,
16 fidl_fuchsia_data as fdata, fidl_fuchsia_driver_framework as fdf,
17 fidl_fuchsia_driver_host as fdh,
18};
19
20impl Node {
21 pub async fn send_start_request(&self) -> Result<(), zx::Status> {
22 let (handles, proxy) = {
23 let handles = self.take_start_handles_for_start();
24 let proxy = self.component_controller_proxy().expect("component");
25 (handles, proxy)
26 };
27
28 let start_child_args =
29 fcomponent::StartChildArgs { numbered_handles: Some(handles), ..Default::default() };
30 let (_, server_end) = fidl::endpoints::create_endpoints();
31
32 proxy
33 .start(start_child_args, server_end)
34 .await
35 .map_err(|e| {
36 error!("Failed to start driver for node {}: {}", self.name(), e);
37 zx::Status::INTERNAL
38 })?
39 .map_err(|e: fcomponent::Error| {
40 error!("Failed to start driver for node {}: {:?}", self.name(), e);
41 zx::Status::INTERNAL
42 })?;
43 Ok(())
44 }
45
46 pub async fn get_next_start_request(
47 &self,
48 ) -> Result<
49 (frunner::ComponentStartInfo, ServerEnd<frunner::ComponentControllerMarker>),
50 zx::Status,
51 > {
52 struct ReleaseStartRequestReceiverGuard<'a> {
53 receiver: Option<StartRequestReceiver>,
54 node: &'a Node,
55 }
56
57 impl<'a> Drop for ReleaseStartRequestReceiverGuard<'a> {
58 fn drop(&mut self) {
59 if let Some(rx) = self.receiver.take() {
60 self.node.set_start_request_receiver(rx);
61 }
62 }
63 }
64
65 let receiver = self.take_start_request_receiver().ok_or(zx::Status::BAD_STATE)?;
66
67 let mut guard = ReleaseStartRequestReceiverGuard { receiver: Some(receiver), node: self };
68
69 let start_request =
70 guard.receiver.as_mut().unwrap().next().await.ok_or(zx::Status::TIMED_OUT)??;
71 let start_info = start_request.info;
72 let controller = start_request.controller;
73 Ok((start_info, controller))
74 }
75
76 pub async fn start_driver(
77 self: &Rc<Self>,
78 mut start_info: frunner::ComponentStartInfo,
79 controller: ServerEnd<frunner::ComponentControllerMarker>,
80 ) -> Result<(), zx::Status> {
81 if self.shutdown_state() == ShutdownState::Stopped {
82 self.node_shutdown_coordinator.borrow_mut().reset_shutdown();
83 }
84 let url = start_info.resolved_url.clone().ok_or(zx::Status::INVALID_ARGS)?;
85 self.set_state(NodeState::Starting { driver_url: url.clone() });
86
87 let program = start_info.program.as_ref();
88 let get_prog_val = |key: &str| -> Option<String> {
89 program.and_then(|p| p.entries.as_ref()).and_then(|e| {
90 e.iter().find(|entry| entry.key == key).and_then(|entry| {
91 if let Some(fdata::DictionaryValue::Str(s)) =
92 entry.value.as_ref().map(|v| v.as_ref())
93 {
94 Some(s.clone())
95 } else {
96 None
97 }
98 })
99 })
100 };
101
102 let colocate = get_prog_val("colocate").as_deref() == Some("true");
103 let use_next_vdso = get_prog_val("use_next_vdso").as_deref() == Some("true");
104 let host_restart_on_crash =
105 get_prog_val("host_restart_on_crash").as_deref() == Some("true");
106 let use_dynamic_linker = get_prog_val("use_dynamic_linker").as_deref() == Some("true");
107
108 if host_restart_on_crash && colocate {
109 error!(
110 "Failed to start driver '{}'. Both host_restart_on_crash and colocate cannot be true.",
111 url
112 );
113 return Err(zx::Status::INVALID_ARGS);
114 }
115 self.set_restart_on_crash(host_restart_on_crash);
116
117 let driver_host = self.host();
118 let mut found_driver_host = colocate;
119 let driver_host = if found_driver_host {
120 match driver_host {
121 Some(dh) => dh,
122 None => {
123 error!(
124 "Failed to start driver '{}', driver is colocated but does not have a parent with a driver host",
125 url
126 );
127 return Err(zx::Status::INVALID_ARGS);
128 }
129 }
130 } else {
131 let driver_host_name = self.driver_host_name_for_colocation();
132 match self.node_manager.get_driver_host(&driver_host_name) {
133 Some(dh) => {
134 found_driver_host = true;
135 self.set_host(dh.clone());
136 dh
137 }
138 None => {
139 if use_dynamic_linker {
140 let driver_host = self
141 .node_manager
142 .create_driver_host_dynamic_linker(driver_host_name)
143 .await?;
144 self.set_host(driver_host.clone());
145 driver_host
146 } else {
147 debug!(
148 "Creating driver host for node '{}' driver url '{}'",
149 self.name(),
150 url
151 );
152 let driver_host = self
153 .node_manager
154 .create_driver_host(use_next_vdso, driver_host_name)
155 .await
156 .map_err(|e| {
157 error!("Failed to start driver '{url}': {e:?}");
158 zx::Status::INTERNAL
159 })?;
160 self.set_host(driver_host.clone());
161 driver_host
162 }
163 }
164 }
165 };
166
167 if found_driver_host {
168 if use_dynamic_linker != driver_host.is_dynamic_linking_enabled() {
172 error!(
173 concat!(
174 "Failed to start driver '{}', driver is colocated and set",
175 "use_dynamic_linker={} but its driver host is not configured for this"
176 ),
177 url,
178 if use_dynamic_linker { "true" } else { "false" }
179 );
180 return Err(zx::Status::INVALID_ARGS);
181 }
182 }
183
184 let (node_client, node_server) = create_endpoints::<fdf::NodeMarker>();
185 let (driver_client, driver_server) = create_endpoints::<fdh::DriverMarker>();
186
187 let node_token = start_info.component_instance.take().unwrap_or_else(|| {
188 warn!("Component instance not provided in start request");
189 zx::Event::create()
190 });
191
192 let node_token_dup = node_token.duplicate_handle(zx::Rights::SAME_RIGHTS)?;
193
194 let runner_component_controller = self.serve_runner_component_controller(controller);
195 let node_server_binding = self.serve_node(node_server);
196
197 let driver = driver_client.into_proxy();
198 let driver_client_binding = self.serve_driver_host_client(driver);
199
200 self.set_state(NodeState::DriverComponent(DriverComponent::new(
201 url.clone(),
202 node_token_dup,
203 node_token.koid().unwrap(),
204 Some(runner_component_controller),
205 Some(node_server_binding),
206 Some(driver_client_binding),
207 DriverState::Binding,
208 )));
209
210 let symbols = if colocate { Some(self.symbols()) } else { None };
211 let offers: Vec<fdf::Offer> = self.offers().iter().map(|f| f.into()).collect();
212 let properties = self.get_node_property_dict();
213
214 let load_args = if use_dynamic_linker {
215 Some(DriverLoadArgs::new(&mut start_info).await?)
216 } else {
217 None
218 };
219
220 let start_args = DriverStartArgs {
221 node: node_client,
222 node_name: self.name.clone(),
223 properties,
224 symbols,
225 offers,
226 start_info,
227 component_instance: node_token,
228 };
229
230 log::info!("Binding {} to {}", url, self.name);
231
232 if use_dynamic_linker {
233 driver_host
234 .start_with_dynamic_linker(load_args.unwrap(), start_args, driver_server)
235 .await
236 } else {
237 driver_host.start(start_args, driver_server).await
238 }
239 .inspect_err(|_| {
240 error!("Failed to start driver host for {}", self.make_component_moniker())
241 })?;
242
243 Ok(())
244 }
245}