blob: fcbb09faf485b4eb2fe021a8ccfef59a87d41ffd [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 {}
Patrick Williams98e703f2023-08-15 02:34:38 -050086 MOCK_METHOD(void, ibmCompatibleAddedCallback, (sdbusplus::message_t&), ());
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050087 MOCK_METHOD(std::optional<std::string>, getPlatformName, ());
88};
89
John Wangd9659342020-02-27 16:46:05 +080090TEST_F(TestBIOSConfig, buildTablesTest)
91{
92 MockdBusHandler dbusHandler;
93
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050094 MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
95
John Wangd9659342020-02-27 16:46:05 +080096 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
97 .WillByDefault(Throw(std::exception()));
98
Tom Joseph7f839f92020-09-21 10:20:44 +053099 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500100 nullptr, nullptr, &mockBiosSystemConfig);
John Wangd9659342020-02-27 16:46:05 +0800101 biosConfig.buildTables();
102
103 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
104 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
105 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
106
107 EXPECT_TRUE(stringTable);
108 EXPECT_TRUE(attrTable);
109 EXPECT_TRUE(attrValueTable);
110
111 std::set<std::string> expectedStrings = {"HMCManagedState",
112 "On",
113 "Off",
114 "FWBootSide",
115 "Perm",
116 "Temp",
117 "InbandCodeUpdate",
118 "Allowed",
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500119 "Allowed",
John Wangd9659342020-02-27 16:46:05 +0800120 "NotAllowed",
121 "CodeUpdatePolicy",
122 "Concurrent",
123 "Disruptive",
124 "VDD_AVSBUS_RAIL",
125 "SBE_IMAGE_MINIMUM_VALID_ECS",
126 "INTEGER_INVALID_CASE",
127 "str_example1",
128 "str_example2",
129 "str_example3"};
130 std::set<std::string> strings;
131 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
132 stringTable->data(), stringTable->size()))
133 {
134 auto str = table::string::decodeString(entry);
135 strings.emplace(str);
136 }
137
138 EXPECT_EQ(strings, expectedStrings);
139
140 BIOSStringTable biosStringTable(*stringTable);
141
142 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
143 attrTable->size()))
144 {
145 auto header = table::attribute::decodeHeader(entry);
146 auto attrName = biosStringTable.findString(header.stringHandle);
147 auto jsonEntry = findJsonEntry(attrName);
148 EXPECT_TRUE(jsonEntry);
149 switch (header.attrType)
150 {
151 case PLDM_BIOS_STRING:
152 case PLDM_BIOS_STRING_READ_ONLY:
153 {
154 auto stringField = table::attribute::decodeStringEntry(entry);
155 auto stringType = BIOSStringAttribute::strTypeMap.at(
156 jsonEntry->at("string_type").get<std::string>());
157 EXPECT_EQ(stringField.stringType,
158 static_cast<uint8_t>(stringType));
159
160 EXPECT_EQ(
161 stringField.minLength,
162 jsonEntry->at("minimum_string_length").get<uint16_t>());
163 EXPECT_EQ(
164 stringField.maxLength,
165 jsonEntry->at("maximum_string_length").get<uint16_t>());
166 EXPECT_EQ(
167 stringField.defLength,
168 jsonEntry->at("default_string_length").get<uint16_t>());
169 EXPECT_EQ(stringField.defString,
170 jsonEntry->at("default_string").get<std::string>());
171 break;
172 }
John Wang95e6b3c2020-02-13 09:43:24 +0800173 case PLDM_BIOS_INTEGER:
174 case PLDM_BIOS_INTEGER_READ_ONLY:
175 {
176 auto integerField = table::attribute::decodeIntegerEntry(entry);
177 EXPECT_EQ(integerField.lowerBound,
178 jsonEntry->at("lower_bound").get<uint64_t>());
179 EXPECT_EQ(integerField.upperBound,
180 jsonEntry->at("upper_bound").get<uint64_t>());
181 EXPECT_EQ(integerField.scalarIncrement,
182 jsonEntry->at("scalar_increment").get<uint32_t>());
183 EXPECT_EQ(integerField.defaultValue,
184 jsonEntry->at("default_value").get<uint64_t>());
185 break;
186 }
John Wang3be70852020-02-13 15:59:04 +0800187 case PLDM_BIOS_ENUMERATION:
188 case PLDM_BIOS_ENUMERATION_READ_ONLY:
189 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500190 auto [pvHdls,
191 defInds] = table::attribute::decodeEnumEntry(entry);
John Wang3be70852020-02-13 15:59:04 +0800192 auto possibleValues = jsonEntry->at("possible_values")
193 .get<std::vector<std::string>>();
194 std::vector<std::string> strings;
195 for (auto pv : pvHdls)
196 {
197 auto s = biosStringTable.findString(pv);
198 strings.emplace_back(s);
199 }
200 EXPECT_EQ(strings, possibleValues);
201 EXPECT_EQ(defInds.size(), 1);
202
203 auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
204 auto defaultValues = jsonEntry->at("default_values")
205 .get<std::vector<std::string>>();
206 EXPECT_EQ(defValue, defaultValues[0]);
207
208 break;
209 }
John Wangd9659342020-02-27 16:46:05 +0800210 default:
211 EXPECT_TRUE(false);
212 break;
213 }
214 }
215
216 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
217 attrValueTable->data(), attrValueTable->size()))
218 {
219 auto header = table::attribute_value::decodeHeader(entry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500220 auto attrEntry = table::attribute::findByHandle(*attrTable,
221 header.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800222 auto attrHeader = table::attribute::decodeHeader(attrEntry);
223 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
224 auto jsonEntry = findJsonEntry(attrName);
225 EXPECT_TRUE(jsonEntry);
226 switch (header.attrType)
227 {
228 case PLDM_BIOS_STRING:
229 case PLDM_BIOS_STRING_READ_ONLY:
230 {
231 auto value = table::attribute_value::decodeStringEntry(entry);
232 auto defValue =
233 jsonEntry->at("default_string").get<std::string>();
234 EXPECT_EQ(value, defValue);
235 break;
236 }
John Wang95e6b3c2020-02-13 09:43:24 +0800237 case PLDM_BIOS_INTEGER:
238 case PLDM_BIOS_INTEGER_READ_ONLY:
239 {
240 auto value = table::attribute_value::decodeIntegerEntry(entry);
241 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
242 EXPECT_EQ(value, defValue);
243 break;
244 }
John Wang3be70852020-02-13 15:59:04 +0800245 case PLDM_BIOS_ENUMERATION:
246 case PLDM_BIOS_ENUMERATION_READ_ONLY:
247 {
248 auto indices = table::attribute_value::decodeEnumEntry(entry);
249 EXPECT_EQ(indices.size(), 1);
250 auto possibleValues = jsonEntry->at("possible_values")
251 .get<std::vector<std::string>>();
252
253 auto defValues = jsonEntry->at("default_values")
254 .get<std::vector<std::string>>();
255 EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
256 break;
257 }
John Wangd9659342020-02-27 16:46:05 +0800258 default:
259 EXPECT_TRUE(false);
260 break;
261 }
262 }
263}
264
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500265TEST_F(TestBIOSConfig, buildTablesSystemSpecificTest)
266{
267 MockdBusHandler dbusHandler;
268
269 MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
270
271 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
272 .WillByDefault(Throw(std::exception()));
273
274 BIOSConfig biosConfig("./system_type1/bios_jsons", tableDir.c_str(),
275 &dbusHandler, 0, 0, nullptr, nullptr,
276 &mockBiosSystemConfig);
277
278 biosConfig.buildTables();
279
280 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
281 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
282 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
283
284 EXPECT_TRUE(stringTable);
285 EXPECT_TRUE(attrTable);
286 EXPECT_TRUE(attrValueTable);
287
288 BIOSStringTable biosStringTable(*stringTable);
289
290 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
291 attrTable->size()))
292 {
293 auto header = table::attribute::decodeHeader(entry);
294 auto attrName = biosStringTable.findString(header.stringHandle);
295 auto jsonEntry = findJsonEntry(attrName);
296 EXPECT_TRUE(jsonEntry);
297 switch (header.attrType)
298 {
299 case PLDM_BIOS_STRING:
300 case PLDM_BIOS_STRING_READ_ONLY:
301 {
302 if (attrName == "str_example2")
303 {
304 auto stringField =
305 table::attribute::decodeStringEntry(entry);
306 EXPECT_EQ(stringField.maxLength, 200);
307 }
308
309 break;
310 }
311 case PLDM_BIOS_INTEGER:
312 case PLDM_BIOS_INTEGER_READ_ONLY:
313 {
314 if (attrName == "SBE_IMAGE_MINIMUM_VALID_ECS")
315 {
316 auto integerField =
317 table::attribute::decodeIntegerEntry(entry);
318 EXPECT_EQ(integerField.upperBound, 30);
319 }
320 break;
321 }
322 case PLDM_BIOS_ENUMERATION:
323 case PLDM_BIOS_ENUMERATION_READ_ONLY:
324 {
325 if (attrName == "FWBootSide")
326 {
327 auto [pvHdls,
328 defInds] = table::attribute::decodeEnumEntry(entry);
329 auto defValue =
330 biosStringTable.findString(pvHdls[defInds[0]]);
331 EXPECT_EQ(defValue, "Temp");
332 }
333 }
334 }
335 }
336}
337
John Wangd9659342020-02-27 16:46:05 +0800338TEST_F(TestBIOSConfig, setAttrValue)
339{
340 MockdBusHandler dbusHandler;
341
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500342 MockBiosSystemConfig mockBiosSystemConfig(&dbusHandler);
343
Tom Joseph7f839f92020-09-21 10:20:44 +0530344 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500345 nullptr, nullptr, &mockBiosSystemConfig);
John Wangd9659342020-02-27 16:46:05 +0800346 biosConfig.removeTables();
347 biosConfig.buildTables();
348
349 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
350 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
351
352 BIOSStringTable biosStringTable(*stringTable);
353 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
354 attrTable->size());
355 auto stringHandle = biosStringTable.findHandle("str_example1");
356 uint16_t attrHandle{};
357
358 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
359 attrTable->size()))
360 {
361 auto header = table::attribute::decodeHeader(entry);
362 if (header.stringHandle == stringHandle)
363 {
364 attrHandle = header.attrHandle;
365 break;
366 }
367 }
368
369 EXPECT_NE(attrHandle, 0);
370
371 std::vector<uint8_t> attrValueEntry{
372 0, 0, /* attr handle */
373 1, /* attr type string read-write */
374 4, 0, /* current string length */
375 'a', 'b', 'c', 'd', /* defaut value string handle index */
376 };
377
378 attrValueEntry[0] = attrHandle & 0xff;
379 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
380
381 DBusMapping dbusMapping{"/xyz/abc/def",
382 "xyz.openbmc_project.str_example1.value",
383 "Str_example1", "string"};
384 PropertyValue value = std::string("abcd");
385 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
386
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600387 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
388 attrValueEntry.size(), false);
John Wangd9659342020-02-27 16:46:05 +0800389 EXPECT_EQ(rc, PLDM_SUCCESS);
390
391 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
392 auto findEntry =
393 [&attrValueTable](
394 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
395 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
396 attrValueTable->data(), attrValueTable->size()))
397 {
398 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
399 if (attrHandle == handle)
400 return entry;
401 }
402 return nullptr;
403 };
404
405 auto entry = findEntry(attrHandle);
406 EXPECT_NE(entry, nullptr);
407
408 auto p = reinterpret_cast<const uint8_t*>(entry);
409 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
410 ElementsAreArray(attrValueEntry));
411}