1 #pragma once
2 
3 #include "types.hpp"
4 #include "utils.hpp"
5 
6 #include <stdint.h>
7 
8 #include <filesystem>
9 #include <fstream>
10 #include <functional>
11 #include <iostream>
12 #include <nlohmann/json.hpp>
13 #include <string>
14 #include <xyz/openbmc_project/Common/error.hpp>
15 
16 #include "libpldm/pdr.h"
17 
18 using InternalFailure =
19     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
20 
21 namespace fs = std::filesystem;
22 
23 namespace pldm
24 {
25 
26 namespace responder
27 {
28 
29 namespace pdr_utils
30 {
31 
32 /** @struct PdrEntry
33  *  PDR entry structure that acts as a PDR record structure in the PDR
34  *  repository to handle PDR APIs.
35  */
36 struct PdrEntry
37 {
38     uint8_t* data;
39     uint32_t size;
40     union
41     {
42         uint32_t recordHandle;
43         uint32_t nextRecordHandle;
44     } handle;
45 };
46 using Type = uint8_t;
47 using Json = nlohmann::json;
48 using RecordHandle = uint32_t;
49 using State = uint8_t;
50 using PossibleValues = std::vector<uint8_t>;
51 
52 /** @brief Map of DBus property State to attribute value
53  */
54 using StatestoDbusVal = std::map<State, pldm::utils::PropertyValue>;
55 using DbusMappings = std::vector<pldm::utils::DBusMapping>;
56 using DbusValMaps = std::vector<StatestoDbusVal>;
57 
58 /** @brief Parse PDR JSON file and output Json object
59  *
60  *  @param[in] path - path of PDR JSON file
61  *
62  *  @return Json - Json object
63  */
64 inline Json readJson(const std::string& path)
65 {
66     fs::path dir(path);
67     if (!fs::exists(dir) || fs::is_empty(dir))
68     {
69         throw InternalFailure();
70     }
71 
72     std::ifstream jsonFile(path);
73     if (!jsonFile.is_open())
74     {
75         std::cerr << "Error opening PDR JSON file, PATH=" << path << "\n";
76         return {};
77     }
78 
79     return Json::parse(jsonFile);
80 }
81 
82 /** @brief Populate the mapping between D-Bus property stateId and attribute
83  *          value for the effecter PDR enumeration attribute.
84  *
85  *  @param[in] type - type of the D-Bus property
86  *  @param[in] dBusValues - json array of D-Bus property values
87  *  @param[in] pv - Possible values for the effecter PDR enumeration attribute
88  *
89  *  @return StatestoDbusVal - Map of D-Bus property stateId to attribute value
90  */
91 StatestoDbusVal populateMapping(const std::string& type, const Json& dBusValues,
92                                 const PossibleValues& pv);
93 
94 /**
95  *  @class RepoInterface
96  *
97  *  @brief Abstract class describing the interface API to the PDR repository,
98  *         this class wraps operations used to handle the new PDR APIs.
99  */
100 class RepoInterface
101 {
102   public:
103     RepoInterface(pldm_pdr* repo) : repo(repo)
104     {
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 
183     pldm_pdr* getPdr() const override;
184 
185     RecordHandle addRecord(const PdrEntry& pdrEntry) override;
186 
187     const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) override;
188 
189     const pldm_pdr_record* getNextRecord(const pldm_pdr_record* currRecord,
190                                          PdrEntry& pdrEntry) override;
191 
192     uint32_t getRecordHandle(const pldm_pdr_record* record) const override;
193 
194     uint32_t getRecordCount() override;
195 
196     bool empty() override;
197 };
198 
199 using namespace pldm::pdr;
200 /** @brief Parse the State Sensor PDR and return the parsed sensor info which
201  *         will be used to lookup the sensor info in the PlatformEventMessage
202  *         command of sensorEvent type.
203  *
204  *  @param[in] stateSensorPdr - state sensor PDR
205  *
206  *  @return terminus handle, sensor ID and parsed sensor info
207  */
208 std::tuple<TerminusHandle, SensorID, SensorInfo>
209     parseStateSensorPDR(const std::vector<uint8_t>& stateSensorPdr);
210 
211 } // namespace pdr_utils
212 } // namespace responder
213 } // namespace pldm
214