// 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 <fcntl.h>
#include <new>
#include <stdio.h>
#include <stdlib.h>

#include <fbl/algorithm.h>
#include <fbl/unique_fd.h>
#include <fuchsia/nand/c/fidl.h>
#include <lib/fdio/watcher.h>
#include <lib/fzl/fdio.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/zx/vmo.h>
#include <unittest/unittest.h>
#include <zircon/device/device.h>
#include <zircon/syscalls.h>

#include "parent.h"

namespace {

constexpr uint32_t kMinOobSize = 4;
constexpr uint32_t kMinBlockSize = 4;
constexpr uint32_t kMinNumBlocks = 5;
constexpr uint32_t kInMemoryPages = 20;

fbl::unique_fd OpenBroker(const char* path) {
    fbl::unique_fd broker;

    auto callback = [](int dir_fd, int event, const char* filename, void* cookie) {
        if (event != WATCH_EVENT_ADD_FILE || strcmp(filename, "broker") != 0) {
            return ZX_OK;
        }
        fbl::unique_fd* broker = reinterpret_cast<fbl::unique_fd*>(cookie);
        broker->reset(openat(dir_fd, filename, O_RDWR));
        return ZX_ERR_STOP;
    };

    fbl::unique_fd dir(open(path, O_DIRECTORY));
    if (dir) {
        zx_time_t deadline = zx_deadline_after(ZX_SEC(5));
        fdio_watch_directory(dir.get(), callback, deadline, &broker);
    }
    return broker;
}

// The device under test.
class NandDevice {
public:
    NandDevice();
    ~NandDevice() {
        if (linked_) {
            fbl::unique_fd broker = caller_.release();
            ioctl_device_unbind(broker.get());
        }
    }

    bool IsValid() const { return is_valid_; }

    // Provides a channel to issue fidl calls.
    zx_handle_t channel() { return caller_.borrow_channel(); }

    // Wrappers for "queue" operations that take care of preserving the vmo's handle
    // and translating the request to the desired block range on the actual device.
    bool Read(const zx::vmo& vmo, const fuchsia_nand_BrokerRequest& request,
              zx_status_t* response = nullptr);
    bool Write(const zx::vmo& vmo, const fuchsia_nand_BrokerRequest& request,
               zx_status_t* response = nullptr);
    bool Erase(const fuchsia_nand_BrokerRequest& request, zx_status_t* response = nullptr);

    // Erases a given block number.
    bool EraseBlock(uint32_t block_num);

    // Verifies that the buffer pointed to by the operation's vmo contains the given
    // pattern for the desired number of pages, skipping the pages before start.
    bool CheckPattern(uint8_t expected, int start, int num_pages, const void* memory);

    const fuchsia_hardware_nand_Info& Info() const { return parent_->Info(); }

    uint32_t PageSize() const { return parent_->Info().page_size; }
    uint32_t OobSize() const { return parent_->Info().oob_size; }
    uint32_t BlockSize() const { return parent_->Info().pages_per_block; }
    uint32_t NumBlocks() const { return num_blocks_; }
    uint32_t NumPages() const { return num_blocks_ * BlockSize(); }
    uint32_t MaxBufferSize() const { return kInMemoryPages * (PageSize() + OobSize()); }

    // True when the whole device under test can be modified.
    bool IsFullDevice() const { return full_device_; }

private:
    bool ValidateNandDevice();

