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

#include <dlfcn.h>
#include <inttypes.h>
#include <new>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <utility>

#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/binding.h>

#include <zircon/dlfcn.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <zircon/syscalls/log.h>

#include <fbl/auto_lock.h>
#include <fbl/function.h>
#include <fs/handler.h>
#include <fuchsia/device/manager/c/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/receiver.h>
#include <lib/async/cpp/wait.h>
#include <lib/fdio/util.h>
#include <lib/fidl/coding.h>
#include <lib/zx/debuglog.h>
#include <lib/zx/resource.h>
#include <lib/zx/vmo.h>
#include <lib/zxio/null.h>

#include "../shared/async-loop-owned-rpc-handler.h"
#include "main.h"
#if ENABLE_DRIVER_TRACING
#include "tracing.h"
#endif
#include "../shared/env.h"
#include "../shared/fidl_txn.h"
#include "../shared/log.h"

zx_status_t zx_driver::Create(fbl::RefPtr<zx_driver>* out_driver) {
    *out_driver = fbl::AdoptRef(new zx_driver());
    return ZX_OK;
}

namespace devmgr {

uint32_t log_flags = LOG_ERROR | LOG_INFO;

struct ProxyIostate : AsyncLoopOwnedRpcHandler<ProxyIostate> {
    ProxyIostate() = default;
    ~ProxyIostate();

    // Creates a ProxyIostate and points |dev| at it.  The ProxyIostate is owned
    // by the async loop, and its destruction may be requested by calling
    // Cancel().
    static zx_status_t Create(const fbl::RefPtr<zx_device_t>& dev, zx::channel rpc);

    // Request the destruction of the proxy connection
    void Cancel();

    static void HandleRpc(fbl::unique_ptr<ProxyIostate> conn,
                          async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
                          const zx_packet_signal_t* signal);

    fbl::RefPtr<zx_device_t> dev;
};
static void proxy_ios_destroy(const fbl::RefPtr<zx_device_t>& dev);

static fbl::DoublyLinkedList<fbl::RefPtr<zx_driver>> dh_drivers;

// Access the devhost's async event loop
async::Loop* DevhostAsyncLoop() {
    static async::Loop loop(&kAsyncLoopConfigAttachToThread);
    return &loop;
}

static zx_status_t SetupRootDevcoordinatorConnection(zx::channel ch) {
    auto conn = fbl::make_unique<DevcoordinatorConnection>();
    if (conn == nullptr) {
        return ZX_ERR_NO_MEMORY;
    }

    conn->set_channel(std::move(ch));
    return DevcoordinatorConnection::BeginWait(std::move(conn), DevhostAsyncLoop()->dispatcher());
}

// Handles destroying Connection objects in the single-threaded DevhostAsyncLoop().
// This allows us to prevent races between canceling waiting on the connection
// channel and executing the connection's handler.
class ConnectionDestroyer {
public:
    static ConnectionDestroyer* Get() {
        static ConnectionDestroyer destroyer;
        return &destroyer;
    }

    zx_status_t QueueDevcoordinatorConnection(DevcoordinatorConnection* conn);
    zx_status_t QueueProxyConnection(ProxyIostate* conn);
private:
    ConnectionDestroyer() = default;

    ConnectionDestroyer(const ConnectionDestroyer&) = delete;
    ConnectionDestroyer& operator=(const ConnectionDestroyer&) = delete;

    ConnectionDestroyer(ConnectionDestroyer&&) = delete;
    ConnectionDestroyer& operator=(ConnectionDestroyer&&) = delete;

    static void Handler(async_dispatcher_t* dispatcher, async::Receiver* receiver,
                        zx_status_t status, const zx_packet_user_t* data);

    enum class Type {
        Devcoordinator,
        Proxy,
    };

