// Copyright 2018 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 <lib/devmgr-launcher/launch.h>

#include <stdint.h>
#include <utility>

#include <fbl/algorithm.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/spawn.h>
#include <lib/fdio/util.h>
#include <lib/zx/channel.h>
#include <lib/zx/process.h>
#include <zircon/assert.h>
#include <zircon/device/vfs.h>
#include <zircon/processargs.h>
#include <zircon/status.h>

#include <lib/devmgr-launcher/processargs.h>

namespace {

constexpr const char* kDevmgrPath = "/boot/bin/devmgr";

} // namespace

namespace devmgr_launcher {

zx_status_t Launch(Args args, zx::job* devmgr_job, zx::channel* devfs_root) {
    // Create containing job (and copy to send to devmgr)
    zx::job job, job_copy;
    zx_status_t status = zx::job::create(*zx::job::default_job(), 0, &job);
    if (status != ZX_OK) {
        return status;
    }
    status = job.duplicate(ZX_RIGHT_SAME_RIGHTS, &job_copy);
    if (status != ZX_OK) {
        return status;
    }

    // Create a new client to /boot to give to devmgr
    zx::channel bootfs_client;
    {
        zx::channel bootfs_server;
        status = zx::channel::create(0, &bootfs_client, &bootfs_server);
        if (status != ZX_OK) {
            return status;
        }

        fdio_ns_t* ns;
        status = fdio_ns_get_installed(&ns);
        if (status != ZX_OK) {
            return status;
        }
        status = fdio_ns_connect(ns, "/boot", ZX_FS_RIGHT_READABLE, bootfs_server.release());
        if (status != ZX_OK) {
            return status;
        }
    }

    // Create channel to connect to devfs
    zx::channel devfs_client, devfs_server;
    status = zx::channel::create(0, &devfs_client, &devfs_server);
    if (status != ZX_OK) {
        return status;
    }

    const bool clone_stdio = !args.stdio.is_valid();

    fbl::Vector<const char*> argv;
    argv.push_back(kDevmgrPath);
    for (const char* path : args.driver_search_paths) {
        argv.push_back("--driver-search-path");
        argv.push_back(path);
    }
    for (const char* path : args.load_drivers) {
        argv.push_back("--load-driver");
        argv.push_back(path);
    }
    if (args.sys_device_driver != nullptr) {
        argv.push_back("--sys-device-driver");
        argv.push_back(args.sys_device_driver);
    }
    argv.push_back(nullptr);

    fbl::Vector<fdio_spawn_action_t> actions;
    actions.push_back(fdio_spawn_action_t{
        .action = FDIO_SPAWN_ACTION_SET_NAME,
        .name = { .data = "test-devmgr" },
    });
    actions.push_back(fdio_spawn_action_t{
        .action = FDIO_SPAWN_ACTION_ADD_HANDLE,
        .h = { .id = PA_HND(PA_JOB_DEFAULT, 0), .handle = job_copy.release() },
    });
    actions.push_back(fdio_spawn_action_t{
        .action = FDIO_SPAWN_ACTION_ADD_HANDLE,
        .h = { .id = DEVMGR_LAUNCHER_DEVFS_ROOT_HND, .handle = devfs_server.release() },
    });
    actions.push_back(fdio_spawn_action_t{
        .action = FDIO_SPAWN_ACTION_ADD_NS_ENTRY,
        .ns = { .prefix = "/boot", .handle = bootfs_client.release() },
    });
    if (args.bootdata) {
        actions.push_back(fdio_spawn_action_t{
            .action = FDIO_SPAWN_ACTION_ADD_HANDLE,
            .h = { .id = PA_HND(PA_VMO_BOOTDATA, 0), .handle = args.bootdata.release() },
        });
    }
    if (!clone_stdio) {
        actions.push_back(fdio_spawn_action_t{
            .action = FDIO_SPAWN_ACTION_TRANSFER_FD,
            .fd = { .local_fd = args.stdio.release(), .target_fd = FDIO_FLAG_USE_FOR_STDIO },
        });
    }

    uint32_t flags = FDIO_SPAWN_DEFAULT_LDSVC;
    if (clone_stdio) {
        flags |= FDIO_SPAWN_CLONE_STDIO;
    }

    zx::process new_process;
    status = fdio_spawn_etc(job.get(),
                            flags,
                            kDevmgrPath,
                            argv.get(),
                            nullptr /* environ */,
                            actions.size(),
                            actions.get(),
                            new_process.reset_and_get_address(),
                            nullptr /* err_msg */);
    if (status != ZX_OK) {
        return status;
    }

    *devmgr_job = std::move(job);
    *devfs_root = std::move(devfs_client);
    return ZX_OK;
}

} // namespace devmgr_integration_test
