// Copyright 2016 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 <ctype.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <threads.h>
#include <unistd.h>
#include <utility>

#include <fbl/string_printf.h>
#include <fbl/unique_fd.h>
#include <fbl/vector.h>
#include <fuchsia/boot/c/fidl.h>
#include <launchpad/launchpad.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/devmgr-launcher/processargs.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/io.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/spawn.h>
#include <lib/fdio/watcher.h>
#include <lib/zx/debuglog.h>
#include <lib/zx/event.h>
#include <lib/zx/port.h>
#include <lib/zx/resource.h>
#include <lib/zx/time.h>
#include <lib/zx/vmo.h>
#include <loader-service/loader-service.h>
#include <zircon/boot/image.h>
#include <zircon/device/vfs.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 <zircon/syscalls/object.h>
#include <zircon/syscalls/policy.h>

#include "boot-args.h"
#include "coordinator.h"
#include "devfs.h"
#include "devhost-loader-service.h"

#include "../shared/env.h"
#include "../shared/fdio.h"
#include "../shared/log.h"

namespace {

constexpr char kArgumentsPath[] = "/bootsvc/" fuchsia_boot_Arguments_Name;
constexpr char kItemsPath[] = "/bootsvc/" fuchsia_boot_Items_Name;
constexpr char kRootResourcePath[] = "/bootsvc/" fuchsia_boot_RootResource_Name;

struct {
    // The handle used to transmit messages to appmgr.
    zx::channel appmgr_client;

    // The handle used by appmgr to serve incoming requests.
    // If appmgr cannot be launched within a timeout, this handle is closed.
    zx::channel appmgr_server;

    zx::unowned_job root_job;
    zx::job svc_job;
    zx::job fuchsia_job;
    zx::channel svchost_outgoing;

    zx::channel fs_root;

