blob: 25300ca1c78fd0a46be98b48804038496abd0d12 [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"
5#include "mocked_bios.hpp"
John Wangd9659342020-02-27 16:46:05 +08006
George Liu6492f522020-06-16 10:34:05 +08007#include <nlohmann/json.hpp>
8
John Wangd9659342020-02-27 16:46:05 +08009#include <fstream>
10#include <memory>
John Wangd9659342020-02-27 16:46:05 +080011
12#include <gmock/gmock.h>
13#include <gtest/gtest.h>
14
15using namespace pldm::bios::utils;
16
17using ::testing::_;
18using ::testing::ElementsAreArray;
19using ::testing::Throw;
20
21class TestBIOSConfig : public ::testing::Test
22{
23 public:
24 static void SetUpTestCase() // will execute once at the begining of all
25 // TestBIOSConfig objects
26 {
27 char tmpdir[] = "/tmp/BIOSTables.XXXXXX";
28 tableDir = fs::path(mkdtemp(tmpdir));
29
30 std::vector<fs::path> paths = {
31 "./bios_jsons/string_attrs.json",
John Wang95e6b3c2020-02-13 09:43:24 +080032 "./bios_jsons/integer_attrs.json",
John Wang3be70852020-02-13 15:59:04 +080033 "./bios_jsons/enum_attrs.json",
John Wangd9659342020-02-27 16:46:05 +080034 };
35
36 for (auto& path : paths)
37 {
38 std::ifstream file;
39 file.open(path);
40 auto j = Json::parse(file);
41 jsons.emplace_back(j);
42 }
43 }
44
45 std::optional<Json> findJsonEntry(const std::string& name)
46 {
47 for (auto& json : jsons)
48 {
49 auto entries = json.at("entries");
50 for (auto& entry : entries)
51 {
52 auto n = entry.at("attribute_name").get<std::string>();
53 if (n == name)
54 {
55 return entry;
56 }
57 }
58 }
59 return std::nullopt;
60 }
61
62 static void TearDownTestCase() // will be executed once at th end of all
63 // TestBIOSConfig objects
64 {
65 fs::remove_all(tableDir);
66 }
67
68 static fs::path tableDir;
69 static std::vector<Json> jsons;
70};
71
72fs::path TestBIOSConfig::tableDir;
73std::vector<Json> TestBIOSConfig::jsons;
74
75TEST_F(TestBIOSConfig, buildTablesTest)
76{
77 MockdBusHandler dbusHandler;
78
79 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
80 .WillByDefault(Throw(std::exception()));
81
Tom Joseph7f839f92020-09-21 10:20:44 +053082 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
83 nullptr);
John Wangd9659342020-02-27 16:46:05 +080084 biosConfig.buildTables();
85
86 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
87 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
88 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
89
90 EXPECT_TRUE(stringTable);
91 EXPECT_TRUE(attrTable);
92 EXPECT_TRUE(attrValueTable);
93
94 std::set<std::string> expectedStrings = {"HMCManagedState",
95 "On",
96 "Off",
97 "FWBootSide",
98 "Perm",
99 "Temp",
100 "InbandCodeUpdate",
101 "Allowed",
102 "NotAllowed",
103 "CodeUpdatePolicy",
104 "Concurrent",
105 "Disruptive",
106 "VDD_AVSBUS_RAIL",
107 "SBE_IMAGE_MINIMUM_VALID_ECS",
108 "INTEGER_INVALID_CASE",
109 "str_example1",
110 "str_example2",
111 "str_example3"};
112 std::set<std::string> strings;
113 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
114 stringTable->data(), stringTable->size()))
115 {
116 auto str = table::string::decodeString(entry);
117 strings.emplace(str);
118 }
119
120 EXPECT_EQ(strings, expectedStrings);
121
122 BIOSStringTable biosStringTable(*stringTable);
123
124 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
125 attrTable->size()))
126 {
127 auto header = table::attribute::decodeHeader(entry);
128 auto attrName = biosStringTable.findString(header.stringHandle);
129 auto jsonEntry = findJsonEntry(attrName);
130 EXPECT_TRUE(jsonEntry);
131 switch (header.attrType)
132 {
133 case PLDM_BIOS_STRING:
134 case PLDM_BIOS_STRING_READ_ONLY:
135 {
136 auto stringField = table::attribute::decodeStringEntry(entry);
137 auto stringType = BIOSStringAttribute::strTypeMap.at(
138 jsonEntry->at("string_type").get<std::string>());
139 EXPECT_EQ(stringField.stringType,
140 static_cast<uint8_t>(stringType));
141
142 EXPECT_EQ(
143 stringField.minLength,
144 jsonEntry->at("minimum_string_length").get<uint16_t>());
145 EXPECT_EQ(
146 stringField.maxLength,
147 jsonEntry->at("maximum_string_length").get<uint16_t>());
148 EXPECT_EQ(
149 stringField.defLength,
150 jsonEntry->at("default_string_length").get<uint16_t>());
151 EXPECT_EQ(stringField.defString,
152 jsonEntry->at("default_string").get<std::string>());
153 break;
154 }
John Wang95e6b3c2020-02-13 09:43:24 +0800155 case PLDM_BIOS_INTEGER:
156 case PLDM_BIOS_INTEGER_READ_ONLY:
157 {
158 auto integerField = table::attribute::decodeIntegerEntry(entry);
159 EXPECT_EQ(integerField.lowerBound,
160 jsonEntry->at("lower_bound").get<uint64_t>());
161 EXPECT_EQ(integerField.upperBound,
162 jsonEntry->at("upper_bound").get<uint64_t>());
163 EXPECT_EQ(integerField.scalarIncrement,
164 jsonEntry->at("scalar_increment").get<uint32_t>());
165 EXPECT_EQ(integerField.defaultValue,
166 jsonEntry->at("default_value").get<uint64_t>());
167 break;
168 }
John Wang3be70852020-02-13 15:59:04 +0800169 case PLDM_BIOS_ENUMERATION:
170 case PLDM_BIOS_ENUMERATION_READ_ONLY:
171 {
172 auto [pvHdls, defInds] =
173 table::attribute::decodeEnumEntry(entry);
174 auto possibleValues = jsonEntry->at("possible_values")
175 .get<std::vector<std::string>>();
176 std::vector<std::string> strings;
177 for (auto pv : pvHdls)
178 {
179 auto s = biosStringTable.findString(pv);
180 strings.emplace_back(s);
181 }
182 EXPECT_EQ(strings, possibleValues);
183 EXPECT_EQ(defInds.size(), 1);
184
185 auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
186 auto defaultValues = jsonEntry->at("default_values")
187 .get<std::vector<std::string>>();
188 EXPECT_EQ(defValue, defaultValues[0]);
189
190 break;
191 }
John Wangd9659342020-02-27 16:46:05 +0800192 default:
193 EXPECT_TRUE(false);
194 break;
195 }
196 }
197
198 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
199 attrValueTable->data(), attrValueTable->size()))
200 {
201 auto header = table::attribute_value::decodeHeader(entry);
202 auto attrEntry =
203 table::attribute::findByHandle(*attrTable, header.attrHandle);
204 auto attrHeader = table::attribute::decodeHeader(attrEntry);
205 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
206 auto jsonEntry = findJsonEntry(attrName);
207 EXPECT_TRUE(jsonEntry);
208 switch (header.attrType)
209 {
210 case PLDM_BIOS_STRING:
211 case PLDM_BIOS_STRING_READ_ONLY:
212 {
213 auto value = table::attribute_value::decodeStringEntry(entry);
214 auto defValue =
215 jsonEntry->at("default_string").get<std::string>();
216 EXPECT_EQ(value, defValue);
217 break;
218 }
John Wang95e6b3c2020-02-13 09:43:24 +0800219 case PLDM_BIOS_INTEGER:
220 case PLDM_BIOS_INTEGER_READ_ONLY:
221 {
222 auto value = table::attribute_value::decodeIntegerEntry(entry);
223 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
224 EXPECT_EQ(value, defValue);
225 break;
226 }
John Wang3be70852020-02-13 15:59:04 +0800227 case PLDM_BIOS_ENUMERATION:
228 case PLDM_BIOS_ENUMERATION_READ_ONLY:
229 {
230 auto indices = table::attribute_value::decodeEnumEntry(entry);
231 EXPECT_EQ(indices.size(), 1);
232 auto possibleValues = jsonEntry->at("possible_values")
233 .get<std::vector<std::string>>();
234
235 auto defValues = jsonEntry->at("default_values")
236 .get<std::vector<std::string>>();
237 EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
238 break;
239 }
John Wangd9659342020-02-27 16:46:05 +0800240 default:
241 EXPECT_TRUE(false);
242 break;
243 }
244 }
245}
246
247TEST_F(TestBIOSConfig, setAttrValue)
248{
249 MockdBusHandler dbusHandler;
250
Tom Joseph7f839f92020-09-21 10:20:44 +0530251 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler, 0, 0,
252 nullptr);
John Wangd9659342020-02-27 16:46:05 +0800253 biosConfig.removeTables();
254 biosConfig.buildTables();
255
256 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
257 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
258
259 BIOSStringTable biosStringTable(*stringTable);
260 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
261 attrTable->size());
262 auto stringHandle = biosStringTable.findHandle("str_example1");
263 uint16_t attrHandle{};
264
265 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
266 attrTable->size()))
267 {
268 auto header = table::attribute::decodeHeader(entry);
269 if (header.stringHandle == stringHandle)
270 {
271 attrHandle = header.attrHandle;
272 break;
273 }
274 }
275
276 EXPECT_NE(attrHandle, 0);
277
278 std::vector<uint8_t> attrValueEntry{
279 0, 0, /* attr handle */
280 1, /* attr type string read-write */
281 4, 0, /* current string length */
282 'a', 'b', 'c', 'd', /* defaut value string handle index */
283 };
284
285 attrValueEntry[0] = attrHandle & 0xff;
286 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
287
288 DBusMapping dbusMapping{"/xyz/abc/def",
289 "xyz.openbmc_project.str_example1.value",
290 "Str_example1", "string"};
291 PropertyValue value = std::string("abcd");
292 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
293
294 auto rc =
295 biosConfig.setAttrValue(attrValueEntry.data(), attrValueEntry.size());
296 EXPECT_EQ(rc, PLDM_SUCCESS);
297
298 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
299 auto findEntry =
300 [&attrValueTable](
301 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
302 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
303 attrValueTable->data(), attrValueTable->size()))
304 {
305 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
306 if (attrHandle == handle)
307 return entry;
308 }
309 return nullptr;
310 };
311
312 auto entry = findEntry(attrHandle);
313 EXPECT_NE(entry, nullptr);
314
315 auto p = reinterpret_cast<const uint8_t*>(entry);
316 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
317 ElementsAreArray(attrValueEntry));
318}