blob: 371658c3ac254de4159614100fd3ba00c0725982 [file] [log] [blame]
John Wangd9659342020-02-27 16:46:05 +08001#include "bios_utils.hpp"
2#include "libpldmresponder/bios_config.hpp"
3#include "libpldmresponder/bios_string_attribute.hpp"
4#include "mocked_bios.hpp"
5#include "mocked_utils.hpp"
6
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
82 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler);
83 biosConfig.buildTables();
84
85 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
86 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
87 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
88
89 EXPECT_TRUE(stringTable);
90 EXPECT_TRUE(attrTable);
91 EXPECT_TRUE(attrValueTable);
92
93 std::set<std::string> expectedStrings = {"HMCManagedState",
94 "On",
95 "Off",
96 "FWBootSide",
97 "Perm",
98 "Temp",
99 "InbandCodeUpdate",
100 "Allowed",
101 "NotAllowed",
102 "CodeUpdatePolicy",
103 "Concurrent",
104 "Disruptive",
105 "VDD_AVSBUS_RAIL",
106 "SBE_IMAGE_MINIMUM_VALID_ECS",
107 "INTEGER_INVALID_CASE",
108 "str_example1",
109 "str_example2",
110 "str_example3"};
111 std::set<std::string> strings;
112 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
113 stringTable->data(), stringTable->size()))
114 {
115 auto str = table::string::decodeString(entry);
116 strings.emplace(str);
117 }
118
119 EXPECT_EQ(strings, expectedStrings);
120
121 BIOSStringTable biosStringTable(*stringTable);
122
123 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
124 attrTable->size()))
125 {
126 auto header = table::attribute::decodeHeader(entry);
127 auto attrName = biosStringTable.findString(header.stringHandle);
128 auto jsonEntry = findJsonEntry(attrName);
129 EXPECT_TRUE(jsonEntry);
130 switch (header.attrType)
131 {
132 case PLDM_BIOS_STRING:
133 case PLDM_BIOS_STRING_READ_ONLY:
134 {
135 auto stringField = table::attribute::decodeStringEntry(entry);
136 auto stringType = BIOSStringAttribute::strTypeMap.at(
137 jsonEntry->at("string_type").get<std::string>());
138 EXPECT_EQ(stringField.stringType,
139 static_cast<uint8_t>(stringType));
140
141 EXPECT_EQ(
142 stringField.minLength,
143 jsonEntry->at("minimum_string_length").get<uint16_t>());
144 EXPECT_EQ(
145 stringField.maxLength,
146 jsonEntry->at("maximum_string_length").get<uint16_t>());
147 EXPECT_EQ(
148 stringField.defLength,
149 jsonEntry->at("default_string_length").get<uint16_t>());
150 EXPECT_EQ(stringField.defString,
151 jsonEntry->at("default_string").get<std::string>());
152 break;
153 }
John Wang95e6b3c2020-02-13 09:43:24 +0800154 case PLDM_BIOS_INTEGER:
155 case PLDM_BIOS_INTEGER_READ_ONLY:
156 {
157 auto integerField = table::attribute::decodeIntegerEntry(entry);
158 EXPECT_EQ(integerField.lowerBound,
159 jsonEntry->at("lower_bound").get<uint64_t>());
160 EXPECT_EQ(integerField.upperBound,
161 jsonEntry->at("upper_bound").get<uint64_t>());
162 EXPECT_EQ(integerField.scalarIncrement,
163 jsonEntry->at("scalar_increment").get<uint32_t>());
164 EXPECT_EQ(integerField.defaultValue,
165 jsonEntry->at("default_value").get<uint64_t>());
166 break;
167 }
John Wang3be70852020-02-13 15:59:04 +0800168 case PLDM_BIOS_ENUMERATION:
169 case PLDM_BIOS_ENUMERATION_READ_ONLY:
170 {
171 auto [pvHdls, defInds] =
172 table::attribute::decodeEnumEntry(entry);
173 auto possibleValues = jsonEntry->at("possible_values")
174 .get<std::vector<std::string>>();
175 std::vector<std::string> strings;
176 for (auto pv : pvHdls)
177 {
178 auto s = biosStringTable.findString(pv);
179 strings.emplace_back(s);
180 }
181 EXPECT_EQ(strings, possibleValues);
182 EXPECT_EQ(defInds.size(), 1);
183
184 auto defValue = biosStringTable.findString(pvHdls[defInds[0]]);
185 auto defaultValues = jsonEntry->at("default_values")
186 .get<std::vector<std::string>>();
187 EXPECT_EQ(defValue, defaultValues[0]);
188
189 break;
190 }
John Wangd9659342020-02-27 16:46:05 +0800191 default:
192 EXPECT_TRUE(false);
193 break;
194 }
195 }
196
197 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
198 attrValueTable->data(), attrValueTable->size()))
199 {
200 auto header = table::attribute_value::decodeHeader(entry);
201 auto attrEntry =
202 table::attribute::findByHandle(*attrTable, header.attrHandle);
203 auto attrHeader = table::attribute::decodeHeader(attrEntry);
204 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
205 auto jsonEntry = findJsonEntry(attrName);
206 EXPECT_TRUE(jsonEntry);
207 switch (header.attrType)
208 {
209 case PLDM_BIOS_STRING:
210 case PLDM_BIOS_STRING_READ_ONLY:
211 {
212 auto value = table::attribute_value::decodeStringEntry(entry);
213 auto defValue =
214 jsonEntry->at("default_string").get<std::string>();
215 EXPECT_EQ(value, defValue);
216 break;
217 }
John Wang95e6b3c2020-02-13 09:43:24 +0800218 case PLDM_BIOS_INTEGER:
219 case PLDM_BIOS_INTEGER_READ_ONLY:
220 {
221 auto value = table::attribute_value::decodeIntegerEntry(entry);
222 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
223 EXPECT_EQ(value, defValue);
224 break;
225 }
John Wang3be70852020-02-13 15:59:04 +0800226 case PLDM_BIOS_ENUMERATION:
227 case PLDM_BIOS_ENUMERATION_READ_ONLY:
228 {
229 auto indices = table::attribute_value::decodeEnumEntry(entry);
230 EXPECT_EQ(indices.size(), 1);
231 auto possibleValues = jsonEntry->at("possible_values")
232 .get<std::vector<std::string>>();
233
234 auto defValues = jsonEntry->at("default_values")
235 .get<std::vector<std::string>>();
236 EXPECT_EQ(possibleValues[indices[0]], defValues[0]);
237 break;
238 }
John Wangd9659342020-02-27 16:46:05 +0800239 default:
240 EXPECT_TRUE(false);
241 break;
242 }
243 }
244}
245
246TEST_F(TestBIOSConfig, setAttrValue)
247{
248 MockdBusHandler dbusHandler;
249
250 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler);
251 biosConfig.removeTables();
252 biosConfig.buildTables();
253
254 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
255 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
256
257 BIOSStringTable biosStringTable(*stringTable);
258 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
259 attrTable->size());
260 auto stringHandle = biosStringTable.findHandle("str_example1");
261 uint16_t attrHandle{};
262
263 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
264 attrTable->size()))
265 {
266 auto header = table::attribute::decodeHeader(entry);
267 if (header.stringHandle == stringHandle)
268 {
269 attrHandle = header.attrHandle;
270 break;
271 }
272 }
273
274 EXPECT_NE(attrHandle, 0);
275
276 std::vector<uint8_t> attrValueEntry{
277 0, 0, /* attr handle */
278 1, /* attr type string read-write */
279 4, 0, /* current string length */
280 'a', 'b', 'c', 'd', /* defaut value string handle index */
281 };
282
283 attrValueEntry[0] = attrHandle & 0xff;
284 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
285
286 DBusMapping dbusMapping{"/xyz/abc/def",
287 "xyz.openbmc_project.str_example1.value",
288 "Str_example1", "string"};
289 PropertyValue value = std::string("abcd");
290 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
291
292 auto rc =
293 biosConfig.setAttrValue(attrValueEntry.data(), attrValueEntry.size());
294 EXPECT_EQ(rc, PLDM_SUCCESS);
295
296 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
297 auto findEntry =
298 [&attrValueTable](
299 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
300 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
301 attrValueTable->data(), attrValueTable->size()))
302 {
303 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
304 if (attrHandle == handle)
305 return entry;
306 }
307 return nullptr;
308 };
309
310 auto entry = findEntry(attrHandle);
311 EXPECT_NE(entry, nullptr);
312
313 auto p = reinterpret_cast<const uint8_t*>(entry);
314 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
315 ElementsAreArray(attrValueEntry));
316}