/*
 * Copyright 2018 Google Inc.
 *
 * 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 "blob_handler.hpp"

#include "blob_errors.hpp"
#include "crc.hpp"
#include "ipmi_errors.hpp"
#include "ipmi_interface.hpp"

#include <array>
#include <cinttypes>
#include <cstring>
#include <iterator>
#include <limits>
#include <memory>

namespace ipmiblob
{

namespace
{
const std::array<std::uint8_t, 3> ipmiPhosphorOen = {0xcf, 0xc2, 0x00};
}

std::unique_ptr<BlobInterface> BlobHandler::CreateBlobHandler(
    std::unique_ptr<IpmiInterface> ipmi)
{
    return std::make_unique<BlobHandler>(std::move(ipmi));
}

std::vector<std::uint8_t> BlobHandler::sendIpmiPayload(
    BlobOEMCommands command, const std::vector<std::uint8_t>& payload)
{
    std::vector<std::uint8_t> request, reply, bytes;

    std::copy(ipmiPhosphorOen.begin(), ipmiPhosphorOen.end(),
              std::back_inserter(request));
    request.push_back(static_cast<std::uint8_t>(command));

    if (!payload.empty())
    {
        /* Grow the vector to hold the bytes. */
        request.reserve(request.size() + sizeof(std::uint16_t));

        /* CRC required. */
        std::uint16_t crc = generateCrc(payload);
        auto src = reinterpret_cast<const std::uint8_t*>(&crc);

        std::copy(src, src + sizeof(crc), std::back_inserter(request));

        /* Copy the payload. */
        std::copy(payload.begin(), payload.end(), std::back_inserter(request));
    }

    try
    {
        reply = ipmi->sendPacket(ipmiOEMNetFn, ipmiOEMBlobCmd, request);
    }
    catch (const IpmiException& e)
    {
        throw BlobException(e.what());
    }

    /* IPMI_CC was OK, and it returned no bytes, so let's be happy with that for
     * now.
     */
    if (reply.empty())
    {
        return reply;
    }

    /* This cannot be a response because it's smaller than the smallest
     * response.
     */
    if (reply.size() < ipmiPhosphorOen.size())
    {
        throw BlobException("Invalid response length");
    }

    /* Verify the OEN. */
    if (std::memcmp(ipmiPhosphorOen.data(), reply.data(),
                    ipmiPhosphorOen.size()) != 0)
    {
        throw BlobException("Invalid OEN received");
    }

    /* In this case there was no data, as there was no CRC. */
    std::size_t headerSize = ipmiPhosphorOen.size() + sizeof(std::uint16_t);
    if (reply.size() < headerSize)
    {
        return {};
    }

    /* Validate CRC. */
    std::uint16_t crc;
    auto ptr = reinterpret_cast<std::uint8_t*>(&crc);
    std::memcpy(ptr, &reply[ipmiPhosphorOen.size()], sizeof(crc));

    bytes.insert(bytes.begin(), reply.begin() + headerSize, reply.end());

    auto computed = generateCrc(bytes);
    if (crc != computed)
    {
        std::fprintf(stderr, "Invalid CRC, received: 0x%x, computed: 0x%x\n",
                     crc, computed);
        throw BlobException("Invalid CRC on received data.");
    }

    return bytes;
}

int BlobHandler::getBlobCount()
{
    std::uint32_t count;
    try
    {
        auto resp = sendIpmiPayload(BlobOEMCommands::bmcBlobGetCount, {});
        if (resp.size() != sizeof(count))
        {
            return 0;
        }

        /* LE to LE (need to make this portable as some point. */
        std::memcpy(&count, resp.data(), sizeof(count));
    }
    catch (const BlobException& b)
    {
        return 0;
    }

    return count;
}

std::string BlobHandler::enumerateBlob(std::uint32_t index)
{
    std::vector<std::uint8_t> payload;
    auto data = reinterpret_cast<const std::uint8_t*>(&index);

    std::copy(data, data + sizeof(std::uint32_t), std::back_inserter(payload));

    try
    {
        auto resp = sendIpmiPayload(BlobOEMCommands::bmcBlobEnumerate, payload);
        return (resp.empty()) ? ""
                              : std::string(&resp[0], &resp[resp.size() - 1]);
    }
    catch (const BlobException& b)
    {
        return "";
    }
}

