1 #include <endian.h>
2 #include <libpldm/base.h>
3 #include <libpldm/bios.h>
4 #include <libpldm/bios_table.h>
5 #include <libpldm/utils.h>
6 
7 #include <algorithm>
8 #include <cstdint>
9 #include <cstring>
10 #include <iterator>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17 
18 using testing::ElementsAreArray;
19 using Table = std::vector<uint8_t>;
20 
buildTable(Table & table)21 void buildTable(Table& table)
22 {
23     auto padSize = ((table.size() % 4) ? (4 - table.size() % 4) : 0);
24     table.insert(table.end(), padSize, 0);
25     uint32_t checksum = crc32(table.data(), table.size());
26     checksum = htole32(checksum);
27     uint8_t a[4];
28     std::memcpy(a, &checksum, sizeof(checksum));
29     table.insert(table.end(), std::begin(a), std::end(a));
30 }
31 
32 template <typename First, typename... Rest>
buildTable(Table & table,First & first,Rest &...rest)33 void buildTable(Table& table, First& first, Rest&... rest)
34 {
35     table.insert(table.end(), first.begin(), first.end());
36     buildTable(table, rest...);
37 }
38 
TEST(AttrTable,HeaderDecodeTest)39 TEST(AttrTable, HeaderDecodeTest)
40 {
41     std::vector<uint8_t> enumEntry{
42         2, 0, /* attr handle */
43         0,    /* attr type */
44         1, 0, /* attr name handle (string handle) */
45         2,    /* number of possible value */
46         2, 0, /* possible value handle */
47         3, 0, /* possible value handle */
48         1,    /* number of default value */
49         0     /* defaut value string handle index */
50     };
51     auto entry =
52         reinterpret_cast<struct pldm_bios_attr_table_entry*>(enumEntry.data());
53     auto attrHandle = pldm_bios_table_attr_entry_decode_attribute_handle(entry);
54     EXPECT_EQ(attrHandle, 2);
55     auto attrType = pldm_bios_table_attr_entry_decode_attribute_type(entry);
56     EXPECT_EQ(attrType, 0);
57     auto stringHandle = pldm_bios_table_attr_entry_decode_string_handle(entry);
58     EXPECT_EQ(stringHandle, 1);
59 }
60 
TEST(AttrTable,EnumEntryDecodeTest)61 TEST(AttrTable, EnumEntryDecodeTest)
62 {
63     std::vector<uint8_t> enumEntry{
64         0, 0, /* attr handle */
65         0,    /* attr type */
66         1, 0, /* attr name handle */
67         2,    /* number of possible value */
68         2, 0, /* possible value handle */
69         3, 0, /* possible value handle */
70         1,    /* number of default value */
71         1     /* defaut value string handle index */
72     };
73 
74     auto entry =
75         reinterpret_cast<struct pldm_bios_attr_table_entry*>(enumEntry.data());
76     uint8_t pvNumber;
77     ASSERT_EQ(
78         pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNumber),
79         PLDM_SUCCESS);
80     EXPECT_EQ(pvNumber, 2);
81     pvNumber = 0;
82     auto rc =
83         pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNumber);
84     EXPECT_EQ(rc, PLDM_SUCCESS);
85     EXPECT_EQ(pvNumber, 2);
86 
87     std::vector<uint16_t> pvHandles(pvNumber, 0);
88     ASSERT_EQ(pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
89                   entry, pvHandles.data(), pvHandles.size()),
90               PLDM_SUCCESS);
91     EXPECT_EQ(pvNumber, 2);
92     EXPECT_EQ(pvHandles[0], 2);
93     EXPECT_EQ(pvHandles[1], 3);
94     pvHandles.resize(1);
95     ASSERT_EQ(pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
96                   entry, pvHandles.data(), pvHandles.size()),
97               PLDM_SUCCESS);
98     EXPECT_EQ(pvHandles[0], 2);
99 
100     pvHandles.resize(2);
101     rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
102         entry, pvHandles.data(), pvHandles.size());
103     EXPECT_EQ(rc, PLDM_SUCCESS);
104     EXPECT_EQ(pvHandles[0], 2);
105     EXPECT_EQ(pvHandles[1], 3);
106     rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
107         entry, pvHandles.data(), 1);
108     EXPECT_EQ(rc, PLDM_SUCCESS);
109 
110     uint8_t defNumber;
111     ASSERT_EQ(
112         pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNumber),
113         PLDM_SUCCESS);
114     EXPECT_EQ(defNumber, 1);
115     std::vector<uint8_t> defIndices(defNumber);
116     rc = pldm_bios_table_attr_entry_enum_decode_def_indices(
117         entry, defIndices.data(), defIndices.size());
118     EXPECT_EQ(rc, defNumber);
119     EXPECT_THAT(defIndices, ElementsAreArray({1}));
120 
121     defNumber = 0;
122     rc =
123         pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNumber);
124     EXPECT_EQ(rc, PLDM_SUCCESS);
125     EXPECT_EQ(defNumber, 1);
126 
127     rc =
128         pldm_bios_table_attr_entry_enum_decode_pv_num_check(nullptr, &pvNumber);
129     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
130     rc = pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, nullptr);
131     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
132 
133     entry->attr_type = PLDM_BIOS_STRING;
134     rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNumber);
135     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
136 
137     rc =
138         pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNumber);
139     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
140     rc =
141         pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(entry, nullptr, 0);
142     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
143 }
144 
TEST(AttrTable,EnumEntryEncodeTest)145 TEST(AttrTable, EnumEntryEncodeTest)
146 {
147     std::vector<uint8_t> enumEntry{
148         0, 0, /* attr handle */
149         0,    /* attr type */
150         1, 0, /* attr name handle */
151         2,    /* number of possible value */
152         2, 0, /* possible value handle */
153         3, 0, /* possible value handle */
154         1,    /* number of default value */
155         0     /* defaut value string handle index */
156     };
157 
158     std::vector<uint16_t> pv_hdls{2, 3};
159     std::vector<uint8_t> defs{0};
160 
161     struct pldm_bios_table_attr_entry_enum_info info = {
162         1,              /* name handle */
163         false,          /* read only */
164         2,              /* pv number */
165         pv_hdls.data(), /* pv handle */
166         1,              /*def number */
167         defs.data()     /*def index*/
168     };
169     auto encodeLength = pldm_bios_table_attr_entry_enum_encode_length(2, 1);
170     EXPECT_EQ(encodeLength, enumEntry.size());
171 
172     std::vector<uint8_t> encodeEntry(encodeLength, 0);
173     ASSERT_EQ(pldm_bios_table_attr_entry_enum_encode_check(
174                   encodeEntry.data(), encodeEntry.size(), &info),
175               PLDM_SUCCESS);
176     // set attr handle = 0
177     encodeEntry[0] = 0;
178     encodeEntry[1] = 0;
179 
180     EXPECT_EQ(enumEntry, encodeEntry);
181 
182     EXPECT_NE(pldm_bios_table_attr_entry_enum_encode_check(
183                   encodeEntry.data(), encodeEntry.size() - 1, &info),
184               PLDM_SUCCESS);
185     auto rc = pldm_bios_table_attr_entry_enum_encode_check(
186         encodeEntry.data(), encodeEntry.size(), &info);
187     EXPECT_EQ(rc, PLDM_SUCCESS);
188     // set attr handle = 0
189     encodeEntry[0] = 0;
190     encodeEntry[1] = 0;
191 
192     EXPECT_EQ(enumEntry, encodeEntry);
193     rc = pldm_bios_table_attr_entry_enum_encode_check(
194         encodeEntry.data(), encodeEntry.size() - 1, &info);
195     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
196 }
197 
TEST(AttrTable,StringEntryDecodeTest)198 TEST(AttrTable, StringEntryDecodeTest)
199 {
200     std::vector<uint8_t> stringEntry{
201         1,   0,       /* attr handle */
202         1,            /* attr type */
203         12,  0,       /* attr name handle */
204         1,            /* string type */
205         1,   0,       /* minimum length of the string in bytes */
206         100, 0,       /* maximum length of the string in bytes */
207         3,   0,       /* length of default string in length */
208         'a', 'b', 'c' /* default string  */
209     };
210 
211     auto entry = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
212         stringEntry.data());
213     auto stringType =
214         pldm_bios_table_attr_entry_string_decode_string_type(entry);
215     EXPECT_EQ(stringType, 1);
216     auto minLength = pldm_bios_table_attr_entry_string_decode_min_length(entry);
217     EXPECT_EQ(minLength, 1);
218     auto maxLength = pldm_bios_table_attr_entry_string_decode_max_length(entry);
219     EXPECT_EQ(maxLength, 100);
220 
221     uint16_t defStringLength;
222     ASSERT_EQ(pldm_bios_table_attr_entry_string_decode_def_string_length_check(
223                   entry, &defStringLength),
224               PLDM_SUCCESS);
225     EXPECT_EQ(defStringLength, 3);
226     std::vector<char> defString(defStringLength + 1);
227     auto rc = pldm_bios_table_attr_entry_string_decode_def_string(
228         entry, defString.data(), defString.size());
229     EXPECT_EQ(rc, 3);
230     EXPECT_STREQ(defString.data(), "abc");
231     rc = pldm_bios_table_attr_entry_string_decode_def_string(
232         entry, defString.data(), defString.size() - 1);
233     EXPECT_EQ(rc, 2);
234     EXPECT_STREQ(defString.data(), "ab");
235 
236     defStringLength = 0;
237     rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
238         entry, &defStringLength);
239     EXPECT_EQ(rc, PLDM_SUCCESS);
240     EXPECT_EQ(defStringLength, 3);
241 
242     rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
243         entry, nullptr);
244     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
245     rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
246         nullptr, &defStringLength);
247     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
248     entry->attr_type = PLDM_BIOS_INTEGER;
249     rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
250         entry, &defStringLength);
251     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
252     rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
253         nullptr, &defStringLength);
254     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
255 }
256 
TEST(AttrTable,StringEntryEncodeTest)257 TEST(AttrTable, StringEntryEncodeTest)
258 {
259     std::vector<uint8_t> stringEntry{
260         0,   0,        /* attr handle */
261         1,             /* attr type */
262         3,   0,        /* attr name handle */
263         1,             /* string type */
264         1,   0,        /* min string length */
265         100, 0,        /* max string length */
266         3,   0,        /* default string length */
267         'a', 'b', 'c', /* defaul string */
268     };
269 
270     struct pldm_bios_table_attr_entry_string_info info = {
271         3,     /* name handle */
272         false, /* read only */
273         1,     /* string type ascii */
274         1,     /* min length */
275         100,   /* max length */
276         3,     /* def length */
277         "abc", /* def string */
278     };
279     auto encodeLength = pldm_bios_table_attr_entry_string_encode_length(3);
280     EXPECT_EQ(encodeLength, stringEntry.size());
281 
282     std::vector<uint8_t> encodeEntry(encodeLength, 0);
283     ASSERT_EQ(pldm_bios_table_attr_entry_string_encode_check(
284                   encodeEntry.data(), encodeEntry.size(), &info),
285               PLDM_SUCCESS);
286     // set attr handle = 0
287     encodeEntry[0] = 0;
288     encodeEntry[1] = 0;
289 
290     EXPECT_EQ(stringEntry, encodeEntry);
291 
292     EXPECT_NE(pldm_bios_table_attr_entry_string_encode_check(
293                   encodeEntry.data(), encodeEntry.size() - 1, &info),
294               PLDM_SUCCESS);
295     auto rc = pldm_bios_table_attr_entry_string_encode_check(
296         encodeEntry.data(), encodeEntry.size(), &info);
297     EXPECT_EQ(rc, PLDM_SUCCESS);
298     // set attr handle = 0
299     encodeEntry[0] = 0;
300     encodeEntry[1] = 0;
301 
302     EXPECT_EQ(stringEntry, encodeEntry);
303     rc = pldm_bios_table_attr_entry_string_encode_check(
304         encodeEntry.data(), encodeEntry.size() - 1, &info);
305     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
306     std::swap(info.max_length, info.min_length);
307     const char* errmsg;
308     rc = pldm_bios_table_attr_entry_string_info_check(&info, &errmsg);
309     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
310     EXPECT_STREQ(
311         "MinimumStingLength should not be greater than MaximumStringLength",
312         errmsg);
313     rc = pldm_bios_table_attr_entry_string_encode_check(
314         encodeEntry.data(), encodeEntry.size(), &info);
315     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
316     std::swap(info.max_length, info.min_length);
317 
318     std::vector<uint8_t> stringEntryLength0{
319         0,   0, /* attr handle */
320         1,      /* attr type */
321         3,   0, /* attr name handle */
322         1,      /* string type */
323         0,   0, /* min string length */
324         100, 0, /* max string length */
325         0,   0, /* default string length */
326     };
327 
328     info.min_length = 0;
329     info.def_length = 0;
330     info.def_string = nullptr;
331 
332     encodeLength = pldm_bios_table_attr_entry_string_encode_length(0);
333     EXPECT_EQ(encodeLength, stringEntryLength0.size());
334 
335     encodeEntry.resize(encodeLength);
336     ASSERT_EQ(pldm_bios_table_attr_entry_string_encode_check(
337                   encodeEntry.data(), encodeEntry.size(), &info),
338               PLDM_SUCCESS);
339     // set attr handle = 0
340     encodeEntry[0] = 0;
341     encodeEntry[1] = 0;
342 
343     EXPECT_EQ(stringEntryLength0, encodeEntry);
344 }
345 
TEST(AttrTable,integerEntryEncodeTest)346 TEST(AttrTable, integerEntryEncodeTest)
347 {
348     std::vector<uint8_t> integerEntry{
349         0,  0,                   /* attr handle */
350         3,                       /* attr type */
351         1,  0,                   /* attr name handle */
352         1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
353         10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
354         2,  0, 0, 0,             /* scalar increment */
355         3,  0, 0, 0, 0, 0, 0, 0, /* defaut value */
356     };
357 
358     std::vector<uint16_t> pv_hdls{2, 3};
359     std::vector<uint8_t> defs{0};
360 
361     struct pldm_bios_table_attr_entry_integer_info info = {
362         1,     /* name handle */
363         false, /* read only */
364         1,     /* lower bound */
365         10,    /* upper bound */
366         2,     /* sacalar increment */
367         3      /* default value */
368     };
369     auto encodeLength = pldm_bios_table_attr_entry_integer_encode_length();
370     EXPECT_EQ(encodeLength, integerEntry.size());
371 
372     std::vector<uint8_t> encodeEntry(encodeLength, 0);
373     ASSERT_EQ(pldm_bios_table_attr_entry_integer_encode_check(
374                   encodeEntry.data(), encodeEntry.size(), &info),
375               PLDM_SUCCESS);
376     // set attr handle = 0
377     encodeEntry[0] = 0;
378     encodeEntry[1] = 0;
379 
380     EXPECT_EQ(integerEntry, encodeEntry);
381 
382     EXPECT_NE(pldm_bios_table_attr_entry_integer_encode_check(
383                   encodeEntry.data(), encodeEntry.size() - 1, &info),
384               PLDM_SUCCESS);
385 
386     auto rc = pldm_bios_table_attr_entry_integer_encode_check(
387         encodeEntry.data(), encodeEntry.size(), &info);
388     EXPECT_EQ(rc, PLDM_SUCCESS);
389     // set attr handle = 0
390     encodeEntry[0] = 0;
391     encodeEntry[1] = 0;
392 
393     EXPECT_EQ(integerEntry, encodeEntry);
394 
395     rc = pldm_bios_table_attr_entry_integer_encode_check(
396         encodeEntry.data(), encodeEntry.size() - 1, &info);
397     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
398 
399     info.lower_bound = 100;
400     info.upper_bound = 50;
401     const char* errmsg;
402     rc = pldm_bios_table_attr_entry_integer_info_check(&info, &errmsg);
403     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
404     EXPECT_STREQ("LowerBound should not be greater than UpperBound", errmsg);
405     rc = pldm_bios_table_attr_entry_integer_encode_check(
406         encodeEntry.data(), encodeEntry.size(), &info);
407     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
408 }
409 
TEST(AttrTable,integerEntryDecodeTest)410 TEST(AttrTable, integerEntryDecodeTest)
411 {
412     std::vector<uint8_t> integerEntry{
413         0,  0,                   /* attr handle */
414         3,                       /* attr type */
415         1,  0,                   /* attr name handle */
416         1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
417         10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
418         2,  0, 0, 0,             /* scalar increment */
419         3,  0, 0, 0, 0, 0, 0, 0, /* defaut value */
420     };
421 
422     uint64_t lower;
423     uint64_t upper;
424     uint64_t def;
425     uint32_t scalar;
426     auto entry = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
427         integerEntry.data());
428     pldm_bios_table_attr_entry_integer_decode(entry, &lower, &upper, &scalar,
429                                               &def);
430     EXPECT_EQ(lower, 1u);
431     EXPECT_EQ(upper, 10u);
432     EXPECT_EQ(scalar, 2u);
433     EXPECT_EQ(def, 3u);
434 }
435 
TEST(AttrTable,ItearatorTest)436 TEST(AttrTable, ItearatorTest)
437 {
438     std::vector<uint8_t> enumEntry{
439         0, 0, /* attr handle */
440         0,    /* attr type */
441         1, 0, /* attr name handle */
442         2,    /* number of possible value */
443         2, 0, /* possible value handle */
444         3, 0, /* possible value handle */
445         1,    /* number of default value */
446         0     /* defaut value string handle index */
447     };
448     std::vector<uint8_t> stringEntry{
449         1,   0,       /* attr handle */
450         1,            /* attr type */
451         12,  0,       /* attr name handle */
452         1,            /* string type */
453         1,   0,       /* minimum length of the string in bytes */
454         100, 0,       /* maximum length of the string in bytes */
455         3,   0,       /* length of default string in length */
456         'a', 'b', 'c' /* default string  */
457     };
458     std::vector<uint8_t> integerEntry{
459         0,  0,                   /* attr handle */
460         3,                       /* attr type */
461         1,  0,                   /* attr name handle */
462         1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
463         10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
464         2,  0, 0, 0,             /* scalar increment */
465         3,  0, 0, 0, 0, 0, 0, 0, /* defaut value */
466     };
467 
468     Table table;
469     buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
470     auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
471                                             PLDM_BIOS_ATTR_TABLE);
472     auto entry = pldm_bios_table_iter_attr_entry_value(iter);
473     auto rc = std::memcmp(entry, enumEntry.data(), enumEntry.size());
474     EXPECT_EQ(rc, 0);
475 
476     pldm_bios_table_iter_next(iter);
477     entry = pldm_bios_table_iter_attr_entry_value(iter);
478     rc = std::memcmp(entry, stringEntry.data(), stringEntry.size());
479     EXPECT_EQ(rc, 0);
480 
481     pldm_bios_table_iter_next(iter);
482     entry = pldm_bios_table_iter_attr_entry_value(iter);
483     rc = std::memcmp(entry, integerEntry.data(), integerEntry.size());
484     EXPECT_EQ(rc, 0);
485 
486     pldm_bios_table_iter_next(iter);
487     entry = pldm_bios_table_iter_attr_entry_value(iter);
488     rc = std::memcmp(entry, enumEntry.data(), enumEntry.size());
489     EXPECT_EQ(rc, 0);
490 
491     pldm_bios_table_iter_next(iter);
492     EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
493     pldm_bios_table_iter_free(iter);
494 }
495 
TEST(AttrTable,FindTest)496 TEST(AttrTable, FindTest)
497 {
498     std::vector<uint8_t> enumEntry{
499         0, 0, /* attr handle */
500         0,    /* attr type */
501         1, 0, /* attr name handle */
502         2,    /* number of possible value */
503         2, 0, /* possible value handle */
504         3, 0, /* possible value handle */
505         1,    /* number of default value */
506         0     /* defaut value string handle index */
507     };
508     std::vector<uint8_t> stringEntry{
509         1,   0,       /* attr handle */
510         1,            /* attr type */
511         2,   0,       /* attr name handle */
512         1,            /* string type */
513         1,   0,       /* minimum length of the string in bytes */
514         100, 0,       /* maximum length of the string in bytes */
515         3,   0,       /* length of default string in length */
516         'a', 'b', 'c' /* default string  */
517     };
518     std::vector<uint8_t> integerEntry{
519         0,  0,                   /* attr handle */
520         3,                       /* attr type */
521         3,  0,                   /* attr name handle */
522         1,  0, 0, 0, 0, 0, 0, 0, /* lower bound */
523         10, 0, 0, 0, 0, 0, 0, 0, /* upper bound */
524         2,  0, 0, 0,             /* scalar increment */
525         3,  0, 0, 0, 0, 0, 0, 0, /* defaut value */
526     };
527 
528     Table table;
529     buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
530 
531     auto entry =
532         pldm_bios_table_attr_find_by_handle(table.data(), table.size(), 1);
533     EXPECT_NE(entry, nullptr);
534     auto p = reinterpret_cast<const uint8_t*>(entry);
535     EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
536                 ElementsAreArray(stringEntry));
537 
538     entry = pldm_bios_table_attr_find_by_handle(table.data(), table.size(), 3);
539     EXPECT_EQ(entry, nullptr);
540 
541     entry = pldm_bios_table_attr_find_by_string_handle(table.data(),
542                                                        table.size(), 2);
543     EXPECT_NE(entry, nullptr);
544     p = reinterpret_cast<const uint8_t*>(entry);
545     EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
546                 ElementsAreArray(stringEntry));
547 
548     entry = pldm_bios_table_attr_find_by_string_handle(table.data(),
549                                                        table.size(), 4);
550     EXPECT_EQ(entry, nullptr);
551 }
552 
TEST(AttrValTable,HeaderDecodeTest)553 TEST(AttrValTable, HeaderDecodeTest)
554 {
555     std::vector<uint8_t> enumEntry{
556         1, 0, /* attr handle */
557         0,    /* attr type */
558         2,    /* number of current value */
559         0,    /* current value string handle index */
560         1,    /* current value string handle index */
561     };
562     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
563         enumEntry.data());
564     auto attrHandle =
565         pldm_bios_table_attr_value_entry_decode_attribute_handle(entry);
566     EXPECT_EQ(attrHandle, 1);
567     auto attrType =
568         pldm_bios_table_attr_value_entry_decode_attribute_type(entry);
569     EXPECT_EQ(attrType, 0);
570 }
571 
TEST(AttrValTable,EnumEntryEncodeTest)572 TEST(AttrValTable, EnumEntryEncodeTest)
573 {
574     std::vector<uint8_t> enumEntry{
575         0, 0, /* attr handle */
576         0,    /* attr type */
577         2,    /* number of current value */
578         0,    /* current value string handle index */
579         1,    /* current value string handle index */
580     };
581 
582     auto length = pldm_bios_table_attr_value_entry_encode_enum_length(2);
583     EXPECT_EQ(length, enumEntry.size());
584     std::vector<uint8_t> encodeEntry(length, 0);
585     uint8_t handles[] = {0, 1};
586     ASSERT_EQ(pldm_bios_table_attr_value_entry_encode_enum_check(
587                   encodeEntry.data(), encodeEntry.size(), 0, 0, 2, handles),
588               PLDM_SUCCESS);
589     EXPECT_EQ(encodeEntry, enumEntry);
590 
591     EXPECT_NE(pldm_bios_table_attr_value_entry_encode_enum_check(
592                   encodeEntry.data(), encodeEntry.size() - 1, 0, 0, 2, handles),
593               PLDM_SUCCESS);
594 
595     auto rc = pldm_bios_table_attr_value_entry_encode_enum_check(
596         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_ENUMERATION, 2,
597         handles);
598     EXPECT_EQ(rc, PLDM_SUCCESS);
599     EXPECT_EQ(encodeEntry, enumEntry);
600     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
601         enumEntry.data());
602     entry->attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY;
603     rc = pldm_bios_table_attr_value_entry_encode_enum_check(
604         encodeEntry.data(), encodeEntry.size(), 0,
605         PLDM_BIOS_ENUMERATION_READ_ONLY, 2, handles);
606     EXPECT_EQ(rc, PLDM_SUCCESS);
607     EXPECT_EQ(encodeEntry, enumEntry);
608     rc = pldm_bios_table_attr_value_entry_encode_enum_check(
609         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 2,
610         handles);
611     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
612     rc = pldm_bios_table_attr_value_entry_encode_enum_check(
613         encodeEntry.data(), encodeEntry.size() - 1, 0, PLDM_BIOS_ENUMERATION, 2,
614         handles);
615     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
616 }
617 
TEST(AttrValTable,EnumEntryDecodeTest)618 TEST(AttrValTable, EnumEntryDecodeTest)
619 {
620     std::vector<uint8_t> enumEntry{
621         0, 0, /* attr handle */
622         0,    /* attr type */
623         2,    /* number of current value */
624         0,    /* current value string handle index */
625         1,    /* current value string handle index */
626     };
627 
628     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
629         enumEntry.data());
630     auto number = pldm_bios_table_attr_value_entry_enum_decode_number(entry);
631     EXPECT_EQ(2, number);
632 
633     std::vector<uint8_t> handles(2, 0);
634     auto rc = pldm_bios_table_attr_value_entry_enum_decode_handles(
635         entry, handles.data(), handles.size());
636     EXPECT_EQ(rc, 2);
637     EXPECT_EQ(handles[0], 0);
638     EXPECT_EQ(handles[1], 1);
639 
640     /* Buffer size is more than the number of current string handles */
641     std::vector<uint8_t> handleIndexes(3, 0);
642     rc = pldm_bios_table_attr_value_entry_enum_decode_handles(
643         entry, handleIndexes.data(), handleIndexes.size());
644     EXPECT_EQ(rc, 2);
645     EXPECT_EQ(handleIndexes[0], 0);
646     EXPECT_EQ(handleIndexes[1], 1);
647 
648     /* Buffersize is less than the number of current string handles */
649     std::vector<uint8_t> strHandles(1, 0);
650     rc = pldm_bios_table_attr_value_entry_enum_decode_handles(
651         entry, strHandles.data(), strHandles.size());
652     EXPECT_EQ(rc, 1);
653     EXPECT_EQ(strHandles[0], 0);
654 }
655 
TEST(AttrValTable,stringEntryEncodeTest)656 TEST(AttrValTable, stringEntryEncodeTest)
657 {
658     std::vector<uint8_t> stringEntry{
659         0,   0,        /* attr handle */
660         1,             /* attr type */
661         3,   0,        /* current string length */
662         'a', 'b', 'c', /* defaut value string handle index */
663     };
664 
665     auto length = pldm_bios_table_attr_value_entry_encode_string_length(3);
666     EXPECT_EQ(length, stringEntry.size());
667     std::vector<uint8_t> encodeEntry(length, 0);
668     ASSERT_EQ(pldm_bios_table_attr_value_entry_encode_string_check(
669                   encodeEntry.data(), encodeEntry.size(), 0, 1, 3, "abc"),
670               PLDM_SUCCESS);
671     EXPECT_EQ(encodeEntry, stringEntry);
672 
673     EXPECT_NE(pldm_bios_table_attr_value_entry_encode_string_check(
674                   encodeEntry.data(), encodeEntry.size() - 1, 0, 1, 3, "abc"),
675               PLDM_SUCCESS);
676 
677     auto rc = pldm_bios_table_attr_value_entry_encode_string_check(
678         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_STRING, 3, "abc");
679     EXPECT_EQ(rc, PLDM_SUCCESS);
680     EXPECT_EQ(encodeEntry, stringEntry);
681     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
682         stringEntry.data());
683     entry->attr_type = PLDM_BIOS_STRING_READ_ONLY;
684     rc = pldm_bios_table_attr_value_entry_encode_string_check(
685         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_STRING_READ_ONLY,
686         3, "abc");
687     EXPECT_EQ(rc, PLDM_SUCCESS);
688     EXPECT_EQ(encodeEntry, stringEntry);
689     rc = pldm_bios_table_attr_value_entry_encode_string_check(
690         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 3,
691         "abc");
692     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
693     rc = pldm_bios_table_attr_value_entry_encode_string_check(
694         encodeEntry.data(), encodeEntry.size() - 1, 0, PLDM_BIOS_STRING, 3,
695         "abc");
696     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
697 }
698 
TEST(AttrValTable,StringEntryDecodeTest)699 TEST(AttrValTable, StringEntryDecodeTest)
700 {
701     std::vector<uint8_t> stringEntry{
702         0,   0,        /* attr handle */
703         1,             /* attr type */
704         3,   0,        /* current string length */
705         'a', 'b', 'c', /* defaut value string handle index */
706     };
707 
708     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
709         stringEntry.data());
710     auto length = pldm_bios_table_attr_value_entry_string_decode_length(entry);
711     EXPECT_EQ(3, length);
712 
713     auto handle = pldm_bios_table_attr_value_entry_decode_handle(entry);
714     EXPECT_EQ(0, handle);
715 
716     auto entryLength = pldm_bios_table_attr_value_entry_length(entry);
717     EXPECT_EQ(stringEntry.size(), entryLength);
718 
719     variable_field currentString{};
720     pldm_bios_table_attr_value_entry_string_decode_string(entry,
721                                                           &currentString);
722     EXPECT_THAT(std::vector<uint8_t>(currentString.ptr,
723                                      currentString.ptr + currentString.length),
724                 ElementsAreArray(std::vector<uint8_t>{'a', 'b', 'c'}));
725 }
726 
TEST(AttrValTable,integerEntryEncodeTest)727 TEST(AttrValTable, integerEntryEncodeTest)
728 {
729     std::vector<uint8_t> integerEntry{
730         0,  0,                   /* attr handle */
731         3,                       /* attr type */
732         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
733     };
734 
735     auto length = pldm_bios_table_attr_value_entry_encode_integer_length();
736     EXPECT_EQ(length, integerEntry.size());
737     std::vector<uint8_t> encodeEntry(length, 0);
738     ASSERT_EQ(
739         pldm_bios_table_attr_value_entry_encode_integer_check(
740             encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER, 10),
741         PLDM_SUCCESS);
742     EXPECT_EQ(encodeEntry, integerEntry);
743 
744     EXPECT_NE(pldm_bios_table_attr_value_entry_encode_integer_check(
745                   encodeEntry.data(), encodeEntry.size() - 1, 0,
746                   PLDM_BIOS_INTEGER, 10),
747               PLDM_SUCCESS);
748 
749     auto rc = pldm_bios_table_attr_value_entry_encode_integer_check(
750         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER, 10);
751     EXPECT_EQ(rc, PLDM_SUCCESS);
752     EXPECT_EQ(encodeEntry, integerEntry);
753     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
754         integerEntry.data());
755     entry->attr_type = PLDM_BIOS_INTEGER_READ_ONLY;
756     rc = pldm_bios_table_attr_value_entry_encode_integer_check(
757         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_INTEGER_READ_ONLY,
758         10);
759     EXPECT_EQ(rc, PLDM_SUCCESS);
760     EXPECT_EQ(encodeEntry, integerEntry);
761 
762     rc = pldm_bios_table_attr_value_entry_encode_integer_check(
763         encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 10);
764     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
765     rc = pldm_bios_table_attr_value_entry_encode_integer_check(
766         encodeEntry.data(), encodeEntry.size() - 1, 0,
767         PLDM_BIOS_INTEGER_READ_ONLY, 10);
768     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
769 }
770 
TEST(AttrValTable,integerEntryDecodeTest)771 TEST(AttrValTable, integerEntryDecodeTest)
772 {
773     std::vector<uint8_t> integerEntry{
774         0,  0,                   /* attr handle */
775         3,                       /* attr type */
776         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
777     };
778 
779     auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
780         integerEntry.data());
781     auto cv = pldm_bios_table_attr_value_entry_integer_decode_cv(entry);
782     EXPECT_EQ(cv, 10u);
783 }
784 
TEST(AttrValTable,IteratorTest)785 TEST(AttrValTable, IteratorTest)
786 {
787     std::vector<uint8_t> enumEntry{
788         0, 0, /* attr handle */
789         0,    /* attr type */
790         2,    /* number of current value */
791         0,    /* current value string handle index */
792         1,    /* current value string handle index */
793     };
794     std::vector<uint8_t> stringEntry{
795         0,   0,        /* attr handle */
796         1,             /* attr type */
797         3,   0,        /* current string length */
798         'a', 'b', 'c', /* defaut value string handle index */
799     };
800     std::vector<uint8_t> integerEntry{
801         0,  0,                   /* attr handle */
802         3,                       /* attr type */
803         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
804     };
805 
806     Table table;
807     buildTable(table, enumEntry, stringEntry, integerEntry, enumEntry);
808 
809     auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
810                                             PLDM_BIOS_ATTR_VAL_TABLE);
811     auto entry = pldm_bios_table_iter_attr_value_entry_value(iter);
812 
813     auto p = reinterpret_cast<const uint8_t*>(entry);
814     EXPECT_THAT(std::vector<uint8_t>(p, p + enumEntry.size()),
815                 ElementsAreArray(enumEntry));
816 
817     pldm_bios_table_iter_next(iter);
818     entry = pldm_bios_table_iter_attr_value_entry_value(iter);
819     p = reinterpret_cast<const uint8_t*>(entry);
820     EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
821                 ElementsAreArray(stringEntry));
822 
823     pldm_bios_table_iter_next(iter);
824     entry = pldm_bios_table_iter_attr_value_entry_value(iter);
825     p = reinterpret_cast<const uint8_t*>(entry);
826     EXPECT_THAT(std::vector<uint8_t>(p, p + integerEntry.size()),
827                 ElementsAreArray(integerEntry));
828 
829     pldm_bios_table_iter_next(iter);
830     entry = pldm_bios_table_iter_attr_value_entry_value(iter);
831     p = reinterpret_cast<const uint8_t*>(entry);
832     EXPECT_THAT(std::vector<uint8_t>(p, p + enumEntry.size()),
833                 ElementsAreArray(enumEntry));
834 
835     pldm_bios_table_iter_next(iter);
836     EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
837 
838     pldm_bios_table_iter_free(iter);
839 }
840 
TEST(AttrValTable,FindTest)841 TEST(AttrValTable, FindTest)
842 {
843     std::vector<uint8_t> enumEntry{
844         0, 0, /* attr handle */
845         0,    /* attr type */
846         2,    /* number of current value */
847         0,    /* current value string handle index */
848         1,    /* current value string handle index */
849     };
850     std::vector<uint8_t> stringEntry{
851         1,   0,        /* attr handle */
852         1,             /* attr type */
853         3,   0,        /* current string length */
854         'a', 'b', 'c', /* defaut value string handle index */
855     };
856     std::vector<uint8_t> integerEntry{
857         2,  0,                   /* attr handle */
858         3,                       /* attr type */
859         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
860     };
861 
862     Table table;
863     buildTable(table, enumEntry, stringEntry, integerEntry);
864 
865     auto entry = pldm_bios_table_attr_value_find_by_handle(table.data(),
866                                                            table.size(), 1);
867     EXPECT_NE(entry, nullptr);
868     auto p = reinterpret_cast<const uint8_t*>(entry);
869     EXPECT_THAT(std::vector<uint8_t>(p, p + stringEntry.size()),
870                 ElementsAreArray(stringEntry));
871 
872     entry = pldm_bios_table_attr_value_find_by_handle(table.data(),
873                                                       table.size(), 3);
874     EXPECT_EQ(entry, nullptr);
875 
876     auto firstEntry =
877         reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(table.data());
878     firstEntry->attr_type = PLDM_BIOS_PASSWORD;
879 #ifdef NDEBUG
880     EXPECT_EQ(pldm_bios_table_attr_value_find_by_handle(table.data(),
881                                                         table.size(), 1),
882               nullptr);
883 #else
884     EXPECT_DEATH(pldm_bios_table_attr_value_find_by_handle(table.data(),
885                                                            table.size(), 1),
886                  "entry_length != NULL");
887 #endif
888 }
889 
TEST(AttrValTable,CopyAndUpdateTest)890 TEST(AttrValTable, CopyAndUpdateTest)
891 {
892     std::vector<uint8_t> enumEntry{
893         0, 0, /* attr handle */
894         0,    /* attr type */
895         2,    /* number of current value */
896         0,    /* current value string handle index */
897         1,    /* current value string handle index */
898     };
899     std::vector<uint8_t> stringEntry{
900         1,   0,        /* attr handle */
901         1,             /* attr type */
902         3,   0,        /* current string length */
903         'a', 'b', 'c', /* defaut value string handle index */
904     };
905     std::vector<uint8_t> integerEntry{
906         2,  0,                   /* attr handle */
907         3,                       /* attr type */
908         10, 0, 0, 0, 0, 0, 0, 0, /* current value */
909     };
910 
911     Table srcTable;
912     buildTable(srcTable, enumEntry, stringEntry, integerEntry);
913 
914     std::vector<uint8_t> stringEntry1{
915         1,   0,        /* attr handle */
916         1,             /* attr type */
917         3,   0,        /* current string length */
918         'd', 'e', 'f', /* defaut value string handle index */
919     };
920 
921     Table expectTable;
922     buildTable(expectTable, enumEntry, stringEntry1, integerEntry);
923     Table destTable(expectTable.size() + 10);
924     auto destLength = destTable.size();
925     auto rc = pldm_bios_table_attr_value_copy_and_update(
926         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
927         stringEntry1.data(), stringEntry1.size());
928 
929     EXPECT_EQ(rc, PLDM_SUCCESS);
930     EXPECT_EQ(destLength, expectTable.size());
931     destTable.resize(destLength);
932     EXPECT_THAT(destTable, ElementsAreArray(expectTable));
933 
934     std::vector<uint8_t> stringEntry2{
935         1,   0,                  /* attr handle */
936         1,                       /* attr type */
937         5,   0,                  /* current string length */
938         'd', 'e', 'f', 'a', 'b', /* defaut value string handle index */
939     };
940     expectTable.resize(0);
941     buildTable(expectTable, enumEntry, stringEntry2, integerEntry);
942     destTable.resize(expectTable.size() + 10);
943     destLength = destTable.size();
944     rc = pldm_bios_table_attr_value_copy_and_update(
945         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
946         stringEntry2.data(), stringEntry2.size());
947     EXPECT_EQ(rc, PLDM_SUCCESS);
948     EXPECT_EQ(destLength, expectTable.size());
949     destTable.resize(destLength);
950     EXPECT_THAT(destTable, ElementsAreArray(expectTable));
951 
952     std::vector<uint8_t> stringEntry3{
953         1,   0, /* attr handle */
954         1,      /* attr type */
955         1,   0, /* current string length */
956         'd',    /* defaut value string handle index */
957     };
958     expectTable.resize(0);
959     buildTable(expectTable, enumEntry, stringEntry3, integerEntry);
960     destTable.resize(expectTable.size() + 10);
961     destLength = destTable.size();
962     rc = pldm_bios_table_attr_value_copy_and_update(
963         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
964         stringEntry3.data(), stringEntry3.size());
965     EXPECT_EQ(rc, PLDM_SUCCESS);
966     EXPECT_EQ(destLength, expectTable.size());
967     destTable.resize(destLength);
968     EXPECT_THAT(destTable, ElementsAreArray(expectTable));
969 
970     stringEntry3[2] = PLDM_BIOS_INTEGER; // set attribute type to integer
971     rc = pldm_bios_table_attr_value_copy_and_update(
972         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
973         stringEntry3.data(), stringEntry3.size());
974     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
975     stringEntry3[2] = PLDM_BIOS_STRING; // set attribute type to string
976 
977     destTable.resize(expectTable.size() - 1);
978     destLength = destTable.size();
979     rc = pldm_bios_table_attr_value_copy_and_update(
980         srcTable.data(), srcTable.size(), destTable.data(), &destLength,
981         stringEntry3.data(), stringEntry3.size());
982     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
983 }
984 
TEST(StringTable,EntryEncodeTest)985 TEST(StringTable, EntryEncodeTest)
986 {
987     std::vector<uint8_t> stringEntry{
988         0,   0,                            /* string handle*/
989         7,   0,                            /* string length */
990         'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
991     };
992 
993     const char* str = "Allowed";
994     auto str_length = std::strlen(str);
995     auto encodeLength = pldm_bios_table_string_entry_encode_length(str_length);
996     EXPECT_EQ(encodeLength, stringEntry.size());
997 
998     std::vector<uint8_t> encodeEntry(encodeLength, 0);
999     ASSERT_EQ(pldm_bios_table_string_entry_encode_check(
1000                   encodeEntry.data(), encodeEntry.size(), str, str_length),
1001               PLDM_SUCCESS);
1002     // set string handle = 0
1003     encodeEntry[0] = 0;
1004     encodeEntry[1] = 0;
1005 
1006     EXPECT_EQ(stringEntry, encodeEntry);
1007 
1008     EXPECT_NE(pldm_bios_table_string_entry_encode_check(
1009                   encodeEntry.data(), encodeEntry.size() - 1, str, str_length),
1010               PLDM_SUCCESS);
1011     auto rc = pldm_bios_table_string_entry_encode_check(
1012         encodeEntry.data(), encodeEntry.size() - 1, str, str_length);
1013     EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
1014 }
1015 
TEST(StringTable,EntryDecodeTest)1016 TEST(StringTable, EntryDecodeTest)
1017 {
1018     std::vector<uint8_t> stringEntry{
1019         4,   0,                            /* string handle*/
1020         7,   0,                            /* string length */
1021         'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
1022     };
1023     auto entry = reinterpret_cast<struct pldm_bios_string_table_entry*>(
1024         stringEntry.data());
1025     auto handle = pldm_bios_table_string_entry_decode_handle(entry);
1026     EXPECT_EQ(handle, 4);
1027     auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
1028     EXPECT_EQ(strLength, 7);
1029 
1030     std::vector<char> buffer(strLength + 1, 0);
1031     pldm_bios_table_string_entry_decode_string_check(entry, buffer.data(),
1032                                                      buffer.size());
1033     EXPECT_EQ(strlen(buffer.data()), strLength);
1034     EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
1035     EXPECT_EQ(pldm_bios_table_string_entry_decode_string_check(
1036                   entry, buffer.data(), 2 + 1 /* sizeof '\0'*/),
1037               PLDM_SUCCESS);
1038     EXPECT_EQ(strlen(buffer.data()), 2);
1039     EXPECT_EQ(std::strcmp("Al", buffer.data()), 0);
1040 
1041     auto rc = pldm_bios_table_string_entry_decode_string_check(
1042         entry, buffer.data(), buffer.size());
1043     EXPECT_EQ(rc, PLDM_SUCCESS);
1044     EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
1045 
1046     /* Ensure equivalence with the unchecked API */
1047     rc = pldm_bios_table_string_entry_decode_string_check(
1048         entry, buffer.data(), 2 + 1 /* sizeof '\0' */);
1049     EXPECT_EQ(rc, std::strcmp("Al", buffer.data()));
1050 }
1051 
TEST(StringTable,IteratorTest)1052 TEST(StringTable, IteratorTest)
1053 {
1054     std::vector<uint8_t> stringHello{
1055         0,   0,                  /* string handle*/
1056         5,   0,                  /* string length */
1057         'H', 'e', 'l', 'l', 'o', /* string */
1058     };
1059     std::vector<uint8_t> stringWorld{
1060         1,   0,                       /* string handle*/
1061         6,   0,                       /* string length */
1062         'W', 'o', 'r', 'l', 'd', '!', /* string */
1063     };
1064 
1065     Table table;
1066     buildTable(table, stringHello, stringWorld);
1067 
1068     auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
1069                                             PLDM_BIOS_STRING_TABLE);
1070     auto entry = pldm_bios_table_iter_string_entry_value(iter);
1071     auto rc = std::memcmp(entry, stringHello.data(), stringHello.size());
1072     EXPECT_EQ(rc, 0);
1073     pldm_bios_table_iter_next(iter);
1074     entry = pldm_bios_table_iter_string_entry_value(iter);
1075     rc = std::memcmp(entry, stringWorld.data(), stringWorld.size());
1076     EXPECT_EQ(rc, 0);
1077     pldm_bios_table_iter_next(iter);
1078     EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
1079     pldm_bios_table_iter_free(iter);
1080 }
1081 
TEST(StringTable,FindTest)1082 TEST(StringTable, FindTest)
1083 {
1084     std::vector<uint8_t> stringHello{
1085         1,   0,                  /* string handle*/
1086         5,   0,                  /* string length */
1087         'H', 'e', 'l', 'l', 'o', /* string */
1088     };
1089     std::vector<uint8_t> stringWorld{
1090         2,   0,                       /* string handle*/
1091         6,   0,                       /* string length */
1092         'W', 'o', 'r', 'l', 'd', '!', /* string */
1093     };
1094     std::vector<uint8_t> stringHi{
1095         3,   0,   /* string handle*/
1096         2,   0,   /* string length */
1097         'H', 'i', /* string */
1098     };
1099 
1100     Table table;
1101     buildTable(table, stringHello, stringWorld, stringHi);
1102 
1103     auto entry = pldm_bios_table_string_find_by_string(table.data(),
1104                                                        table.size(), "World!");
1105     EXPECT_NE(entry, nullptr);
1106     auto handle = pldm_bios_table_string_entry_decode_handle(entry);
1107     EXPECT_EQ(handle, 2);
1108 
1109     entry = pldm_bios_table_string_find_by_string(table.data(), table.size(),
1110                                                   "Worl");
1111     EXPECT_EQ(entry, nullptr);
1112 
1113     entry =
1114         pldm_bios_table_string_find_by_handle(table.data(), table.size(), 3);
1115     EXPECT_NE(entry, nullptr);
1116     auto str_length = pldm_bios_table_string_entry_decode_string_length(entry);
1117     EXPECT_EQ(str_length, 2);
1118     std::vector<char> strBuf(str_length + 1, 0);
1119     auto rc = pldm_bios_table_string_entry_decode_string_check(
1120         entry, strBuf.data(), strBuf.size());
1121     EXPECT_EQ(rc, PLDM_SUCCESS);
1122     EXPECT_EQ(std::strcmp("Hi", strBuf.data()), 0);
1123 
1124     entry =
1125         pldm_bios_table_string_find_by_handle(table.data(), table.size(), 4);
1126     EXPECT_EQ(entry, nullptr);
1127 }
1128 
TEST(Iterator,DeathTest)1129 TEST(Iterator, DeathTest)
1130 {
1131 
1132     Table table(256, 0);
1133 
1134     /* first entry */
1135     auto attr_entry =
1136         reinterpret_cast<struct pldm_bios_attr_table_entry*>(table.data());
1137     auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
1138                                             PLDM_BIOS_ATTR_TABLE);
1139     attr_entry->attr_type = PLDM_BIOS_PASSWORD;
1140 #ifndef NDEBUG
1141     EXPECT_DEATH(pldm_bios_table_iter_next(iter), "attr_table_entry != NULL");
1142 #endif
1143     pldm_bios_table_iter_free(iter);
1144 }
1145 
TEST(PadAndChecksum,PadAndChecksum)1146 TEST(PadAndChecksum, PadAndChecksum)
1147 {
1148     EXPECT_EQ(4u, pldm_bios_table_pad_checksum_size(0));
1149     EXPECT_EQ(7u, pldm_bios_table_pad_checksum_size(1));
1150     EXPECT_EQ(6u, pldm_bios_table_pad_checksum_size(2));
1151     EXPECT_EQ(5u, pldm_bios_table_pad_checksum_size(3));
1152     EXPECT_EQ(4u, pldm_bios_table_pad_checksum_size(4));
1153 
1154     // The table is borrowed from
1155     // https://github.com/openbmc/pldm/commit/69d3e7fb2d9935773f4fbf44326c33f3fc0a3c38
1156     // refer to the commit message
1157     Table attrValTable = {0x09, 0x00, 0x01, 0x02, 0x00, 0x65, 0x66};
1158     auto sizeWithoutPad = attrValTable.size();
1159     attrValTable.resize(sizeWithoutPad +
1160                         pldm_bios_table_pad_checksum_size(sizeWithoutPad));
1161     ASSERT_EQ(pldm_bios_table_append_pad_checksum_check(
1162                   attrValTable.data(), attrValTable.size(), &sizeWithoutPad),
1163               PLDM_SUCCESS);
1164     Table expectedTable = {0x09, 0x00, 0x01, 0x02, 0x00, 0x65,
1165                            0x66, 0x00, 0x6d, 0x81, 0x4a, 0xb6};
1166     EXPECT_EQ(attrValTable, expectedTable);
1167 }
1168 
TEST(BIOSTableChecksum,testBIOSTableChecksum)1169 TEST(BIOSTableChecksum, testBIOSTableChecksum)
1170 {
1171     std::vector<uint8_t> stringTable{
1172         1,   0,                  /* string handle*/
1173         5,   0,                  /* string length */
1174         'T', 'a', 'b', 'l', 'e', /* string */
1175     };
1176 
1177     buildTable(stringTable);
1178 
1179     EXPECT_EQ(true,
1180               pldm_bios_table_checksum(stringTable.data(), stringTable.size()));
1181 }
1182