/*
// Copyright (c) 2020 Intel Corporation
//
// 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 "cpuinfo.hpp"
#include "cpuinfo_utils.hpp"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/ioctl.h>

#include <boost/asio/io_service.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/container/flat_map.hpp>

#include <iostream>
#include <list>
#include <optional>
#include <sstream>
#include <string>

extern "C"
{
#include <i2c/smbus.h>
#include <linux/i2c-dev.h>
}

#if PECI_ENABLED
#include "speed_select.hpp"

#include <peci.h>
#endif

#include <phosphor-logging/log.hpp>
#include <sdbusplus/asio/object_server.hpp>

namespace cpu_info
{
static constexpr bool debug = false;
static constexpr const char* assetInterfaceName =
    "xyz.openbmc_project.Inventory.Decorator.Asset";
static constexpr const char* cpuProcessName =
    "xyz.openbmc_project.Smbios.MDR_V2";

// constants for reading SSPEC or QDF string from PIROM
// Currently, they are the same for platforms with Ice Lake
static constexpr uint8_t defaultI2cBus = 13;
static constexpr uint8_t defaultI2cSlaveAddr0 = 0x50;
static constexpr uint8_t sspecRegAddr = 0xd;
static constexpr uint8_t sspecSize = 6;

using CPUInfoMap = boost::container::flat_map<size_t, std::shared_ptr<CPUInfo>>;

static CPUInfoMap cpuInfoMap = {};

/**
 * Simple aggregate to define an external D-Bus property which needs to be set
 * by this application.
 */
struct CpuProperty
{
    std::string object;
    std::string interface;
    std::string name;
    std::string value;
};

/**
 * List of properties we want to set on other D-Bus objects. This list is kept
 * around so that if any target objects are removed+re-added, then we can set
 * the values again.
 */
static std::list<CpuProperty> propertiesToSet;

static std::ostream& logStream(int cpu)
{
    return std::cerr << "[CPU " << cpu << "] ";
}

static void setCpuProperty(
    const std::shared_ptr<sdbusplus::asio::connection>& conn, size_t cpu,
    const std::string& interface, const std::string& propName,
    const std::string& propVal);
static void setDbusProperty(
    const std::shared_ptr<sdbusplus::asio::connection>& conn, size_t cpu,
    const CpuProperty& newProp);
static void createCpuUpdatedMatch(
    const std::shared_ptr<sdbusplus::asio::connection>& conn, size_t cpu);

static std::optional<std::string> readSSpec(uint8_t bus, uint8_t slaveAddr,
                                            uint8_t regAddr, size_t count)
{
    unsigned long funcs = 0;
    std::string devPath = "/dev/i2c-" + std::to_string(bus);

    int fd = ::open(devPath.c_str(), O_RDWR);
    if (fd < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Error in open!",
            phosphor::logging::entry("PATH=%s", devPath.c_str()),
            phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
        return std::nullopt;
    }

    if (::ioctl(fd, I2C_FUNCS, &funcs) < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Error in I2C_FUNCS!",
            phosphor::logging::entry("PATH=%s", devPath.c_str()),
            phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
        ::close(fd);
        return std::nullopt;
    }

    if (!(funcs & I2C_FUNC_SMBUS_READ_BYTE_DATA))
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "i2c bus does not support read!",
            phosphor::logging::entry("PATH=%s", devPath.c_str()),
            phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
        ::close(fd);
        return std::nullopt;
    }

    if (::ioctl(fd, I2C_SLAVE_FORCE, slaveAddr) < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Error in I2C_SLAVE_FORCE!",
            phosphor::logging::entry("PATH=%s", devPath.c_str()),
            phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
        ::close(fd);
        return std::nullopt;
    }

    int value = 0;
    std::string sspec;
    sspec.reserve(count);

    for (size_t i = 0; i < count; i++)
    {
        value = ::i2c_smbus_read_byte_data(fd, regAddr + i);
        if (value < 0)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Error in i2c read!",
                phosphor::logging::entry("PATH=%s", devPath.c_str()),
                phosphor::logging::entry("SLAVEADDR=0x%x", slaveAddr));
            ::close(fd);
            return std::nullopt;
        }
        if (!std::isprint(static_cast<unsigned char>(value)))
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Non printable value in sspec, ignored.");
            continue;
        }
        // sspec always starts with S,
        // if not assume it is QDF string which starts at offset 2
        if (i == 0 && static_cast<unsigned char>(value) != 'S')
        {
            i = 1;
            continue;
        }
        sspec.push_back(static_cast<unsigned char>(value));
    }
    ::close(fd);

    if (sspec.size() < 4)
    {
        return std::nullopt;
    }

    return sspec;
}

