// 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 "driver_host.h"

#include <dlfcn.h>
#include <fuchsia/device/manager/c/fidl.h>
#include <fuchsia/device/manager/llcpp/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <inttypes.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/receiver.h>
#include <lib/async/cpp/wait.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/coding.h>
#include <lib/zx/debuglog.h>
#include <lib/zx/process.h>
#include <lib/zx/resource.h>
#include <lib/zx/vmo.h>
#include <lib/zxio/inception.h>
#include <lib/zxio/null.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/assert.h>
#include <zircon/dlfcn.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/log.h>

#include <memory>
#include <new>
#include <utility>
#include <vector>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <fbl/auto_call.h>
#include <fbl/auto_lock.h>
#include <fbl/function.h>
#include <fbl/string_printf.h>

#include "async_loop_owned_rpc_handler.h"
#include "composite_device.h"
#include "connection_destroyer.h"
#include "device_controller_connection.h"
#include "env.h"
#include "fidl_txn.h"
#include "log.h"
#include "main.h"
#include "proxy_iostate.h"
#include "scheduler_profile.h"
#include "tracing.h"

namespace {

llcpp::fuchsia::device::manager::DeviceProperty convert_device_prop(const zx_device_prop_t& prop) {
  return llcpp::fuchsia::device::manager::DeviceProperty{
      .id = prop.id,
      .reserved = prop.reserved,
      .value = prop.value,
  };
}

static fx_log_severity_t log_min_severity(const char* name, const char* flag) {
  if (!strcasecmp(flag, "error")) {
    return FX_LOG_ERROR;
  }
  if (!strcasecmp(flag, "warning")) {
    return FX_LOG_WARNING;
  }
  if (!strcasecmp(flag, "info")) {
    return FX_LOG_INFO;
  }
  if (!strcasecmp(flag, "debug")) {
    return FX_LOG_DEBUG;
  }
  if (!strcasecmp(flag, "trace")) {
    return FX_LOG_TRACE;
  }
  if (!strcasecmp(flag, "serial")) {
    return DDK_LOG_SERIAL;
  }
  LOGF(WARNING, "Invalid minimum log severity '%s' for driver '%s', will log all", flag, name);
  return FX_LOG_ALL;
}

zx_status_t log_rpc_result(const fbl::RefPtr<zx_device_t>& dev, const char* opname,
                           zx_status_t status, zx_status_t call_status = ZX_OK) {
  if (status != ZX_OK) {
    LOGD(ERROR, *dev, "Failed %s RPC: %s", opname, zx_status_get_string(status));
    return status;
  }
  if (call_status != ZX_OK && call_status != ZX_ERR_NOT_FOUND) {
    LOGD(ERROR, *dev, "Failed %s: %s", opname, zx_status_get_string(call_status));
  }
  return call_status;
}

}  // namespace

const char* mkdevpath(const zx_device_t& dev, char* const path, size_t max) {
  if (max == 0) {
    return "";
  }
  char* end = path + max;
  char sep = 0;

  auto append_name = [&end, &path, &sep](const zx_device_t& dev) {
    *(--end) = sep;

    size_t len = strlen(dev.name());
    if (len > static_cast<size_t>(end - path)) {
      return;
    }
    end -= len;
    memcpy(end, dev.name(), len);
    sep = '/';
  };

  append_name(dev);

  fbl::RefPtr<zx_device> itr_dev = dev.parent();
  while (itr_dev && end > path) {
    append_name(*itr_dev);
    itr_dev = itr_dev->parent();
  }

  // If devpath is longer than |max|, add an ellipsis.
  constexpr char ellipsis[] = "...";
  constexpr size_t ellipsis_len = sizeof(ellipsis) - 1;
  if (*end == sep && max > ellipsis_len) {
    if (ellipsis_len > static_cast<size_t>(end - path)) {
      end = path;
    } else {
      end -= ellipsis_len;
    }
    memcpy(end, ellipsis, ellipsis_len);
  }

  return end;
}

zx_status_t zx_driver::Create(std::string_view libname, InspectNodeCollection& drivers,
                              fbl::RefPtr<zx_driver>* out_driver) {
  char process_name[ZX_MAX_NAME_LEN] = {};
  zx::process::self()->get_property(ZX_PROP_NAME, process_name, sizeof(process_name));
  const char* tags[] = {process_name, "driver"};
  fx_logger_config_t config{
      .min_severity = FX_LOG_SEVERITY_DEFAULT,
      .console_fd = getenv_bool("devmgr.log-to-debuglog", false) ? dup(STDOUT_FILENO) : -1,
      .log_service_channel = ZX_HANDLE_INVALID,
      .tags = tags,
      .num_tags = std::size(tags),
  };
  fx_logger_t* logger;
  zx_status_t status = fx_logger_create(&config, &logger);
  if (status != ZX_OK) {
    return status;
  }

  *out_driver = fbl::AdoptRef(new zx_driver(logger, libname, drivers));
  return ZX_OK;
}

zx_driver::zx_driver(fx_logger_t* logger, std::string_view libname, InspectNodeCollection& drivers)
    : logger_(logger), libname_(libname), inspect_(drivers, std::string(libname)) {}

zx_driver::~zx_driver() { fx_logger_destroy(logger_); }

