blob: 9bcf096d677f55ee397567acb44119b1001d164e [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;
Archana Kakani46f352e2024-03-17 08:21:08 -050093 std::string biosFilePath("./bios_jsons");
John Wangd9659342020-02-27 16:46:05 +080094
Archana Kakani46f352e2024-03-17 08:21:08 -050095 BIOSConfig biosConfig(biosFilePath.c_str(), tableDir.c_str(), &dbusHandler,
96 0, 0, nullptr, nullptr, &mockSystemConfig, []() {});
John Wangd9659342020-02-27 16:46:05 +080097 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
98 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
99 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
100
101 EXPECT_TRUE(stringTable);
102 EXPECT_TRUE(attrTable);
103 EXPECT_TRUE(attrValueTable);
104
105 std::set<std::string> expectedStrings = {"HMCManagedState",
106 "On",
107 "Off",
108 "FWBootSide",
109 "Perm",
110 "Temp",
111 "InbandCodeUpdate",
112 "Allowed",
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500113 "Allowed",
John Wangd9659342020-02-27 16:46:05 +0800114 "NotAllowed",
115 "CodeUpdatePolicy",
116 "Concurrent",
117 "Disruptive",
118 "VDD_AVSBUS_RAIL",
119 "SBE_IMAGE_MINIMUM_VALID_ECS",
120 "INTEGER_INVALID_CASE",
121 "str_example1",
122 "str_example2",
123 "str_example3"};
124 std::set<std::string> strings;
125 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
126 stringTable->data(), stringTable->size()))
127 {
128 auto str = table::string::decodeString(entry);
129 strings.emplace(str);
130 }
131
132 EXPECT_EQ(strings, expectedStrings);
133
134 BIOSStringTable biosStringTable(*stringTable);
135
136 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
137 attrTable->size()))
138 {
139 auto header = table::attribute::decodeHeader(entry);
140 auto attrName = biosStringTable.findString(header.stringHandle);
141 auto jsonEntry = findJsonEntry(attrName);
142 EXPECT_TRUE(jsonEntry);
143 switch (header.attrType)
144 {
145 case PLDM_BIOS_STRING:
146 case PLDM_BIOS_STRING_READ_ONLY:
147 {
148 auto stringField = table::attribute::decodeStringEntry(entry);
149 auto stringType = BIOSStringAttribute::strTypeMap.at(
150 jsonEntry->at("string_type").get<std::string>());
151 EXPECT_EQ(stringField.stringType,
152 static_cast<uint8_t>(stringType));
153
154 EXPECT_EQ(
155 stringField.minLength,
156 jsonEntry->at("minimum_string_length").get<uint16_t>());
157 EXPECT_EQ(
158 stringField.maxLength,
159 jsonEntry->at("maximum_string_length").get<uint16_t>());
160 EXPECT_EQ(
161 stringField.defLength,
162 jsonEntry->at("default_string_length").get<uint16_t>());
163 EXPECT_EQ(stringField.defString,
164 jsonEntry->at("default_string").get<std::string>());
165 break;
166 }
John Wang95e6b3c2020-02-13 09:43:24 +0800167 case PLDM_BIOS_INTEGER:
168 case PLDM_BIOS_INTEGER_READ_ONLY:
169 {
170 auto integerField = table::attribute::decodeIntegerEntry(entry);
171 EXPECT_EQ(integerField.lowerBound,
172 jsonEntry->at("lower_bound").get<uint64_t>());
173 EXPECT_EQ(integerField.upperBound,
174 jsonEntry->at("upper_bound").get<uint64_t>());
175 EXPECT_EQ(integerField.scalarIncrement,
176 jsonEntry->at("scalar_increment").get<uint32_t>());
177 EXPECT_EQ(integerField.defaultValue,
178 jsonEntry->at("default_value").get<uint64_t>());
179 break;
180 }
John Wang3be70852020-02-13 15:59:04 +0800181 case PLDM_BIOS_ENUMERATION:
182 case PLDM_BIOS_ENUMERATION_READ_ONLY:
183 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500184 auto [pvHdls,
185 defInds] = table::attribute::decodeEnumEntry(entry);
John Wang3be70852020-02-13 15:59:04 +0800186 auto possibleValues = jsonEntry->at("possible_values")
187 .get<std::vector<std::string>>();
188 std::vector<std::string> strings;
189 for (auto pv : pvHdls)
190 {
191 auto s = biosStringTable.findString(pv);
192 strings.emplace_back(s);
193 }
194 EXPECT_EQ(strings, possibleValues);
195 EXPECT_EQ(defInds.size(), 1);
196
197 auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
198 auto defaultValues = jsonEntry->at("default_values")
199 .get<std::vector<std::string>>();
200 EXPECT_EQ(defValue, defaultValues[0]);
201
202 break;
203 }
John Wangd9659342020-02-27 16:46:05 +0800204 default:
205 EXPECT_TRUE(false);
206 break;
207 }
208 }
209
210 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
211 attrValueTable->data(), attrValueTable->size()))
212 {
213 auto header = table::attribute_value::decodeHeader(entry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500214 auto attrEntry = table::attribute::findByHandle(*attrTable,
215 header.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800216 auto attrHeader = table::attribute::decodeHeader(attrEntry);
217 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
218 auto jsonEntry = findJsonEntry(attrName);
219 EXPECT_TRUE(jsonEntry);
220 switch (header.attrType)
221 {
222 case PLDM_BIOS_STRING:
223 case PLDM_BIOS_STRING_READ_ONLY:
224 {
225 auto value = table::attribute_value::decodeStringEntry(entry);
226 auto defValue =
227 jsonEntry->at("default_string").get<std::string>();
228 EXPECT_EQ(value, defValue);
229 break;
230 }
John Wang95e6b3c2020-02-13 09:43:24 +0800231 case PLDM_BIOS_INTEGER:
232 case PLDM_BIOS_INTEGER_READ_ONLY:
233 {
234 auto value = table::attribute_value::decodeIntegerEntry(entry);
235 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
236 EXPECT_EQ(value, defValue);
237 break;
238 }
John Wang3be70852020-02-13 15:59:04 +0800239 case PLDM_BIOS_ENUMERATION:
240 case PLDM_BIOS_ENUMERATION_READ_ONLY:
241 {
242 auto indices = table::attribute_value::decodeEnumEntry(entry);
243 EXPECT_EQ(indices.size(), 1);
244 auto possibleValues = jsonEntry->at("possible_values")
245 .get<std::vector<std::string>>();
246
247 auto defValues = jsonEntry->at("default_values")
248 .get<std::vector<std::string>>();
249 EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
250 break;
251 }
John Wangd9659342020-02-27 16:46:05 +0800252 default:
253 EXPECT_TRUE(false);
254 break;
255 }
256 }
257}
258
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600259TEST_F(TestBIOSConfig, setBIOSTable)
260{
261 MockdBusHandler dbusHandler;
262 MockSystemConfig mockSystemConfig;
263
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600264 BIOSConfig biosConfig("./", tableDir.c_str(), &dbusHandler, 0, 0, nullptr,
265 nullptr, &mockSystemConfig, []() {});
266
267 std::set<std::string> strings{"pvm_system_name", "pvm_stop_at_standby",
268 "fw_boot_side", "fw_next_boot_side"};
269
270 Table table;
271 for (const auto& elem : strings)
272 {
273 table::string::constructEntry(table, elem);
274 }
275
276 table::appendPadAndChecksum(table);
277 auto rc = biosConfig.setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
278 EXPECT_EQ(rc, PLDM_SUCCESS);
279
280 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
281 EXPECT_TRUE(stringTable);
282}
283
284TEST_F(TestBIOSConfig, getBIOSTableFailure)
285{
286 MockdBusHandler dbusHandler;
287 MockSystemConfig mockSystemConfig;
288
Archana Kakani46f352e2024-03-17 08:21:08 -0500289 BIOSConfig biosConfig("./jsons", tableDir.c_str(), &dbusHandler, 0, 0,
290 nullptr, nullptr, &mockSystemConfig, []() {});
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600291
292 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
293 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
294 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
295
296 EXPECT_FALSE(stringTable);
297 EXPECT_FALSE(attrTable);
298 EXPECT_FALSE(attrValueTable);
299}
300
301TEST_F(TestBIOSConfig, setAttrValueFailure)
302{
303 MockdBusHandler dbusHandler;
304 MockSystemConfig mockSystemConfig;
305
Archana Kakani46f352e2024-03-17 08:21:08 -0500306 BIOSConfig biosConfig("./jsons", tableDir.c_str(), &dbusHandler, 0, 0,
307 nullptr, nullptr, &mockSystemConfig, []() {});
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600308
309 std::vector<uint8_t> attrValueEntry{
310 0, 0, /* attr handle */
311 1, /* attr type string read-write */
312 4, 0, /* current string length */
313 'a', 'b', 'c', 'd', /* defaut value string handle index */
314 };
315
316 uint16_t attrHandle{10};
317 attrValueEntry[0] = attrHandle & 0xff;
318 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
319
320 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
321 attrValueEntry.size(), false);
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600322 EXPECT_EQ(rc, PLDM_BIOS_TABLE_UNAVAILABLE);
323}
324
John Wangd9659342020-02-27 16:46:05 +0800325TEST_F(TestBIOSConfig, setAttrValue)
326{
327 MockdBusHandler dbusHandler;
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600328 MockSystemConfig mockSystemConfig;
John Wangd9659342020-02-27 16:46:05 +0800329
Tom Joseph7f839f92020-09-21 10:20:44 +0530330 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600331 nullptr, nullptr, &mockSystemConfig, []() {});
John Wangd9659342020-02-27 16:46:05 +0800332
333 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
334 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
335
336 BIOSStringTable biosStringTable(*stringTable);
337 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
338 attrTable->size());
339 auto stringHandle = biosStringTable.findHandle("str_example1");
340 uint16_t attrHandle{};
341
342 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
343 attrTable->size()))
344 {
345 auto header = table::attribute::decodeHeader(entry);
346 if (header.stringHandle == stringHandle)
347 {
348 attrHandle = header.attrHandle;
349 break;
350 }
351 }
352
353 EXPECT_NE(attrHandle, 0);
354
355 std::vector<uint8_t> attrValueEntry{
356 0, 0, /* attr handle */
357 1, /* attr type string read-write */
358 4, 0, /* current string length */
359 'a', 'b', 'c', 'd', /* defaut value string handle index */
360 };
361
362 attrValueEntry[0] = attrHandle & 0xff;
363 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
364
365 DBusMapping dbusMapping{"/xyz/abc/def",
366 "xyz.openbmc_project.str_example1.value",
367 "Str_example1", "string"};
368 PropertyValue value = std::string("abcd");
369 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
370
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600371 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
372 attrValueEntry.size(), false);
John Wangd9659342020-02-27 16:46:05 +0800373 EXPECT_EQ(rc, PLDM_SUCCESS);
374
375 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
376 auto findEntry =
377 [&attrValueTable](
378 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
379 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
380 attrValueTable->data(), attrValueTable->size()))
381 {
382 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
383 if (attrHandle == handle)
384 return entry;
385 }
386 return nullptr;
387 };
388
389 auto entry = findEntry(attrHandle);
390 EXPECT_NE(entry, nullptr);
391
392 auto p = reinterpret_cast<const uint8_t*>(entry);
393 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
394 ElementsAreArray(attrValueEntry));
395}