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 /** @class BIOSConfig
52  *  @brief Manager BIOS Attributes
53  */
54 class BIOSConfig
55 {
56   public:
57     BIOSConfig() = delete;
58     BIOSConfig(const BIOSConfig&) = delete;
59     BIOSConfig(BIOSConfig&&) = delete;
60     BIOSConfig& operator=(const BIOSConfig&) = delete;
61     BIOSConfig& operator=(BIOSConfig&&) = delete;
62     ~BIOSConfig() = default;
63 
64     /** @brief Construct BIOSConfig
65      *  @param[in] jsonDir - The directory where json file exists
66      *  @param[in] tableDir - The directory where the persistent table is placed
67      *  @param[in] dbusHandler - Dbus Handler
68      */
69     explicit BIOSConfig(const char* jsonDir, const char* tableDir,
70                         DBusHandler* const dbusHandler);
71 
72     /** @brief Set attribute value on dbus and attribute value table
73      *  @param[in] entry - attribute value entry
74      *  @param[in] size - size of the attribute value entry
75      *  @return pldm_completion_codes
76      */
77     int setAttrValue(const void* entry, size_t size);
78 
79     /** @brief Remove the persistent tables */
80     void removeTables();
81 
82     /** @brief Build bios tables(string,attribute,attribute value table)*/
83     void buildTables();
84 
85     /** @brief Get BIOS table of specified type
86      *  @param[in] tableType - The table type
87      *  @return The bios table, std::nullopt if the table is unaviliable
88      */
89     std::optional<Table> getBIOSTable(pldm_bios_table_types tableType);
90 
91     /** @brief set BIOS table
92      *  @param[in] tableType - Indicates what table is being transferred
93      *             {BIOSStringTable=0x0, BIOSAttributeTable=0x1,
94      *              BIOSAttributeValueTable=0x2}
95      *  @param[in] table - table data
96      *  @return pldm_completion_codes
97      */
98     int setBIOSTable(uint8_t tableType, const Table& table);
99 
100   private:
101     const fs::path jsonDir;
102     const fs::path tableDir;
103     DBusHandler* const dbusHandler;
104     bool isUpdateProperty;
105     BaseBIOSTable baseBIOSTableMaps;
106 
107     // vector persists all attributes
108     using BIOSAttributes = std::vector<std::unique_ptr<BIOSAttribute>>;
109     BIOSAttributes biosAttributes;
110 
111     using propName = std::string;
112     using DbusChObjProperties = std::map<propName, PropertyValue>;
113 
114     // vector to catch the D-Bus property change signals for BIOS attributes
115     std::vector<std::unique_ptr<sdbusplus::bus::match::match>> biosAttrMatch;
116 
117     /** @brief Method to update a BIOS attribute when the corresponding Dbus
118      *  property is changed
119      *  @param[in] chProperties - list of properties which have changed
120      *  @param[in] biosAttrIndex - Index of BIOSAttribute pointer in
121      * biosAttributes
122      *  @return - none
123      */
124     void processBiosAttrChangeNotification(
125         const DbusChObjProperties& chProperties, uint32_t biosAttrIndex);
126 
127     /** @brief Construct an attribute and persist it
128      *  @tparam T - attribute type
129      *  @param[in] entry - json entry
130      */
131     template <typename T>
132     void constructAttribute(const Json& entry)
133     {
134         try
135         {
136             biosAttributes.push_back(std::make_unique<T>(entry, dbusHandler));
137             auto biosAttrIndex = biosAttributes.size() - 1;
138             auto dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
139 
140             if (dBusMap.has_value())
141             {
142                 using namespace sdbusplus::bus::match::rules;
143                 biosAttrMatch.push_back(
144                     std::make_unique<sdbusplus::bus::match::match>(
145                         pldm::utils::DBusHandler::getBus(),
146                         propertiesChanged(dBusMap->objectPath,
147                                           dBusMap->interface),
148                         [this,
149                          biosAttrIndex](sdbusplus::message::message& msg) {
150                             DbusChObjProperties props;
151                             std::string iface;
152                             msg.read(iface, props);
153                             processBiosAttrChangeNotification(props,
154                                                               biosAttrIndex);
155                         }));
156             }
157         }
158         catch (const std::exception& e)
159         {
160             std::cerr << "Constructs Attribute Error, " << e.what()
161                       << std::endl;
162         }
163     }
164 
165     /** Construct attributes and persist them */
166     void constructAttributes();
167 
168     using ParseHandler = std::function<void(const Json& entry)>;
169 
170     /** @brief Helper function to parse json
171      *  @param[in] filePath - Path of json file
172      *  @param[in] handler - Handler to process each entry in the json
173      */
174     void load(const fs::path& filePath, ParseHandler handler);
175 
176     /** @brief Build String Table and persist it
177      *  @return The built string table, std::nullopt if it fails.
178      */
179     std::optional<Table> buildAndStoreStringTable();
180 
181     /** @brief Build attr table and attr value table and persist them
182      *  @param[in] stringTable - The string Table
183      */
184     void buildAndStoreAttrTables(const Table& stringTable);
185 
186     /** @brief Persist the table
187      *  @param[in] path - Path to persist the table
188      *  @param[in] table - The table
189      */
190     void storeTable(const fs::path& path, const Table& table);
191 
192     /** @brief Load bios table to ram
193      *  @param[in] path - Path of the table
194      *  @return The table, std::nullopt if loading fails
195      */
196     std::optional<Table> loadTable(const fs::path& path);
197 
198     /** @brief Check the attribute value to update
199      *  @param[in] attrValueEntry - The attribute value entry to update
200      *  @param[in] attrEntry - The attribute table entry
201      *  @param[in] stringTable - The string  table
202      *  @return pldm_completion_codes
203      */
204     int checkAttrValueToUpdate(
205         const pldm_bios_attr_val_table_entry* attrValueEntry,
206         const pldm_bios_attr_table_entry* attrEntry, Table& stringTable);
207 
208     /** @brief Check the attribute table
209      *  @param[in] table - The table
210      *  @return pldm_completion_codes
211      */
212     int checkAttributeTable(const Table& table);
213 
214     /** @brief Check the attribute value table
215      *  @param[in] table - The table
216      *  @return pldm_completion_codes
217      */
218     int checkAttributeValueTable(const Table& table);
219 
220     /** @brief Update the BaseBIOSTable property of the D-Bus interface
221      */
222     void updateBaseBIOSTableProperty();
223 };
224 
225 } // namespace bios
226 } // namespace responder
227 } // namespace pldm
228