// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2018 IBM Corp.
#include "pnor_partition.hpp"
#include "pnor_partition_table.hpp"
#include "config.h"
#include "mboxd_flash.h"
#include "mboxd_pnor_partition_table.h"
#include "xyz/openbmc_project/Common/error.hpp"
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog-errors.hpp>

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

#include "common.h"

#include <string>
#include <exception>
#include <stdexcept>
#include <iostream>

namespace openpower
{
namespace virtual_pnor
{

namespace fs = std::experimental::filesystem;

fs::path Request::getPartitionFilePath(int flags)
{
    // Check if partition exists in patch location
    auto dst = fs::path(ctx->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 = ctx->paths.prsv_loc;
            break;

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

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

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

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

    assert(flags == O_RDWR);
    auto src = fs::path(ctx->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 = ctx->paths.rw_loc;
    if (partition.data.user.data[1] & PARTITION_PRESERVED)
    {
        dst = ctx->paths.prsv_loc;
    }

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

    return dst;
}

ssize_t Request::fulfil(void *buf, size_t len, int flags)
{
    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());
    }

    fs::path path = getPartitionFilePath(flags);

    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());
    }

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

    // copy to the reserved memory area
    if (flags == O_RDONLY)
    {
        len = std::min(partition.data.actual - offset, len);
        memcpy(buf, (char *)map + offset, len);
    }
    else
    {
        // if the asked offset + no of bytes to read is greater
        // then size of the partition file then throw error.
        //
        // FIXME: Don't use .actual, use  (.size << ctx->block_size_shift),
        // otherwise we can't grow the size of the data to fill the partition
        if ((base + offset + len) > (base + partition.data.actual))
        {
            munmap(map, partition.data.actual);
            close(fd);

            /* FIXME: offset calculation */
            std::stringstream err;
            err << "Request size 0x" << std::hex << len << " from offset 0x"
                << std::hex << offset << " exceeds the partition size 0x"
                << std::hex << partition.data.actual;
            throw OutOfBoundsOffset(err.str());
        }
        memcpy((char *)map + offset, buf, len);
        set_flash_bytemap(ctx, base + offset, len, FLASH_DIRTY);
    }
    munmap(map, partition.data.actual);
    close(fd);

    return len;
}

} // namespace virtual_pnor
} // namespace openpower
