// Copyright 2017 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 "src/devices/bin/driver_manager/coordinator.h"

#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <fidl/fuchsia.io/cpp/wire.h>
#include <fidl/fuchsia.pkg/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/receiver.h>
#include <lib/async/cpp/task.h>
#include <lib/ddk/driver.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/io.h>
#include <lib/fidl-async/bind.h>
#include <lib/fidl-async/cpp/bind.h>
#include <lib/fidl/coding.h>
#include <lib/fidl/llcpp/arena.h>
#include <lib/fidl/llcpp/wire_messaging.h>
#include <lib/fit/defer.h>
#include <lib/fzl/owned-vmo-mapper.h>
#include <lib/service/llcpp/service.h>
#include <lib/zbitl/error-string.h>
#include <lib/zbitl/image.h>
#include <lib/zbitl/item.h>
#include <lib/zbitl/vmo.h>
#include <lib/zircon-internal/ktrace.h>
#include <lib/zx/clock.h>
#include <lib/zx/job.h>
#include <lib/zx/time.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <threads.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/policy.h>
#include <zircon/syscalls/system.h>

#include <array>
#include <cstdint>
#include <memory>
#include <string_view>
#include <utility>
#include <vector>

#include <driver-info/driver-info.h>
#include <fbl/string_printf.h>
#include <inspector/inspector.h>
#include <src/bringup/lib/mexec/mexec.h>
#include <src/lib/fsl/vmo/sized_vmo.h>
#include <src/lib/fsl/vmo/vector.h>

#include "src/devices/bin/driver_manager/driver_host_loader_service.h"
#include "src/devices/bin/driver_manager/manifest_parser.h"
#include "src/devices/bin/driver_manager/package_resolver.h"
#include "src/devices/bin/driver_manager/v1/driver_development.h"
#include "src/devices/bin/driver_manager/v1/unbind_task.h"
#include "src/devices/lib/log/log.h"
#include "src/lib/storage/vfs/cpp/pseudo_dir.h"

namespace fio = fuchsia_io;

namespace {

namespace fdd = fuchsia_driver_development;
namespace fdm = fuchsia_device_manager;
namespace fdr = fuchsia_driver_registrar;
namespace fpm = fuchsia_power_manager;

constexpr char kDriverHostPath[] = "/pkg/bin/driver_host";
constexpr const char* kItemsPath = fidl::DiscoverableProtocolDefaultPath<fuchsia_boot::Items>;

// The driver_host doesn't just define its own __asan_default_options()
// function because that conflicts with the build-system feature of injecting
// such a function based on the `asan_default_options` GN build argument.
// Since driver_host is only ever launched here, it can always get its
// necessary options through its environment variables.  The sanitizer
// runtime combines the __asan_default_options() and environment settings.
constexpr char kAsanEnvironment[] =
    "ASAN_OPTIONS="