zx_status_t DriverHostContext::SetupRootDevcoordinatorConnection(zx::channel ch) {
  auto conn = std::make_unique<internal::DevhostControllerConnection>(this);
  if (conn == nullptr) {
    return ZX_ERR_NO_MEMORY;
  }

  conn->set_channel(std::move(ch));
  return internal::DevhostControllerConnection::BeginWait(std::move(conn), loop_.dispatcher());
}

// Send message to driver_manager asking to add child device to
// parent device.  Called under the api lock.
zx_status_t DriverHostContext::DriverManagerAdd(const fbl::RefPtr<zx_device_t>& parent,
                                                const fbl::RefPtr<zx_device_t>& child,
                                                const char* proxy_args,
                                                const zx_device_prop_t* props, uint32_t prop_count,
                                                zx::vmo inspect, zx::channel client_remote) {
  bool add_invisible = child->flags() & DEV_FLAG_INVISIBLE;
  fuchsia::device::manager::AddDeviceConfig add_device_config;

  if (child->flags() & DEV_FLAG_ALLOW_MULTI_COMPOSITE) {
    add_device_config |= fuchsia::device::manager::AddDeviceConfig::ALLOW_MULTI_COMPOSITE;
  }
  if (add_invisible) {
    add_device_config |= fuchsia::device::manager::AddDeviceConfig::INVISIBLE;
  }
  if (child->flags() & DEV_FLAG_UNBINDABLE) {
    add_device_config |= fuchsia::device::manager::AddDeviceConfig::SKIP_AUTOBIND;
  }

  zx_status_t status;
  zx::channel coordinator_local, coordinator_remote;
  if ((status = zx::channel::create(0, &coordinator_local, &coordinator_remote)) != ZX_OK) {
    return status;
  }

  zx::channel device_controller, device_controller_remote;
  if ((status = zx::channel::create(0, &device_controller, &device_controller_remote)) != ZX_OK) {
    return status;
  }

  fidl::Client<llcpp::fuchsia::device::manager::Coordinator> coordinator;
  coordinator.Bind(std::move(coordinator_local), loop_.dispatcher());
  std::unique_ptr<DeviceControllerConnection> conn;
  status = DeviceControllerConnection::Create(this, child, std::move(device_controller),
                                              std::move(coordinator), &conn);
  if (status != ZX_OK) {
    return status;
  }

  std::vector<llcpp::fuchsia::device::manager::DeviceProperty> props_list = {};
  for (size_t i = 0; i < prop_count; i++) {
    props_list.push_back(convert_device_prop(props[i]));
  }

  const auto rpc = parent->coordinator_client;
  if (!rpc) {
    return ZX_ERR_IO_REFUSED;
  }
  size_t proxy_args_len = proxy_args ? strlen(proxy_args) : 0;
  zx_status_t call_status = ZX_OK;
  static_assert(sizeof(zx_device_prop_t) == sizeof(uint64_t));
  uint64_t device_id = 0;
  auto response = rpc->AddDevice_Sync(
      std::move(coordinator_remote), std::move(device_controller_remote),
      ::fidl::unowned_vec(props_list), ::fidl::unowned_str(child->name(), strlen(child->name())),
      child->protocol_id(), ::fidl::unowned_str(child->driver->libname()),
      ::fidl::unowned_str(proxy_args, proxy_args_len), add_device_config,
      child->ops()->init /* has_init */, std::move(inspect), std::move(client_remote));
  status = response.status();
  if (status == ZX_OK) {
    if (response.Unwrap()->result.is_response()) {
      device_id = response.Unwrap()->result.response().local_device_id;
      if (add_invisible) {
        // Mark child as invisible until the init function is replied.
        child->set_flag(DEV_FLAG_INVISIBLE);
      }
    } else {
      call_status = response.Unwrap()->result.err();
    }
  }

  status = log_rpc_result(parent, "add-device", status, call_status);
  if (status != ZX_OK) {
    return status;
  }

  child->set_local_id(device_id);
  return DeviceControllerConnection::BeginWait(std::move(conn), loop_.dispatcher());
}

// Send message to driver_manager informing it that this device
// is being removed.  Called under the api lock.
zx_status_t DriverHostContext::DriverManagerRemove(fbl::RefPtr<zx_device_t> dev) {
  DeviceControllerConnection* conn = dev->conn.load();
  if (conn == nullptr) {
    LOGD(ERROR, *dev, "Invalid device controller connection");
    return ZX_ERR_INTERNAL;
  }
  VLOGD(1, *dev, "Removing device %p", dev.get());

  // This must be done before the RemoveDevice message is sent to
  // driver_manager, since driver_manager will close the channel in response.
  // The async loop may see the channel close before it sees the queued
  // shutdown packet, so it needs to check if dev->conn has been nulled to
  // handle that gracefully.
  dev->conn.store(nullptr);

  // Drop the device vnode, since no one should be able to open connections anymore.
  // This will break the reference cycle between the DevfsVnode and the zx_device.
  dev->vnode.reset();

  // respond to the remove fidl call
  dev->removal_cb(ZX_OK);

  // Forget our local ID, to release the reference stored by the local ID map
  dev->set_local_id(0);

  // Forget about our rpc channel since after the port_queue below it may be
  // closed.
  dev->rpc = zx::unowned_channel();
  dev->coordinator_client = nullptr;

  // queue an event to destroy the connection
  ConnectionDestroyer::Get()->QueueDeviceControllerConnection(loop_.dispatcher(), conn);

  // shut down our proxy rpc channel if it exists
  ProxyIosDestroy(dev);

  return ZX_OK;
}

