blob: 05a3ced10bd73a2ae8340d4c8c7939aac5d5d83d [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 Wangd9659342020-02-27 16:46:05 +080032 };
33
34 for (auto& path : paths)
35 {
36 std::ifstream file;
37 file.open(path);
38 auto j = Json::parse(file);
39 jsons.emplace_back(j);
40 }
41 }
42
43 std::optional<Json> findJsonEntry(const std::string& name)
44 {
45 for (auto& json : jsons)
46 {
47 auto entries = json.at("entries");
48 for (auto& entry : entries)
49 {
50 auto n = entry.at("attribute_name").get<std::string>();
51 if (n == name)
52 {
53 return entry;
54 }
55 }
56 }
57 return std::nullopt;
58 }
59
60 static void TearDownTestCase() // will be executed once at th end of all
61 // TestBIOSConfig objects
62 {
63 fs::remove_all(tableDir);
64 }
65
66 static fs::path tableDir;
67 static std::vector<Json> jsons;
68};
69
70fs::path TestBIOSConfig::tableDir;
71std::vector<Json> TestBIOSConfig::jsons;
72
73TEST_F(TestBIOSConfig, buildTablesTest)
74{
75 MockdBusHandler dbusHandler;
76
77 ON_CALL(dbusHandler, getDbusPropertyVariant(_, _, _))
78 .WillByDefault(Throw(std::exception()));
79
80 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler);
81 biosConfig.buildTables();
82
83 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
84 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
85 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
86
87 EXPECT_TRUE(stringTable);
88 EXPECT_TRUE(attrTable);
89 EXPECT_TRUE(attrValueTable);
90
91 std::set<std::string> expectedStrings = {"HMCManagedState",
92 "On",
93 "Off",
94 "FWBootSide",
95 "Perm",
96 "Temp",
97 "InbandCodeUpdate",
98 "Allowed",
99 "NotAllowed",
100 "CodeUpdatePolicy",
101 "Concurrent",
102 "Disruptive",
103 "VDD_AVSBUS_RAIL",
104 "SBE_IMAGE_MINIMUM_VALID_ECS",
105 "INTEGER_INVALID_CASE",
106 "str_example1",
107 "str_example2",
108 "str_example3"};
109 std::set<std::string> strings;
110 for (auto entry : BIOSTableIter<PLDM_BIOS_STRING_TABLE>(
111 stringTable->data(), stringTable->size()))
112 {
113 auto str = table::string::decodeString(entry);
114 strings.emplace(str);
115 }
116
117 EXPECT_EQ(strings, expectedStrings);
118
119 BIOSStringTable biosStringTable(*stringTable);
120
121 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
122 attrTable->size()))
123 {
124 auto header = table::attribute::decodeHeader(entry);
125 auto attrName = biosStringTable.findString(header.stringHandle);
126 auto jsonEntry = findJsonEntry(attrName);
127 EXPECT_TRUE(jsonEntry);
128 switch (header.attrType)
129 {
130 case PLDM_BIOS_STRING:
131 case PLDM_BIOS_STRING_READ_ONLY:
132 {
133 auto stringField = table::attribute::decodeStringEntry(entry);
134 auto stringType = BIOSStringAttribute::strTypeMap.at(
135 jsonEntry->at("string_type").get<std::string>());
136 EXPECT_EQ(stringField.stringType,
137 static_cast<uint8_t>(stringType));
138
139 EXPECT_EQ(
140 stringField.minLength,
141 jsonEntry->at("minimum_string_length").get<uint16_t>());
142 EXPECT_EQ(
143 stringField.maxLength,
144 jsonEntry->at("maximum_string_length").get<uint16_t>());
145 EXPECT_EQ(
146 stringField.defLength,
147 jsonEntry->at("default_string_length").get<uint16_t>());
148 EXPECT_EQ(stringField.defString,
149 jsonEntry->at("default_string").get<std::string>());
150 break;
151 }
John Wang95e6b3c2020-02-13 09:43:24 +0800152 case PLDM_BIOS_INTEGER:
153 case PLDM_BIOS_INTEGER_READ_ONLY:
154 {
155 auto integerField = table::attribute::decodeIntegerEntry(entry);
156 EXPECT_EQ(integerField.lowerBound,
157 jsonEntry->at("lower_bound").get<uint64_t>());
158 EXPECT_EQ(integerField.upperBound,
159 jsonEntry->at("upper_bound").get<uint64_t>());
160 EXPECT_EQ(integerField.scalarIncrement,
161 jsonEntry->at("scalar_increment").get<uint32_t>());
162 EXPECT_EQ(integerField.defaultValue,
163 jsonEntry->at("default_value").get<uint64_t>());
164 break;
165 }
John Wangd9659342020-02-27 16:46:05 +0800166 default:
167 EXPECT_TRUE(false);
168 break;
169 }
170 }
171
172 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
173 attrValueTable->data(), attrValueTable->size()))
174 {
175 auto header = table::attribute_value::decodeHeader(entry);
176 auto attrEntry =
177 table::attribute::findByHandle(*attrTable, header.attrHandle);
178 auto attrHeader = table::attribute::decodeHeader(attrEntry);
179 auto attrName = biosStringTable.findString(attrHeader.stringHandle);
180 auto jsonEntry = findJsonEntry(attrName);
181 EXPECT_TRUE(jsonEntry);
182 switch (header.attrType)
183 {
184 case PLDM_BIOS_STRING:
185 case PLDM_BIOS_STRING_READ_ONLY:
186 {
187 auto value = table::attribute_value::decodeStringEntry(entry);
188 auto defValue =
189 jsonEntry->at("default_string").get<std::string>();
190 EXPECT_EQ(value, defValue);
191 break;
192 }
John Wang95e6b3c2020-02-13 09:43:24 +0800193 case PLDM_BIOS_INTEGER:
194 case PLDM_BIOS_INTEGER_READ_ONLY:
195 {
196 auto value = table::attribute_value::decodeIntegerEntry(entry);
197 auto defValue = jsonEntry->at("default_value").get<uint64_t>();
198 EXPECT_EQ(value, defValue);
199 break;
200 }
John Wangd9659342020-02-27 16:46:05 +0800201 default:
202 EXPECT_TRUE(false);
203 break;
204 }
205 }
206}
207
208TEST_F(TestBIOSConfig, setAttrValue)
209{
210 MockdBusHandler dbusHandler;
211
212 BIOSConfig biosConfig("./bios_jsons", tableDir.c_str(), &dbusHandler);
213 biosConfig.removeTables();
214 biosConfig.buildTables();
215
216 auto stringTable = biosConfig.getBIOSTable(PLDM_BIOS_STRING_TABLE);
217 auto attrTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_TABLE);
218
219 BIOSStringTable biosStringTable(*stringTable);
220 BIOSTableIter<PLDM_BIOS_ATTR_TABLE> attrTableIter(attrTable->data(),
221 attrTable->size());
222 auto stringHandle = biosStringTable.findHandle("str_example1");
223 uint16_t attrHandle{};
224
225 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_TABLE>(attrTable->data(),
226 attrTable->size()))
227 {
228 auto header = table::attribute::decodeHeader(entry);
229 if (header.stringHandle == stringHandle)
230 {
231 attrHandle = header.attrHandle;
232 break;
233 }
234 }
235
236 EXPECT_NE(attrHandle, 0);
237
238 std::vector<uint8_t> attrValueEntry{
239 0, 0, /* attr handle */
240 1, /* attr type string read-write */
241 4, 0, /* current string length */
242 'a', 'b', 'c', 'd', /* defaut value string handle index */
243 };
244
245 attrValueEntry[0] = attrHandle & 0xff;
246 attrValueEntry[1] = (attrHandle >> 8) & 0xff;
247
248 DBusMapping dbusMapping{"/xyz/abc/def",
249 "xyz.openbmc_project.str_example1.value",
250 "Str_example1", "string"};
251 PropertyValue value = std::string("abcd");
252 EXPECT_CALL(dbusHandler, setDbusProperty(dbusMapping, value)).Times(1);
253
254 auto rc =
255 biosConfig.setAttrValue(attrValueEntry.data(), attrValueEntry.size());
256 EXPECT_EQ(rc, PLDM_SUCCESS);
257
258 auto attrValueTable = biosConfig.getBIOSTable(PLDM_BIOS_ATTR_VAL_TABLE);
259 auto findEntry =
260 [&attrValueTable](
261 uint16_t handle) -> const pldm_bios_attr_val_table_entry* {
262 for (auto entry : BIOSTableIter<PLDM_BIOS_ATTR_VAL_TABLE>(
263 attrValueTable->data(), attrValueTable->size()))
264 {
265 auto [attrHandle, _] = table::attribute_value::decodeHeader(entry);
266 if (attrHandle == handle)
267 return entry;
268 }
269 return nullptr;
270 };
271
272 auto entry = findEntry(attrHandle);
273 EXPECT_NE(entry, nullptr);
274
275 auto p = reinterpret_cast<const uint8_t*>(entry);
276 EXPECT_THAT(std::vector<uint8_t>(p, p + attrValueEntry.size()),
277 ElementsAreArray(attrValueEntry));
278}