void BlobHandler::commit(std::uint16_t session,
                         const std::vector<std::uint8_t>& bytes)
{
    std::vector<std::uint8_t> request;
    auto addrSession = reinterpret_cast<const std::uint8_t*>(&session);
    std::copy(addrSession, addrSession + sizeof(session),
              std::back_inserter(request));

    /* You have one byte to describe the length. */
    if (bytes.size() > std::numeric_limits<std::uint8_t>::max())
    {
        throw BlobException("Commit data length greater than 8-bit limit\n");
    }

    std::uint8_t length = static_cast<std::uint8_t>(bytes.size());
    auto addrLength = reinterpret_cast<const std::uint8_t*>(&length);
    std::copy(addrLength, addrLength + sizeof(length),
              std::back_inserter(request));

    std::copy(bytes.begin(), bytes.end(), std::back_inserter(request));

    sendIpmiPayload(BlobOEMCommands::bmcBlobCommit, request);
}

void BlobHandler::writeGeneric(BlobOEMCommands command, std::uint16_t session,
                               std::uint32_t offset,
                               const std::vector<std::uint8_t>& bytes)
{
    std::vector<std::uint8_t> payload;

    payload.reserve(
        sizeof(std::uint16_t) + sizeof(std::uint32_t) + bytes.size());

    auto data = reinterpret_cast<const std::uint8_t*>(&session);
    std::copy(data, data + sizeof(std::uint16_t), std::back_inserter(payload));

    data = reinterpret_cast<const std::uint8_t*>(&offset);
    std::copy(data, data + sizeof(std::uint32_t), std::back_inserter(payload));

    std::copy(bytes.begin(), bytes.end(), std::back_inserter(payload));

    sendIpmiPayload(command, payload);
}

void BlobHandler::writeMeta(std::uint16_t session, std::uint32_t offset,
                            const std::vector<std::uint8_t>& bytes)
{
    writeGeneric(BlobOEMCommands::bmcBlobWriteMeta, session, offset, bytes);
}

void BlobHandler::writeBytes(std::uint16_t session, std::uint32_t offset,
                             const std::vector<std::uint8_t>& bytes)
{
    writeGeneric(BlobOEMCommands::bmcBlobWrite, session, offset, bytes);
}

std::vector<std::string> BlobHandler::getBlobList()
{
    std::vector<std::string> list;
    int blobCount = getBlobCount();

    for (int i = 0; i < blobCount; i++)
    {
        auto name = enumerateBlob(i);
        /* Currently ignore failures. */
        if (!name.empty())
        {
            list.push_back(name);
        }
    }

    return list;
}

StatResponse BlobHandler::statGeneric(BlobOEMCommands command,
                                      const std::vector<std::uint8_t>& request)
{
    StatResponse meta;
    static constexpr std::size_t blobStateSize = sizeof(meta.blob_state);
    static constexpr std::size_t metaSize = sizeof(meta.size);
    static constexpr std::size_t metaOffset = blobStateSize + metaSize;
    static constexpr std::size_t minRespSize =
        metaOffset + sizeof(std::uint8_t);
    std::vector<std::uint8_t> resp;

    try
    {
        resp = sendIpmiPayload(command, request);
    }
    catch (const BlobException& b)
    {
        throw;
    }

    // Avoid out of bounds memcpy below
    if (resp.size() < minRespSize)
    {
        std::fprintf(stderr,
                     "Invalid response length, Got %zu which is less than "
                     "minRespSize %zu\n",
                     resp.size(), minRespSize);
        throw BlobException("Invalid response length");
    }

    std::memcpy(&meta.blob_state, &resp[0], blobStateSize);
    std::memcpy(&meta.size, &resp[blobStateSize], metaSize);
    std::uint8_t len = resp[metaOffset];

    auto metaDataLength = resp.size() - minRespSize;
    if (metaDataLength != len)
    {
        std::fprintf(stderr,
                     "Metadata length did not match actual length, Got %zu "
                     "which does not equal expected length %" PRIu8 "\n",
                     metaDataLength, len);
        throw BlobException("Metadata length did not match actual length");
    }

    if (len > 0)
    {
        meta.metadata.resize(len);
        std::copy(resp.begin() + minRespSize, resp.end(),
                  meta.metadata.begin());
    }

    return meta;
}

