// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
extern "C" {
#include "mboxd.h"
}

#include "config.h"

#include "pnor_partition.hpp"
#include "pnor_partition_table.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

#include <assert.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <syslog.h>
#include <unistd.h>

#include <exception>
#include <iostream>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <stdexcept>
#include <string>

#include "common.h"
#include "vpnor/backend.h"

namespace openpower
{
namespace virtual_pnor
{

namespace fs = std::experimental::filesystem;

fs::path Request::getPartitionFilePath(int flags)
{
    struct vpnor_data* priv = (struct vpnor_data*)backend->priv;

    // Check if partition exists in patch location
    auto dst = fs::path(priv->paths.patch_loc) / partition.data.name;
    if (fs::is_regular_file(dst))
    {
        return dst;
    }

    switch (partition.data.user.data[1] &
            (PARTITION_PRESERVED | PARTITION_READONLY))
    {
        case PARTITION_PRESERVED:
            dst = priv->paths.prsv_loc;
            break;

        case PARTITION_READONLY:
            dst = priv->paths.ro_loc;
            break;

        default:
            dst = priv->paths.rw_loc;
    }
    dst /= partition.data.name;

    if (fs::exists(dst))
    {
        return dst;
    }

    if (flags == O_RDONLY)
    {
        dst = fs::path(priv->paths.ro_loc) / partition.data.name;
        assert(fs::exists(dst));
        return dst;
    }

    assert(flags == O_RDWR);
    auto src = fs::path(priv->paths.ro_loc) / partition.data.name;
    assert(fs::exists(src));

    MSG_DBG("RWRequest: Didn't find '%s' under '%s', copying from '%s'\n",
            partition.data.name, dst.c_str(), src.c_str());

    dst = priv->paths.rw_loc;
    if (partition.data.user.data[1] & PARTITION_PRESERVED)
    {
        dst = priv->paths.prsv_loc;
    }

    dst /= partition.data.name;
    fs::copy_file(src, dst);

    return dst;
}

size_t Request::clamp(size_t len)
{
    size_t maxAccess = offset + len;
    size_t partSize = partition.data.size << backend->block_size_shift;
    return std::min(maxAccess, partSize) - offset;
}

void Request::resize(const fs::path& path, size_t len)
{
    size_t maxAccess = offset + len;
    size_t fileSize = fs::file_size(path);
    if (maxAccess < fileSize)
    {
        return;
    }
    MSG_DBG("Resizing %s to %zu bytes\n", path.c_str(), maxAccess);
    int rc = truncate(path.c_str(), maxAccess);
    if (rc == -1)
    {
        MSG_ERR("Failed to resize %s: %d\n", path.c_str(), errno);
        throw std::system_error(errno, std::system_category());
    }
}

size_t Request::fulfil(const fs::path& path, int flags, void* buf, size_t len)
{
    if (!(flags == O_RDONLY || flags == O_RDWR))
    {
        std::stringstream err;
        err << "Require O_RDONLY (0x" << std::hex << O_RDONLY << " or O_RDWR "
            << std::hex << O_RDWR << " for flags, got: 0x" << std::hex << flags;
        throw std::invalid_argument(err.str());
    }

    int fd = ::open(path.c_str(), flags);
    if (fd == -1)
    {
        MSG_ERR("Failed to open backing file at '%s': %d\n", path.c_str(),
                errno);
        throw std::system_error(errno, std::system_category());
    }

    if (flags == O_RDONLY)
    {
        MSG_INFO("Fulfilling read request against %s at offset 0x%zx into %p "
                 "for %zu\n",
                 path.c_str(), offset, buf, len);
    }
    else
    {
        MSG_INFO("Fulfilling write request against %s at offset 0x%zx from %p "
                 "for %zu\n",
                 path.c_str(), offset, buf, len);
    }

    size_t fileSize = fs::file_size(path);
    int mprot = PROT_READ | ((flags == O_RDWR) ? PROT_WRITE : 0);
    auto map = mmap(NULL, fileSize, mprot, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED)
    {
        close(fd);
        MSG_ERR("Failed to map backing file '%s' for %zd bytes: %d\n",
                path.c_str(), fileSize, errno);
        throw std::system_error(errno, std::system_category());
    }

    // copy to the reserved memory area
    if (flags == O_RDONLY)
    {
        memset(buf, 0xff, len);
        memcpy(buf, (char*)map + offset, std::min(len, fileSize));
    }
    else
    {
        memcpy((char*)map + offset, buf, len);
        backend_set_bytemap(backend, base + offset, len, FLASH_DIRTY);
    }
    munmap(map, fileSize);
    close(fd);

    return len;
}

} // namespace virtual_pnor
} // namespace openpower
