1 #pragma once
2
3 #include "common/types.hpp"
4 #include "common/utils.hpp"
5
6 #include <libpldm/pdr.h>
7
8 #include <nlohmann/json.hpp>
9 #include <phosphor-logging/lg2.hpp>
10 #include <xyz/openbmc_project/Common/error.hpp>
11
12 #include <cstdint>
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 EffecterId = uint16_t;
80 using StatestoDbusVal = std::map<State, pldm::utils::PropertyValue>;
81 using DbusMappings = std::vector<pldm::utils::DBusMapping>;
82 using DbusValMaps = std::vector<StatestoDbusVal>;
83 using DbusObjMaps = std::map<EffecterId, std::tuple<DbusMappings, DbusValMaps>>;
84 using EventStates = std::array<uint8_t, 8>;
85
86 /** @brief Parse PDR JSON file and output Json object
87 *
88 * @param[in] path - path of PDR JSON file
89 *
90 * @return Json - Json object
91 */
readJson(const std::string & path)92 inline Json readJson(const std::string& path)
93 {
94 fs::path dir(path);
95 if (!fs::exists(dir) || fs::is_empty(dir))
96 {
97 throw InternalFailure();
98 }
99
100 std::ifstream jsonFile(path);
101 if (!jsonFile.is_open())
102 {
103 error("Error opening PDR JSON file at '{PATH}'", "PATH", path);
104 return {};
105 }
106
107 return Json::parse(jsonFile);
108 }
109
110 /** @brief Populate the mapping between D-Bus property stateId and attribute
111 * value for the effecter PDR enumeration attribute.
112 *
113 * @param[in] type - type of the D-Bus property
114 * @param[in] dBusValues - json array of D-Bus property values
115 * @param[in] pv - Possible values for the effecter PDR enumeration attribute
116 *
117 * @return StatestoDbusVal - Map of D-Bus property stateId to attribute value
118 */
119 StatestoDbusVal populateMapping(const std::string& type, const Json& dBusValues,
120 const PossibleValues& pv);
121
122 /**
123 * @class RepoInterface
124 *
125 * @brief Abstract class describing the interface API to the PDR repository,
126 * this class wraps operations used to handle the new PDR APIs.
127 */
128 class RepoInterface
129 {
130 public:
RepoInterface(pldm_pdr * repo)131 RepoInterface(pldm_pdr* repo) : repo(repo) {}
132
133 virtual ~RepoInterface() = default;
134
135 /** @brief Get an opaque pldm_pdr structure
136 *
137 * @return pldm_pdr - pldm_pdr structure
138 */
139 virtual pldm_pdr* getPdr() const = 0;
140
141 /** @brief Add a PDR record to a PDR repository
142 *
143 * @param[in] pdrEntry - PDR records entry(data, size, recordHandle)
144 *
145 * @return uint32_t - record handle assigned to PDR record
146 */
147 virtual RecordHandle addRecord(const PdrEntry& pdrEntry) = 0;
148
149 /** @brief Get the first PDR record from a PDR repository
150 *
151 * @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle)
152 *
153 * @return opaque pointer acting as PDR record handle, will be NULL if
154 * record was not found
155 */
156 virtual const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) = 0;
157
158 /** @brief Get the next PDR record from a PDR repository
159 *
160 * @param[in] currRecord - opaque pointer acting as a PDR record handle
161 * @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle)
162 *
163 * @return opaque pointer acting as PDR record handle, will be NULL if
164 * record was not found
165 */
166 virtual const pldm_pdr_record* getNextRecord(
167 const pldm_pdr_record* currRecord, 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:
Repo(pldm_pdr * repo)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