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