/*
 * Copyright (c) 2018-2021 Ampere Computing 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 "oemcommands.hpp"

#include <boost/container/flat_map.hpp>
#include <ipmid/api.hpp>
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
#include <phosphor-logging/log.hpp>

#include <cstdlib>

using namespace phosphor::logging;

using BasicVariantType =
    std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
                 double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;
using FruObjectType = boost::container::flat_map<
    sdbusplus::message::object_path,
    boost::container::flat_map<
        std::string,
        boost::container::flat_map<std::string, BasicVariantType>>>;

constexpr static const char* fruDeviceServiceName =
    "xyz.openbmc_project.FruDevice";

constexpr static const char* chassisTypeRackMount = "23";

static inline auto response(uint8_t cc)
{
    return std::make_tuple(cc, std::nullopt);
}

static inline auto responseFailure()
{
    return response(responseFail);
}

/** @brief get Baseboard FRU's address
 *  @param - busIdx, address of I2C device
 *  @returns - true if successfully, false if fail
 */
[[maybe_unused]] static bool getBaseBoardFRUAddr(uint8_t& busIdx, uint8_t& addr)
{
    bool retVal = false;
    sd_bus* bus = NULL;
    FruObjectType fruObjects;

    /*
     * Read all managed objects of FRU device
     */
    int ret = sd_bus_default_system(&bus);
    if (ret < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Failed to connect to system bus");
        sd_bus_unref(bus);
        return false;
    }
    sdbusplus::bus::bus dbus(bus);
    auto mapperCall = dbus.new_method_call(fruDeviceServiceName, "/",
                                           "org.freedesktop.DBus.ObjectManager",
                                           "GetManagedObjects");

    try
    {
        auto mapperReply = dbus.call(mapperCall);
        mapperReply.read(fruObjects);
    }
    catch (sdbusplus::exception_t& e)
    {
        log<level::ERR>("Fail to call GetManagedObjects method");

        sd_bus_unref(bus);
        return false;
    }

    /*
     * Scan all FRU objects to find out baseboard FRU device.
     * The basedboard FRU device is indecate by chassis type
     * is Rack Mount - "23"
     */
    for (const auto& fruObj : fruObjects)
    {
        auto fruDeviceInf = fruObj.second.find("xyz.openbmc_project.FruDevice");

        if (fruDeviceInf != fruObj.second.end())
        {
            auto chassisProperty = fruDeviceInf->second.find("CHASSIS_TYPE");

            if (chassisProperty != fruDeviceInf->second.end())
            {
                std::string chassisType =
                    std::get<std::string>(chassisProperty->second);
                auto busProperty = fruDeviceInf->second.find("BUS");
                auto addrProperty = fruDeviceInf->second.find("ADDRESS");

                if ((0 == chassisType.compare(chassisTypeRackMount)) &&
                    (busProperty != fruDeviceInf->second.end()) &&
                    (addrProperty != fruDeviceInf->second.end()))
                {
                    busIdx = (uint8_t)std::get<uint32_t>(busProperty->second);
                    addr = (uint8_t)std::get<uint32_t>(addrProperty->second);
                    retVal = true;
                    break;
                }
            }
        }
    }

    sd_bus_unref(bus);
    return retVal;
}

/** @brief get Raw FRU's data
 *  @param - busIdx, address of I2C device.
 *         - fruData: data have been read
 *  @returns - true if successfully, false if fail
 */
static bool getRawFruData(uint8_t busIdx, uint8_t addr,
                          std::vector<uint8_t>& fruData)
{
    bool retVal = false;
    sd_bus* bus = NULL;
    int ret = sd_bus_default_system(&bus);

    if (ret < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Failed to connect to system bus",
            phosphor::logging::entry("ERRNO=0x%X", -ret));
    }
    else
    {
        sdbusplus::bus::bus dbus(bus);
        auto MapperCall = dbus.new_method_call(
            fruDeviceServiceName, "/xyz/openbmc_project/FruDevice",
            "xyz.openbmc_project.FruDeviceManager", "GetRawFru");

        MapperCall.append(busIdx, addr);

        try
        {
            auto mapperReply = dbus.call(MapperCall);
            mapperReply.read(fruData);
            retVal = true;
        }
        catch (sdbusplus::exception_t& e)
        {
            log<level::ERR>("Fail to read Raw FRU data from system bus\n");
        }
    }

    sd_bus_unref(bus);

    return retVal;
}

