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 Populate the mapping between D-Bus property stateId and attribute
93  *          value for the effecter PDR enumeration attribute.
94  *
95  *  @param[in] type - type of the D-Bus property
96  *  @param[in] dBusValues - json array of D-Bus property values
97  *  @param[in] pv - Possible values for the effecter PDR enumeration attribute
98  *
99  *  @return StatestoDbusVal - Map of D-Bus property stateId to attribute value
100  */
101 StatestoDbusVal populateMapping(const std::string& type, const Json& dBusValues,
102                                 const PossibleValues& pv);
103 
104 /**
105  *  @class RepoInterface
106  *
107  *  @brief Abstract class describing the interface API to the PDR repository,
108  *         this class wraps operations used to handle the new PDR APIs.
109  */
110 class RepoInterface
111 {
112   public:
113     RepoInterface(pldm_pdr* repo) : repo(repo)
114     {}
115 
116     virtual ~RepoInterface() = default;
117 
118     /** @brief Get an opaque pldm_pdr structure
119      *
120      *  @return pldm_pdr - pldm_pdr structure
121      */
122     virtual pldm_pdr* getPdr() const = 0;
123 
124     /** @brief Add a PDR record to a PDR repository
125      *
126      *  @param[in] pdrEntry - PDR records entry(data, size, recordHandle)
127      *
128      *  @return uint32_t - record handle assigned to PDR record
129      */
130     virtual RecordHandle addRecord(const PdrEntry& pdrEntry) = 0;
131 
132     /** @brief Get the first PDR record from a PDR repository
133      *
134      *  @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle)
135      *
136      *  @return opaque pointer acting as PDR record handle, will be NULL if
137      *          record was not found
138      */
139     virtual const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) = 0;
140 
141     /** @brief Get the next PDR record from a PDR repository
142      *
143      *  @param[in] currRecord - opaque pointer acting as a PDR record handle
144      *  @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle)
145      *
146      *  @return opaque pointer acting as PDR record handle, will be NULL if
147      *          record was not found
148      */
149     virtual const pldm_pdr_record*
150         getNextRecord(const pldm_pdr_record* currRecord,
151                       PdrEntry& pdrEntry) = 0;
152 
153     /** @brief Get record handle of a PDR record
154      *
155      *  @param[in] record - opaque pointer acting as a PDR record handle
156      *
157      *  @return uint32_t - record handle assigned to PDR record; 0 if record is
158      *                     not found
159      */
160     virtual uint32_t getRecordHandle(const pldm_pdr_record* record) const = 0;
161 
162     /** @brief Get number of records in a PDR repository
163      *
164      *  @return uint32_t - number of records
165      */
166     virtual uint32_t getRecordCount() = 0;
167 
168     /** @brief Determine if records are empty in a PDR repository
169      *
170      *  @return bool - true means empty and false means not empty
171      */
172     virtual bool empty() = 0;
173 
174   protected:
175     pldm_pdr* repo;
176 };
177 
178 /**
179  *  @class Repo
180  *
181  *  Wrapper class to handle the PDR APIs
182  *
183  *  This class wraps operations used to handle PDR APIs.
184  */
185 class Repo : public RepoInterface
186 {
187   public:
188     Repo(pldm_pdr* repo) : RepoInterface(repo)
189     {}
190 
191     pldm_pdr* getPdr() const override;
192 
193     RecordHandle addRecord(const PdrEntry& pdrEntry) override;
194 
195     const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) override;
196 
197     const pldm_pdr_record* getNextRecord(const pldm_pdr_record* currRecord,
198                                          PdrEntry& pdrEntry) override;
199 
200     uint32_t getRecordHandle(const pldm_pdr_record* record) const override;
201 
202     uint32_t getRecordCount() override;
203 
204     bool empty() override;
205 };
206 
207 /** @brief Parse the State Sensor PDR and return the parsed sensor info which
208  *         will be used to lookup the sensor info in the PlatformEventMessage
209  *         command of sensorEvent type.
210  *
211  *  @param[in] stateSensorPdr - state sensor PDR
212  *
213  *  @return terminus handle, sensor ID and parsed sensor info
214  */
215 std::tuple<pldm::pdr::TerminusHandle, pldm::pdr::SensorID,
216            pldm::pdr::SensorInfo>
217     parseStateSensorPDR(const std::vector<uint8_t>& stateSensorPdr);
218 
219 } // namespace pdr_utils
220 } // namespace responder
221 } // namespace pldm
222