    // Used to bind the svchost to the virtual-console binary to provide fidl
    // services.
    zx::channel virtcon_fidl;
} g_handles;

// Wait for the requested file.  Its parent directory must exist.
zx_status_t wait_for_file(const char* path, zx::time deadline) {
    char path_copy[PATH_MAX];
    if (strlen(path) >= PATH_MAX) {
        return ZX_ERR_INVALID_ARGS;
    }
    strcpy(path_copy, path);

    char* last_slash = strrchr(path_copy, '/');
    // Waiting on the root of the fs or paths with no slashes is not supported by this function
    if (last_slash == path_copy || last_slash == nullptr) {
        return ZX_ERR_NOT_SUPPORTED;
    }
    last_slash[0] = 0;
    char* dirname = path_copy;
    char* basename = last_slash + 1;

    auto watch_func = [](int dirfd, int event, const char* fn, void* cookie) -> zx_status_t {
        auto basename = static_cast<const char*>(cookie);
        if (event != WATCH_EVENT_ADD_FILE) {
            return ZX_OK;
        }
        if (!strcmp(fn, basename)) {
            return ZX_ERR_STOP;
        }
        return ZX_OK;
    };

    fbl::unique_fd dirfd(open(dirname, O_RDONLY));
    if (!dirfd.is_valid()) {
        return ZX_ERR_INVALID_ARGS;
    }
    zx_status_t status = fdio_watch_directory(dirfd.get(), watch_func, deadline.get(),
                                              reinterpret_cast<void*>(basename));
    if (status == ZX_ERR_STOP) {
        return ZX_OK;
    }
    return status;
}

void do_autorun(const char* name, const char* cmd) {
    if (cmd != nullptr) {
        auto args = devmgr::ArgumentVector::FromCmdline(cmd);
        args.Print("autorun");
        devmgr::devmgr_launch(g_handles.svc_job, name, args.argv(), nullptr, -1,
                              nullptr, nullptr, 0, nullptr, FS_ALL);
    }
}

// Get kernel arguments from the arguments service.
zx_status_t get_arguments(zx::vmo* args_vmo, size_t* args_size) {
    zx::channel local, remote;
    zx_status_t status = zx::channel::create(0, &local, &remote);
    if (status != ZX_OK) {
        return status;
    }
    status = fdio_service_connect(kArgumentsPath, remote.release());
    if (status != ZX_OK) {
        return status;
    }
    return fuchsia_boot_ArgumentsGet(local.get(), args_vmo->reset_and_get_address(), args_size);
}

// Get ramdisk from the boot items service.
zx_status_t get_ramdisk(zx::vmo* ramdisk_vmo) {
    zx::channel local, remote;
    zx_status_t status = zx::channel::create(0, &local, &remote);
    if (status != ZX_OK) {
        return status;
    }
    status = fdio_service_connect(kItemsPath, remote.release());
    if (status != ZX_OK) {
        fprintf(stderr, "devcoordinator: get_arguments: fdio_service_connect returned %d\n",
                status);
        return status;
    }
    uint32_t length;
    return fuchsia_boot_ItemsGet(local.get(), ZBI_TYPE_STORAGE_RAMDISK, 0,
                                 ramdisk_vmo->reset_and_get_address(), &length);
}

// Get the root resource from the root resource service. Not receiving the
// startup handle is logged, but not fatal.  In test environments, it would not
// be present.
zx_status_t get_root_resource(zx::resource* root_resource) {
    zx::channel local, remote;
    zx_status_t status = zx::channel::create(0, &local, &remote);
    if (status != ZX_OK) {
        return status;
    }
    status = fdio_service_connect(kRootResourcePath, remote.release());
    if (status != ZX_OK) {
        return status;
    }
    return fuchsia_boot_RootResourceGet(local.get(), root_resource->reset_and_get_address());
}

int fuchsia_starter(void* arg) {
    auto coordinator = static_cast<devmgr::Coordinator*>(arg);
    bool appmgr_started = false;
    bool autorun_started = false;
    bool drivers_loaded = false;

    size_t appmgr_timeout = 20;
    zx::time deadline = zx::deadline_after(zx::sec(appmgr_timeout));

    do {
        zx_status_t status = coordinator->fshost_event().wait_one(
            FSHOST_SIGNAL_READY, deadline, nullptr);
        if (status == ZX_ERR_TIMED_OUT) {
            if (g_handles.appmgr_server.is_valid()) {
                if (coordinator->require_system()) {
                    fprintf(stderr, "devcoordinator: appmgr not launched in %zus, closing appmgr handle\n",
                            appmgr_timeout);
                }
                g_handles.appmgr_server.reset();
            }
            deadline = zx::time::infinite();
            continue;
        }
        if (status != ZX_OK) {
            fprintf(stderr, "devcoordinator: error waiting on fuchsia start event: %d\n", status);
            break;
        }
        status = coordinator->fshost_event().signal(FSHOST_SIGNAL_READY, 0);
        if (status != ZX_OK) {
            fprintf(stderr, "devcoordinator: error signaling fshost: %d\n", status);
        }

        if (!drivers_loaded) {
            // we're starting the appmgr because /system is present
            // so we also signal the device coordinator that those
            // drivers are now loadable
            coordinator->set_system_available(true);
            coordinator->ScanSystemDrivers();
            drivers_loaded = true;
        }

        const char* argv_appmgr[] = {
            "/system/bin/appmgr",
            nullptr,
        };

        struct stat s;
        if (!appmgr_started && stat(argv_appmgr[0], &s) == 0) {
            unsigned int appmgr_hnd_count = 0;
            zx_handle_t appmgr_hnds[2] = {};
            uint32_t appmgr_ids[2] = {};
            if (g_handles.appmgr_server.is_valid()) {
                assert(appmgr_hnd_count < fbl::count_of(appmgr_hnds));
                appmgr_hnds[appmgr_hnd_count] = g_handles.appmgr_server.release();
                appmgr_ids[appmgr_hnd_count] = PA_DIRECTORY_REQUEST;
                appmgr_hnd_count++;
            }
            devmgr::devmgr_launch(g_handles.fuchsia_job, "appmgr",
                                  argv_appmgr, nullptr, -1, appmgr_hnds, appmgr_ids,
                                  appmgr_hnd_count, nullptr, FS_FOR_APPMGR);
            appmgr_started = true;
        }
        if (!autorun_started) {
            do_autorun("autorun:system", coordinator->boot_args().Get("zircon.autorun.system"));
            autorun_started = true;
        }
    } while (!appmgr_started);
    return 0;
}

int console_starter(void* arg) {
    auto& boot_args = *static_cast<const devmgr::BootArgs*>(arg);

    // If we got a TERM environment variable (aka a TERM=... argument on
    // the kernel command line), pass this down; otherwise pass TERM=uart.
    const char* term = boot_args.Get("TERM");
    if (term == nullptr) {
        term = "TERM=uart";
    } else {
        term -= sizeof("TERM=") - 1;
    }

    const char* device = boot_args.Get("console.path");
    if (device == nullptr) {
        device = "/dev/misc/console";
    }

    const char* envp[] = {
        term,
        nullptr,
    };

    zx_status_t status = wait_for_file(device, zx::time::infinite());
    if (status != ZX_OK) {
        printf("devcoordinator: failed to wait for console '%s'\n", device);
        return 1;
    }
    fbl::unique_fd fd(open(device, O_RDWR));
    if (!fd.is_valid()) {
        printf("devcoordinator: failed to open console '%s'\n", device);
        return 1;
    }

    const char* argv_sh[] = {"/boot/bin/sh", nullptr};
    devmgr::devmgr_launch(g_handles.svc_job, "sh:console", argv_sh,
                          envp, fd.release(), nullptr, nullptr, 0, nullptr, FS_ALL);
    return 0;
}

int pwrbtn_monitor_starter(void* arg) {
    const char* name = "pwrbtn-monitor";
    const char* argv[] = {"/boot/bin/pwrbtn-monitor", nullptr};

    zx::job job_copy;
    zx_status_t status =
        g_handles.svc_job.duplicate(ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_WRITE, &job_copy);
    if (status != ZX_OK) {
        printf("devcoordinator: svc_job.duplicate failed %s\n", zx_status_get_string(status));
        return 1;
    }

    zx::debuglog debuglog;
    if ((status = zx::debuglog::create(zx::resource(), 0, &debuglog) != ZX_OK)) {
        printf("devcoordinator: cannot create debuglog handle\n");
        return 1;
    }

    zx::channel input_handle = devmgr::fs_clone("dev/class/input");
    if (!input_handle.is_valid()) {
        printf("devcoordinator: failed to clone /dev/input\n");
        return 1;
    }

    zx::channel svc_handle = devmgr::fs_clone("svc");
    if (!svc_handle.is_valid()) {
        printf("devcoordinator: failed to clone /svc\n");
        return 1;
    }

    fdio_spawn_action_t actions[] = {
        {.action = FDIO_SPAWN_ACTION_SET_NAME, .name = {.data = name}},
        {.action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
         .ns = {.prefix = "/input", .handle = input_handle.release()}},
        // Ideally we'd only expose /svc/fuchsia.device.manager.Administrator, but we do not
        // support exposing single services.
        {.action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
         .ns = {.prefix = "/svc", .handle = svc_handle.release()}},
        {.action = FDIO_SPAWN_ACTION_ADD_HANDLE,
         .h = {.id = PA_HND(PA_FD, FDIO_FLAG_USE_FOR_STDIO | 0),
               .handle = debuglog.release()}},
    };

    char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
    uint32_t spawn_flags = FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_DEFAULT_LDSVC;
    status = fdio_spawn_etc(job_copy.get(), spawn_flags, argv[0], argv,
                            nullptr, fbl::count_of(actions), actions,
                            nullptr, err_msg);
    if (status != ZX_OK) {
        printf("devcoordinator: spawn %s (%s) failed: %s: %s\n", argv[0], name, err_msg,
               zx_status_get_string(status));
        return 1;
    }

    printf("devcoordinator: launch %s (%s) OK\n", argv[0], name);
    return 0;
}

void start_console_shell(const devmgr::BootArgs& boot_args) {
    // Only start a shell on the kernel console if it isn't already running a shell.
    if (boot_args.GetBool("kernel.shell", false)) {
        return;
    }
    thrd_t t;
    int ret = thrd_create_with_name(&t, console_starter, const_cast<devmgr::BootArgs*>(&boot_args),
                                    "console-starter");
    if (ret == thrd_success) {
        thrd_detach(t);
    }
}

zx_status_t fuchsia_create_job() {
    zx_status_t status = zx::job::create(*g_handles.root_job, 0u, &g_handles.fuchsia_job);
    if (status != ZX_OK) {
        printf("devcoordinator: unable to create fuchsia job: %d (%s)\n", status,
               zx_status_get_string(status));
        return status;
    }

    g_handles.fuchsia_job.set_property(ZX_PROP_NAME, "fuchsia", 7);

    const zx_policy_basic_t basic_policy[] = {
        // Lock down process creation. Child tasks must use fuchsia.process.Launcher.
        {.condition = ZX_POL_NEW_PROCESS, .policy = ZX_POL_ACTION_DENY}};

    status = g_handles.fuchsia_job.set_policy(ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, basic_policy,
                                              fbl::count_of(basic_policy));
    if (status != ZX_OK) {
        printf("devcoordinator: unable to set basic policy for fuchsia job: %d (%s)\n", status,
               zx_status_get_string(status));
        return status;
    }

    // Set the minimum timer slack amount and default mode. The amount should be large enough to
    // allow for some coalescing of timers, but small enough to ensure applications don't miss
    // deadlines.
    //
    // Why LATE and not CENTER or EARLY? Timers firing a little later than requested is not uncommon
    // in non-realtime systems. Programs are generally tolerant of some delays. However, timers
    // firing before their dealine can be unexpected and lead to bugs.
    const zx_policy_timer_slack_t timer_slack_policy{ZX_USEC(500), ZX_TIMER_SLACK_LATE};

    status = g_handles.fuchsia_job.set_policy(ZX_JOB_POL_RELATIVE, ZX_JOB_POL_TIMER_SLACK,
                                              &timer_slack_policy, 1);
    if (status != ZX_OK) {
        printf("devcoordinator: unable to set timer slack policy for fuchsia job: %d (%s)\n", status,
               zx_status_get_string(status));
        return status;
    }

    return ZX_OK;
}

zx_status_t svchost_start(bool require_system, devmgr::Coordinator* coordinator,
                          zx::channel fshost_client) {
    const auto& root_resource = coordinator->root_resource();
    zx::channel dir_request, svchost_local;
    zx::debuglog logger;
    zx::channel appmgr_svc_req;
    zx::channel appmgr_svc;

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

    status = zx::debuglog::create(zx::resource(), 0, &logger);
    if (status != ZX_OK) {
        return status;
    }

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

    status =
        fdio_service_connect_at(g_handles.appmgr_client.get(), "svc", appmgr_svc_req.release());
    if (status != ZX_OK) {
        return status;
    }

    const char* name = "svchost";
    const char* argv[2] = {
        "/boot/bin/svchost",
        require_system ? "--require-system" : nullptr,
    };
    int argc = require_system ? 2 : 1;

    zx::job svc_job_copy;
    status = g_handles.svc_job.duplicate(
        ZX_RIGHTS_BASIC | ZX_RIGHT_MANAGE_JOB | ZX_RIGHT_MANAGE_PROCESS, &svc_job_copy);
    if (status != ZX_OK) {
        return status;
    }

    zx::job root_job_copy;
    status = g_handles.root_job->duplicate(ZX_RIGHTS_BASIC | ZX_RIGHTS_IO | ZX_RIGHTS_PROPERTY |
                                               ZX_RIGHT_ENUMERATE | ZX_RIGHT_MANAGE_PROCESS,
                                           &root_job_copy);
    if (status != ZX_OK) {
        return status;
    }

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

        status = coordinator->BindOutgoingServices(std::move(fidl_server));
        if (status != ZX_OK) {
            printf("Unable to start fidl services.\n");
            return status;
        }
    }

