// 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 <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <lib/log/log.h>
#include <lib/mtd/mtd-interface.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() { return mtd_info_.writesize; }

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

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

uint32_t MtdInterface::Size() { 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
