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

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <ddk/metadata.h>
#include <ddk/metadata/bad-block.h>
#include <ddk/metadata/nand.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/array.h>
#include <fbl/auto_lock.h>
#include <zircon/assert.h>
#include <zircon/driver/binding.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>

#include <utility>

namespace {

struct RamNandOp {
  nand_operation_t op;
  nand_queue_callback completion_cb;
  void* cookie;
  list_node_t node;
};

zx_status_t Unlink(void* ctx, fidl_txn_t* txn) {
  NandDevice* device = reinterpret_cast<NandDevice*>(ctx);
  zx_status_t status = device->Unlink();
  return fuchsia_hardware_nand_RamNandUnlink_reply(txn, status);
}

fuchsia_hardware_nand_RamNand_ops_t fidl_ops = {.Unlink = Unlink};

static_assert(ZBI_PARTITION_NAME_LEN == fuchsia_hardware_nand_NAME_LEN, "bad fidl name");
static_assert(ZBI_PARTITION_GUID_LEN == fuchsia_hardware_nand_GUID_LEN, "bad fidl guid");

uint32_t GetNumPartitions(const fuchsia_hardware_nand_RamNandInfo& info) {
  return fbl::min(info.partition_map.partition_count, fuchsia_hardware_nand_MAX_PARTITIONS);
}

void ExtractNandConfig(const fuchsia_hardware_nand_RamNandInfo& info, nand_config_t* config) {
  config->bad_block_config.type = kAmlogicUboot;

  uint32_t extra_count = 0;
  for (uint32_t i = 0; i < GetNumPartitions(info); i++) {
    const auto& partition = info.partition_map.partitions[i];
    if (partition.hidden && partition.bbt) {
      config->bad_block_config.aml_uboot.table_start_block = partition.first_block;
      config->bad_block_config.aml_uboot.table_end_block = partition.last_block;
    } else if (!partition.hidden) {
      if (partition.copy_count > 1) {
        nand_partition_config_t* extra = &config->extra_partition_config[extra_count];

        memcpy(extra->type_guid, partition.unique_guid, ZBI_PARTITION_GUID_LEN);
        extra->copy_count = partition.copy_count;
        extra->copy_byte_offset = partition.copy_byte_offset;
        extra_count++;
      }
    }
  }
  config->extra_partition_config_count = extra_count;
}

fbl::Array<char> ExtractPartitionMap(const fuchsia_hardware_nand_RamNandInfo& info) {
  uint32_t num_partitions = GetNumPartitions(info);
  uint32_t dest_partitions = num_partitions;
  for (uint32_t i = 0; i < num_partitions; i++) {
    if (info.partition_map.partitions[i].hidden) {
      dest_partitions--;
    }
  }

  size_t len = sizeof(zbi_partition_map_t) + sizeof(zbi_partition_t) * dest_partitions;
  fbl::Array<char> buffer(new char[len], len);
  memset(buffer.data(), 0, len);
  zbi_partition_map_t* map = reinterpret_cast<zbi_partition_map_t*>(buffer.data());

  map->block_count = info.nand_info.num_blocks;
  map->block_size = info.nand_info.page_size * info.nand_info.pages_per_block;
  map->partition_count = dest_partitions;
  memcpy(map->guid, info.partition_map.device_guid, sizeof(map->guid));

  zbi_partition_t* dest = map->partitions;
  for (uint32_t i = 0; i < num_partitions; i++) {
    const auto& src = info.partition_map.partitions[i];
    if (!src.hidden) {
      memcpy(dest->type_guid, src.type_guid, sizeof(dest->type_guid));
      memcpy(dest->uniq_guid, src.unique_guid, sizeof(dest->uniq_guid));
      dest->first_block = src.first_block;
      dest->last_block = src.last_block;
      memcpy(dest->name, src.name, sizeof(dest->name));
      dest++;
    }
  }
  return buffer;
}

}  // namespace

NandDevice::NandDevice(const NandParams& params, zx_device_t* parent)
    : DeviceType(parent), params_(params) {}

NandDevice::~NandDevice() {
  if (thread_created_) {
    Kill();
    sync_completion_signal(&wake_signal_);
    int result_code;
    thrd_join(worker_, &result_code);

    for (;;) {
      RamNandOp* nand_op = list_remove_head_type(&txn_list_, RamNandOp, node);
      if (!nand_op) {
        break;
      }
      nand_op->completion_cb(nand_op->cookie, ZX_ERR_BAD_STATE, &nand_op->op);
    }
  }

  if (mapped_addr_) {
    zx_vmar_unmap(zx_vmar_root_self(), mapped_addr_, DdkGetSize());
  }
  DdkRemoveDeprecated();
}