    zx::channel virtcon_client;
    status = zx::channel::create(0, &virtcon_client, &g_handles.virtcon_fidl);
    if (status != ZX_OK) {
        printf("Unable to create virtcon channel.\n");
        return status;
    }

    // svchost needs to hold this to talk to zx_kerneldebug but doesn't need any rights.
    // TODO(ZX-971): when zx_debug_send_command syscall is descoped, update this too.
    zx::resource root_resource_copy;
    if (root_resource.is_valid()) {
        status = root_resource.duplicate(ZX_RIGHT_TRANSFER, &root_resource_copy);
        if (status != ZX_OK) {
            return status;
        }
    }

    launchpad_t* lp = nullptr;
    launchpad_create(svc_job_copy.get(), name, &lp);
    launchpad_load_from_file(lp, argv[0]);
    launchpad_set_args(lp, argc, argv);
    launchpad_add_handle(lp, dir_request.release(), PA_DIRECTORY_REQUEST);
    launchpad_add_handle(lp, logger.release(), PA_HND(PA_FD, FDIO_FLAG_USE_FOR_STDIO));

    // Remove once svchost hosts the tracelink service itself.
    launchpad_add_handle(lp, appmgr_svc.release(), PA_HND(PA_USER0, 0));

    // Give svchost a restricted root job handle. svchost is already a privileged system service
    // as it controls system-wide process launching. With the root job it can consolidate a few
    // services such as crashsvc and the profile service.
    launchpad_add_handle(lp, root_job_copy.release(), PA_HND(PA_USER0, 1));

