blob: 417c0aedb036fc52995962e1dead7a2027e58c34 [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
Carol Wang69d3e7f2019-09-04 16:43:15 +080076TEST(getAttrValue, enumScenarios)
Tom Joseph52552ef2019-06-20 09:50:15 +053077{
Tom Joseph52552ef2019-06-20 09:50:15 +053078 // All the BIOS Strings in the BIOS JSON config files.
79 AttrValuesMap valueMap{
80 {"HMCManagedState", {false, {"On", "Off"}, {"On"}}},
81 {"FWBootSide", {false, {"Perm", "Temp"}, {"Perm"}}},
82 {"InbandCodeUpdate", {false, {"Allowed", "NotAllowed"}, {"Allowed"}}},
83 {"CodeUpdatePolicy",
84 {false, {"Concurrent", "Disruptive"}, {"Concurrent"}}}};
85
Carol Wang69d3e7f2019-09-04 16:43:15 +080086 auto rc = bios_parser::bios_enum::setupValueLookup("./bios_jsons");
Sampa Misrab37be312019-07-03 02:26:41 -050087 ASSERT_EQ(rc, 0);
88
Carol Wang69d3e7f2019-09-04 16:43:15 +080089 auto values = bios_parser::bios_enum::getValues();
Tom Joseph52552ef2019-06-20 09:50:15 +053090 ASSERT_EQ(valueMap == values, true);
91
Carol Wang69d3e7f2019-09-04 16:43:15 +080092 bios_parser::bios_enum::CurrentValues cv{"Concurrent"};
93 auto value = bios_parser::bios_enum::getAttrValue("CodeUpdatePolicy");
Tom Joseph52552ef2019-06-20 09:50:15 +053094 ASSERT_EQ(value == cv, true);
95
96 // Invalid attribute name
Carol Wang69d3e7f2019-09-04 16:43:15 +080097 ASSERT_THROW(bios_parser::bios_enum::getAttrValue("CodeUpdatePolic"),
98 std::out_of_range);
99}
100
101TEST(getAttrValue, stringScenarios)
102{
103 // All the BIOS Strings in the BIOS JSON config files.
104 bios_parser::bios_string::AttrValuesMap valueMap{
105 {"str_example1", {false, 1, 1, 100, 3, "abc"}},
106 {"str_example2", {false, 2, 0, 100, 0, ""}},
107 {"str_example3", {true, 0, 1, 100, 2, "ef"}}};
108
109 auto rc = bios_parser::bios_string::setupValueLookup("./bios_jsons");
110 EXPECT_EQ(rc, 0);
111
112 auto values = bios_parser::bios_string::getValues();
113 ASSERT_EQ(valueMap == values, true);
114
115 // Test the attribute without dbus
116 std::string cv = "ef";
117 auto value = bios_parser::bios_string::getAttrValue("str_example3");
118 EXPECT_EQ(value, cv);
119
120 // Invalid attribute name
121 ASSERT_THROW(bios_parser::bios_string::getAttrValue("str_example"),
122 std::out_of_range);
Tom Joseph52552ef2019-06-20 09:50:15 +0530123}
Sampa Misrab37be312019-07-03 02:26:41 -0500124
125namespace fs = std::filesystem;
126class TestAllBIOSTables : public ::testing::Test
127{
128 public:
129 static void SetUpTestCase() // will execute once at the begining of all
130 // TestAllBIOSTables objects
131 {
132 char tmpdir[] = "/tmp/allBiosTables.XXXXXX";
133 biosPath = fs::path(mkdtemp(tmpdir));
134 }
135
136 static void TearDownTestCase() // will be executed once at th eend of all
137 // TestAllBIOSTables objects
138 {
139 fs::remove_all(biosPath);
140 }
141
142 static fs::path biosPath;
143};
144
145fs::path TestAllBIOSTables::biosPath;
146
147TEST_F(TestAllBIOSTables, GetBIOSTableTestBadRequest)
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 = 0xFF;
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
164 struct pldm_get_bios_table_resp* resp =
165 reinterpret_cast<struct pldm_get_bios_table_resp*>(
166 responsePtr->payload);
167
168 ASSERT_EQ(PLDM_INVALID_BIOS_TABLE_TYPE, resp->completion_code);
169}
170
171TEST_F(TestAllBIOSTables, buildBIOSTablesTestBadRequest)
172{
173 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
174 requestPayload{};
175 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
176 struct pldm_get_bios_table_req* req =
177 (struct pldm_get_bios_table_req*)request->payload;
178 req->transfer_handle = 9;
179 req->transfer_op_flag = PLDM_GET_FIRSTPART;
180 req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
181
182 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
183
184 auto response = internal::buildBIOSTables(request, requestPayloadLength,
185 "./bios_jsons", biosPath.c_str());
186 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
187 struct pldm_get_bios_table_resp* resp =
188 reinterpret_cast<struct pldm_get_bios_table_resp*>(
189 responsePtr->payload);
190 ASSERT_EQ(PLDM_BIOS_TABLE_UNAVAILABLE, resp->completion_code);
191
192 req->table_type = PLDM_BIOS_ATTR_TABLE;
193 response = internal::buildBIOSTables(request, requestPayloadLength,
194 "./bios_jsons", biosPath.c_str());
195 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
196 resp = reinterpret_cast<struct pldm_get_bios_table_resp*>(
197 responsePtr->payload);
198 ASSERT_EQ(PLDM_BIOS_TABLE_UNAVAILABLE, resp->completion_code);
199}
200
201TEST_F(TestAllBIOSTables, GetBIOSStringTableTestGoodRequest)
202{
203 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
204 requestPayload{};
205 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
206 struct pldm_get_bios_table_req* req =
207 (struct pldm_get_bios_table_req*)request->payload;
208 req->transfer_handle = 9;
209 req->transfer_op_flag = PLDM_GET_FIRSTPART;
210 req->table_type = PLDM_BIOS_STRING_TABLE;
211
212 Strings biosStrings = getStrings("./bios_jsons");
213 std::sort(biosStrings.begin(), biosStrings.end());
214 biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
215 biosStrings.end());
216
217 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
218 uint8_t times = 0;
219 while (times < 2)
220 { // first time fresh table second time existing table
221 auto response = internal::buildBIOSTables(
222 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
223 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
224
225 struct pldm_get_bios_table_resp* resp =
226 reinterpret_cast<struct pldm_get_bios_table_resp*>(
227 responsePtr->payload);
228
229 ASSERT_EQ(0, resp->completion_code);
230 ASSERT_EQ(0, resp->next_transfer_handle);
231 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
232
233 uint16_t strLen = 0;
234 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
235
236 for (auto elem : biosStrings)
237 {
238 struct pldm_bios_string_table_entry* ptr =
239 reinterpret_cast<struct pldm_bios_string_table_entry*>(
240 tableData);
241 strLen = ptr->string_length;
242 ASSERT_EQ(strLen, elem.size());
243 ASSERT_EQ(0, memcmp(elem.c_str(), ptr->name, strLen));
244 tableData += (sizeof(pldm_bios_string_table_entry) - 1) + strLen;
245
246 } // end for
247 times++;
248 }
249}
250
251TEST_F(TestAllBIOSTables, getBIOSAttributeTableTestGoodRequest)
252{
253 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
254 requestPayload{};
255 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
256 struct pldm_get_bios_table_req* req =
257 (struct pldm_get_bios_table_req*)request->payload;
258 req->transfer_handle = 9;
259 req->transfer_op_flag = PLDM_GET_FIRSTPART;
260 req->table_type = PLDM_BIOS_ATTR_TABLE;
261
262 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
263
264 uint8_t times = 0;
265 while (times < 2)
266 { // first time fresh table second time existing table
267 auto response = internal::buildBIOSTables(
268 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
269 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
270
271 struct pldm_get_bios_table_resp* resp =
272 reinterpret_cast<struct pldm_get_bios_table_resp*>(
273 responsePtr->payload);
274
275 ASSERT_EQ(0, resp->completion_code);
276 ASSERT_EQ(0, resp->next_transfer_handle);
277 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
278
279 uint32_t attrTableLen =
280 response.size() - sizeof(pldm_msg_hdr) -
281 (sizeof(resp->completion_code) +
282 sizeof(resp->next_transfer_handle) + sizeof(resp->transfer_flag));
283 uint32_t traversed = 0;
284 uint16_t attrHdl = 0;
285 uint16_t stringHdl = 0;
286 uint8_t attrType = 0;
287 uint8_t numPosVals = 0;
288 uint8_t numDefVals = 0;
289 uint8_t defIndex = 0;
290
291 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
292 while (1)
293 {
294 struct pldm_bios_attr_table_entry* ptr =
295 reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
296 attrHdl = ptr->attr_handle;
297 attrType = ptr->attr_type;
298 EXPECT_EQ(0, attrHdl);
299 EXPECT_EQ(PLDM_BIOS_ENUMERATION, attrType);
300 stringHdl = ptr->string_handle;
301 EXPECT_EQ(stringHdl, 1);
302 tableData += sizeof(attrHdl) + sizeof(attrType) + sizeof(stringHdl);
303 numPosVals = *tableData;
304 EXPECT_EQ(numPosVals, 2);
305 traversed += sizeof(attrHdl) + sizeof(attrType) + sizeof(stringHdl);
306 traversed += sizeof(numPosVals);
307 PossibleValuesByHandle possiVals;
308 tableData++;
309 uint16_t* temp = reinterpret_cast<uint16_t*>(tableData);
310 uint32_t i = 0;
311 while (i < numPosVals)
312 {
313 uint16_t val = *temp;
314 possiVals.push_back(val);
315 temp++;
316 i++;
317 }
318 EXPECT_EQ(possiVals.size(), 2);
319 tableData += numPosVals * sizeof(stringHdl);
320 traversed += numPosVals * sizeof(stringHdl);
321 numDefVals = *tableData;
322 EXPECT_EQ(numDefVals, 1);
323 tableData += numDefVals * sizeof(defIndex);
324 traversed += numDefVals + sizeof(numDefVals);
325
326 break; // test for first row only
327
328 if ((attrTableLen - traversed) < 8)
329 {
330 // reached pad
331 break;
332 }
333
334 } // end while
335 times++;
336 }
337
338} // end TEST
339
340TEST_F(TestAllBIOSTables, getBIOSAttributeValueTableTestGoodRequest)
341{
342 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
343 requestPayload{};
344 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
345 struct pldm_get_bios_table_req* req =
346 (struct pldm_get_bios_table_req*)request->payload;
347 req->transfer_handle = 9;
348 req->transfer_op_flag = PLDM_GET_FIRSTPART;
349 req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
350
351 std::string attrName("CodeUpdatePolicy");
352 CurrentValues currVals = getAttrValue(attrName);
353
354 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
355
356 uint8_t times = 0;
357 while (times < 2)
358 { // first time frest table second time existing table
359 auto response = internal::buildBIOSTables(
360 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
361 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
362
363 struct pldm_get_bios_table_resp* resp =
364 reinterpret_cast<struct pldm_get_bios_table_resp*>(
365 responsePtr->payload);
366
367 ASSERT_EQ(0, resp->completion_code);
368 ASSERT_EQ(0, resp->next_transfer_handle);
369 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
370
371 uint32_t attrValTableLen =
372 response.size() - sizeof(pldm_msg_hdr) -
373 (sizeof(resp->completion_code) +
374 sizeof(resp->next_transfer_handle) + sizeof(resp->transfer_flag));
375 uint32_t traversed = 0;
376 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
377
378 uint16_t attrHdl;
379 uint8_t attrType;
380 uint8_t numCurrVals;
381 uint8_t currValStrIndex;
382
383 while (1)
384 {
385 struct pldm_bios_attr_val_table_entry* ptr =
386 reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
387 tableData);
388 attrHdl = ptr->attr_handle;
389 attrType = ptr->attr_type;
390 EXPECT_EQ(0, attrHdl);
391 EXPECT_EQ(PLDM_BIOS_ENUMERATION, attrType);
392 tableData += sizeof(attrHdl) + sizeof(attrType);
393 traversed += sizeof(attrHdl) + sizeof(attrType);
394 numCurrVals = *tableData;
395 EXPECT_EQ(1, numCurrVals);
396 tableData += sizeof(numCurrVals);
397 traversed += sizeof(numCurrVals);
398 currValStrIndex = *tableData;
399 EXPECT_EQ(0, currValStrIndex);
400 tableData += numCurrVals;
401 traversed += numCurrVals;
402 break; // testing for first row
403 if ((attrValTableLen - traversed) < 8)
404 {
405 break;
406 }
407 }
408 times++;
409 }
410
411} // end TEST
Carol Wang69d3e7f2019-09-04 16:43:15 +0800412
413class TestSingleTypeBIOSTable : public ::testing::Test
414{
415 public:
416 void SetUp() override
417 { // will be executed before each individual test defined
418 // in TestSingleTypeBIOSTable
419 char tmpdir[] = "/tmp/singleTypeBIOSTable.XXXXXX";
420 destBiosPath = fs::path(mkdtemp(tmpdir));
421 }
422
423 void TearDown() override
424 { // will be executed after each individual test
425 // defined in TestSingleTypeBIOSTable
426 fs::remove_all(destBiosPath);
427 }
428
429 void CopySingleJsonFile(std::string file)
430 {
431 fs::path srcDir("./bios_jsons");
432 fs::path srcBiosPath = srcDir / file;
433 std::filesystem::copy(srcBiosPath, destBiosPath);
434 }
435
436 fs::path destBiosPath;
437};
438
439TEST_F(TestSingleTypeBIOSTable, getBIOSAttributeValueTableBasedOnStringTypeTest)
440{
441 // Copy string json file to the destination
442 TestSingleTypeBIOSTable::CopySingleJsonFile(bios_parser::bIOSStrJson);
443 auto fpath = TestSingleTypeBIOSTable::destBiosPath.c_str();
444
445 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
446 requestPayload{};
447 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
448 struct pldm_get_bios_table_req* req =
449 (struct pldm_get_bios_table_req*)request->payload;
450
451 // Get string table with string json file only
452 req->transfer_handle = 9;
453 req->transfer_op_flag = PLDM_GET_FIRSTPART;
454 req->table_type = PLDM_BIOS_STRING_TABLE;
455
456 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
457 auto str_response =
458 internal::buildBIOSTables(request, requestPayloadLength, fpath, fpath);
459
460 // Get attribute table with string json file only
461 req->transfer_handle = 9;
462 req->transfer_op_flag = PLDM_GET_FIRSTPART;
463 req->table_type = PLDM_BIOS_ATTR_TABLE;
464
465 auto attr_response =
466 internal::buildBIOSTables(request, requestPayloadLength, fpath, fpath);
467
468 // Get attribute value table with string type
469 req->transfer_handle = 9;
470 req->transfer_op_flag = PLDM_GET_FIRSTPART;
471 req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
472
473 // Test attribute str_example3 here, which has no dbus
474 for (uint8_t times = 0; times < 2; times++)
475 { // first time first table second time existing table
476 auto response = internal::buildBIOSTables(request, requestPayloadLength,
477 fpath, fpath);
478 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
479
480 struct pldm_get_bios_table_resp* resp =
481 reinterpret_cast<struct pldm_get_bios_table_resp*>(
482 responsePtr->payload);
483
484 ASSERT_EQ(0, resp->completion_code);
485 ASSERT_EQ(0, resp->next_transfer_handle);
486 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
487
488 uint32_t attrValTableLen =
489 response.size() - sizeof(pldm_msg_hdr) -
490 (sizeof(struct pldm_get_bios_table_resp) - 1);
491 uint32_t traversed = 0;
492 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
493
494 while (true)
495 {
496 struct pldm_bios_attr_val_table_entry* ptr =
497 reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
498 tableData);
499 uint16_t attrHdl = ptr->attr_handle;
500 uint8_t attrType = ptr->attr_type;
501 EXPECT_EQ(PLDM_BIOS_STRING_READ_ONLY, attrType);
502 tableData += sizeof(attrHdl) + sizeof(attrType);
503 traversed += sizeof(attrHdl) + sizeof(attrType);
504 auto sizeDefaultStr = *(reinterpret_cast<uint16_t*>(tableData));
505 EXPECT_EQ(2, sizeDefaultStr);
506 tableData += sizeof(uint16_t);
507 traversed += sizeof(uint16_t);
508 EXPECT_EQ('e', *tableData);
509 EXPECT_EQ('f', *(tableData + 1));
510 tableData += sizeDefaultStr;
511 traversed += sizeDefaultStr;
512 break; // testing for first row
513 if ((attrValTableLen - traversed) < 8)
514 {
515 break;
516 }
517 }
518 }
519
520} // end TEST