#include "bios.hpp"

#include "libpldmresponder/utils.hpp"
#include "registration.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

#include <array>
#include <boost/crc.hpp>
#include <chrono>
#include <ctime>
#include <iostream>
#include <numeric>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <stdexcept>
#include <string>
#include <variant>
#include <vector>

using namespace pldm::responder::bios;
using namespace bios_parser;
using namespace bios_parser::bios_enum;

namespace pldm
{

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using EpochTimeUS = uint64_t;
using BIOSTableRow = std::vector<uint8_t>;

constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
constexpr auto padChksumMax = 7;

namespace responder
{

namespace utils
{

void epochToBCDTime(uint64_t timeSec, uint8_t& seconds, uint8_t& minutes,
                    uint8_t& hours, uint8_t& day, uint8_t& month,
                    uint16_t& year)
{
    auto t = time_t(timeSec);
    auto time = localtime(&t);

    seconds = decimalToBcd(time->tm_sec);
    minutes = decimalToBcd(time->tm_min);
    hours = decimalToBcd(time->tm_hour);
    day = decimalToBcd(time->tm_mday);
    month =
        decimalToBcd(time->tm_mon + 1); // The number of months in the range
                                        // 0 to 11.PLDM expects range 1 to 12
    year = decimalToBcd(time->tm_year + 1900); // The number of years since 1900
}

} // namespace utils

Response getDateTime(const pldm_msg* request, size_t payloadLength)
{
    uint8_t seconds = 0;
    uint8_t minutes = 0;
    uint8_t hours = 0;
    uint8_t day = 0;
    uint8_t month = 0;
    uint16_t year = 0;

    constexpr auto timeInterface = "xyz.openbmc_project.Time.EpochTime";
    constexpr auto bmcTimePath = "/xyz/openbmc_project/time/bmc";
    Response response(sizeof(pldm_msg_hdr) + PLDM_GET_DATE_TIME_RESP_BYTES, 0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
    std::variant<EpochTimeUS> value;

    auto bus = sdbusplus::bus::new_default();
    try
    {
        auto service = getService(bus, bmcTimePath, timeInterface);

        auto method = bus.new_method_call(service.c_str(), bmcTimePath,
                                          dbusProperties, "Get");
        method.append(timeInterface, "Elapsed");

        auto reply = bus.call(method);
        reply.read(value);
    }

    catch (std::exception& e)
    {
        log<level::ERR>("Error getting time", entry("PATH=%s", bmcTimePath),
                        entry("TIME INTERACE=%s", timeInterface));

        encode_get_date_time_resp(request->hdr.instance_id, PLDM_ERROR, seconds,
                                  minutes, hours, day, month, year,
                                  responsePtr);
        return response;
    }

    uint64_t timeUsec = std::get<EpochTimeUS>(value);

    uint64_t timeSec = std::chrono::duration_cast<std::chrono::seconds>(
                           std::chrono::microseconds(timeUsec))
                           .count();

    utils::epochToBCDTime(timeSec, seconds, minutes, hours, day, month, year);

    encode_get_date_time_resp(request->hdr.instance_id, PLDM_SUCCESS, seconds,
                              minutes, hours, day, month, year, responsePtr);
    return response;
}

/** @brief Generate the next attribute handle
 *
 *  @return - uint16_t - next attribute handle
 */
AttributeHandle nextAttributeHandle()
{
    static AttributeHandle attrHdl = 0;
    return attrHdl++;
}

/** @brief Generate the next string handle
 *  *
 *  @return - uint16_t - next string handle
 */
StringHandle nextStringHandle()
{
    static StringHandle strHdl = 0;
    return strHdl++;
}

/** @brief Construct the BIOS string table
 *
 *  @param[in] BIOSStringTable - the string table
 *  @param[in] transferHandle - transfer handle to identify part of transfer
 *  @param[in] transferOpFlag - flag to indicate which part of data being
 * transferred
 *  @param[in] instanceID - instance ID to identify the command
 *  @param[in] biosJsonDir - path where the BIOS json files are present
 */
Response getBIOSStringTable(BIOSTable& BIOSStringTable, uint32_t transferHandle,
                            uint8_t transferOpFlag, uint8_t instanceID,
                            const char* biosJsonDir)
{
    Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
                      0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());

    if (BIOSStringTable.isEmpty())
    { // no persisted table, constructing fresh table and file
        auto biosStrings = bios_parser::getStrings(biosJsonDir);
        std::sort(biosStrings.begin(), biosStrings.end());
        // remove all duplicate strings received from bios json
        biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
                          biosStrings.end());
        size_t allStringsLen =
            std::accumulate(biosStrings.begin(), biosStrings.end(), 0,
                            [](size_t sum, const std::string& elem) {
                                return sum + elem.size();
                            });
        size_t sizeWithoutPad =
            allStringsLen +
            (biosStrings.size() * (sizeof(pldm_bios_string_table_entry) - 1));
        uint8_t padSize = utils::getNumPadBytes(sizeWithoutPad);
        uint32_t stringTableSize{};
        uint32_t checkSum;
        if (biosStrings.size())
        {
            stringTableSize = sizeWithoutPad + padSize + sizeof(checkSum);
        }
        Table stringTable(
            stringTableSize,
            0); // initializing to 0 so that pad will be automatically added
        auto tablePtr = reinterpret_cast<uint8_t*>(stringTable.data());
        for (const auto& elem : biosStrings)
        {
            auto stringPtr =
                reinterpret_cast<struct pldm_bios_string_table_entry*>(
                    tablePtr);

            stringPtr->string_handle = nextStringHandle();
            stringPtr->string_length = elem.length();
            memcpy(stringPtr->name, elem.c_str(), elem.length());
            tablePtr += sizeof(stringPtr->string_handle) +
                        sizeof(stringPtr->string_length);
            tablePtr += elem.length();
        }
        tablePtr += padSize;

        if (stringTableSize)
        {
            // compute checksum
            boost::crc_32_type result;
            result.process_bytes(stringTable.data(), stringTableSize);
            checkSum = result.checksum();
            std::copy_n(reinterpret_cast<uint8_t*>(&checkSum), sizeof(checkSum),
                        stringTable.data() + sizeWithoutPad + padSize);
            BIOSStringTable.store(stringTable);
        }

        response.resize(sizeof(pldm_msg_hdr) +
                            PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
                            stringTableSize,
                        0);
        responsePtr = reinterpret_cast<pldm_msg*>(response.data());
        size_t respPayloadLength = response.size();
        uint32_t nxtTransferHandle = 0;
        uint8_t transferFlag = PLDM_START_AND_END;
        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS, nxtTransferHandle,
                                   transferFlag, stringTable.data(),
                                   respPayloadLength, responsePtr);
    }
    else
    { // persisted table present, constructing response
        size_t respPayloadLength = response.size();
        uint32_t nxtTransferHandle = 0;
        uint8_t transferFlag = PLDM_START_AND_END;
        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS, nxtTransferHandle,
                                   transferFlag, nullptr, respPayloadLength,
                                   responsePtr); // filling up the header here
        BIOSStringTable.load(response);
    }

    return response;
}

