blob: ade09b28ca1cd55f50d0cddaa0decbd3307285d9 [file] [log] [blame]
John Wangd9659342020-02-27 16:46:05 +08001#include "bios_config.hpp"
2
John Wang3be70852020-02-13 15:59:04 +08003#include "bios_enum_attribute.hpp"
John Wang95e6b3c2020-02-13 09:43:24 +08004#include "bios_integer_attribute.hpp"
John Wangd9659342020-02-27 16:46:05 +08005#include "bios_string_attribute.hpp"
Sampa Misra46ece062020-03-18 07:17:44 -05006#include "bios_table.hpp"
John Wangd9659342020-02-27 16:46:05 +08007
8#include <fstream>
9#include <iostream>
10
11namespace pldm
12{
13namespace responder
14{
15namespace bios
16{
17namespace
18{
19
20constexpr auto enumJsonFile = "enum_attrs.json";
21constexpr auto stringJsonFile = "string_attrs.json";
22constexpr auto integerJsonFile = "integer_attrs.json";
23
24constexpr auto stringTableFile = "stringTable";
25constexpr auto attrTableFile = "attributeTable";
26constexpr auto attrValueTableFile = "attributeValueTable";
27
28} // namespace
29
30BIOSConfig::BIOSConfig(const char* jsonDir, const char* tableDir,
31 DBusHandler* const dbusHandler) :
32 jsonDir(jsonDir),
33 tableDir(tableDir), dbusHandler(dbusHandler)
34{
35 constructAttributes();
36}
37
38void BIOSConfig::buildTables()
39{
40 fs::create_directory(tableDir);
41 auto stringTable = buildAndStoreStringTable();
42 if (stringTable)
43 {
44 buildAndStoreAttrTables(*stringTable);
45 }
46}
47
48std::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
66void BIOSConfig::constructAttributes()
67{
68 load(jsonDir / stringJsonFile, [this](const Json& entry) {
69 constructAttribute<BIOSStringAttribute>(entry);
70 });
John Wang3be70852020-02-13 15:59:04 +080071 load(jsonDir / integerJsonFile, [this](const Json& entry) {
John Wang95e6b3c2020-02-13 09:43:24 +080072 constructAttribute<BIOSIntegerAttribute>(entry);
73 });
John Wang3be70852020-02-13 15:59:04 +080074 load(jsonDir / enumJsonFile, [this](const Json& entry) {
75 constructAttribute<BIOSEnumAttribute>(entry);
76 });
John Wangd9659342020-02-27 16:46:05 +080077}
78
79void 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
110std::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
144void BIOSConfig::storeTable(const fs::path& path, const Table& table)
145{
146 BIOSTable biosTable(path.c_str());
147 biosTable.store(table);
148}
149
150std::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
163void 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
196int 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
253void 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
Sampa Misra46ece062020-03-18 07:17:44 -0500267void 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
John Wangd9659342020-02-27 16:46:05 +0800344} // namespace bios
345} // namespace responder
346} // namespace pldm