    // All drivers have a pure C ABI.  But each individual driver might
    // statically link in its own copy of some C++ library code.  Since no
    // C++ language relationships leak through the driver ABI, each driver is
    // its own whole program from the perspective of the C++ language rules.
    // But the ASan runtime doesn't understand this and wants to diagnose ODR
    // violations when the same global is defined in multiple drivers, which
    // is likely with C++ library use.  There is no real way to teach the
    // ASan instrumentation or runtime about symbol visibility and isolated
    // worlds within the program, so the only thing to do is suppress the ODR
    // violation detection.  This unfortunately means real ODR violations
    // within a single C++ driver won't be caught either.
    "detect_odr_violation=0";

// Currently we check if DriverManager is built using ASAN.
// If it is, then we assume DriverHost is also ASAN.
//
// We currently assume that either the whole system is ASAN or the whole
// system is non-ASAN. One day we might be able to be more flexible about
// which drivers must get loaded into the same driver_host and thus be able
// to use both ASan and non-ASan driver_hosts at the same time when only
// a subset of drivers use ASan.
bool driver_host_is_asan() {
  bool is_asan = false;
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
  is_asan = true;
#endif
#endif
  return is_asan;
}

// send message to driver_host, requesting the creation of a device
zx_status_t CreateProxyDevice(const fbl::RefPtr<Device>& dev, fbl::RefPtr<DriverHost>& dh,
                              const char* args, zx::channel rpc_proxy) {
  auto coordinator_endpoints = fidl::CreateEndpoints<fdm::Coordinator>();
  if (coordinator_endpoints.is_error()) {
    return coordinator_endpoints.error_value();
  }

  auto device_controller_request = dev->ConnectDeviceController(dev->coordinator->dispatcher());

  fidl::Arena arena;
  if (dev->libname().size() != 0) {
    zx::vmo vmo;
    if (auto status = dev->coordinator->LibnameToVmo(dev->libname(), &vmo); status != ZX_OK) {
      return status;
    }

    auto driver_path = fidl::StringView::FromExternal(dev->libname().data(), dev->libname().size());
    auto args_view = fidl::StringView::FromExternal(args, strlen(args));

    fdm::wire::ProxyDevice proxy{driver_path, std::move(vmo), std::move(rpc_proxy), args_view};
    auto type = fdm::wire::DeviceType::WithProxy(arena, std::move(proxy));

    dh->controller()
        ->CreateDevice(std::move(coordinator_endpoints->client),
                       std::move(device_controller_request), std::move(type), dev->local_id())
        .ThenExactlyOnce(
            [](fidl::WireUnownedResult<fdm::DriverHostController::CreateDevice>& result) {
              if (!result.ok()) {
                LOGF(ERROR, "Failed to create device: %s",
                     result.error().FormatDescription().c_str());
                return;
              }
              if (result.value().status != ZX_OK) {
                LOGF(ERROR, "Failed to create device: %s",
                     zx_status_get_string(result.value().status));
              }
            });
  } else {
    fdm::wire::StubDevice stub{dev->protocol_id()};
    auto type = fdm::wire::DeviceType::WithStub(stub);
    dh->controller()
        ->CreateDevice(std::move(coordinator_endpoints->client),
                       std::move(device_controller_request), std::move(type), dev->local_id())
        .ThenExactlyOnce(
            [](fidl::WireUnownedResult<fdm::DriverHostController::CreateDevice>& result) {
              if (!result.ok()) {
                LOGF(ERROR, "Failed to create device: %s",
                     result.error().FormatDescription().c_str());
                return;
              }
              if (result.value().status != ZX_OK) {
                LOGF(ERROR, "Failed to create device: %s",
                     zx_status_get_string(result.value().status));
              }
            });
  }

  Device::Bind(dev, dev->coordinator->dispatcher(), std::move(coordinator_endpoints->server));
  return ZX_OK;
}

zx_status_t CreateNewProxyDevice(const fbl::RefPtr<Device>& dev, fbl::RefPtr<DriverHost>& dh,
                                 fidl::ClientEnd<fio::Directory> incoming_dir) {
  auto coordinator_endpoints = fidl::CreateEndpoints<fdm::Coordinator>();
  if (coordinator_endpoints.is_error()) {
    return coordinator_endpoints.error_value();
  }

  auto device_controller_request = dev->ConnectDeviceController(dev->coordinator->dispatcher());

  fdm::wire::NewProxyDevice new_proxy{std::move(incoming_dir)};
  auto type = fdm::wire::DeviceType::WithNewProxy(std::move(new_proxy));

  dh->controller()
      ->CreateDevice(std::move(coordinator_endpoints->client), std::move(device_controller_request),
                     std::move(type), dev->local_id())
      .ThenExactlyOnce(
          [](fidl::WireUnownedResult<fdm::DriverHostController::CreateDevice>& result) {
            if (!result.ok()) {
              LOGF(ERROR, "Failed to create device: %s",
                   result.error().FormatDescription().c_str());
              return;
            }
            if (result.value().status != ZX_OK) {
              LOGF(ERROR, "Failed to create device: %s",
                   zx_status_get_string(result.value().status));
            }
          });

  Device::Bind(dev, dev->coordinator->dispatcher(), std::move(coordinator_endpoints->server));
  return ZX_OK;
}

// Binds the driver to the device by sending a request to driver_host.
zx_status_t BindDriverToDevice(const fbl::RefPtr<Device>& dev, const char* libname) {
  zx::vmo vmo;
  zx_status_t status = dev->coordinator->LibnameToVmo(libname, &vmo);
  if (status != ZX_OK) {
    return status;
  }
  dev->flags |= DEV_CTX_BOUND;
  dev->device_controller()
      ->BindDriver(fidl::StringView::FromExternal(libname, strlen(libname)), std::move(vmo))
      .ThenExactlyOnce([dev](fidl::WireUnownedResult<fdm::DeviceController::BindDriver>& result) {
        if (!result.ok()) {
          LOGF(ERROR, "Failed to bind driver '%s': %s", dev->name().data(), result.status_string());
          dev->flags &= (~DEV_CTX_BOUND);
          return;
        }
        if (result.value().status != ZX_OK) {
          LOGF(ERROR, "Failed to bind driver '%s': %s", dev->name().data(),
               zx_status_get_string(result.value().status));
          dev->flags &= (~DEV_CTX_BOUND);
          return;
        }
      });
  return ZX_OK;
}

}  // namespace

namespace statecontrol_fidl = fuchsia_hardware_power_statecontrol;

Coordinator::Coordinator(CoordinatorConfig config, InspectManager* inspect_manager,
                         async_dispatcher_t* dispatcher, async_dispatcher_t* firmware_dispatcher)
    : config_(std::move(config)),
      dispatcher_(dispatcher),
      base_resolver_(config_.boot_args),
      inspect_manager_(inspect_manager),
      package_resolver_(config_.boot_args),
      driver_loader_(config_.boot_args, std::move(config_.driver_index), &base_resolver_,
                     dispatcher, config_.require_system, &package_resolver_) {
  shutdown_system_state_ = config_.default_shutdown_system_state;

  root_device_ =
      fbl::MakeRefCounted<Device>(this, "root", fbl::String(), "root,", nullptr, ZX_PROTOCOL_ROOT,
                                  zx::vmo(), zx::channel(), fidl::ClientEnd<fio::Directory>());
  root_device_->flags = DEV_CTX_IMMORTAL | DEV_CTX_MUST_ISOLATE;

  bind_driver_manager_ =
      std::make_unique<BindDriverManager>(this, fit::bind_member<&Coordinator::AttemptBind>(this));

  device_manager_ = std::make_unique<DeviceManager>(this, config_.crash_policy);

  suspend_resume_manager_ = std::make_unique<SuspendResumeManager>(this, config_.suspend_timeout);
  firmware_loader_ =
      std::make_unique<FirmwareLoader>(this, firmware_dispatcher, config_.path_prefix);
  debug_dump_ = std::make_unique<DebugDump>(this);
}

Coordinator::~Coordinator() {}