    // Also give svchost a restricted root resource handle, this allows it to run the kernel-debug
    // service.
    if (root_resource_copy.is_valid()) {
        launchpad_add_handle(lp, root_resource_copy.release(), PA_HND(PA_USER0, 2));
    }

    // TODO(smklein): Merge "fidl_client" (proxying requests to devmgr) and
    // "fshost_client" (proxying requests to fshost) into one service provider
    // PseudoDirectory.

    // Add handle to channel to allow svchost to proxy fidl services to us.
    launchpad_add_handle(lp, fidl_client.release(), PA_HND(PA_USER0, 3));

    // Add a handle to allow svchost to proxy services to fshost.
    launchpad_add_handle(lp, fshost_client.release(), PA_HND(PA_USER0, 4));
    if (!coordinator->boot_args().GetBool("virtcon.disable", false)) {
        // Add handle to channel to allow svchost to proxy fidl services to
        // virtcon.
        launchpad_add_handle(lp, virtcon_client.release(), PA_HND(PA_USER0, 5));
    }

    // Give svchost access to /dev/class/sysmem, to enable svchost to forward sysmem service
    // requests to the sysmem driver.  Create a namespace containing /dev/class/sysmem.
    const char* nametable[1] = {};
    uint32_t count = 0;
    zx::channel fs_handle = devmgr::fs_clone("dev/class/sysmem");
    if (fs_handle.is_valid()) {
        nametable[count] = "/sysmem";
        launchpad_add_handle(lp, fs_handle.release(), PA_HND(PA_NS_DIR, count++));
    } else {
        launchpad_abort(lp, ZX_ERR_BAD_STATE, "devcoordinator: failed to clone /dev/class/sysmem");
        // The launchpad_go() call below will fail, but will still free lp.
    }

    launchpad_set_nametable(lp, count, nametable);

    const char* errmsg = nullptr;
    if ((status = launchpad_go(lp, nullptr, &errmsg)) != ZX_OK) {
        printf("devcoordinator: launchpad %s (%s) failed: %s: %d\n", argv[0], name, errmsg, status);
        return status;
    } else {
        printf("devcoordinator: launch %s (%s) OK\n", argv[0], name);
    }

    zx::channel svchost_public_remote;
    status = zx::channel::create(0, &svchost_public_remote, &g_handles.svchost_outgoing);
    if (status != ZX_OK) {
        return status;
    }

    return fdio_service_connect_at(svchost_local.get(), "public", svchost_public_remote.release());
}

