/*
 * Mailbox Daemon Implementation
 *
 * Copyright 2018 IBM
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include "pnor_partition.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 <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
{

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using namespace std::string_literals;

ReturnCode Request::open(const std::string& path, int mode)
{
    if (mode == O_RDWR && partition->data.user.data[1] & PARTITION_READONLY)
    {
        MSG_ERR("Can't open RO partition '%s' for write\n", path.c_str());
        return ReturnCode::PARTITION_READ_ONLY;
    }

    fs::path partitionFilePath = path;

    if (!fs::exists(partitionFilePath))
    {
        return ReturnCode::FILE_NOT_FOUND;
    }

    auto descriptor = ::open(partitionFilePath.c_str(), mode);
    if (descriptor < 0)
    {
        return ReturnCode::FILE_OPEN_FAILURE;
    }

    fd.set(descriptor);
    descriptor = -1;

    return ReturnCode::SUCCESS;
}

std::string Request::getPartitionFilePath(struct mbox_context* context,
                                          uint32_t offset)
{
    partition = vpnor_get_partition(context, offset);
    if (!partition)
    {
        MSG_ERR("Couldn't get the partition info for offset 0x%" PRIx32 "\n",
                offset);
        elog<InternalFailure>();
    }

    fs::path partitionFilePath;

    // Check if partition exists in patch location
    partitionFilePath = context->paths.patch_loc;
    partitionFilePath /= partition->data.name;
    if (fs::is_regular_file(partitionFilePath))
    {
        return partitionFilePath.string();
    }

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

        case PARTITION_READONLY:
            partitionFilePath = context->paths.ro_loc;
            break;

        default:
            partitionFilePath = context->paths.rw_loc;
    }
    partitionFilePath /= partition->data.name;
    return partitionFilePath.string();
}

const pnor_partition* RORequest::getPartitionInfo(struct mbox_context* context,
                                                  uint32_t offset)
{
    std::string path = getPartitionFilePath(context, offset);
    ReturnCode rc = Request::open(path, O_RDONLY);
    if (rc == ReturnCode::SUCCESS)
    {
        return partition;
    }
    // not interested in any other error except FILE_NOT_FOUND
    if (rc != ReturnCode::FILE_NOT_FOUND)
    {
        MSG_ERR(
            "RORequest: Error opening partition file '%s' (offset 0x%" PRIx32
            "): %u\n",
            path.c_str(), offset, static_cast<uint8_t>(rc));
        elog<InternalFailure>();
    }

    // if the offset lies in read only partition then throw error.
    if (partition->data.user.data[1] & PARTITION_READONLY)
    {
        MSG_ERR("RORequest: Requested offset 0x%" PRIx32
                " is in a read-only partition (%s)\n",
                offset, path.c_str());
        elog<InternalFailure>();
    }

    // we don't get the file in the respective partition(RW/PSRV)
    // try to open it from RO location.

    fs::path partitionFilePath = context->paths.ro_loc;
    partitionFilePath /= partition->data.name;

    rc = Request::open(partitionFilePath, O_RDONLY);
    if (rc != ReturnCode::SUCCESS)
    {
        MSG_ERR("RORequest: Failed to open partition file '%s' at RO fallback "
                "(offset 0x%" PRIx32 "): %u\n",
                partitionFilePath.c_str(), offset, static_cast<uint8_t>(rc));
        elog<InternalFailure>();
    }

    return partition;
}

const pnor_partition* RWRequest::getPartitionInfo(struct mbox_context* context,
                                                  uint32_t offset)
{
    std::string path = getPartitionFilePath(context, offset);
    std::error_code ec;

    ReturnCode rc = Request::open(path, O_RDWR);
    if (rc == ReturnCode::SUCCESS)
    {
        return partition;
    }
    // not interested in any other error except FILE_NOT_FOUND
    if (rc != ReturnCode::FILE_NOT_FOUND)
    {
        MSG_ERR(
            "RWRequest: Error opening partition file '%s' (offset 0x%" PRIx32
            "): %d\n",
            path.c_str(), offset, static_cast<uint8_t>(rc));
        elog<InternalFailure>();
    }

    // if the file is not available in the respective(RW/PSRV) partition
    // then copy the file from RO to the respective(RW/PSRV) partition
    // and open it for writing.

    fs::path fromPath = context->paths.ro_loc;
    fromPath /= partition->data.name;
    if (!fs::exists(fromPath))
    {
        MSG_ERR("RWRequest: Partition '%s' for offset 0x%" PRIx32
                " not found in RO directory '%s'\n",
                partition->data.name, offset, context->paths.ro_loc);
        elog<InternalFailure>();
    }
    // copy the file from ro to respective partition
    fs::path toPath = context->paths.rw_loc;

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

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

    toPath /= partition->data.name;
    if (!fs::copy_file(fromPath, toPath, ec))
    {
        MSG_ERR("RWRequest: Failed to copy file from '%s' to '%s': %d\n",
                fromPath.c_str(), toPath.c_str(), ec.value());
        elog<InternalFailure>();
    }

    rc = Request::open(toPath.c_str(), O_RDWR);

    if (rc != ReturnCode::SUCCESS)
    {
        MSG_ERR("RWRequest: Failed to open file at '%s': %d\n", toPath.c_str(),
                static_cast<uint8_t>(rc));
        elog<InternalFailure>();
    }

    return partition;
}

} // namespace virtual_pnor
} // namespace openpower