void Coordinator::LoadV1Drivers(std::string_view sys_device_driver,
                                fbl::Vector<std::string>& driver_search_paths,
                                fbl::Vector<const char*>& load_drivers) {
  InitCoreDevices(sys_device_driver);

  // Load the drivers.
  for (const std::string& path : driver_search_paths) {
    find_loadable_drivers(boot_args(), path, fit::bind_member<&Coordinator::DriverAddedInit>(this));
  }
  for (const char* driver : load_drivers) {
    load_driver(boot_args(), driver, fit::bind_member<&Coordinator::DriverAddedInit>(this));
  }

  PrepareProxy(sys_device_, nullptr);

  // Bind all the drivers we loaded.
  AddAndBindDrivers(std::move(drivers_));
  DriverLoader::MatchDeviceConfig config;
  bind_driver_manager_->BindAllDevicesDriverIndex(config);

  // Bind the fallback drivers if we don't require the full system.
  if (config_.require_system) {
    LOGF(INFO, "Full system required, fallback drivers will be loaded after '/system' is loaded");
  } else {
    BindFallbackDrivers();
  }

  // Schedule the base drivers to load.
  driver_loader_.WaitForBaseDrivers([this]() {
    DriverLoader::MatchDeviceConfig config;
    config.only_return_base_and_fallback_drivers = true;
    bind_driver_manager_->BindAllDevicesDriverIndex(config);
  });

  devfs_publish(root_device_, sys_device_);

  // TODO(https://fxbug.dev/99076) Remove this when this issue is fixed.
  LOGF(INFO, "V1 drivers loaded and published");
}

void Coordinator::InitCoreDevices(std::string_view sys_device_driver) {
  // If the sys device is not a path, then we try to load it like a URL.
  if (sys_device_driver[0] != '/') {
    auto string = std::string(sys_device_driver.data());
    driver_loader_.LoadDriverUrl(string);
  }

  sys_device_ =
      fbl::MakeRefCounted<Device>(this, "sys", sys_device_driver, "sys,", root_device_, 0,
                                  zx::vmo(), zx::channel(), fidl::ClientEnd<fio::Directory>());
  sys_device_->flags = DEV_CTX_IMMORTAL | DEV_CTX_MUST_ISOLATE;
}

void Coordinator::RegisterWithPowerManager(fidl::ClientEnd<fio::Directory> devfs,
                                           RegisterWithPowerManagerCompletion completion) {
  auto system_state_endpoints = fidl::CreateEndpoints<fdm::SystemStateTransition>();
  if (system_state_endpoints.is_error()) {
    completion(system_state_endpoints.error_value());
    return;
  }
  std::unique_ptr<SystemStateManager> system_state_manager;
  auto status = SystemStateManager::Create(
      dispatcher_, this, std::move(system_state_endpoints->server), &system_state_manager);
  if (status != ZX_OK) {
    completion(status);
    return;
  }
  set_system_state_manager(std::move(system_state_manager));
  auto result = service::Connect<fpm::DriverManagerRegistration>();
  if (result.is_error()) {
    LOGF(ERROR, "Failed to connect to fuchsia.power.manager: %s", result.status_string());
    completion(result.error_value());
    return;
  }

  RegisterWithPowerManager(std::move(*result), std::move(system_state_endpoints->client),
                           std::move(devfs), std::move(completion));
}

void Coordinator::RegisterWithPowerManager(
    fidl::ClientEnd<fpm::DriverManagerRegistration> power_manager,
    fidl::ClientEnd<fdm::SystemStateTransition> system_state_transition,
    fidl::ClientEnd<fio::Directory> devfs, RegisterWithPowerManagerCompletion completion) {
  power_manager_client_.Bind(std::move(power_manager), dispatcher_);
  power_manager_client_->Register(std::move(system_state_transition), std::move(devfs))
      .ThenExactlyOnce(
          [this, completion = std::move(completion)](
              fidl::WireUnownedResult<fpm::DriverManagerRegistration::Register>& result) mutable {
            if (!result.ok()) {
              // In this branch, `this` could be invalidated.
              // We cannot use any member variable or member function.
              LOGF(INFO, "Failed to register with power_manager: %s\n",
                   result.error().FormatDescription().c_str());
              completion(result.status());
              return;
            }

            if (result->is_error()) {
              fpm::wire::RegistrationError err = result->error_value();
              if (err == fpm::wire::RegistrationError::kInvalidHandle) {
                LOGF(ERROR, "Failed to register with power_manager. Invalid handle.\n");
                completion(ZX_ERR_BAD_HANDLE);
                return;
              }
              LOGF(ERROR, "Failed to register with power_manager\n");
              completion(ZX_ERR_INTERNAL);
              return;
            }
            LOGF(INFO, "Registered with power manager successfully");
            set_power_manager_registered(true);
            completion(ZX_OK);
          });
}

const Driver* Coordinator::LibnameToDriver(std::string_view libname) const {
  for (const auto& drv : drivers_) {
    if (libname.compare(drv.libname) == 0) {
      return &drv;
    }
  }

  return driver_loader_.LibnameToDriver(libname);
}

zx_status_t Coordinator::LibnameToVmo(const fbl::String& libname, zx::vmo* out_vmo) const {
  const Driver* drv = LibnameToDriver(libname);
  if (drv == nullptr) {
    LOGF(ERROR, "Cannot find driver '%s'", libname.data());
    return ZX_ERR_NOT_FOUND;
  }

  // Check for cached DSO
  if (drv->dso_vmo != ZX_HANDLE_INVALID) {
    zx_status_t r = drv->dso_vmo.duplicate(
        ZX_RIGHTS_BASIC | ZX_RIGHTS_PROPERTY | ZX_RIGHT_READ | ZX_RIGHT_EXECUTE | ZX_RIGHT_MAP,
        out_vmo);
    if (r != ZX_OK) {
      LOGF(ERROR, "Cannot duplicate cached DSO for '%s' '%s'", drv->name.data(), libname.data());
    }
    return r;
  } else {
    return load_vmo(libname, out_vmo);
  }
}

zx_handle_t get_service_root();