    ParentDevice* parent_ = g_parent_device_;
    fzl::FdioCaller caller_;
    uint32_t num_blocks_ = 0;
    uint32_t first_block_ = 0;
    bool full_device_ = true;
    bool linked_ = false;
    bool is_valid_ = false;
};

NandDevice::NandDevice() {
    ZX_ASSERT(parent_->IsValid());
    if (parent_->IsBroker()) {
        caller_.reset(fbl::unique_fd(open(parent_->Path(), O_RDWR)));
    } else {
        const char kBroker[] = "/boot/driver/nand-broker.so";
        if (ioctl_device_bind(parent_->get(), kBroker, sizeof(kBroker) - 1) < 0) {
            unittest_printf_critical("Failed to bind broker\n");
            return;
        }
        linked_ = true;
        caller_.reset(OpenBroker(parent_->Path()));
    }
    is_valid_ = ValidateNandDevice();
}

bool NandDevice::Read(const zx::vmo& vmo, const fuchsia_nand_BrokerRequest& request,
                      zx_status_t* response) {
    BEGIN_TEST;
    fuchsia_nand_BrokerRequest request_copy = request;
    if (!full_device_) {
        request_copy.offset_nand = request.offset_nand + first_block_ * BlockSize();
        ZX_DEBUG_ASSERT(request.offset_nand < NumPages());
        ZX_DEBUG_ASSERT(request.offset_nand + request.length <= NumPages());
    }

    uint32_t bit_flips;
    zx_status_t status;
    zx::vmo dup;
    ASSERT_EQ(ZX_OK, vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
    request_copy.vmo = dup.release();
    ASSERT_EQ(ZX_OK, fuchsia_nand_BrokerRead(channel(), &request_copy, &status, &bit_flips));
    if (response) {
        *response = status;
    } else {
        ASSERT_EQ(ZX_OK, status);
    }
    ASSERT_EQ(0, bit_flips);
    END_TEST;
}

bool NandDevice::Write(const zx::vmo& vmo, const fuchsia_nand_BrokerRequest& request,
                       zx_status_t* response) {
    BEGIN_TEST;
    fuchsia_nand_BrokerRequest request_copy = request;
    if (!full_device_) {
        request_copy.offset_nand = request.offset_nand + first_block_ * BlockSize();
        ZX_DEBUG_ASSERT(request.offset_nand < NumPages());
        ZX_DEBUG_ASSERT(request.offset_nand + request.length <= NumPages());
    }

    zx_status_t status;
    zx::vmo dup;
    ASSERT_EQ(ZX_OK, vmo.duplicate(ZX_RIGHT_SAME_RIGHTS, &dup));
    request_copy.vmo = dup.release();
    ASSERT_EQ(ZX_OK, fuchsia_nand_BrokerWrite(channel(), &request_copy, &status));
    if (response) {
        *response = status;
    } else {
        ASSERT_EQ(ZX_OK, status);
    }
    END_TEST;
}

bool NandDevice::Erase(const fuchsia_nand_BrokerRequest& request, zx_status_t* response) {
    BEGIN_TEST;
    fuchsia_nand_BrokerRequest request_copy = request;
    if (!full_device_) {
        request_copy.offset_nand = request.offset_nand + first_block_;
        ZX_DEBUG_ASSERT(request.offset_nand < NumBlocks());
        ZX_DEBUG_ASSERT(request.offset_nand + request.length <= NumBlocks());
    }

    zx_status_t status;
    ASSERT_EQ(ZX_OK, fuchsia_nand_BrokerErase(channel(), &request_copy, &status));
    if (response) {
        *response = status;
    } else {
        ASSERT_EQ(ZX_OK, status);
    }
    END_TEST;
}

bool NandDevice::EraseBlock(uint32_t block_num) {
    BEGIN_TEST;
    fuchsia_nand_BrokerRequest request = {};
    request.length = 1;
    request.offset_nand = block_num;
    ASSERT_TRUE(Erase(request));
    END_TEST;
}

bool NandDevice::CheckPattern(uint8_t expected, int start, int num_pages, const void* memory) {
    const uint8_t* buffer = reinterpret_cast<const uint8_t*>(memory) + PageSize() * start;
    for (uint32_t i = 0; i < PageSize() * num_pages; i++) {
        if (buffer[i] != expected) {
            return false;
        }
    }
    return true;
}

bool NandDevice::ValidateNandDevice() {
    if (parent_->IsExternal()) {
        // This looks like using code under test to setup the test, but this
        // path is for external devices, not really the broker. The issue is that
        // ParentDevice cannot query a nand device for the actual parameters.
        fuchsia_hardware_nand_Info info;
        zx_status_t status;
        if (fuchsia_nand_BrokerGetInfo(channel(), &status, &info) != ZX_OK || status != ZX_OK) {
            printf("Failed to query nand device\n");
            return false;
        }
        parent_->SetInfo(info);
    }

    num_blocks_ = parent_->NumBlocks();
    first_block_ = parent_->FirstBlock();
    if (OobSize() < kMinOobSize || BlockSize() < kMinBlockSize || num_blocks_ < kMinNumBlocks ||
        num_blocks_ + first_block_ > parent_->Info().num_blocks) {
        printf("Invalid nand device parameters\n");
        return false;
    }
    if (num_blocks_ != parent_->Info().num_blocks) {
        // Not using the whole device, don't need to test all limits.
        num_blocks_ = fbl::min(num_blocks_, kMinNumBlocks);
        full_device_ = false;
    }
    return true;
}

bool TrivialLifetimeTest() {
    BEGIN_TEST;
    NandDevice device;

    ASSERT_TRUE(device.IsValid());
    END_TEST;
}

bool QueryTest() {
    BEGIN_TEST;
    NandDevice device;
    ASSERT_TRUE(device.IsValid());

    fuchsia_hardware_nand_Info info;
    zx_status_t status;
    ASSERT_EQ(ZX_OK, fuchsia_nand_BrokerGetInfo(device.channel(), &status, &info));
    ASSERT_EQ(ZX_OK, status);

    EXPECT_EQ(device.Info().page_size, info.page_size);
    EXPECT_EQ(device.Info().oob_size, info.oob_size);
    EXPECT_EQ(device.Info().pages_per_block, info.pages_per_block);
    EXPECT_EQ(device.Info().num_blocks, info.num_blocks);
    EXPECT_EQ(device.Info().ecc_bits, info.ecc_bits);
    EXPECT_EQ(device.Info().nand_class, info.nand_class);

    END_TEST;
}

bool ReadWriteLimitsTest() {
    BEGIN_TEST;
    NandDevice device;
    ASSERT_TRUE(device.IsValid());

    fzl::VmoMapper mapper;
    zx::vmo vmo;
    ASSERT_EQ(ZX_OK, mapper.CreateAndMap(device.MaxBufferSize(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                                         nullptr, &vmo));

    fuchsia_nand_BrokerRequest request = {};
    zx_status_t status;
    ASSERT_TRUE(device.Read(vmo, request, &status));
    EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);

    ASSERT_TRUE(device.Write(vmo, request, &status));
    EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);

    if (device.IsFullDevice()) {
        request.length = 1;
        request.offset_nand = device.NumPages();

        ASSERT_TRUE(device.Read(vmo, request, &status));
        EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);

        ASSERT_TRUE(device.Write(vmo, request, &status));
        EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);