void fshost_start(devmgr::Coordinator* coordinator, const devmgr::DevmgrArgs& devmgr_args,
                  zx::channel fshost_server) {
    // assemble handles to pass down to fshost
    zx_handle_t handles[ZX_CHANNEL_MAX_MSG_HANDLES];
    uint32_t types[fbl::count_of(handles)];
    size_t n = 0;
    zx_handle_t ldsvc;

    // Pass "fs_root", and ldsvc handles to fshost.
    if (zx_channel_create(0, g_handles.fs_root.reset_and_get_address(), &handles[n]) == ZX_OK) {
        types[n++] = PA_HND(PA_USER0, 0);
    }
    if (zx_channel_create(0, &ldsvc, &handles[n]) == ZX_OK) {
        types[n++] = PA_HND(PA_USER0, 2);
    } else {
        ldsvc = ZX_HANDLE_INVALID;
    }

    // The "public directory" of the fshost service.
    handles[n] = fshost_server.release();
    types[n++] = PA_HND(PA_USER0, 3);

    // pass fuchsia start event to fshost
    zx::event fshost_event_duplicate;
    if (coordinator->fshost_event().duplicate(ZX_RIGHT_SAME_RIGHTS, &fshost_event_duplicate) ==
        ZX_OK) {
        handles[n] = fshost_event_duplicate.release();
        types[n++] = PA_HND(PA_USER1, 0);
    }

    // pass VDSO VMOS to fshost
    for (uint32_t m = 0; n < fbl::count_of(handles); m++) {
        uint32_t type = PA_HND(PA_VMO_VDSO, m);
        if (m == 0) {
            // By this point, launchpad has already moved PA_HND(PA_VMO_VDSO, 0) into a static.
            handles[n] = ZX_HANDLE_INVALID;
            launchpad_get_vdso_vmo(&handles[n]);
        } else {
            handles[n] = zx_take_startup_handle(type);
        }

        if (handles[n] != ZX_HANDLE_INVALID) {
            types[n++] = type;
        } else {
            break;
        }
    }

    // pass ramdisk to fshost
    zx::vmo ramdisk_vmo;
    zx_status_t status = get_ramdisk(&ramdisk_vmo);
    if (status == ZX_OK && ramdisk_vmo.is_valid()) {
        handles[n] = ramdisk_vmo.release();
        types[n++] = PA_HND(PA_VMO_BOOTDATA, 0);
    }

    // pass command line to the fshost
    fbl::Vector<const char*> args{"/boot/bin/fshost"};
    if (coordinator->boot_args().GetBool("netsvc.netboot", false) ||
        coordinator->boot_args().GetBool("zircon.system.disable-automount", false)) {
        args.push_back("--netboot");
    }
    if (devmgr_args.disable_block_watcher) {
        args.push_back("--disable-block-watcher");
    }
    args.push_back(nullptr);

    // pass zircon.system.* options to the fshost as environment variables
    fbl::Vector<const char*> env;
    coordinator->boot_args().Collect("zircon.system", &env);
    env.push_back(nullptr);

    devmgr::devmgr_launch(g_handles.svc_job, "fshost", args.get(), env.get(), -1, handles, types, n,
                          nullptr, FS_BOOT | FS_DEV | FS_SVC);

    // switch to system loader service provided by fshost
    zx_handle_close(dl_set_loader_service(ldsvc));
}

void devmgr_vfs_init(devmgr::Coordinator* coordinator, const devmgr::DevmgrArgs& devmgr_args,
                     bool needs_svc_mount, zx::channel fshost_server) {
    fdio_ns_t* ns;
    zx_status_t r;
    r = fdio_ns_get_installed(&ns);
    ZX_ASSERT_MSG(r == ZX_OK, "devcoordinator: cannot get namespace: %s\n", zx_status_get_string(r));
    r = fdio_ns_bind(ns, "/dev", devmgr::fs_clone("dev").release());
    ZX_ASSERT_MSG(r == ZX_OK, "devcoordinator: cannot bind /dev to namespace: %s\n",
                  zx_status_get_string(r));

    if (needs_svc_mount) {
        r = fdio_ns_bind(ns, "/svc", devmgr::fs_clone("svc").release());
        ZX_ASSERT_MSG(r == ZX_OK, "devcoordinator: cannot bind /svc to namespace: %s\n",
                      zx_status_get_string(r));
    }

    // Start fshost before binding /system, since it publishes it.
    fshost_start(coordinator, devmgr_args, std::move(fshost_server));

    if ((r = fdio_ns_bind(ns, "/system", devmgr::fs_clone("system").release())) != ZX_OK) {
        printf("devcoordinator: cannot bind /system to namespace: %d\n", r);
    }
}