zx_status_t Coordinator::GetTopologicalPath(const fbl::RefPtr<const Device>& dev, char* out,
                                            size_t max) {
  // TODO: Remove VLA.
  char tmp[max];
  char name_buf[fio::wire::kMaxFilename + strlen("dev/")];
  char* path = tmp + max - 1;
  *path = 0;
  size_t total = 1;

  fbl::RefPtr<const Device> itr = dev;
  while (itr != nullptr) {
    if (itr->flags & DEV_CTX_PROXY) {
      itr = itr->parent();
    }

    const char* name;
    if (itr->name().compare("root") == 0 && itr->parent() == nullptr) {
      name = "dev";
    } else if (itr->composite() != nullptr) {
      strcpy(name_buf, "dev/");
      strncpy(name_buf + strlen("dev/"), itr->name().data(), fio::wire::kMaxFilename);
      name_buf[sizeof(name_buf) - 1] = 0;
      name = name_buf;
    } else {
      name = itr->name().data();
    }

    size_t len = strlen(name) + 1;
    if (len > (max - total)) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }

    memcpy(path - len + 1, name, len - 1);
    path -= len;
    *path = '/';
    total += len;
    itr = itr->parent();
  }

  memcpy(out, path, total);
  return ZX_OK;
}

zx_status_t Coordinator::NewDriverHost(const char* name, fbl::RefPtr<DriverHost>* out) {
  std::string root_driver_path_arg;
  std::vector<const char*> env;
  if (driver_host_is_asan()) {
    env.push_back(kAsanEnvironment);
  }

  auto driver_host_env = (*boot_args())->Collect("driver.");
  if (!driver_host_env.ok()) {
    return driver_host_env.status();
  }

  std::vector<std::string> strings;
  for (auto& entry : driver_host_env.value().results) {
    strings.emplace_back(entry.data(), entry.size());
  }

  // Make the clock backstop boot arg available to drivers that
  // deal with time (RTC).
  // TODO(fxbug.dev/60668): Remove once UTC time is removed from the kernel.
  auto backstop_env = (*boot_args())->GetString("clock.backstop");
  if (!backstop_env.ok()) {
    return backstop_env.status();
  }

  auto backstop_env_value = std::move(backstop_env.value().value);
  if (!backstop_env_value.is_null()) {
    strings.push_back(std::string("clock.backstop=") +
                      std::string(backstop_env_value.data(), backstop_env_value.size()));
  }

  for (auto& entry : strings) {
    env.push_back(entry.data());
  }

  if (config_.log_to_debuglog) {
    env.push_back("devmgr.log-to-debuglog=true");
  }
  if (config_.verbose) {
    env.push_back("devmgr.verbose=true");
  }
  root_driver_path_arg = "devmgr.root_driver_path=" + config_.path_prefix + "driver/";
  env.push_back(root_driver_path_arg.c_str());

  env.push_back(nullptr);

  DriverHostConfig config{
      .name = name,
      .binary = kDriverHostPath,
      .env = env.data(),
      .job = zx::unowned_job(config_.driver_host_job),
      .root_resource = zx::unowned_resource(root_resource()),
      .loader_service_connector = &loader_service_connector_,
      .fs_provider = config_.fs_provider,
      .coordinator = this,
  };
  fbl::RefPtr<DriverHost> dh;
  zx_status_t status = DriverHost::Launch(config, &dh);
  if (status != ZX_OK) {
    return status;
  }
  launched_first_driver_host_ = true;

  VLOGF(1, "New driver_host %p", dh.get());
  *out = std::move(dh);
  return ZX_OK;
}

zx_status_t Coordinator::MakeVisible(const fbl::RefPtr<Device>& dev) {
  if (dev->state() == Device::State::kDead) {
    return ZX_ERR_BAD_STATE;
  }
  if (dev->state() == Device::State::kInitializing) {
    // This should only be called in response to the init hook completing.
    return ZX_ERR_BAD_STATE;
  }
  if (dev->flags & DEV_CTX_INVISIBLE) {
    dev->flags &= ~DEV_CTX_INVISIBLE;
    devfs_advertise(dev);
    zx_status_t r = dev->SignalReadyForBind();
    if (r != ZX_OK) {
      return r;
    }
  }
  return ZX_OK;
}

// Traverse up the device tree to find the metadata with the matching |type|.
// |buffer| can be nullptr, in which case only the size of the metadata is
// returned. This is used by GetMetadataSize method.
zx_status_t Coordinator::GetMetadata(const fbl::RefPtr<Device>& dev, uint32_t type, void* buffer,
                                     size_t buflen, size_t* size) {
  // search dev and its parent devices for a match
  fbl::RefPtr<Device> test = dev;
  while (true) {
    for (const auto& md : test->metadata()) {
      if (md.type == type) {
        if (buffer != nullptr) {
          if (md.length > buflen) {
            return ZX_ERR_BUFFER_TOO_SMALL;
          }
          memcpy(buffer, md.Data(), md.length);
        }
        *size = md.length;
        return ZX_OK;
      }
    }
    if (test->parent() == nullptr) {
      break;
    }
    test = test->parent();
  }

  // search fragments of composite devices
  if (test->composite()) {
    for (auto& fragment : test->composite()->bound_fragments()) {
      auto dev = fragment.bound_device();
      if (dev != nullptr) {
        if (GetMetadata(dev, type, buffer, buflen, size) == ZX_OK) {
          return ZX_OK;
        }
      }
    }
  }

  return ZX_ERR_NOT_FOUND;
}

zx_status_t Coordinator::AddMetadata(const fbl::RefPtr<Device>& dev, uint32_t type,
                                     const void* data, uint32_t length) {
  std::unique_ptr<Metadata> md;
  zx_status_t status = Metadata::Create(length, &md);
  if (status != ZX_OK) {
    return status;
  }

  md->type = type;
  md->length = length;
  memcpy(md->Data(), data, length);
  dev->AddMetadata(std::move(md));
  return ZX_OK;
}

