blob: 3a1599295a9329ebb6c8a7a5e120f11a9ffbf26d [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"
Kamalkumar Patel3c50c822024-01-30 07:14:40 -06006#include "libpldmresponder/platform_config.hpp"
John Wangd9659342020-02-27 16:46:05 +08007#include "mocked_bios.hpp"
John Wangd9659342020-02-27 16:46:05 +08008
George Liu6492f522020-06-16 10:34:05 +08009#include <nlohmann/json.hpp>
10
John Wangd9659342020-02-27 16:46:05 +080011#include <fstream>
12#include <memory>
John Wangd9659342020-02-27 16:46:05 +080013
14#include <gmock/gmock.h>
15#include <gtest/gtest.h>
16
17using namespace pldm::bios::utils;
Brad Bishop5079ac42021-08-19 18:35:06 -040018using namespace pldm::responder::bios;
19using namespace pldm::utils;
John Wangd9659342020-02-27 16:46:05 +080020
21using ::testing::_;
22using ::testing::ElementsAreArray;
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050023using ::testing::Return;
24using ::testing::StrEq;
John Wangd9659342020-02-27 16:46:05 +080025using ::testing::Throw;
26
27class TestBIOSConfig : public ::testing::Test
28{
29 public:
30 static void SetUpTestCase() // will execute once at the begining of all
31 // TestBIOSConfig objects
32 {
33 char tmpdir[] = "/tmp/BIOSTables.XXXXXX";
34 tableDir = fs::path(mkdtemp(tmpdir));
35
36 std::vector<fs::path> paths = {
37 "./bios_jsons/string_attrs.json",
John Wang95e6b3c2020-02-13 09:43:24 +080038 "./bios_jsons/integer_attrs.json",
John Wang3be70852020-02-13 15:59:04 +080039 "./bios_jsons/enum_attrs.json",
John Wangd9659342020-02-27 16:46:05 +080040 };
41
42 for (auto& path : paths)
43 {
44 std::ifstream file;
45 file.open(path);
46 auto j = Json::parse(file);
47 jsons.emplace_back(j);
48 }
49 }
50
51 std::optional<Json> findJsonEntry(const std::string& name)
52 {
53 for (auto& json : jsons)
54 {
55 auto entries = json.at("entries");
56 for (auto& entry : entries)
57 {
58 auto n = entry.at("attribute_name").get<std::string>();
59 if (n == name)
60 {
61 return entry;
62 }
63 }
64 }
65 return std::nullopt;
66 }
67
68 static void TearDownTestCase() // will be executed once at th end of all
69 // TestBIOSConfig objects
70 {
71 fs::remove_all(tableDir);
72 }
73
74 static fs::path tableDir;
75 static std::vector<Json> jsons;
76};
77
78fs::path TestBIOSConfig::tableDir;
79std::vector<Json> TestBIOSConfig::jsons;
80
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060081class MockSystemConfig : public pldm::responder::platform_config::Handler
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050082{
83 public:
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060084 MockSystemConfig() {}
Patrick Williams98e703f2023-08-15 02:34:38 -050085 MOCK_METHOD(void, ibmCompatibleAddedCallback, (sdbusplus::message_t&), ());
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060086 MOCK_METHOD(std::optional<std::filesystem::path>, getPlatformName, ());
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050087};
88
John Wangd9659342020-02-27 16:46:05 +080089TEST_F(TestBIOSConfig, buildTablesTest)
90{
91 MockdBusHandler dbusHandler;
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060092 MockSystemConfig mockSystemConfig;
John Wangd9659342020-02-27 16:46:05 +080093
Archana Kakani62dd8ff2024-02-12 10:00:40 -060094 EXPECT_CALL(mockSystemConfig, getPlatformName())
95 .WillOnce(Return(std::filesystem::path("bios_jsons")));
John Wangd9659342020-02-27 16:46:05 +080096
Archana Kakani62dd8ff2024-02-12 10:00:40 -060097 BIOSConfig biosConfig("./", tableDir.c_str(), &dbusHandler, 0, 0, nullptr,
98 nullptr, &mockSystemConfig, []() {});
John Wangd9659342020-02-27 16:46:05 +080099 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
100 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
101 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
102
103 EXPECT_TRUE(stringTable);
104 EXPECT_TRUE(attrTable);
105 EXPECT_TRUE(attrValueTable);
106
107 std::set<std::string> expectedStrings = {"HMCManagedState",
108 "On",
109 "Off",
110 "FWBootSide",
111 "Perm",
112 "Temp",
113 "InbandCodeUpdate",
114 "Allowed",
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500115 "Allowed",
John Wangd9659342020-02-27 16:46:05 +0800116 "NotAllowed",
117 "CodeUpdatePolicy",
118 "Concurrent",
119 "Disruptive",
120 "VDD_AVSBUS_RAIL",
121 "SBE_IMAGE_MINIMUM_VALID_ECS",
122 "INTEGER_INVALID_CASE",
123 "str_example1",
124 "str_example2",
125 "str_example3"};
126 std::set<std::string> strings;
127 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
128 stringTable->data(), stringTable->size()))
129 {
130 auto str = table::string::decodeString(entry);
131 strings.emplace(str);
132 }
133
134 EXPECT_EQ(strings, expectedStrings);
135
136 BIOSStringTable biosStringTable(*stringTable);
137
138 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
139 attrTable->size()))
140 {
141 auto header = table::attribute::decodeHeader(entry);
142 auto attrName = biosStringTable.findString(header.stringHandle);
143 auto jsonEntry = findJsonEntry(attrName);
144 EXPECT_TRUE(jsonEntry);
145 switch (header.attrType)
146 {
147 case PLDM_BIOS_STRING:
148 case PLDM_BIOS_STRING_READ_ONLY:
149 {
150 auto stringField = table::attribute::decodeStringEntry(entry);
151 auto stringType = BIOSStringAttribute::strTypeMap.at(
152 jsonEntry->at("string_type").get<std::string>());
153 EXPECT_EQ(stringField.stringType,
154 static_cast<uint8_t>(stringType));
155
156 EXPECT_EQ(
157 stringField.minLength,
158 jsonEntry->at("minimum_string_length").get<uint16_t>());
159 EXPECT_EQ(
160 stringField.maxLength,
161 jsonEntry->at("maximum_string_length").get<uint16_t>());
162 EXPECT_EQ(
163 stringField.defLength,
164 jsonEntry->at("default_string_length").get<uint16_t>());
165 EXPECT_EQ(stringField.defString,
166 jsonEntry->at("default_string").get<std::string>());
167 break;
168 }
John Wang95e6b3c2020-02-13 09:43:24 +0800169 case PLDM_BIOS_INTEGER:
170 case PLDM_BIOS_INTEGER_READ_ONLY:
171 {
172 auto integerField = table::attribute::decodeIntegerEntry(entry);
173 EXPECT_EQ(integerField.lowerBound,
174 jsonEntry->at("lower_bound").get<uint64_t>());
175 EXPECT_EQ(integerField.upperBound,
176 jsonEntry->at("upper_bound").get<uint64_t>());
177 EXPECT_EQ(integerField.scalarIncrement,
178 jsonEntry->at("scalar_increment").get<uint32_t>());
179 EXPECT_EQ(integerField.defaultValue,
180 jsonEntry->at("default_value").get<uint64_t>());
181 break;
182 }
John Wang3be70852020-02-13 15:59:04 +0800183 case PLDM_BIOS_ENUMERATION:
184 case PLDM_BIOS_ENUMERATION_READ_ONLY:
185 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500186 auto [pvHdls,
187 defInds] = table::attribute::decodeEnumEntry(entry);
John Wang3be70852020-02-13 15:59:04 +0800188 auto possibleValues = jsonEntry->at("possible_values")
189 .get<std::vector<std::string>>();
190 std::vector<std::string> strings;
191 for (auto pv : pvHdls)
192 {
193 auto s = biosStringTable.findString(pv);
194 strings.emplace_back(s);
195 }
196 EXPECT_EQ(strings, possibleValues);
197 EXPECT_EQ(defInds.size(), 1);
198
199 auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
200 auto defaultValues = jsonEntry->at("default_values")
201 .get<std::vector<std::string>>();
202 EXPECT_EQ(defValue, defaultValues[0]);
203
204 break;
205 }
John Wangd9659342020-02-27 16:46:05 +0800206 default:
207 EXPECT_TRUE(false);
208 break;
209 }
210 }
211
212 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
213 attrValueTable->data(), attrValueTable->size()))
214 {
215 auto header = table::attribute_value::decodeHeader(entry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500216 auto attrEntry = table::attribute::findByHandle(*attrTable,
217 header.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800218 auto attrHeader = table::attribute::decodeHeader(attrEntry);
219 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
220 auto jsonEntry = findJsonEntry(attrName);
221 EXPECT_TRUE(jsonEntry);
222 switch (header.attrType)
223 {
224 case PLDM_BIOS_STRING:
225 case PLDM_BIOS_STRING_READ_ONLY:
226 {
227 auto value = table::attribute_value::decodeStringEntry(entry);
228 auto defValue =
229 jsonEntry->at("default_string").get<std::string>();
230 EXPECT_EQ(value, defValue);
231 break;
232 }
John Wang95e6b3c2020-02-13 09:43:24 +0800233 case PLDM_BIOS_INTEGER:
234 case PLDM_BIOS_INTEGER_READ_ONLY:
235 {
236 auto value = table::attribute_value::decodeIntegerEntry(entry);
237 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
238 EXPECT_EQ(value, defValue);
239 break;
240 }
John Wang3be70852020-02-13 15:59:04 +0800241 case PLDM_BIOS_ENUMERATION:
242 case PLDM_BIOS_ENUMERATION_READ_ONLY:
243 {
244 auto indices = table::attribute_value::decodeEnumEntry(entry);
245 EXPECT_EQ(indices.size(), 1);
246 auto possibleValues = jsonEntry->at("possible_values")
247 .get<std::vector<std::string>>();
248
249 auto defValues = jsonEntry->at("default_values")
250 .get<std::vector<std::string>>();
251 EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
252 break;
253 }
John Wangd9659342020-02-27 16:46:05 +0800254 default:
255 EXPECT_TRUE(false);
256 break;
257 }
258 }
259}
260
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500261TEST_F(TestBIOSConfig, buildTablesSystemSpecificTest)
262{
263 MockdBusHandler dbusHandler;
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600264 MockSystemConfig mockSystemConfig;
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500265
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600266 EXPECT_CALL(mockSystemConfig, getPlatformName()).WillOnce(Return(""));
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500267 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
268 .WillByDefault(Throw(std::exception()));
269
270 BIOSConfig biosConfig("./system_type1/bios_jsons", tableDir.c_str(),
271 &dbusHandler, 0, 0, nullptr, nullptr,
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600272 &mockSystemConfig, []() {});
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500273
274 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
275 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
276 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
277
278 EXPECT_TRUE(stringTable);
279 EXPECT_TRUE(attrTable);
280 EXPECT_TRUE(attrValueTable);
281
282 BIOSStringTable biosStringTable(*stringTable);
283
284 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
285 attrTable->size()))
286 {
287 auto header = table::attribute::decodeHeader(entry);
288 auto attrName = biosStringTable.findString(header.stringHandle);
289 auto jsonEntry = findJsonEntry(attrName);
290 EXPECT_TRUE(jsonEntry);
291 switch (header.attrType)
292 {
293 case PLDM_BIOS_STRING:
294 case PLDM_BIOS_STRING_READ_ONLY:
295 {
296 if (attrName == "str_example2")
297 {
298 auto stringField =
299 table::attribute::decodeStringEntry(entry);
300 EXPECT_EQ(stringField.maxLength, 200);
301 }
302
303 break;
304 }
305 case PLDM_BIOS_INTEGER:
306 case PLDM_BIOS_INTEGER_READ_ONLY:
307 {
308 if (attrName == "SBE_IMAGE_MINIMUM_VALID_ECS")
309 {
310 auto integerField =
311 table::attribute::decodeIntegerEntry(entry);
312 EXPECT_EQ(integerField.upperBound, 30);
313 }
314 break;
315 }
316 case PLDM_BIOS_ENUMERATION:
317 case PLDM_BIOS_ENUMERATION_READ_ONLY:
318 {
319 if (attrName == "FWBootSide")
320 {
321 auto [pvHdls,
322 defInds] = table::attribute::decodeEnumEntry(entry);
323 auto defValue =
324 biosStringTable.findString(pvHdls[defInds[0]]);
325 EXPECT_EQ(defValue, "Temp");
326 }
327 }
328 }
329 }
330}
331
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600332TEST_F(TestBIOSConfig, setBIOSTable)
333{
334 MockdBusHandler dbusHandler;
335 MockSystemConfig mockSystemConfig;
336
337 EXPECT_CALL(mockSystemConfig, getPlatformName()).WillOnce(Return("jsons"));
338 BIOSConfig biosConfig("./", tableDir.c_str(), &dbusHandler, 0, 0, nullptr,
339 nullptr, &mockSystemConfig, []() {});
340
341 std::set<std::string> strings{"pvm_system_name", "pvm_stop_at_standby",
342 "fw_boot_side", "fw_next_boot_side"};
343
344 Table table;
345 for (const auto& elem : strings)
346 {
347 table::string::constructEntry(table, elem);
348 }
349
350 table::appendPadAndChecksum(table);
351 auto rc = biosConfig.setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
352 EXPECT_EQ(rc, PLDM_SUCCESS);
353
354 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
355 EXPECT_TRUE(stringTable);
356}
357
358TEST_F(TestBIOSConfig, getBIOSTableFailure)
359{
360 MockdBusHandler dbusHandler;
361 MockSystemConfig mockSystemConfig;
362
363 EXPECT_CALL(mockSystemConfig, getPlatformName()).WillOnce(Return("jsons"));
364 BIOSConfig biosConfig("./", tableDir.c_str(), &dbusHandler, 0, 0, nullptr,
365 nullptr, &mockSystemConfig, []() {});
366
367 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
368 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
369 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
370
371 EXPECT_FALSE(stringTable);
372 EXPECT_FALSE(attrTable);
373 EXPECT_FALSE(attrValueTable);
374}
375
376TEST_F(TestBIOSConfig, setAttrValueFailure)
377{
378 MockdBusHandler dbusHandler;
379 MockSystemConfig mockSystemConfig;
380
381 EXPECT_CALL(mockSystemConfig, getPlatformName()).WillOnce(Return("jsons"));
382 BIOSConfig biosConfig("./", tableDir.c_str(), &dbusHandler, 0, 0, nullptr,
383 nullptr, &mockSystemConfig, []() {});
384
385 std::vector<uint8_t> attrValueEntry{
386 0, 0, /* attr handle */
387 1, /* attr type string read-write */
388 4, 0, /* current string length */
389 'a', 'b', 'c', 'd', /* defaut value string handle index */
390 };
391
392 uint16_t attrHandle{10};
393 attrValueEntry[0] = attrHandle & 0xff;
394 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
395
396 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
397 attrValueEntry.size(), false);
398 std::cout << "Error in settig Attribute " << rc << std::endl;
399 EXPECT_EQ(rc, PLDM_BIOS_TABLE_UNAVAILABLE);
400}
401
John Wangd9659342020-02-27 16:46:05 +0800402TEST_F(TestBIOSConfig, setAttrValue)
403{
404 MockdBusHandler dbusHandler;
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600405 MockSystemConfig mockSystemConfig;
John Wangd9659342020-02-27 16:46:05 +0800406
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600407 EXPECT_CALL(mockSystemConfig, getPlatformName()).WillOnce(Return(""));
Tom Joseph7f839f92020-09-21 10:20:44 +0530408 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600409 nullptr, nullptr, &mockSystemConfig, []() {});
John Wangd9659342020-02-27 16:46:05 +0800410
411 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
412 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
413
414 BIOSStringTable biosStringTable(*stringTable);
415 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
416 attrTable->size());
417 auto stringHandle = biosStringTable.findHandle("str_example1");
418 uint16_t attrHandle{};
419
420 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
421 attrTable->size()))
422 {
423 auto header = table::attribute::decodeHeader(entry);
424 if (header.stringHandle == stringHandle)
425 {
426 attrHandle = header.attrHandle;
427 break;
428 }
429 }
430
431 EXPECT_NE(attrHandle, 0);
432
433 std::vector<uint8_t> attrValueEntry{
434 0, 0, /* attr handle */
435 1, /* attr type string read-write */
436 4, 0, /* current string length */
437 'a', 'b', 'c', 'd', /* defaut value string handle index */
438 };
439
440 attrValueEntry[0] = attrHandle & 0xff;
441 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
442
443 DBusMapping dbusMapping{"/xyz/abc/def",
444 "xyz.openbmc_project.str_example1.value",
445 "Str_example1", "string"};
446 PropertyValue value = std::string("abcd");
447 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
448
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600449 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
450 attrValueEntry.size(), false);
John Wangd9659342020-02-27 16:46:05 +0800451 EXPECT_EQ(rc, PLDM_SUCCESS);
452
453 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
454 auto findEntry =
455 [&attrValueTable](
456 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
457 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
458 attrValueTable->data(), attrValueTable->size()))
459 {
460 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
461 if (attrHandle == handle)
462 return entry;
463 }
464 return nullptr;
465 };
466
467 auto entry = findEntry(attrHandle);
468 EXPECT_NE(entry, nullptr);
469
470 auto p = reinterpret_cast<const uint8_t*>(entry);
471 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
472 ElementsAreArray(attrValueEntry));
473}