[fdf][driver_manager] Refactor bind functions

Pull the v1 bind bytecode functions out into their own source
set so they do not depend on any of the DFv1 code, such as
Devices, or Coordinator.

Bug: 103306
Change-Id: I51450e12316d54fe0564cd46fc8e175b3a8d657d
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/693794
Reviewed-by: Sarah Chan <spqchan@google.com>
Commit-Queue: Auto-Submit <auto-submit@fuchsia-infra.iam.gserviceaccount.com>
Fuchsia-Auto-Submit: David Gilhooley <dgilhooley@google.com>
diff --git a/src/devices/bin/driver_manager/BUILD.gn b/src/devices/bin/driver_manager/BUILD.gn
index 8a6edb1..bc531b1 100644
--- a/src/devices/bin/driver_manager/BUILD.gn
+++ b/src/devices/bin/driver_manager/BUILD.gn
@@ -20,6 +20,23 @@
   }
 }
 
+# TODO(fxb/38132): Migrate to the new bind rules and delete the below
+source_set("binding") {
+  sources = [
+    "binding.cc",
+    "binding.h",
+  ]
+  public_deps = [
+    "//src/lib/ddk",
+    "//src/lib/ddk:ddk-deprecated-binding-headers",
+    "//zircon/system/ulib/fbl",
+  ]
+  deps = [
+    "//src/devices/lib/bind:bind-lib",
+    "//src/devices/lib/log",
+  ]
+}
+
 source_set("manifest_parser") {
   sources = [
     "manifest_parser.cc",
@@ -46,7 +63,7 @@
     "base_package_resolver.h",
     "bind_driver_manager.cc",
     "bind_driver_manager.h",
-    "binding.cc",
+    "binding_internal.cc",
     "binding_internal.h",
     "builtin_devices.cc",
     "builtin_devices.h",
@@ -100,6 +117,7 @@
   ]
 
   public_deps = [
+    ":binding",
     ":manifest_parser",
     "v2:driver_runner",
     "//sdk/fidl/fuchsia.boot",
diff --git a/src/devices/bin/driver_manager/bind_driver_manager.cc b/src/devices/bin/driver_manager/bind_driver_manager.cc
index 05dffb3..dfdaeba 100644
--- a/src/devices/bin/driver_manager/bind_driver_manager.cc
+++ b/src/devices/bin/driver_manager/bind_driver_manager.cc
@@ -8,6 +8,7 @@
 #include <lib/fit/function.h>
 #include <zircon/status.h>
 
+#include "src/devices/bin/driver_manager/binding_internal.h"
 #include "src/devices/bin/driver_manager/devfs.h"
 #include "src/devices/lib/log/log.h"
 
diff --git a/src/devices/bin/driver_manager/binding.cc b/src/devices/bin/driver_manager/binding.cc
index 8a89512..5f70ca2 100644
--- a/src/devices/bin/driver_manager/binding.cc
+++ b/src/devices/bin/driver_manager/binding.cc
@@ -2,21 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <lib/ddk/binding.h>
-#include <lib/ddk/device.h>
-#include <lib/ddk/driver.h>
-#include <stdio.h>
+#include "binding.h"
 
-#include <optional>
+#include <stdio.h>
 
 #include <fbl/array.h>
 
-#include "binding_internal.h"
-#include "coordinator.h"
-#include "device.h"
 #include "src/devices/lib/bind/ffi_bindings.h"
 #include "src/devices/lib/log/log.h"
-#include "src/lib/fxl/strings/utf_codecs.h"
 
 namespace internal {
 
@@ -117,91 +110,3 @@
 }
 
 }  // namespace internal
-
-bool can_driver_bind(const Driver* drv, uint32_t protocol_id,
-                     const fbl::Array<const zx_device_prop_t>& props,
-                     const fbl::Array<const StrProperty>& str_props, bool autobind) {
-  if (drv->bytecode_version == 1) {
-    auto* binding = std::get_if<std::unique_ptr<zx_bind_inst_t[]>>(&drv->binding);
-    if (!binding && drv->binding_size > 0) {
-      return false;
-    }
-
-    internal::BindProgramContext ctx;
-    ctx.props = &props;
-    ctx.protocol_id = protocol_id;
-    ctx.binding = binding ? binding->get() : nullptr;
-    ctx.binding_size = drv->binding_size;
-    ctx.name = drv->name.c_str();
-    ctx.autobind = autobind ? 1 : 0;
-    return internal::EvaluateBindProgram(&ctx);
-  }
-
-  if (drv->bytecode_version == 2) {
-    auto* bytecode = std::get_if<std::unique_ptr<uint8_t[]>>(&drv->binding);
-    if (!bytecode && drv->binding_size > 0) {
-      return false;
-    }
-
-    fbl::Array<device_property_t> properties(new device_property_t[props.size()], props.size());
-    for (size_t i = 0; i < props.size(); i++) {
-      properties[i] = device_property_t{.key = props[i].id, .value = props[i].value};
-    }
-
-    fbl::Array<device_str_property_t> str_properties(new device_str_property_t[str_props.size()],
-                                                     str_props.size());
-    for (size_t i = 0; i < str_props.size(); i++) {
-      if (!fxl::IsStringUTF8(str_props[i].key)) {
-        LOGF(ERROR, "String property key is not in UTF-8 encoding");
-        return false;
-      }
-
-      if (str_props[i].value.valueless_by_exception()) {
-        LOGF(ERROR, "String property value is not set");
-        return false;
-      }
-
-      switch (str_props[i].value.index()) {
-        case StrPropValueType::Integer: {
-          const auto prop_val = std::get<StrPropValueType::Integer>(str_props[i].value);
-          str_properties[i] = str_property_with_int(str_props[i].key.c_str(), prop_val);
-          break;
-        }
-        case StrPropValueType::String: {
-          auto* prop_val = std::get_if<StrPropValueType::String>(&str_props[i].value);
-          if (prop_val && !fxl::IsStringUTF8(*prop_val)) {
-            LOGF(ERROR, "String property value is not in UTF-8 encoding");
-            return false;
-          }
-          str_properties[i] = str_property_with_string(str_props[i].key.c_str(), prop_val->c_str());
-          break;
-        }
-        case StrPropValueType::Bool: {
-          const auto prop_val = std::get<StrPropValueType::Bool>(str_props[i].value);
-          str_properties[i] = str_property_with_bool(str_props[i].key.c_str(), prop_val);
-          break;
-        }
-        case StrPropValueType::Enum: {
-          auto* prop_val = std::get_if<StrPropValueType::Enum>(&str_props[i].value);
-          if (prop_val && !fxl::IsStringUTF8(*prop_val)) {
-            LOGF(ERROR, "Enum property value is not in UTF-8 encoding");
-            return false;
-          }
-          str_properties[i] = str_property_with_enum(str_props[i].key.c_str(), prop_val->c_str());
-          break;
-        }
-        default: {
-          LOGF(ERROR, "String property value type is invalid.");
-          return false;
-        }
-      }
-    }
-
-    return match_bind_rules(bytecode ? bytecode->get() : nullptr, drv->binding_size,
-                            properties.get(), props.size(), str_properties.get(),
-                            str_properties.size(), protocol_id, autobind);
-  }
-
-  LOGF(ERROR, "Invalid bytecode version: %i", drv->bytecode_version);
-  return false;
-}
diff --git a/src/devices/bin/driver_manager/binding.h b/src/devices/bin/driver_manager/binding.h
new file mode 100644
index 0000000..72ae865
--- /dev/null
+++ b/src/devices/bin/driver_manager/binding.h
@@ -0,0 +1,29 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SRC_DEVICES_BIN_DRIVER_MANAGER_BINDING_H_
+#define SRC_DEVICES_BIN_DRIVER_MANAGER_BINDING_H_
+
+#include <lib/ddk/binding_priv.h>
+
+#include <fbl/array.h>
+#include <fbl/macros.h>
+
+namespace internal {
+
+struct BindProgramContext {
+  const fbl::Array<const zx_device_prop_t>* props;
+  uint32_t protocol_id;
+  size_t binding_size;
+  const zx_bind_inst_t* binding;
+  const char* name;
+  uint32_t autobind;
+};
+
+uint32_t LookupBindProperty(BindProgramContext* ctx, uint32_t id);
+bool EvaluateBindProgram(BindProgramContext* ctx);
+
+}  // namespace internal
+
+#endif  // SRC_DEVICES_BIN_DRIVER_MANAGER_BINDING_H_
diff --git a/src/devices/bin/driver_manager/binding_internal.cc b/src/devices/bin/driver_manager/binding_internal.cc
new file mode 100644
index 0000000..f3ea001
--- /dev/null
+++ b/src/devices/bin/driver_manager/binding_internal.cc
@@ -0,0 +1,97 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "binding_internal.h"
+
+#include "src/devices/lib/bind/ffi_bindings.h"
+#include "src/devices/lib/log/log.h"
+#include "src/lib/fxl/strings/utf_codecs.h"
+
+bool can_driver_bind(const Driver* drv, uint32_t protocol_id,
+                     const fbl::Array<const zx_device_prop_t>& props,
+                     const fbl::Array<const StrProperty>& str_props, bool autobind) {
+  if (drv->bytecode_version == 1) {
+    auto* binding = std::get_if<std::unique_ptr<zx_bind_inst_t[]>>(&drv->binding);
+    if (!binding && drv->binding_size > 0) {
+      return false;
+    }
+
+    internal::BindProgramContext ctx;
+    ctx.props = &props;
+    ctx.protocol_id = protocol_id;
+    ctx.binding = binding ? binding->get() : nullptr;
+    ctx.binding_size = drv->binding_size;
+    ctx.name = drv->name.c_str();
+    ctx.autobind = autobind ? 1 : 0;
+    return internal::EvaluateBindProgram(&ctx);
+  }
+
+  if (drv->bytecode_version == 2) {
+    auto* bytecode = std::get_if<std::unique_ptr<uint8_t[]>>(&drv->binding);
+    if (!bytecode && drv->binding_size > 0) {
+      return false;
+    }
+
+    fbl::Array<device_property_t> properties(new device_property_t[props.size()], props.size());
+    for (size_t i = 0; i < props.size(); i++) {
+      properties[i] = device_property_t{.key = props[i].id, .value = props[i].value};
+    }
+
+    fbl::Array<device_str_property_t> str_properties(new device_str_property_t[str_props.size()],
+                                                     str_props.size());
+    for (size_t i = 0; i < str_props.size(); i++) {
+      if (!fxl::IsStringUTF8(str_props[i].key)) {
+        LOGF(ERROR, "String property key is not in UTF-8 encoding");
+        return false;
+      }
+
+      if (str_props[i].value.valueless_by_exception()) {
+        LOGF(ERROR, "String property value is not set");
+        return false;
+      }
+
+      switch (str_props[i].value.index()) {
+        case StrPropValueType::Integer: {
+          const auto prop_val = std::get<StrPropValueType::Integer>(str_props[i].value);
+          str_properties[i] = str_property_with_int(str_props[i].key.c_str(), prop_val);
+          break;
+        }
+        case StrPropValueType::String: {
+          auto* prop_val = std::get_if<StrPropValueType::String>(&str_props[i].value);
+          if (prop_val && !fxl::IsStringUTF8(*prop_val)) {
+            LOGF(ERROR, "String property value is not in UTF-8 encoding");
+            return false;
+          }
+          str_properties[i] = str_property_with_string(str_props[i].key.c_str(), prop_val->c_str());
+          break;
+        }
+        case StrPropValueType::Bool: {
+          const auto prop_val = std::get<StrPropValueType::Bool>(str_props[i].value);
+          str_properties[i] = str_property_with_bool(str_props[i].key.c_str(), prop_val);
+          break;
+        }
+        case StrPropValueType::Enum: {
+          auto* prop_val = std::get_if<StrPropValueType::Enum>(&str_props[i].value);
+          if (prop_val && !fxl::IsStringUTF8(*prop_val)) {
+            LOGF(ERROR, "Enum property value is not in UTF-8 encoding");
+            return false;
+          }
+          str_properties[i] = str_property_with_enum(str_props[i].key.c_str(), prop_val->c_str());
+          break;
+        }
+        default: {
+          LOGF(ERROR, "String property value type is invalid.");
+          return false;
+        }
+      }
+    }
+
+    return match_bind_rules(bytecode ? bytecode->get() : nullptr, drv->binding_size,
+                            properties.get(), props.size(), str_properties.get(),
+                            str_properties.size(), protocol_id, autobind);
+  }
+
+  LOGF(ERROR, "Invalid bytecode version: %i", drv->bytecode_version);
+  return false;
+}
diff --git a/src/devices/bin/driver_manager/binding_internal.h b/src/devices/bin/driver_manager/binding_internal.h
index 485b5c2c..d5ab677 100644
--- a/src/devices/bin/driver_manager/binding_internal.h
+++ b/src/devices/bin/driver_manager/binding_internal.h
@@ -5,32 +5,13 @@
 #ifndef SRC_DEVICES_BIN_DRIVER_MANAGER_BINDING_INTERNAL_H_
 #define SRC_DEVICES_BIN_DRIVER_MANAGER_BINDING_INTERNAL_H_
 
-#include <lib/ddk/binding.h>
-#include <lib/ddk/device.h>
-#include <lib/ddk/driver.h>
-#include <stdio.h>
-
-#include <fbl/array.h>
-#include <fbl/macros.h>
-
+#include "binding.h"
 #include "composite_device.h"
 #include "coordinator.h"
 #include "device.h"
 
 namespace internal {
 
-struct BindProgramContext {
-  const fbl::Array<const zx_device_prop_t>* props;
-  uint32_t protocol_id;
-  size_t binding_size;
-  const zx_bind_inst_t* binding;
-  const char* name;
-  uint32_t autobind;
-};
-
-uint32_t LookupBindProperty(BindProgramContext* ctx, uint32_t id);
-bool EvaluateBindProgram(BindProgramContext* ctx);
-
 template <typename T>
 bool EvaluateBindProgram(const fbl::RefPtr<T>& device, const char* drv_name,
                          const fbl::Array<const zx_bind_inst_t>& bind_program, bool autobind) {
@@ -46,4 +27,8 @@
 
 }  // namespace internal
 
+bool can_driver_bind(const Driver* drv, uint32_t protocol_id,
+                     const fbl::Array<const zx_device_prop_t>& props,
+                     const fbl::Array<const StrProperty>& str_props, bool autobind);
+
 #endif  // SRC_DEVICES_BIN_DRIVER_MANAGER_BINDING_INTERNAL_H_
diff --git a/src/devices/bin/driver_manager/binding_v2_test.cc b/src/devices/bin/driver_manager/binding_v2_test.cc
index 605815d..85c2632 100644
--- a/src/devices/bin/driver_manager/binding_v2_test.cc
+++ b/src/devices/bin/driver_manager/binding_v2_test.cc
@@ -6,6 +6,7 @@
 
 #include <zxtest/zxtest.h>
 
+#include "binding_internal.h"
 #include "coordinator.h"
 #include "src/devices/lib/bind/ffi_bindings.h"
 
diff --git a/src/devices/bin/driver_manager/coordinator.h b/src/devices/bin/driver_manager/coordinator.h
index 22da088..cb6fc4b 100644
--- a/src/devices/bin/driver_manager/coordinator.h
+++ b/src/devices/bin/driver_manager/coordinator.h
@@ -329,8 +329,4 @@
   std::unique_ptr<BindDriverManager> bind_driver_manager_;
 };
 
-bool can_driver_bind(const Driver* drv, uint32_t protocol_id,
-                     const fbl::Array<const zx_device_prop_t>& props,
-                     const fbl::Array<const StrProperty>& str_props, bool autobind);
-
 #endif  // SRC_DEVICES_BIN_DRIVER_MANAGER_COORDINATOR_H_