// Create the proxy node for the given device if it doesn't exist and ensure it
// has a driver_host.  If |target_driver_host| is not nullptr and the proxy doesn't have
// a driver_host yet, |target_driver_host| will be used for it.  Otherwise a new driver_host
// will be created.
zx_status_t Coordinator::PrepareProxy(const fbl::RefPtr<Device>& dev,
                                      fbl::RefPtr<DriverHost> target_driver_host) {
  ZX_ASSERT(!(dev->flags & DEV_CTX_PROXY) && (dev->flags & DEV_CTX_MUST_ISOLATE));

  // proxy args are "processname,args"
  const char* arg0 = dev->args().data();
  const char* arg1 = strchr(arg0, ',');
  if (arg1 == nullptr) {
    LOGF(ERROR, "Missing proxy arguments, expected '%s,args' (see fxbug.dev/33674)", arg0);
    return ZX_ERR_INTERNAL;
  }
  size_t arg0len = arg1 - arg0;
  arg1++;

  char driver_hostname[32];
  snprintf(driver_hostname, sizeof(driver_hostname), "driver_host:%.*s", (int)arg0len, arg0);

  zx_status_t r;
  if (dev->proxy() == nullptr && (r = dev->CreateProxy()) != ZX_OK) {
    LOGF(ERROR, "Cannot create proxy device '%s': %s", dev->name().data(), zx_status_get_string(r));
    return r;
  }

  // if this device has no driver_host, first instantiate it
  if (dev->proxy()->host() == nullptr) {
    zx::channel h0, h1;
    // the immortal root devices do not provide proxy rpc
    bool need_proxy_rpc = !(dev->flags & DEV_CTX_IMMORTAL);

    if (need_proxy_rpc || dev == sys_device_) {
      // create rpc channel for proxy device to talk to the busdev it proxys
      if ((r = zx::channel::create(0, &h0, &h1)) < 0) {
        return r;
      }
    }
    if (target_driver_host == nullptr) {
      if ((r = NewDriverHost(driver_hostname, &target_driver_host)) < 0) {
        LOGF(ERROR, "Failed to create driver_host '%s': %s", driver_hostname,
             zx_status_get_string(r));
        return r;
      }
    }

    dev->proxy()->set_host(std::move(target_driver_host));
    if ((r = CreateProxyDevice(dev->proxy(), dev->proxy()->host(), arg1, std::move(h1))) < 0) {
      LOGF(ERROR, "Failed to create proxy device '%s' in driver_host '%s': %s", dev->name().data(),
           driver_hostname, zx_status_get_string(r));
      return r;
    }
    if (need_proxy_rpc) {
      if (auto result = dev->device_controller()->ConnectProxy(std::move(h0)); !result.ok()) {
        LOGF(ERROR, "Failed to connect to proxy device '%s' in driver_host '%s': %s",
             dev->name().data(), driver_hostname, zx_status_get_string(result.status()));
      }
    }
    if (dev == sys_device_) {
      if ((r = fdio_service_connect(kItemsPath, h0.release())) != ZX_OK) {
        LOGF(ERROR, "Failed to connect to %s: %s", kItemsPath, zx_status_get_string(r));
      }
    }
    zx::channel client_remote = dev->take_client_remote();
    if (client_remote.is_valid()) {
      if ((r = devfs_connect(dev->proxy().get(),
                             fidl::ServerEnd<fio::Node>(std::move(client_remote)))) != ZX_OK) {
        LOGF(ERROR, "Failed to connect to service from proxy device '%s' in driver_host '%s': %s",
             dev->name().data(), driver_hostname, zx_status_get_string(r));
      }
    }
  }

  return ZX_OK;
}

zx_status_t Coordinator::PrepareNewProxy(const fbl::RefPtr<Device>& dev,
                                         fbl::RefPtr<DriverHost> target_driver_host) {
  zx_status_t status;
  if (dev->new_proxy() == nullptr && (status = dev->CreateNewProxy()) != ZX_OK) {
    LOGF(ERROR, "Cannot create new proxy device '%s': %s", dev->name().data(),
         zx_status_get_string(status));
    return status;
  }

  char driver_hostname[32];
  snprintf(driver_hostname, sizeof(driver_hostname), "driver_host:%.*s",
           static_cast<int>(dev->name().size()), dev->name().data());

  if (target_driver_host == nullptr) {
    if (status = NewDriverHost(driver_hostname, &target_driver_host); status != ZX_OK) {
      LOGF(ERROR, "Failed to create driver_host '%s': %s", driver_hostname,
           zx_status_get_string(status));
      return status;
    }
  }
  dev->new_proxy()->set_host(std::move(target_driver_host));
  if (status = CreateNewProxyDevice(dev->new_proxy(), dev->new_proxy()->host(),
                                    dev->take_outgoing_dir());
      status != ZX_OK) {
    LOGF(ERROR, "Failed to create proxy device '%s' in driver_host '%s': %s", dev->name().data(),
         driver_hostname, zx_status_get_string(status));
    return status;
  }

  return ZX_OK;
}

