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