/**
 * Higher level SSpec logic.
 * This handles retrying the PIROM reads until two subsequent reads are
 * successful and return matching data. When we have confidence that the data
 * read is correct, then set the property on D-Bus.
 */
static void tryReadSSpec(
    const std::shared_ptr<sdbusplus::asio::connection>& conn, size_t cpuIndex)
{
    static int failedReads = 0;

    auto cpuInfoIt = cpuInfoMap.find(cpuIndex);
    if (cpuInfoIt == cpuInfoMap.end())
    {
        return;
    }
    auto cpuInfo = cpuInfoIt->second;

    std::optional<std::string> newSSpec =
        readSSpec(cpuInfo->i2cBus, cpuInfo->i2cDevice, sspecRegAddr, sspecSize);
    logStream(cpuInfo->id) << "SSpec read status: "
                           << static_cast<bool>(newSSpec) << "\n";
    if (newSSpec && newSSpec == cpuInfo->sSpec)
    {
        setCpuProperty(conn, cpuInfo->id, assetInterfaceName, "Model",
                       *newSSpec);
        return;
    }

    // If this read failed, back off for a little longer so that hopefully the
    // transient condition affecting PIROM reads will pass, but give up after
    // several consecutive failures. But if this read looked OK, try again
    // sooner to confirm it.
    int retrySeconds;
    if (newSSpec)
    {
        retrySeconds = 1;
        failedReads = 0;
        cpuInfo->sSpec = *newSSpec;
    }
    else
    {
        retrySeconds = 5;
        if (++failedReads > 10)
        {
            logStream(cpuInfo->id) << "PIROM Read failed too many times\n";
            return;
        }
    }

    auto sspecTimer = std::make_shared<boost::asio::steady_timer>(
        conn->get_io_context(), std::chrono::seconds(retrySeconds));
    sspecTimer->async_wait(
        [sspecTimer, conn, cpuIndex](boost::system::error_code ec) {
            if (ec)
            {
                return;
            }
            tryReadSSpec(conn, cpuIndex);
        });
}

/**
 * Add a D-Bus property to the global list, and attempt to set it by calling
 * `setDbusProperty`.
 *
 * @param[in,out]   conn        D-Bus connection.
 * @param[in]       cpu         1-based CPU index.
 * @param[in]       interface   Interface to set.
 * @param[in]       propName    Property to set.
 * @param[in]       propVal     Value to set.
 */
static void setCpuProperty(
    const std::shared_ptr<sdbusplus::asio::connection>& conn, size_t cpu,
    const std::string& interface, const std::string& propName,
    const std::string& propVal)
{
    // cpuId from configuration is one based as
    // dbus object path used by smbios is 0 based
    const std::string objectPath = cpuPath + std::to_string(cpu - 1);

    // Can switch to emplace_back if you define a CpuProperty constructor.
    propertiesToSet.push_back(
        CpuProperty{objectPath, interface, propName, propVal});

    setDbusProperty(conn, cpu, propertiesToSet.back());
}

/**
 * Set a D-Bus property which is already contained in the global list, and also
 * setup a D-Bus match to make sure the target property stays correct.
 *
 * @param[in,out]   conn    D-Bus connection.
 * @param[in]       cpu     1-baesd CPU index.
 * @param[in]       newProp Property to set.
 */
