blob: e742ee63fd3923a57f6cb6af990854575980e07b [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"
6
7#include <fstream>
8#include <iostream>
9
10namespace pldm
11{
12namespace responder
13{
14namespace bios
15{
16namespace
17{
18
19constexpr auto enumJsonFile = "enum_attrs.json";
20constexpr auto stringJsonFile = "string_attrs.json";
21constexpr auto integerJsonFile = "integer_attrs.json";
22
23constexpr auto stringTableFile = "stringTable";
24constexpr auto attrTableFile = "attributeTable";
25constexpr auto attrValueTableFile = "attributeValueTable";
26
27} // namespace
28
29BIOSConfig::BIOSConfig(const char* jsonDir, const char* tableDir,
30 DBusHandler* const dbusHandler) :
31 jsonDir(jsonDir),
32 tableDir(tableDir), dbusHandler(dbusHandler)
33{
34 constructAttributes();
35}
36
37void BIOSConfig::buildTables()
38{
39 fs::create_directory(tableDir);
40 auto stringTable = buildAndStoreStringTable();
41 if (stringTable)
42 {
43 buildAndStoreAttrTables(*stringTable);
44 }
45}
46
47std::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
65void BIOSConfig::constructAttributes()
66{
67 load(jsonDir / stringJsonFile, [this](const Json& entry) {
68 constructAttribute<BIOSStringAttribute>(entry);
69 });
John Wang3be70852020-02-13 15:59:04 +080070 load(jsonDir / integerJsonFile, [this](const Json& entry) {
John Wang95e6b3c2020-02-13 09:43:24 +080071 constructAttribute<BIOSIntegerAttribute>(entry);
72 });
John Wang3be70852020-02-13 15:59:04 +080073 load(jsonDir / enumJsonFile, [this](const Json& entry) {
74 constructAttribute<BIOSEnumAttribute>(entry);
75 });
John Wangd9659342020-02-27 16:46:05 +080076}
77
78void 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
109std::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
143void BIOSConfig::storeTable(const fs::path& path, const Table& table)
144{
145 BIOSTable biosTable(path.c_str());
146 biosTable.store(table);
147}
148
149std::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
162void 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
195int 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
252void 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