void DriverHostContext::ProxyIosDestroy(const fbl::RefPtr<zx_device_t>& dev) {
  fbl::AutoLock guard(&dev->proxy_ios_lock);

  if (dev->proxy_ios) {
    dev->proxy_ios->CancelLocked(loop_.dispatcher());
  }
}

zx_status_t DriverHostContext::FindDriver(std::string_view libname, zx::vmo vmo,
                                          fbl::RefPtr<zx_driver_t>* out) {
  // check for already-loaded driver first
  for (auto& drv : drivers_) {
    if (!libname.compare(drv.libname())) {
      *out = fbl::RefPtr(&drv);
      return drv.status();
    }
  }

  fbl::RefPtr<zx_driver> new_driver;
  zx_status_t status = zx_driver::Create(libname, inspect().drivers(), &new_driver);
  if (status != ZX_OK) {
    return status;
  }

  // Let the |drivers_| list and our out parameter each have a refcount.
  drivers_.push_back(new_driver);
  *out = new_driver;

  const char* c_libname = new_driver->libname().c_str();

  void* dl = dlopen_vmo(vmo.get(), RTLD_NOW);
  if (dl == nullptr) {
    LOGF(ERROR, "Cannot load '%s': %s", c_libname, dlerror());
    new_driver->set_status(ZX_ERR_IO);
    return new_driver->status();
  }

  auto dn = static_cast<const zircon_driver_note_t*>(dlsym(dl, "__zircon_driver_note__"));
  if (dn == nullptr) {
    LOGF(ERROR, "Driver '%s' missing __zircon_driver_note__ symbol", c_libname);
    new_driver->set_status(ZX_ERR_IO);
    return new_driver->status();
  }
  auto ops = static_cast<const zx_driver_ops_t**>(dlsym(dl, "__zircon_driver_ops__"));
  auto dr = static_cast<zx_driver_rec_t*>(dlsym(dl, "__zircon_driver_rec__"));
  if (dr == nullptr) {
    LOGF(ERROR, "Driver '%s' missing __zircon_driver_rec__ symbol", c_libname);
    new_driver->set_status(ZX_ERR_IO);
    return new_driver->status();
  }
  // TODO(kulakowski) Eventually just check __zircon_driver_ops__,
  // when bind programs are standalone.
  if (ops == nullptr) {
    ops = &dr->ops;
  }
  if (!(*ops)) {
    LOGF(ERROR, "Driver '%s' has nullptr ops", c_libname);
    new_driver->set_status(ZX_ERR_INVALID_ARGS);
    return new_driver->status();
  }
  if ((*ops)->version != DRIVER_OPS_VERSION) {
    LOGF(ERROR, "Driver '%s' has bad driver ops version %#lx, expecting %#lx", c_libname,
         (*ops)->version, DRIVER_OPS_VERSION);
    new_driver->set_status(ZX_ERR_INVALID_ARGS);
    return new_driver->status();
  }

  new_driver->set_driver_rec(dr);
  new_driver->set_name(dn->payload.name);
  new_driver->set_ops(*ops);
  dr->driver = new_driver.get();

  // Check for minimum log severity of driver.
  const auto flag_name = fbl::StringPrintf("driver.%s.log", new_driver->name());
  const char* flag_value = getenv(flag_name.data());
  if (flag_value != nullptr) {
    fx_log_severity_t min_severity = log_min_severity(new_driver->name(), flag_value);
    status = fx_logger_set_min_severity(new_driver->logger(), min_severity);
    if (status != ZX_OK) {
      LOGF(ERROR, "Failed to set minimum log severity for driver '%s': %s", new_driver->name(),
           zx_status_get_string(status));
    } else {
      LOGF(INFO, "Driver '%s' set minimum log severity to %d", new_driver->name(), min_severity);
    }
  }

  if (new_driver->has_init_op()) {
    new_driver->set_status(new_driver->InitOp());
    if (new_driver->status() != ZX_OK) {
      LOGF(ERROR, "Driver '%s' failed in init: %s", c_libname,
           zx_status_get_string(new_driver->status()));
    }
  } else {
    new_driver->set_status(ZX_OK);
  }

  return new_driver->status();
}