zx_status_t NandDevice::Bind(const fuchsia_hardware_nand_RamNandInfo& info) {
  char name[fuchsia_hardware_nand_NAME_LEN];
  zx_status_t status = Init(name, zx::vmo(info.vmo));
  if (status != ZX_OK) {
    return status;
  }

  zx_device_prop_t props[] = {
      {BIND_PROTOCOL, 0, ZX_PROTOCOL_NAND},
      {BIND_NAND_CLASS, 0, params_.nand_class},
  };

  status = DdkAdd(name, DEVICE_ADD_INVISIBLE, props, fbl::count_of(props));
  if (status != ZX_OK) {
    return status;
  }

  if (info.export_nand_config) {
    nand_config_t config = {};
    ExtractNandConfig(info, &config);
    status = DdkAddMetadata(DEVICE_METADATA_PRIVATE, &config, sizeof(config));
    if (status != ZX_OK) {
      return status;
    }
  }
  if (info.export_partition_map) {
    fbl::Array<char> map = ExtractPartitionMap(info);
    status = DdkAddMetadata(DEVICE_METADATA_PARTITION_MAP, map.data(), map.size());
    if (status != ZX_OK) {
      return status;
    }
  }

  DdkMakeVisible();
  return ZX_OK;
}

zx_status_t NandDevice::Init(char name[NAME_MAX], zx::vmo vmo) {
  ZX_DEBUG_ASSERT(!thread_created_);
  static uint64_t dev_count = 0;
  snprintf(name, NAME_MAX, "ram-nand-%" PRIu64, dev_count++);

  zx_status_t status;
  const bool use_vmo = vmo.is_valid();
  if (use_vmo) {
    vmo_ = std::move(vmo);

    uint64_t size;
    status = vmo_.get_size(&size);
    if (status != ZX_OK) {
      return status;
    }
    if (size < DdkGetSize()) {
      return ZX_ERR_INVALID_ARGS;
    }
  } else {
    status = zx::vmo::create(DdkGetSize(), 0, &vmo_);
    if (status != ZX_OK) {
      return status;
    }
  }

  status = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, vmo_.get(), 0,
                       DdkGetSize(), &mapped_addr_);
  if (status != ZX_OK) {
    return status;
  }
  if (!use_vmo) {
    memset(reinterpret_cast<char*>(mapped_addr_), 0xff, DdkGetSize());
  }

  list_initialize(&txn_list_);
  if (thrd_create(&worker_, WorkerThreadStub, this) != thrd_success) {
    return ZX_ERR_NO_RESOURCES;
  }
  thread_created_ = true;

  return ZX_OK;
}

void NandDevice::DdkUnbindDeprecated() {
  Kill();
  sync_completion_signal(&wake_signal_);
  DdkRemoveDeprecated();
}

zx_status_t NandDevice::DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn) {
  {
    fbl::AutoLock lock(&lock_);
    if (dead_) {
      return ZX_ERR_BAD_STATE;
    }
  }
  return fuchsia_hardware_nand_RamNand_dispatch(this, txn, msg, &fidl_ops);
}

zx_status_t NandDevice::Unlink() {
  DdkUnbindDeprecated();
  return ZX_OK;
}

void NandDevice::NandQuery(fuchsia_hardware_nand_Info* info_out, size_t* nand_op_size_out) {
  *info_out = params_;
  *nand_op_size_out = sizeof(RamNandOp);
}

void NandDevice::NandQueue(nand_operation_t* operation, nand_queue_callback completion_cb,
                           void* cookie) {
  uint32_t max_pages = params_.NumPages();
  switch (operation->command) {
    case NAND_OP_READ:
    case NAND_OP_WRITE: {
      if (operation->rw.offset_nand >= max_pages || !operation->rw.length ||
          (max_pages - operation->rw.offset_nand) < operation->rw.length) {
        completion_cb(cookie, ZX_ERR_OUT_OF_RANGE, operation);
        return;
      }
      if (operation->rw.data_vmo == ZX_HANDLE_INVALID &&
          operation->rw.oob_vmo == ZX_HANDLE_INVALID) {
        completion_cb(cookie, ZX_ERR_BAD_HANDLE, operation);
        return;
      }
      break;
    }
    case NAND_OP_ERASE:
      if (!operation->erase.num_blocks || operation->erase.first_block >= params_.num_blocks ||
          params_.num_blocks - operation->erase.first_block < operation->erase.num_blocks) {
        completion_cb(cookie, ZX_ERR_OUT_OF_RANGE, operation);
        return;
      }
      break;

    default:
      completion_cb(cookie, ZX_ERR_NOT_SUPPORTED, operation);
      return;
  }

  if (AddToList(operation, completion_cb, cookie)) {
    sync_completion_signal(&wake_signal_);
  } else {
    completion_cb(cookie, ZX_ERR_BAD_STATE, operation);
  }
}

zx_status_t NandDevice::NandGetFactoryBadBlockList(uint32_t* bad_blocks, size_t bad_block_len,
                                                   size_t* num_bad_blocks) {
  *num_bad_blocks = 0;
  return ZX_OK;
}

void NandDevice::Kill() {
  fbl::AutoLock lock(&lock_);
  dead_ = true;
}

