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