namespace internal {

namespace {

// We need a global pointer to a DriverHostContext so that we can implement the functions exported
// to drivers.  Some of these functions unfortunately do not take an argument that can be used to
// find a context.
DriverHostContext* kContextForApi = nullptr;

}  // namespace

void RegisterContextForApi(DriverHostContext* context) {
  ZX_ASSERT((context == nullptr) != (kContextForApi == nullptr));
  kContextForApi = context;
}
DriverHostContext* ContextForApi() { return kContextForApi; }

void DevhostControllerConnection::CreateDevice(zx::channel coordinator_client,
                                               zx::channel device_controller_rpc,
                                               ::fidl::StringView driver_path_view,
                                               ::zx::vmo driver_vmo, ::zx::handle parent_proxy,
                                               ::fidl::StringView proxy_args,
                                               uint64_t local_device_id,
                                               CreateDeviceCompleter::Sync& completer) {
  std::string_view driver_path(driver_path_view.data(), driver_path_view.size());
  // This does not operate under the driver_host api lock,
  // since the newly created device is not visible to
  // any API surface until a driver is bound to it.
  // (which can only happen via another message on this thread)

  // named driver -- ask it to create the device
  fbl::RefPtr<zx_driver_t> drv;
  zx_status_t r = driver_host_context_->FindDriver(driver_path, std::move(driver_vmo), &drv);
  if (r != ZX_OK) {
    LOGF(ERROR, "Failed to load driver '%.*s': %s", driver_path.size(), driver_path.data(),
         zx_status_get_string(r));
    return;
  }
  if (!drv->has_create_op()) {
    LOGF(ERROR, "Driver does not support create operation");
    return;
  }

  fidl::Client<llcpp::fuchsia::device::manager::Coordinator> coordinator;
  coordinator.Bind(std::move(coordinator_client), driver_host_context_->loop().dispatcher());

  // Create a dummy parent device for use in this call to Create
  fbl::RefPtr<zx_device> parent;
  r = zx_device::Create(driver_host_context_, "device_create dummy", drv.get(), &parent);
  if (r != ZX_OK) {
    LOGF(ERROR, "Failed to create device: %s", zx_status_get_string(r));
    return;
  }
  // magic cookie for device create handshake
  CreationContext creation_context = {
      .parent = std::move(parent),
      .child = nullptr,
      .device_controller_rpc = zx::unowned_channel(device_controller_rpc),
      .coordinator_client = coordinator.get(),
  };

  r = drv->CreateOp(&creation_context, creation_context.parent, "proxy", proxy_args.data(),
                    parent_proxy.release());

  // Suppress a warning about dummy device being in a bad state.  The
  // message is spurious in this case, since the dummy parent never
  // actually begins its device lifecycle.  This flag is ordinarily
  // set by device_remove().
  creation_context.parent->set_flag(DEV_FLAG_DEAD);

  if (r != ZX_OK) {
    LOGF(ERROR, "Failed to create driver: %s", zx_status_get_string(r));
    return;
  }

  auto new_device = std::move(creation_context.child);
  if (new_device == nullptr) {
    LOGF(ERROR, "Driver did not create a device");
    return;
  }

  new_device->set_local_id(local_device_id);
  std::unique_ptr<DeviceControllerConnection> newconn;
  r = DeviceControllerConnection::Create(driver_host_context_, std::move(new_device),
                                         std::move(device_controller_rpc), std::move(coordinator),
                                         &newconn);
  if (r != ZX_OK) {
    return;
  }

  // TODO: inform devcoord
  VLOGF(1, "Created device %p '%.*s'", new_device.get(), driver_path.size(), driver_path.data());
  r = DeviceControllerConnection::BeginWait(std::move(newconn),
                                            driver_host_context_->loop().dispatcher());
  if (r != ZX_OK) {
    LOGF(ERROR, "Failed to wait for device controller connection: %s", zx_status_get_string(r));
    return;
  }
}

void DevhostControllerConnection::CreateCompositeDevice(
    zx::channel coordinator_client, zx::channel device_controller_rpc,
    ::fidl::VectorView<::llcpp::fuchsia::device::manager::Fragment> fragments,
    ::fidl::StringView name, uint64_t local_device_id,
    CreateCompositeDeviceCompleter::Sync& completer) {
  // Convert the fragment IDs into zx_device references
  CompositeFragments fragments_list(new CompositeFragment[fragments.count()], fragments.count());
  {
    // Acquire the API lock so that we don't have to worry about concurrent
    // device removes
    fbl::AutoLock lock(&driver_host_context_->api_lock());

    for (size_t i = 0; i < fragments.count(); ++i) {
      const auto& fragment = fragments.data()[i];
      uint64_t local_id = fragment.id;
      fbl::RefPtr<zx_device_t> dev = zx_device::GetDeviceFromLocalId(local_id);
      if (dev == nullptr || (dev->flags() & DEV_FLAG_DEAD)) {
        completer.Reply(ZX_ERR_NOT_FOUND);
        return;
      }
      fragments_list[i].name = std::string(fragment.name.data(), fragment.name.size());
      fragments_list[i].device = std::move(dev);
    }
  }

  auto driver = GetCompositeDriver(driver_host_context_);
  if (driver == nullptr) {
    completer.Reply(ZX_ERR_INTERNAL);
    return;
  }

  fbl::RefPtr<zx_device_t> dev;
  static_assert(fuchsia_device_manager_DEVICE_NAME_MAX + 1 >= sizeof(dev->name()));
  zx_status_t status = zx_device::Create(driver_host_context_,
                                         std::string(name.data(), name.size()), driver.get(), &dev);
  if (status != ZX_OK) {
    completer.Reply(status);
    return;
  }
  dev->set_local_id(local_device_id);

  fidl::Client<llcpp::fuchsia::device::manager::Coordinator> coordinator;
  coordinator.Bind(std::move(coordinator_client), driver_host_context_->loop().dispatcher());
  std::unique_ptr<DeviceControllerConnection> newconn;
  status = DeviceControllerConnection::Create(driver_host_context_, dev,
                                              std::move(device_controller_rpc),
                                              std::move(coordinator), &newconn);
  if (status != ZX_OK) {
    completer.Reply(status);
    return;
  }

  status = InitializeCompositeDevice(dev, std::move(fragments_list));
  if (status != ZX_OK) {
    completer.Reply(status);
    return;
  }

  VLOGF(1, "Created composite device %p '%s'", dev.get(), dev->name());
  status = DeviceControllerConnection::BeginWait(std::move(newconn),
                                                 driver_host_context_->loop().dispatcher());
  if (status != ZX_OK) {
    completer.Reply(status);
    return;
  }
  completer.Reply(ZX_OK);
}

void DevhostControllerConnection::CreateDeviceStub(zx::channel coordinator_client,
                                                   zx::channel device_controller_rpc,
                                                   uint32_t protocol_id, uint64_t local_device_id,
                                                   CreateDeviceStubCompleter::Sync& completer) {
  // This method is used for creating driverless proxies in case of misc, root, test devices.
  // Since there are no proxy drivers backing the device, a dummy proxy driver will be used for
  // device creation.
  if (!proxy_driver_) {
    auto status =
        zx_driver::Create("proxy", driver_host_context_->inspect().drivers(), &proxy_driver_);
    if (status != ZX_OK) {
      return;
    }
  }

  fbl::RefPtr<zx_device_t> dev;
  zx_status_t r = zx_device::Create(driver_host_context_, "proxy", proxy_driver_.get(), &dev);
  // TODO: dev->ops() and other lifecycle bits
  // no name means a dummy proxy device
  if (r != ZX_OK) {
    return;
  }
  dev->set_protocol_id(protocol_id);
  dev->set_ops(&kDeviceDefaultOps);
  dev->set_local_id(local_device_id);

  fidl::Client<llcpp::fuchsia::device::manager::Coordinator> coordinator;
  coordinator.Bind(std::move(coordinator_client), driver_host_context_->loop().dispatcher());
  std::unique_ptr<DeviceControllerConnection> newconn;
  r = DeviceControllerConnection::Create(driver_host_context_, dev,
                                         std::move(device_controller_rpc), std::move(coordinator),
                                         &newconn);
  if (r != ZX_OK) {
    return;
  }
  VLOGF(1, "Created device stub %p '%s'", dev.get(), dev->name());
  r = DeviceControllerConnection::BeginWait(std::move(newconn),
                                            driver_host_context_->loop().dispatcher());
  if (r != ZX_OK) {
    return;
  }
}

zx_status_t DevhostControllerConnection::HandleRead() {
  zx::unowned_channel conn = channel();
  uint8_t msg[ZX_CHANNEL_MAX_MSG_BYTES];
  zx_handle_info_t hin[ZX_CHANNEL_MAX_MSG_HANDLES];
  uint32_t msize = sizeof(msg);
  uint32_t hcount = std::size(hin);
  zx_status_t status = conn->read_etc(0, msg, hin, msize, hcount, &msize, &hcount);
  if (status != ZX_OK) {
    return status;
  }

  fidl_incoming_msg_t fidl_msg = {
      .bytes = msg,
      .handles = hin,
      .num_bytes = msize,
      .num_handles = hcount,
  };

  if (fidl_msg.num_bytes < sizeof(fidl_message_header_t)) {
    FidlHandleInfoCloseMany(fidl_msg.handles, fidl_msg.num_handles);
    return ZX_ERR_IO;
  }

  auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
  DevmgrFidlTxn txn(std::move(conn), hdr->txid);
  fuchsia::device::manager::DevhostController::Dispatch(this, &fidl_msg, &txn);
  return txn.Status();
}

// handles devcoordinator rpc

void DevhostControllerConnection::HandleRpc(std::unique_ptr<DevhostControllerConnection> conn,
                                            async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                            zx_status_t status, const zx_packet_signal_t* signal) {
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to wait on %p from driver_manager: %s", conn.get(),
         zx_status_get_string(status));
    return;
  }
  if (signal->observed & ZX_CHANNEL_READABLE) {
    status = conn->HandleRead();
    if (status != ZX_OK) {
      LOGF(FATAL, "Unhandled RPC on %p from driver_manager: %s", conn.get(),
           zx_status_get_string(status));
    }
    BeginWait(std::move(conn), dispatcher);
    return;
  }
  if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
    // This is expected in test environments where driver_manager has terminated.
    // TODO(fxbug.dev/52627): Support graceful termination.
    LOGF(WARNING, "Disconnected %p from driver_manager", conn.get());
    exit(1);
  }
  LOGF(WARNING, "Unexpected signal state %#08x", signal->observed);
  BeginWait(std::move(conn), dispatcher);
}

