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 7 #include <fstream> 8 #include <iostream> 9 10 namespace pldm 11 { 12 namespace responder 13 { 14 namespace bios 15 { 16 namespace 17 { 18 19 constexpr auto enumJsonFile = "enum_attrs.json"; 20 constexpr auto stringJsonFile = "string_attrs.json"; 21 constexpr auto integerJsonFile = "integer_attrs.json"; 22 23 constexpr auto stringTableFile = "stringTable"; 24 constexpr auto attrTableFile = "attributeTable"; 25 constexpr auto attrValueTableFile = "attributeValueTable"; 26 27 } // namespace 28 29 BIOSConfig::BIOSConfig(const char* jsonDir, const char* tableDir, 30 DBusHandler* const dbusHandler) : 31 jsonDir(jsonDir), 32 tableDir(tableDir), dbusHandler(dbusHandler) 33 { 34 constructAttributes(); 35 } 36 37 void BIOSConfig::buildTables() 38 { 39 fs::create_directory(tableDir); 40 auto stringTable = buildAndStoreStringTable(); 41 if (stringTable) 42 { 43 buildAndStoreAttrTables(*stringTable); 44 } 45 } 46 47 std::optional<Table> BIOSConfig::getBIOSTable(pldm_bios_table_types tableType) 48 { 49 fs::path tablePath; 50 switch (tableType) 51 { 52 case PLDM_BIOS_STRING_TABLE: 53 tablePath = tableDir / stringTableFile; 54 break; 55 case PLDM_BIOS_ATTR_TABLE: 56 tablePath = tableDir / attrTableFile; 57 break; 58 case PLDM_BIOS_ATTR_VAL_TABLE: 59 tablePath = tableDir / attrValueTableFile; 60 break; 61 } 62 return loadTable(tablePath); 63 } 64 65 void BIOSConfig::constructAttributes() 66 { 67 load(jsonDir / stringJsonFile, [this](const Json& entry) { 68 constructAttribute<BIOSStringAttribute>(entry); 69 }); 70 load(jsonDir / integerJsonFile, [this](const Json& entry) { 71 constructAttribute<BIOSIntegerAttribute>(entry); 72 }); 73 load(jsonDir / enumJsonFile, [this](const Json& entry) { 74 constructAttribute<BIOSEnumAttribute>(entry); 75 }); 76 } 77 78 void BIOSConfig::buildAndStoreAttrTables(const Table& stringTable) 79 { 80 BIOSStringTable biosStringTable(stringTable); 81 82 if (biosAttributes.empty()) 83 { 84 return; 85 } 86 87 Table attrTable, attrValueTable; 88 89 for (auto& attr : biosAttributes) 90 { 91 try 92 { 93 attr->constructEntry(biosStringTable, attrTable, attrValueTable); 94 } 95 catch (const std::exception& e) 96 { 97 std::cerr << "Construct Table Entry Error, AttributeName = " 98 << attr->name << std::endl; 99 } 100 } 101 102 table::appendPadAndChecksum(attrTable); 103 table::appendPadAndChecksum(attrValueTable); 104 105 storeTable(tableDir / attrTableFile, attrTable); 106 storeTable(tableDir / attrValueTableFile, attrValueTable); 107 } 108 109 std::optional<Table> BIOSConfig::buildAndStoreStringTable() 110 { 111 std::set<std::string> strings; 112 auto handler = [&strings](const Json& entry) { 113 strings.emplace(entry.at("attribute_name")); 114 }; 115 116 load(jsonDir / stringJsonFile, handler); 117 load(jsonDir / integerJsonFile, handler); 118 load(jsonDir / enumJsonFile, [&strings](const Json& entry) { 119 strings.emplace(entry.at("attribute_name")); 120 auto possibleValues = entry.at("possible_values"); 121 for (auto& pv : possibleValues) 122 { 123 strings.emplace(pv); 124 } 125 }); 126 127 if (strings.empty()) 128 { 129 return std::nullopt; 130 } 131 132 Table table; 133 for (const auto& elem : strings) 134 { 135 table::string::constructEntry(table, elem); 136 } 137 138 table::appendPadAndChecksum(table); 139 storeTable(tableDir / stringTableFile, table); 140 return table; 141 } 142 143 void BIOSConfig::storeTable(const fs::path& path, const Table& table) 144 { 145 BIOSTable biosTable(path.c_str()); 146 biosTable.store(table); 147 } 148 149 std::optional<Table> BIOSConfig::loadTable(const fs::path& path) 150 { 151 BIOSTable biosTable(path.c_str()); 152 if (biosTable.isEmpty()) 153 { 154 return std::nullopt; 155 } 156 157 Table table; 158 biosTable.load(table); 159 return table; 160 } 161 162 void BIOSConfig::load(const fs::path& filePath, ParseHandler handler) 163 { 164 std::ifstream file; 165 Json jsonConf; 166 if (fs::exists(filePath)) 167 { 168 try 169 { 170 file.open(filePath); 171 jsonConf = Json::parse(file); 172 auto entries = jsonConf.at("entries"); 173 for (auto& entry : entries) 174 { 175 try 176 { 177 handler(entry); 178 } 179 catch (const std::exception& e) 180 { 181 std::cerr 182 << "Failed to parse JSON config file(entry handler) : " 183 << filePath.c_str() << ", " << e.what() << std::endl; 184 } 185 } 186 } 187 catch (const std::exception& e) 188 { 189 std::cerr << "Failed to parse JSON config file : " 190 << filePath.c_str() << std::endl; 191 } 192 } 193 } 194 195 int BIOSConfig::setAttrValue(const void* entry, size_t size) 196 { 197 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE); 198 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE); 199 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE); 200 if (!attrValueTable || !attrTable || !stringTable) 201 { 202 return PLDM_BIOS_TABLE_UNAVAILABLE; 203 } 204 205 auto destTable = 206 table::attribute_value::updateTable(*attrValueTable, entry, size); 207 208 if (!destTable) 209 { 210 return PLDM_ERROR; 211 } 212 auto attrValueEntry = 213 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry); 214 215 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry); 216 217 auto attrEntry = 218 table::attribute::findByHandle(*attrTable, attrValHeader.attrHandle); 219 if (!attrEntry) 220 { 221 return PLDM_ERROR; 222 } 223 224 try 225 { 226 auto attrHeader = table::attribute::decodeHeader(attrEntry); 227 228 BIOSStringTable biosStringTable(*stringTable); 229 auto attrName = biosStringTable.findString(attrHeader.stringHandle); 230 231 auto iter = std::find_if( 232 biosAttributes.begin(), biosAttributes.end(), 233 [&attrName](const auto& attr) { return attr->name == attrName; }); 234 235 if (iter == biosAttributes.end()) 236 { 237 return PLDM_ERROR; 238 } 239 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry, biosStringTable); 240 } 241 catch (const std::exception& e) 242 { 243 std::cerr << "Set attribute value error: " << e.what() << std::endl; 244 return PLDM_ERROR; 245 } 246 247 BIOSTable biosAttrValueTable((tableDir / attrValueTableFile).c_str()); 248 biosAttrValueTable.store(*destTable); 249 return PLDM_SUCCESS; 250 } 251 252 void BIOSConfig::removeTables() 253 { 254 try 255 { 256 fs::remove(tableDir / stringTableFile); 257 fs::remove(tableDir / attrTableFile); 258 fs::remove(tableDir / attrValueTableFile); 259 } 260 catch (const std::exception& e) 261 { 262 std::cerr << "Remove the tables error: " << e.what() << std::endl; 263 } 264 } 265 266 } // namespace bios 267 } // namespace responder 268 } // namespace pldm 269