1 #pragma once 2 3 #include "common/types.hpp" 4 #include "common/utils.hpp" 5 6 #include <libpldm/pdr.h> 7 #include <stdint.h> 8 9 #include <nlohmann/json.hpp> 10 #include <phosphor-logging/lg2.hpp> 11 #include <xyz/openbmc_project/Common/error.hpp> 12 13 #include <filesystem> 14 #include <fstream> 15 #include <functional> 16 #include <iostream> 17 #include <string> 18 19 PHOSPHOR_LOG2_USING; 20 21 using InternalFailure = 22 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 23 24 namespace fs = std::filesystem; 25 26 namespace pldm 27 { 28 namespace responder 29 { 30 namespace pdr_utils 31 { 32 /** @struct Type ID associated with pdr 33 * 34 */ 35 enum class TypeId 36 { 37 PLDM_EFFECTER_ID, 38 PLDM_SENSOR_ID 39 }; 40 41 struct FruTLV 42 { 43 uint8_t fruFieldType; 44 uint8_t fruFieldLen; 45 std::vector<uint8_t> fruFieldValue; 46 }; 47 48 struct FruRecordDataFormat 49 { 50 uint16_t fruRSI; 51 uint8_t fruRecType; 52 uint8_t fruNum; 53 uint8_t fruEncodeType; 54 std::vector<FruTLV> fruTLV; 55 }; 56 57 /** @struct PdrEntry 58 * PDR entry structure that acts as a PDR record structure in the PDR 59 * repository to handle PDR APIs. 60 */ 61 struct PdrEntry 62 { 63 uint8_t* data; 64 uint32_t size; 65 union 66 { 67 uint32_t recordHandle; 68 uint32_t nextRecordHandle; 69 } handle; 70 }; 71 using Type = uint8_t; 72 using Json = nlohmann::json; 73 using RecordHandle = uint32_t; 74 using State = uint8_t; 75 using PossibleValues = std::vector<uint8_t>; 76 77 /** @brief Map of DBus property State to attribute value 78 */ 79 using StatestoDbusVal = std::map<State, pldm::utils::PropertyValue>; 80 using DbusMappings = std::vector<pldm::utils::DBusMapping>; 81 using DbusValMaps = std::vector<StatestoDbusVal>; 82 using EventStates = std::array<uint8_t, 8>; 83 84 /** @brief Parse PDR JSON file and output Json object 85 * 86 * @param[in] path - path of PDR JSON file 87 * 88 * @return Json - Json object 89 */ 90 inline Json readJson(const std::string& path) 91 { 92 fs::path dir(path); 93 if (!fs::exists(dir) || fs::is_empty(dir)) 94 { 95 throw InternalFailure(); 96 } 97 98 std::ifstream jsonFile(path); 99 if (!jsonFile.is_open()) 100 { 101 error("Error opening PDR JSON file, PATH={JSON_PATH}", "JSON_PATH", 102 path); 103 return {}; 104 } 105 106 return Json::parse(jsonFile); 107 } 108 109 /** @brief Populate the mapping between D-Bus property stateId and attribute 110 * value for the effecter PDR enumeration attribute. 111 * 112 * @param[in] type - type of the D-Bus property 113 * @param[in] dBusValues - json array of D-Bus property values 114 * @param[in] pv - Possible values for the effecter PDR enumeration attribute 115 * 116 * @return StatestoDbusVal - Map of D-Bus property stateId to attribute value 117 */ 118 StatestoDbusVal populateMapping(const std::string& type, const Json& dBusValues, 119 const PossibleValues& pv); 120 121 /** 122 * @class RepoInterface 123 * 124 * @brief Abstract class describing the interface API to the PDR repository, 125 * this class wraps operations used to handle the new PDR APIs. 126 */ 127 class RepoInterface 128 { 129 public: 130 RepoInterface(pldm_pdr* repo) : repo(repo) {} 131 132 virtual ~RepoInterface() = default; 133 134 /** @brief Get an opaque pldm_pdr structure 135 * 136 * @return pldm_pdr - pldm_pdr structure 137 */ 138 virtual pldm_pdr* getPdr() const = 0; 139 140 /** @brief Add a PDR record to a PDR repository 141 * 142 * @param[in] pdrEntry - PDR records entry(data, size, recordHandle) 143 * 144 * @return uint32_t - record handle assigned to PDR record 145 */ 146 virtual RecordHandle addRecord(const PdrEntry& pdrEntry) = 0; 147 148 /** @brief Get the first PDR record from a PDR repository 149 * 150 * @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle) 151 * 152 * @return opaque pointer acting as PDR record handle, will be NULL if 153 * record was not found 154 */ 155 virtual const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) = 0; 156 157 /** @brief Get the next PDR record from a PDR repository 158 * 159 * @param[in] currRecord - opaque pointer acting as a PDR record handle 160 * @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle) 161 * 162 * @return opaque pointer acting as PDR record handle, will be NULL if 163 * record was not found 164 */ 165 virtual const pldm_pdr_record* 166 getNextRecord(const pldm_pdr_record* currRecord, 167 PdrEntry& pdrEntry) = 0; 168 169 /** @brief Get record handle of a PDR record 170 * 171 * @param[in] record - opaque pointer acting as a PDR record handle 172 * 173 * @return uint32_t - record handle assigned to PDR record; 0 if record is 174 * not found 175 */ 176 virtual uint32_t getRecordHandle(const pldm_pdr_record* record) const = 0; 177 178 /** @brief Get number of records in a PDR repository 179 * 180 * @return uint32_t - number of records 181 */ 182 virtual uint32_t getRecordCount() = 0; 183 184 /** @brief Determine if records are empty in a PDR repository 185 * 186 * @return bool - true means empty and false means not empty 187 */ 188 virtual bool empty() = 0; 189 190 protected: 191 pldm_pdr* repo; 192 }; 193 194 /** 195 * @class Repo 196 * 197 * Wrapper class to handle the PDR APIs 198 * 199 * This class wraps operations used to handle PDR APIs. 200 */ 201 class Repo : public RepoInterface 202 { 203 public: 204 Repo(pldm_pdr* repo) : RepoInterface(repo) {} 205 206 pldm_pdr* getPdr() const override; 207 208 RecordHandle addRecord(const PdrEntry& pdrEntry) override; 209 210 const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) override; 211 212 const pldm_pdr_record* getNextRecord(const pldm_pdr_record* currRecord, 213 PdrEntry& pdrEntry) override; 214 215 uint32_t getRecordHandle(const pldm_pdr_record* record) const override; 216 217 uint32_t getRecordCount() override; 218 219 bool empty() override; 220 }; 221 222 /** @brief Parse the State Sensor PDR and return the parsed sensor info which 223 * will be used to lookup the sensor info in the PlatformEventMessage 224 * command of sensorEvent type. 225 * 226 * @param[in] stateSensorPdr - state sensor PDR 227 * 228 * @return terminus handle, sensor ID and parsed sensor info 229 */ 230 std::tuple<pldm::pdr::TerminusHandle, pldm::pdr::SensorID, 231 pldm::pdr::SensorInfo> 232 parseStateSensorPDR(const std::vector<uint8_t>& stateSensorPdr); 233 234 /** @brief Parse FRU record table and return the vector of the FRU record data 235 * format structure 236 * 237 * @param[in] fruData - fru data 238 * @param[in] fruLen - fru len 239 * 240 * @return std::vector<FruRecordDataFormat> - the vector of the FRU record data 241 * format structure 242 */ 243 std::vector<FruRecordDataFormat> parseFruRecordTable(const uint8_t* fruData, 244 size_t fruLen); 245 246 /** @brief Return the size of data type based on the effecterDataSize enum value 247 * 248 * @param[in] effecterDataSize - Bitwidth and format of setting effecter value 249 * @return[out] Map the effecterDataSize enum value to datatype and return the 250 * size of dataType 251 */ 252 size_t getEffecterDataSize(uint8_t effecterDataSize); 253 254 } // namespace pdr_utils 255 } // namespace responder 256 } // namespace pldm 257