/** @brief Find the string handle from the BIOS string table given the name
 *
 *  @param[in] name - name of the BIOS string
 *  @param[in] BIOSStringTable - the string table
 *  @return - uint16_t - handle of the string
 */
StringHandle findStringHandle(const std::string& name,
                              const BIOSTable& BIOSStringTable)
{
    StringHandle hdl{};
    Response response;
    BIOSStringTable.load(response);

    auto tableData = response.data();
    size_t tableLen = response.size();
    auto tableEntry =
        reinterpret_cast<struct pldm_bios_string_table_entry*>(response.data());
    while (1)
    {
        hdl = tableEntry->string_handle;
        uint16_t len = tableEntry->string_length;
        if (memcmp(name.c_str(), tableEntry->name, len) == 0)
        {
            break;
        }
        tableData += (sizeof(struct pldm_bios_string_table_entry) - 1) + len;

        if (std::distance(tableData, response.data() + tableLen) <=
            padChksumMax)
        {
            log<level::ERR>("Reached end of BIOS string table,did not find the "
                            "handle for the string",
                            entry("STRING=%s", name.c_str()));
            elog<InternalFailure>();
            break;
        }

        tableEntry =
            reinterpret_cast<struct pldm_bios_string_table_entry*>(tableData);
    }
    return hdl;
}

