// 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/ftl-mtd/nand-volume-driver.h>
#include <stdio.h>
#include <zircon/assert.h>

#include <functional>
#include <utility>

namespace ftl_mtd {

using namespace std::placeholders;

zx_status_t NandVolumeDriver::Create(uint32_t block_offset, uint32_t max_bad_blocks,
                                     std::unique_ptr<mtd::NandInterface> interface,
                                     std::unique_ptr<NandVolumeDriver>* out) {
  uint32_t block_count = interface->Size() / interface->BlockSize();
  if (block_offset >= block_count) {
    fprintf(stderr, "Block offset must be less than block count of %u.\n", block_count);
    return ZX_ERR_INVALID_ARGS;
  }

  uint32_t usable_block_count = block_count - block_offset;
  if (max_bad_blocks >= usable_block_count) {
    fprintf(stderr, "Max bad blocks must be less than block count of %u.\n", usable_block_count);
    return ZX_ERR_INVALID_ARGS;
  }

  uint32_t page_multiplier = 1;
  while (page_multiplier * interface->OobSize() < kMinimumOobSize) {
    page_multiplier *= 2;
  }

  *out = std::unique_ptr<NandVolumeDriver>(
      new NandVolumeDriver(block_offset, max_bad_blocks, page_multiplier, std::move(interface)));
  return ZX_OK;
}

NandVolumeDriver::NandVolumeDriver(uint32_t block_offset, uint32_t max_bad_blocks,
                                   uint32_t page_multiplier,
                                   std::unique_ptr<mtd::NandInterface> interface)
    : NdmBaseDriver(ftl::DefaultLogger()),
      block_offset_(block_offset),
      page_multiplier_(page_multiplier),
      max_bad_blocks_(max_bad_blocks),
      interface_(std::move(interface)) {}

const char* NandVolumeDriver::Init() { return nullptr; }

const char* NandVolumeDriver::Attach(const ftl::Volume* ftl_volume) {
  ftl::VolumeOptions options = {
      .num_blocks = (interface_->Size() - ByteOffset()) / interface_->BlockSize(),
      // This should be 2%, but that is of the whole device, not just this partition.
      .max_bad_blocks = max_bad_blocks_,
      .block_size = interface_->BlockSize(),
      .page_size = PageSize(),
      .eb_size = SpareSize(),
      .flags = 0  // Same as FSF_DRVR_PAGES (current default).
  };

  return CreateNdmVolume(ftl_volume, options);
}

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

int NandVolumeDriver::NandWrite(uint32_t start_page, uint32_t page_count, const void* page_buffer,
                                const void* oob_buffer) {
  uint32_t real_start_page;
  uint32_t real_end_page;
  if (GetPageIndices(start_page, page_count, &real_start_page, &real_end_page) != ZX_OK) {
    return ftl::kNdmFatalError;
  }

  const uint8_t* page_buffer_ptr = reinterpret_cast<const uint8_t*>(page_buffer);
  const uint8_t* oob_buffer_ptr = reinterpret_cast<const uint8_t*>(oob_buffer);

  for (uint32_t page = real_start_page; page < real_end_page; page++) {
    zx_status_t status =
        interface_->WritePage(GetByteOffsetForPage(page), page_buffer_ptr, oob_buffer_ptr);

    // We checked the inputs before, so the interface should never return ZX_ERR_INVALID_ARGS.
    ZX_ASSERT(status != ZX_ERR_INVALID_ARGS);

    if (status != ZX_OK) {
      return ftl::kNdmError;
    }

    page_buffer_ptr += interface_->PageSize();
    oob_buffer_ptr += interface_->OobSize();
  }

  return ftl::kNdmOk;
}

int NandVolumeDriver::NandRead(uint32_t start_page, uint32_t page_count, void* page_buffer,
                               void* oob_buffer) {
  uint32_t real_start_page;
  uint32_t real_end_page;
  if (GetPageIndices(start_page, page_count, &real_start_page, &real_end_page) != ZX_OK) {
    return ftl::kNdmFatalError;
  }

  uint8_t* page_buffer_ptr = reinterpret_cast<uint8_t*>(page_buffer);
  uint8_t* oob_buffer_ptr = reinterpret_cast<uint8_t*>(oob_buffer);

  for (uint32_t page = real_start_page; page < real_end_page; page++) {
    zx_status_t status =
        ReadPageAndOob(GetByteOffsetForPage(page), page_buffer_ptr, oob_buffer_ptr);

    if (status != ZX_OK) {
      return ftl::kNdmFatalError;
    }

    if (page_buffer) {
      page_buffer_ptr += interface_->PageSize();
    }

    if (oob_buffer) {
      oob_buffer_ptr += interface_->OobSize();
    }
  }

  return ftl::kNdmOk;
}

int NandVolumeDriver::NandErase(uint32_t page_num) {
  uint32_t real_start_page;
  uint32_t real_end_page;
  if (GetPageIndices(page_num, 1, &real_start_page, &real_end_page) != ZX_OK) {
    return ftl::kNdmError;
  }

  zx_status_t status = interface_->EraseBlock(GetBlockOffsetForPage(real_start_page));
  return status == ZX_OK ? ftl::kNdmOk : ftl::kNdmError;
}

int NandVolumeDriver::IsBadBlock(uint32_t page_num) {
  bool is_bad_block = false;

  uint32_t real_start_page;
  uint32_t real_end_page;
  if (GetPageIndices(page_num, 1, &real_start_page, &real_end_page) != ZX_OK) {
    return ftl::kNdmError;
  }

  zx_status_t status =
      interface_->IsBadBlock(GetBlockOffsetForPage(real_start_page), &is_bad_block);
  if (status != ZX_OK) {
    return ftl::kNdmError;
  }

  return is_bad_block ? ftl::kTrue : ftl::kFalse;
}

bool NandVolumeDriver::IsEmptyPage(uint32_t page_num, const uint8_t* page_buffer,
                                   const uint8_t* oob_buffer) {
  return IsEmptyPageImpl(page_buffer, PageSize(), oob_buffer, SpareSize());
}

zx_status_t NandVolumeDriver::ReadPageAndOob(uint32_t byte_offset, void* page_buffer,
                                             void* oob_buffer) {
  if (page_buffer) {
    uint32_t actual;
    zx_status_t read_page_status = interface_->ReadPage(byte_offset, page_buffer, &actual);

    if (read_page_status != ZX_OK) {
      return read_page_status;
    }

    if (actual != interface_->PageSize()) {
      return ZX_ERR_IO_DATA_LOSS;
    }
  }

  if (oob_buffer) {
    zx_status_t read_oob_status = interface_->ReadOob(byte_offset, oob_buffer);
    if (read_oob_status != ZX_OK) {
      return read_oob_status;
    }
  }

  return ZX_OK;
}

zx_status_t NandVolumeDriver::GetPageIndices(uint32_t mapped_page, uint32_t mapped_page_count,
                                             uint32_t* start_page, uint32_t* end_page) {
  uint32_t start = ByteOffset() / interface_->PageSize() + page_multiplier_ * mapped_page;
  uint32_t end = start + page_multiplier_ * mapped_page_count;
  uint32_t last_page = interface_->Size() / interface_->PageSize();

  if (start >= last_page || end > last_page) {
    return ZX_ERR_OUT_OF_RANGE;
  }

  *start_page = start;
  *end_page = end;
  return ZX_OK;
}

uint32_t NandVolumeDriver::GetBlockOffsetForPage(uint32_t real_page) {
  return GetByteOffsetForPage(real_page) / interface_->BlockSize() * interface_->BlockSize();
}

uint32_t NandVolumeDriver::GetByteOffsetForPage(uint32_t real_page) {
  return real_page * interface_->PageSize();
}

uint32_t NandVolumeDriver::ByteOffset() { return block_offset_ * interface_->BlockSize(); }

uint32_t NandVolumeDriver::PageSize() { return page_multiplier_ * interface_->PageSize(); }

uint8_t NandVolumeDriver::SpareSize() { return page_multiplier_ * interface_->OobSize(); }

}  // namespace ftl_mtd
