blob: d70a961e120b06b6ab89089fca8bca83bd66f0a7 [file] [log] [blame]
Deepak Kodihallid130e1a2020-06-17 05:55:32 -05001#include "common/bios_utils.hpp"
Tom Joseph53279882021-04-28 06:29:13 -07002#include "common/test/mocked_utils.hpp"
John Wangd9659342020-02-27 16:46:05 +08003#include "libpldmresponder/bios_config.hpp"
4#include "libpldmresponder/bios_string_attribute.hpp"
Sagar Srinivas11ce8d22022-07-28 11:32:34 -05005#include "libpldmresponder/oem_handler.hpp"
John Wangd9659342020-02-27 16:46:05 +08006#include "mocked_bios.hpp"
John Wangd9659342020-02-27 16:46:05 +08007
George Liu6492f522020-06-16 10:34:05 +08008#include <nlohmann/json.hpp>
9
John Wangd9659342020-02-27 16:46:05 +080010#include <fstream>
11#include <memory>
John Wangd9659342020-02-27 16:46:05 +080012
13#include <gmock/gmock.h>
14#include <gtest/gtest.h>
15
16using namespace pldm::bios::utils;
Brad Bishop5079ac42021-08-19 18:35:06 -040017using namespace pldm::responder::bios;
18using namespace pldm::utils;
John Wangd9659342020-02-27 16:46:05 +080019
20using ::testing::_;
21using ::testing::ElementsAreArray;
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050022using ::testing::Return;
23using ::testing::StrEq;
John Wangd9659342020-02-27 16:46:05 +080024using ::testing::Throw;
25
26class TestBIOSConfig : public ::testing::Test
27{
28 public:
29 static void SetUpTestCase() // will execute once at the begining of all
30 // TestBIOSConfig objects
31 {
32 char tmpdir[] = "/tmp/BIOSTables.XXXXXX";
33 tableDir = fs::path(mkdtemp(tmpdir));
34
35 std::vector<fs::path> paths = {
36 "./bios_jsons/string_attrs.json",
John Wang95e6b3c2020-02-13 09:43:24 +080037 "./bios_jsons/integer_attrs.json",
John Wang3be70852020-02-13 15:59:04 +080038 "./bios_jsons/enum_attrs.json",
John Wangd9659342020-02-27 16:46:05 +080039 };
40
41 for (auto& path : paths)
42 {
43 std::ifstream file;
44 file.open(path);
45 auto j = Json::parse(file);
46 jsons.emplace_back(j);
47 }
48 }
49
50 std::optional<Json> findJsonEntry(const std::string& name)
51 {
52 for (auto& json : jsons)
53 {
54 auto entries = json.at("entries");
55 for (auto& entry : entries)
56 {
57 auto n = entry.at("attribute_name").get<std::string>();
58 if (n == name)
59 {
60 return entry;
61 }
62 }
63 }
64 return std::nullopt;
65 }
66
67 static void TearDownTestCase() // will be executed once at th end of all
68 // TestBIOSConfig objects
69 {
70 fs::remove_all(tableDir);
71 }
72
73 static fs::path tableDir;
74 static std::vector<Json> jsons;
75};
76
77fs::path TestBIOSConfig::tableDir;
78std::vector<Json> TestBIOSConfig::jsons;
79
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050080class MockBiosSystemConfig : public pldm::responder::oem_bios::Handler
81{
82 public:
83 MockBiosSystemConfig(const pldm::utils::DBusHandler* dBusIntf) :
84 pldm::responder::oem_bios::Handler(dBusIntf)
85 {}
86 MOCK_METHOD(void, ibmCompatibleAddedCallback,
87 (sdbusplus::message::message&), ());
88 MOCK_METHOD(std::optional<std::string>, getPlatformName, ());
89};
90
John Wangd9659342020-02-27 16:46:05 +080091TEST_F(TestBIOSConfig, buildTablesTest)
92{
93 MockdBusHandler dbusHandler;
94
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050095 MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
96
John Wangd9659342020-02-27 16:46:05 +080097 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
98 .WillByDefault(Throw(std::exception()));
99
Tom Joseph7f839f92020-09-21 10:20:44 +0530100 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500101 nullptr, nullptr, &mockBiosSystemConfig);
John Wangd9659342020-02-27 16:46:05 +0800102 biosConfig.buildTables();
103
104 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
105 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
106 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
107
108 EXPECT_TRUE(stringTable);
109 EXPECT_TRUE(attrTable);
110 EXPECT_TRUE(attrValueTable);
111
112 std::set<std::string> expectedStrings = {"HMCManagedState",
113 "On",
114 "Off",
115 "FWBootSide",
116 "Perm",
117 "Temp",
118 "InbandCodeUpdate",
119 "Allowed",
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500120 "Allowed",
John Wangd9659342020-02-27 16:46:05 +0800121 "NotAllowed",
122 "CodeUpdatePolicy",
123 "Concurrent",
124 "Disruptive",
125 "VDD_AVSBUS_RAIL",
126 "SBE_IMAGE_MINIMUM_VALID_ECS",
127 "INTEGER_INVALID_CASE",
128 "str_example1",
129 "str_example2",
130 "str_example3"};
131 std::set<std::string> strings;
132 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
133 stringTable->data(), stringTable->size()))
134 {
135 auto str = table::string::decodeString(entry);
136 strings.emplace(str);
137 }
138
139 EXPECT_EQ(strings, expectedStrings);
140
141 BIOSStringTable biosStringTable(*stringTable);
142
143 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
144 attrTable->size()))
145 {
146 auto header = table::attribute::decodeHeader(entry);
147 auto attrName = biosStringTable.findString(header.stringHandle);
148 auto jsonEntry = findJsonEntry(attrName);
149 EXPECT_TRUE(jsonEntry);
150 switch (header.attrType)
151 {
152 case PLDM_BIOS_STRING:
153 case PLDM_BIOS_STRING_READ_ONLY:
154 {
155 auto stringField = table::attribute::decodeStringEntry(entry);
156 auto stringType = BIOSStringAttribute::strTypeMap.at(
157 jsonEntry->at("string_type").get<std::string>());
158 EXPECT_EQ(stringField.stringType,
159 static_cast<uint8_t>(stringType));
160
161 EXPECT_EQ(
162 stringField.minLength,
163 jsonEntry->at("minimum_string_length").get<uint16_t>());
164 EXPECT_EQ(
165 stringField.maxLength,
166 jsonEntry->at("maximum_string_length").get<uint16_t>());
167 EXPECT_EQ(
168 stringField.defLength,
169 jsonEntry->at("default_string_length").get<uint16_t>());
170 EXPECT_EQ(stringField.defString,
171 jsonEntry->at("default_string").get<std::string>());
172 break;
173 }
John Wang95e6b3c2020-02-13 09:43:24 +0800174 case PLDM_BIOS_INTEGER:
175 case PLDM_BIOS_INTEGER_READ_ONLY:
176 {
177 auto integerField = table::attribute::decodeIntegerEntry(entry);
178 EXPECT_EQ(integerField.lowerBound,
179 jsonEntry->at("lower_bound").get<uint64_t>());
180 EXPECT_EQ(integerField.upperBound,
181 jsonEntry->at("upper_bound").get<uint64_t>());
182 EXPECT_EQ(integerField.scalarIncrement,
183 jsonEntry->at("scalar_increment").get<uint32_t>());
184 EXPECT_EQ(integerField.defaultValue,
185 jsonEntry->at("default_value").get<uint64_t>());
186 break;
187 }
John Wang3be70852020-02-13 15:59:04 +0800188 case PLDM_BIOS_ENUMERATION:
189 case PLDM_BIOS_ENUMERATION_READ_ONLY:
190 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500191 auto [pvHdls,
192 defInds] = table::attribute::decodeEnumEntry(entry);
John Wang3be70852020-02-13 15:59:04 +0800193 auto possibleValues = jsonEntry->at("possible_values")
194 .get<std::vector<std::string>>();
195 std::vector<std::string> strings;
196 for (auto pv : pvHdls)
197 {
198 auto s = biosStringTable.findString(pv);
199 strings.emplace_back(s);
200 }
201 EXPECT_EQ(strings, possibleValues);
202 EXPECT_EQ(defInds.size(), 1);
203
204 auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
205 auto defaultValues = jsonEntry->at("default_values")
206 .get<std::vector<std::string>>();
207 EXPECT_EQ(defValue, defaultValues[0]);
208
209 break;
210 }
John Wangd9659342020-02-27 16:46:05 +0800211 default:
212 EXPECT_TRUE(false);
213 break;
214 }
215 }
216
217 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
218 attrValueTable->data(), attrValueTable->size()))
219 {
220 auto header = table::attribute_value::decodeHeader(entry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500221 auto attrEntry = table::attribute::findByHandle(*attrTable,
222 header.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800223 auto attrHeader = table::attribute::decodeHeader(attrEntry);
224 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
225 auto jsonEntry = findJsonEntry(attrName);
226 EXPECT_TRUE(jsonEntry);
227 switch (header.attrType)
228 {
229 case PLDM_BIOS_STRING:
230 case PLDM_BIOS_STRING_READ_ONLY:
231 {
232 auto value = table::attribute_value::decodeStringEntry(entry);
233 auto defValue =
234 jsonEntry->at("default_string").get<std::string>();
235 EXPECT_EQ(value, defValue);
236 break;
237 }
John Wang95e6b3c2020-02-13 09:43:24 +0800238 case PLDM_BIOS_INTEGER:
239 case PLDM_BIOS_INTEGER_READ_ONLY:
240 {
241 auto value = table::attribute_value::decodeIntegerEntry(entry);
242 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
243 EXPECT_EQ(value, defValue);
244 break;
245 }
John Wang3be70852020-02-13 15:59:04 +0800246 case PLDM_BIOS_ENUMERATION:
247 case PLDM_BIOS_ENUMERATION_READ_ONLY:
248 {
249 auto indices = table::attribute_value::decodeEnumEntry(entry);
250 EXPECT_EQ(indices.size(), 1);
251 auto possibleValues = jsonEntry->at("possible_values")
252 .get<std::vector<std::string>>();
253
254 auto defValues = jsonEntry->at("default_values")
255 .get<std::vector<std::string>>();
256 EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
257 break;
258 }
John Wangd9659342020-02-27 16:46:05 +0800259 default:
260 EXPECT_TRUE(false);
261 break;
262 }
263 }
264}
265
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500266TEST_F(TestBIOSConfig, buildTablesSystemSpecificTest)
267{
268 MockdBusHandler dbusHandler;
269
270 MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
271
272 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
273 .WillByDefault(Throw(std::exception()));
274
275 BIOSConfig biosConfig("./system_type1/bios_jsons", tableDir.c_str(),
276 &dbusHandler, 0, 0, nullptr, nullptr,
277 &mockBiosSystemConfig);
278
279 biosConfig.buildTables();
280
281 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
282 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
283 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
284
285 EXPECT_TRUE(stringTable);
286 EXPECT_TRUE(attrTable);
287 EXPECT_TRUE(attrValueTable);
288
289 BIOSStringTable biosStringTable(*stringTable);
290
291 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
292 attrTable->size()))
293 {
294 auto header = table::attribute::decodeHeader(entry);
295 auto attrName = biosStringTable.findString(header.stringHandle);
296 auto jsonEntry = findJsonEntry(attrName);
297 EXPECT_TRUE(jsonEntry);
298 switch (header.attrType)
299 {
300 case PLDM_BIOS_STRING:
301 case PLDM_BIOS_STRING_READ_ONLY:
302 {
303 if (attrName == "str_example2")
304 {
305 auto stringField =
306 table::attribute::decodeStringEntry(entry);
307 EXPECT_EQ(stringField.maxLength, 200);
308 }
309
310 break;
311 }
312 case PLDM_BIOS_INTEGER:
313 case PLDM_BIOS_INTEGER_READ_ONLY:
314 {
315 if (attrName == "SBE_IMAGE_MINIMUM_VALID_ECS")
316 {
317 auto integerField =
318 table::attribute::decodeIntegerEntry(entry);
319 EXPECT_EQ(integerField.upperBound, 30);
320 }
321 break;
322 }
323 case PLDM_BIOS_ENUMERATION:
324 case PLDM_BIOS_ENUMERATION_READ_ONLY:
325 {
326 if (attrName == "FWBootSide")
327 {
328 auto [pvHdls,
329 defInds] = table::attribute::decodeEnumEntry(entry);
330 auto defValue =
331 biosStringTable.findString(pvHdls[defInds[0]]);
332 EXPECT_EQ(defValue, "Temp");
333 }
334 }
335 }
336 }
337}
338
John Wangd9659342020-02-27 16:46:05 +0800339TEST_F(TestBIOSConfig, setAttrValue)
340{
341 MockdBusHandler dbusHandler;
342
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500343 MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
344
Tom Joseph7f839f92020-09-21 10:20:44 +0530345 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500346 nullptr, nullptr, &mockBiosSystemConfig);
John Wangd9659342020-02-27 16:46:05 +0800347 biosConfig.removeTables();
348 biosConfig.buildTables();
349
350 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
351 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
352
353 BIOSStringTable biosStringTable(*stringTable);
354 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
355 attrTable->size());
356 auto stringHandle = biosStringTable.findHandle("str_example1");
357 uint16_t attrHandle{};
358
359 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
360 attrTable->size()))
361 {
362 auto header = table::attribute::decodeHeader(entry);
363 if (header.stringHandle == stringHandle)
364 {
365 attrHandle = header.attrHandle;
366 break;
367 }
368 }
369
370 EXPECT_NE(attrHandle, 0);
371
372 std::vector<uint8_t> attrValueEntry{
373 0, 0, /* attr handle */
374 1, /* attr type string read-write */
375 4, 0, /* current string length */
376 'a', 'b', 'c', 'd', /* defaut value string handle index */
377 };
378
379 attrValueEntry[0] = attrHandle & 0xff;
380 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
381
382 DBusMapping dbusMapping{"/xyz/abc/def",
383 "xyz.openbmc_project.str_example1.value",
384 "Str_example1", "string"};
385 PropertyValue value = std::string("abcd");
386 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
387
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600388 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
389 attrValueEntry.size(), false);
John Wangd9659342020-02-27 16:46:05 +0800390 EXPECT_EQ(rc, PLDM_SUCCESS);
391
392 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
393 auto findEntry =
394 [&attrValueTable](
395 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
396 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
397 attrValueTable->data(), attrValueTable->size()))
398 {
399 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
400 if (attrHandle == handle)
401 return entry;
402 }
403 return nullptr;
404 };
405
406 auto entry = findEntry(attrHandle);
407 EXPECT_NE(entry, nullptr);
408
409 auto p = reinterpret_cast<const uint8_t*>(entry);
410 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
411 ElementsAreArray(attrValueEntry));
412}