/** @brief Find the string name from the BIOS string table for a string handle
 *
 *  @param[in] stringHdl - string handle
 *  @param[in] BIOSStringTable - the string table
 *
 *  @return - std::string - name of the corresponding BIOS string
 */
std::string findStringName(StringHandle stringHdl,
                           const BIOSTable& BIOSStringTable)
{
    std::string name;
    Response response;
    BIOSStringTable.load(response);

    auto tableData = response.data();
    size_t tableLen = response.size();
    auto tableEntry =
        reinterpret_cast<struct pldm_bios_string_table_entry*>(response.data());
    while (1)
    {
        StringHandle currHdl = tableEntry->string_handle;
        uint16_t len = tableEntry->string_length;
        if (currHdl == stringHdl)
        {
            name.resize(len);
            memcpy(name.data(), tableEntry->name, len);
            break;
        }
        tableData += (sizeof(struct pldm_bios_string_table_entry) - 1) + len;

        if (std::distance(tableData, response.data() + tableLen) <=
            padChksumMax)
        {
            log<level::ERR>("Reached end of BIOS string table,did not find "
                            "string name for handle",
                            entry("STRING_HANDLE=%d", stringHdl));
            break;
        }

        tableEntry =
            reinterpret_cast<struct pldm_bios_string_table_entry*>(tableData);
    }
    return name;
}