int service_starter(void* arg) {
    auto coordinator = static_cast<devmgr::Coordinator*>(arg);

    bool netboot = false;
    bool vruncmd = false;
    fbl::String vcmd;
    if (!(coordinator->boot_args().GetBool("netsvc.disable", false) ||
          coordinator->disable_netsvc())) {
        const char* args[] = {
            "/boot/bin/netsvc", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
        int argc = 1;

        if (coordinator->boot_args().GetBool("netsvc.netboot", false)) {
            args[argc++] = "--netboot";
            netboot = true;
            vruncmd = true;
        }

        if (coordinator->boot_args().GetBool("netsvc.advertise", true)) {
            args[argc++] = "--advertise";
        }

        const char* interface = coordinator->boot_args().Get("netsvc.interface");
        if (interface != nullptr) {
            args[argc++] = "--interface";
            args[argc++] = interface;
        }

        const char* nodename = coordinator->boot_args().Get("zircon.nodename");
        if (nodename) {
            args[argc++] = nodename;
        }

        zx::process proc;
        zx_status_t status = devmgr::devmgr_launch(g_handles.svc_job, "netsvc", args, nullptr, -1,
                                                   nullptr, nullptr, 0, &proc, FS_ALL);
        if (status == ZX_OK) {
            if (vruncmd) {
                zx_info_handle_basic_t info = {};
                proc.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
                proc.reset();
                vcmd = fbl::StringPrintf("dlog -f -t -p %zu", info.koid);
            }
        } else {
            vruncmd = false;
        }
        __UNUSED auto leaked_handle = proc.release();
    }

    if (!coordinator->boot_args().GetBool("virtcon.disable", false)) {
        // pass virtcon.* options along
        fbl::Vector<const char*> env;
        coordinator->boot_args().Collect("virtcon.", &env);
        env.push_back(nullptr);

        const char* num_shells =
            coordinator->require_system() && !netboot ? "0" : "3";
        size_t handle_count = 0;
        zx_handle_t handles[2];
        uint32_t types[2];

        handles[handle_count] = g_handles.virtcon_fidl.release();
        types[handle_count] = PA_HND(PA_USER0, 0);
        ++handle_count;

        zx::debuglog debuglog;
        zx_status_t status = zx::debuglog::create(coordinator->root_resource(),
                                                  ZX_LOG_FLAG_READABLE, &debuglog);
        if (status == ZX_OK) {
            handles[handle_count] = debuglog.release();
            types[handle_count] = PA_HND(PA_USER0, 1);
            ++handle_count;
        }

        const char* args[] = {"/boot/bin/virtual-console", "--shells", num_shells, nullptr, nullptr,
                              nullptr};
        if (vruncmd) {
            args[3] = "--run";
            args[4] = vcmd.data();
        }
        devmgr::devmgr_launch(g_handles.svc_job, "virtual-console", args, env.get(), -1, handles,
                              types, handle_count, nullptr, FS_ALL);
    }

    const char* epoch = coordinator->boot_args().Get("devmgr.epoch");
    if (epoch) {
        zx_time_t offset = ZX_SEC(atoi(epoch));
        zx_clock_adjust(coordinator->root_resource().get(), ZX_CLOCK_UTC, offset);
    }

    do_autorun("autorun:boot", coordinator->boot_args().Get("zircon.autorun.boot"));

    thrd_t t;
    int ret = thrd_create_with_name(&t, fuchsia_starter, coordinator, "fuchsia-starter");
    if (ret == thrd_success) {
        thrd_detach(t);
    }

    return 0;
}

void ParseArgs(int argc, char** argv, devmgr::DevmgrArgs* out) {
    enum {
        kDriverSearchPath,
        kLoadDriver,
        kSysDeviceDriver,
        kUseSystemSvchost,
        kDisableBlockWatcher,
        kDisableNetsvc,
    };
    option options[] = {
        {"driver-search-path", required_argument, nullptr, kDriverSearchPath},
        {"load-driver", required_argument, nullptr, kLoadDriver},
        {"sys-device-driver", required_argument, nullptr, kSysDeviceDriver},
        {"use-system-svchost", no_argument, nullptr, kUseSystemSvchost},
        {"disable-block-watcher", no_argument, nullptr, kDisableBlockWatcher},
        {"disable-netsvc", no_argument, nullptr, kDisableNetsvc},
    };

    auto print_usage_and_exit = [options]() {
        printf("devcoordinator: supported arguments:\n");
        for (const auto& option : options) {
            printf("  --%s\n", option.name);
        }
        abort();
    };

    auto check_not_duplicated = [print_usage_and_exit](const char* arg) {
        if (arg != nullptr) {
            printf("devcoordinator: duplicated argument\n");
            print_usage_and_exit();
        }
    };

    // Reset the args state
    *out = devmgr::DevmgrArgs();

    int opt;
    while ((opt = getopt_long(argc, argv, "", options, nullptr)) != -1) {
        switch (opt) {
        case kDriverSearchPath:
            out->driver_search_paths.push_back(optarg);
            break;
        case kLoadDriver:
            out->load_drivers.push_back(optarg);
            break;
        case kSysDeviceDriver:
            check_not_duplicated(out->sys_device_driver);
            out->sys_device_driver = optarg;
            break;
        case kUseSystemSvchost:
            out->use_system_svchost = true;
            break;
        case kDisableBlockWatcher:
            out->disable_block_watcher = true;
            break;
        case kDisableNetsvc:
            out->disable_netsvc = true;
            break;
        default:
            print_usage_and_exit();
        }
    }
}

zx_status_t CreateDevhostJob(const zx::job& root_job, zx::job* devhost_job_out) {
    zx::job devhost_job;
    zx_status_t status = zx::job::create(root_job, 0u, &devhost_job);
    if (status != ZX_OK) {
        log(ERROR, "devcoordinator: unable to create devhost job\n");
        return status;
    }
    static const zx_policy_basic_t policy[] = {
        {ZX_POL_BAD_HANDLE, ZX_POL_ACTION_EXCEPTION},
    };
    status = devhost_job.set_policy(ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC, &policy,
                                    fbl::count_of(policy));
    if (status != ZX_OK) {
        log(ERROR, "devcoordinator: zx_job_set_policy() failed\n");
        return status;
    }
    status = devhost_job.set_property(ZX_PROP_NAME, "zircon-drivers", 15);
    if (status != ZX_OK) {
        log(ERROR, "devcoordinator: zx_job_set_property() failed\n");
        return status;
    }

    *devhost_job_out = std::move(devhost_job);
    return ZX_OK;
}

} // namespace