zx_status_t Coordinator::AttemptBind(const Driver* drv, const fbl::RefPtr<Device>& dev) {
  if (!driver_host_is_asan() && drv->flags & ZIRCON_DRIVER_NOTE_FLAG_ASAN) {
    LOGF(ERROR, "%s (%s) requires ASAN, but we are not in an ASAN environment", drv->libname.data(),
         drv->name.data());
    return ZX_ERR_BAD_STATE;
  }

  // cannot bind driver to already bound device
  if (dev->IsAlreadyBound()) {
    return ZX_ERR_ALREADY_BOUND;
  }
  if (!(dev->flags & DEV_CTX_MUST_ISOLATE)) {
    VLOGF(1, "Binding driver to %s in same driver host as parent", dev->name().data());
    // non-busdev is pretty simple
    if (dev->host() == nullptr) {
      LOGF(ERROR, "Cannot bind to device '%s', it has no driver_host", dev->name().data());
      return ZX_ERR_BAD_STATE;
    }
    return BindDriverToDevice(dev, drv->libname.c_str());
  }

  zx_status_t status;
  if (dev->has_outgoing_directory()) {
    VLOGF(1, "Preparing new proxy for %s", dev->name().data());
    auto target_driver_host = (dev->flags & DEV_CTX_MUST_ISOLATE) ? nullptr : dev->host();
    status = PrepareNewProxy(dev, target_driver_host);
    if (status != ZX_OK) {
      return status;
    }
    status = BindDriverToDevice(dev->new_proxy(), drv->libname.c_str());
  } else {
    VLOGF(1, "Preparing old proxy for %s", dev->name().data());
    status = PrepareProxy(dev, nullptr /* target_driver_host */);
    if (status != ZX_OK) {
      return status;
    }
    status = BindDriverToDevice(dev->proxy(), drv->libname.c_str());
  }
  // TODO(swetland): arrange to mark us unbound when the proxy (or its driver_host) goes away
  if ((status == ZX_OK) && !(dev->flags & DEV_CTX_MULTI_BIND)) {
    dev->flags |= DEV_CTX_BOUND;
  }
  return status;
}

zx_status_t Coordinator::SetMexecZbis(zx::vmo kernel_zbi, zx::vmo data_zbi) {
  if (!kernel_zbi.is_valid() || !data_zbi.is_valid()) {
    return ZX_ERR_INVALID_ARGS;
  }

  if (zx_status_t status = mexec::PrepareDataZbi(root_resource().borrow(), data_zbi.borrow());
      status != ZX_OK) {
    LOGF(ERROR, "Failed to prepare mexec data ZBI: %s", zx_status_get_string(status));
    return status;
  }

  fidl::WireSyncClient<fuchsia_boot::Items> items;
  if (auto result = service::Connect<fuchsia_boot::Items>(); result.is_error()) {
    LOGF(ERROR, "Failed to connect to fuchsia.boot::Items: %s", result.status_string());
    return result.error_value();
  } else {
    items = fidl::BindSyncClient(std::move(result).value());
  }

  // Driver metadata that the driver framework generally expects to be present.
  constexpr std::array kItemsToAppend{ZBI_TYPE_DRV_MAC_ADDRESS, ZBI_TYPE_DRV_PARTITION_MAP,
                                      ZBI_TYPE_DRV_BOARD_PRIVATE, ZBI_TYPE_DRV_BOARD_INFO};
  zbitl::Image data_image{data_zbi.borrow()};
  for (uint32_t type : kItemsToAppend) {
    std::string_view name = zbitl::TypeName(type);

    // TODO(fxbug.dev/102804): Use a method that returns all matching items of
    // a given type instead of guessing possible `extra` values.
    for (uint32_t extra : std::array{0, 1, 2}) {
      fsl::SizedVmo payload;
      if (auto result = items->Get(type, extra); !result.ok()) {
        return result.status();
      } else if (!result.value().payload.is_valid()) {
        // Absence is signified with an empty result value.
        LOGF(INFO, "No %.*s item (%#xu) present to append to mexec data ZBI",
             static_cast<int>(name.size()), name.data(), type);
        continue;
      } else {
        payload = {std::move(result.value().payload), result.value().length};
      }

      std::vector<char> contents;
      if (!fsl::VectorFromVmo(payload, &contents)) {
        LOGF(ERROR, "Failed to read contents of %.*s item (%#xu)", static_cast<int>(name.size()),
             name.data(), type);
        return ZX_ERR_INTERNAL;
      }

      if (auto result = data_image.Append(zbi_header_t{.type = type, .extra = extra},
                                          zbitl::AsBytes(contents));
          result.is_error()) {
        LOGF(ERROR, "Failed to append %.*s item (%#xu) to mexec data ZBI: %s",
             static_cast<int>(name.size()), name.data(), type,
             zbitl::ViewErrorString(result.error_value()).c_str());
        return ZX_ERR_INTERNAL;
      }
    }
  }

  mexec_kernel_zbi_ = std::move(kernel_zbi);
  mexec_data_zbi_ = std::move(data_zbi);
  return ZX_OK;
}

// DriverAdded is called when a driver is added after the
// devcoordinator has started.  The driver is added to the new-drivers
// list and work is queued to process it.
void Coordinator::DriverAdded(Driver* drv, const char* version) {
  fbl::DoublyLinkedList<std::unique_ptr<Driver>> driver_list;
  driver_list.push_back(std::unique_ptr<Driver>(drv));
  async::PostTask(dispatcher_, [this, driver_list = std::move(driver_list)]() mutable {
    AddAndBindDrivers(std::move(driver_list));
  });
}

// DriverAddedInit is called from driver enumeration during
// startup and before the devcoordinator starts running.  Enumerated
// drivers are added directly to the all-drivers or fallback list.
//
// TODO: fancier priorities
void Coordinator::DriverAddedInit(Driver* drv, const char* version) {
  auto driver = std::unique_ptr<Driver>(drv);

  if (driver->fallback) {
    // fallback driver, load only if all else fails
    fallback_drivers_.push_front(std::move(driver));
  } else if (version[0] == '!') {
    // debugging / development hack
    // prioritize drivers with version "!..." over others
    drivers_.push_front(std::move(driver));
  } else {
    drivers_.push_back(std::move(driver));
  }
}

