/*
 * Copyright (c)  2018 Intel Corporation.
 * Copyright (c)  2018-present Facebook.
 *
 * 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 <biccommands.hpp>
#include <commandutils.hpp>
#include <ipmid/api-types.hpp>
#include <ipmid/api.hpp>
#include <phosphor-logging/log.hpp>
#include <types.hpp>

#include <iostream>
#include <variant>
#include <vector>

namespace ipmi
{

int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
               std::vector<uint8_t>&);

using namespace phosphor::logging;

#ifdef BIC_ENABLED
static void registerBICFunctions() __attribute__((constructor));
#endif

extern message::Response::ptr executeIpmiCommand(message::Request::ptr);

int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&,
               std::vector<uint8_t>&);

constexpr std::array<uint8_t, 2> amdDimmLoopPrefix = {0xDD, 0xEE};

namespace dimm
{
std::unordered_map<hostId, dimmLoop> dimmLoops;
} // namespace dimm

//----------------------------------------------------------------------
// ipmiOemBicHandler (IPMI/Section - ) (CMD_OEM_BIC_INFO)
// This Function will handle BIC request for netfn=0x38 and cmd=1
// send the response back to the sender.
//----------------------------------------------------------------------

ipmi::RspType<IanaType, uint8_t, uint2_t, uint6_t, uint8_t, uint8_t,
              ipmi::message::Payload>
    ipmiOemBicHandler(ipmi::Context::ptr ctx, IanaType reqIana,
                      uint8_t interface, uint2_t lun, uint6_t netFnReq,
                      uint8_t cmdReq, SecureBuffer data)
{
    ipmi::message::Response::ptr res;

    // Updating the correct netfn and cmd in the ipmi Context
    ctx->netFn = ((uint8_t)netFnReq);
    ctx->cmd = cmdReq;

    // creating ipmi message request for calling executeIpmiCommand function
    auto req = std::make_shared<ipmi::message::Request>(ctx, std::move(data));

    // Calling executeIpmiCommand request function
    res = ipmi::executeIpmiCommand(req);

    // sending the response with headers and payload
    return ipmi::responseSuccess(reqIana, interface, lun, ++netFnReq, cmdReq,
                                 res->cc, res->payload);
}

void dimmLoopPatternDetection(size_t hostId, std::vector<uint8_t> data)
{
    if constexpr (postCodeSize != amdFourBytesPostCode)
    {
        return;
    }

    if (data.size() != amdFourBytesPostCode)
    {
        return;
    }

    /*
    Reference from Meta_BIOS_Requirement_Spec_v0.80
    For AMD platform, the POST code looping pattern format should be:
    (each group has 4 bytes)
    ●Group #0: [DDEE0000]
    ●Group #1: [DDEE] + Total Error Count
    ●Group #2: [DDEE] + Number of Error DIMM
    ●Group #3: [DDEE] + Dimm location
    ●Group #4: [DDEE] + major code
    ●Group #5: [DDEE] + minor code
    */
    std::array<uint8_t, 2> prefix = {data[3], data[2]};

    if (prefix != amdDimmLoopPrefix)
    {
        // Clear all the post code stored before.
        if (dimm::dimmLoops[hostId].startDetect)
        {
            dimm::dimmLoops[hostId].totalErrorCount = 0;
            dimm::dimmLoops[hostId].postCode.clear();

            dimm::dimmLoops[hostId].startDetect = false;
        }
        return;
    }

    // Which means it already got the dimm loop, stop checking again.
    if (dimm::dimmLoops[hostId].gotPattern)
    {
        return;
    }

    constexpr std::array<uint8_t, 4> anchorTag = {0x0, 0x0, 0xEE, 0xDD};
    if (std::ranges::equal(anchorTag, data))
    {
        dimm::dimmLoops[hostId].startDetect = true;
    }
    if (dimm::dimmLoops[hostId].startDetect)
    {
        // The second one is error count
        if (dimm::dimmLoops[hostId].postCode.size() % 6 == 1)
        {
            dimm::dimmLoops[hostId].totalErrorCount = (data[1] << 8) | data[0];
        }

        dimm::dimmLoops[hostId].postCode.push_back(data);

        // Is the last element of dimmloop then stop to detect
        if (dimm::dimmLoops[hostId].postCode.size() ==
            (dimm::dimmLoops[hostId].totalErrorCount * 6))
        {
            // Gets whole pattern success
            dimm::dimmLoops[hostId].gotPattern = true;
        }
    }
}

