1 #pragma once
2 
3 #include <stdint.h>
4 
5 #include <filesystem>
6 #include <fstream>
7 #include <functional>
8 #include <iostream>
9 #include <nlohmann/json.hpp>
10 #include <string>
11 #include <xyz/openbmc_project/Common/error.hpp>
12 
13 #include "libpldm/pdr.h"
14 
15 using InternalFailure =
16     sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
17 
18 namespace fs = std::filesystem;
19 
20 namespace pldm
21 {
22 
23 namespace responder
24 {
25 
26 namespace pdr_utils
27 {
28 
29 /** @struct PdrEntry
30  *  PDR entry structure that acts as a PDR record structure in the PDR
31  *  repository to handle PDR APIs.
32  */
33 struct PdrEntry
34 {
35     uint8_t* data;
36     uint32_t size;
37     union
38     {
39         uint32_t recordHandle;
40         uint32_t nextRecordHandle;
41     } handle;
42 };
43 using Type = uint8_t;
44 using Json = nlohmann::json;
45 using RecordHandle = uint32_t;
46 
47 /** @brief Parse PDR JSON file and output Json object
48  *
49  *  @param[in] path - path of PDR JSON file
50  *
51  *  @return Json - Json object
52  */
53 inline Json readJson(const std::string& path)
54 {
55     fs::path dir(path);
56     if (!fs::exists(dir) || fs::is_empty(dir))
57     {
58         throw InternalFailure();
59     }
60 
61     std::ifstream jsonFile(path);
62     if (!jsonFile.is_open())
63     {
64         std::cerr << "Error opening PDR JSON file, PATH=" << path << "\n";
65         return {};
66     }
67 
68     return Json::parse(jsonFile);
69 }
70 
71 /**
72  *  @class RepoInterface
73  *
74  *  @brief Abstract class describing the interface API to the PDR repository,
75  *         this class wraps operations used to handle the new PDR APIs.
76  */
77 class RepoInterface
78 {
79   public:
80     RepoInterface(pldm_pdr* repo) : repo(repo)
81     {
82     }
83 
84     virtual ~RepoInterface() = default;
85 
86     /** @brief Get an opaque pldm_pdr structure
87      *
88      *  @return pldm_pdr - pldm_pdr structure
89      */
90     virtual pldm_pdr* getPdr() const = 0;
91 
92     /** @brief Add a PDR record to a PDR repository
93      *
94      *  @param[in] pdrEntry - PDR records entry(data, size, recordHandle)
95      *
96      *  @return uint32_t - record handle assigned to PDR record
97      */
98     virtual RecordHandle addRecord(const PdrEntry& pdrEntry) = 0;
99 
100     /** @brief Get the first PDR record from a PDR repository
101      *
102      *  @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle)
103      *
104      *  @return opaque pointer acting as PDR record handle, will be NULL if
105      *          record was not found
106      */
107     virtual const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) = 0;
108 
109     /** @brief Get the next PDR record from a PDR repository
110      *
111      *  @param[in] currRecord - opaque pointer acting as a PDR record handle
112      *  @param[in] pdrEntry - PDR records entry(data, size, nextRecordHandle)
113      *
114      *  @return opaque pointer acting as PDR record handle, will be NULL if
115      *          record was not found
116      */
117     virtual const pldm_pdr_record*
118         getNextRecord(const pldm_pdr_record* currRecord,
119                       PdrEntry& pdrEntry) = 0;
120 
121     /** @brief Get record handle of a PDR record
122      *
123      *  @param[in] record - opaque pointer acting as a PDR record handle
124      *
125      *  @return uint32_t - record handle assigned to PDR record; 0 if record is
126      *                     not found
127      */
128     virtual uint32_t getRecordHandle(const pldm_pdr_record* record) const = 0;
129 
130     /** @brief Get number of records in a PDR repository
131      *
132      *  @return uint32_t - number of records
133      */
134     virtual uint32_t getRecordCount() = 0;
135 
136     /** @brief Determine if records are empty in a PDR repository
137      *
138      *  @return bool - true means empty and false means not empty
139      */
140     virtual bool empty() = 0;
141 
142   protected:
143     pldm_pdr* repo;
144 };
145 
146 /**
147  *  @class Repo
148  *
149  *  Wrapper class to handle the PDR APIs
150  *
151  *  This class wraps operations used to handle PDR APIs.
152  */
153 class Repo : public RepoInterface
154 {
155   public:
156     Repo(pldm_pdr* repo) : RepoInterface(repo)
157     {
158     }
159 
160     pldm_pdr* getPdr() const override;
161 
162     RecordHandle addRecord(const PdrEntry& pdrEntry) override;
163 
164     const pldm_pdr_record* getFirstRecord(PdrEntry& pdrEntry) override;
165 
166     const pldm_pdr_record* getNextRecord(const pldm_pdr_record* currRecord,
167                                          PdrEntry& pdrEntry) override;
168 
169     uint32_t getRecordHandle(const pldm_pdr_record* record) const override;
170 
171     uint32_t getRecordCount() override;
172 
173     bool empty() override;
174 };
175 
176 } // namespace pdr_utils
177 } // namespace responder
178 } // namespace pldm
179