namespace bios_type_enum
{

/** @brief Find the indices  into the array of the possible values of string
 *  handles for the current values.This is used in attribute value table
 *
 *  @param[in] possiVals - vector of string handles comprising all the possible
 *                         values for an attribute
 *  @param[in] currVals - vector of strings comprising all current values
 *                        for an attribute
 *  @param[in] BIOSStringTable - the string table
 *
 *  @return - std::vector<uint8_t> - indices into the array of the possible
 *                                   values of string handles
 */
std::vector<uint8_t> findStrIndices(PossibleValuesByHandle possiVals,
                                    CurrentValues currVals,
                                    const BIOSTable& BIOSStringTable)
{
    std::vector<uint8_t> stringIndices;

    for (const auto& currVal : currVals)
    {
        StringHandle curHdl;
        try
        {
            curHdl = findStringHandle(currVal, BIOSStringTable);
        }
        catch (InternalFailure& e)
        {
            log<level::ERR>("Exception fetching handle for the string",
                            entry("STRING=%s", currVal.c_str()));
            continue;
        }

        uint8_t i = 0;
        for (auto possiHdl : possiVals)
        {
            if (possiHdl == curHdl)
            {
                stringIndices.push_back(i);
                break;
            }
            i++;
        }
    }
    return stringIndices;
}

/** @brief Find the indices into the array of the possible values of string
 *  handles for the default values. This is used in attribute table
 *
 *  @param[in] possiVals - vector of strings comprising all the possible values
 *                         for an attribute
 *  @param[in] defVals - vector of strings comprising all the default values
 *                       for an attribute
 *  @return - std::vector<uint8_t> - indices into the array of the possible
 *                                   values of string
 */
std::vector<uint8_t> findDefaultValHandle(const PossibleValues& possiVals,
                                          const DefaultValues& defVals)
{
    std::vector<uint8_t> defHdls;
    for (const auto& defs : defVals)
    {
        auto index = std::lower_bound(possiVals.begin(), possiVals.end(), defs);
        if (index != possiVals.end())
        {
            defHdls.push_back(index - possiVals.begin());
        }
    }

    return defHdls;
}

/** @brief Construct the attibute table for BIOS type Enumeration and
 *         Enumeration ReadOnly
 *  @param[in] BIOSStringTable - the string table
 *  @param[in] biosJsonDir - path where the BIOS json files are present
 *
 *  @return - Table - the attribute eenumeration table
 */
Table constructAttrTable(const BIOSTable& BIOSStringTable,
                         const char* biosJsonDir)
{
    setupValueLookup(biosJsonDir);
    const auto& attributeMap = getValues();
    Table attributeTable;
    StringHandle strHandle;

    for (const auto& [key, value] : attributeMap)
    {
        try
        {
            strHandle = findStringHandle(key, BIOSStringTable);
        }
        catch (InternalFailure& e)
        {
            log<level::ERR>("Could not find handle for BIOS string",
                            entry("ATTRIBUTE=%s", key.c_str()));
            continue;
        }
        uint8_t typeOfAttr = (std::get<0>(value))
                                 ? PLDM_BIOS_ENUMERATION_READ_ONLY
                                 : PLDM_BIOS_ENUMERATION;
        PossibleValues possiVals = std::get<1>(value);
        DefaultValues defVals = std::get<2>(value);
        // both the possible and default values are stored in sorted manner to
        // ease in fetching back/comparison
        std::sort(possiVals.begin(), possiVals.end());
        std::sort(defVals.begin(), defVals.end());

        std::vector<StringHandle> possiValsByHdl;
        for (const auto& elem : possiVals)
        {
            try
            {
                auto hdl = findStringHandle(elem, BIOSStringTable);
                possiValsByHdl.push_back(std::move(hdl));
            }
            catch (InternalFailure& e)
            {
                log<level::ERR>("Could not find handle for BIOS string",
                                entry("STRING=%s", elem.c_str()));
                continue;
            }
        }
        auto defValsByHdl = findDefaultValHandle(possiVals, defVals);

        BIOSTableRow enumAttrTable(
            (sizeof(struct pldm_bios_attr_table_entry) - 1) + sizeof(uint8_t) +
                possiValsByHdl.size() * sizeof(uint16_t) + sizeof(uint8_t) +
                defValsByHdl.size() * sizeof(uint8_t),
            0);
        BIOSTableRow::iterator it = enumAttrTable.begin();
        auto attrPtr = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
            enumAttrTable.data());
        attrPtr->attr_handle = nextAttributeHandle();
        attrPtr->attr_type = typeOfAttr;
        attrPtr->string_handle = std::move(strHandle);
        std::advance(it, (sizeof(struct pldm_bios_attr_table_entry) - 1));
        uint8_t numPossibleVals = possiValsByHdl.size();
        std::copy_n(&numPossibleVals, sizeof(numPossibleVals), it);
        std::advance(it, sizeof(numPossibleVals));
        std::copy_n(reinterpret_cast<uint8_t*>(possiValsByHdl.data()),
                    sizeof(uint16_t) * possiValsByHdl.size(), it);
        std::advance(
            it, sizeof(uint16_t) *
                    possiValsByHdl.size()); // possible val handle is uint16_t
        uint8_t numDefaultVals = defValsByHdl.size();
        std::copy_n(&numDefaultVals, sizeof(numDefaultVals), it);
        std::advance(it, sizeof(numDefaultVals));
        std::copy(defValsByHdl.begin(), defValsByHdl.end(), it);
        std::advance(it, defValsByHdl.size());

        std::move(enumAttrTable.begin(), enumAttrTable.end(),
                  std::back_inserter(attributeTable));
    }

    return attributeTable;
}

/** @brief Construct the attibute value table for BIOS type Enumeration and
 *  Enumeration ReadOnly
 *
 *  @param[in] BIOSAttributeTable - the attribute table
 *  @param[in] BIOSStringTable - the string table
 *
 *  @return - Table - the attribute value table
 */
