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