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

#include <fcntl.h>
#include <lib/async/default.h>
#include <lib/fdio/cpp/caller.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/unsafe.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/vmo.h>
#include <zircon/boot/image.h>
#include <zircon/status.h>
#include <zircon/syscalls/debug.h>

#include <ddk/platform-defs.h>
#include <sdk/lib/sys/cpp/component_context.h>

namespace isolated_devmgr {

zx_status_t IsolatedDevmgr::WaitForFile(const char* path) {
  fbl::unique_fd out;
  return devmgr_integration_test::RecursiveWaitForFile(devmgr_.devfs_root(), path, &out);
}

void IsolatedDevmgr::Connect(zx::channel req) {
  fdio_cpp::UnownedFdioCaller fd(devmgr_.devfs_root().get());
  fdio_service_clone_to(fd.borrow_channel(), req.release());
}

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;
}();

#define BOARD_REVISION_TEST 42

const zbi_board_info_t kBoardInfo = []() {
  zbi_board_info_t board_info = {};
  board_info.revision = BOARD_REVISION_TEST;
  return board_info;
}();

// This function is responsible for serializing driver data. It must be kept
// updated with the function that deserialized the data. This function
// is TestBoard::FetchAndDeserialize.
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_INFO: {
      zx_status_t status = zx::vmo::create(sizeof(kBoardInfo), 0, &vmo);
      if (status != ZX_OK) {
        return status;
      }
      status = vmo.write(&kBoardInfo, 0, sizeof(kBoardInfo));
      if (status != ZX_OK) {
        return status;
      }
      *length = sizeof(kBoardInfo);
      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);

      size_t metadata_size = 0;
      for (board_test::DeviceEntry& entry : entries) {
        metadata_size += entry.metadata_size;
      }

      zx_status_t status = zx::vmo::create(list_size + entry_size + metadata_size, 0, &vmo);
      if (status != ZX_OK) {
        return status;
      }

      // Write DeviceList to vmo.
      board_test::DeviceList list{.count = entries.size()};
      status = vmo.write(&list, 0, sizeof(list));
      if (status != ZX_OK) {
        return status;
      }

      // Write DeviceEntries to vmo.
      status = vmo.write(entries.data(), list_size, entry_size);
      if (status != ZX_OK) {
        return status;
      }

      // Write Metadata to vmo.
      size_t write_offset = list_size + entry_size;
      for (board_test::DeviceEntry& entry : entries) {
        status = vmo.write(entry.metadata, write_offset, entry.metadata_size);
        if (status != ZX_OK) {
          return status;
        }
        write_offset += entry.metadata_size;
      }

      *length = static_cast<uint32_t>(list_size + entry_size + metadata_size);
      break;
    }
    default:
      break;
  }
  *out = std::move(vmo);
  return ZX_OK;
}

}  // namespace

std::unique_ptr<IsolatedDevmgr> IsolatedDevmgr::Create(
    devmgr_launcher::Args args,
    std::unique_ptr<fbl::Vector<board_test::DeviceEntry>> device_list_unique_ptr,
    async_dispatcher_t* dispatcher) {
  if (dispatcher == nullptr) {
    dispatcher = async_get_default_dispatcher();
  }

  devmgr_integration_test::IsolatedDevmgr devmgr;
  if (device_list_unique_ptr != nullptr) {
    args.get_boot_item = [dev_list_ptr = std::move(device_list_unique_ptr)](
                             uint32_t type, uint32_t extra, zx::vmo* out, uint32_t* length) {
      return GetBootItem(*dev_list_ptr, type, extra, out, length);
    };
  }

  zx_status_t status =
      devmgr_integration_test::IsolatedDevmgr::Create(std::move(args), dispatcher, &devmgr);

  if (status == ZX_OK) {
    return std::make_unique<IsolatedDevmgr>(std::move(devmgr));
  } else {
    FX_LOGS(ERROR) << "Failed to create devmgr: " << zx_status_get_string(status);
    return nullptr;
  }
}

}  // namespace isolated_devmgr
