// 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 <errno.h>
#include <fcntl.h>
#include <lib/log/log.h>
#include <lib/mtd/mtd-interface.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

// Some chips report a spare size that is not capable of being read and/or
// written usually due to reserved bits for ECC or limits set by a NAND
// controller. Allow the spare size to be set based on a build flag to account
// for this.
#ifndef SPARE_SIZE
#define SPARE_SIZE 0
#endif

namespace mtd {

std::unique_ptr<MtdInterface> MtdInterface::Create(const std::string& path) {
  fbl::unique_fd fd(open(path.c_str(), O_RDWR));
  if (!fd) {
    LOGF(ERROR, "MtdInterface")("Failed to open %s: %s\n", path.c_str(), strerror(errno));
    return nullptr;
  }

  mtd_info_t mtd_info;
  int ret = ioctl(fd.get(), MEMGETINFO, &mtd_info);
  if (ret) {
    LOGF(ERROR, "MtdInterface")("Failed to get info for %s: %s", path.c_str(), strerror(errno));
    return nullptr;
  }

  // Cannot use make_unique with a private constructor, so create MtdInterface
  // using new explicitly and wrap it in a unique_ptr immediately.
  return std::unique_ptr<MtdInterface>(new MtdInterface(std::move(fd), mtd_info));
}

MtdInterface::MtdInterface(fbl::unique_fd fd, const mtd_info_t& mtd_info)
    : fd_(std::move(fd)), mtd_info_(mtd_info) {}

uint32_t MtdInterface::PageSize() const { return mtd_info_.writesize; }

uint32_t MtdInterface::BlockSize() const { return mtd_info_.erasesize; }

uint32_t MtdInterface::OobSize() const { return SPARE_SIZE > 0 ? SPARE_SIZE : mtd_info_.oobsize; }

uint32_t MtdInterface::Size() const { return mtd_info_.size; }

zx_status_t MtdInterface::ReadPage(uint32_t byte_offset, void* data_bytes, uint32_t* actual) {
  if (byte_offset % PageSize() != 0) {
    LOG(ERROR, "MtdInterface")("byte_offset must be set to the start of a page");
    return ZX_ERR_INVALID_ARGS;
  }

  lseek(fd_.get(), byte_offset, SEEK_SET);

  ssize_t ret = read(fd_.get(), data_bytes, PageSize());
  if (ret != PageSize()) {
    LOGF(ERROR, "MtdInterface")
    ("Failed to read page at offset %u: %s", byte_offset, strerror(errno));
    // TODO(mbrunson): Return more specific error.
    return ZX_ERR_IO;
  }

  *actual = static_cast<uint32_t>(ret);
  return ZX_OK;
}

zx_status_t MtdInterface::ReadOob(uint32_t byte_offset, void* oob_bytes) {
  if (byte_offset % PageSize() != 0) {
    LOG(ERROR, "MtdInterface")("byte_offset must be set to the start of a page.");
    return ZX_ERR_INVALID_ARGS;
  }

  struct mtd_oob_buf oob = {byte_offset, OobSize(), static_cast<unsigned char*>(oob_bytes)};

  int ret = ioctl(fd_.get(), MEMREADOOB, &oob);
  if (ret < 0) {
    LOGF(ERROR, "MtdInterface")
    ("Failed to read OOB at offset %u: %s", byte_offset, strerror(errno));
    // TODO(mbrunson): Return more specific error.
    return ZX_ERR_IO;
  }

  return ZX_OK;
}

zx_status_t MtdInterface::WritePage(uint32_t byte_offset, const void* data_bytes,
                                    const void* oob_bytes) {
  if (byte_offset % PageSize() != 0) {
    LOG(ERROR, "MtdInterface")("byte_offset must be set to the start of a page.");
    return ZX_ERR_INVALID_ARGS;
  }

  ssize_t ret;

  // Some drivers don't support MEMWRITE so implement a fallback using
  // MEMWRITEOOB and POSIX write operations. Incidentally, tests on using
  // nandsim fail in this manner and do not report the failure, so we're relying
  // on a build flag.
#ifdef MEMWRITE_NOT_SUPPORTED
  if (oob_bytes) {
    struct mtd_oob_buf oob_req = {byte_offset, OobSize(),
                                  reinterpret_cast<unsigned char*>(const_cast<void*>(oob_bytes))};

    ret = ioctl(fd_.get(), MEMWRITEOOB, &oob_req);
    if (ret < 0) {
      LOGF(ERROR, "MtdInterface")
      ("Failed to write page at offset %d: %s", byte_offset, strerror(errno));
      return ZX_ERR_IO;
    }
  }

  if (data_bytes) {
    if (lseek(fd_.get(), byte_offset, SEEK_SET) != byte_offset) {
      LOGF(ERROR, "MtdInterface")("Failed to seek to offset %d: %s", byte_offset, strerror(errno));
      return ZX_ERR_IO;
    }

    ret = write(fd_.get(), data_bytes, PageSize());
    LOGF(INFO, "MtdInterface")("write: %d", ret);
    if (ret != PageSize()) {
      LOGF(ERROR, "MtdInterface")
      ("Failed to write page at offset %d: %s", byte_offset, strerror(errno));
      return ZX_ERR_IO;
    }

    if (static_cast<size_t>(ret) != PageSize()) {
      LOGF(ERROR, "MtdInterface")
      ("Wrote unexpected number of bytes. Expected %lu, wrote %d: %s", PageSize(), ret,
       strerror(errno));
      return ZX_ERR_IO_DATA_LOSS;
    }
  }
#else
  struct mtd_write_req req = {static_cast<uint64_t>(byte_offset),
                              static_cast<uint64_t>(PageSize()),
                              static_cast<uint64_t>(OobSize()),
                              reinterpret_cast<uint64_t>(data_bytes),
                              reinterpret_cast<uint64_t>(oob_bytes),
                              MTD_OPS_PLACE_OOB,
                              {0}};

  ret = ioctl(fd_.get(), MEMWRITE, &req);
  if (ret < 0) {
    LOGF(ERROR, "MtdInterface")
    ("Failed to write page at offset %d: %s", byte_offset, strerror(errno));
    // TODO(mbrunson): Return more specific error.
    return ZX_ERR_IO;
  }
#endif

  return ZX_OK;
}

zx_status_t MtdInterface::EraseBlock(uint32_t byte_offset) {
  if (byte_offset % BlockSize() != 0) {
    LOG(ERROR, "MtdInterface")("byte_offset must be set to the start of a block.");
    return ZX_ERR_INVALID_ARGS;
  }

  int ret;
  erase_info_t ei = {byte_offset, BlockSize()};

  if ((ret = ioctl(fd_.get(), MEMERASE, &ei)) < 0) {
    perror("Failed to erase block");
    // TODO(mbrunson): Return more specific error.
    return ZX_ERR_IO;
  }
  return ZX_OK;
}

zx_status_t MtdInterface::IsBadBlock(uint32_t byte_offset, bool* is_bad_block) {
  if (byte_offset % BlockSize() != 0) {
    LOG(ERROR, "MtdInterface")("byte_offset must be set to the start of a block.");
    return ZX_ERR_INVALID_ARGS;
  }

  loff_t seek = byte_offset;

  int ret = ioctl(fd_.get(), MEMGETBADBLOCK, &seek);
  if (ret < 0) {
    LOGF(ERROR, "MtdInterface")
    ("Failed to get bad block info at offset %d: %s", byte_offset, strerror(errno));
    // TODO(mbrunson): Return more specific error.
    return ZX_ERR_IO;
  }

  *is_bad_block = ret > 0;
  return ZX_OK;
}

}  // namespace mtd