int main(int argc, char** argv) {
  char process_name[ZX_MAX_NAME_LEN] = {};
  zx::process::self()->get_property(ZX_PROP_NAME, process_name, sizeof(process_name));
  const char* tags[] = {process_name, "device"};
  fx_logger_config_t config{
      .min_severity = getenv_bool("devmgr.verbose", false) ? FX_LOG_ALL : FX_LOG_SEVERITY_DEFAULT,
      .console_fd = getenv_bool("devmgr.log-to-debuglog", false) ? dup(STDOUT_FILENO) : -1,
      .log_service_channel = ZX_HANDLE_INVALID,
      .tags = tags,
      .num_tags = std::size(tags),
  };
  zx_status_t status = fx_log_reconfigure(&config);
  if (status != ZX_OK) {
    return status;
  }

  zx::resource root_resource(zx_take_startup_handle(PA_HND(PA_RESOURCE, 0)));
  if (!root_resource.is_valid()) {
    LOGF(WARNING, "No root resource handle");
  }

  zx::channel root_conn_channel(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
  if (!root_conn_channel.is_valid()) {
    LOGF(ERROR, "Invalid root connection to driver_manager");
    return ZX_ERR_BAD_HANDLE;
  }

  DriverHostContext ctx(&kAsyncLoopConfigAttachToCurrentThread, std::move(root_resource));

  const char* root_driver_path = getenv("devmgr.root_driver_path");
  if (root_driver_path != nullptr) {
    ctx.set_root_driver_path(root_driver_path);
  }

  RegisterContextForApi(&ctx);

  status = connect_scheduler_profile_provider();
  if (status != ZX_OK) {
    LOGF(INFO, "Failed to connect to profile provider: %s", zx_status_get_string(status));
    return status;
  }

  if (getenv_bool("driver.tracing.enable", true)) {
    status = start_trace_provider();
    if (status != ZX_OK) {
      LOGF(INFO, "Failed to register trace provider: %s", zx_status_get_string(status));
      // This is not a fatal error.
    }
  }
  auto stop_tracing = fbl::AutoCall([]() { stop_trace_provider(); });

  status = ctx.SetupRootDevcoordinatorConnection(std::move(root_conn_channel));
  if (status != ZX_OK) {
    LOGF(ERROR, "Failed to watch root connection to driver_manager: %s",
         zx_status_get_string(status));
    return status;
  }

  status = ctx.inspect().Serve(zx::channel(zx_take_startup_handle(PA_DIRECTORY_REQUEST)),
                               ctx.loop().dispatcher());
  if (status != ZX_OK) {
    LOGF(WARNING, "driver_host: error serving diagnostics directory: %s\n",
         zx_status_get_string(status));
    // This is not a fatal error
  }

  return ctx.loop().Run(zx::time::infinite(), false /* once */);
}

}  // namespace internal

