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 PdrEntry
42  *  PDR entry structure that acts as a PDR record structure in the PDR
43  *  repository to handle PDR APIs.
44  */
45 struct PdrEntry
46 {
47     uint8_t* data;
48     uint32_t size;
49     union
50     {
51         uint32_t recordHandle;
52         uint32_t nextRecordHandle;
53     } handle;
54 };
55 using Type = uint8_t;
56 using Json = nlohmann::json;
57 using RecordHandle = uint32_t;
58 using State = uint8_t;
59 using PossibleValues = std::vector<uint8_t>;
60 
61 /** @brief Map of DBus property State to attribute value
62  */
63 using StatestoDbusVal = std::map<State, pldm::utils::PropertyValue>;
64 using DbusMappings = std::vector<pldm::utils::DBusMapping>;
65 using DbusValMaps = std::vector<StatestoDbusVal>;
66 
67 /** @brief Parse PDR JSON file and output Json object
68  *
69  *  @param[in] path - path of PDR JSON file
70  *
71  *  @return Json - Json object
72  */
73 inline Json readJson(const std::string& path)
74 {
75     fs::path dir(path);
76     if (!fs::exists(dir) || fs::is_empty(dir))
77     {
78         throw InternalFailure();
79     }
80 
81     std::ifstream jsonFile(path);
82     if (!jsonFile.is_open())
83     {
84         error("Error opening PDR JSON file, PATH={JSON_PATH}", "JSON_PATH",
85               path);
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     virtual ~RepoInterface() = default;
116 
117     /** @brief Get an opaque pldm_pdr structure
118      *
119      *  @return pldm_pdr - pldm_pdr structure
120      */
121     virtual pldm_pdr* getPdr() const = 0;
122 
123     /** @brief Add a PDR record to a PDR repository
124      *
125      *  @param[in] pdrEntry - PDR records entry(data, size, recordHandle)
126      *
127      *  @return uint32_t - record handle assigned to PDR record
128      */
129     virtual RecordHandle addRecord(const PdrEntry& pdrEntry) = 0;
130 
131     /** @brief Get the first PDR record from a PDR repository
132      *
133      *  @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle)
134      *
135      *  @return opaque pointer acting as PDR record handle, will be NULL if
136      *          record was not found
137      */
138     virtual const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) = 0;
139 
140     /** @brief Get the next PDR record from a PDR repository
141      *
142      *  @param[in] currRecord - opaque pointer acting as a PDR record handle
143      *  @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle)
144      *
145      *  @return opaque pointer acting as PDR record handle, will be NULL if
146      *          record was not found
147      */
148     virtual const pldm_pdr_record*
149         getNextRecord(const pldm_pdr_record* currRecord,
150                       PdrEntry& pdrEntry) = 0;
151 
152     /** @brief Get record handle of a PDR record
153      *
154      *  @param[in] record - opaque pointer acting as a PDR record handle
155      *
156      *  @return uint32_t - record handle assigned to PDR record; 0 if record is
157      *                     not found
158      */
159     virtual uint32_t getRecordHandle(const pldm_pdr_record* record) const = 0;
160 
161     /** @brief Get number of records in a PDR repository
162      *
163      *  @return uint32_t - number of records
164      */
165     virtual uint32_t getRecordCount() = 0;
166 
167     /** @brief Determine if records are empty in a PDR repository
168      *
169      *  @return bool - true means empty and false means not empty
170      */
171     virtual bool empty() = 0;
172 
173   protected:
174     pldm_pdr* repo;
175 };
176 
177 /**
178  *  @class Repo
179  *
180  *  Wrapper class to handle the PDR APIs
181  *
182  *  This class wraps operations used to handle PDR APIs.
183  */
184 class Repo : public RepoInterface
185 {
186   public:
187     Repo(pldm_pdr* repo) : RepoInterface(repo) {}
188 
189     pldm_pdr* getPdr() const override;
190 
191     RecordHandle addRecord(const PdrEntry& pdrEntry) override;
192 
193     const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) override;
194 
195     const pldm_pdr_record* getNextRecord(const pldm_pdr_record* currRecord,
196                                          PdrEntry& pdrEntry) override;
197 
198     uint32_t getRecordHandle(const pldm_pdr_record* record) const override;
199 
200     uint32_t getRecordCount() override;
201 
202     bool empty() override;
203 };
204 
205 /** @brief Parse the State Sensor PDR and return the parsed sensor info which
206  *         will be used to lookup the sensor info in the PlatformEventMessage
207  *         command of sensorEvent type.
208  *
209  *  @param[in] stateSensorPdr - state sensor PDR
210  *
211  *  @return terminus handle, sensor ID and parsed sensor info
212  */
213 std::tuple<pldm::pdr::TerminusHandle, pldm::pdr::SensorID,
214            pldm::pdr::SensorInfo>
215     parseStateSensorPDR(const std::vector<uint8_t>& stateSensorPdr);
216 
217 } // namespace pdr_utils
218 } // namespace responder
219 } // namespace pldm
220