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