// 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 <inttypes.h>
#include <lib/sync/completion.h>
#include <lib/zircon-internal/debug.h>
#include <lib/zx/vmo.h>
#include <zircon/assert.h>
#include <zircon/status.h>

#include <memory>
#include <utility>

#include <ddk/protocol/block.h>
#include <ddk/protocol/block/volume.h>
#include <fbl/alloc_checker.h>
#include <zxcrypt/ddk-volume.h>
#include <zxcrypt/volume.h>

#define ZXDEBUG 0

namespace zxcrypt {

void SyncComplete(void* cookie, zx_status_t status, block_op_t* block) {
  // Use the 32bit command field to shuttle the response back to the callsite that's waiting on
  // the completion
  block->command = status;
  sync_completion_signal(static_cast<sync_completion_t*>(cookie));
}

// Performs synchronous I/O
zx_status_t SyncIO(zx_device_t* dev, uint32_t cmd, void* buf, size_t off, size_t len) {
  zx_status_t rc;

  if (!dev || !buf || len == 0) {
    xprintf("bad parameter(s): dev=%p, buf=%p, len=%zu\n", dev, buf, len);
    return ZX_ERR_INVALID_ARGS;
  }

  block_impl_protocol_t proto;
  if ((rc = device_get_protocol(dev, ZX_PROTOCOL_BLOCK, &proto)) != ZX_OK) {
    xprintf("block protocol not support\n");
    return ZX_ERR_NOT_SUPPORTED;
  }

  zx::vmo vmo;
  if ((rc = zx::vmo::create(len, 0, &vmo)) != ZX_OK) {
    xprintf("zx::vmo::create failed: %s\n", zx_status_get_string(rc));
    return rc;
  }

  block_info_t info;
  size_t op_size;
  block_impl_query(&proto, &info, &op_size);

  size_t bsz = info.block_size;
  ZX_DEBUG_ASSERT(off / bsz <= UINT32_MAX);
  ZX_DEBUG_ASSERT(len / bsz <= UINT32_MAX);
  fbl::AllocChecker ac;
  std::unique_ptr<char[]> raw;
  if constexpr (alignof(block_op_t) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
    raw = std::unique_ptr<char[]>(
        new (static_cast<std::align_val_t>(alignof(block_op_t)), &ac) char[op_size]);
  } else {
    raw = std::unique_ptr<char[]>(new (&ac) char[op_size]);
  }
  if (!ac.check()) {
    return ZX_ERR_NO_MEMORY;
  }
  block_op_t* block = reinterpret_cast<block_op_t*>(raw.get());

  sync_completion_t completion;
  sync_completion_reset(&completion);

  block->command = cmd;
  block->rw.vmo = vmo.get();
  block->rw.length = static_cast<uint32_t>(len / bsz);
  block->rw.offset_dev = static_cast<uint32_t>(off / bsz);
  block->rw.offset_vmo = 0;

  if (cmd == BLOCK_OP_WRITE && (rc = vmo.write(buf, 0, len)) != ZX_OK) {
    xprintf("zx::vmo::write failed: %s\n", zx_status_get_string(rc));
    return rc;
  }

  block_impl_queue(&proto, block, SyncComplete, &completion);
  sync_completion_wait(&completion, ZX_TIME_INFINITE);

  rc = block->command;
  if (rc != ZX_OK) {
    xprintf("Block I/O failed: %s\n", zx_status_get_string(rc));
    return rc;
  }

  if (cmd == BLOCK_OP_READ && (rc = vmo.read(buf, 0, len)) != ZX_OK) {
    xprintf("zx::vmo::read failed: %s\n", zx_status_get_string(rc));
    return rc;
  }

  return ZX_OK;
}

DdkVolume::DdkVolume(zx_device_t* dev) : Volume(), dev_(dev) {}

zx_status_t DdkVolume::Bind(crypto::Cipher::Direction direction, crypto::Cipher* cipher) const {
  zx_status_t rc;
  ZX_DEBUG_ASSERT(dev_);  // Cannot bind from library

  if (!cipher) {
    xprintf("bad parameter(s): cipher=%p\n", cipher);
    return ZX_ERR_INVALID_ARGS;
  }
  if (!block_.get()) {
    xprintf("not initialized\n");
    return ZX_ERR_BAD_STATE;
  }
  if ((rc = cipher->Init(cipher_, direction, data_key_, data_iv_, block_.len())) != ZX_OK) {
    return rc;
  }

  return ZX_OK;
}

zx_status_t DdkVolume::Unlock(zx_device_t* dev, const crypto::Secret& key, key_slot_t slot,
                              std::unique_ptr<DdkVolume>* out) {
  zx_status_t rc;

  if (!dev || !out) {
    xprintf("bad parameter(s): dev=%p, out=%p\n", dev, out);
    return ZX_ERR_INVALID_ARGS;
  }
  fbl::AllocChecker ac;
  std::unique_ptr<DdkVolume> volume(new (&ac) DdkVolume(dev));
  if (!ac.check()) {
    xprintf("allocation failed: %zu bytes\n", sizeof(DdkVolume));
    return ZX_ERR_NO_MEMORY;
  }
  if ((rc = volume->Init()) != ZX_OK) {
    xprintf("volume->Init() failed: %s\n", zx_status_get_string(rc));
    return rc;
  }
  if ((rc = volume->Unlock(key, slot)) != ZX_OK) {
    xprintf("volume->Unlock() failed: %s\n", zx_status_get_string(rc));
    return rc;
  }

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

zx_status_t DdkVolume::Init() { return Volume::Init(); }

zx_status_t DdkVolume::Unlock(const crypto::Secret& key, key_slot_t slot) {
  return Volume::Unlock(key, slot);
}

zx_status_t DdkVolume::GetBlockInfo(BlockInfo* out) {
  zx_status_t rc;
  block_impl_protocol_t proto;
  if ((rc = device_get_protocol(dev_, ZX_PROTOCOL_BLOCK, &proto)) != ZX_OK) {
    xprintf("block protocol not supported\n");
    return ZX_ERR_NOT_SUPPORTED;
  }

  block_info_t info;
  size_t block_op_size;
  block_impl_query(&proto, &info, &block_op_size);

  out->block_count = info.block_count;
  out->block_size = info.block_size;
  return ZX_OK;
}

zx_status_t DdkVolume::GetFvmSliceSize(uint64_t* out) {
  zx_status_t rc;
  block_volume_protocol_t proto;
  if ((rc = device_get_protocol(dev_, ZX_PROTOCOL_BLOCK_VOLUME, &proto)) != ZX_OK) {
    xprintf("block volume protocol not supported\n");
    return ZX_ERR_NOT_SUPPORTED;
  }

  parent_volume_info_t info;
  if ((rc = block_volume_query(&proto, &info)) != ZX_OK) {
    return rc;
  }

  *out = info.slice_size;
  return ZX_OK;
}

zx_status_t DdkVolume::DoBlockFvmVsliceQuery(uint64_t vslice_start,
                                             SliceRegion ranges[MAX_SLICE_REGIONS],
                                             uint64_t* slice_count) {
  static_assert(MAX_SLICE_QUERY_REQUESTS == Volume::MAX_SLICE_REGIONS,
                "block volume slice response count must match");
  zx_status_t rc;
  block_volume_protocol_t proto;
  if ((rc = device_get_protocol(dev_, ZX_PROTOCOL_BLOCK_VOLUME, &proto)) != ZX_OK) {
    xprintf("block volume protocol not supported\n");
    return ZX_ERR_NOT_SUPPORTED;
  }

  slice_region_t tmp_ranges[MAX_SLICE_QUERY_REQUESTS];
  size_t range_count;
  if ((rc = block_volume_query_slices(&proto, &vslice_start, 1, tmp_ranges,
                                      MAX_SLICE_QUERY_REQUESTS, &range_count)) != ZX_OK) {
    return rc;
  }
  if (range_count > Volume::MAX_SLICE_REGIONS) {
    // Should be impossible.  Trust nothing.
    return ZX_ERR_BAD_STATE;
  }

  *slice_count = range_count;
  for (size_t i = 0; i < range_count; i++) {
    ranges[i].allocated = tmp_ranges[i].allocated;
    ranges[i].count = tmp_ranges[i].count;
  }
  return ZX_OK;
}

zx_status_t DdkVolume::DoBlockFvmExtend(uint64_t start_slice, uint64_t slice_count) {
  zx_status_t rc;
  block_volume_protocol_t proto;
  if ((rc = device_get_protocol(dev_, ZX_PROTOCOL_BLOCK_VOLUME, &proto)) != ZX_OK) {
    xprintf("block volume protocol not supported\n");
    return ZX_ERR_NOT_SUPPORTED;
  }

  slice_extent_t extent;
  extent.offset = start_slice;
  extent.length = slice_count;
  return block_volume_extend(&proto, &extent);
}

zx_status_t DdkVolume::Read() {
  return SyncIO(dev_, BLOCK_OP_READ, block_.get(), offset_, block_.len());
}

zx_status_t DdkVolume::Write() {
  return SyncIO(dev_, BLOCK_OP_WRITE, block_.get(), offset_, block_.len());
}

}  // namespace zxcrypt
