blob: d54ef2cca677df6b2f8aeb651792b37c4cd53965 [file] [log] [blame]
Sampa Misra032bd502019-03-06 05:03:22 -06001#include "libpldmresponder/bios.hpp"
Tom Joseph52552ef2019-06-20 09:50:15 +05302#include "libpldmresponder/bios_parser.hpp"
Sampa Misrab37be312019-07-03 02:26:41 -05003#include "libpldmresponder/bios_table.hpp"
Sampa Misra032bd502019-03-06 05:03:22 -06004
5#include <string.h>
6
7#include <array>
8#include <ctime>
Sampa Misrab37be312019-07-03 02:26:41 -05009#include <filesystem>
Sampa Misra032bd502019-03-06 05:03:22 -060010
11#include "libpldm/base.h"
12#include "libpldm/bios.h"
13
14#include <gtest/gtest.h>
15
Sampa Misrab37be312019-07-03 02:26:41 -050016using namespace pldm;
Sampa Misra032bd502019-03-06 05:03:22 -060017using namespace pldm::responder;
Sampa Misrab37be312019-07-03 02:26:41 -050018using namespace pldm::responder::bios;
Sampa Misra032bd502019-03-06 05:03:22 -060019using namespace pldm::responder::utils;
Sampa Misrab37be312019-07-03 02:26:41 -050020using namespace bios_parser;
21using namespace bios_parser::bios_enum;
Sampa Misra032bd502019-03-06 05:03:22 -060022
23TEST(epochToBCDTime, testTime)
24{
25 struct tm time
26 {
27 };
28 time.tm_year = 119;
29 time.tm_mon = 3;
30 time.tm_mday = 13;
31 time.tm_hour = 5;
32 time.tm_min = 18;
33 time.tm_sec = 13;
34 time.tm_isdst = -1;
35
36 time_t epochTime = mktime(&time);
37 uint8_t seconds = 0;
38 uint8_t minutes = 0;
39 uint8_t hours = 0;
40 uint8_t day = 0;
41 uint8_t month = 0;
42 uint16_t year = 0;
43
44 epochToBCDTime(epochTime, seconds, minutes, hours, day, month, year);
45
46 ASSERT_EQ(0x13, seconds);
47 ASSERT_EQ(0x18, minutes);
48 ASSERT_EQ(0x5, hours);
49 ASSERT_EQ(0x13, day);
50 ASSERT_EQ(0x4, month);
51 ASSERT_EQ(0x2019, year);
52}
Tom Joseph52552ef2019-06-20 09:50:15 +053053
54TEST(GetBIOSStrings, allScenarios)
55{
56 using namespace bios_parser;
57 // All the BIOS Strings in the BIOS JSON config files.
Carol Wang612f35b2019-08-26 17:14:26 +080058 Strings vec{"HMCManagedState", "On", "Off",
59 "FWBootSide", "Perm", "Temp",
60 "InbandCodeUpdate", "Allowed", "NotAllowed",
61 "CodeUpdatePolicy", "Concurrent", "Disruptive",
62 "str_example1", "str_example2", "str_example3"};
Tom Joseph52552ef2019-06-20 09:50:15 +053063
64 Strings nullVec{};
65
66 // Invalid directory
67 auto strings = bios_parser::getStrings("./bios_json");
68 ASSERT_EQ(strings == nullVec, true);
69
70 strings = bios_parser::getStrings("./bios_jsons");
Carol Wang612f35b2019-08-26 17:14:26 +080071 std::sort(strings.begin(), strings.end());
72 std::sort(vec.begin(), vec.end());
Tom Joseph52552ef2019-06-20 09:50:15 +053073 ASSERT_EQ(strings == vec, true);
74}
75
76TEST(getAttrValue, allScenarios)
77{
78 using namespace bios_parser::bios_enum;
Tom Joseph52552ef2019-06-20 09:50:15 +053079 // All the BIOS Strings in the BIOS JSON config files.
80 AttrValuesMap valueMap{
81 {"HMCManagedState", {false, {"On", "Off"}, {"On"}}},
82 {"FWBootSide", {false, {"Perm", "Temp"}, {"Perm"}}},
83 {"InbandCodeUpdate", {false, {"Allowed", "NotAllowed"}, {"Allowed"}}},
84 {"CodeUpdatePolicy",
85 {false, {"Concurrent", "Disruptive"}, {"Concurrent"}}}};
86
Sampa Misrab37be312019-07-03 02:26:41 -050087 auto rc = setupValueLookup("./bios_jsons");
88 ASSERT_EQ(rc, 0);
89
Tom Joseph52552ef2019-06-20 09:50:15 +053090 auto values = getValues();
91 ASSERT_EQ(valueMap == values, true);
92
93 CurrentValues cv{"Concurrent"};
94 auto value = getAttrValue("CodeUpdatePolicy");
95 ASSERT_EQ(value == cv, true);
96
97 // Invalid attribute name
98 ASSERT_THROW(getAttrValue("CodeUpdatePolic"), std::out_of_range);
99}
Sampa Misrab37be312019-07-03 02:26:41 -0500100
101namespace fs = std::filesystem;
102class TestAllBIOSTables : public ::testing::Test
103{
104 public:
105 static void SetUpTestCase() // will execute once at the begining of all
106 // TestAllBIOSTables objects
107 {
108 char tmpdir[] = "/tmp/allBiosTables.XXXXXX";
109 biosPath = fs::path(mkdtemp(tmpdir));
110 }
111
112 static void TearDownTestCase() // will be executed once at th eend of all
113 // TestAllBIOSTables objects
114 {
115 fs::remove_all(biosPath);
116 }
117
118 static fs::path biosPath;
119};
120
121fs::path TestAllBIOSTables::biosPath;
122
123TEST_F(TestAllBIOSTables, GetBIOSTableTestBadRequest)
124{
125 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
126 requestPayload{};
127 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
128 struct pldm_get_bios_table_req* req =
129 (struct pldm_get_bios_table_req*)request->payload;
130 req->transfer_handle = 9;
131 req->transfer_op_flag = PLDM_GET_FIRSTPART;
132 req->table_type = 0xFF;
133
134 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
135
136 auto response = internal::buildBIOSTables(request, requestPayloadLength,
137 "./bios_jsons", biosPath.c_str());
138 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
139
140 struct pldm_get_bios_table_resp* resp =
141 reinterpret_cast<struct pldm_get_bios_table_resp*>(
142 responsePtr->payload);
143
144 ASSERT_EQ(PLDM_INVALID_BIOS_TABLE_TYPE, resp->completion_code);
145}
146
147TEST_F(TestAllBIOSTables, buildBIOSTablesTestBadRequest)
148{
149 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
150 requestPayload{};
151 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
152 struct pldm_get_bios_table_req* req =
153 (struct pldm_get_bios_table_req*)request->payload;
154 req->transfer_handle = 9;
155 req->transfer_op_flag = PLDM_GET_FIRSTPART;
156 req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
157
158 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
159
160 auto response = internal::buildBIOSTables(request, requestPayloadLength,
161 "./bios_jsons", biosPath.c_str());
162 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
163 struct pldm_get_bios_table_resp* resp =
164 reinterpret_cast<struct pldm_get_bios_table_resp*>(
165 responsePtr->payload);
166 ASSERT_EQ(PLDM_BIOS_TABLE_UNAVAILABLE, resp->completion_code);
167
168 req->table_type = PLDM_BIOS_ATTR_TABLE;
169 response = internal::buildBIOSTables(request, requestPayloadLength,
170 "./bios_jsons", biosPath.c_str());
171 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
172 resp = reinterpret_cast<struct pldm_get_bios_table_resp*>(
173 responsePtr->payload);
174 ASSERT_EQ(PLDM_BIOS_TABLE_UNAVAILABLE, resp->completion_code);
175}
176
177TEST_F(TestAllBIOSTables, GetBIOSStringTableTestGoodRequest)
178{
179 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
180 requestPayload{};
181 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
182 struct pldm_get_bios_table_req* req =
183 (struct pldm_get_bios_table_req*)request->payload;
184 req->transfer_handle = 9;
185 req->transfer_op_flag = PLDM_GET_FIRSTPART;
186 req->table_type = PLDM_BIOS_STRING_TABLE;
187
188 Strings biosStrings = getStrings("./bios_jsons");
189 std::sort(biosStrings.begin(), biosStrings.end());
190 biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
191 biosStrings.end());
192
193 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
194 uint8_t times = 0;
195 while (times < 2)
196 { // first time fresh table second time existing table
197 auto response = internal::buildBIOSTables(
198 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
199 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
200
201 struct pldm_get_bios_table_resp* resp =
202 reinterpret_cast<struct pldm_get_bios_table_resp*>(
203 responsePtr->payload);
204
205 ASSERT_EQ(0, resp->completion_code);
206 ASSERT_EQ(0, resp->next_transfer_handle);
207 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
208
209 uint16_t strLen = 0;
210 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
211
212 for (auto elem : biosStrings)
213 {
214 struct pldm_bios_string_table_entry* ptr =
215 reinterpret_cast<struct pldm_bios_string_table_entry*>(
216 tableData);
217 strLen = ptr->string_length;
218 ASSERT_EQ(strLen, elem.size());
219 ASSERT_EQ(0, memcmp(elem.c_str(), ptr->name, strLen));
220 tableData += (sizeof(pldm_bios_string_table_entry) - 1) + strLen;
221
222 } // end for
223 times++;
224 }
225}
226
227TEST_F(TestAllBIOSTables, getBIOSAttributeTableTestGoodRequest)
228{
229 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
230 requestPayload{};
231 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
232 struct pldm_get_bios_table_req* req =
233 (struct pldm_get_bios_table_req*)request->payload;
234 req->transfer_handle = 9;
235 req->transfer_op_flag = PLDM_GET_FIRSTPART;
236 req->table_type = PLDM_BIOS_ATTR_TABLE;
237
238 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
239
240 uint8_t times = 0;
241 while (times < 2)
242 { // first time fresh table second time existing table
243 auto response = internal::buildBIOSTables(
244 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
245 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
246
247 struct pldm_get_bios_table_resp* resp =
248 reinterpret_cast<struct pldm_get_bios_table_resp*>(
249 responsePtr->payload);
250
251 ASSERT_EQ(0, resp->completion_code);
252 ASSERT_EQ(0, resp->next_transfer_handle);
253 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
254
255 uint32_t attrTableLen =
256 response.size() - sizeof(pldm_msg_hdr) -
257 (sizeof(resp->completion_code) +
258 sizeof(resp->next_transfer_handle) + sizeof(resp->transfer_flag));
259 uint32_t traversed = 0;
260 uint16_t attrHdl = 0;
261 uint16_t stringHdl = 0;
262 uint8_t attrType = 0;
263 uint8_t numPosVals = 0;
264 uint8_t numDefVals = 0;
265 uint8_t defIndex = 0;
266
267 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
268 while (1)
269 {
270 struct pldm_bios_attr_table_entry* ptr =
271 reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
272 attrHdl = ptr->attr_handle;
273 attrType = ptr->attr_type;
274 EXPECT_EQ(0, attrHdl);
275 EXPECT_EQ(PLDM_BIOS_ENUMERATION, attrType);
276 stringHdl = ptr->string_handle;
277 EXPECT_EQ(stringHdl, 1);
278 tableData += sizeof(attrHdl) + sizeof(attrType) + sizeof(stringHdl);
279 numPosVals = *tableData;
280 EXPECT_EQ(numPosVals, 2);
281 traversed += sizeof(attrHdl) + sizeof(attrType) + sizeof(stringHdl);
282 traversed += sizeof(numPosVals);
283 PossibleValuesByHandle possiVals;
284 tableData++;
285 uint16_t* temp = reinterpret_cast<uint16_t*>(tableData);
286 uint32_t i = 0;
287 while (i < numPosVals)
288 {
289 uint16_t val = *temp;
290 possiVals.push_back(val);
291 temp++;
292 i++;
293 }
294 EXPECT_EQ(possiVals.size(), 2);
295 tableData += numPosVals * sizeof(stringHdl);
296 traversed += numPosVals * sizeof(stringHdl);
297 numDefVals = *tableData;
298 EXPECT_EQ(numDefVals, 1);
299 tableData += numDefVals * sizeof(defIndex);
300 traversed += numDefVals + sizeof(numDefVals);
301
302 break; // test for first row only
303
304 if ((attrTableLen - traversed) < 8)
305 {
306 // reached pad
307 break;
308 }
309
310 } // end while
311 times++;
312 }
313
314} // end TEST
315
316TEST_F(TestAllBIOSTables, getBIOSAttributeValueTableTestGoodRequest)
317{
318 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
319 requestPayload{};
320 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
321 struct pldm_get_bios_table_req* req =
322 (struct pldm_get_bios_table_req*)request->payload;
323 req->transfer_handle = 9;
324 req->transfer_op_flag = PLDM_GET_FIRSTPART;
325 req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
326
327 std::string attrName("CodeUpdatePolicy");
328 CurrentValues currVals = getAttrValue(attrName);
329
330 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
331
332 uint8_t times = 0;
333 while (times < 2)
334 { // first time frest table second time existing table
335 auto response = internal::buildBIOSTables(
336 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
337 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
338
339 struct pldm_get_bios_table_resp* resp =
340 reinterpret_cast<struct pldm_get_bios_table_resp*>(
341 responsePtr->payload);
342
343 ASSERT_EQ(0, resp->completion_code);
344 ASSERT_EQ(0, resp->next_transfer_handle);
345 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
346
347 uint32_t attrValTableLen =
348 response.size() - sizeof(pldm_msg_hdr) -
349 (sizeof(resp->completion_code) +
350 sizeof(resp->next_transfer_handle) + sizeof(resp->transfer_flag));
351 uint32_t traversed = 0;
352 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
353
354 uint16_t attrHdl;
355 uint8_t attrType;
356 uint8_t numCurrVals;
357 uint8_t currValStrIndex;
358
359 while (1)
360 {
361 struct pldm_bios_attr_val_table_entry* ptr =
362 reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
363 tableData);
364 attrHdl = ptr->attr_handle;
365 attrType = ptr->attr_type;
366 EXPECT_EQ(0, attrHdl);
367 EXPECT_EQ(PLDM_BIOS_ENUMERATION, attrType);
368 tableData += sizeof(attrHdl) + sizeof(attrType);
369 traversed += sizeof(attrHdl) + sizeof(attrType);
370 numCurrVals = *tableData;
371 EXPECT_EQ(1, numCurrVals);
372 tableData += sizeof(numCurrVals);
373 traversed += sizeof(numCurrVals);
374 currValStrIndex = *tableData;
375 EXPECT_EQ(0, currValStrIndex);
376 tableData += numCurrVals;
377 traversed += numCurrVals;
378 break; // testing for first row
379 if ((attrValTableLen - traversed) < 8)
380 {
381 break;
382 }
383 }
384 times++;
385 }
386
387} // end TEST