static void setDbusProperty(
    const std::shared_ptr<sdbusplus::asio::connection>& conn, size_t cpu,
    const CpuProperty& newProp)
{
    createCpuUpdatedMatch(conn, cpu);
    conn->async_method_call(
        [](const boost::system::error_code ec) {
            if (ec)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Cannot set CPU property!");
                return;
            }
        },
        cpuProcessName, newProp.object.c_str(),
        "org.freedesktop.DBus.Properties", "Set", newProp.interface,
        newProp.name, std::variant<std::string>{newProp.value});
}

/**
 * Set up a D-Bus match (if one does not already exist) to watch for any new
 * interfaces on the cpu object. When new interfaces are added, re-send all
 * properties targeting that object/interface.
 *
 * @param[in,out]   conn    D-Bus connection.
 * @param[in]       cpu     1-based CPU index.
 */
static void createCpuUpdatedMatch(
    const std::shared_ptr<sdbusplus::asio::connection>& conn, size_t cpu)
{
    static boost::container::flat_map<size_t,
                                      std::unique_ptr<sdbusplus::bus::match_t>>
        cpuUpdatedMatch;

    if (cpuUpdatedMatch[cpu])
    {
        return;
    }

    const std::string objectPath = cpuPath + std::to_string(cpu - 1);

    cpuUpdatedMatch.insert_or_assign(
        cpu,
        std::make_unique<sdbusplus::bus::match_t>(
            static_cast<sdbusplus::bus_t&>(*conn),
            sdbusplus::bus::match::rules::interfacesAdded() +
                sdbusplus::bus::match::rules::argNpath(0, objectPath.c_str()),
            [conn, cpu](sdbusplus::message_t& msg) {
                sdbusplus::message::object_path objectName;
                boost::container::flat_map<
                    std::string,
                    boost::container::flat_map<
                        std::string, std::variant<std::string, uint64_t>>>
                    msgData;

                msg.read(objectName, msgData);

                // Go through all the property changes, and retry all of them
                // targeting this object/interface which was just added.
                for (const CpuProperty& prop : propertiesToSet)
                {
                    if (prop.object == objectName &&
                        msgData.contains(prop.interface))
                    {
                        setDbusProperty(conn, cpu, prop);
                    }
                }
            }));
}

