1 #pragma once
2 
3 #include "bios_table.h"
4 
5 #include "bios_attribute.hpp"
6 #include "bios_table.hpp"
7 
8 #include <nlohmann/json.hpp>
9 
10 #include <functional>
11 #include <iostream>
12 #include <memory>
13 #include <optional>
14 #include <set>
15 #include <string>
16 #include <vector>
17 
18 namespace pldm
19 {
20 namespace responder
21 {
22 namespace bios
23 {
24 
25 enum class BoundType
26 {
27     LowerBound,
28     UpperBound,
29     ScalarIncrement,
30     MinStringLength,
31     MaxStringLength,
32     OneOf
33 };
34 
35 using AttributeName = std::string;
36 using AttributeType = std::string;
37 using ReadonlyStatus = bool;
38 using DisplayName = std::string;
39 using Description = std::string;
40 using MenuPath = std::string;
41 using CurrentValue = std::variant<int64_t, std::string>;
42 using DefaultValue = std::variant<int64_t, std::string>;
43 using OptionString = std::string;
44 using OptionValue = std::variant<int64_t, std::string>;
45 using Option = std::vector<std::tuple<OptionString, OptionValue>>;
46 using BIOSTableObj =
47     std::tuple<AttributeType, ReadonlyStatus, DisplayName, Description,
48                MenuPath, CurrentValue, DefaultValue, Option>;
49 using BaseBIOSTable = std::map<AttributeName, BIOSTableObj>;
50 
51 using PendingObj = std::tuple<AttributeType, CurrentValue>;
52 using PendingAttributes = std::map<AttributeName, PendingObj>;
53 
54 /** @class BIOSConfig
55  *  @brief Manager BIOS Attributes
56  */
57 class BIOSConfig
58 {
59   public:
60     BIOSConfig() = delete;
61     BIOSConfig(const BIOSConfig&) = delete;
62     BIOSConfig(BIOSConfig&&) = delete;
63     BIOSConfig& operator=(const BIOSConfig&) = delete;
64     BIOSConfig& operator=(BIOSConfig&&) = delete;
65     ~BIOSConfig() = default;
66 
67     /** @brief Construct BIOSConfig
68      *  @param[in] jsonDir - The directory where json file exists
69      *  @param[in] tableDir - The directory where the persistent table is placed
70      *  @param[in] dbusHandler - Dbus Handler
71      */
72     explicit BIOSConfig(const char* jsonDir, const char* tableDir,
73                         DBusHandler* const dbusHandler);
74 
75     /** @brief Set attribute value on dbus and attribute value table
76      *  @param[in] entry - attribute value entry
77      *  @param[in] size - size of the attribute value entry
78      *  @return pldm_completion_codes
79      */
80     int setAttrValue(const void* entry, size_t size);
81 
82     /** @brief Remove the persistent tables */
83     void removeTables();
84 
85     /** @brief Build bios tables(string,attribute,attribute value table)*/
86     void buildTables();
87 
88     /** @brief Get BIOS table of specified type
89      *  @param[in] tableType - The table type
90      *  @return The bios table, std::nullopt if the table is unaviliable
91      */
92     std::optional<Table> getBIOSTable(pldm_bios_table_types tableType);
93 
94     /** @brief set BIOS table
95      *  @param[in] tableType - Indicates what table is being transferred
96      *             {BIOSStringTable=0x0, BIOSAttributeTable=0x1,
97      *              BIOSAttributeValueTable=0x2}
98      *  @param[in] table - table data
99      *  @return pldm_completion_codes
100      */
101     int setBIOSTable(uint8_t tableType, const Table& table);
102 
103   private:
104     const fs::path jsonDir;
105     const fs::path tableDir;
106     DBusHandler* const dbusHandler;
107     bool isUpdateProperty;
108     BaseBIOSTable baseBIOSTableMaps;
109 
110     // vector persists all attributes
111     using BIOSAttributes = std::vector<std::unique_ptr<BIOSAttribute>>;
112     BIOSAttributes biosAttributes;
113 
114     using propName = std::string;
115     using DbusChObjProperties = std::map<propName, PropertyValue>;
116 
117     // vector to catch the D-Bus property change signals for BIOS attributes
118     std::vector<std::unique_ptr<sdbusplus::bus::match::match>> biosAttrMatch;
119 
120     /** @brief Method to update a BIOS attribute when the corresponding Dbus
121      *  property is changed
122      *  @param[in] chProperties - list of properties which have changed
123      *  @param[in] biosAttrIndex - Index of BIOSAttribute pointer in
124      * biosAttributes
125      *  @return - none
126      */
127     void processBiosAttrChangeNotification(
128         const DbusChObjProperties& chProperties, uint32_t biosAttrIndex);
129 
130     /** @brief Construct an attribute and persist it
131      *  @tparam T - attribute type
132      *  @param[in] entry - json entry
133      */
134     template <typename T>
135     void constructAttribute(const Json& entry)
136     {
137         try
138         {
139             biosAttributes.push_back(std::make_unique<T>(entry, dbusHandler));
140             auto biosAttrIndex = biosAttributes.size() - 1;
141             auto dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
142 
143             if (dBusMap.has_value())
144             {
145                 using namespace sdbusplus::bus::match::rules;
146                 biosAttrMatch.push_back(
147                     std::make_unique<sdbusplus::bus::match::match>(
148                         pldm::utils::DBusHandler::getBus(),
149                         propertiesChanged(dBusMap->objectPath,
150                                           dBusMap->interface),
151                         [this,
152                          biosAttrIndex](sdbusplus::message::message& msg) {
153                             DbusChObjProperties props;
154                             std::string iface;
155                             msg.read(iface, props);
156                             processBiosAttrChangeNotification(props,
157                                                               biosAttrIndex);
158                         }));
159             }
160         }
161         catch (const std::exception& e)
162         {
163             std::cerr << "Constructs Attribute Error, " << e.what()
164                       << std::endl;
165         }
166     }
167 
168     /** Construct attributes and persist them */
169     void constructAttributes();
170 
171     using ParseHandler = std::function<void(const Json& entry)>;
172 
173     /** @brief Helper function to parse json
174      *  @param[in] filePath - Path of json file
175      *  @param[in] handler - Handler to process each entry in the json
176      */
177     void load(const fs::path& filePath, ParseHandler handler);
178 
179     /** @brief Build String Table and persist it
180      *  @return The built string table, std::nullopt if it fails.
181      */
182     std::optional<Table> buildAndStoreStringTable();
183 
184     /** @brief Build attr table and attr value table and persist them
185      *  @param[in] stringTable - The string Table
186      */
187     void buildAndStoreAttrTables(const Table& stringTable);
188 
189     /** @brief Persist the table
190      *  @param[in] path - Path to persist the table
191      *  @param[in] table - The table
192      */
193     void storeTable(const fs::path& path, const Table& table);
194 
195     /** @brief Load bios table to ram
196      *  @param[in] path - Path of the table
197      *  @return The table, std::nullopt if loading fails
198      */
199     std::optional<Table> loadTable(const fs::path& path);
200 
201     /** @brief Check the attribute value to update
202      *  @param[in] attrValueEntry - The attribute value entry to update
203      *  @param[in] attrEntry - The attribute table entry
204      *  @param[in] stringTable - The string  table
205      *  @return pldm_completion_codes
206      */
207     int checkAttrValueToUpdate(
208         const pldm_bios_attr_val_table_entry* attrValueEntry,
209         const pldm_bios_attr_table_entry* attrEntry, Table& stringTable);
210 
211     /** @brief Check the attribute table
212      *  @param[in] table - The table
213      *  @return pldm_completion_codes
214      */
215     int checkAttributeTable(const Table& table);
216 
217     /** @brief Check the attribute value table
218      *  @param[in] table - The table
219      *  @return pldm_completion_codes
220      */
221     int checkAttributeValueTable(const Table& table);
222 
223     /** @brief Update the BaseBIOSTable property of the D-Bus interface
224      */
225     void updateBaseBIOSTableProperty();
226 
227     /** @brief Listen the PendingAttributes property of the D-Bus interface and
228      *         update BaseBIOSTable
229      */
230     void listenPendingAttributes();
231 
232     /** @brief Find attribute handle from bios attribute table
233      *  @param[in] attrName - attribute name
234      *  @return attribute handle
235      */
236     uint16_t findAttrHandle(const std::string& attrName);
237 
238     /** @brief Listen the PendingAttributes property of the D-Bus interface
239      * and update BaseBIOSTable
240      *  @param[in] msg - Data associated with subscribed signal
241      */
242     void constructPendingAttribute(const PendingAttributes& pendingAttributes);
243 };
244 
245 } // namespace bios
246 } // namespace responder
247 } // namespace pldm
248