// Copyright 2019 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/driver-integration-test/fixture.h>

#include <memory.h>
#include <string.h>

#include <ddk/platform-defs.h>
#include <fbl/algorithm.h>
#include <lib/devmgr-launcher/launch.h>
#include <lib/zx/vmo.h>
#include <libzbi/zbi-cpp.h>
#include <zircon/assert.h>
#include <zircon/boot/image.h>
#include <zircon/status.h>

namespace driver_integration_test {

namespace {

// This board driver knows how to interpret the metadata for which devices to
// spawn.
const zbi_platform_id_t kPlatformId = []() {
    zbi_platform_id_t plat_id = {};
    plat_id.vid = PDEV_VID_TEST;
    plat_id.pid = PDEV_PID_INTEGRATION_TEST;
    strcpy(plat_id.board_name, "driver-integration-test");
    return plat_id;
}();

zx_status_t GetBootItem(const fbl::Vector<board_test::DeviceEntry>& entries, uint32_t type,
                        uint32_t extra, zx::vmo* out, uint32_t* length) {
    zx::vmo vmo;
    switch (type) {
    case ZBI_TYPE_PLATFORM_ID: {
        zx_status_t status = zx::vmo::create(sizeof(kPlatformId), 0, &vmo);
        if (status != ZX_OK) {
            return status;
        }
        status = vmo.write(&kPlatformId, 0, sizeof(kPlatformId));
        if (status != ZX_OK) {
            return status;
        }
        *length = sizeof(kPlatformId);
        break;
    }
    case ZBI_TYPE_DRV_BOARD_PRIVATE: {
        size_t list_size = sizeof(board_test::DeviceList);
        size_t entry_size = entries.size() * sizeof(board_test::DeviceEntry);
        zx_status_t status = zx::vmo::create(list_size + entry_size, 0, &vmo);
        if (status != ZX_OK) {
            return status;
        }
        board_test::DeviceList list{.count = entries.size()};
        status = vmo.write(&list, 0, sizeof(list));
        if (status != ZX_OK) {
            return status;
        }
        status = vmo.write(entries.get(), list_size, entry_size);
        if (status != ZX_OK) {
            return status;
        }
        *length = static_cast<uint32_t>(list_size + entry_size);
        break;
    }
    default:
        break;
    }
    *out = std::move(vmo);
    return ZX_OK;
}

} // namespace

zx_status_t IsolatedDevmgr::Create(IsolatedDevmgr::Args* args, IsolatedDevmgr* out) {
    IsolatedDevmgr devmgr;

    devmgr_launcher::Args devmgr_args;
    devmgr_args.sys_device_driver = "/boot/driver/platform-bus.so";
    devmgr_args.driver_search_paths.swap(args->driver_search_paths);
    devmgr_args.load_drivers.swap(args->load_drivers);
    devmgr_args.disable_block_watcher = args->disable_block_watcher;
    devmgr_args.disable_netsvc = args->disable_netsvc;
    devmgr_args.get_boot_item = [args](uint32_t type, uint32_t extra, zx::vmo* out,
                                       uint32_t* length) {
        return GetBootItem(args->device_list, type, extra, out, length);
    };

    zx_status_t status =
        devmgr_integration_test::IsolatedDevmgr::Create(std::move(devmgr_args), &devmgr.devmgr_);
    if (status != ZX_OK) {
        return status;
    }

    *out = std::move(devmgr);
    return ZX_OK;
}

} // namespace driver_integration_test