void DriverHostContext::MakeVisible(const fbl::RefPtr<zx_device_t>& dev,
                                    const device_make_visible_args_t* args) {
  ZX_ASSERT_MSG(!dev->ops()->init,
                "Cannot call device_make_visible if init hook is implemented."
                "The device will automatically be made visible once the init hook is replied to.");
  const auto client = dev->coordinator_client;
  if (!client) {
    return;
  }

  if (args && args->power_states && args->power_state_count != 0) {
    dev->SetPowerStates(args->power_states, args->power_state_count);
  }
  if (args && args->performance_states && (args->performance_state_count != 0)) {
    dev->SetPerformanceStates(args->performance_states, args->performance_state_count);
  }

  // TODO(teisenbe): Handle failures here...
  VLOGD(1, *dev, "make-visible");
  auto response = client->MakeVisible_Sync();
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK) {
    if (response.Unwrap()->result.is_err()) {
      call_status = response.Unwrap()->result.err();
    }
  }
  log_rpc_result(dev, "make-visible", status, call_status);
  dev->unset_flag(DEV_FLAG_INVISIBLE);

  // Reply to any pending bind/rebind requests, if all
  // the children are initialized.
  bool reply_bind_rebind = true;
  for (auto& child : dev->parent()->children()) {
    if (child.flags() & DEV_FLAG_INVISIBLE) {
      reply_bind_rebind = false;
    }
  }
  if (!reply_bind_rebind || !dev->parent()->complete_bind_rebind_after_init()) {
    return;
  }
  status = (status == ZX_OK) ? call_status : status;
  if (auto bind_conn = dev->parent()->take_bind_conn(); bind_conn) {
    bind_conn(status);
  }
  if (auto rebind_conn = dev->parent()->take_rebind_conn(); rebind_conn) {
    rebind_conn(status);
  }
}

zx_status_t DriverHostContext::ScheduleRemove(const fbl::RefPtr<zx_device_t>& dev,
                                              bool unbind_self) {
  const auto client = dev->coordinator_client;
  ZX_ASSERT(client);
  VLOGD(1, *dev, "schedule-remove");
  auto resp = client->ScheduleRemove(unbind_self);
  log_rpc_result(dev, "schedule-remove", resp.status());
  return resp.status();
}

zx_status_t DriverHostContext::ScheduleUnbindChildren(const fbl::RefPtr<zx_device_t>& dev) {
  const auto client = dev->coordinator_client;
  ZX_ASSERT(client);
  VLOGD(1, *dev, "schedule-unbind-children");
  auto resp = client->ScheduleUnbindChildren();
  log_rpc_result(dev, "schedule-unbind-children", resp.status());
  return resp.status();
}

zx_status_t DriverHostContext::GetTopoPath(const fbl::RefPtr<zx_device_t>& dev, char* path,
                                           size_t max, size_t* actual) {
  fbl::RefPtr<zx_device_t> remote_dev = dev;
  if (dev->flags() & DEV_FLAG_INSTANCE) {
    // Instances cannot be opened a second time. If dev represents an instance, return the path
    // to its parent, prefixed with an '@'.
    if (max < 1) {
      return ZX_ERR_BUFFER_TOO_SMALL;
    }
    path[0] = '@';
    path++;
    max--;
    remote_dev = dev->parent();
  }

  const auto client = remote_dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }

  VLOGD(1, *remote_dev, "get-topo-path");
  auto response = client->GetTopologicalPath_Sync();
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK) {
    if (response.Unwrap()->result.is_err()) {
      call_status = response.Unwrap()->result.err();
    } else {
      auto& r = response.Unwrap()->result.response();
      memcpy(path, r.path.data(), r.path.size());
      *actual = r.path.size();
    }
  }

  log_rpc_result(dev, "get-topo-path", status, call_status);
  if (status != ZX_OK) {
    return status;
  }
  if (call_status != ZX_OK) {
    return status;
  }

  path[*actual] = 0;
  *actual += 1;

  // Account for the prefixed '@' we may have added above.
  if (dev->flags() & DEV_FLAG_INSTANCE) {
    *actual += 1;
  }
  return ZX_OK;
}