StatResponse BlobHandler::getStat(const std::string& id)
{
    std::vector<std::uint8_t> name;
    std::copy(id.begin(), id.end(), std::back_inserter(name));
    name.push_back(0x00); /* need to add nul-terminator. */

    return statGeneric(BlobOEMCommands::bmcBlobStat, name);
}

StatResponse BlobHandler::getStat(std::uint16_t session)
{
    std::vector<std::uint8_t> request;
    auto addrSession = reinterpret_cast<const std::uint8_t*>(&session);
    std::copy(addrSession, addrSession + sizeof(session),
              std::back_inserter(request));

    return statGeneric(BlobOEMCommands::bmcBlobSessionStat, request);
}

std::uint16_t BlobHandler::openBlob(const std::string& id,
                                    std::uint16_t handlerFlags)
{
    std::uint16_t session;
    std::vector<std::uint8_t> request, resp;
    auto addrFlags = reinterpret_cast<const std::uint8_t*>(&handlerFlags);

    std::copy(addrFlags, addrFlags + sizeof(handlerFlags),
              std::back_inserter(request));
    std::copy(id.begin(), id.end(), std::back_inserter(request));
    request.push_back(0x00); /* need to add nul-terminator. */

    try
    {
        resp = sendIpmiPayload(BlobOEMCommands::bmcBlobOpen, request);
    }
    catch (const BlobException& b)
    {
        throw;
    }

    if (resp.size() != sizeof(session))
    {
        throw BlobException("Did not receive session.");
    }

    std::memcpy(&session, resp.data(), sizeof(session));
    return session;
}

void BlobHandler::closeBlob(std::uint16_t session)
{
    std::vector<std::uint8_t> request;
    auto addrSession = reinterpret_cast<const std::uint8_t*>(&session);
    std::copy(addrSession, addrSession + sizeof(session),
              std::back_inserter(request));

    try
    {
        sendIpmiPayload(BlobOEMCommands::bmcBlobClose, request);
    }
    catch (const BlobException& b)
    {
        std::fprintf(stderr, "Received failure on close: %s\n", b.what());
    }
}

bool BlobHandler::deleteBlob(const std::string& id)
{
    std::vector<std::uint8_t> name;
    std::copy(id.begin(), id.end(), std::back_inserter(name));
    name.push_back(0x00); /* need to add nul-terminator. */

    try
    {
        sendIpmiPayload(BlobOEMCommands::bmcBlobDelete, name);
        return true;
    }
    catch (const BlobException& b)
    {
        std::fprintf(stderr, "Received failure on delete: %s\n", b.what());
    }
    return false;
}

std::vector<std::uint8_t> BlobHandler::readBytes(
    std::uint16_t session, std::uint32_t offset, std::uint32_t length)
{
    std::vector<std::uint8_t> payload;

    payload.reserve(
        sizeof(std::uint16_t) + sizeof(std::uint32_t) + sizeof(std::uint32_t));

    auto data = reinterpret_cast<const std::uint8_t*>(&session);
    std::copy(data, data + sizeof(std::uint16_t), std::back_inserter(payload));

    data = reinterpret_cast<const std::uint8_t*>(&offset);
    std::copy(data, data + sizeof(std::uint32_t), std::back_inserter(payload));

    data = reinterpret_cast<const std::uint8_t*>(&length);
    std::copy(data, data + sizeof(std::uint32_t), std::back_inserter(payload));

    return sendIpmiPayload(BlobOEMCommands::bmcBlobRead, payload);
}

} // namespace ipmiblob
