blob: b5b207b7ade5fd2c81ce6282e2cb7e82bc56ddd0 [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.
58 Strings vec{"HMCManagedState", "On", "Off",
59 "FWBootSide", "Perm", "Temp",
60 "InbandCodeUpdate", "Allowed", "NotAllowed",
61 "CodeUpdatePolicy", "Concurrent", "Disruptive"};
62
63 Strings nullVec{};
64
65 // Invalid directory
66 auto strings = bios_parser::getStrings("./bios_json");
67 ASSERT_EQ(strings == nullVec, true);
68
69 strings = bios_parser::getStrings("./bios_jsons");
70 ASSERT_EQ(strings == vec, true);
71}
72
73TEST(getAttrValue, allScenarios)
74{
75 using namespace bios_parser::bios_enum;
Tom Joseph52552ef2019-06-20 09:50:15 +053076 // All the BIOS Strings in the BIOS JSON config files.
77 AttrValuesMap valueMap{
78 {"HMCManagedState", {false, {"On", "Off"}, {"On"}}},
79 {"FWBootSide", {false, {"Perm", "Temp"}, {"Perm"}}},
80 {"InbandCodeUpdate", {false, {"Allowed", "NotAllowed"}, {"Allowed"}}},
81 {"CodeUpdatePolicy",
82 {false, {"Concurrent", "Disruptive"}, {"Concurrent"}}}};
83
Sampa Misrab37be312019-07-03 02:26:41 -050084 auto rc = setupValueLookup("./bios_jsons");
85 ASSERT_EQ(rc, 0);
86
Tom Joseph52552ef2019-06-20 09:50:15 +053087 auto values = getValues();
88 ASSERT_EQ(valueMap == values, true);
89
90 CurrentValues cv{"Concurrent"};
91 auto value = getAttrValue("CodeUpdatePolicy");
92 ASSERT_EQ(value == cv, true);
93
94 // Invalid attribute name
95 ASSERT_THROW(getAttrValue("CodeUpdatePolic"), std::out_of_range);
96}
Sampa Misrab37be312019-07-03 02:26:41 -050097
98namespace fs = std::filesystem;
99class TestAllBIOSTables : public ::testing::Test
100{
101 public:
102 static void SetUpTestCase() // will execute once at the begining of all
103 // TestAllBIOSTables objects
104 {
105 char tmpdir[] = "/tmp/allBiosTables.XXXXXX";
106 biosPath = fs::path(mkdtemp(tmpdir));
107 }
108
109 static void TearDownTestCase() // will be executed once at th eend of all
110 // TestAllBIOSTables objects
111 {
112 fs::remove_all(biosPath);
113 }
114
115 static fs::path biosPath;
116};
117
118fs::path TestAllBIOSTables::biosPath;
119
120TEST_F(TestAllBIOSTables, GetBIOSTableTestBadRequest)
121{
122 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
123 requestPayload{};
124 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
125 struct pldm_get_bios_table_req* req =
126 (struct pldm_get_bios_table_req*)request->payload;
127 req->transfer_handle = 9;
128 req->transfer_op_flag = PLDM_GET_FIRSTPART;
129 req->table_type = 0xFF;
130
131 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
132
133 auto response = internal::buildBIOSTables(request, requestPayloadLength,
134 "./bios_jsons", biosPath.c_str());
135 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
136
137 struct pldm_get_bios_table_resp* resp =
138 reinterpret_cast<struct pldm_get_bios_table_resp*>(
139 responsePtr->payload);
140
141 ASSERT_EQ(PLDM_INVALID_BIOS_TABLE_TYPE, resp->completion_code);
142}
143
144TEST_F(TestAllBIOSTables, buildBIOSTablesTestBadRequest)
145{
146 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
147 requestPayload{};
148 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
149 struct pldm_get_bios_table_req* req =
150 (struct pldm_get_bios_table_req*)request->payload;
151 req->transfer_handle = 9;
152 req->transfer_op_flag = PLDM_GET_FIRSTPART;
153 req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
154
155 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
156
157 auto response = internal::buildBIOSTables(request, requestPayloadLength,
158 "./bios_jsons", biosPath.c_str());
159 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
160 struct pldm_get_bios_table_resp* resp =
161 reinterpret_cast<struct pldm_get_bios_table_resp*>(
162 responsePtr->payload);
163 ASSERT_EQ(PLDM_BIOS_TABLE_UNAVAILABLE, resp->completion_code);
164
165 req->table_type = PLDM_BIOS_ATTR_TABLE;
166 response = internal::buildBIOSTables(request, requestPayloadLength,
167 "./bios_jsons", biosPath.c_str());
168 responsePtr = reinterpret_cast<pldm_msg*>(response.data());
169 resp = reinterpret_cast<struct pldm_get_bios_table_resp*>(
170 responsePtr->payload);
171 ASSERT_EQ(PLDM_BIOS_TABLE_UNAVAILABLE, resp->completion_code);
172}
173
174TEST_F(TestAllBIOSTables, GetBIOSStringTableTestGoodRequest)
175{
176 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
177 requestPayload{};
178 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
179 struct pldm_get_bios_table_req* req =
180 (struct pldm_get_bios_table_req*)request->payload;
181 req->transfer_handle = 9;
182 req->transfer_op_flag = PLDM_GET_FIRSTPART;
183 req->table_type = PLDM_BIOS_STRING_TABLE;
184
185 Strings biosStrings = getStrings("./bios_jsons");
186 std::sort(biosStrings.begin(), biosStrings.end());
187 biosStrings.erase(std::unique(biosStrings.begin(), biosStrings.end()),
188 biosStrings.end());
189
190 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
191 uint8_t times = 0;
192 while (times < 2)
193 { // first time fresh table second time existing table
194 auto response = internal::buildBIOSTables(
195 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
196 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
197
198 struct pldm_get_bios_table_resp* resp =
199 reinterpret_cast<struct pldm_get_bios_table_resp*>(
200 responsePtr->payload);
201
202 ASSERT_EQ(0, resp->completion_code);
203 ASSERT_EQ(0, resp->next_transfer_handle);
204 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
205
206 uint16_t strLen = 0;
207 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
208
209 for (auto elem : biosStrings)
210 {
211 struct pldm_bios_string_table_entry* ptr =
212 reinterpret_cast<struct pldm_bios_string_table_entry*>(
213 tableData);
214 strLen = ptr->string_length;
215 ASSERT_EQ(strLen, elem.size());
216 ASSERT_EQ(0, memcmp(elem.c_str(), ptr->name, strLen));
217 tableData += (sizeof(pldm_bios_string_table_entry) - 1) + strLen;
218
219 } // end for
220 times++;
221 }
222}
223
224TEST_F(TestAllBIOSTables, getBIOSAttributeTableTestGoodRequest)
225{
226 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
227 requestPayload{};
228 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
229 struct pldm_get_bios_table_req* req =
230 (struct pldm_get_bios_table_req*)request->payload;
231 req->transfer_handle = 9;
232 req->transfer_op_flag = PLDM_GET_FIRSTPART;
233 req->table_type = PLDM_BIOS_ATTR_TABLE;
234
235 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
236
237 uint8_t times = 0;
238 while (times < 2)
239 { // first time fresh table second time existing table
240 auto response = internal::buildBIOSTables(
241 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
242 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
243
244 struct pldm_get_bios_table_resp* resp =
245 reinterpret_cast<struct pldm_get_bios_table_resp*>(
246 responsePtr->payload);
247
248 ASSERT_EQ(0, resp->completion_code);
249 ASSERT_EQ(0, resp->next_transfer_handle);
250 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
251
252 uint32_t attrTableLen =
253 response.size() - sizeof(pldm_msg_hdr) -
254 (sizeof(resp->completion_code) +
255 sizeof(resp->next_transfer_handle) + sizeof(resp->transfer_flag));
256 uint32_t traversed = 0;
257 uint16_t attrHdl = 0;
258 uint16_t stringHdl = 0;
259 uint8_t attrType = 0;
260 uint8_t numPosVals = 0;
261 uint8_t numDefVals = 0;
262 uint8_t defIndex = 0;
263
264 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
265 while (1)
266 {
267 struct pldm_bios_attr_table_entry* ptr =
268 reinterpret_cast<struct pldm_bios_attr_table_entry*>(tableData);
269 attrHdl = ptr->attr_handle;
270 attrType = ptr->attr_type;
271 EXPECT_EQ(0, attrHdl);
272 EXPECT_EQ(PLDM_BIOS_ENUMERATION, attrType);
273 stringHdl = ptr->string_handle;
274 EXPECT_EQ(stringHdl, 1);
275 tableData += sizeof(attrHdl) + sizeof(attrType) + sizeof(stringHdl);
276 numPosVals = *tableData;
277 EXPECT_EQ(numPosVals, 2);
278 traversed += sizeof(attrHdl) + sizeof(attrType) + sizeof(stringHdl);
279 traversed += sizeof(numPosVals);
280 PossibleValuesByHandle possiVals;
281 tableData++;
282 uint16_t* temp = reinterpret_cast<uint16_t*>(tableData);
283 uint32_t i = 0;
284 while (i < numPosVals)
285 {
286 uint16_t val = *temp;
287 possiVals.push_back(val);
288 temp++;
289 i++;
290 }
291 EXPECT_EQ(possiVals.size(), 2);
292 tableData += numPosVals * sizeof(stringHdl);
293 traversed += numPosVals * sizeof(stringHdl);
294 numDefVals = *tableData;
295 EXPECT_EQ(numDefVals, 1);
296 tableData += numDefVals * sizeof(defIndex);
297 traversed += numDefVals + sizeof(numDefVals);
298
299 break; // test for first row only
300
301 if ((attrTableLen - traversed) < 8)
302 {
303 // reached pad
304 break;
305 }
306
307 } // end while
308 times++;
309 }
310
311} // end TEST
312
313TEST_F(TestAllBIOSTables, getBIOSAttributeValueTableTestGoodRequest)
314{
315 std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_BIOS_TABLE_REQ_BYTES>
316 requestPayload{};
317 auto request = reinterpret_cast<pldm_msg*>(requestPayload.data());
318 struct pldm_get_bios_table_req* req =
319 (struct pldm_get_bios_table_req*)request->payload;
320 req->transfer_handle = 9;
321 req->transfer_op_flag = PLDM_GET_FIRSTPART;
322 req->table_type = PLDM_BIOS_ATTR_VAL_TABLE;
323
324 std::string attrName("CodeUpdatePolicy");
325 CurrentValues currVals = getAttrValue(attrName);
326
327 size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
328
329 uint8_t times = 0;
330 while (times < 2)
331 { // first time frest table second time existing table
332 auto response = internal::buildBIOSTables(
333 request, requestPayloadLength, "./bios_jsons", biosPath.c_str());
334 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
335
336 struct pldm_get_bios_table_resp* resp =
337 reinterpret_cast<struct pldm_get_bios_table_resp*>(
338 responsePtr->payload);
339
340 ASSERT_EQ(0, resp->completion_code);
341 ASSERT_EQ(0, resp->next_transfer_handle);
342 ASSERT_EQ(PLDM_START_AND_END, resp->transfer_flag);
343
344 uint32_t attrValTableLen =
345 response.size() - sizeof(pldm_msg_hdr) -
346 (sizeof(resp->completion_code) +
347 sizeof(resp->next_transfer_handle) + sizeof(resp->transfer_flag));
348 uint32_t traversed = 0;
349 uint8_t* tableData = reinterpret_cast<uint8_t*>(resp->table_data);
350
351 uint16_t attrHdl;
352 uint8_t attrType;
353 uint8_t numCurrVals;
354 uint8_t currValStrIndex;
355
356 while (1)
357 {
358 struct pldm_bios_attr_val_table_entry* ptr =
359 reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
360 tableData);
361 attrHdl = ptr->attr_handle;
362 attrType = ptr->attr_type;
363 EXPECT_EQ(0, attrHdl);
364 EXPECT_EQ(PLDM_BIOS_ENUMERATION, attrType);
365 tableData += sizeof(attrHdl) + sizeof(attrType);
366 traversed += sizeof(attrHdl) + sizeof(attrType);
367 numCurrVals = *tableData;
368 EXPECT_EQ(1, numCurrVals);
369 tableData += sizeof(numCurrVals);
370 traversed += sizeof(numCurrVals);
371 currValStrIndex = *tableData;
372 EXPECT_EQ(0, currValStrIndex);
373 tableData += numCurrVals;
374 traversed += numCurrVals;
375 break; // testing for first row
376 if ((attrValTableLen - traversed) < 8)
377 {
378 break;
379 }
380 }
381 times++;
382 }
383
384} // end TEST