/** @brief update MAC address information in FRU data
 *  @param - fruData: FRU data
 *         - macAddress: MAC address information
 *  @returns - true if successfully, false if fail
 */
static bool updateMACAddrInFRU(std::vector<uint8_t>& fruData,
                               std::vector<uint8_t> macAddress)
{
    bool retVal = false;
    uint32_t areaOffset = fruData[3] * 8; /* Board area start offset */
    char macAddressStr[18];
    uint32_t boardLeng = 0;
    uint8_t checkSumVal = 0;

    /*
     * Update MAC address at first custom field of Board Information Area.
     */
    if (areaOffset != 0)
    {
        /*
         * The Board Manufacturer type/length byte is stored
         * at byte 0x06 of Board area.
         */
        uint32_t fieldOffset = areaOffset + 6;

        /*
         * Scan all 5 predefined fields of Board area to jump to
         * first Custom field.
         */
        for (uint32_t i = 0; i < 5; i++)
        {
            fieldOffset += (fruData[fieldOffset] & 0x3f) + 1;
        }

        /*
         * Update the MAC address information when type/length is not
         * EndOfField byte and the length of Custom field is 17.
         */
        if ((fruData[fieldOffset] != 0xc1) &&
            ((uint8_t)17 == (fruData[fieldOffset] & (uint8_t)0x3f)))
        {
            sprintf(macAddressStr, "%02X:%02X:%02X:%02X:%02X:%02X",
                    macAddress[0], macAddress[1], macAddress[2], macAddress[3],
                    macAddress[4], macAddress[5]);

            /*
             * Update 17 bytes of MAC address information
             */
            fieldOffset++;
            for (uint32_t i = 0; i < 17; i++)
            {
                fruData[fieldOffset + i] = macAddressStr[i];
            }

            /*
             * Re-caculate the checksum of Board Information Area.
             */
            boardLeng = fruData[areaOffset + 1] * 8;
            for (uint32_t i = 0; i < boardLeng - 1; i++)
            {
                checkSumVal += fruData[areaOffset + i];
            }

            checkSumVal = ~checkSumVal + 1;
            fruData[areaOffset + boardLeng - 1] = checkSumVal;

            retVal = true;
        }
        else
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "FRU does not include MAC address information");
        }
    }
    else
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "FRU does not include Board Information Area");
    }

    return retVal;
}

/** @brief write FRU data to EEPROM
 *  @param - busIdx and address of I2C device.
 *         - fruData: FRU data
 *  @returns - true if successfully, false if fail
 */
static bool writeFruData(uint8_t busIdx, uint8_t addr,
                         std::vector<uint8_t>& fruData)
{
    bool retVal = false;
    sd_bus* bus = NULL;
    int ret = sd_bus_default_system(&bus);

    if (ret < 0)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Failed to connect to system bus",
            phosphor::logging::entry("ERRNO=0x%X", -ret));
    }
    else
    {
        sdbusplus::bus::bus dbus(bus);
        auto MapperCall = dbus.new_method_call(
            fruDeviceServiceName, "/xyz/openbmc_project/FruDevice",
            "xyz.openbmc_project.FruDeviceManager", "WriteFru");

        MapperCall.append(busIdx, addr, fruData);

        try
        {
            auto mapperReply = dbus.call(MapperCall);
            retVal = true;
        }
        catch (sdbusplus::exception_t& e)
        {
            log<level::ERR>("Fail to Write FRU data via system bus\n");
        }
    }

    sd_bus_unref(bus);

    return retVal;
}

