// Copyright 2024 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 "hoth_util_impl.hpp"

#include <google3/g_ec_commands.h>
#include <google3/host_commands.h>

#include <boost/endian/conversion.hpp>
#include <phosphor-logging/log.hpp>
#include <stdplus/raw.hpp>
#include <xyz/openbmc_project/Control/Hoth/error.hpp>

#include <cstdint>
#include <limits>
#include <memory>
#include <span>
#include <vector>

using CommandFailure =
    sdbusplus::xyz::openbmc_project::Control::Hoth::Error::CommandFailure;
using ResponseFailure =
    sdbusplus::xyz::openbmc_project::Control::Hoth::Error::ResponseFailure;

namespace ipmi_hoth
{
namespace internal
{

using namespace phosphor::logging;

std::vector<uint8_t>
    HothUtilImpl::wrapECSKMHSSRequest(std::span<const uint8_t> request)
{
    // Populate EC request header based on the request
    g_ec_host_request skmHssHeader = {
        /*struct_version*/ G_EC_HOST_REQUEST_VERSION,
        /*checksum*/ 0,
        /*command*/ G_EC_PRIVATE_HOST_COMMAND_VALUE(EC_PRV_CMD_HOTH_SKM_HSS),
        /*command_version*/ 0,
        /*reserved*/ 0,
        /*data_len*/ static_cast<uint16_t>(request.size())};

    boost::endian::native_to_little_inplace(skmHssHeader);
    skmHssHeader.checksum -=
        calculateChecksum(stdplus::raw::asSpan<uint8_t>(skmHssHeader), request);

    // Concatenate the request header and the request into one uint8_t vector to
    // be sent to EC
    const auto requestHeaderPtr = reinterpret_cast<uint8_t*>(&skmHssHeader);
    std::vector<uint8_t> hothCommand(requestHeaderPtr,
                                     requestHeaderPtr + sizeof(skmHssHeader));
    hothCommand.insert(hothCommand.end(), request.begin(), request.end());
    return hothCommand;
}

std::vector<uint8_t> HothUtilImpl::readSKMHSS(uint32_t slot)
{
    struct ec_request_skm_hss request = {};
    request.operation = SKM_HSS_READ;
    request.slot = slot;
    return wrapECSKMHSSRequest(stdplus::raw::asSpan<const uint8_t>(request));
}

std::vector<uint8_t>
    HothUtilImpl::writeSKMHSS(uint32_t slot, std::span<const uint8_t> data)
{
    if (data.empty() || data.size() > SKM_HSS_STRUCT_SIZE)
    {
        log<level::ERR>("Bad HSS payload size",
                        entry("REQ_SIZE=%lu SKM_HSS_SIZE=%lu",
                              static_cast<unsigned long>(data.size()),
                              static_cast<unsigned long>(SKM_HSS_STRUCT_SIZE)));
        throw CommandFailure();
    }
    struct ec_request_skm_hss request = {};
    request.operation = SKM_HSS_WRITE;
    request.slot = slot;
    std::memcpy(request.payload.data, data.data(), data.size());
    return wrapECSKMHSSRequest(stdplus::raw::asSpan<const uint8_t>(request));
}

std::vector<uint8_t> HothUtilImpl::deleteSKMHSS(uint32_t slot)
{
    struct ec_request_skm_hss request = {};
    request.operation = SKM_HSS_DELETE;
    request.slot = slot;
    return wrapECSKMHSSRequest(stdplus::raw::asSpan<const uint8_t>(request));
}

std::span<const uint8_t>
    HothUtilImpl::payloadECResponse(std::span<const uint8_t> rsp)
{
    g_ec_host_response header{};

    if (rsp.size() < sizeof(header))
    {
        log<level::ERR>("Response is too short",
                        entry("LENGTH=%d", rsp.size()));
        throw ResponseFailure();
    }

    std::memcpy(&header, rsp.data(), sizeof(header));
    boost::endian::native_to_little_inplace(header);

    if (header.struct_version != G_EC_HOST_RESPONSE_VERSION)
    {
        log<level::ERR>(
            "Unsupported stuct_version in response",
            entry("VERSION=%d", static_cast<uint8_t>(header.struct_version)));
        throw ResponseFailure();
    }

    if (header.result != EC_RES_SUCCESS && header.result != EC_RES_UNAVAILABLE)
    {
        log<level::ERR>(
            "Unexpected return code",
            entry("RESULT=%d", static_cast<uint16_t>(header.result)));
        throw ResponseFailure();
    }

    return rsp.last(rsp.size() - sizeof(header));
}

} // namespace internal

} // namespace ipmi_hoth