    async::Receiver receiver_{ConnectionDestroyer::Handler};
};

zx_status_t ConnectionDestroyer::QueueProxyConnection(ProxyIostate* conn) {
    zx_packet_user_t pkt = {};
    pkt.u64[0] = static_cast<uint64_t>(Type::Proxy);
    pkt.u64[1] = reinterpret_cast<uintptr_t>(conn);
    return receiver_.QueuePacket(DevhostAsyncLoop()->dispatcher(), &pkt);
}

zx_status_t ConnectionDestroyer::QueueDevcoordinatorConnection(DevcoordinatorConnection* conn) {
    zx_packet_user_t pkt = {};
    pkt.u64[0] = static_cast<uint64_t>(Type::Devcoordinator);
    pkt.u64[1] = reinterpret_cast<uintptr_t>(conn);
    return receiver_.QueuePacket(DevhostAsyncLoop()->dispatcher(), &pkt);
}

void ConnectionDestroyer::Handler(async_dispatcher_t* dispatcher, async::Receiver* receiver,
                               zx_status_t status, const zx_packet_user_t* data) {
    Type type = static_cast<Type>(data->u64[0]);
    uintptr_t ptr = data->u64[1];

    switch (type) {
        case Type::Devcoordinator: {
            auto conn = reinterpret_cast<DevcoordinatorConnection*>(ptr);
            log(TRACE, "devhost: destroying devcoord conn '%p'\n", conn);
            delete conn;
            break;
        }
        case Type::Proxy: {
            auto conn = reinterpret_cast<ProxyIostate*>(ptr);
            log(TRACE, "devhost: destroying proxy conn '%p'\n", conn);
            delete conn;
            break;
        }
        default:
            ZX_ASSERT_MSG(false, "Unknown IosDestructionType %" PRIu64 "\n", data->u64[0]);
    }
}

static const char* mkdevpath(const fbl::RefPtr<zx_device_t>& dev, char* path, size_t max) {
    if (dev == nullptr) {
        return "";
    }
    if (max < 1) {
        return "<invalid>";
    }
    char* end = path + max;
    char sep = 0;

    fbl::RefPtr<zx_device> itr_dev(dev);
    while (itr_dev) {
        *(--end) = sep;

        size_t len = strlen(itr_dev->name);
        if (len > (size_t)(end - path)) {
            break;
        }
        end -= len;
        memcpy(end, itr_dev->name, len);
        sep = '/';
        itr_dev = itr_dev->parent;
    }
    return end;
}

static uint32_t logflagval(char* flag) {
    if (!strcmp(flag, "error")) {
        return DDK_LOG_ERROR;
    }
    if (!strcmp(flag, "warn")) {
        return DDK_LOG_WARN;
    }
    if (!strcmp(flag, "info")) {
        return DDK_LOG_INFO;
    }
    if (!strcmp(flag, "trace")) {
        return DDK_LOG_TRACE;
    }
    if (!strcmp(flag, "spew")) {
        return DDK_LOG_SPEW;
    }
    if (!strcmp(flag, "debug1")) {
        return DDK_LOG_DEBUG1;
    }
    if (!strcmp(flag, "debug2")) {
        return DDK_LOG_DEBUG2;
    }
    if (!strcmp(flag, "debug3")) {
        return DDK_LOG_DEBUG3;
    }
    if (!strcmp(flag, "debug4")) {
        return DDK_LOG_DEBUG4;
    }
    return static_cast<uint32_t>(strtoul(flag, nullptr, 0));
}

static void logflag(char* flag, uint32_t* flags) {
    if (*flag == '+') {
        *flags |= logflagval(flag + 1);
    } else if (*flag == '-') {
        *flags &= ~logflagval(flag + 1);
    }
}

static zx_status_t dh_find_driver(fbl::StringPiece libname, zx::vmo vmo,
                                  fbl::RefPtr<zx_driver_t>* out) {
    // check for already-loaded driver first
    for (auto& drv : dh_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(&new_driver);
    if (status != ZX_OK) {
        return status;
    }
    new_driver->set_libname(libname);

    // Let the |dh_drivers| list and our out parameter each have a refcount.
    dh_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) {
        log(ERROR, "devhost: cannot load '%s': %s\n", c_libname, dlerror());
        new_driver->set_status(ZX_ERR_IO);
        return new_driver->status();
    }

    const zircon_driver_note_t* dn;
    dn = static_cast<const zircon_driver_note_t*>(dlsym(dl, "__zircon_driver_note__"));
    if (dn == nullptr) {
        log(ERROR, "devhost: driver '%s' missing __zircon_driver_note__ symbol\n", c_libname);
        new_driver->set_status(ZX_ERR_IO);
        return new_driver->status();
    }
    zx_driver_rec_t* dr;
    dr = static_cast<zx_driver_rec_t*>(dlsym(dl, "__zircon_driver_rec__"));
    if (dr == nullptr) {
        log(ERROR, "devhost: driver '%s' missing __zircon_driver_rec__ symbol\n", c_libname);
        new_driver->set_status(ZX_ERR_IO);
        return new_driver->status();
    }
    if (!dr->ops) {
        log(ERROR, "devhost: driver '%s' has nullptr ops\n", c_libname);
        new_driver->set_status(ZX_ERR_INVALID_ARGS);
        return new_driver->status();
    }
    if (dr->ops->version != DRIVER_OPS_VERSION) {
        log(ERROR, "devhost: driver '%s' has bad driver ops version %" PRIx64
            ", expecting %" PRIx64 "\n", c_libname, dr->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(dr->ops);
    dr->driver = new_driver.get();

    // check for dprintf log level flags
    char tmp[128];
    snprintf(tmp, sizeof(tmp), "driver.%s.log", new_driver->name());
    char* log = getenv(tmp);
    if (log) {
        while (log) {
            char* sep = strchr(log, ',');
            if (sep) {
                *sep = 0;
                logflag(log, &dr->log_flags);
                *sep = ',';
                log = sep + 1;
            } else {
                logflag(log, &dr->log_flags);
                break;
            }
        }
        log(INFO, "devhost: driver '%s': log flags set to: 0x%x\n", new_driver->name(), dr->log_flags);
    }

    if (new_driver->has_init_op()) {
        new_driver->set_status(new_driver->InitOp());
        if (new_driver->status() != ZX_OK) {
            log(ERROR, "devhost: driver '%s' failed in init: %d\n",
                c_libname, new_driver->status());
        }
    } else {
        new_driver->set_status(ZX_OK);
    }

    return new_driver->status();
}

static zx_status_t dh_null_reply(fidl_txn_t* reply, const fidl_msg_t* msg) {
    return ZX_OK;
}

static fidl_txn_t dh_null_txn = {
    .reply = dh_null_reply,
};

struct DevhostRpcReadContext {
    const char* path;
    DevcoordinatorConnection* conn;
};

// Handler for when open() is called on a device
static zx_status_t fidl_devcoord_connection_directory_open(void* ctx, uint32_t flags, uint32_t mode,
                                                           const char* path_data, size_t path_size,
                                                           zx_handle_t object) {
    auto conn = static_cast<DevcoordinatorConnection*>(ctx);
    zx::channel c(object);
    return devhost_device_connect(conn->dev, flags, path_data, path_size, std::move(c));
}

static const fuchsia_io_Directory_ops_t kDevcoordinatorConnectionDirectoryOps = []() {
    fuchsia_io_Directory_ops_t ops;
    ops.Open = fidl_devcoord_connection_directory_open;
    return ops;
}();

static zx_status_t fidl_CreateDeviceStub(void* raw_ctx, zx_handle_t raw_rpc, uint32_t protocol_id) {
    auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
    zx::channel rpc(raw_rpc);
    log(RPC_IN, "devhost[%s] create device stub\n", ctx->path);

    auto newconn = fbl::make_unique<DevcoordinatorConnection>();
    if (!newconn) {
        return ZX_ERR_NO_MEMORY;
    }

    fbl::RefPtr<zx_device_t> dev;
    zx_status_t r = zx_device::Create(&dev);
    //TODO: dev->ops and other lifecycle bits
    // no name means a dummy proxy device
    if (r != ZX_OK) {
        return r;
    }
    strcpy(dev->name, "proxy");
    dev->protocol_id = protocol_id;
    dev->ops = &device_default_ops;
    dev->rpc = zx::unowned_channel(rpc);
    newconn->dev = dev;

    newconn->set_channel(std::move(rpc));
    log(RPC_IN, "devhost[%s] creating new stub conn=%p\n", ctx->path, newconn.get());
    if ((r = DevcoordinatorConnection::BeginWait(std::move(newconn),
                                                 DevhostAsyncLoop()->dispatcher())) != ZX_OK) {
        return r;
    }
    return ZX_OK;
}

static zx_status_t fidl_CreateDevice(void* raw_ctx, zx_handle_t raw_rpc,
                                     const char* driver_path_data, size_t driver_path_size,
                                     zx_handle_t raw_driver_vmo, zx_handle_t raw_parent_proxy,
                                     const char* proxy_args_data, size_t proxy_args_size) {
    auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
    zx::channel rpc(raw_rpc);
    zx::vmo driver_vmo(raw_driver_vmo);
    zx::handle parent_proxy(raw_parent_proxy);
    fbl::StringPiece driver_path(driver_path_data, driver_path_size);

    // This does not operate under the devhost 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)
    log(RPC_IN, "devhost[%s] create device drv='%.*s' args='%.*s'\n", ctx->path,
        static_cast<int>(driver_path_size), driver_path_data,
        static_cast<int>(proxy_args_size), proxy_args_data);

    auto newconn = fbl::make_unique<DevcoordinatorConnection>();
    if (!newconn) {
        return ZX_ERR_NO_MEMORY;
    }

    // named driver -- ask it to create the device
    fbl::RefPtr<zx_driver_t> drv;
    zx_status_t r = dh_find_driver(driver_path, std::move(driver_vmo), &drv);
    if (r != ZX_OK) {
        log(ERROR, "devhost[%s] driver load failed: %d\n", ctx->path, r);
        return r;
    }
    if (drv->has_create_op()) {
        // Create a dummy parent device for use in this call to Create
        fbl::RefPtr<zx_device> parent;
        if ((r = zx_device::Create(&parent)) != ZX_OK) {
            return r;
        }
        // magic cookie for device create handshake
        char dummy_name[sizeof(parent->name)] = "device_create dummy";
        memcpy(&parent->name, &dummy_name, sizeof(parent->name));

        CreationContext creation_context = {
            .parent = std::move(parent),
            .child = nullptr,
            .rpc = zx::unowned_channel(rpc),
        };

        char proxy_args[fuchsia_device_manager_DEVICE_ARGS_MAX + 1];
        memcpy(proxy_args, proxy_args_data, proxy_args_size);
        proxy_args[proxy_args_size] = 0;

        r = drv->CreateOp(&creation_context, creation_context.parent, "proxy", proxy_args, 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->flags |= DEV_FLAG_VERY_DEAD;

        if (r != ZX_OK) {
            log(ERROR, "devhost[%s] driver create() failed: %d\n", ctx->path, r);
            return r;
        }
        newconn->dev = std::move(creation_context.child);
        if (newconn->dev == nullptr) {
            log(ERROR, "devhost[%s] driver create() failed to create a device!", ctx->path);
            return ZX_ERR_BAD_STATE;
        }
    } else {
        log(ERROR, "devhost[%s] driver create() not supported\n", ctx->path);
        return ZX_ERR_NOT_SUPPORTED;
    }
    //TODO: inform devcoord

    newconn->set_channel(std::move(rpc));
    log(RPC_IN, "devhost[%s] creating '%.*s' conn=%p\n", ctx->path,
        static_cast<int>(driver_path_size), driver_path_data, newconn.get());
    if ((r = DevcoordinatorConnection::BeginWait(std::move(newconn),
                                                 DevhostAsyncLoop()->dispatcher())) != ZX_OK) {
        return r;
    }
    return ZX_OK;
}

static zx_status_t fidl_BindDriver(void* raw_ctx, const char* driver_path_data,
                                   size_t driver_path_size, zx_handle_t raw_driver_vmo,
                                   fidl_txn_t* txn) {
    auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
    zx::vmo driver_vmo(raw_driver_vmo);
    fbl::StringPiece driver_path(driver_path_data, driver_path_size);

    //TODO: api lock integration
    log(RPC_IN, "devhost[%s] bind driver '%.*s'\n", ctx->path,
        static_cast<int>(driver_path_size), driver_path_data);
    fbl::RefPtr<zx_driver_t> drv;
    if (ctx->conn->dev->flags & DEV_FLAG_DEAD) {
        log(ERROR, "devhost[%s] bind to removed device disallowed\n", ctx->path);
        return fuchsia_device_manager_ControllerBindDriver_reply(txn, ZX_ERR_IO_NOT_PRESENT);
    }

    zx_status_t r;
    if ((r = dh_find_driver(driver_path, std::move(driver_vmo), &drv)) < 0) {
        log(ERROR, "devhost[%s] driver load failed: %d\n", ctx->path, r);
        return fuchsia_device_manager_ControllerBindDriver_reply(txn, r);
    }

    if (drv->has_bind_op()) {
        CreationContext creation_ctx = {
            .parent = ctx->conn->dev,
            .child = nullptr,
            .rpc = zx::unowned_channel(),
        };
        r = drv->BindOp(&creation_ctx, ctx->conn->dev);

        if ((r == ZX_OK) && (creation_ctx.child == nullptr)) {
            printf("devhost: WARNING: driver '%.*s' did not add device in bind()\n",
                   static_cast<int>(driver_path_size), driver_path_data);
        }
        if (r != ZX_OK) {
            log(ERROR, "devhost[%s] bind driver '%.*s' failed: %d\n", ctx->path,
                   static_cast<int>(driver_path_size), driver_path_data, r);
        }
        return fuchsia_device_manager_ControllerBindDriver_reply(txn, r);
    }

    if (!drv->has_create_op()) {
        log(ERROR, "devhost[%s] neither create nor bind are implemented: '%.*s'\n",
            ctx->path, static_cast<int>(driver_path_size), driver_path_data);
    }
    return fuchsia_device_manager_ControllerBindDriver_reply(txn, ZX_ERR_NOT_SUPPORTED);
}

static zx_status_t fidl_ConnectProxy(void* raw_ctx, zx_handle_t raw_shadow) {
    auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
    zx::channel shadow(raw_shadow);

    log(RPC_SDW, "devhost[%s] connect proxy rpc\n", ctx->path);
    ctx->conn->dev->ops->rxrpc(ctx->conn->dev->ctx, ZX_HANDLE_INVALID);
    // Ignore any errors in the creation for now?
    // TODO(teisenbe/kulakowski): Investigate if this is the right thing
    ProxyIostate::Create(ctx->conn->dev, std::move(shadow));
    return ZX_OK;
}

static zx_status_t fidl_Suspend(void* raw_ctx, uint32_t flags, fidl_txn_t* txn) {
    auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
    // call suspend on the device this devhost is rooted on
    fbl::RefPtr<zx_device_t> device = ctx->conn->dev;
    while (device->parent != nullptr) {
        device = device->parent;
    }
    zx_status_t r;
    {
        ApiAutoLock lock;
        r = devhost_device_suspend(device, flags);
    }
    // TODO(teisenbe): We should probably check this return...
    fuchsia_device_manager_ControllerSuspend_reply(txn, r);
    return ZX_OK;
}

static zx_status_t fidl_RemoveDevice(void* raw_ctx) {
    auto ctx = static_cast<DevhostRpcReadContext*>(raw_ctx);
    device_remove(ctx->conn->dev.get());
    return ZX_OK;
}

static fuchsia_device_manager_Controller_ops_t fidl_ops = {
    .CreateDeviceStub = fidl_CreateDeviceStub,
    .CreateDevice = fidl_CreateDevice,
    .BindDriver = fidl_BindDriver,
    .ConnectProxy = fidl_ConnectProxy,
    .Suspend = fidl_Suspend,
    .RemoveDevice = fidl_RemoveDevice,
};

static zx_status_t dh_handle_rpc_read(zx_handle_t h, DevcoordinatorConnection* conn) {
    uint8_t msg[8192];
    zx_handle_t hin[ZX_CHANNEL_MAX_MSG_HANDLES];
    uint32_t msize = sizeof(msg);
    uint32_t hcount = fbl::count_of(hin);

    zx_status_t r;
    if ((r = zx_channel_read(h, 0, &msg, hin, msize, hcount, &msize, &hcount)) != ZX_OK) {
        return r;
    }

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

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

    char buffer[512];
    const char* path = mkdevpath(conn->dev, buffer, sizeof(buffer));

    // Double-check that Open (the only message we forward) cannot be mistaken for an
    // internal dev coordinator RPC message.
    static_assert(
        fuchsia_device_manager_ControllerCreateDeviceStubOrdinal !=
            fuchsia_io_DirectoryOpenOrdinal &&
        fuchsia_device_manager_ControllerCreateDeviceOrdinal != fuchsia_io_DirectoryOpenOrdinal &&
        fuchsia_device_manager_ControllerBindDriverOrdinal != fuchsia_io_DirectoryOpenOrdinal &&
        fuchsia_device_manager_ControllerConnectProxyOrdinal != fuchsia_io_DirectoryOpenOrdinal &&
        fuchsia_device_manager_ControllerSuspendOrdinal != fuchsia_io_DirectoryOpenOrdinal &&
        fuchsia_device_manager_ControllerRemoveDeviceOrdinal != fuchsia_io_DirectoryOpenOrdinal);

    auto hdr = static_cast<fidl_message_header_t*>(fidl_msg.bytes);
    if (hdr->ordinal == fuchsia_io_DirectoryOpenOrdinal) {
        log(RPC_RIO, "devhost[%s] FIDL OPEN\n", path);

        r = fuchsia_io_Directory_dispatch(conn, &dh_null_txn, &fidl_msg,
                                          &kDevcoordinatorConnectionDirectoryOps);
        if (r != ZX_OK) {
            log(ERROR, "devhost: OPEN failed: %d\n", r);
            return r;
        }
        return ZX_OK;
    }

    FidlTxn txn(zx::unowned_channel(h), hdr->txid);
    DevhostRpcReadContext read_ctx = { path, conn };
    return fuchsia_device_manager_Controller_dispatch(&read_ctx, txn.fidl_txn(), &fidl_msg,
                                                      &fidl_ops);
}

// handles devcoordinator rpc
void DevcoordinatorConnection::HandleRpc(fbl::unique_ptr<DevcoordinatorConnection> conn,
                                         async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                         zx_status_t status, const zx_packet_signal_t* signal) {
    if (status != ZX_OK) {
        log(ERROR, "devhost: devcoord conn wait error: %d\n", status);
        return;
    }
    if (signal->observed & ZX_CHANNEL_READABLE) {
        zx_status_t r = dh_handle_rpc_read(wait->object(), conn.get());
        if (r != ZX_OK) {
            log(ERROR, "devhost: devmgr rpc unhandleable ios=%p r=%d. fatal.\n", conn.get(), r);
            exit(0);
        }
        BeginWait(std::move(conn), dispatcher);
        return;
    }
    if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
        // Check if we were expecting this peer close.  If not, this could be a
        // serious bug.
        if (conn->dev->conn.load() == nullptr) {
            // We're in the middle of shutting down, so just stop processing
            // signals and wait for the queued shutdown packet.  It has a
            // reference to the connection, which it will use to recover
            // ownership of it.
            __UNUSED auto r = conn.release();
            return;
        }

        log(ERROR, "devhost: devmgr disconnected! fatal. (conn=%p)\n", conn.get());
        exit(0);
    }
    log(ERROR, "devhost: no work? %08x\n", signal->observed);
    BeginWait(std::move(conn), dispatcher);
}

// handles remoteio rpc
void DevfsConnection::HandleRpc(fbl::unique_ptr<DevfsConnection> conn,
                                async_dispatcher_t* dispatcher, async::WaitBase* wait,
                                zx_status_t status, const zx_packet_signal_t* signal) {
    if (status != ZX_OK) {
        log(ERROR, "devhost: devfs conn wait error: %d\n", status);
        return;
    }

    if (signal->observed & ZX_CHANNEL_READABLE) {
        status = fs::ReadMessage(wait->object(), [&conn](fidl_msg_t* msg, fs::FidlConnection* txn) {
            return devhost_fidl_handler(msg, txn->Txn(), conn.get());
        });
        if (status == ZX_OK) {
            BeginWait(std::move(conn), dispatcher);
            return;
        }
    } else if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
        fs::CloseMessage([&conn](fidl_msg_t* msg, fs::FidlConnection* txn) {
            return devhost_fidl_handler(msg, txn->Txn(), conn.get());
        });
    } else {
        printf("dh_handle_fidl_rpc: invalid signals %x\n", signal->observed);
        exit(0);
    }

    // We arrive here if devhost_fidl_handler was a clean close (ERR_DISPATCHER_DONE),
    // or close-due-to-error (non-ZX_OK), or if the channel was closed
    // out from under us.  In all cases, we are done with this connection, so we
    // will destroy it by letting it leave scope.
    log(TRACE, "devhost: destroying devfs conn %p\n", conn.get());
}

ProxyIostate::~ProxyIostate() {
    fbl::AutoLock guard(&dev->proxy_ios_lock);
    if (dev->proxy_ios == this) {
        dev->proxy_ios = nullptr;
    }
}

// Handling RPC From Proxy Devices to BusDevs
void ProxyIostate::HandleRpc(fbl::unique_ptr<ProxyIostate> conn, async_dispatcher_t* dispatcher,
                             async::WaitBase* wait, zx_status_t status,
                             const zx_packet_signal_t* signal) {
    if (status != ZX_OK) {
        return;
    }

    if (conn->dev == nullptr) {
        log(RPC_SDW, "proxy-rpc: stale rpc? (ios=%p)\n", conn.get());
        // Do not re-issue the wait here
        return;
    }
    if (signal->observed & ZX_CHANNEL_READABLE) {
        log(RPC_SDW, "proxy-rpc: rpc readable (ios=%p,dev=%p)\n", conn.get(), conn->dev.get());
        zx_status_t r = conn->dev->ops->rxrpc(conn->dev->ctx, wait->object());
        if (r != ZX_OK) {
            log(RPC_SDW, "proxy-rpc: rpc cb error %d (ios=%p,dev=%p)\n", r, conn.get(),
                conn->dev.get());
            // Let |conn| be destroyed
            return;
        }
        BeginWait(std::move(conn), dispatcher);
        return;
    }
    if (signal->observed & ZX_CHANNEL_PEER_CLOSED) {
        log(RPC_SDW, "proxy-rpc: peer closed (ios=%p,dev=%p)\n", conn.get(), conn->dev.get());
        // Let |conn| be destroyed
        return;
    }
    log(ERROR, "devhost: no work? %08x\n", signal->observed);
    BeginWait(std::move(conn), dispatcher);
}

zx_status_t ProxyIostate::Create(const fbl::RefPtr<zx_device_t>& dev, zx::channel rpc) {
    // This must be held for the adding of the channel to the port, since the
    // async loop may run immediately after that point.
    fbl::AutoLock guard(&dev->proxy_ios_lock);

    if (dev->proxy_ios) {
        dev->proxy_ios->Cancel();
        dev->proxy_ios = nullptr;
    }

    auto ios = fbl::make_unique<ProxyIostate>();
    if (ios == nullptr) {
        return ZX_ERR_NO_MEMORY;
    }

    ios->dev = dev;
    ios->set_channel(std::move(rpc));

    // |ios| is will be owned by the async loop.  |dev| holds a reference that will be
    // cleared prior to destruction.
    dev->proxy_ios = ios.get();

    zx_status_t status = BeginWait(std::move(ios), DevhostAsyncLoop()->dispatcher());
    if (status != ZX_OK) {
        dev->proxy_ios = nullptr;
        return status;
    }

    return ZX_OK;
}

// The device for which ProxyIostate is currently attached to should have
// its proxy_ios_lock held across Cancel().
void ProxyIostate::Cancel() {
    // TODO(teisenbe): We should probably check the return code in case the
    // queue was full
    ConnectionDestroyer::Get()->QueueProxyConnection(this);
}

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

    if (dev->proxy_ios) {
        dev->proxy_ios->Cancel();
    }
    dev->proxy_ios = nullptr;
}


#define LOGBUF_MAX (ZX_LOG_RECORD_MAX - sizeof(zx_log_record_t))

static zx::debuglog devhost_log_handle;

static ssize_t devhost_log_write_internal(uint32_t flags, const void* void_data, size_t len) {
    struct Context {
        Context() = default;

        uint32_t next = 0;
        zx::unowned_debuglog handle;
        char data[LOGBUF_MAX] = {};
    };
    static thread_local fbl::unique_ptr<Context> ctx;

    if (ctx == nullptr) {
        ctx = fbl::make_unique<Context>();
        if (ctx == nullptr) {
            return len;
        }
        ctx->handle = zx::unowned_debuglog(devhost_log_handle);
    }

    const char* data = static_cast<const char*>(void_data);
    size_t r = len;

    auto flush_context = [&]() {
        ctx->handle->write(flags, ctx->data, ctx->next);
        ctx->next = 0;
    };

    while (len-- > 0) {
        char c = *data++;
        if (c == '\n') {
            if (ctx->next) {
                flush_context();
            }
            continue;
        }
        if (c < ' ') {
            continue;
        }
        ctx->data[ctx->next++] = c;
        if (ctx->next == LOGBUF_MAX) {
            flush_context();
        }
    }
    return r;
}

} // namespace devmgr