//----------------------------------------------------------------------
// ipmiOemPostCodeHandler (CMD_OEM_BIC_POST_BUFFER_INFO)
// This Function will handle BIC incoming postcode from multi-host for
// netfn=0x38 and cmd=0x08 or 0x33 send the response back to the sender.
//----------------------------------------------------------------------

ipmi::RspType<IanaType> ipmiOemPostCodeHandler(ipmi::Context::ptr ctx,
                                               IanaType reqIana,
                                               uint8_t dataLen,
                                               std::vector<uint8_t> data)
{
    // creating bus connection
    auto conn = getSdBus();

    auto hostId = findHost(ctx->hostIdx);
    if (!hostId)
    {
        lg2::error("Invalid Host Id received");
        return ipmi::responseInvalidCommand();
    }
    dimmLoopPatternDetection(*hostId, data);

    using postcode_t = std::tuple<uint64_t, std::vector<uint8_t>>;

    std::string dbusObjStr = dbusObj + std::to_string((ctx->hostIdx + 1));

    for (unsigned int index = 0; index < dataLen; index++)
    {
        uint64_t primaryPostCode = static_cast<uint64_t>(data[index]);
        auto postCode = postcode_t(primaryPostCode, {});

        try
        {
            auto method = conn->new_method_call(
                "xyz.openbmc_project.State.Boot.Raw", dbusObjStr.c_str(),
                "org.freedesktop.DBus.Properties", "Set");

            // Adding parameters to method call
            method.append(dbusService, "Value",
                          std::variant<postcode_t>(postCode));

            // Invoke method call function
            auto reply = conn->call(method);
        }

        catch (std::exception& e)
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "post code handler error\n");

            // sending the Error response
            return ipmi::responseResponseError();
        }
    }

    return ipmi::responseSuccess(reqIana);
}

//----------------------------------------------------------------------
// ipmiOemGetBicGpioState (CMD_OEM_GET_BIC_GPIO_STATE)
// This Function will handle BIC GPIO stats for
// netfn=0x38 and cmd=0x03 send the response back to the sender.
//----------------------------------------------------------------------

ipmi::RspType<IanaType, std::vector<uint8_t>>
    ipmiOemGetBicGpioState(ipmi::Context::ptr ctx, std::vector<uint8_t> reqIana)
{
    std::vector<uint8_t> respData;

    if (std::equal(reqIana.begin(), reqIana.end(), iana.begin()) == false)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Invalid IANA number");
        return ipmi::responseInvalidFieldRequest();
    }

    uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;

    if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqIana, respData))
    {
        return ipmi::responseUnspecifiedError();
    }

    std::vector<uint8_t> gpioState;
    IanaType respIana;

    auto r =
        std::ranges::copy_n(respData.begin(), iana.size(), respIana.begin()).in;
    std::copy(r, respData.end(), std::back_inserter(gpioState));

    return ipmi::responseSuccess(respIana, gpioState);
}

//----------------------------------------------------------------------
// ipmiOemSetHostPowerState (CMD_OEM_SET_HOST_POWER_STATE)
// This Function will handle BIC incoming IPMI request for
// setting host current state for netfn=0x38 and cmd=0x0C
// send the response back to the sender.
//----------------------------------------------------------------------

ipmi::RspType<IanaType> ipmiOemSetHostPowerState(ipmi::Context::ptr ctx,
                                                 IanaType reqIana,
                                                 uint8_t status)
{
    std::string targetUnit;

    switch (static_cast<HostPowerState>(status))
    {
        case HostPowerState::HOST_POWER_ON:
            targetUnit = "obmc-host-startmin@.target";
            break;
        case HostPowerState::HOST_POWER_OFF:
            targetUnit = "obmc-host-stop@.target";
            break;
        default:
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "IPMI ipmiOemHostPowerStatus power status error");
            return ipmi::responseUnspecifiedError();
    }

    int mousePos = targetUnit.find('@');
    targetUnit.insert(mousePos + 1, std::to_string(ctx->hostIdx + 1));

    auto conn = getSdBus();
    auto method = conn->new_method_call(systemdService, systemdObjPath,
                                        systemdInterface, "StartUnit");
    method.append(targetUnit);
    method.append("replace");

    try
    {
        conn->call_noreply(method);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "IPMI ipmiOemHostPowerStatus Failed in call method",
            phosphor::logging::entry("ERROR=%s", e.what()));
        return ipmi::responseUnspecifiedError();
    }

    return ipmi::responseSuccess(reqIana);
}

