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