[Bind] Add device properties fallback
The stored device properties might not contain the
protocol ID or autobind data. As such, when matching
a driver to a device, the protocol ID and autobind
values need to be added to the device properties.
Bug: 74316
Testing: Added unit tests in binding_v2_tests.cc
Change-Id: I2d55bc79ac8db507216b2158988db0e8809f6909
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/514108
Commit-Queue: Sarah Chan <spqchan@google.com>
Reviewed-by: Alex Legg <alexlegg@google.com>
Reviewed-by: David Gilhooley <dgilhooley@google.com>
diff --git a/src/devices/bin/driver_manager/binding.cc b/src/devices/bin/driver_manager/binding.cc
index 9a9d9c5..4a6057c 100644
--- a/src/devices/bin/driver_manager/binding.cc
+++ b/src/devices/bin/driver_manager/binding.cc
@@ -158,8 +158,8 @@
properties[i] = device_property_t{.key = props[i].id, .value = props[i].value};
}
- return match_bind_rules(drv->binding_size, bytecode ? bytecode->get() : nullptr, props.size(),
- properties.get());
+ return match_bind_rules(bytecode ? bytecode->get() : nullptr, drv->binding_size,
+ properties.get(), props.size(), protocol_id, autobind);
}
LOGF(ERROR, "Invalid bytecode version: %i", drv->bytecode_version);
diff --git a/src/devices/bin/driver_manager/binding_v2_test.cc b/src/devices/bin/driver_manager/binding_v2_test.cc
index 7411000c..e2d0766 100644
--- a/src/devices/bin/driver_manager/binding_v2_test.cc
+++ b/src/devices/bin/driver_manager/binding_v2_test.cc
@@ -12,7 +12,7 @@
// Tests for matching device properties to the new bytecode.
bool match_bind_rules(const uint8_t* bytecode, const zx_device_prop_t* props, size_t bytecode_sz,
- size_t props_sz) {
+ size_t props_sz, uint32_t protocol_id, bool autobind) {
auto driver = Driver();
driver.bytecode_version = 2;
@@ -28,7 +28,7 @@
memcpy(properties.data(), props, sizeof(props[0]) * props_sz);
}
- return driver_is_bindable(&driver, 0, std::move(properties), false);
+ return driver_is_bindable(&driver, protocol_id, std::move(properties), autobind);
}
TEST(BindingV2Test, SingleAbortInstruction) {
@@ -39,7 +39,8 @@
0x30 // Abort instruction
};
zx_device_prop_t properties[] = {zx_device_prop_t{5, 0, 2}};
- ASSERT_FALSE(match_bind_rules(bytecode, properties, std::size(bytecode), std::size(properties)));
+ ASSERT_FALSE(
+ match_bind_rules(bytecode, properties, std::size(bytecode), std::size(properties), 5, false));
}
TEST(BindingV2Test, NoBindRules) {
@@ -49,7 +50,8 @@
0x49, 0x4E, 0x53, 0x54, 0x0, 0x0, 0x0, 0x0 // Instruction header
};
zx_device_prop_t properties[] = {zx_device_prop_t{5, 0, 2}};
- ASSERT_TRUE(match_bind_rules(bytecode, properties, std::size(bytecode), std::size(properties)));
+ ASSERT_TRUE(
+ match_bind_rules(bytecode, properties, std::size(bytecode), std::size(properties), 5, false));
}
TEST(BindingV2Test, MatchDeviceProperty) {
@@ -60,7 +62,8 @@
0x01, 0x01, 0x05, 0x0, 0x0, 0x0, 0x01, 0x02, 0x0, 0x0, 0x0, // Equal instruction
};
zx_device_prop_t properties[] = {zx_device_prop_t{4, 0, 3}, zx_device_prop_t{5, 0, 2}};
- ASSERT_TRUE(match_bind_rules(bytecode, properties, std::size(bytecode), std::size(properties)));
+ ASSERT_TRUE(
+ match_bind_rules(bytecode, properties, std::size(bytecode), std::size(properties), 5, false));
}
TEST(BindingV2Test, MismatchDeviceProperty) {
@@ -71,22 +74,56 @@
0x01, 0x01, 0x05, 0x0, 0x0, 0x0, 0x01, 0x02, 0x0, 0x0, 0x0, // Equal instruction
};
zx_device_prop_t properties[] = {zx_device_prop_t{5, 0, 20}};
- ASSERT_FALSE(match_bind_rules(bytecode, properties, std::size(bytecode), std::size(properties)));
+ ASSERT_FALSE(
+ match_bind_rules(bytecode, properties, std::size(bytecode), std::size(properties), 5, false));
}
-TEST(BindingV2Test, NoDeviceProperties) {
+TEST(BindingV2Test, NoDevicePropertiesWithMismatchProtocolId) {
uint8_t bytecode[] = {
0x42, 0x49, 0x4E, 0x44, 0x02, 0x0, 0x0, 0x0, // Bind header
0x53, 0x59, 0x4E, 0x42, 0x0, 0x0, 0x0, 0x0, // Symbol table header
0x49, 0x4E, 0x53, 0x54, 0x0B, 0x0, 0x0, 0x0, // Instruction header
- 0x01, 0x01, 0x05, 0x0, 0x0, 0x0, 0x01, 0x02, 0x0, 0x0, 0x0, // Equal instruction
+ 0x01, 0x01, 0x01, 0x0, 0x0, 0x0, 0x01, 0x02, 0x0, 0x0, 0x0, // Equal instruction
};
zx_device_prop_t properties[] = {};
- ASSERT_FALSE(match_bind_rules(bytecode, properties, std::size(bytecode), 0));
+ ASSERT_FALSE(match_bind_rules(bytecode, properties, std::size(bytecode), 0, 5, false));
+}
+
+TEST(BindingV2Test, NoDevicePropertiesWithMatchingProtocolId) {
+ uint8_t bytecode[] = {
+ 0x42, 0x49, 0x4E, 0x44, 0x02, 0x0, 0x0, 0x0, // Bind header
+ 0x53, 0x59, 0x4E, 0x42, 0x0, 0x0, 0x0, 0x0, // Symbol table header
+ 0x49, 0x4E, 0x53, 0x54, 0x0B, 0x0, 0x0, 0x0, // Instruction header
+ 0x01, 0x01, 0x01, 0x0, 0x0, 0x0, 0x01, 0x05, 0x0, 0x0, 0x0, // Equal instruction
+ };
+ zx_device_prop_t properties[] = {};
+ ASSERT_TRUE(match_bind_rules(bytecode, properties, std::size(bytecode), 0, 5, false));
+}
+
+TEST(BindingV2Test, NoDevicePropertiesWithMismatchAutobind) {
+ uint8_t bytecode[] = {
+ 0x42, 0x49, 0x4E, 0x44, 0x02, 0x0, 0x0, 0x0, // Bind header
+ 0x53, 0x59, 0x4E, 0x42, 0x0, 0x0, 0x0, 0x0, // Symbol table header
+ 0x49, 0x4E, 0x53, 0x54, 0x0B, 0x0, 0x0, 0x0, // Instruction header
+ 0x01, 0x01, 0x02, 0x0, 0x0, 0x0, 0x01, 0x01, 0x0, 0x0, 0x0, // Equal instruction
+ };
+ zx_device_prop_t properties[] = {};
+ ASSERT_FALSE(match_bind_rules(bytecode, properties, std::size(bytecode), 0, 5, false));
+}
+
+TEST(BindingV2Test, NoDevicePropertiesWithMatchingAutobind) {
+ uint8_t bytecode[] = {
+ 0x42, 0x49, 0x4E, 0x44, 0x02, 0x0, 0x0, 0x0, // Bind header
+ 0x53, 0x59, 0x4E, 0x42, 0x0, 0x0, 0x0, 0x0, // Symbol table header
+ 0x49, 0x4E, 0x53, 0x54, 0x0B, 0x0, 0x0, 0x0, // Instruction header
+ 0x01, 0x01, 0x02, 0x0, 0x0, 0x0, 0x01, 0x01, 0x0, 0x0, 0x0, // Equal instruction
+ };
+ zx_device_prop_t properties[] = {};
+ ASSERT_TRUE(match_bind_rules(bytecode, properties, std::size(bytecode), 0, 5, true));
}
TEST(BindingV2Test, EmptyBytecode) {
uint8_t bytecode[] = {};
zx_device_prop_t properties[] = {zx_device_prop_t{5, 0, 20}};
- ASSERT_FALSE(match_bind_rules(bytecode, properties, 0, std::size(properties)));
+ ASSERT_FALSE(match_bind_rules(bytecode, properties, 0, std::size(properties), 5, false));
}
diff --git a/src/devices/lib/bind/ffi_bindings.h b/src/devices/lib/bind/ffi_bindings.h
index ba68996..42ff272 100644
--- a/src/devices/lib/bind/ffi_bindings.h
+++ b/src/devices/lib/bind/ffi_bindings.h
@@ -11,8 +11,9 @@
};
extern "C" {
-bool match_bind_rules(size_t bytecode_sz, const uint8_t *bytecode, size_t properties_sz,
- const device_property_t *properties);
+bool match_bind_rules(const uint8_t *bytecode, size_t bytecode_sz,
+ const device_property_t *properties, size_t properties_sz,
+ uint8_t protocol_id, bool autobind);
}
#endif // SRC_DEVICES_LIB_BIND_FFI_BINDINGS_H_
diff --git a/src/devices/lib/bind/src/ffi.rs b/src/devices/lib/bind/src/ffi.rs
index d5520f7..8ee748e 100644
--- a/src/devices/lib/bind/src/ffi.rs
+++ b/src/devices/lib/bind/src/ffi.rs
@@ -6,28 +6,33 @@
use bind::match_bind::{match_bytecode, PropertyKey};
use std::collections::HashMap;
+const BIND_PROTOCOL: u64 = 0x0001;
+const BIND_AUTOBIND: u64 = 0x0002;
+
#[repr(C)]
pub struct device_property_t {
key: u32,
value: u32,
}
+// |bytecode_sz| must match the size of |bytecode_c|. |properties_sz| must
+// match the size o |properties_c|.
#[no_mangle]
-pub unsafe extern "C" fn match_bind_rules(
- bytecode_sz: libc::size_t,
+pub extern "C" fn match_bind_rules(
bytecode_c: *const u8,
- properties_sz: libc::size_t,
+ bytecode_sz: libc::size_t,
properties_c: *const device_property_t,
+ properties_sz: libc::size_t,
+ protocol_id: u32,
+ autobind: bool,
) -> bool {
if bytecode_c.is_null() {
return false;
}
- let bytecode = std::slice::from_raw_parts(bytecode_c, bytecode_sz).to_vec();
-
let mut device_properties = HashMap::new();
if !properties_c.is_null() {
- let properties = std::slice::from_raw_parts(properties_c, properties_sz);
+ let properties = unsafe { std::slice::from_raw_parts(properties_c, properties_sz) };
for property in properties.iter() {
device_properties.insert(
PropertyKey::NumberKey(property.key as u64),
@@ -36,6 +41,16 @@
}
}
+ // Insert the protocol ID property if it's missing.
+ device_properties
+ .entry(PropertyKey::NumberKey(BIND_PROTOCOL))
+ .or_insert(Symbol::NumberValue(protocol_id as u64));
+ device_properties
+ .entry(PropertyKey::NumberKey(BIND_AUTOBIND))
+ .or_insert(Symbol::NumberValue(if autobind { 1 } else { 0 }));
+
+ let bytecode = unsafe { std::slice::from_raw_parts(bytecode_c, bytecode_sz).to_vec() };
+
// TODO(fxb/73943): Return the error instead of returning false.
match_bytecode(bytecode, device_properties).unwrap_or_else(|e| {
println!("Error evaluating the bytecode: {}", e);