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

#include <lib/ftl/ndm-driver.h>
#include <stdint.h>
#include <zircon/assert.h>

#include <cstdint>
#include <memory>
#include <new>
#include <vector>

#include <ddk/debug.h>
#include <ddktl/protocol/badblock.h>
#include <fbl/array.h>

#include "ddk/protocol/nand.h"
#include "nand_operation.h"
#include "oob_doubler.h"

namespace {

uint32_t GetParameter(const char* key) {
  const char* value = getenv(key);
  if (!value) {
    return 0;
  }
  return static_cast<uint32_t>(strtoul(value, nullptr, 0));
}

__PRINTFLIKE(3, 4) void LogTrace(const char* file, int line, const char* format, ...) {
  va_list args;
  va_start(args, format);
  zxlogvf(TRACE, file, line, format, args);
  va_end(args);
}

__PRINTFLIKE(3, 4) void LogDebug(const char* file, int line, const char* format, ...) {
  va_list args;
  va_start(args, format);
  zxlogvf(DEBUG, file, line, format, args);
  va_end(args);
}

__PRINTFLIKE(3, 4) void LogInfo(const char* file, int line, const char* format, ...) {
  va_list args;
  va_start(args, format);
  zxlogvf(INFO, file, line, format, args);
  va_end(args);
}

__PRINTFLIKE(3, 4) void LogWarning(const char* file, int line, const char* format, ...) {
  va_list args;
  va_start(args, format);
  zxlogvf(WARNING, file, line, format, args);
  va_end(args);
}

__PRINTFLIKE(3, 4) void LogError(const char* file, int line, const char* format, ...) {
  va_list args;
  va_start(args, format);
  zxlogvf(ERROR, file, line, format, args);
  va_end(args);
}

class NandDriverImpl final : public ftl::NandDriver {
 public:
  NandDriverImpl(const nand_protocol_t* parent, const bad_block_protocol_t* bad_block,
                 ftl::OperationCounters* counters)
      : parent_(parent), bad_block_protocol_(bad_block), counters_(counters) {}
  ~NandDriverImpl() final {}

  // NdmDriver interface:
  const char* Init() final;
  const char* Attach(const ftl::Volume* ftl_volume) final;
  bool Detach() final;
  int NandRead(uint32_t start_page, uint32_t page_count, void* page_buffer, void* oob_buffer) final;
  int NandWrite(uint32_t start_page, uint32_t page_count, const void* page_buffer,
                const void* oob_buffer) final;
  int NandErase(uint32_t page_num) final;
  int IsBadBlock(uint32_t page_num) final;
  bool IsEmptyPage(uint32_t page_num, const uint8_t* data, const uint8_t* spare) final;
  void TryEraseRange(uint32_t start_block, uint32_t end_block) final;
  const fuchsia_hardware_nand_Info& info() const final { return info_; }

 private:
  // Returns true if initialization was performed with an alternate configuration.
  // |options| is passed by value, so a temporary object will be created by the
  // compiler.
  bool HandleAlternateConfig(const ftl::Volume* ftl_volume, ftl::VolumeOptions options);
  bool GetBadBlocks();