zx_status_t DriverHostContext::DeviceBind(const fbl::RefPtr<zx_device_t>& dev,
                                          const char* drv_libname) {
  const auto client = dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }
  VLOGD(1, *dev, "bind-device");
  auto driver_path = ::fidl::unowned_str(drv_libname, strlen(drv_libname));
  auto response = client->BindDevice_Sync(std::move(driver_path));
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK && response.Unwrap()->result.is_err()) {
    call_status = response.Unwrap()->result.err();
  }
  log_rpc_result(dev, "bind-device", status, call_status);
  if (status != ZX_OK) {
    return status;
  }

  return call_status;
}

zx_status_t DriverHostContext::DeviceRunCompatibilityTests(const fbl::RefPtr<zx_device_t>& dev,
                                                           int64_t hook_wait_time) {
  const auto client = dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }
  VLOGD(1, *dev, "run-compatibility-test");
  auto response = client->RunCompatibilityTests_Sync(hook_wait_time);
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK && response.Unwrap()->result.is_err()) {
    call_status = response.Unwrap()->result.err();
  }
  log_rpc_result(dev, "run-compatibility-test", status, call_status);
  if (status != ZX_OK) {
    return status;
  }
  return call_status;
}

zx_status_t DriverHostContext::LoadFirmware(const fbl::RefPtr<zx_device_t>& dev, const char* path,
                                            zx_handle_t* vmo_handle, size_t* size) {
  if ((vmo_handle == nullptr) || (size == nullptr)) {
    return ZX_ERR_INVALID_ARGS;
  }

  zx::vmo vmo;
  const auto client = dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }
  VLOGD(1, *dev, "load-firmware");
  auto str_path = ::fidl::unowned_str(path, strlen(path));
  auto response = client->LoadFirmware_Sync(std::move(str_path));
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  auto result = std::move(response.Unwrap()->result);
  if (result.is_err()) {
    call_status = result.err();
  } else {
    auto resp = std::move(result.mutable_response());
    *size = resp.size;
    vmo = std::move(resp.vmo);
  }
  log_rpc_result(dev, "load-firmware", status, call_status);
  if (status != ZX_OK) {
    return status;
  }
  *vmo_handle = vmo.release();
  if (call_status == ZX_OK && *vmo_handle == ZX_HANDLE_INVALID) {
    return ZX_ERR_INTERNAL;
  }
  return call_status;
}

void DriverHostContext::LoadFirmwareAsync(const fbl::RefPtr<zx_device_t>& dev, const char* path,
                                          load_firmware_callback_t callback, void* context) {
  ZX_DEBUG_ASSERT(callback);

  fbl::RefPtr<zx_device_t> device_ref = dev;

  const auto client = dev->coordinator_client;
  if (!client) {
    callback(context, ZX_ERR_IO_REFUSED, ZX_HANDLE_INVALID, 0);
    return;
  }
  VLOGD(1, *dev, "load-firmware-async");
  auto str_path = ::fidl::unowned_str(path, strlen(path));
  auto result = client->LoadFirmware(
      std::move(str_path),
      [callback, context, dev = std::move(device_ref)](
          llcpp::fuchsia::device::manager::Coordinator::LoadFirmwareResponse* response) {
        zx_status_t call_status = ZX_OK;
        size_t size = 0;
        zx::vmo vmo;

        if (response->result.is_err()) {
          call_status = response->result.err();
        } else {
          auto& resp = response->result.mutable_response();
          size = resp.size;
          vmo = std::move(resp.vmo);
        }
        log_rpc_result(dev, "load-firmware-async", ZX_OK, call_status);
        if (call_status == ZX_OK && !vmo.is_valid()) {
          call_status = ZX_ERR_INTERNAL;
        }

        callback(context, call_status, vmo.release(), size);
      });

  if (result.status() != ZX_OK) {
    log_rpc_result(dev, "load-firmware-async", result.status(), ZX_OK);
    callback(context, result.status(), ZX_HANDLE_INVALID, 0);
  }
}

zx_status_t DriverHostContext::GetMetadata(const fbl::RefPtr<zx_device_t>& dev, uint32_t type,
                                           void* buf, size_t buflen, size_t* actual) {
  if (!buf) {
    return ZX_ERR_INVALID_ARGS;
  }

  const auto client = dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }
  VLOGD(1, *dev, "get-metadata");
  auto response = client->GetMetadata_Sync(type);
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK) {
    if (response->result.is_response()) {
      const auto& r = response.Unwrap()->result.mutable_response();
      if (r.data.count() > buflen) {
        return ZX_ERR_BUFFER_TOO_SMALL;
      }
      memcpy(buf, r.data.data(), r.data.count());
      if (actual != nullptr) {
        *actual = r.data.count();
      }
    } else {
      call_status = response->result.err();
    }
  }
  return log_rpc_result(dev, "get-metadata", status, call_status);
}

zx_status_t DriverHostContext::GetMetadataSize(const fbl::RefPtr<zx_device_t>& dev, uint32_t type,
                                               size_t* out_length) {
  const auto client = dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }
  VLOGD(1, *dev, "get-metadata-size");
  auto response = client->GetMetadataSize_Sync(type);
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK) {
    if (response->result.is_response()) {
      *out_length = response->result.response().size;
    } else {
      call_status = response->result.err();
    }
  }
  return log_rpc_result(dev, "get-metadata-size", status, call_status);
}

