blob: af55f9217fd64a20d2f4185eb0335481e15b2955 [file] [log] [blame]
#pragma once
#include "fru_parser.hpp"
#include "libpldmresponder/pdr_utils.hpp"
#include "oem_handler.hpp"
#include "pldmd/handler.hpp"
#include <libpldm/fru.h>
#include <libpldm/pdr.h>
#include <sdbusplus/message.hpp>
#include <map>
#include <string>
#include <variant>
#include <vector>
namespace pldm
{
namespace responder
{
namespace dbus
{
using Value = std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
int64_t, uint64_t, double, std::string,
std::vector<uint8_t>, std::vector<std::string>>;
using PropertyMap = std::map<Property, Value>;
using InterfaceMap = std::map<Interface, PropertyMap>;
using ObjectValueTree = std::map<sdbusplus::message::object_path, InterfaceMap>;
using ObjectPath = std::string;
using AssociatedEntityMap = std::map<ObjectPath, pldm_entity>;
} // namespace dbus
/** @class FruImpl
*
* @brief Builds the PLDM FRU table containing the FRU records
*/
class FruImpl
{
public:
/* @brief Header size for FRU record, it includes the FRU record set
* identifier, FRU record type, Number of FRU fields, Encoding type
* of FRU fields
*/
static constexpr size_t recHeaderSize =
sizeof(struct pldm_fru_record_data_format) -
sizeof(struct pldm_fru_record_tlv);
/** @brief Constructor for FruImpl, the configPath is consumed to build the
* FruParser object.
*
* @param[in] configPath - path to the directory containing config files
* for PLDM FRU
* @param[in] fruMasterJsonPath - path to the file containing the FRU D-Bus
* Lookup Map
* @param[in] pdrRepo - opaque pointer to PDR repository
* @param[in] entityTree - opaque pointer to the entity association tree
* @param[in] bmcEntityTree - opaque pointer to bmc's entity association
* tree
* @param[in] oemFruHandler - OEM fru handler
*/
FruImpl(const std::string& configPath,
const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
pldm_entity_association_tree* entityTree,
pldm_entity_association_tree* bmcEntityTree) :
parser(configPath, fruMasterJsonPath), pdrRepo(pdrRepo),
entityTree(entityTree), bmcEntityTree(bmcEntityTree)
{}
/** @brief Total length of the FRU table in bytes, this includes the pad
* bytes and the checksum.
*
* @return size of the FRU table
*/
uint32_t size() const
{
return table.size();
}
/** @brief The checksum of the contents of the FRU table
*
* @return checksum
*/
uint32_t checkSum() const
{
return checksum;
}
/** @brief Number of record set identifiers in the FRU tables
*
* @return number of record set identifiers
*/
uint16_t numRSI() const
{
return rsi;
}
/** @brief The number of FRU records in the table
*
* @return number of FRU records
*/
uint16_t numRecords() const
{
return numRecs;
}
/** @brief Get the FRU table
*
* @param[out] - Populate response with the FRU table
*/
void getFRUTable(Response& response);
/** @brief Get the Fru Table MetaData
*
*/
void getFRURecordTableMetadata();
/** @brief Get FRU Record Table By Option
* @param[out] response - Populate response with the FRU table got by
* options
* @param[in] fruTableHandle - The fru table handle
* @param[in] recordSetIdentifer - The record set identifier
* @param[in] recordType - The record type
* @param[in] fieldType - The field type
*/
int getFRURecordByOption(Response& response, uint16_t fruTableHandle,
uint16_t recordSetIdentifer, uint8_t recordType,
uint8_t fieldType);
/** @brief FRU table is built by processing the D-Bus inventory namespace
* based on the config files for FRU. The table is populated based
* on the isBuilt flag.
*/
void buildFRUTable();
/** @brief Get std::map associated with the entity
* key: object path
* value: pldm_entity
*
* @return std::map<ObjectPath, pldm_entity>
*/
inline const pldm::responder::dbus::AssociatedEntityMap&
getAssociateEntityMap() const
{
return associatedEntityMap;
}
/** @brief Get pldm entity by the object path
*
* @param[in] intfMaps - D-Bus interfaces and the associated property
* values for the FRU
*
* @return pldm_entity
*/
std::optional<pldm_entity>
getEntityByObjectPath(const dbus::InterfaceMap& intfMaps);
/** @brief Update pldm entity to association tree
*
* @param[in] objects - std::map The object value tree
* @param[in] path - Object path
*
* Ex: Input path =
* "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"
*
* Get the parent class in turn and store it in a temporary vector
*
* Output tmpObjPaths = {
* "/xyz/openbmc_project/inventory/system",
* "/xyz/openbmc_project/inventory/system/chassis/",
* "/xyz/openbmc_project/inventory/system/chassis/motherboard",
* "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"}
*
*/
void updateAssociationTree(const dbus::ObjectValueTree& objects,
const std::string& path);
/* @brief Method to populate the firmware version ID
*
* @return firmware version ID
*/
std::string populatefwVersion();
/* @brief Method to resize the table
*
* @return resized table
*/
std::vector<uint8_t> tableResize();
/* @brief set FRU Record Table
*
* @param[in] fruData - the data of the fru
*
* @return PLDM completion code
*/
int setFRUTable(const std::vector<uint8_t>& fruData);
/* @brief Method to set the oem platform handler in fru handler class
*
* @param[in] handler - oem fru handler
*/
inline void setOemFruHandler(pldm::responder::oem_fru::Handler* handler)
{
oemFruHandler = handler;
}
private:
uint16_t nextRSI()
{
return ++rsi;
}
uint32_t nextRecordHandle()
{
return ++rh;
}
uint32_t rh = 0;
uint16_t rsi = 0;
uint16_t numRecs = 0;
uint8_t padBytes = 0;
std::vector<uint8_t> table;
uint32_t checksum = 0;
bool isBuilt = false;
fru_parser::FruParser parser;
pldm_pdr* pdrRepo;
pldm_entity_association_tree* entityTree;
pldm_entity_association_tree* bmcEntityTree;
pldm::responder::oem_fru::Handler* oemFruHandler = nullptr;
dbus::ObjectValueTree objects;
std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{};
/** @brief populateRecord builds the FRU records for an instance of FRU and
* updates the FRU table with the FRU records.
*
* @param[in] interfaces - D-Bus interfaces and the associated property
* values for the FRU
* @param[in] recordInfos - FRU record info to build the FRU records
* @param[in/out] entity - PLDM entity corresponding to FRU instance
*/
void populateRecords(const dbus::InterfaceMap& interfaces,
const fru_parser::FruRecordInfos& recordInfos,
const pldm_entity& entity);
/** @brief Associate sensor/effecter to FRU entity
*/
dbus::AssociatedEntityMap associatedEntityMap;
};
namespace fru
{
class Handler : public CmdHandler
{
public:
Handler(const std::string& configPath,
const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
pldm_entity_association_tree* entityTree,
pldm_entity_association_tree* bmcEntityTree) :
impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree)
{
handlers.emplace(
PLDM_GET_FRU_RECORD_TABLE_METADATA,
[this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
return this->getFRURecordTableMetadata(request, payloadLength);
});
handlers.emplace(
PLDM_GET_FRU_RECORD_TABLE,
[this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
return this->getFRURecordTable(request, payloadLength);
});
handlers.emplace(
PLDM_GET_FRU_RECORD_BY_OPTION,
[this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
return this->getFRURecordByOption(request, payloadLength);
});
handlers.emplace(
PLDM_SET_FRU_RECORD_TABLE,
[this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
return this->setFRURecordTable(request, payloadLength);
});
}
/** @brief Handler for Get FRURecordTableMetadata
*
* @param[in] request - Request message payload
* @param[in] payloadLength - Request payload length
*
* @return PLDM response message
*/
Response getFRURecordTableMetadata(const pldm_msg* request,
size_t payloadLength);
/** @brief Handler for GetFRURecordTable
*
* @param[in] request - Request message payload
* @param[in] payloadLength - Request payload length
*
* @return PLDM response message
*/
Response getFRURecordTable(const pldm_msg* request, size_t payloadLength);
/** @brief Build FRU table is bnot already built
*
*/
void buildFRUTable()
{
impl.buildFRUTable();
}
/** @brief Get std::map associated with the entity
* key: object path
* value: pldm_entity
*
* @return std::map<ObjectPath, pldm_entity>
*/
const pldm::responder::dbus::AssociatedEntityMap&
getAssociateEntityMap() const
{
return impl.getAssociateEntityMap();
}
/** @brief Handler for GetFRURecordByOption
*
* @param[in] request - Request message payload
* @param[in] payloadLength - Request payload length
*
* @return PLDM response message
*/
Response getFRURecordByOption(const pldm_msg* request,
size_t payloadLength);
/** @brief Handler for SetFRURecordTable
*
* @param[in] request - Request message
* @param[in] payloadLength - Request payload length
*
* @return PLDM response message
*/
Response setFRURecordTable(const pldm_msg* request, size_t payloadLength);
/* @brief Method to set the oem platform handler in fru handler class
*
* @param[in] handler - oem fru handler
*/
void setOemFruHandler(pldm::responder::oem_fru::Handler* handler)
{
impl.setOemFruHandler(handler);
}
using Table = std::vector<uint8_t>;
private:
FruImpl impl;
};
} // namespace fru
} // namespace responder
} // namespace pldm