1 #include "bios_config.hpp" 2 3 #include "bios_enum_attribute.hpp" 4 #include "bios_integer_attribute.hpp" 5 #include "bios_string_attribute.hpp" 6 #include "bios_table.hpp" 7 8 #include <fstream> 9 #include <iostream> 10 11 namespace pldm 12 { 13 namespace responder 14 { 15 namespace bios 16 { 17 namespace 18 { 19 20 constexpr auto enumJsonFile = "enum_attrs.json"; 21 constexpr auto stringJsonFile = "string_attrs.json"; 22 constexpr auto integerJsonFile = "integer_attrs.json"; 23 24 constexpr auto stringTableFile = "stringTable"; 25 constexpr auto attrTableFile = "attributeTable"; 26 constexpr auto attrValueTableFile = "attributeValueTable"; 27 28 } // namespace 29 30 BIOSConfig::BIOSConfig(const char* jsonDir, const char* tableDir, 31 DBusHandler* const dbusHandler) : 32 jsonDir(jsonDir), 33 tableDir(tableDir), dbusHandler(dbusHandler) 34 { 35 constructAttributes(); 36 } 37 38 void BIOSConfig::buildTables() 39 { 40 fs::create_directory(tableDir); 41 auto stringTable = buildAndStoreStringTable(); 42 if (stringTable) 43 { 44 buildAndStoreAttrTables(*stringTable); 45 } 46 } 47 48 std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType) 49 { 50 fs::path tablePath; 51 switch (tableType) 52 { 53 case PLDM_BIOS_STRING_TABLE: 54 tablePath = tableDir / stringTableFile; 55 break; 56 case PLDM_BIOS_ATTR_TABLE: 57 tablePath = tableDir / attrTableFile; 58 break; 59 case PLDM_BIOS_ATTR_VAL_TABLE: 60 tablePath = tableDir / attrValueTableFile; 61 break; 62 } 63 return loadTable(tablePath); 64 } 65 66 void BIOSConfig::constructAttributes() 67 { 68 load(jsonDir / stringJsonFile, [this](const Json& entry) { 69 constructAttribute<BIOSStringAttribute>(entry); 70 }); 71 load(jsonDir / integerJsonFile, [this](const Json& entry) { 72 constructAttribute<BIOSIntegerAttribute>(entry); 73 }); 74 load(jsonDir / enumJsonFile, [this](const Json& entry) { 75 constructAttribute<BIOSEnumAttribute>(entry); 76 }); 77 } 78 79 void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable) 80 { 81 BIOSStringTable biosStringTable(stringTable); 82 83 if (biosAttributes.empty()) 84 { 85 return; 86 } 87 88 Table attrTable, attrValueTable; 89 90 for (auto& attr : biosAttributes) 91 { 92 try 93 { 94 attr->constructEntry(biosStringTable, attrTable, attrValueTable); 95 } 96 catch (const std::exception& e) 97 { 98 std::cerr << "Construct Table Entry Error, AttributeName = " 99 << attr->name << std::endl; 100 } 101 } 102 103 table::appendPadAndChecksum(attrTable); 104 table::appendPadAndChecksum(attrValueTable); 105 106 storeTable(tableDir / attrTableFile, attrTable); 107 storeTable(tableDir / attrValueTableFile, attrValueTable); 108 } 109 110 std::optional<Table> BIOSConfig::buildAndStoreStringTable() 111 { 112 std::set<std::string> strings; 113 auto handler = [&strings](const Json& entry) { 114 strings.emplace(entry.at("attribute_name")); 115 }; 116 117 load(jsonDir / stringJsonFile, handler); 118 load(jsonDir / integerJsonFile, handler); 119 load(jsonDir / enumJsonFile, [&strings](const Json& entry) { 120 strings.emplace(entry.at("attribute_name")); 121 auto possibleValues = entry.at("possible_values"); 122 for (auto& pv : possibleValues) 123 { 124 strings.emplace(pv); 125 } 126 }); 127 128 if (strings.empty()) 129 { 130 return std::nullopt; 131 } 132 133 Table table; 134 for (const auto& elem : strings) 135 { 136 table::string::constructEntry(table, elem); 137 } 138 139 table::appendPadAndChecksum(table); 140 storeTable(tableDir / stringTableFile, table); 141 return table; 142 } 143 144 void BIOSConfig::storeTable(const fs::path& path, const Table& table) 145 { 146 BIOSTable biosTable(path.c_str()); 147 biosTable.store(table); 148 } 149 150 std::optional<Table> BIOSConfig::loadTable(const fs::path& path) 151 { 152 BIOSTable biosTable(path.c_str()); 153 if (biosTable.isEmpty()) 154 { 155 return std::nullopt; 156 } 157 158 Table table; 159 biosTable.load(table); 160 return table; 161 } 162 163 void BIOSConfig::load(const fs::path& filePath, ParseHandler handler) 164 { 165 std::ifstream file; 166 Json jsonConf; 167 if (fs::exists(filePath)) 168 { 169 try 170 { 171 file.open(filePath); 172 jsonConf = Json::parse(file); 173 auto entries = jsonConf.at("entries"); 174 for (auto& entry : entries) 175 { 176 try 177 { 178 handler(entry); 179 } 180 catch (const std::exception& e) 181 { 182 std::cerr 183 << "Failed to parse JSON config file(entry handler) : " 184 << filePath.c_str() << ", " << e.what() << std::endl; 185 } 186 } 187 } 188 catch (const std::exception& e) 189 { 190 std::cerr << "Failed to parse JSON config file : " 191 << filePath.c_str() << std::endl; 192 } 193 } 194 } 195 196 int BIOSConfig::setAttrValue(const void* entry, size_t size) 197 { 198 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 199 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 200 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 201 if (!attrValueTable || !attrTable || !stringTable) 202 { 203 return PLDM_BIOS_TABLE_UNAVAILABLE; 204 } 205 206 auto destTable = 207 table::attribute_value::updateTable(*attrValueTable, entry, size); 208 209 if (!destTable) 210 { 211 return PLDM_ERROR; 212 } 213 auto attrValueEntry = 214 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry); 215 216 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry); 217 218 auto attrEntry = 219 table::attribute::findByHandle(*attrTable, attrValHeader.attrHandle); 220 if (!attrEntry) 221 { 222 return PLDM_ERROR; 223 } 224 225 try 226 { 227 auto attrHeader = table::attribute::decodeHeader(attrEntry); 228 229 BIOSStringTable biosStringTable(*stringTable); 230 auto attrName = biosStringTable.findString(attrHeader.stringHandle); 231 232 auto iter = std::find_if( 233 biosAttributes.begin(), biosAttributes.end(), 234 [&attrName](const auto& attr) { return attr->name == attrName; }); 235 236 if (iter == biosAttributes.end()) 237 { 238 return PLDM_ERROR; 239 } 240 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry, biosStringTable); 241 } 242 catch (const std::exception& e) 243 { 244 std::cerr << "Set attribute value error: " << e.what() << std::endl; 245 return PLDM_ERROR; 246 } 247 248 BIOSTable biosAttrValueTable((tableDir / attrValueTableFile).c_str()); 249 biosAttrValueTable.store(*destTable); 250 return PLDM_SUCCESS; 251 } 252 253 void BIOSConfig::removeTables() 254 { 255 try 256 { 257 fs::remove(tableDir / stringTableFile); 258 fs::remove(tableDir / attrTableFile); 259 fs::remove(tableDir / attrValueTableFile); 260 } 261 catch (const std::exception& e) 262 { 263 std::cerr << "Remove the tables error: " << e.what() << std::endl; 264 } 265 } 266 267 void BIOSConfig::processBiosAttrChangeNotification( 268 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex) 269 { 270 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap(); 271 const auto& propertyName = dBusMap->propertyName; 272 const auto& attrName = biosAttributes[biosAttrIndex]->name; 273 274 const auto it = chProperties.find(propertyName); 275 if (it == chProperties.end()) 276 { 277 return; 278 } 279 280 PropertyValue newPropVal = it->second; 281 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 282 if (!stringTable.has_value()) 283 { 284 std::cerr << "BIOS string table unavailable\n"; 285 return; 286 } 287 BIOSStringTable biosStringTable(*stringTable); 288 uint16_t attrNameHdl{}; 289 try 290 { 291 attrNameHdl = biosStringTable.findHandle(attrName); 292 } 293 catch (std::invalid_argument& e) 294 { 295 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE=" 296 << attrName.c_str() << "\n"; 297 return; 298 } 299 300 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 301 if (!attrTable.has_value()) 302 { 303 std::cerr << "Attribute table not present\n"; 304 return; 305 } 306 const struct pldm_bios_attr_table_entry* tableEntry = 307 table::attribute::findByStringHandle(*attrTable, attrNameHdl); 308 if (tableEntry == nullptr) 309 { 310 std::cerr << "Attribute not found in attribute table, name= " 311 << attrName.c_str() << "name handle=" << attrNameHdl << "\n"; 312 return; 313 } 314 315 auto [attrHdl, attrType, stringHdl] = 316 table::attribute::decodeHeader(tableEntry); 317 318 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 319 320 if (!attrValueSrcTable.has_value()) 321 { 322 std::cerr << "Attribute value table not present\n"; 323 return; 324 } 325 326 Table newValue; 327 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal( 328 newValue, attrHdl, attrType, newPropVal); 329 if (rc != PLDM_SUCCESS) 330 { 331 std::cerr << "Could not update the attribute value table for attribute " 332 "handle=" 333 << attrHdl << " and type=" << (uint32_t)attrType << "\n"; 334 return; 335 } 336 auto destTable = table::attribute_value::updateTable( 337 *attrValueSrcTable, newValue.data(), newValue.size()); 338 if (destTable.has_value()) 339 { 340 storeTable(tableDir / attrValueTableFile, *destTable); 341 } 342 } 343 344 } // namespace bios 345 } // namespace responder 346 } // namespace pldm 347