#if PECI_ENABLED
static void getPPIN(boost::asio::io_service& io,
                    const std::shared_ptr<sdbusplus::asio::connection>& conn,
                    const size_t& cpu)
{
    if (cpuInfoMap.find(cpu) == cpuInfoMap.end() || cpuInfoMap[cpu] == nullptr)
    {
        std::cerr << "No information found for cpu " << cpu << "\n";
        return;
    }

    std::shared_ptr<CPUInfo> cpuInfo = cpuInfoMap[cpu];

    if (cpuInfo->id != cpu)
    {
        std::cerr << "Incorrect CPU id " << (unsigned)cpuInfo->id << " expect "
                  << cpu << "\n";
        return;
    }

    uint8_t cpuAddr = cpuInfo->peciAddr;

    uint8_t cc = 0;
    CPUModel model{};
    uint8_t stepping = 0;

    // Wait for POST to complete to ensure that BIOS has time to enable the
    // PPIN. Before BIOS enables it, we would get a 0x90 CC on PECI.
    if (hostState != HostState::postComplete ||
        peci_GetCPUID(cpuAddr, &model, &stepping, &cc) != PECI_CC_SUCCESS)
    {
        // Start the PECI check loop
        auto waitTimer = std::make_shared<boost::asio::steady_timer>(io);
        waitTimer->expires_after(
            std::chrono::seconds(cpu_info::peciCheckInterval));

        waitTimer->async_wait(
            [waitTimer, &io, conn, cpu](const boost::system::error_code& ec) {
                if (ec)
                {
                    // operation_aborted is expected if timer is canceled
                    // before completion.
                    if (ec != boost::asio::error::operation_aborted)
                    {
                        phosphor::logging::log<phosphor::logging::level::ERR>(
                            "info update timer async_wait failed ",
                            phosphor::logging::entry("EC=0x%x", ec.value()));
                    }
                    return;
                }
                getPPIN(io, conn, cpu);
            });
        return;
    }

    switch (model)
    {
        case iceLake:
        case iceLakeD:
        case sapphireRapids:
        case emeraldRapids:
        case graniteRapids:
        case graniteRapidsD:
        case sierraForest:
        {
            // PPIN can be read through PCS 19
            static constexpr uint8_t u8Size = 4; // default to a DWORD
            static constexpr uint8_t u8PPINPkgIndex = 19;
            static constexpr uint16_t u16PPINPkgParamHigh = 2;
            static constexpr uint16_t u16PPINPkgParamLow = 1;
            uint64_t cpuPPIN = 0;
            uint32_t u32PkgValue = 0;

            int ret =
                peci_RdPkgConfig(cpuAddr, u8PPINPkgIndex, u16PPINPkgParamLow,
                                 u8Size, (uint8_t*)&u32PkgValue, &cc);
            if (0 != ret)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "peci read package config failed at address",
                    phosphor::logging::entry("PECIADDR=0x%x",
                                             (unsigned)cpuAddr),
                    phosphor::logging::entry("CC=0x%x", cc));
                u32PkgValue = 0;
            }

            cpuPPIN = u32PkgValue;
            ret = peci_RdPkgConfig(cpuAddr, u8PPINPkgIndex, u16PPINPkgParamHigh,
                                   u8Size, (uint8_t*)&u32PkgValue, &cc);
            if (0 != ret)
            {
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "peci read package config failed at address",
                    phosphor::logging::entry("PECIADDR=0x%x",
                                             (unsigned)cpuAddr),
                    phosphor::logging::entry("CC=0x%x", cc));
                cpuPPIN = 0;
                u32PkgValue = 0;
            }

            cpuPPIN |= static_cast<uint64_t>(u32PkgValue) << 32;

            // set SerialNumber if cpuPPIN is valid
            if (0 != cpuPPIN)
            {
                std::stringstream stream;
                stream << std::hex << cpuPPIN;
                std::string serialNumber(stream.str());
                cpuInfo->publishUUID(*conn, serialNumber);
            }
            break;
        }
        default:
            phosphor::logging::log<phosphor::logging::level::INFO>(
                "in-compatible cpu for cpu asset info");
            break;
    }
}
#endif

/**
 * Get cpu and pirom address
 */
static void getCpuAddress(
    boost::asio::io_service& io,
    const std::shared_ptr<sdbusplus::asio::connection>& conn,
    const std::string& service, const std::string& object,
    const std::string& interface)
{
    conn->async_method_call(
        [&io, conn](boost::system::error_code ec,
                    const boost::container::flat_map<
                        std::string,
                        std::variant<std::string, uint64_t, uint32_t, uint16_t,
                                     std::vector<std::string>>>& properties) {
            const uint64_t* value = nullptr;
            std::optional<uint8_t> peciAddress;
            uint8_t i2cBus = defaultI2cBus;
            std::optional<uint8_t> i2cDevice;
            std::optional<size_t> cpu;

            if (ec)
            {
                std::cerr << "DBUS response error " << ec.value() << ": "
                          << ec.message() << "\n";
                return;
            }

            for (const auto& property : properties)
            {
                std::cerr << "property " << property.first << "\n";
                if (property.first == "Address")
                {
                    value = std::get_if<uint64_t>(&property.second);
                    if (value != nullptr)
                    {
                        peciAddress = static_cast<uint8_t>(*value);
                    }
                }
                if (property.first == "CpuID")
                {
                    value = std::get_if<uint64_t>(&property.second);
                    if (value != nullptr)
                    {
                        cpu = static_cast<size_t>(*value);
                    }
                }
                if (property.first == "PiromI2cAddress")
                {
                    value = std::get_if<uint64_t>(&property.second);
                    if (value != nullptr)
                    {
                        i2cDevice = static_cast<uint8_t>(*value);
                    }
                }
                if (property.first == "PiromI2cBus")
                {
                    value = std::get_if<uint64_t>(&property.second);
                    if (value != nullptr)
                    {
                        i2cBus = static_cast<uint8_t>(*value);
                    }
                }
            }

            if (!cpu || !peciAddress)
            {
                return;
            }

            if (!i2cDevice)
            {
                i2cDevice = defaultI2cSlaveAddr0 + *cpu - 1;
            }

            auto key = cpuInfoMap.find(*cpu);

            if (key != cpuInfoMap.end())
            {
                cpuInfoMap.erase(key);
            }

            cpuInfoMap.emplace(*cpu,
                               std::make_shared<CPUInfo>(*cpu, *peciAddress,
                                                         i2cBus, *i2cDevice));

            tryReadSSpec(conn, *cpu);

#if PECI_ENABLED
            getPPIN(io, conn, *cpu);
#endif
        },
        service, object, "org.freedesktop.DBus.Properties", "GetAll",
        interface);
}

