blob: d073e85382ffb9366b96d5176c0171b3d1600ea4 [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
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060094 EXPECT_CALL(mockSystemConfig, getPlatformName()).WillOnce(Return(""));
John Wangd9659342020-02-27 16:46:05 +080095 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
96 .WillByDefault(Throw(std::exception()));
97
Tom Joseph7f839f92020-09-21 10:20:44 +053098 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060099 nullptr, nullptr, &mockSystemConfig);
John Wangd9659342020-02-27 16:46:05 +0800100 biosConfig.buildTables();
John Wangd9659342020-02-27 16:46:05 +0800101 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
102 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
103 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
104
105 EXPECT_TRUE(stringTable);
106 EXPECT_TRUE(attrTable);
107 EXPECT_TRUE(attrValueTable);
108
109 std::set<std::string> expectedStrings = {"HMCManagedState",
110 "On",
111 "Off",
112 "FWBootSide",
113 "Perm",
114 "Temp",
115 "InbandCodeUpdate",
116 "Allowed",
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500117 "Allowed",
John Wangd9659342020-02-27 16:46:05 +0800118 "NotAllowed",
119 "CodeUpdatePolicy",
120 "Concurrent",
121 "Disruptive",
122 "VDD_AVSBUS_RAIL",
123 "SBE_IMAGE_MINIMUM_VALID_ECS",
124 "INTEGER_INVALID_CASE",
125 "str_example1",
126 "str_example2",
127 "str_example3"};
128 std::set<std::string> strings;
129 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
130 stringTable->data(), stringTable->size()))
131 {
132 auto str = table::string::decodeString(entry);
133 strings.emplace(str);
134 }
135
136 EXPECT_EQ(strings, expectedStrings);
137
138 BIOSStringTable biosStringTable(*stringTable);
139
140 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
141 attrTable->size()))
142 {
143 auto header = table::attribute::decodeHeader(entry);
144 auto attrName = biosStringTable.findString(header.stringHandle);
145 auto jsonEntry = findJsonEntry(attrName);
146 EXPECT_TRUE(jsonEntry);
147 switch (header.attrType)
148 {
149 case PLDM_BIOS_STRING:
150 case PLDM_BIOS_STRING_READ_ONLY:
151 {
152 auto stringField = table::attribute::decodeStringEntry(entry);
153 auto stringType = BIOSStringAttribute::strTypeMap.at(
154 jsonEntry->at("string_type").get<std::string>());
155 EXPECT_EQ(stringField.stringType,
156 static_cast<uint8_t>(stringType));
157
158 EXPECT_EQ(
159 stringField.minLength,
160 jsonEntry->at("minimum_string_length").get<uint16_t>());
161 EXPECT_EQ(
162 stringField.maxLength,
163 jsonEntry->at("maximum_string_length").get<uint16_t>());
164 EXPECT_EQ(
165 stringField.defLength,
166 jsonEntry->at("default_string_length").get<uint16_t>());
167 EXPECT_EQ(stringField.defString,
168 jsonEntry->at("default_string").get<std::string>());
169 break;
170 }
John Wang95e6b3c2020-02-13 09:43:24 +0800171 case PLDM_BIOS_INTEGER:
172 case PLDM_BIOS_INTEGER_READ_ONLY:
173 {
174 auto integerField = table::attribute::decodeIntegerEntry(entry);
175 EXPECT_EQ(integerField.lowerBound,
176 jsonEntry->at("lower_bound").get<uint64_t>());
177 EXPECT_EQ(integerField.upperBound,
178 jsonEntry->at("upper_bound").get<uint64_t>());
179 EXPECT_EQ(integerField.scalarIncrement,
180 jsonEntry->at("scalar_increment").get<uint32_t>());
181 EXPECT_EQ(integerField.defaultValue,
182 jsonEntry->at("default_value").get<uint64_t>());
183 break;
184 }
John Wang3be70852020-02-13 15:59:04 +0800185 case PLDM_BIOS_ENUMERATION:
186 case PLDM_BIOS_ENUMERATION_READ_ONLY:
187 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500188 auto [pvHdls,
189 defInds] = table::attribute::decodeEnumEntry(entry);
John Wang3be70852020-02-13 15:59:04 +0800190 auto possibleValues = jsonEntry->at("possible_values")
191 .get<std::vector<std::string>>();
192 std::vector<std::string> strings;
193 for (auto pv : pvHdls)
194 {
195 auto s = biosStringTable.findString(pv);
196 strings.emplace_back(s);
197 }
198 EXPECT_EQ(strings, possibleValues);
199 EXPECT_EQ(defInds.size(), 1);
200
201 auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
202 auto defaultValues = jsonEntry->at("default_values")
203 .get<std::vector<std::string>>();
204 EXPECT_EQ(defValue, defaultValues[0]);
205
206 break;
207 }
John Wangd9659342020-02-27 16:46:05 +0800208 default:
209 EXPECT_TRUE(false);
210 break;
211 }
212 }
213
214 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
215 attrValueTable->data(), attrValueTable->size()))
216 {
217 auto header = table::attribute_value::decodeHeader(entry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500218 auto attrEntry = table::attribute::findByHandle(*attrTable,
219 header.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800220 auto attrHeader = table::attribute::decodeHeader(attrEntry);
221 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
222 auto jsonEntry = findJsonEntry(attrName);
223 EXPECT_TRUE(jsonEntry);
224 switch (header.attrType)
225 {
226 case PLDM_BIOS_STRING:
227 case PLDM_BIOS_STRING_READ_ONLY:
228 {
229 auto value = table::attribute_value::decodeStringEntry(entry);
230 auto defValue =
231 jsonEntry->at("default_string").get<std::string>();
232 EXPECT_EQ(value, defValue);
233 break;
234 }
John Wang95e6b3c2020-02-13 09:43:24 +0800235 case PLDM_BIOS_INTEGER:
236 case PLDM_BIOS_INTEGER_READ_ONLY:
237 {
238 auto value = table::attribute_value::decodeIntegerEntry(entry);
239 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
240 EXPECT_EQ(value, defValue);
241 break;
242 }
John Wang3be70852020-02-13 15:59:04 +0800243 case PLDM_BIOS_ENUMERATION:
244 case PLDM_BIOS_ENUMERATION_READ_ONLY:
245 {
246 auto indices = table::attribute_value::decodeEnumEntry(entry);
247 EXPECT_EQ(indices.size(), 1);
248 auto possibleValues = jsonEntry->at("possible_values")
249 .get<std::vector<std::string>>();
250
251 auto defValues = jsonEntry->at("default_values")
252 .get<std::vector<std::string>>();
253 EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
254 break;
255 }
John Wangd9659342020-02-27 16:46:05 +0800256 default:
257 EXPECT_TRUE(false);
258 break;
259 }
260 }
261}
262
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500263TEST_F(TestBIOSConfig, buildTablesSystemSpecificTest)
264{
265 MockdBusHandler dbusHandler;
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600266 MockSystemConfig mockSystemConfig;
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500267
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600268 EXPECT_CALL(mockSystemConfig, getPlatformName()).WillOnce(Return(""));
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500269 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
270 .WillByDefault(Throw(std::exception()));
271
272 BIOSConfig biosConfig("./system_type1/bios_jsons", tableDir.c_str(),
273 &dbusHandler, 0, 0, nullptr, nullptr,
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600274 &mockSystemConfig);
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500275
276 biosConfig.buildTables();
277
278 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
279 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
280 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
281
282 EXPECT_TRUE(stringTable);
283 EXPECT_TRUE(attrTable);
284 EXPECT_TRUE(attrValueTable);
285
286 BIOSStringTable biosStringTable(*stringTable);
287
288 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
289 attrTable->size()))
290 {
291 auto header = table::attribute::decodeHeader(entry);
292 auto attrName = biosStringTable.findString(header.stringHandle);
293 auto jsonEntry = findJsonEntry(attrName);
294 EXPECT_TRUE(jsonEntry);
295 switch (header.attrType)
296 {
297 case PLDM_BIOS_STRING:
298 case PLDM_BIOS_STRING_READ_ONLY:
299 {
300 if (attrName == "str_example2")
301 {
302 auto stringField =
303 table::attribute::decodeStringEntry(entry);
304 EXPECT_EQ(stringField.maxLength, 200);
305 }
306
307 break;
308 }
309 case PLDM_BIOS_INTEGER:
310 case PLDM_BIOS_INTEGER_READ_ONLY:
311 {
312 if (attrName == "SBE_IMAGE_MINIMUM_VALID_ECS")
313 {
314 auto integerField =
315 table::attribute::decodeIntegerEntry(entry);
316 EXPECT_EQ(integerField.upperBound, 30);
317 }
318 break;
319 }
320 case PLDM_BIOS_ENUMERATION:
321 case PLDM_BIOS_ENUMERATION_READ_ONLY:
322 {
323 if (attrName == "FWBootSide")
324 {
325 auto [pvHdls,
326 defInds] = table::attribute::decodeEnumEntry(entry);
327 auto defValue =
328 biosStringTable.findString(pvHdls[defInds[0]]);
329 EXPECT_EQ(defValue, "Temp");
330 }
331 }
332 }
333 }
334}
335
John Wangd9659342020-02-27 16:46:05 +0800336TEST_F(TestBIOSConfig, setAttrValue)
337{
338 MockdBusHandler dbusHandler;
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600339 MockSystemConfig mockSystemConfig;
John Wangd9659342020-02-27 16:46:05 +0800340
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600341 EXPECT_CALL(mockSystemConfig, getPlatformName()).WillOnce(Return(""));
Tom Joseph7f839f92020-09-21 10:20:44 +0530342 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600343 nullptr, nullptr, &mockSystemConfig);
John Wangd9659342020-02-27 16:46:05 +0800344 biosConfig.removeTables();
345 biosConfig.buildTables();
346
347 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
348 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
349
350 BIOSStringTable biosStringTable(*stringTable);
351 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
352 attrTable->size());
353 auto stringHandle = biosStringTable.findHandle("str_example1");
354 uint16_t attrHandle{};
355
356 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
357 attrTable->size()))
358 {
359 auto header = table::attribute::decodeHeader(entry);
360 if (header.stringHandle == stringHandle)
361 {
362 attrHandle = header.attrHandle;
363 break;
364 }
365 }
366
367 EXPECT_NE(attrHandle, 0);
368
369 std::vector<uint8_t> attrValueEntry{
370 0, 0, /* attr handle */
371 1, /* attr type string read-write */
372 4, 0, /* current string length */
373 'a', 'b', 'c', 'd', /* defaut value string handle index */
374 };
375
376 attrValueEntry[0] = attrHandle & 0xff;
377 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
378
379 DBusMapping dbusMapping{"/xyz/abc/def",
380 "xyz.openbmc_project.str_example1.value",
381 "Str_example1", "string"};
382 PropertyValue value = std::string("abcd");
383 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
384
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600385 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
386 attrValueEntry.size(), false);
John Wangd9659342020-02-27 16:46:05 +0800387 EXPECT_EQ(rc, PLDM_SUCCESS);
388
389 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
390 auto findEntry =
391 [&attrValueTable](
392 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
393 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
394 attrValueTable->data(), attrValueTable->size()))
395 {
396 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
397 if (attrHandle == handle)
398 return entry;
399 }
400 return nullptr;
401 };
402
403 auto entry = findEntry(attrHandle);
404 EXPECT_NE(entry, nullptr);
405
406 auto p = reinterpret_cast<const uint8_t*>(entry);
407 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
408 ElementsAreArray(attrValueEntry));
409}