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