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