__EXPORT void driver_printf(uint32_t flags, const char* fmt, ...) {
    char buffer[512];
    va_list ap;
    va_start(ap, fmt);
    int r = vsnprintf(buffer, sizeof(buffer), fmt, ap);
    va_end(ap);

    if (r > (int)sizeof(buffer)) {
        r = sizeof(buffer);
    }

    devmgr::devhost_log_write_internal(flags, buffer, r);
}

namespace devmgr {

static zx_status_t devhost_log_write(zxio_t* io, const void* buffer,
                                     size_t capacity, size_t* out_actual) {
    devhost_log_write_internal(0, buffer, capacity);
    *out_actual = capacity;
    return ZX_OK;
}

static constexpr zxio_ops_t devhost_log_ops = []() {
    zxio_ops_t ops = zxio_default_ops;
    ops.write = devhost_log_write;
    return ops;
}();

static void devhost_io_init() {
    if (zx::debuglog::create(zx::resource(), 0, &devhost_log_handle) < 0) {
        return;
    }
    fdio_t* io = nullptr;
    zxio_storage_t* storage = nullptr;
    if ((io = fdio_zxio_create(&storage)) == nullptr) {
        return;
    }
    zxio_init(&storage->io, &devhost_log_ops);
    close(1);
    fdio_bind_to_fd(io, 1, 0);
    dup2(1, 2);
}

// Send message to devcoordinator asking to add child device to
// parent device.  Called under devhost api lock.
zx_status_t devhost_add(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) {
    char buffer[512];
    const char* path = mkdevpath(parent, buffer, sizeof(buffer));
    log(RPC_OUT, "devhost[%s] add '%s'\n", path, child->name);

    bool add_invisible = child->flags & DEV_FLAG_INVISIBLE;

    auto conn = fbl::make_unique<DevcoordinatorConnection>();
    if (!conn) {
        return ZX_ERR_NO_MEMORY;
    }

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

    const zx::channel& rpc = *parent->rpc;
    if (!rpc.is_valid()) {
        return ZX_ERR_IO_REFUSED;
    }
    size_t proxy_args_len = proxy_args ? strlen(proxy_args) : 0;
    zx_status_t call_status;
    static_assert(sizeof(zx_device_prop_t) == sizeof(uint64_t));
    if (add_invisible) {
        status = fuchsia_device_manager_CoordinatorAddDeviceInvisible(
                rpc.get(), hsend.release(), reinterpret_cast<const uint64_t*>(props), prop_count,
                child->name, strlen(child->name), child->protocol_id,
                child->driver->libname().data(), child->driver->libname().size(), proxy_args,
                proxy_args_len, &call_status);
    } else {
        status = fuchsia_device_manager_CoordinatorAddDevice(
                rpc.get(), hsend.release(), reinterpret_cast<const uint64_t*>(props), prop_count,
                child->name, strlen(child->name), child->protocol_id,
                child->driver->libname().data(), child->driver->libname().size(), proxy_args,
                proxy_args_len, &call_status);
    }
    if (status != ZX_OK) {
        log(ERROR, "devhost[%s] add '%s': rpc sending failed: %d\n", path, child->name, status);
        return status;
    } else if (call_status != ZX_OK) {
        log(ERROR, "devhost[%s] add '%s': rpc failed: %d\n", path, child->name, call_status);
        return call_status;
    }

    child->rpc = zx::unowned_channel(hrpc);
    child->conn.store(conn.get());

    conn->dev = child;
    conn->set_channel(std::move(hrpc));
    status = DevcoordinatorConnection::BeginWait(std::move(conn), DevhostAsyncLoop()->dispatcher());
    if (status != ZX_OK) {
        child->conn.store(nullptr);
        child->rpc = zx::unowned_channel();
        return status;
    }
    return ZX_OK;
}

static void log_rpc(const fbl::RefPtr<zx_device_t>& dev, const char* opname) {
    char buffer[512];
    const char* path = mkdevpath(dev, buffer, sizeof(buffer));
    log(RPC_OUT, "devhost[%s] %s'\n", path, opname);
}

static void log_rpc_result(const char* opname, zx_status_t status, zx_status_t call_status) {
    if (status != ZX_OK) {
        log(ERROR, "devhost: rpc:%s sending failed: %d\n", opname, status);
    } else if (call_status != ZX_OK) {
        log(ERROR, "devhost: rpc:%s failed: %d\n", opname, call_status);
    }
}

void devhost_make_visible(const fbl::RefPtr<zx_device_t>& dev) {
    const zx::channel& rpc = *dev->rpc;
    if (!rpc.is_valid()) {
        return;
    }

    // TODO(teisenbe): Handle failures here...
    log_rpc(dev, "make-visible");
    zx_status_t call_status;
    zx_status_t status = fuchsia_device_manager_CoordinatorMakeVisible(
            rpc.get(), &call_status);
    log_rpc_result("make-visible", status, call_status);
}

// Send message to devcoordinator informing it that this device
// is being removed.  Called under devhost api lock.
zx_status_t devhost_remove(const fbl::RefPtr<zx_device_t>& dev) {
    DevcoordinatorConnection* conn = dev->conn.load();
    if (conn == nullptr) {
        log(ERROR, "removing device %p, conn is nullptr\n", dev.get());
        return ZX_ERR_INTERNAL;
    }

    // This must be done before the RemoveDevice message is sent to
    // devcoordinator, since devcoordinator 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);

    log(DEVLC, "removing device %p, conn %p\n", dev.get(), conn);

    const zx::channel& rpc = *dev->rpc;
    ZX_ASSERT(rpc.is_valid());
    // TODO(teisenbe): Handle failures here...
    log_rpc(dev, "remove-device");
    zx_status_t call_status;
    zx_status_t status = fuchsia_device_manager_CoordinatorRemoveDevice(rpc.get(), &call_status);
    log_rpc_result("remove-device", status, call_status);

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

    // queue an event to destroy the connection
    ConnectionDestroyer::Get()->QueueDevcoordinatorConnection(conn);

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

    return ZX_OK;
}

zx_status_t devhost_get_topo_path(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 zx::channel& rpc = *remote_dev->rpc;
    if (!rpc.is_valid()) {
        return ZX_ERR_IO_REFUSED;
    }

    log_rpc(remote_dev, "get-topo-path");
    zx_status_t call_status;
    zx_status_t status = fuchsia_device_manager_CoordinatorGetTopologicalPath(
            rpc.get(), &call_status, path, max - 1, actual);
    log_rpc_result("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 devhost_device_bind(const fbl::RefPtr<zx_device_t>& dev, const char* drv_libname) {
    const zx::channel& rpc = *dev->rpc;
    if (!rpc.is_valid()) {
        return ZX_ERR_IO_REFUSED;
    }
    log_rpc(dev, "bind-device");
    zx_status_t call_status;
    zx_status_t status = fuchsia_device_manager_CoordinatorBindDevice(
            rpc.get(), drv_libname, strlen(drv_libname), &call_status);
    log_rpc_result("bind-device", status, call_status);
    if (status != ZX_OK) {
        return status;
    }
    return call_status;
}

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

    const zx::channel& rpc = *dev->rpc;
    if (!rpc.is_valid()) {
        return ZX_ERR_IO_REFUSED;
    }
    log_rpc(dev, "load-firmware");
    zx_status_t call_status;
    zx_status_t status = fuchsia_device_manager_CoordinatorLoadFirmware(
            rpc.get(), path, strlen(path), &call_status, vmo, size);
    log_rpc_result("load-firmware", status, call_status);
    if (status != ZX_OK) {
        return status;
    }
    if (call_status == ZX_OK && *vmo == ZX_HANDLE_INVALID) {
        return ZX_ERR_INTERNAL;
    }
    return call_status;
}

zx_status_t devhost_get_metadata(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 zx::channel& rpc = *dev->rpc;
    if (!rpc.is_valid()) {
        return ZX_ERR_IO_REFUSED;
    }
    uint8_t data[fuchsia_device_manager_METADATA_MAX];
    size_t length = 0;
    log_rpc(dev, "get-metadata");
    zx_status_t call_status;
    zx_status_t status = fuchsia_device_manager_CoordinatorGetMetadata(
            rpc.get(), type, &call_status, data, sizeof(data), &length);
    if (status != ZX_OK) {
        log(ERROR, "devhost: rpc:get-metadata sending failed: %d\n", status);
        return status;
    }
    if (call_status != ZX_OK) {
        if (call_status != ZX_ERR_NOT_FOUND) {
            log(ERROR, "devhost: rpc:get-metadata failed: %d\n", call_status);
        }
        return call_status;
    }

    memcpy(buf, data, length);
    if (actual != nullptr) {
        *actual = length;
    }
    return ZX_OK;
}

zx_status_t devhost_add_metadata(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 zx::channel& rpc = *dev->rpc;
    if (!rpc.is_valid()) {
        return ZX_ERR_IO_REFUSED;
    }
    log_rpc(dev, "add-metadata");
    zx_status_t call_status;
    zx_status_t status = fuchsia_device_manager_CoordinatorAddMetadata(
            rpc.get(), type, reinterpret_cast<const uint8_t*>(data), length, &call_status);
    log_rpc_result("add-metadata", status, call_status);
    if (status != ZX_OK) {
        return status;
    }
    return call_status;
}

zx_status_t devhost_publish_metadata(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 zx::channel& rpc = *dev->rpc;
    if (!rpc.is_valid()) {
        return ZX_ERR_IO_REFUSED;
    }
    log_rpc(dev, "publish-metadata");
    zx_status_t call_status;
    zx_status_t status = fuchsia_device_manager_CoordinatorPublishMetadata(
            rpc.get(), path, strlen(path), type, reinterpret_cast<const uint8_t*>(data), length,
            &call_status);
    log_rpc_result("publish-metadata", status, call_status);
    if (status != ZX_OK) {
        return status;
    }
    return call_status;
}

zx_handle_t root_resource_handle;


zx_status_t devhost_start_connection(fbl::unique_ptr<DevfsConnection> conn, zx::channel h) {
    conn->set_channel(std::move(h));
    return DevfsConnection::BeginWait(std::move(conn), DevhostAsyncLoop()->dispatcher());
}

__EXPORT int device_host_main(int argc, char** argv) {
    devhost_io_init();

    log(TRACE, "devhost: main()\n");

    zx::channel root_conn_channel(zx_take_startup_handle(PA_HND(PA_USER0, 0)));
    if (!root_conn_channel.is_valid()) {
        log(ERROR, "devhost: rpc handle invalid\n");
        return -1;
    }

    root_resource_handle = zx_take_startup_handle(PA_HND(PA_RESOURCE, 0));
    if (root_resource_handle == ZX_HANDLE_INVALID) {
        log(ERROR, "devhost: no root resource handle!\n");
    }

    zx_status_t r;

#if ENABLE_DRIVER_TRACING
    {
        if (getenv_bool("driver.tracing.enable", true)) {
            r = devhost_start_trace_provider();
            if (r != ZX_OK) {
                log(INFO, "devhost: error registering as trace provider: %d\n", r);
                // This is not a fatal error.
            }
        }
    }
#endif
    if ((r = SetupRootDevcoordinatorConnection(std::move(root_conn_channel))) != ZX_OK) {
        log(ERROR, "devhost: could not watch rpc channel: %d\n", r);
        return -1;
    }

    r = DevhostAsyncLoop()->Run(zx::time::infinite(), false /* once */);
    log(ERROR, "devhost: async loop finished: %d\n", r);

    return 0;
}

} // namespace devmgr