bool NandDevice::AddToList(nand_operation_t* operation, nand_queue_callback completion_cb,
                           void* cookie) {
  fbl::AutoLock lock(&lock_);
  bool is_dead = dead_;
  if (!dead_) {
    RamNandOp* nand_op = reinterpret_cast<RamNandOp*>(operation);
    nand_op->completion_cb = completion_cb;
    nand_op->cookie = cookie;
    list_add_tail(&txn_list_, &nand_op->node);
  }
  return !is_dead;
}

bool NandDevice::RemoveFromList(nand_operation_t** operation) {
  fbl::AutoLock lock(&lock_);
  bool is_dead = dead_;
  if (!dead_) {
    RamNandOp* nand_op = list_remove_head_type(&txn_list_, RamNandOp, node);
    *operation = reinterpret_cast<nand_operation_t*>(nand_op);
  }
  return !is_dead;
}

int NandDevice::WorkerThread() {
  for (;;) {
    nand_operation_t* operation;
    for (;;) {
      if (!RemoveFromList(&operation)) {
        return 0;
      }
      if (operation) {
        sync_completion_reset(&wake_signal_);
        break;
      } else {
        sync_completion_wait(&wake_signal_, ZX_TIME_INFINITE);
      }
    }

    zx_status_t status = ZX_OK;

    switch (operation->command) {
      case NAND_OP_READ:
      case NAND_OP_WRITE:
        status = ReadWriteData(operation);
        if (status == ZX_OK) {
          status = ReadWriteOob(operation);
        }
        break;

      case NAND_OP_ERASE: {
        status = Erase(operation);
        break;
      }
      default:
        ZX_DEBUG_ASSERT(false);  // Unexpected.
    }

    auto* op = reinterpret_cast<RamNandOp*>(operation);
    op->completion_cb(op->cookie, status, operation);
  }
}

int NandDevice::WorkerThreadStub(void* arg) {
  NandDevice* device = static_cast<NandDevice*>(arg);
  return device->WorkerThread();
}

zx_status_t NandDevice::ReadWriteData(nand_operation_t* operation) {
  if (operation->rw.data_vmo == ZX_HANDLE_INVALID) {
    return ZX_OK;
  }

  uint32_t nand_addr = operation->rw.offset_nand * params_.page_size;
  uint64_t vmo_addr = operation->rw.offset_data_vmo * params_.page_size;
  uint32_t length = operation->rw.length * params_.page_size;
  void* addr = reinterpret_cast<char*>(mapped_addr_) + nand_addr;

  if (operation->command == NAND_OP_READ) {
    operation->rw.corrected_bit_flips = 0;
    return zx_vmo_write(operation->rw.data_vmo, addr, vmo_addr, length);
  }

  ZX_DEBUG_ASSERT(operation->command == NAND_OP_WRITE);

  // Likely something bad is going on if writing multiple blocks.
  ZX_DEBUG_ASSERT_MSG(operation->rw.length <= params_.pages_per_block, "Writing multiple blocks");
  ZX_DEBUG_ASSERT_MSG(
      operation->rw.offset_nand / params_.pages_per_block ==
          (operation->rw.offset_nand + operation->rw.length - 1) / params_.pages_per_block,
      "Writing multiple blocks");

  return zx_vmo_read(operation->rw.data_vmo, addr, vmo_addr, length);
}

zx_status_t NandDevice::ReadWriteOob(nand_operation_t* operation) {
  if (operation->rw.oob_vmo == ZX_HANDLE_INVALID) {
    return ZX_OK;
  }

  uint32_t nand_addr = MainDataSize() + operation->rw.offset_nand * params_.oob_size;
  uint64_t vmo_addr = operation->rw.offset_oob_vmo * params_.page_size;
  uint32_t length = operation->rw.length * params_.oob_size;
  void* addr = reinterpret_cast<char*>(mapped_addr_) + nand_addr;

  if (operation->command == NAND_OP_READ) {
    operation->rw.corrected_bit_flips = 0;
    return zx_vmo_write(operation->rw.oob_vmo, addr, vmo_addr, length);
  }

  ZX_DEBUG_ASSERT(operation->command == NAND_OP_WRITE);
  return zx_vmo_read(operation->rw.oob_vmo, addr, vmo_addr, length);
}

zx_status_t NandDevice::Erase(nand_operation_t* operation) {
  ZX_DEBUG_ASSERT(operation->command == NAND_OP_ERASE);

  uint32_t block_size = params_.page_size * params_.pages_per_block;
  uint32_t nand_addr = operation->erase.first_block * block_size;
  uint32_t length = operation->erase.num_blocks * block_size;
  void* addr = reinterpret_cast<char*>(mapped_addr_) + nand_addr;

  memset(addr, 0xff, length);

  // Clear the OOB area:
  uint32_t oob_per_block = params_.oob_size * params_.pages_per_block;
  length = operation->erase.num_blocks * oob_per_block;
  nand_addr = MainDataSize() + operation->erase.first_block * oob_per_block;
  addr = reinterpret_cast<char*>(mapped_addr_) + nand_addr;

  memset(addr, 0xff, length);

  return ZX_OK;
}
