blob: c1810de67910bd6da230f83c3fd492dfa9a2314b [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{
George Liu9d8921e2020-05-14 15:41:50 +080035 fs::create_directories(tableDir);
John Wangd9659342020-02-27 16:46:05 +080036 constructAttributes();
37}
38
39void BIOSConfig::buildTables()
40{
John Wangd9659342020-02-27 16:46:05 +080041 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
John Wang8241b342020-06-05 10:49:17 +0800196int BIOSConfig::checkAttrValueToUpdate(
197 const pldm_bios_attr_val_table_entry* attrValueEntry,
198 const pldm_bios_attr_table_entry* attrEntry, Table&)
199
200{
201 auto [attrHandle, attrType] =
202 table::attribute_value::decodeHeader(attrValueEntry);
203
204 switch (attrType)
205 {
206 case PLDM_BIOS_ENUMERATION:
207 {
208 auto value =
209 table::attribute_value::decodeEnumEntry(attrValueEntry);
210 auto [pvHdls, defIndex] =
211 table::attribute::decodeEnumEntry(attrEntry);
212 assert(value.size() == 1);
213 if (value[0] >= pvHdls.size())
214 {
215 std::cerr << "Enum: Illgeal index, Index = " << (int)value[0]
216 << std::endl;
217 return PLDM_ERROR_INVALID_DATA;
218 }
219
220 return PLDM_SUCCESS;
221 }
222 case PLDM_BIOS_INTEGER:
223 {
224 auto value =
225 table::attribute_value::decodeIntegerEntry(attrValueEntry);
226 auto [lower, upper, scalar, def] =
227 table::attribute::decodeIntegerEntry(attrEntry);
228
229 if (value < lower || value > upper)
230 {
231 std::cerr << "Integer: out of bound, value = " << value
232 << std::endl;
233 return PLDM_ERROR_INVALID_DATA;
234 }
235 return PLDM_SUCCESS;
236 }
237 case PLDM_BIOS_STRING:
238 {
239 auto stringConf = table::attribute::decodeStringEntry(attrEntry);
240 auto value =
241 table::attribute_value::decodeStringEntry(attrValueEntry);
242 if (value.size() < stringConf.minLength ||
243 value.size() > stringConf.maxLength)
244 {
245 std::cerr << "String: Length error, string = " << value
246 << " length = " << value.size() << std::endl;
247 return PLDM_ERROR_INVALID_LENGTH;
248 }
249 return PLDM_SUCCESS;
250 }
251 default:
252 std::cerr << "ReadOnly or Unspported type, type = " << attrType
253 << std::endl;
254 return PLDM_ERROR;
255 };
256}
257
John Wangd9659342020-02-27 16:46:05 +0800258int BIOSConfig::setAttrValue(const void* entry, size_t size)
259{
260 auto attrValueTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
261 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
262 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
263 if (!attrValueTable || !attrTable || !stringTable)
264 {
265 return PLDM_BIOS_TABLE_UNAVAILABLE;
266 }
267
John Wangd9659342020-02-27 16:46:05 +0800268 auto attrValueEntry =
269 reinterpret_cast<const pldm_bios_attr_val_table_entry*>(entry);
270
271 auto attrValHeader = table::attribute_value::decodeHeader(attrValueEntry);
272
273 auto attrEntry =
274 table::attribute::findByHandle(*attrTable, attrValHeader.attrHandle);
275 if (!attrEntry)
276 {
277 return PLDM_ERROR;
278 }
279
John Wang8241b342020-06-05 10:49:17 +0800280 auto rc = checkAttrValueToUpdate(attrValueEntry, attrEntry, *stringTable);
281 if (rc != PLDM_SUCCESS)
282 {
283 return rc;
284 }
285
286 auto destTable =
287 table::attribute_value::updateTable(*attrValueTable, entry, size);
288
289 if (!destTable)
290 {
291 return PLDM_ERROR;
292 }
293
John Wangd9659342020-02-27 16:46:05 +0800294 try
295 {
296 auto attrHeader = table::attribute::decodeHeader(attrEntry);
297
298 BIOSStringTable biosStringTable(*stringTable);
299 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
300
301 auto iter = std::find_if(
302 biosAttributes.begin(), biosAttributes.end(),
303 [&attrName](const auto& attr) { return attr->name == attrName; });
304
305 if (iter == biosAttributes.end())
306 {
307 return PLDM_ERROR;
308 }
309 (*iter)->setAttrValueOnDbus(attrValueEntry, attrEntry, biosStringTable);
310 }
311 catch (const std::exception& e)
312 {
313 std::cerr << "Set attribute value error: " << e.what() << std::endl;
314 return PLDM_ERROR;
315 }
316
317 BIOSTable biosAttrValueTable((tableDir / attrValueTableFile).c_str());
318 biosAttrValueTable.store(*destTable);
319 return PLDM_SUCCESS;
320}
321
322void BIOSConfig::removeTables()
323{
324 try
325 {
326 fs::remove(tableDir / stringTableFile);
327 fs::remove(tableDir / attrTableFile);
328 fs::remove(tableDir / attrValueTableFile);
329 }
330 catch (const std::exception& e)
331 {
332 std::cerr << "Remove the tables error: " << e.what() << std::endl;
333 }
334}
335
Sampa Misra46ece062020-03-18 07:17:44 -0500336void BIOSConfig::processBiosAttrChangeNotification(
337 const DbusChObjProperties& chProperties, uint32_t biosAttrIndex)
338{
339 const auto& dBusMap = biosAttributes[biosAttrIndex]->getDBusMap();
340 const auto& propertyName = dBusMap->propertyName;
341 const auto& attrName = biosAttributes[biosAttrIndex]->name;
342
343 const auto it = chProperties.find(propertyName);
344 if (it == chProperties.end())
345 {
346 return;
347 }
348
349 PropertyValue newPropVal = it->second;
350 auto stringTable = getBIOSTable(PLDM_BIOS_STRING_TABLE);
351 if (!stringTable.has_value())
352 {
353 std::cerr << "BIOS string table unavailable\n";
354 return;
355 }
356 BIOSStringTable biosStringTable(*stringTable);
357 uint16_t attrNameHdl{};
358 try
359 {
360 attrNameHdl = biosStringTable.findHandle(attrName);
361 }
362 catch (std::invalid_argument& e)
363 {
364 std::cerr << "Could not find handle for BIOS string, ATTRIBUTE="
365 << attrName.c_str() << "\n";
366 return;
367 }
368
369 auto attrTable = getBIOSTable(PLDM_BIOS_ATTR_TABLE);
370 if (!attrTable.has_value())
371 {
372 std::cerr << "Attribute table not present\n";
373 return;
374 }
375 const struct pldm_bios_attr_table_entry* tableEntry =
376 table::attribute::findByStringHandle(*attrTable, attrNameHdl);
377 if (tableEntry == nullptr)
378 {
379 std::cerr << "Attribute not found in attribute table, name= "
380 << attrName.c_str() << "name handle=" << attrNameHdl << "\n";
381 return;
382 }
383
384 auto [attrHdl, attrType, stringHdl] =
385 table::attribute::decodeHeader(tableEntry);
386
387 auto attrValueSrcTable = getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
388
389 if (!attrValueSrcTable.has_value())
390 {
391 std::cerr << "Attribute value table not present\n";
392 return;
393 }
394
395 Table newValue;
396 auto rc = biosAttributes[biosAttrIndex]->updateAttrVal(
397 newValue, attrHdl, attrType, newPropVal);
398 if (rc != PLDM_SUCCESS)
399 {
400 std::cerr << "Could not update the attribute value table for attribute "
401 "handle="
402 << attrHdl << " and type=" << (uint32_t)attrType << "\n";
403 return;
404 }
405 auto destTable = table::attribute_value::updateTable(
406 *attrValueSrcTable, newValue.data(), newValue.size());
407 if (destTable.has_value())
408 {
409 storeTable(tableDir / attrValueTableFile, *destTable);
410 }
411}
412
John Wangd9659342020-02-27 16:46:05 +0800413} // namespace bios
414} // namespace responder
415} // namespace pldm