blob: 90b2ad2f6d88b9c34b88f3ce47d2c3c0a8e37f52 [file] [log] [blame]
John Wangd9659342020-02-27 16:46:05 +08001#include "bios_config.hpp"
2
John Wang95e6b3c2020-02-13 09:43:24 +08003#include "bios_integer_attribute.hpp"
John Wangd9659342020-02-27 16:46:05 +08004#include "bios_string_attribute.hpp"
5
6#include <fstream>
7#include <iostream>
8
9namespace pldm
10{
11namespace responder
12{
13namespace bios
14{
15namespace
16{
17
18constexpr auto enumJsonFile = "enum_attrs.json";
19constexpr auto stringJsonFile = "string_attrs.json";
20constexpr auto integerJsonFile = "integer_attrs.json";
21
22constexpr auto stringTableFile = "stringTable";
23constexpr auto attrTableFile = "attributeTable";
24constexpr auto attrValueTableFile = "attributeValueTable";
25
26} // namespace
27
28BIOSConfig::BIOSConfig(const char* jsonDir, const char* tableDir,
29 DBusHandler* const dbusHandler) :
30 jsonDir(jsonDir),
31 tableDir(tableDir), dbusHandler(dbusHandler)
32{
33 constructAttributes();
34}
35
36void BIOSConfig::buildTables()
37{
38 fs::create_directory(tableDir);
39 auto stringTable = buildAndStoreStringTable();
40 if (stringTable)
41 {
42 buildAndStoreAttrTables(*stringTable);
43 }
44}
45
46std::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
64void BIOSConfig::constructAttributes()
65{
66 load(jsonDir / stringJsonFile, [this](const Json& entry) {
67 constructAttribute<BIOSStringAttribute>(entry);
68 });
John Wang95e6b3c2020-02-13 09:43:24 +080069 load(jsonDir / stringJsonFile, [this](const Json& entry) {
70 constructAttribute<BIOSIntegerAttribute>(entry);
71 });
John Wangd9659342020-02-27 16:46:05 +080072}
73
74void 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
105std::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
139void BIOSConfig::storeTable(const fs::path& path, const Table& table)
140{
141 BIOSTable biosTable(path.c_str());
142 biosTable.store(table);
143}
144
145std::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
158void 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
191int 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
248void 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