blob: ea290158c393562a7b9eb1747afe467fcfcc9081 [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:
Manojkiran Eda2576aec2024-06-17 12:05:17 +053030 static void SetUpTestCase() // will execute once at the beginning of all
John Wangd9659342020-02-27 16:46:05 +080031 // TestBIOSConfig objects
32 {
33 char tmpdir[] = "/tmp/BIOSTables.XXXXXX";
34 tableDir = fs::path(mkdtemp(tmpdir));
35
Archana Kakaniac713ee2024-05-20 01:27:53 -050036 std::vector<fs::path> paths = {"./bios_jsons/bios_attrs.json"};
John Wangd9659342020-02-27 16:46:05 +080037
Pavithra Barithaya15b94112024-04-10 02:42:12 -050038 for (const auto& path : paths)
John Wangd9659342020-02-27 16:46:05 +080039 {
40 std::ifstream file;
41 file.open(path);
42 auto j = Json::parse(file);
43 jsons.emplace_back(j);
44 }
45 }
46
47 std::optional<Json> findJsonEntry(const std::string& name)
48 {
49 for (auto& json : jsons)
50 {
51 auto entries = json.at("entries");
52 for (auto& entry : entries)
53 {
54 auto n = entry.at("attribute_name").get<std::string>();
55 if (n == name)
56 {
57 return entry;
58 }
59 }
60 }
61 return std::nullopt;
62 }
63
64 static void TearDownTestCase() // will be executed once at th end of all
65 // TestBIOSConfig objects
66 {
67 fs::remove_all(tableDir);
68 }
69
70 static fs::path tableDir;
71 static std::vector<Json> jsons;
72};
73
74fs::path TestBIOSConfig::tableDir;
75std::vector<Json> TestBIOSConfig::jsons;
76
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060077class MockSystemConfig : public pldm::responder::platform_config::Handler
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050078{
79 public:
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060080 MockSystemConfig() {}
Patrick Williams98e703f2023-08-15 02:34:38 -050081 MOCK_METHOD(void, ibmCompatibleAddedCallback, (sdbusplus::message_t&), ());
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060082 MOCK_METHOD(std::optional<std::filesystem::path>, getPlatformName, ());
Sagar Srinivas11ce8d22022-07-28 11:32:34 -050083};
84
John Wangd9659342020-02-27 16:46:05 +080085TEST_F(TestBIOSConfig, buildTablesTest)
86{
87 MockdBusHandler dbusHandler;
Kamalkumar Patel3c50c822024-01-30 07:14:40 -060088 MockSystemConfig mockSystemConfig;
Archana Kakani46f352e2024-03-17 08:21:08 -050089 std::string biosFilePath("./bios_jsons");
John Wangd9659342020-02-27 16:46:05 +080090
Archana Kakani46f352e2024-03-17 08:21:08 -050091 BIOSConfig biosConfig(biosFilePath.c_str(), tableDir.c_str(), &dbusHandler,
92 0, 0, nullptr, nullptr, &mockSystemConfig, []() {});
John Wangd9659342020-02-27 16:46:05 +080093 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
94 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
95 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
96
97 EXPECT_TRUE(stringTable);
98 EXPECT_TRUE(attrTable);
99 EXPECT_TRUE(attrValueTable);
100
101 std::set<std::string> expectedStrings = {"HMCManagedState",
102 "On",
103 "Off",
104 "FWBootSide",
105 "Perm",
106 "Temp",
107 "InbandCodeUpdate",
108 "Allowed",
Sagar Srinivas11ce8d22022-07-28 11:32:34 -0500109 "Allowed",
John Wangd9659342020-02-27 16:46:05 +0800110 "NotAllowed",
111 "CodeUpdatePolicy",
112 "Concurrent",
113 "Disruptive",
114 "VDD_AVSBUS_RAIL",
115 "SBE_IMAGE_MINIMUM_VALID_ECS",
116 "INTEGER_INVALID_CASE",
117 "str_example1",
118 "str_example2",
119 "str_example3"};
120 std::set<std::string> strings;
121 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
122 stringTable->data(), stringTable->size()))
123 {
124 auto str = table::string::decodeString(entry);
125 strings.emplace(str);
126 }
127
128 EXPECT_EQ(strings, expectedStrings);
129
130 BIOSStringTable biosStringTable(*stringTable);
131
132 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
133 attrTable->size()))
134 {
135 auto header = table::attribute::decodeHeader(entry);
136 auto attrName = biosStringTable.findString(header.stringHandle);
137 auto jsonEntry = findJsonEntry(attrName);
138 EXPECT_TRUE(jsonEntry);
139 switch (header.attrType)
140 {
141 case PLDM_BIOS_STRING:
142 case PLDM_BIOS_STRING_READ_ONLY:
143 {
144 auto stringField = table::attribute::decodeStringEntry(entry);
145 auto stringType = BIOSStringAttribute::strTypeMap.at(
146 jsonEntry->at("string_type").get<std::string>());
147 EXPECT_EQ(stringField.stringType,
148 static_cast<uint8_t>(stringType));
149
150 EXPECT_EQ(
151 stringField.minLength,
152 jsonEntry->at("minimum_string_length").get<uint16_t>());
153 EXPECT_EQ(
154 stringField.maxLength,
155 jsonEntry->at("maximum_string_length").get<uint16_t>());
John Wangd9659342020-02-27 16:46:05 +0800156 EXPECT_EQ(stringField.defString,
157 jsonEntry->at("default_string").get<std::string>());
Archana Kakani7d475702024-05-22 08:30:27 -0500158 EXPECT_EQ(stringField.defLength,
159 (stringField.defString).length());
John Wangd9659342020-02-27 16:46:05 +0800160 break;
161 }
John Wang95e6b3c2020-02-13 09:43:24 +0800162 case PLDM_BIOS_INTEGER:
163 case PLDM_BIOS_INTEGER_READ_ONLY:
164 {
165 auto integerField = table::attribute::decodeIntegerEntry(entry);
166 EXPECT_EQ(integerField.lowerBound,
167 jsonEntry->at("lower_bound").get<uint64_t>());
168 EXPECT_EQ(integerField.upperBound,
169 jsonEntry->at("upper_bound").get<uint64_t>());
170 EXPECT_EQ(integerField.scalarIncrement,
171 jsonEntry->at("scalar_increment").get<uint32_t>());
172 EXPECT_EQ(integerField.defaultValue,
173 jsonEntry->at("default_value").get<uint64_t>());
174 break;
175 }
John Wang3be70852020-02-13 15:59:04 +0800176 case PLDM_BIOS_ENUMERATION:
177 case PLDM_BIOS_ENUMERATION_READ_ONLY:
178 {
Patrick Williams6da4f912023-05-10 07:50:53 -0500179 auto [pvHdls,
180 defInds] = table::attribute::decodeEnumEntry(entry);
John Wang3be70852020-02-13 15:59:04 +0800181 auto possibleValues = jsonEntry->at("possible_values")
182 .get<std::vector<std::string>>();
183 std::vector<std::string> strings;
184 for (auto pv : pvHdls)
185 {
186 auto s = biosStringTable.findString(pv);
187 strings.emplace_back(s);
188 }
189 EXPECT_EQ(strings, possibleValues);
190 EXPECT_EQ(defInds.size(), 1);
191
192 auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
193 auto defaultValues = jsonEntry->at("default_values")
194 .get<std::vector<std::string>>();
195 EXPECT_EQ(defValue, defaultValues[0]);
196
197 break;
198 }
John Wangd9659342020-02-27 16:46:05 +0800199 default:
200 EXPECT_TRUE(false);
201 break;
202 }
203 }
204
205 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
206 attrValueTable->data(), attrValueTable->size()))
207 {
208 auto header = table::attribute_value::decodeHeader(entry);
Patrick Williams6da4f912023-05-10 07:50:53 -0500209 auto attrEntry = table::attribute::findByHandle(*attrTable,
210 header.attrHandle);
John Wangd9659342020-02-27 16:46:05 +0800211 auto attrHeader = table::attribute::decodeHeader(attrEntry);
212 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
213 auto jsonEntry = findJsonEntry(attrName);
214 EXPECT_TRUE(jsonEntry);
215 switch (header.attrType)
216 {
217 case PLDM_BIOS_STRING:
218 case PLDM_BIOS_STRING_READ_ONLY:
219 {
220 auto value = table::attribute_value::decodeStringEntry(entry);
221 auto defValue =
222 jsonEntry->at("default_string").get<std::string>();
223 EXPECT_EQ(value, defValue);
224 break;
225 }
John Wang95e6b3c2020-02-13 09:43:24 +0800226 case PLDM_BIOS_INTEGER:
227 case PLDM_BIOS_INTEGER_READ_ONLY:
228 {
229 auto value = table::attribute_value::decodeIntegerEntry(entry);
230 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
231 EXPECT_EQ(value, defValue);
232 break;
233 }
John Wang3be70852020-02-13 15:59:04 +0800234 case PLDM_BIOS_ENUMERATION:
235 case PLDM_BIOS_ENUMERATION_READ_ONLY:
236 {
237 auto indices = table::attribute_value::decodeEnumEntry(entry);
238 EXPECT_EQ(indices.size(), 1);
239 auto possibleValues = jsonEntry->at("possible_values")
240 .get<std::vector<std::string>>();
241
242 auto defValues = jsonEntry->at("default_values")
243 .get<std::vector<std::string>>();
244 EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
245 break;
246 }
John Wangd9659342020-02-27 16:46:05 +0800247 default:
248 EXPECT_TRUE(false);
249 break;
250 }
251 }
252}
253
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600254TEST_F(TestBIOSConfig, setBIOSTable)
255{
256 MockdBusHandler dbusHandler;
257 MockSystemConfig mockSystemConfig;
258
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600259 BIOSConfig biosConfig("./", tableDir.c_str(), &dbusHandler, 0, 0, nullptr,
260 nullptr, &mockSystemConfig, []() {});
261
262 std::set<std::string> strings{"pvm_system_name", "pvm_stop_at_standby",
263 "fw_boot_side", "fw_next_boot_side"};
264
265 Table table;
266 for (const auto& elem : strings)
267 {
268 table::string::constructEntry(table, elem);
269 }
270
271 table::appendPadAndChecksum(table);
272 auto rc = biosConfig.setBIOSTable(PLDM_BIOS_STRING_TABLE, table);
273 EXPECT_EQ(rc, PLDM_SUCCESS);
274
275 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
276 EXPECT_TRUE(stringTable);
277}
278
279TEST_F(TestBIOSConfig, getBIOSTableFailure)
280{
281 MockdBusHandler dbusHandler;
282 MockSystemConfig mockSystemConfig;
283
Archana Kakani46f352e2024-03-17 08:21:08 -0500284 BIOSConfig biosConfig("./jsons", tableDir.c_str(), &dbusHandler, 0, 0,
285 nullptr, nullptr, &mockSystemConfig, []() {});
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600286
287 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
288 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
289 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
290
291 EXPECT_FALSE(stringTable);
292 EXPECT_FALSE(attrTable);
293 EXPECT_FALSE(attrValueTable);
294}
295
296TEST_F(TestBIOSConfig, setAttrValueFailure)
297{
298 MockdBusHandler dbusHandler;
299 MockSystemConfig mockSystemConfig;
300
Archana Kakani46f352e2024-03-17 08:21:08 -0500301 BIOSConfig biosConfig("./jsons", tableDir.c_str(), &dbusHandler, 0, 0,
302 nullptr, nullptr, &mockSystemConfig, []() {});
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600303
304 std::vector<uint8_t> attrValueEntry{
305 0, 0, /* attr handle */
306 1, /* attr type string read-write */
307 4, 0, /* current string length */
Manojkiran Eda2576aec2024-06-17 12:05:17 +0530308 'a', 'b', 'c', 'd', /* default value string handle index */
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600309 };
310
311 uint16_t attrHandle{10};
312 attrValueEntry[0] = attrHandle & 0xff;
313 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
314
315 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
316 attrValueEntry.size(), false);
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600317 EXPECT_EQ(rc, PLDM_BIOS_TABLE_UNAVAILABLE);
318}
319
John Wangd9659342020-02-27 16:46:05 +0800320TEST_F(TestBIOSConfig, setAttrValue)
321{
322 MockdBusHandler dbusHandler;
Kamalkumar Patel3c50c822024-01-30 07:14:40 -0600323 MockSystemConfig mockSystemConfig;
John Wangd9659342020-02-27 16:46:05 +0800324
Tom Joseph7f839f92020-09-21 10:20:44 +0530325 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
Archana Kakani62dd8ff2024-02-12 10:00:40 -0600326 nullptr, nullptr, &mockSystemConfig, []() {});
John Wangd9659342020-02-27 16:46:05 +0800327
328 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
329 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
330
331 BIOSStringTable biosStringTable(*stringTable);
332 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
333 attrTable->size());
334 auto stringHandle = biosStringTable.findHandle("str_example1");
335 uint16_t attrHandle{};
336
337 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
338 attrTable->size()))
339 {
340 auto header = table::attribute::decodeHeader(entry);
341 if (header.stringHandle == stringHandle)
342 {
343 attrHandle = header.attrHandle;
344 break;
345 }
346 }
347
348 EXPECT_NE(attrHandle, 0);
349
350 std::vector<uint8_t> attrValueEntry{
351 0, 0, /* attr handle */
352 1, /* attr type string read-write */
353 4, 0, /* current string length */
Manojkiran Eda2576aec2024-06-17 12:05:17 +0530354 'a', 'b', 'c', 'd', /* default value string handle index */
John Wangd9659342020-02-27 16:46:05 +0800355 };
356
357 attrValueEntry[0] = attrHandle & 0xff;
358 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
359
360 DBusMapping dbusMapping{"/xyz/abc/def",
361 "xyz.openbmc_project.str_example1.value",
362 "Str_example1", "string"};
363 PropertyValue value = std::string("abcd");
364 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
365
Sagar Srinivascac0ebb2021-11-23 07:50:28 -0600366 auto rc = biosConfig.setAttrValue(attrValueEntry.data(),
367 attrValueEntry.size(), false);
John Wangd9659342020-02-27 16:46:05 +0800368 EXPECT_EQ(rc, PLDM_SUCCESS);
369
370 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
371 auto findEntry =
372 [&attrValueTable](
373 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
374 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
375 attrValueTable->data(), attrValueTable->size()))
376 {
377 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
378 if (attrHandle == handle)
379 return entry;
380 }
381 return nullptr;
382 };
383
384 auto entry = findEntry(attrHandle);
385 EXPECT_NE(entry, nullptr);
386
387 auto p = reinterpret_cast<const uint8_t*>(entry);
388 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
389 ElementsAreArray(attrValueEntry));
390}