        request.length = 2;
        request.offset_nand = device.NumPages() - 1;

        ASSERT_TRUE(device.Read(vmo, request, &status));
        EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);

        ASSERT_TRUE(device.Write(vmo, request, &status));
        EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);
    }

    request.length = 1;
    request.offset_nand = device.NumPages() - 1;

    ASSERT_TRUE(device.Read(vmo, request, &status));
    EXPECT_EQ(ZX_ERR_BAD_HANDLE, status);

    ASSERT_TRUE(device.Write(vmo, request, &status));
    EXPECT_EQ(ZX_ERR_BAD_HANDLE, status);

    request.data_vmo = true;

    ASSERT_TRUE(device.Read(vmo, request, &status));
    EXPECT_EQ(ZX_OK, status);

    ASSERT_TRUE(device.Write(vmo, request, &status));
    EXPECT_EQ(ZX_OK, status);

    END_TEST;
}

bool EraseLimitsTest() {
    return true;
    BEGIN_TEST;
    NandDevice device;
    ASSERT_TRUE(device.IsValid());

    fuchsia_nand_BrokerRequest request = {};
    zx_status_t status;
    ASSERT_TRUE(device.Erase(request, &status));
    EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);

    request.offset_nand = device.NumBlocks();

    if (device.IsFullDevice()) {
        request.length = 1;
        ASSERT_TRUE(device.Erase(request, &status));
        EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);

        request.length = 2;
        request.offset_nand = device.NumBlocks() - 1;
        ASSERT_TRUE(device.Erase(request, &status));
        EXPECT_EQ(ZX_ERR_OUT_OF_RANGE, status);
    }

    request.length = 1;
    request.offset_nand = device.NumBlocks() - 1;
    ASSERT_TRUE(device.Erase(request, &status));
    EXPECT_EQ(ZX_OK, status);

    END_TEST;
}