  ftl::OobDoubler parent_;
  size_t op_size_ = 0;
  fuchsia_hardware_nand_Info info_ = {};
  const bad_block_protocol_t* bad_block_protocol_;
  fbl::Array<uint32_t> bad_blocks_;
  ftl::OperationCounters* counters_ = nullptr;
};

const char* NandDriverImpl::Init() {
  parent_.Query(&info_, &op_size_);
  zxlogf(INFO, "FTL: Nand: page_size %u, block size %u, %u blocks, %u ecc, %u oob, op size %lu",
         info_.page_size, info_.pages_per_block, info_.num_blocks, info_.ecc_bits, info_.oob_size,
         op_size_);

  if (!GetBadBlocks()) {
    return "Failed to query bad blocks";
  }

  ZX_DEBUG_ASSERT(info_.oob_size >= 16);
  return nullptr;
}

const char* NandDriverImpl::Attach(const ftl::Volume* ftl_volume) {
  ftl::VolumeOptions options = {
      .num_blocks = info_.num_blocks,
      // This should be 2%, but that is of the whole device, not just this partition.
      // TODO(fxbug.dev/39372): This value should be provided by the stack. For now, use 2% for
      // small disks (likely tests).
      .max_bad_blocks = info_.num_blocks > 1000 ? 41 : info_.num_blocks / 50,
      .block_size = info_.page_size * info_.pages_per_block,
      .page_size = info_.page_size,
      .eb_size = info_.oob_size,
      // If flags change, make sure that HandleAlternateConfig() still makes sense.
      .flags = ftl::kReadOnlyInit};

  if (!IsNdmDataPresent(options)) {
    if (HandleAlternateConfig(ftl_volume, options)) {
      // Already handled.
      return nullptr;
    }
    options.flags = 0;
  } else if (BadBbtReservation()) {
    return "Unable to use bad block reservation";
  }
  ftl::LoggerProxy logger = {
      .trace = &LogTrace,
      .debug = &LogDebug,
      .info = &LogInfo,
      .warn = &LogWarning,
      .error = &LogError,
  };
  const char* error = CreateNdmVolumeWithLogger(ftl_volume, options, true, logger);
  if (error) {
    // Retry allowing the volume to be fixed as needed.
    zxlogf(INFO, "FTL: About to retry volume creation");
    options.flags = 0;
    error = CreateNdmVolume(ftl_volume, options);
  }

  if (!error && !volume_data_saved()) {
    // Initialization is complete; update the control data format, but ignore errors.
    if (!WriteVolumeData()) {
      zxlogf(ERROR, "FTL: Failed to upgrade NDM version");
    }
  }
  return error;
}

bool NandDriverImpl::Detach() { return RemoveNdmVolume(); }

// Returns kNdmOk, kNdmUncorrectableEcc, kNdmFatalError or kNdmUnsafeEcc.
int NandDriverImpl::NandRead(uint32_t start_page, uint32_t page_count, void* page_buffer,
                             void* oob_buffer) {
  if (counters_ != nullptr) {
    counters_->page_read++;
  }
  ftl::NandOperation operation(op_size_);
  uint32_t data_pages = page_buffer ? page_count : 0;
  size_t data_size = data_pages * info_.page_size;
  size_t oob_size = (oob_buffer ? page_count : 0) * info_.oob_size;
  size_t num_bytes = data_size + oob_size;

  nand_operation_t* op = operation.GetOperation();
  op->rw.command = NAND_OP_READ;
  op->rw.offset_nand = start_page;
  op->rw.length = page_count;

  zx_status_t status = ZX_OK;
  if (page_buffer) {
    status = operation.SetDataVmo(num_bytes);
    if (status != ZX_OK) {
      zxlogf(ERROR, "FTL: SetDataVmo Failed: %d", status);
      return ftl::kNdmFatalError;
    }
  }

  if (oob_buffer) {
    status = operation.SetOobVmo(num_bytes);
    op->rw.offset_oob_vmo = data_pages;
    if (status != ZX_OK) {
      zxlogf(ERROR, "FTL: SetOobVmo Failed: %d", status);
      return ftl::kNdmFatalError;
    }
  }

  zxlogf(TRACE, "FTL: Read page, start %d, len %d", start_page, page_count);
  status = operation.Execute(&parent_);
  if (status == ZX_ERR_IO_DATA_INTEGRITY) {
    return ftl::kNdmUncorrectableEcc;
  }

  if (status != ZX_OK) {
    zxlogf(ERROR, "FTL: Read failed: %d", status);
    return ftl::kNdmFatalError;
  }

  if (page_buffer) {
    memcpy(page_buffer, operation.buffer(), data_size);
  }

  if (oob_buffer) {
    memcpy(oob_buffer, operation.buffer() + data_size, oob_size);
  }

  // This threshold is somewhat arbitrary, and should be adjusted if we deal
  // with multiple controllers (by making it part of the nand protocol), or
  // if we find it inappropriate after running endurance tests. We could also
  // decide we need the FTL to have a more active role detecting blocks that
  // should be moved around.
  if (op->rw.corrected_bit_flips > info_.ecc_bits / 2) {
    return ftl::kNdmUnsafeEcc;
  }

  return ftl::kNdmOk;
}

// Returns kNdmOk, kNdmError or kNdmFatalError. kNdmError triggers marking the block as bad.
int NandDriverImpl::NandWrite(uint32_t start_page, uint32_t page_count, const void* page_buffer,
                              const void* oob_buffer) {
  if (counters_ != nullptr) {
    counters_->page_write++;
  }
  ftl::NandOperation operation(op_size_);
  uint32_t data_pages = page_buffer ? page_count : 0;
  size_t data_size = data_pages * info_.page_size;
  size_t oob_size = (oob_buffer ? page_count : 0) * info_.oob_size;
  size_t num_bytes = data_size + oob_size;

  nand_operation_t* op = operation.GetOperation();
  op->rw.command = NAND_OP_WRITE;
  op->rw.offset_nand = start_page;
  op->rw.length = page_count;

  zx_status_t status = ZX_OK;
  if (page_buffer) {
    status = operation.SetDataVmo(num_bytes);
    if (status != ZX_OK) {
      zxlogf(ERROR, "FTL: SetDataVmo Failed: %d", status);
      return ftl::kNdmFatalError;
    }
    memcpy(operation.buffer(), page_buffer, data_size);
  }

  if (oob_buffer) {
    status = operation.SetOobVmo(num_bytes);
    op->rw.offset_oob_vmo = data_pages;
    if (status != ZX_OK) {
      zxlogf(ERROR, "FTL: SetOobVmo Failed: %d", status);
      return ftl::kNdmFatalError;
    }
    memcpy(operation.buffer() + data_size, oob_buffer, oob_size);
  }

  zxlogf(TRACE, "FTL: Write page, start %d, len %d", start_page, page_count);
  status = operation.Execute(&parent_);
  if (status != ZX_OK) {
    return status == ZX_ERR_IO ? ftl::kNdmError : ftl::kNdmFatalError;
  }

  return ftl::kNdmOk;
}

// Returns kNdmOk or kNdmError. kNdmError triggers marking the block as bad.
int NandDriverImpl::NandErase(uint32_t page_num) {
  if (counters_ != nullptr) {
    counters_->block_erase++;
  }
  uint32_t block_num = page_num / info_.pages_per_block;
  ftl::NandOperation operation(op_size_);

  nand_operation_t* op = operation.GetOperation();
  op->erase.command = NAND_OP_ERASE;
  op->erase.first_block = block_num;
  op->erase.num_blocks = 1;

  zxlogf(TRACE, "FTL: Erase block num %d", block_num);

  zx_status_t status = operation.Execute(&parent_);
  if (status != ZX_OK) {
    zxlogf(ERROR, "FTL: NandErase failed: %d", status);
    return status == ZX_ERR_IO ? ftl::kNdmError : ftl::kNdmFatalError;
  }

  return ftl::kNdmOk;
}

// Returns kTrue, kFalse or kNdmError.
int NandDriverImpl::IsBadBlock(uint32_t page_num) {
  if (!bad_blocks_.size()) {
    return ftl::kFalse;
  }

  // The list should be really short.
  uint32_t block_num = page_num / info_.pages_per_block;
  for (uint32_t bad_block : bad_blocks_) {
    if (bad_block == block_num) {
      zxlogf(ERROR, "FTL: IsBadBlock(%d) found", block_num);
      return ftl::kTrue;
    }
  }
  return ftl::kFalse;
}

bool NandDriverImpl::IsEmptyPage(uint32_t page_num, const uint8_t* data, const uint8_t* spare) {
  return IsEmptyPageImpl(data, info_.page_size, spare, info_.oob_size);
}

void NandDriverImpl::TryEraseRange(uint32_t start_block, uint32_t end_block) {
  std::vector<std::unique_ptr<ftl::NandOperation>> erase_operations;
  end_block = std::min(end_block, info_.num_blocks);

  for (unsigned int i = start_block; i < end_block; ++i) {
    // Skip known bad blocks.
    if (IsBadBlock(i) != ftl::kFalse) {
      continue;
    }

    // Each erase operation is queued independently to prevent a new bad block in the range
    // invalidating the erasure of the entire range.
    erase_operations.push_back(std::make_unique<ftl::NandOperation>(op_size_));
    auto& operation = *erase_operations.back();
    operation.GetOperation()->command = NAND_OP_ERASE;
    operation.GetOperation()->erase.first_block = i;
    operation.GetOperation()->erase.num_blocks = 1;
  }

  auto results = ftl::NandOperation::ExecuteBatch(&parent_, erase_operations);
  for (size_t i = 0; i < erase_operations.size(); ++i) {
    // If we run into a new bad block while erasing, its harmless, though we should log it.
    if (results[i].is_error()) {
      zxlogf(DEBUG, "FTL: Bad block detect at block number %i.",
             erase_operations[i]->GetOperation()->erase.first_block);
    }
  }
}

bool NandDriverImpl::HandleAlternateConfig(const ftl::Volume* ftl_volume,
                                           ftl::VolumeOptions options) {
  uint32_t num_blocks = GetParameter("driver.ftl.original-size");
  if (!num_blocks || num_blocks >= info_.num_blocks) {
    return false;
  }
  options.num_blocks = num_blocks;

  if (!IsNdmDataPresent(options)) {
    // Nothing at the alternate location.
    return false;
  }
  RemoveNdmVolume();

  options.flags = 0;  // Allow automatic fixing of errors.
  zxlogf(INFO, "FTL: About to read volume of size %u blocks", num_blocks);
  if (!IsNdmDataPresent(options)) {
    zxlogf(ERROR, "FTL: Failed to read initial volume");
    return true;
  }

  if (!SaveBadBlockData()) {
    zxlogf(ERROR, "FTL: Failed to extract bad block table");
    return true;
  }
  RemoveNdmVolume();

  TryEraseRange(num_blocks, info_.num_blocks);
  options.num_blocks = info_.num_blocks;
  if (!IsNdmDataPresent(options)) {
    zxlogf(ERROR, "FTL: Failed to NDM extend volume");
    return true;
  }
  if (!RestoreBadBlockData()) {
    zxlogf(ERROR, "FTL: Failed to write bad block table");
    return true;
  }

  const char* error = CreateNdmVolume(ftl_volume, options);
  if (error) {
    zxlogf(ERROR, "FTL: Failed to extend volume: %s", error);
  } else {
    zxlogf(INFO, "FTL: Volume successfully extended");
  }

  return true;
}

bool NandDriverImpl::GetBadBlocks() {
  if (!bad_block_protocol_->ops) {
    return true;
  }
  ddk::BadBlockProtocolClient client(const_cast<bad_block_protocol_t*>(bad_block_protocol_));

  size_t num_bad_blocks;
  zx_status_t status = client.GetBadBlockList(nullptr, 0, &num_bad_blocks);
  if (status != ZX_OK) {
    return false;
  }
  if (!num_bad_blocks) {
    return true;
  }

  std::unique_ptr<uint32_t[]> bad_block_list(new uint32_t[num_bad_blocks]);
  size_t new_count;
  status = client.GetBadBlockList(bad_block_list.get(), num_bad_blocks, &new_count);
  if (status != ZX_OK) {
    return false;
  }
  ZX_ASSERT(new_count == num_bad_blocks);

  bad_blocks_ = fbl::Array<uint32_t>(bad_block_list.release(), num_bad_blocks);

  for (uint32_t bad_block : bad_blocks_) {
    zxlogf(DEBUG, "Bad block: %x", bad_block);
  }
  return true;
}

}  // namespace

namespace ftl {

// Static.
std::unique_ptr<NandDriver> NandDriver::Create(const nand_protocol_t* parent,
                                               const bad_block_protocol_t* bad_block) {
  return std::unique_ptr<NandDriver>(new NandDriverImpl(parent, bad_block, nullptr));
}

std::unique_ptr<NandDriver> NandDriver::CreateWithCounters(const nand_protocol_t* parent,
                                                           const bad_block_protocol_t* bad_block,
                                                           OperationCounters* counters) {
  return std::unique_ptr<NandDriver>(new NandDriverImpl(parent, bad_block, counters));
}

}  // namespace ftl.
