// Copyright 2022 Google LLC
//
// 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 "handler.hpp"

#include "bm_config.h"

#include "bmc_mode_enum.hpp"
#include "errors.hpp"
#include "handler_impl.hpp"
#include "util.hpp"

#include <fcntl.h>
#include <ipmid/api.h>
#include <mtd/mtd-abi.h>
#include <mtd/mtd-user.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <nlohmann/json.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

#include <cinttypes>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <map>
#include <sstream>
#include <string>
#include <string_view>
#include <tuple>
#include <variant>

#ifndef NCSI_IF_NAME
#define NCSI_IF_NAME eth0
#endif

// To deal with receiving a string without quotes.
#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)
#define NCSI_IF_NAME_STR STR(NCSI_IF_NAME)

namespace ipmi
{
std::uint8_t getChannelByName(const std::string& chName);
}

namespace google
{
namespace ipmi
{
using Json = nlohmann::json;
using namespace phosphor::logging;
using InternalFailure =
    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;

uint8_t isBmcInBareMetalMode(const std::unique_ptr<FileSystemInterface>& fs)
{
#if BARE_METAL
    return static_cast<uint8_t>(BmcMode::BM_MODE);
#else
    std::error_code ec;

    if (fs->exists(bmDriveCleaningDoneAckFlagPath, ec))
    {
        std::fprintf(
            stderr,
            "%s exists so we acked cleaning done and must be in BM mode\n",
            bmDriveCleaningDoneAckFlagPath);
        return static_cast<uint8_t>(BmcMode::BM_MODE);
    }

    if (fs->exists(bmDriveCleaningDoneFlagPath, ec))
    {
        fs->rename(bmDriveCleaningDoneFlagPath, bmDriveCleaningDoneAckFlagPath,
                   ec);
        std::fprintf(
            stderr,
            "%s exists so we just finished cleaning and must be in BM mode\n",
            bmDriveCleaningDoneFlagPath);
        return static_cast<uint8_t>(BmcMode::BM_MODE);
    }

    if (fs->exists(BM_SIGNAL_PATH, ec))
    {
        if (!fs->exists(bmDriveCleaningFlagPath, ec))
        {
            fs->create(bmDriveCleaningFlagPath);
        }

        std::fprintf(
            stderr,
            "%s exists and no done/ack flag, we must be in BM cleaning mode\n",
            BM_SIGNAL_PATH);
        return static_cast<uint8_t>(BmcMode::BM_CLEANING_MODE);
    }

    std::fprintf(
        stderr,
        "Unable to find any BM state files so we must not be in BM mode\n");
    return static_cast<uint8_t>(BmcMode::NON_BM_MODE);
#endif
}

uint8_t Handler::getBmcMode()
{
    // BM_CLEANING_MODE is not implemented yet
    return isBmcInBareMetalMode(this->getFs());
}

std::tuple<std::uint8_t, std::string>
    Handler::getEthDetails(std::string intf) const
{
    if (intf.empty())
    {
        intf = NCSI_IF_NAME_STR;
    }
    return std::make_tuple(::ipmi::getChannelByName(intf), std::move(intf));
}

std::int64_t Handler::getRxPackets(const std::string& name) const
{
    std::ostringstream opath;
    opath << "/sys/class/net/" << name << "/statistics/rx_packets";
    std::string path = opath.str();

    // Minor sanity & security check (of course, I'm less certain if unicode
    // comes into play here.
    //
    // Basically you can't easily inject ../ or /../ into the path below.
    if (name.find("/") != std::string::npos)
    {
        std::fprintf(stderr, "Invalid or illegal name: '%s'\n", name.c_str());
        throw IpmiException(::ipmi::ccInvalidFieldRequest);
    }

    std::error_code ec;
    if (!this->getFs()->exists(path, ec))
    {
        std::fprintf(stderr, "Path: '%s' doesn't exist.\n", path.c_str());
        throw IpmiException(::ipmi::ccInvalidFieldRequest);
    }
    // We're uninterested in the state of ec.

    int64_t count = 0;
    std::ifstream ifs;
    ifs.exceptions(std::ifstream::failbit);
    try
    {
        ifs.open(path);
        ifs >> count;
    }
    catch (std::ios_base::failure& fail)
    {
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return count;
}

VersionTuple Handler::getCpldVersion(unsigned int id) const
{
    std::ostringstream opath;
    opath << "/run/cpld" << id << ".version";
    // Check for file

    std::error_code ec;
    if (!this->getFs()->exists(opath.str(), ec))
    {
        std::fprintf(stderr, "Path: '%s' doesn't exist.\n",
                     opath.str().c_str());
        throw IpmiException(::ipmi::ccInvalidFieldRequest);
    }
    // We're uninterested in the state of ec.

    // If file exists, read.
    std::ifstream ifs;
    ifs.exceptions(std::ifstream::failbit);
    std::string value;
    try
    {
        ifs.open(opath.str());
        ifs >> value;
    }
    catch (std::ios_base::failure& fail)
    {
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    // If value parses as expected, return version.
    VersionTuple version = std::make_tuple(0, 0, 0, 0);

    int num_fields = std::sscanf(value.c_str(),
                                 "%" SCNu8 ".%" SCNu8 ".%" SCNu8 ".%" SCNu8,
                                 &std::get<0>(version), &std::get<1>(version),
                                 &std::get<2>(version), &std::get<3>(version));
    if (num_fields == 0)
    {
        std::fprintf(stderr, "Invalid version.\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return version;
}

static constexpr auto TIME_DELAY_FILENAME = "/run/psu_timedelay";
static constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
static constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
static constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
static constexpr auto PSU_HARDRESET_TARGET = "gbmc-psu-hardreset.target";

void Handler::psuResetDelay(std::uint32_t delay) const
{
    std::ofstream ofs;
    ofs.open(TIME_DELAY_FILENAME, std::ofstream::out);
    if (!ofs.good())
    {
        std::fprintf(stderr, "Unable to open file for output.\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    ofs << "PSU_HARDRESET_DELAY=" << delay << std::endl;
    if (ofs.fail())
    {
        std::fprintf(stderr, "Write failed\n");
        ofs.close();
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    // Write succeeded, please continue.
    ofs.flush();
    ofs.close();

    auto bus = sdbusplus::bus::new_default();
    auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
                                      SYSTEMD_INTERFACE, "StartUnit");

    method.append(PSU_HARDRESET_TARGET);
    method.append("replace");

    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to call PSU hard reset");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

static constexpr auto RESET_ON_SHUTDOWN_FILENAME = "/run/powercycle_on_s5";

void Handler::psuResetOnShutdown() const
{
    std::ofstream ofs;
    ofs.open(RESET_ON_SHUTDOWN_FILENAME, std::ofstream::out);
    if (!ofs.good())
    {
        std::fprintf(stderr, "Unable to open file for output.\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
    ofs.close();
}

uint32_t Handler::getFlashSize()
{
    mtd_info_t info;
    int fd = open("/dev/mtd0", O_RDONLY);
    int err = ioctl(fd, MEMGETINFO, &info);
    close(fd);

    if (err)
    {
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
    return info.size;
}

std::string Handler::getEntityName(std::uint8_t id, std::uint8_t instance)
{
    // Check if we support this Entity ID.
    auto it = _entityIdToName.find(id);
    if (it == _entityIdToName.end())
    {
        log<level::ERR>("Unknown Entity ID", entry("ENTITY_ID=%d", id));
        throw IpmiException(::ipmi::ccInvalidFieldRequest);
    }

    std::string entityName;
    try
    {
        // Parse the JSON config file.
        if (!_entityConfigParsed)
        {
            _entityConfig = parseConfig(_configFile);
            _entityConfigParsed = true;
        }

        // Find the "entity id:entity instance" mapping to entity name.
        entityName = readNameFromConfig(it->second, instance, _entityConfig);
        if (entityName.empty())
        {
            throw IpmiException(::ipmi::ccInvalidFieldRequest);
        }
    }
    catch (InternalFailure& e)
    {
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return entityName;
}

std::string Handler::getMachineName()
{
    const char* path = "/etc/os-release";
    std::ifstream ifs(path);
    if (ifs.fail())
    {
        std::fprintf(stderr, "Failed to open: %s\n", path);
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    std::string line;
    while (true)
    {
        std::getline(ifs, line);
        if (ifs.eof())
        {
            std::fprintf(stderr, "Failed to find OPENBMC_TARGET_MACHINE: %s\n",
                         path);
            throw IpmiException(::ipmi::ccInvalidCommand);
        }
        if (ifs.fail())
        {
            std::fprintf(stderr, "Failed to read: %s\n", path);
            throw IpmiException(::ipmi::ccUnspecifiedError);
        }
        std::string_view lineView(line);
        constexpr std::string_view prefix = "OPENBMC_TARGET_MACHINE=";
        if (lineView.substr(0, prefix.size()) != prefix)
        {
            continue;
        }
        lineView.remove_prefix(prefix.size());
        lineView.remove_prefix(
            std::min(lineView.find_first_not_of('"'), lineView.size()));
        lineView.remove_suffix(
            lineView.size() - 1 -
            std::min(lineView.find_last_not_of('"'), lineView.size() - 1));
        return std::string(lineView);
    }
}

static constexpr auto HOST_TIME_DELAY_FILENAME = "/run/host_poweroff_delay";
static constexpr auto HOST_POWEROFF_TARGET = "gbmc-host-poweroff.target";

void Handler::hostPowerOffDelay(std::uint32_t delay) const
{
    // Set time delay
    std::ofstream ofs;
    ofs.open(HOST_TIME_DELAY_FILENAME, std::ofstream::out);
    if (!ofs.good())
    {
        std::fprintf(stderr, "Unable to open file for output.\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    ofs << "HOST_POWEROFF_DELAY=" << delay << std::endl;
    ofs.close();
    if (ofs.fail())
    {
        std::fprintf(stderr, "Write failed\n");
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    // Write succeeded, please continue.
    auto bus = sdbusplus::bus::new_default();
    auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
                                      SYSTEMD_INTERFACE, "StartUnit");

    method.append(HOST_POWEROFF_TARGET);
    method.append("replace");

    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to call Power Off",
                        entry("WHAT=%s", ex.what()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

std::string readNameFromConfig(const std::string& type, uint8_t instance,
                               const Json& config)
{
    static const std::vector<Json> empty{};
    std::vector<Json> readings = config.value(type, empty);
    std::string name = "";

    for (const auto& j : readings)
    {
        uint8_t instanceNum = j.value("instance", 0);
        // Not the instance we're interested in
        if (instanceNum != instance)
        {
            continue;
        }

        // Found the instance we're interested in
        name = j.value("name", "");

        break;
    }

    return name;
}

void Handler::buildI2cPcieMapping()
{
    _pcie_i2c_map = buildPcieMap();
}

size_t Handler::getI2cPcieMappingSize() const
{
    return _pcie_i2c_map.size();
}

std::tuple<std::uint32_t, std::string>
    Handler::getI2cEntry(unsigned int entry) const
{
    return _pcie_i2c_map[entry];
}

namespace
{

static constexpr std::string_view ACCEL_OOB_ROOT = "/com/google/customAccel/";
static constexpr char ACCEL_OOB_SERVICE[] = "com.google.custom_accel";
static constexpr char ACCEL_OOB_INTERFACE[] = "com.google.custom_accel.BAR";

// C type for "a{oa{sa{sv}}}" from DBus.ObjectManager::GetManagedObjects()
using AnyType = std::variant<std::string, uint8_t, uint32_t, uint64_t>;
using AnyTypeList = std::vector<std::pair<std::string, AnyType>>;
using NamedArrayOfAnyTypeLists =
    std::vector<std::pair<std::string, AnyTypeList>>;
using ArrayOfObjectPathsAndTieredAnyTypeLists = std::vector<
    std::pair<sdbusplus::message::object_path, NamedArrayOfAnyTypeLists>>;

} // namespace

sdbusplus::bus_t Handler::getDbus() const
{
    return sdbusplus::bus::new_default();
}

const std::unique_ptr<FileSystemInterface>& Handler::getFs() const
{
    return this->fsPtr;
}

uint32_t Handler::accelOobDeviceCount() const
{
    ArrayOfObjectPathsAndTieredAnyTypeLists data;

    try
    {
        auto bus = getDbus();
        auto method = bus.new_method_call(ACCEL_OOB_SERVICE, "/",
                                          "org.freedesktop.DBus.ObjectManager",
                                          "GetManagedObjects");
        bus.call(method).read(data);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>(
            "Failed to call GetManagedObjects on com.google.custom_accel",
            entry("WHAT=%s", ex.what()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    return data.size();
}

std::string Handler::accelOobDeviceName(size_t index) const
{
    ArrayOfObjectPathsAndTieredAnyTypeLists data;

    try
    {
        auto bus = getDbus();
        auto method = bus.new_method_call(ACCEL_OOB_SERVICE, "/",
                                          "org.freedesktop.DBus.ObjectManager",
                                          "GetManagedObjects");
        bus.call(method).read(data);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>(
            "Failed to call GetManagedObjects on com.google.custom_accel",
            entry("WHAT=%s", ex.what()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    if (index >= data.size())
    {
        log<level::WARNING>(
            "Requested index is larger than the number of entries.",
            entry("INDEX=%zu", index), entry("NUM_NAMES=%zu", data.size()));
        throw IpmiException(::ipmi::ccParmOutOfRange);
    }

    std::string_view name(data[index].first.str);
    if (!name.starts_with(ACCEL_OOB_ROOT))
    {
        throw IpmiException(::ipmi::ccInvalidCommand);
    }
    name.remove_prefix(ACCEL_OOB_ROOT.length());
    return std::string(name);
}

uint64_t Handler::accelOobRead(std::string_view name, uint64_t address,
                               uint8_t num_bytes) const
{
    static constexpr char ACCEL_OOB_METHOD[] = "Read";

    std::string object_name(ACCEL_OOB_ROOT);
    object_name.append(name);

    auto bus = getDbus();
    auto method = bus.new_method_call(ACCEL_OOB_SERVICE, object_name.c_str(),
                                      ACCEL_OOB_INTERFACE, ACCEL_OOB_METHOD);
    method.append(address, static_cast<uint64_t>(num_bytes));

    std::vector<uint8_t> bytes;

    try
    {
        bus.call(method).read(bytes);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to call Read on com.google.custom_accel",
                        entry("WHAT=%s", ex.what()),
                        entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
                        entry("DBUS_OBJECT=%s", object_name.c_str()),
                        entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
                        entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD),
                        entry("DBUS_ARG_ADDRESS=%016llx", address),
                        entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    if (bytes.size() < num_bytes)
    {
        log<level::ERR>(
            "Call to Read on com.google.custom_accel didn't return the expected"
            " number of bytes.",
            entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
            entry("DBUS_OBJECT=%s", object_name.c_str()),
            entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
            entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD),
            entry("DBUS_ARG_ADDRESS=%016llx", address),
            entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes),
            entry("DBUS_RETURN_SIZE=%zu", bytes.size()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }

    if (bytes.size() > sizeof(uint64_t))
    {
        log<level::ERR>(
            "Call to Read on com.google.custom_accel returned more than 8B.",
            entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
            entry("DBUS_OBJECT=%s", object_name.c_str()),
            entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
            entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD),
            entry("DBUS_ARG_ADDRESS=%016llx", address),
            entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes),
            entry("DBUS_RETURN_SIZE=%zu", bytes.size()));
        throw IpmiException(::ipmi::ccReqDataTruncated);
    }

    uint64_t data = 0;
    for (size_t i = 0; i < num_bytes; ++i)
    {
        data = (data << 8) | bytes[i];
    }

    return data;
}

void Handler::accelOobWrite(std::string_view name, uint64_t address,
                            uint8_t num_bytes, uint64_t data) const
{
    static constexpr std::string_view ACCEL_OOB_METHOD = "Write";

    std::string object_name(ACCEL_OOB_ROOT);
    object_name.append(name);

    if (num_bytes > sizeof(data))
    {
        log<level::ERR>(
            "Call to Write on com.google.custom_accel requested more than 8B.",
            entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
            entry("DBUS_OBJECT=%s", object_name.c_str()),
            entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
            entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD.data()),
            entry("DBUS_ARG_ADDRESS=%016llx", address),
            entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes),
            entry("DBUS_ARG_DATA=%016llx", data));
        throw IpmiException(::ipmi::ccParmOutOfRange);
    }

    std::vector<uint8_t> bytes;
    bytes.reserve(num_bytes);
    for (size_t i = 0; i < num_bytes; ++i)
    {
        bytes.emplace_back(data & 0xff);
        data >>= 8;
    }

    try
    {
        auto bus = getDbus();
        auto method =
            bus.new_method_call(ACCEL_OOB_SERVICE, object_name.c_str(),
                                ACCEL_OOB_INTERFACE, ACCEL_OOB_METHOD.data());
        method.append(address, bytes);
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to call Write on com.google.custom_accel",
                        entry("WHAT=%s", ex.what()),
                        entry("DBUS_SERVICE=%s", ACCEL_OOB_SERVICE),
                        entry("DBUS_OBJECT=%s", object_name.c_str()),
                        entry("DBUS_INTERFACE=%s", ACCEL_OOB_INTERFACE),
                        entry("DBUS_METHOD=%s", ACCEL_OOB_METHOD.data()),
                        entry("DBUS_ARG_ADDRESS=%016llx", address),
                        entry("DBUS_ARG_NUM_BYTES=%zu", (size_t)num_bytes),
                        entry("DBUS_ARG_DATA=%016llx", data));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

std::vector<uint8_t> Handler::pcieBifurcation(uint8_t index)
{
    return bifurcationHelper.get().getBifurcation(index).value_or(
        std::vector<uint8_t>{});
}

static constexpr auto BARE_METAL_TARGET = "gbmc-bare-metal-active.target";

void Handler::linuxBootDone() const
{
    if (isBmcInBareMetalMode(this->fsPtr) !=
        static_cast<uint8_t>(BmcMode::BM_MODE))
    {
        return;
    }

    log<level::INFO>("LinuxBootDone: Disabling IPMI");

    // Start the bare metal active systemd target.
    auto bus = sdbusplus::bus::new_default();
    auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
                                      SYSTEMD_INTERFACE, "StartUnit");

    method.append(BARE_METAL_TARGET);
    method.append("replace");

    try
    {
        bus.call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& ex)
    {
        log<level::ERR>("Failed to start bare metal active systemd target",
                        entry("WHAT=%s", ex.what()));
        throw IpmiException(::ipmi::ccUnspecifiedError);
    }
}

} // namespace ipmi
} // namespace google