Table constructAttrValueTable(const BIOSTable& BIOSAttributeTable,
                              const BIOSTable& BIOSStringTable)
{
    Table attributeValueTable;
    Response response;
    BIOSAttributeTable.load(response);

    auto tableData = response.data();
    size_t tableLen = response.size();
    auto attrPtr =
        reinterpret_cast<struct pldm_bios_attr_table_entry*>(response.data());

    while (1)
    {
        uint16_t attrHdl = attrPtr->attr_handle;
        uint8_t attrType = attrPtr->attr_type;
        uint16_t stringHdl = attrPtr->string_handle;
        tableData += (sizeof(struct pldm_bios_attr_table_entry) - 1);
        uint8_t numPossiVals = *tableData;
        tableData++; // pass number of possible values
        PossibleValuesByHandle possiValsByHdl(numPossiVals, 0);
        memcpy(possiValsByHdl.data(), tableData,
               sizeof(uint16_t) * numPossiVals);
        tableData += sizeof(uint16_t) * numPossiVals;
        uint8_t numDefVals = *tableData;
        tableData++;             // pass number of def vals
        tableData += numDefVals; // pass all the def val indices

        auto attrName = findStringName(stringHdl, BIOSStringTable);
        if (attrName.empty())
        {
            if (std::distance(tableData, response.data() + tableLen) <=
                padChksumMax)
            {
                log<level::ERR>("Did not find string name for handle",
                                entry("STRING_HANDLE=%d", stringHdl));
                return attributeValueTable;
            }
            attrPtr =
                reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
            continue;
        }
        CurrentValues currVals;
        try
        {
            currVals = getAttrValue(attrName);
        }
        catch (const std::exception& e)
        {
            log<level::ERR>(
                "constructAttrValueTable returned error for attribute",
                entry("NAME=%s", attrName.c_str()),
                entry("ERROR=%s", e.what()));
            if (std::distance(tableData, response.data() + tableLen) <=
                padChksumMax)
            {
                return attributeValueTable;
            }

            attrPtr =
                reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
            continue;
        }
        // sorting since the possible values are stored in sorted way
        std::sort(currVals.begin(), currVals.end());
        auto currValStrIndices =
            findStrIndices(possiValsByHdl, currVals, BIOSStringTable);
        // number of current values equals to the number of string handles
        // received not the number of strings received from getAttrValue
        uint8_t numCurrVals = currValStrIndices.size();

        BIOSTableRow enumAttrValTable(
            (sizeof(struct pldm_bios_attr_val_table_entry) - 1) +
                sizeof(uint8_t) + numCurrVals * sizeof(uint8_t),
            0);
        BIOSTableRow::iterator it = enumAttrValTable.begin();
        auto attrValPtr =
            reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
                enumAttrValTable.data());
        attrValPtr->attr_handle = attrHdl;
        attrValPtr->attr_type = attrType;
        std::advance(it, (sizeof(pldm_bios_attr_val_table_entry) - 1));
        std::copy_n(&numCurrVals, sizeof(numCurrVals), it);
        std::advance(it, sizeof(numCurrVals));
        if (numCurrVals)
        {
            std::copy(currValStrIndices.begin(), currValStrIndices.end(), it);
            std::advance(it, currValStrIndices.size());
        }
        std::move(enumAttrValTable.begin(), enumAttrValTable.end(),
                  std::back_inserter(attributeValueTable));

        if (std::distance(tableData, response.data() + tableLen) <=
            padChksumMax)
        {
            break;
        }

        attrPtr =
            reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
    }

    return attributeValueTable;
}

} // end namespace bios_type_enum

/** @brief Construct the BIOS attribute table
 *
 *  @param[in] BIOSAttributeTable - the attribute table
 *  @param[in] BIOSStringTable - the string table
 *  @param[in] transferHandle - transfer handle to identify part of transfer
 *  @param[in] transferOpFlag - flag to indicate which part of data being
 * transferred
 *  @param[in] instanceID - instance ID to identify the command
 *  @param[in] biosJsonDir - path where the BIOS json files are present
 */