zx_status_t Coordinator::AddDeviceGroup(
    const fbl::RefPtr<Device>& dev, std::string_view name,
    fuchsia_device_manager::wire::DeviceGroupDescriptor group_desc) {
  if (group_desc.fragments.count() == 0) {
    return ZX_ERR_INVALID_ARGS;
  }

  char device_path[fdm::wire::kDevicePathMax + 1];
  zx_status_t status = GetTopologicalPath(dev, device_path, sizeof(device_path));
  if (status != ZX_OK) {
    return status;
  }

  // Append the device name to the path.
  auto topological_path = std::string(device_path) + "/";
  topological_path.append(name);

  status = driver_loader_.AddDeviceGroup(topological_path, group_desc.fragments);
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to add device group to the driver index.\n");
    return status;
  }

  status = bind_driver_manager_->AddDeviceGroup(topological_path, name, group_desc);
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to add device group to the bind driver manager.\n");
    return status;
  }

  return ZX_OK;
}

zx_status_t Coordinator::BindDriver(Driver* drv) {
  if (!running_) {
    return ZX_ERR_UNAVAILABLE;
  }
  for (auto& dev : device_manager_->devices()) {
    zx_status_t status =
        bind_driver_manager_->MatchAndBind(fbl::RefPtr(&dev), drv, true /* autobind */);
    if (status == ZX_ERR_NEXT || status == ZX_ERR_ALREADY_BOUND) {
      continue;
    }
    if (status != ZX_OK) {
      return status;
    }
  }
  return ZX_OK;
}

void Coordinator::AddAndBindDrivers(fbl::DoublyLinkedList<std::unique_ptr<Driver>> drivers) {
  std::unique_ptr<Driver> driver;
  while ((driver = drivers.pop_front()) != nullptr) {
    Driver* driver_ptr = driver.get();
    drivers_.push_back(std::move(driver));

    zx_status_t status = BindDriver(driver_ptr);
    if (status != ZX_OK && status != ZX_ERR_UNAVAILABLE) {
      LOGF(ERROR, "Failed to bind driver '%s': %s", driver_ptr->name.data(),
           zx_status_get_string(status));
    }
  }
}

void Coordinator::StartLoadingNonBootDrivers() { driver_loader_.StartSystemLoadingThread(this); }

void Coordinator::BindFallbackDrivers() {
  for (auto& driver : fallback_drivers_) {
    LOGF(INFO, "Fallback driver '%s' is available", driver.name.data());
  }

  AddAndBindDrivers(std::move(fallback_drivers_));
}

void Coordinator::GetDriverInfo(GetDriverInfoRequestView request,
                                GetDriverInfoCompleter::Sync& completer) {
  std::vector<const Driver*> driver_list;
  if (request->driver_filter.empty()) {
    for (const auto& driver : drivers()) {
      driver_list.push_back(&driver);
    }
  } else {
    for (const auto& d : request->driver_filter) {
      std::string_view driver_path(d.data(), d.size());
      for (const auto& drv : drivers()) {
        if (driver_path.compare(drv.libname) == 0) {
          driver_list.push_back(&drv);
          break;
        }
      }
    }
  }

  auto arena = std::make_unique<fidl::Arena<512>>();
  auto result = ::GetDriverInfo(*arena, driver_list);
  if (result.is_error()) {
    request->iterator.Close(result.status_value());
    return;
  }

  auto index_result = driver_loader_.GetDriverInfo(*arena, request->driver_filter);
  if (!index_result.is_error()) {
    result->reserve(result->size() + index_result->size());
    result->insert(result->end(), index_result->begin(), index_result->end());
  } else {
    LOGF(ERROR, "Failed to call index: %s\n", zx_status_get_string(index_result.status_value()));
  }

  // If we have driver filters check that we found one driver per filter.
  if (!request->driver_filter.empty() && (result->size() != request->driver_filter.count())) {
    request->iterator.Close(ZX_ERR_NOT_FOUND);
    return;
  }

  auto iterator = std::make_unique<DriverInfoIterator>(std::move(arena), std::move(*result));
  fidl::BindServer(dispatcher(), std::move(request->iterator), std::move(iterator));
}

void Coordinator::Register(RegisterRequestView request, RegisterCompleter::Sync& completer) {
  std::string driver_url_str(request->package_url.url.data(), request->package_url.url.size());
  zx_status_t status = LoadEphemeralDriver(&package_resolver_, driver_url_str);
  if (status != ZX_OK) {
    LOGF(ERROR, "Could not load '%s'", driver_url_str.c_str());
    completer.ReplyError(status);
    return;
  }
  LOGF(INFO, "Loaded driver '%s'", driver_url_str.c_str());
  completer.ReplySuccess();
}

zx_status_t Coordinator::LoadEphemeralDriver(internal::PackageResolverInterface* resolver,
                                             const std::string& package_url) {
  ZX_ASSERT(config_.enable_ephemeral);

  auto result = resolver->FetchDriver(package_url);
  if (!result.is_ok()) {
    return result.status_value();
  }
  fbl::DoublyLinkedList<std::unique_ptr<Driver>> driver_list;
  driver_list.push_back(std::move(result.value()));
  async::PostTask(dispatcher_, [this, driver_list = std::move(driver_list)]() mutable {
    AddAndBindDrivers(std::move(driver_list));
  });

  return ZX_OK;
}

void Coordinator::GetDeviceInfo(GetDeviceInfoRequestView request,
                                GetDeviceInfoCompleter::Sync& completer) {
  std::vector<fbl::RefPtr<Device>> device_list;
  if (request->device_filter.empty()) {
    for (auto& device : device_manager_->devices()) {
      device_list.push_back(fbl::RefPtr(&device));
    }
  } else {
    for (const auto& device_path : request->device_filter) {
      fbl::RefPtr<Device> device;
      std::string path(device_path.data(), device_path.size());
      zx_status_t status = devfs_walk(root_device_->devnode(), path.c_str(), &device);
      if (status != ZX_OK) {
        request->iterator.Close(status);
        return;
      }
      device_list.push_back(std::move(device));
    }
  }

  auto arena = std::make_unique<fidl::Arena<512>>();
  auto result = ::GetDeviceInfo(*arena, device_list);
  if (result.is_error()) {
    request->iterator.Close(result.status_value());
    return;
  }

  auto iterator = std::make_unique<DeviceInfoIterator>(std::move(arena), std::move(*result));
  fidl::BindServer(dispatcher(), std::move(request->iterator), std::move(iterator),
                   [](auto* server, fidl::UnbindInfo info, auto channel) {
                     if (!info.is_peer_closed()) {
                       LOGF(WARNING, "Closed DeviceInfoIterator: %s", info.lossy_description());
                     }
                   });
}