/**
 * D-Bus client: to get platform specific configs
 */
static void getCpuConfiguration(
    boost::asio::io_service& io,
    const std::shared_ptr<sdbusplus::asio::connection>& conn,
    sdbusplus::asio::object_server& objServer)
{
    // Get the Cpu configuration
    // In case it's not available, set a match for it
    static std::unique_ptr<sdbusplus::bus::match_t> cpuConfigMatch =
        std::make_unique<sdbusplus::bus::match_t>(
            *conn,
            "type='signal',interface='org.freedesktop.DBus.Properties',member='"
            "PropertiesChanged',arg0='xyz.openbmc_project."
            "Configuration.XeonCPU'",
            [&io, conn, &objServer](sdbusplus::message_t& /* msg */) {
                std::cerr << "get cpu configuration match\n";
                static boost::asio::steady_timer filterTimer(io);
                filterTimer.expires_after(
                    std::chrono::seconds(configCheckInterval));

                filterTimer.async_wait(
                    [&io, conn,
                     &objServer](const boost::system::error_code& ec) {
                        if (ec == boost::asio::error::operation_aborted)
                        {
                            return; // we're being canceled
                        }
                        else if (ec)
                        {
                            std::cerr << "Error: " << ec.message() << "\n";
                            return;
                        }
                        getCpuConfiguration(io, conn, objServer);
                    });
            });

    conn->async_method_call(
        [&io, conn](
            boost::system::error_code ec,
            const std::vector<std::pair<
                std::string,
                std::vector<std::pair<std::string, std::vector<std::string>>>>>&
                subtree) {
            if constexpr (debug)
                std::cerr << "async_method_call callback\n";

            if (ec)
            {
                std::cerr << "error with async_method_call\n";
                return;
            }
            if (subtree.empty())
            {
                // No config data yet, so wait for the match
                return;
            }

            for (const auto& object : subtree)
            {
                for (const auto& service : object.second)
                {
                    getCpuAddress(io, conn, service.first, object.first,
                                  "xyz.openbmc_project.Configuration.XeonCPU");
                }
            }
            if constexpr (debug)
                std::cerr << "getCpuConfiguration callback complete\n";

            return;
        },
        "xyz.openbmc_project.ObjectMapper",
        "/xyz/openbmc_project/object_mapper",
        "xyz.openbmc_project.ObjectMapper", "GetSubTree",
        "/xyz/openbmc_project/", 0,
        std::array<const char*, 1>{
            "xyz.openbmc_project.Configuration.XeonCPU"});
}

} // namespace cpu_info

int main()
{
    // setup connection to dbus
    boost::asio::io_service& io = cpu_info::dbus::getIOContext();
    std::shared_ptr<sdbusplus::asio::connection> conn =
        cpu_info::dbus::getConnection();

    // CPUInfo Object
    conn->request_name(cpu_info::cpuInfoObject);
    sdbusplus::asio::object_server server =
        sdbusplus::asio::object_server(conn);
    sdbusplus::bus_t& bus = static_cast<sdbusplus::bus_t&>(*conn);
    sdbusplus::server::manager_t objManager(bus,
                                            "/xyz/openbmc_project/inventory");

    cpu_info::hostStateSetup(conn);

#if PECI_ENABLED
    cpu_info::sst::init();
#endif

    // shared_ptr conn is global for the service
    // const reference of conn is passed to async calls
    cpu_info::getCpuConfiguration(io, conn, server);

    io.run();

    return 0;
}