zx_status_t DriverHostContext::AddMetadata(const fbl::RefPtr<zx_device_t>& dev, uint32_t type,
                                           const void* data, size_t length) {
  if (!data && length) {
    return ZX_ERR_INVALID_ARGS;
  }
  const auto client = dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }
  VLOGD(1, *dev, "add-metadata");
  auto response = client->AddMetadata_Sync(
      type, ::fidl::VectorView(
                fidl::unowned_ptr(reinterpret_cast<uint8_t*>(const_cast<void*>(data))), length));
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK && response->result.is_err()) {
    call_status = response->result.err();
  }
  return log_rpc_result(dev, "add-metadata", status, call_status);
}

zx_status_t DriverHostContext::PublishMetadata(const fbl::RefPtr<zx_device_t>& dev,
                                               const char* path, uint32_t type, const void* data,
                                               size_t length) {
  if (!path || (!data && length)) {
    return ZX_ERR_INVALID_ARGS;
  }
  const auto client = dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }
  VLOGD(1, *dev, "publish-metadata");
  auto response = client->PublishMetadata_Sync(
      ::fidl::unowned_str(path, strlen(path)), type,
      ::fidl::VectorView(fidl::unowned_ptr(reinterpret_cast<uint8_t*>(const_cast<void*>(data))),
                         length));
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK && response->result.is_err()) {
    call_status = response->result.err();
  }
  return log_rpc_result(dev, "publish-metadata", status, call_status);
}

zx_status_t DriverHostContext::DeviceAddComposite(const fbl::RefPtr<zx_device_t>& dev,
                                                  const char* name,
                                                  const composite_device_desc_t* comp_desc) {
  if (comp_desc == nullptr || (comp_desc->props == nullptr && comp_desc->props_count > 0) ||
      comp_desc->fragments == nullptr || name == nullptr) {
    return ZX_ERR_INVALID_ARGS;
  }
  const auto client = dev->coordinator_client;
  if (!client) {
    return ZX_ERR_IO_REFUSED;
  }

  VLOGD(1, *dev, "create-composite");
  std::vector<fuchsia::device::manager::DeviceFragment> compvec = {};
  for (size_t i = 0; i < comp_desc->fragments_count; i++) {
    ::fidl::Array<fuchsia::device::manager::DeviceFragmentPart,
                  fuchsia::device::manager::DEVICE_FRAGMENT_PARTS_MAX>
        parts{};
    for (uint32_t j = 0; j < comp_desc->fragments[i].parts_count; j++) {
      ::fidl::Array<fuchsia::device::manager::BindInstruction,
                    fuchsia::device::manager::DEVICE_FRAGMENT_PART_INSTRUCTIONS_MAX>
          bind_instructions{};
      for (uint32_t k = 0; k < comp_desc->fragments[i].parts[j].instruction_count; k++) {
        bind_instructions[k] = fuchsia::device::manager::BindInstruction{
            .op = comp_desc->fragments[i].parts[j].match_program[k].op,
            .arg = comp_desc->fragments[i].parts[j].match_program[k].arg,
            .debug = comp_desc->fragments[i].parts[j].match_program[k].debug,
        };
      }
      auto part = fuchsia::device::manager::DeviceFragmentPart{
          .match_program_count = comp_desc->fragments[i].parts[j].instruction_count,
          .match_program = bind_instructions,
      };
      parts[j] = part;
    }
    auto dc = fuchsia::device::manager::DeviceFragment{
        .name = ::fidl::StringView{fidl::unowned_ptr(comp_desc->fragments[i].name),
                                   strnlen(comp_desc->fragments[i].name, 32)},
        .parts_count = comp_desc->fragments[i].parts_count,
        .parts = parts,
    };
    compvec.push_back(std::move(dc));
  }

  std::vector<fuchsia::device::manager::DeviceMetadata> metadata = {};
  for (size_t i = 0; i < comp_desc->metadata_count; i++) {
    auto meta = fuchsia::device::manager::DeviceMetadata{
        .key = comp_desc->metadata_list[i].type,
        .data = fidl::VectorView(fidl::unowned_ptr(reinterpret_cast<uint8_t*>(
                                     const_cast<void*>(comp_desc->metadata_list[i].data))),
                                 comp_desc->metadata_list[i].length)};
    metadata.emplace_back(std::move(meta));
  }

  std::vector<llcpp::fuchsia::device::manager::DeviceProperty> props = {};
  for (size_t i = 0; i < comp_desc->props_count; i++) {
    props.push_back(convert_device_prop(comp_desc->props[i]));
  }

  fuchsia::device::manager::CompositeDeviceDescriptor comp_dev = {
      .props = ::fidl::unowned_vec(props),
      .fragments = ::fidl::unowned_vec(compvec),
      .coresident_device_index = comp_desc->coresident_device_index,
      .metadata = ::fidl::unowned_vec(metadata)};

  static_assert(sizeof(comp_desc->props[0]) == sizeof(uint64_t));
  auto response =
      client->AddCompositeDevice_Sync(::fidl::unowned_str(name, strlen(name)), std::move(comp_dev));
  zx_status_t status = response.status();
  zx_status_t call_status = ZX_OK;
  if (status == ZX_OK && response->result.is_err()) {
    call_status = response->result.err();
  }
  return log_rpc_result(dev, "create-composite", status, call_status);
}