/** @brief execute a command and get the output of the command
 *  @param[in] the command
 *  @returns output of the command
 */
std::string exec(const char* cmd)
{
    char buffer[128];
    std::string result = "";
    /* Pipe stream from a command */
    FILE* pipe = popen(cmd, "r");
    if (!pipe)
        throw std::runtime_error("popen() failed!");
    try
    {
        /* Reads a line from the specified stream and stores it */
        while (fgets(buffer, sizeof buffer, pipe) != NULL)
        {
            result += buffer;
        }
    }
    catch (...)
    {
        pclose(pipe);
        throw;
    }
    /* Close a stream that was opened by popen() */
    pclose(pipe);
    return result;
}

/** @brief implements sync RTC time to BMC commands
 *  @param - None
 *  @returns IPMI completion code.
 */
ipmi::RspType<> ipmiSyncRTCTimeToBMC()
{
    std::string cmd;
    std::string cmdOutput;
    int ret;
    try
    {
        /* Check the mode of NTP in the system, set the system time in case the
         * NTP mode is disabled.
         */
        cmd = "systemctl status systemd-timesyncd.service | grep inactive";
        cmdOutput = exec(cmd.c_str());
        if (cmdOutput.empty())
        {
            log<level::INFO>("Can not set system time while the mode is NTP");
            return responseFailure();
        }
        else
        {
            /* Sync time from RTC to BMC using hwclock */
            ret = system("hwclock --hctosys");
            if (ret == -1)
            {
                log<level::INFO>("Can not set the system time");
                return responseFailure();
            }
        }
    }
    catch (const std::exception& e)
    {
        log<level::ERR>(e.what());
        return responseFailure();
    }

    return ipmi::responseSuccess();
}

/** @brief implements ipmi oem command edit MAC address
 *  @param - new macAddress
 *  @returns - Fail or Success.
 */
ipmi::RspType<uint8_t> ipmiDocmdSetMacAddress(std::vector<uint8_t> macAddress)
{
    std::vector<uint8_t> fruData;
    uint8_t busIdx = 0;
    uint8_t addrss = 0;

    if (macAddress.size() != 6)
    {
        log<level::ERR>("new MAC address is invalid");
        return responseFailure();
    }

#if defined(MAC_ADDRESS_FRU_BUS) && defined(MAC_ADDRESS_FRU_ADDR)
    /* Set BUS and Address of FRU device that includes MAC address */
    busIdx = MAC_ADDRESS_FRU_BUS;
    addrss = MAC_ADDRESS_FRU_ADDR;
#else
    /* Calculate BUS and Address of FRU device that includes MAC address */
    if (!getBaseBoardFRUAddr(busIdx, addrss))
    {
        log<level::ERR>(
            "Can not get the bus and address of baseboard FRU device");
        return responseFailure();
    }
#endif

    if (!getRawFruData(busIdx, addrss, fruData))
    {
        log<level::ERR>("Can not get raw FRU data");
        return responseFailure();
    }

    if (!updateMACAddrInFRU(fruData, macAddress))
    {
        log<level::ERR>("Can not update MAC address");
        return responseFailure();
    }

    if (!writeFruData(busIdx, addrss, fruData))
    {
        log<level::ERR>("Can not Write FRU data");
        return responseFailure();
    }

    return ipmi::responseSuccess(macAddress.size());
}

void registerOEMFunctions() __attribute__((constructor));
void registerOEMFunctions()
{
    ipmi::registerHandler(ipmi::prioOemBase, ipmi::ampere::netFnAmpere,
                          ipmi::general::cmdSyncRtcTime, ipmi::Privilege::User,
                          ipmiSyncRTCTimeToBMC);

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::ampere::netFnAmpere,
                          ipmi::general::cmdEditBmcMacAdr,
                          ipmi::Privilege::User, ipmiDocmdSetMacAddress);
}