Response getBIOSAttributeTable(BIOSTable& BIOSAttributeTable,
                               const BIOSTable& BIOSStringTable,
                               uint32_t transferHandle, uint8_t transferOpFlag,
                               uint8_t instanceID, const char* biosJsonDir)
{
    Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
                      0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
    uint32_t nxtTransferHandle = 0;
    uint8_t transferFlag = PLDM_START_AND_END;
    size_t respPayloadLength{};

    if (BIOSAttributeTable.isEmpty())
    { // no persisted table, constructing fresh table and response
        auto attributeTable =
            bios_type_enum::constructAttrTable(BIOSStringTable, biosJsonDir);

        // calculate pad
        uint8_t padSize = utils::getNumPadBytes(attributeTable.size());
        std::vector<uint8_t> pad(padSize, 0);
        if (padSize)
        {
            std::move(pad.begin(), pad.end(),
                      std::back_inserter(attributeTable));
        }

        if (!attributeTable.empty())
        {
            // compute checksum
            boost::crc_32_type result;
            size_t size = attributeTable.size();
            result.process_bytes(attributeTable.data(), size);
            uint32_t checkSum = result.checksum();
            attributeTable.resize(size + sizeof(checkSum));
            std::copy_n(reinterpret_cast<uint8_t*>(&checkSum), sizeof(checkSum),
                        attributeTable.data() + size);
            BIOSAttributeTable.store(attributeTable);
        }
        response.resize(sizeof(pldm_msg_hdr) +
                        PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
                        attributeTable.size());
        responsePtr = reinterpret_cast<pldm_msg*>(response.data());
        respPayloadLength = response.size();
        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS, nxtTransferHandle,
                                   transferFlag, attributeTable.data(),
                                   respPayloadLength, responsePtr);
    }
    else
    { // persisted table present, constructing response
        respPayloadLength = response.size();
        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS, nxtTransferHandle,
                                   transferFlag, nullptr, respPayloadLength,
                                   responsePtr); // filling up the header here
        BIOSAttributeTable.load(response);
    }

    return response;
}

/** @brief Construct the BIOS attribute value table
 *
 *  @param[in] BIOSAttributeValueTable - the attribute value table
 *  @param[in] BIOSAttributeTable - the attribute table
 *  @param[in] BIOSStringTable - the string table
 *  @param[in] transferHandle - transfer handle to identify part of transfer
 *  @param[in] transferOpFlag - flag to indicate which part of data being
 * transferred
 *  @param[in] instanceID - instance ID to identify the command
 *  @param[in] biosJsonDir -  path where the BIOS json files are present
 */
Response getBIOSAttributeValueTable(BIOSTable& BIOSAttributeValueTable,
                                    const BIOSTable& BIOSAttributeTable,
                                    const BIOSTable& BIOSStringTable,
                                    uint32_t& transferHandle,
                                    uint8_t& transferOpFlag, uint8_t instanceID,
                                    const char* biosJsonDir)
{
    Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
                      0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
    uint32_t nxtTransferHandle = 0;
    uint8_t transferFlag = PLDM_START_AND_END;
    size_t respPayloadLength{};

    if (BIOSAttributeValueTable.isEmpty())
    { // no persisted table, constructing fresh table and data
        Table attributeValueTable = bios_type_enum::constructAttrValueTable(
            BIOSAttributeTable, BIOSStringTable);
        // calculate pad
        uint8_t padSize = utils::getNumPadBytes(attributeValueTable.size());
        std::vector<uint8_t> pad(padSize, 0);
        if (padSize)
        {
            std::move(pad.begin(), pad.end(),
                      std::back_inserter(attributeValueTable));
        }
        if (!attributeValueTable.empty())
        {
            // compute checksum
            boost::crc_32_type result;
            result.process_bytes(attributeValueTable.data(),
                                 attributeValueTable.size());
            uint32_t checkSum = result.checksum();
            size_t size = attributeValueTable.size();
            attributeValueTable.resize(size + sizeof(checkSum));
            std::copy_n(reinterpret_cast<uint8_t*>(&checkSum), sizeof(checkSum),
                        attributeValueTable.data() + size);
            BIOSAttributeValueTable.store(attributeValueTable);
        }

        response.resize(sizeof(pldm_msg_hdr) +
                        PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES +
                        attributeValueTable.size());
        responsePtr = reinterpret_cast<pldm_msg*>(response.data());
        respPayloadLength = response.size();
        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS, nxtTransferHandle,
                                   transferFlag, attributeValueTable.data(),
                                   respPayloadLength, responsePtr);
    }
    else
    { // persisted table present, constructing response
        respPayloadLength = response.size();
        encode_get_bios_table_resp(instanceID, PLDM_SUCCESS, nxtTransferHandle,
                                   transferFlag, nullptr, respPayloadLength,
                                   responsePtr); // filling up the header here
        BIOSAttributeValueTable.load(response);
    }

    return response;
}

