// 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 <fuchsia/device/llcpp/fidl.h>
#include <fuchsia/io/c/fidl.h>
#include <zircon/device/vfs.h>

#include <block-client/cpp/remote-block-device.h>
#include <fs/trace.h>

namespace block_client {
namespace {

zx_status_t BlockGetFifo(const zx::channel& device, zx::fifo* out_fifo) {
  zx_status_t status, io_status;
  io_status =
      fuchsia_hardware_block_BlockGetFifo(device.get(), &status, out_fifo->reset_and_get_address());
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

zx_status_t BlockCloseFifo(const zx::channel& device) {
  zx_status_t status, io_status;
  io_status = fuchsia_hardware_block_BlockCloseFifo(device.get(), &status);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

}  // namespace

zx_status_t RemoteBlockDevice::ReadBlock(uint64_t block_num, uint64_t block_size,
                                         void* block) const {
  uint64_t offset = block_num * block_size;
  size_t actual;
  zx_status_t status, io_status;
  io_status = fuchsia_io_FileReadAt(device_.get(), block_size, offset, &status,
                                    reinterpret_cast<uint8_t*>(block), block_size, &actual);
  if (io_status != ZX_OK) {
    return io_status;
  }
  if (status != ZX_OK) {
    return status;
  }
  if (actual != block_size) {
    return ZX_ERR_IO;
  }
  return ZX_OK;
}

zx_status_t RemoteBlockDevice::FifoTransaction(block_fifo_request_t* requests, size_t count) {
  return fifo_client_.Transaction(requests, count);
}

zx_status_t RemoteBlockDevice::GetDevicePath(size_t buffer_len, char* out_name,
                                             size_t* out_len) const {
  if (buffer_len == 0) {
    return ZX_ERR_BUFFER_TOO_SMALL;
  }
  zx_status_t status, io_status;

  auto resp = ::llcpp::fuchsia::device::Controller::Call::GetTopologicalPath(
      zx::unowned_channel(device_.get()));

  io_status = resp.status();
  if (io_status != ZX_OK) {
    return io_status;
  }

  if (resp->result.is_err()) {
    status = resp->result.err();
  } else {
    auto& r = resp->result.response();
    *out_len = r.path.size();
    memcpy(out_name, r.path.data(), r.path.size());
    status = ZX_OK;
  }

  if (status != ZX_OK) {
    return status;
  }
  // Ensure null-terminated
  out_name[*out_len] = 0;
  // Account for the null byte in the length, since callers expect it.
  (*out_len)++;
  return ZX_OK;
}

zx_status_t RemoteBlockDevice::BlockGetInfo(fuchsia_hardware_block_BlockInfo* out_info) const {
  zx_status_t status;
  zx_status_t io_status = fuchsia_hardware_block_BlockGetInfo(device_.get(), &status, out_info);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

zx_status_t RemoteBlockDevice::BlockAttachVmo(const zx::vmo& vmo,
                                              storage::Vmoid* out_vmoid) {
  zx::vmo xfer_vmo;
  zx_status_t status = vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &xfer_vmo);
  if (status != ZX_OK) {
    return status;
  }

  fuchsia_hardware_block_VmoId vmoid;
  zx_status_t io_status =
      fuchsia_hardware_block_BlockAttachVmo(device_.get(), xfer_vmo.release(), &status, &vmoid);
  if (io_status != ZX_OK) {
    return io_status;
  }
  *out_vmoid = storage::Vmoid(vmoid.id);
  return status;
}

zx_status_t RemoteBlockDevice::VolumeQuery(
    fuchsia_hardware_block_volume_VolumeInfo* out_info) const {
  // Querying may be used to confirm if the underlying connection is capable of
  // communicating the FVM protocol. Clone the connection, since if the block
  // device does NOT speak the Volume protocol, the connection is terminated.
  zx::channel connection, server;
  zx_status_t status = zx::channel::create(0, &connection, &server);
  if (status != ZX_OK) {
    return status;
  }
  uint32_t flags = ZX_FS_FLAG_CLONE_SAME_RIGHTS;
  status = fuchsia_io_NodeClone(device_.get(), flags, server.release());
  if (status != ZX_OK) {
    return status;
  }

  zx_status_t io_status =
      fuchsia_hardware_block_volume_VolumeQuery(connection.get(), &status, out_info);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

zx_status_t RemoteBlockDevice::VolumeQuerySlices(
    const uint64_t* slices, size_t slices_count,
    fuchsia_hardware_block_volume_VsliceRange* out_ranges, size_t* out_ranges_count) const {
  zx_status_t status, io_status;
  io_status = fuchsia_hardware_block_volume_VolumeQuerySlices(
      device_.get(), slices, slices_count, &status, out_ranges, out_ranges_count);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

zx_status_t RemoteBlockDevice::VolumeExtend(uint64_t offset, uint64_t length) {
  zx_status_t status, io_status;
  io_status = fuchsia_hardware_block_volume_VolumeExtend(device_.get(), offset, length, &status);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

zx_status_t RemoteBlockDevice::VolumeShrink(uint64_t offset, uint64_t length) {
  zx_status_t status, io_status;
  io_status = fuchsia_hardware_block_volume_VolumeShrink(device_.get(), offset, length, &status);
  if (io_status != ZX_OK) {
    return io_status;
  }
  return status;
}

zx_status_t RemoteBlockDevice::Create(zx::channel device, std::unique_ptr<RemoteBlockDevice>* out) {
  zx::fifo fifo;
  zx_status_t status = BlockGetFifo(device, &fifo);
  if (status != ZX_OK) {
    FS_TRACE_ERROR("Could not acquire block fifo: %d\n", status);
    return status;
  }
  block_client::Client fifo_client;
  status = block_client::Client::Create(std::move(fifo), &fifo_client);
  if (status != ZX_OK) {
    return status;
  }
  *out = std::unique_ptr<RemoteBlockDevice>(
      new RemoteBlockDevice(std::move(device), std::move(fifo_client)));
  return ZX_OK;
}

RemoteBlockDevice::RemoteBlockDevice(zx::channel device, block_client::Client fifo_client)
    : device_(std::move(device)), fifo_client_(std::move(fifo_client)) {}

RemoteBlockDevice::~RemoteBlockDevice() { BlockCloseFifo(device_); }

}  // namespace block_client