void Coordinator::BindAllUnboundNodes(BindAllUnboundNodesRequestView request,
                                      BindAllUnboundNodesCompleter::Sync& completer) {
  LOGF(WARNING, "BindAllUnboundNodes is only supported in DFv2.");
  completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
}

void Coordinator::UnregisterSystemStorageForShutdown(
    UnregisterSystemStorageForShutdownRequestView request,
    UnregisterSystemStorageForShutdownCompleter::Sync& completer) {
  suspend_resume_manager_->suspend_handler().UnregisterSystemStorageForShutdown(
      [completer = completer.ToAsync()](zx_status_t status) mutable { completer.Reply(status); });
}

zx::status<> Coordinator::PublishDriverDevelopmentService(
    const fbl::RefPtr<fs::PseudoDir>& svc_dir) {
  const auto driver_dev = [this](fidl::ServerEnd<fdd::DriverDevelopment> request) {
    fidl::BindServer<fidl::WireServer<fdd::DriverDevelopment>>(
        dispatcher_, std::move(request), this,
        [](fidl::WireServer<fdd::DriverDevelopment>* self, fidl::UnbindInfo info,
           fidl::ServerEnd<fdd::DriverDevelopment> server_end) {
          if (info.is_user_initiated()) {
            return;
          }
          if (info.is_peer_closed()) {
            // For this development protocol, the client is free to disconnect
            // at any time.
            return;
          }
          LOGF(ERROR, "Error serving '%s': %s",
               fidl::DiscoverableProtocolName<fdd::DriverDevelopment>,
               info.FormatDescription().c_str());
        });
    return ZX_OK;
  };
  zx_status_t status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fdd::DriverDevelopment>,
                                         fbl::MakeRefCounted<fs::Service>(driver_dev));
  return zx::make_status(status);
}

zx::status<> Coordinator::PublishDriverRegistrarService(const fbl::RefPtr<fs::PseudoDir>& svc_dir) {
  const auto driver_registrar = [this](fidl::ServerEnd<fdr::DriverRegistrar> request) {
    driver_registrar_binding_ = fidl::BindServer<fidl::WireServer<fdr::DriverRegistrar>>(
        dispatcher_, std::move(request), this);
    return ZX_OK;
  };
  zx_status_t status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fdr::DriverRegistrar>,
                                         fbl::MakeRefCounted<fs::Service>(driver_registrar));
  return zx::make_status(status);
}

zx_status_t Coordinator::InitOutgoingServices(const fbl::RefPtr<fs::PseudoDir>& svc_dir) {
  const auto admin = [this](fidl::ServerEnd<fdm::Administrator> request) {
    fidl::BindServer<fidl::WireServer<fdm::Administrator>>(dispatcher_, std::move(request), this);
    return ZX_OK;
  };
  zx_status_t status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fdm::Administrator>,
                                         fbl::MakeRefCounted<fs::Service>(admin));
  if (status != ZX_OK) {
    return status;
  }

  const auto system_state_manager_register =
      [this](fidl::ServerEnd<fdm::SystemStateTransition> request) {
        auto status = fidl::BindSingleInFlightOnly<fidl::WireServer<fdm::SystemStateTransition>>(
            dispatcher_, std::move(request), std::make_unique<SystemStateManager>(this));
        if (status != ZX_OK) {
          LOGF(ERROR, "Failed to bind to client channel for '%s': %s",
               fidl::DiscoverableProtocolName<fdm::SystemStateTransition>,
               zx_status_get_string(status));
        }
        return status;
      };
  status = svc_dir->AddEntry(fidl::DiscoverableProtocolName<fdm::SystemStateTransition>,
                             fbl::MakeRefCounted<fs::Service>(system_state_manager_register));
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to add entry in service directory for '%s': %s",
         fidl::DiscoverableProtocolName<fdm::SystemStateTransition>, zx_status_get_string(status));
    return status;
  }

  const auto debug = [this](fidl::ServerEnd<fdm::DebugDumper> request) {
    fidl::BindServer<fidl::WireServer<fdm::DebugDumper>>(dispatcher_, std::move(request),
                                                         debug_dump_.get());
    return ZX_OK;
  };
  return svc_dir->AddEntry(fidl::DiscoverableProtocolName<fdm::DebugDumper>,
                           fbl::MakeRefCounted<fs::Service>(debug));
}

std::string Coordinator::GetFragmentDriverUrl() const { return "#driver/fragment.so"; }

void Coordinator::RestartDriverHosts(RestartDriverHostsRequestView request,
                                     RestartDriverHostsCompleter::Sync& completer) {
  std::string_view driver_path(request->driver_path.data(), request->driver_path.size());

  // Find devices containing the driver.
  uint32_t count = 0;
  for (auto& dev : device_manager_->devices()) {
    // Call remove on the device's driver host if it contains the driver.
    if (dev.libname().compare(driver_path) == 0) {
      LOGF(INFO, "Device %s found in restart driver hosts.", dev.name().data());
      LOGF(INFO, "Shutting down host: %ld.", dev.host()->koid());

      // Unbind and Remove all the devices in the Driver Host.
      device_manager_->ScheduleUnbindRemoveAllDevices(dev.host());
      count++;
    }
  }

  completer.ReplySuccess(count);
}