Response getBIOSTable(const pldm_msg* request, size_t payloadLength)
{
    auto response = internal::buildBIOSTables(request, payloadLength,
                                              BIOS_JSONS_DIR, BIOS_TABLES_DIR);

    return response;
}

namespace bios
{

void registerHandlers()
{
    registerHandler(PLDM_BIOS, PLDM_GET_DATE_TIME, std::move(getDateTime));
    registerHandler(PLDM_BIOS, PLDM_GET_BIOS_TABLE, std::move(getBIOSTable));
}

namespace internal
{

Response buildBIOSTables(const pldm_msg* request, size_t payloadLength,
                         const char* biosJsonDir, const char* biosTablePath)
{
    Response response(sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_MIN_RESP_BYTES,
                      0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());

    uint32_t transferHandle{};
    uint8_t transferOpFlag{};
    uint8_t tableType{};

    auto rc = decode_get_bios_table_req(request, payloadLength, &transferHandle,
                                        &transferOpFlag, &tableType);
    if (rc == PLDM_SUCCESS)
    {
        BIOSTable BIOSStringTable(
            ((std::string(biosTablePath) + "/stringTable")).c_str());
        BIOSTable BIOSAttributeTable(
            ((std::string(biosTablePath) + "/attributeTable")).c_str());
        BIOSTable BIOSAttributeValueTable(
            ((std::string(biosTablePath) + "/attributeValueTable")).c_str());
        switch (tableType)
        {
            case PLDM_BIOS_STRING_TABLE:

                response = getBIOSStringTable(
                    BIOSStringTable, transferHandle, transferOpFlag,
                    request->hdr.instance_id, biosJsonDir);
                break;
            case PLDM_BIOS_ATTR_TABLE:

                if (BIOSStringTable.isEmpty())
                {
                    rc = PLDM_BIOS_TABLE_UNAVAILABLE;
                }
                else
                {
                    response = getBIOSAttributeTable(
                        BIOSAttributeTable, BIOSStringTable, transferHandle,
                        transferOpFlag, request->hdr.instance_id, biosJsonDir);
                }
                break;
            case PLDM_BIOS_ATTR_VAL_TABLE:
                if (BIOSAttributeTable.isEmpty())
                {
                    rc = PLDM_BIOS_TABLE_UNAVAILABLE;
                }
                else
                {
                    response = getBIOSAttributeValueTable(
                        BIOSAttributeValueTable, BIOSAttributeTable,
                        BIOSStringTable, transferHandle, transferOpFlag,
                        request->hdr.instance_id, biosJsonDir);
                }
                break;
            default:
                rc = PLDM_INVALID_BIOS_TABLE_TYPE;
                break;
        }
    }

    if (rc != PLDM_SUCCESS)
    {
        uint32_t nxtTransferHandle{};
        uint8_t transferFlag{};
        size_t respPayloadLength{};

        encode_get_bios_table_resp(request->hdr.instance_id, rc,
                                   nxtTransferHandle, transferFlag, nullptr,
                                   respPayloadLength, responsePtr);
    }

    return response;
}

} // end namespace internal
} // namespace bios

} // namespace responder
} // namespace pldm