namespace devmgr {

zx::channel fs_clone(const char* path) {
    if (!strcmp(path, "dev")) {
        return devfs_root_clone();
    }
    zx::channel h0, h1;
    if (zx::channel::create(0, &h0, &h1) != ZX_OK) {
        return zx::channel();
    }
    if (!strcmp(path, "boot")) {
        fdio_open("/boot", ZX_FS_RIGHT_READABLE, h1.release());
        return h0;
    }
    zx::unowned_channel fs(g_handles.fs_root);
    int flags = FS_DIR_FLAGS;
    if (!strcmp(path, "hub")) {
        fs = zx::unowned_channel(g_handles.appmgr_client);
    } else if (!strcmp(path, "svc")) {
        flags = ZX_FS_RIGHT_READABLE | ZX_FS_RIGHT_WRITABLE;
        fs = zx::unowned_channel(g_handles.svchost_outgoing);
        path = ".";
    } else if (!strncmp(path, "dev/", 4)) {
        fs = devfs_root_borrow();
        path += 4;
    }
    fdio_open_at(fs->get(), path, flags, h1.release());
    return h0;
}

} // namespace devmgr

int main(int argc, char** argv) {
    devmgr::BootArgs boot_args;
    zx::vmo args_vmo;
    size_t args_size;
    zx_status_t status = get_arguments(&args_vmo, &args_size);
    if (status == ZX_OK) {
        status = devmgr::BootArgs::Create(std::move(args_vmo), args_size, &boot_args);
        if (status != ZX_OK) {
            fprintf(stderr, "devcoordinator: failed to create boot arguments (size %lu): %d\n",
                    args_size, status);
            return 1;
        }
    } else {
        fprintf(stderr, "devcoordinator: failed to get boot arguments (status: %d), assuming test "
                        "environment and continuing\n", status);
    }

    if (boot_args.GetBool("devmgr.verbose", false)) {
        devmgr::log_flags |= LOG_ALL;
    }

    devmgr::DevmgrArgs devmgr_args;
    ParseArgs(argc, argv, &devmgr_args);
    // Set up the default values for our arguments if they weren't given.
    if (devmgr_args.driver_search_paths.size() == 0) {
        devmgr_args.driver_search_paths.push_back("/boot/driver");
    }
    if (devmgr_args.sys_device_driver == nullptr) {
        devmgr_args.sys_device_driver = "/boot/driver/platform-bus.so";
    }

    g_handles.root_job = zx::job::default_job();
    g_handles.root_job->set_property(ZX_PROP_NAME, "root", 4);
    bool require_system = boot_args.GetBool("devmgr.require-system", false);

    async::Loop loop(&kAsyncLoopConfigNoAttachToThread);
    devmgr::CoordinatorConfig config{};
    config.dispatcher = loop.dispatcher();
    config.boot_args = &boot_args;
    config.require_system = require_system;
    config.asan_drivers = boot_args.GetBool("devmgr.devhost.asan", false);
    config.suspend_fallback = boot_args.GetBool("devmgr.suspend-timeout-fallback", false);
    config.suspend_debug = boot_args.GetBool("devmgr.suspend-timeout-debug", false);
    config.disable_netsvc = devmgr_args.disable_netsvc;

    status = get_root_resource(&config.root_resource);
    if (status != ZX_OK) {
        fprintf(stderr, "devcoordinator: failed to get root resource, assuming test "
                        "environment and continuing\n");
    }
    // TODO: limit to enumerate rights
    status = g_handles.root_job->duplicate(ZX_RIGHT_SAME_RIGHTS, &config.sysinfo_job);
    if (status != ZX_OK) {
        fprintf(stderr, "devcoordinator: failed to duplicate root job for sysinfo: %d\n", status);
    }
    status = CreateDevhostJob(*g_handles.root_job, &config.devhost_job);
    if (status != ZX_OK) {
        fprintf(stderr, "devcoordinator: failed to create devhost job: %d\n", status);
        return 1;
    }
    status = zx::event::create(0, &config.fshost_event);
    if (status != ZX_OK) {
        fprintf(stderr, "devcoordinator: failed to create fshost event: %d\n", status);
        return 1;
    }

    devmgr::Coordinator coordinator(std::move(config));
    status = coordinator.InitializeCoreDevices(devmgr_args.sys_device_driver);
    if (status != ZX_OK) {
        log(ERROR, "devcoordinator: failed to initialize core devices\n");
        return 1;
    }

    devmgr::devfs_init(coordinator.root_device(), loop.dispatcher());
    devfs_publish(coordinator.root_device(), coordinator.misc_device());
    devfs_publish(coordinator.root_device(), coordinator.sys_device());
    devfs_publish(coordinator.root_device(), coordinator.test_device());

    // Check if whatever launched devmgr gave a channel to be connected to /dev.
    // This is for use in tests to let the test environment see devfs.
    zx::channel devfs_client(zx_take_startup_handle(DEVMGR_LAUNCHER_DEVFS_ROOT_HND));
    if (devfs_client.is_valid()) {
        fdio_service_clone_to(devmgr::devfs_root_borrow()->get(), devfs_client.release());
    }

    status = zx::job::create(*g_handles.root_job, 0u, &g_handles.svc_job);
    if (status != ZX_OK) {
        fprintf(stderr, "devcoordinator: failed to create service job: %d\n", status);
        return 1;
    }
    g_handles.svc_job.set_property(ZX_PROP_NAME, "zircon-services", 16);

    status = fuchsia_create_job();
    if (status != ZX_OK) {
        return 1;
    }

    zx::channel fshost_client, fshost_server;
    zx::channel::create(0, &fshost_client, &fshost_server);
    zx::channel::create(0, &g_handles.appmgr_client, &g_handles.appmgr_server);

    if (devmgr_args.use_system_svchost) {
        zx::channel dir_request;
        zx_status_t status = zx::channel::create(0, &dir_request, &g_handles.svchost_outgoing);
        if (status != ZX_OK) {
            fprintf(stderr, "devcoordinator: failed to create svchost_outgoing channel\n");
            return 1;
        }
        status = fdio_service_connect("/svc", dir_request.release());
        if (status != ZX_OK) {
            fprintf(stderr, "devcoordinator: failed to connect to /svc\n");
            return 1;
        }
    } else {
        status = svchost_start(require_system, &coordinator, std::move(fshost_client));
        if (status != ZX_OK) {
            fprintf(stderr, "devcoordinator: failed to start svchost: %d", status);
            return 1;
        }
    }

    const bool needs_svc_mount = !devmgr_args.use_system_svchost;
    devmgr_vfs_init(&coordinator, devmgr_args, needs_svc_mount, std::move(fshost_server));

    // If this is not a full Fuchsia build, do not setup appmgr services, as
    // this will delay startup.
    if (!require_system) {
        devmgr::devmgr_disable_appmgr_services();
    }

    thrd_t t;
    int ret = thrd_create_with_name(&t, pwrbtn_monitor_starter, nullptr, "pwrbtn-monitor-starter");
    if (ret != thrd_success) {
        log(ERROR, "devcoordinator: failed to create pwrbtn monitor starter thread\n");
        return 1;
    }
    thrd_detach(t);

    start_console_shell(boot_args);

    ret = thrd_create_with_name(&t, service_starter, &coordinator, "service-starter");
    if (ret != thrd_success) {
        log(ERROR, "devcoordinator: failed to create service starter thread\n");
        return 1;
    }
    thrd_detach(t);

    fbl::unique_ptr<devmgr::DevhostLoaderService> loader_service;
    if (boot_args.GetBool("devmgr.devhost.strict-linking", false)) {
        status = devmgr::DevhostLoaderService::Create(loop.dispatcher(), &loader_service);
        if (status != ZX_OK) {
            return 1;
        }
        coordinator.set_loader_service(loader_service.get());
    }

    for (const char* path : devmgr_args.driver_search_paths) {
        devmgr::find_loadable_drivers(
            path, fit::bind_member(&coordinator, &devmgr::Coordinator::DriverAddedInit));
    }
    for (const char* driver : devmgr_args.load_drivers) {
        devmgr::load_driver(driver,
                            fit::bind_member(&coordinator, &devmgr::Coordinator::DriverAddedInit));
    }

    // Special case early handling for the ramdisk boot
    // path where /system is present before the coordinator
    // starts.  This avoids breaking the "priority hack" and
    // can be removed once the real driver priority system
    // exists.
    if (coordinator.system_available()) {
        status = coordinator.ScanSystemDrivers();
        if (status != ZX_OK) {
            return 1;
        }
    }

    if (coordinator.require_system() && !coordinator.system_loaded()) {
        printf(
            "devcoordinator: full system required, ignoring fallback drivers until /system is loaded\n");
    } else {
        coordinator.UseFallbackDrivers();
    }

    coordinator.PrepareProxy(coordinator.sys_device(), nullptr);
    coordinator.PrepareProxy(coordinator.test_device(), nullptr);
    // Initial bind attempt for drivers enumerated at startup.
    coordinator.BindDrivers();

    coordinator.set_running(true);
    status = loop.Run();
    fprintf(stderr, "devcoordinator: coordinator exited unexpectedly: %d\n", status);
    return status == ZX_OK ? 0 : 1;
}