bool ReadWriteTest() {
    BEGIN_TEST;
    NandDevice device;
    ASSERT_TRUE(device.IsValid());
    ASSERT_TRUE(device.EraseBlock(0));

    fzl::VmoMapper mapper;
    zx::vmo vmo;
    ASSERT_EQ(ZX_OK, mapper.CreateAndMap(device.MaxBufferSize(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                                         nullptr, &vmo));
    memset(mapper.start(), 0x55, mapper.size());

    fuchsia_nand_BrokerRequest request = {};
    request.length = 4;
    request.offset_nand = 4;
    request.data_vmo = true;

    ASSERT_TRUE(device.Write(vmo, request));

    memset(mapper.start(), 0, mapper.size());

    ASSERT_TRUE(device.Read(vmo, request));
    ASSERT_TRUE(device.CheckPattern(0x55, 0, 4, mapper.start()));

    END_TEST;
}

bool ReadWriteOobTest() {
    BEGIN_TEST;
    NandDevice device;
    ASSERT_TRUE(device.IsValid());
    ASSERT_TRUE(device.EraseBlock(0));

    fzl::VmoMapper mapper;
    zx::vmo vmo;
    ASSERT_EQ(ZX_OK, mapper.CreateAndMap(device.MaxBufferSize(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                                         nullptr, &vmo));
    const char desired[] = {'a', 'b', 'c', 'd'};
    memcpy(mapper.start(), desired, sizeof(desired));

    fuchsia_nand_BrokerRequest request = {};
    request.length = 1;
    request.offset_nand = 2;
    request.oob_vmo = true;

    ASSERT_TRUE(device.Write(vmo, request));

    request.length = 2;
    request.offset_nand = 1;
    memset(mapper.start(), 0, device.OobSize() * 2);

    ASSERT_TRUE(device.Read(vmo, request));

    // The "second page" has the data of interest.
    ASSERT_EQ(0,
              memcmp(reinterpret_cast<char*>(mapper.start()) + device.OobSize(), desired,
                     sizeof(desired)));

    END_TEST;
}

bool ReadWriteDataAndOobTest() {
    BEGIN_TEST;
    NandDevice device;
    ASSERT_TRUE(device.IsValid());
    ASSERT_TRUE(device.EraseBlock(0));

    fzl::VmoMapper mapper;
    zx::vmo vmo;
    ASSERT_EQ(ZX_OK, mapper.CreateAndMap(device.MaxBufferSize(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                                         nullptr, &vmo));

    char* buffer = reinterpret_cast<char*>(mapper.start());
    memset(buffer, 0x55, device.PageSize() * 2);
    memset(buffer + device.PageSize() * 2, 0xaa, device.OobSize() * 2);

    fuchsia_nand_BrokerRequest request = {};
    request.length = 2;
    request.offset_nand = 2;
    request.offset_oob_vmo = 2; // OOB is right after data.
    request.data_vmo = true;
    request.oob_vmo = true;

    ASSERT_TRUE(device.Write(vmo, request));

    memset(buffer, 0, device.PageSize() * 4);

    ASSERT_TRUE(device.Read(vmo, request));

    // Verify data.
    ASSERT_TRUE(device.CheckPattern(0x55, 0, 2, buffer));

    // Verify OOB.
    memset(buffer, 0xaa, device.PageSize());
    ASSERT_EQ(0, memcmp(buffer + device.PageSize() * 2, buffer, device.OobSize() * 2));

    END_TEST;
}

bool EraseTest() {
    BEGIN_TEST;
    NandDevice device;
    ASSERT_TRUE(device.IsValid());

    fzl::VmoMapper mapper;
    zx::vmo vmo;
    ASSERT_EQ(ZX_OK, mapper.CreateAndMap(device.MaxBufferSize(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                                         nullptr, &vmo));

    memset(mapper.start(), 0x55, mapper.size());

    fuchsia_nand_BrokerRequest request = {};
    request.length = kMinBlockSize;
    request.data_vmo = true;
    request.offset_nand = device.BlockSize();
    ASSERT_TRUE(device.Write(vmo, request));

    request.offset_nand = device.BlockSize() * 2;
    ASSERT_TRUE(device.Write(vmo, request));

    ASSERT_TRUE(device.EraseBlock(1));
    ASSERT_TRUE(device.EraseBlock(2));

    ASSERT_TRUE(device.Read(vmo, request));
    ASSERT_TRUE(device.CheckPattern(0xff, 0, kMinBlockSize, mapper.start()));

    request.offset_nand = device.BlockSize();
    ASSERT_TRUE(device.Read(vmo, request));
    ASSERT_TRUE(device.CheckPattern(0xff, 0, kMinBlockSize, mapper.start()));

    END_TEST;
}

} // namespace

BEGIN_TEST_CASE(NandBrokerTests)
RUN_TEST_SMALL(TrivialLifetimeTest)
RUN_TEST_SMALL(QueryTest)
RUN_TEST_SMALL(ReadWriteLimitsTest)
RUN_TEST_SMALL(EraseLimitsTest)
RUN_TEST_SMALL(ReadWriteTest)
RUN_TEST_SMALL(ReadWriteOobTest)
RUN_TEST_SMALL(ReadWriteDataAndOobTest)
RUN_TEST_SMALL(EraseTest)
END_TEST_CASE(NandBrokerTests)