//----------------------------------------------------------------------
// ipmiOemGetBiosFlashSize (CMD_OEM_GET_FLASH_SIZE)
// This Function will return the bios flash size
// netfn=0x38 and cmd=0x19 send the response back to the sender.
//----------------------------------------------------------------------

ipmi::RspType<IanaType, flashSize>
    ipmiOemGetBiosFlashSize(ipmi::Context::ptr ctx, IanaType ianaReq,
                            uint8_t target)
{
    if (iana != ianaReq)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Invalid IANA ID length received");
        return ipmi::responseReqDataLenInvalid();
    }

    std::vector<uint8_t> respData;
    uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;
    std::vector<uint8_t> reqData(ianaReq.begin(), ianaReq.end());
    reqData.emplace_back(target);

    if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
    {
        return ipmi::responseUnspecifiedError();
    }

    if (respData.size() != flashSizeRespLen)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Invalid Response Data length received");
        return ipmi::responseReqDataLenInvalid();
    }

    IanaType ianaResp;
    std::copy_n(respData.begin(), ianaResp.size(), ianaResp.begin());

    if (iana != ianaResp)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Invalid IANA ID received");
        return ipmi::responseInvalidCommand();
    }

    flashSize flashResp;
    std::vector<uint8_t>::iterator respDataIter = respData.begin();
    std::advance(respDataIter, ianaResp.size());
    std::copy_n(respDataIter, flashResp.size(), flashResp.begin());

    // sending the success response.
    return ipmi::responseSuccess(ianaResp, flashResp);
}

//----------------------------------------------------------------------
// ipmiOemClearCmos (CMD_OEM_CLEAR_CMOS)
// This Function will clear the CMOS.
// netfn=0x38 and cmd=0x25
//----------------------------------------------------------------------
ipmi::RspType<IanaType> ipmiOemClearCmos(ipmi::Context::ptr ctx,
                                         IanaType ianaReq)
{
    if (iana != ianaReq)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Invalid request of IANA ID length received");
        return ipmi::responseReqDataLenInvalid();
    }

    uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2;

    std::vector<uint8_t> respData;
    std::vector<uint8_t> reqData(ianaReq.begin(), ianaReq.end());

    if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData))
    {
        return ipmi::responseUnspecifiedError();
    }

    if (respData.size() != iana.size())
    {
        return ipmi::responseReqDataLenInvalid();
    }

    IanaType resp;
    std::copy_n(respData.begin(), resp.size(), resp.begin());

    if (iana != resp)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Invalid response of IANA ID received");
        return ipmi::responseUnspecifiedError();
    }

    // sending the success response.
    return ipmi::responseSuccess(resp);
}

[[maybe_unused]] static void registerBICFunctions(void)
{
    phosphor::logging::log<phosphor::logging::level::INFO>(
        "Registering BIC commands");

    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
                          static_cast<Cmd>(fb_bic_cmds::CMD_OEM_BIC_INFO),
                          ipmi::Privilege::User, ipmiOemBicHandler);
    ipmi::registerHandler(
        ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
        static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SEND_POST_BUFFER_TO_BMC),
        ipmi::Privilege::User, ipmiOemPostCodeHandler);
    ipmi::registerHandler(
        ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
        static_cast<Cmd>(fb_bic_cmds::CMD_OEM_1S_4BYTE_POST_BUF),
        ipmi::Privilege::User, ipmiOemPostCodeHandler);
    ipmi::registerHandler(
        ipmi::prioOemBase, ipmi::netFnOemFive,
        static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_BIC_GPIO_STATE),
        ipmi::Privilege::User, ipmiOemGetBicGpioState);
    ipmi::registerHandler(
        ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
        static_cast<Cmd>(fb_bic_cmds::CMD_OEM_SET_HOST_POWER_STATE),
        ipmi::Privilege::User, ipmiOemSetHostPowerState);
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
                          static_cast<Cmd>(fb_bic_cmds::CMD_OEM_GET_FLASH_SIZE),
                          ipmi::Privilege::User, ipmiOemGetBiosFlashSize);
    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemFive,
                          static_cast<Cmd>(fb_bic_cmds::CMD_OEM_CLEAR_CMOS),
                          ipmi::Privilege::User, ipmiOemClearCmos);
    return;
}

} // namespace ipmi
