blob: 8a808a5f9a492a878f5c20000d4aa1fb58d44b90 [file] [log] [blame]
#include <string.h>
#include <cstring>
#include <vector>
#include "libpldm/base.h"
#include "libpldm/bios.h"
#include "libpldm/bios_table.h"
#include <gtest/gtest.h>
using Table = std::vector<uint8_t>;
void buildTable(Table& table)
{
auto padSize = ((table.size() % 4) ? (4 - table.size() % 4) : 0);
table.insert(table.end(), padSize, 0);
table.insert(table.end(), sizeof(uint32_t) /*checksum*/, 0);
}
template <typename First, typename... Rest>
void buildTable(Table& table, First& first, Rest&... rest)
{
table.insert(table.end(), first.begin(), first.end());
buildTable(table, rest...);
}
TEST(AttrTable, EnumEntryDecodeTest)
{
std::vector<uint8_t> enumEntry{
0, 0, /* attr handle */
0, /* attr type */
1, 0, /* attr name handle */
2, /* number of possible value */
2, 0, /* possible value handle */
3, 0, /* possible value handle */
1, /* number of default value */
0 /* defaut value string handle index */
};
auto entry =
reinterpret_cast<struct pldm_bios_attr_table_entry*>(enumEntry.data());
uint8_t pvNumber = pldm_bios_table_attr_entry_enum_decode_pv_num(entry);
EXPECT_EQ(pvNumber, 2);
pvNumber = 0;
auto rc =
pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNumber);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(pvNumber, 2);
std::vector<uint16_t> pvHandles(pvNumber, 0);
pvNumber = pldm_bios_table_attr_entry_enum_decode_pv_hdls(
entry, pvHandles.data(), pvHandles.size());
EXPECT_EQ(pvNumber, 2);
EXPECT_EQ(pvHandles[0], 2);
EXPECT_EQ(pvHandles[1], 3);
pvHandles.resize(1);
pvNumber = pldm_bios_table_attr_entry_enum_decode_pv_hdls(
entry, pvHandles.data(), pvHandles.size());
EXPECT_EQ(pvNumber, 1);
EXPECT_EQ(pvHandles[0], 2);
pvHandles.resize(2);
rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
entry, pvHandles.data(), pvHandles.size());
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(pvHandles[0], 2);
EXPECT_EQ(pvHandles[1], 3);
rc = pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(
entry, pvHandles.data(), 1);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
uint8_t defNumber = pldm_bios_table_attr_entry_enum_decode_def_num(entry);
EXPECT_EQ(defNumber, 1);
defNumber = 0;
rc =
pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNumber);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(defNumber, 1);
rc =
pldm_bios_table_attr_entry_enum_decode_pv_num_check(nullptr, &pvNumber);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, nullptr);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
entry->attr_type = PLDM_BIOS_STRING;
rc = pldm_bios_table_attr_entry_enum_decode_pv_num_check(entry, &pvNumber);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc =
pldm_bios_table_attr_entry_enum_decode_def_num_check(entry, &defNumber);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc =
pldm_bios_table_attr_entry_enum_decode_pv_hdls_check(entry, nullptr, 0);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
TEST(AttrTable, StringEntryDecodeTest)
{
std::vector<uint8_t> stringEntry{
1, 0, /* attr handle */
1, /* attr type */
12, 0, /* attr name handle */
1, /* string type */
1, 0, /* minimum length of the string in bytes */
100, 0, /* maximum length of the string in bytes */
3, 0, /* length of default string in length */
'a', 'b', 'c' /* default string */
};
auto entry = reinterpret_cast<struct pldm_bios_attr_table_entry*>(
stringEntry.data());
uint16_t def_string_length =
pldm_bios_table_attr_entry_string_decode_def_string_length(entry);
EXPECT_EQ(def_string_length, 3);
def_string_length = 0;
auto rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
entry, &def_string_length);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(def_string_length, 3);
rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
entry, nullptr);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
nullptr, &def_string_length);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
entry->attr_type = PLDM_BIOS_INTEGER;
rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
entry, &def_string_length);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = pldm_bios_table_attr_entry_string_decode_def_string_length_check(
nullptr, &def_string_length);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
}
TEST(AttrTable, ItearatorTest)
{
std::vector<uint8_t> enumEntry{
0, 0, /* attr handle */
0, /* attr type */
1, 0, /* attr name handle */
2, /* number of possible value */
2, 0, /* possible value handle */
3, 0, /* possible value handle */
1, /* number of default value */
0 /* defaut value string handle index */
};
std::vector<uint8_t> stringEntry{
1, 0, /* attr handle */
1, /* attr type */
12, 0, /* attr name handle */
1, /* string type */
1, 0, /* minimum length of the string in bytes */
100, 0, /* maximum length of the string in bytes */
3, 0, /* length of default string in length */
'a', 'b', 'c' /* default string */
};
Table table;
buildTable(table, enumEntry, stringEntry, enumEntry);
auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
PLDM_BIOS_ATTR_TABLE);
auto entry = pldm_bios_table_iter_attr_entry_value(iter);
auto rc = std::memcmp(entry, enumEntry.data(), enumEntry.size());
EXPECT_EQ(rc, 0);
pldm_bios_table_iter_next(iter);
entry = pldm_bios_table_iter_attr_entry_value(iter);
rc = std::memcmp(entry, stringEntry.data(), stringEntry.size());
EXPECT_EQ(rc, 0);
pldm_bios_table_iter_next(iter);
entry = pldm_bios_table_iter_attr_entry_value(iter);
rc = std::memcmp(entry, enumEntry.data(), enumEntry.size());
EXPECT_EQ(rc, 0);
pldm_bios_table_iter_next(iter);
EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
pldm_bios_table_iter_free(iter);
}
TEST(AttrValTable, EnumEntryEncodeTest)
{
std::vector<uint8_t> enumEntry{
0, 0, /* attr handle */
0, /* attr type */
2, /* number of current value */
0, /* current value string handle index */
1, /* current value string handle index */
};
auto length = pldm_bios_table_attr_value_entry_encode_enum_length(2);
EXPECT_EQ(length, enumEntry.size());
std::vector<uint8_t> encodeEntry(length, 0);
uint8_t handles[] = {0, 1};
pldm_bios_table_attr_value_entry_encode_enum(
encodeEntry.data(), encodeEntry.size(), 0, 0, 2, handles);
EXPECT_EQ(encodeEntry, enumEntry);
EXPECT_DEATH(
pldm_bios_table_attr_value_entry_encode_enum(
encodeEntry.data(), encodeEntry.size() - 1, 0, 0, 2, handles),
"length <= entry_length");
auto rc = pldm_bios_table_attr_value_entry_encode_enum_check(
encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_ENUMERATION, 2,
handles);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(encodeEntry, enumEntry);
auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
enumEntry.data());
entry->attr_type = PLDM_BIOS_ENUMERATION_READ_ONLY;
rc = pldm_bios_table_attr_value_entry_encode_enum_check(
encodeEntry.data(), encodeEntry.size(), 0,
PLDM_BIOS_ENUMERATION_READ_ONLY, 2, handles);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(encodeEntry, enumEntry);
rc = pldm_bios_table_attr_value_entry_encode_enum_check(
encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 2,
handles);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = pldm_bios_table_attr_value_entry_encode_enum_check(
encodeEntry.data(), encodeEntry.size() - 1, 0, PLDM_BIOS_ENUMERATION, 2,
handles);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
}
TEST(AttrValTable, stringEntryEncodeTest)
{
std::vector<uint8_t> stringEntry{
0, 0, /* attr handle */
1, /* attr type */
3, 0, /* current string length */
'a', 'b', 'c', /* defaut value string handle index */
};
auto length = pldm_bios_table_attr_value_entry_encode_string_length(3);
EXPECT_EQ(length, stringEntry.size());
std::vector<uint8_t> encodeEntry(length, 0);
pldm_bios_table_attr_value_entry_encode_string(
encodeEntry.data(), encodeEntry.size(), 0, 1, 3, "abc");
EXPECT_EQ(encodeEntry, stringEntry);
EXPECT_DEATH(
pldm_bios_table_attr_value_entry_encode_string(
encodeEntry.data(), encodeEntry.size() - 1, 0, 1, 3, "abc"),
"length <= entry_length");
auto rc = pldm_bios_table_attr_value_entry_encode_string_check(
encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_STRING, 3, "abc");
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(encodeEntry, stringEntry);
auto entry = reinterpret_cast<struct pldm_bios_attr_val_table_entry*>(
stringEntry.data());
entry->attr_type = PLDM_BIOS_STRING_READ_ONLY;
rc = pldm_bios_table_attr_value_entry_encode_string_check(
encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_STRING_READ_ONLY,
3, "abc");
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(encodeEntry, stringEntry);
rc = pldm_bios_table_attr_value_entry_encode_string_check(
encodeEntry.data(), encodeEntry.size(), 0, PLDM_BIOS_PASSWORD, 3,
"abc");
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = pldm_bios_table_attr_value_entry_encode_string_check(
encodeEntry.data(), encodeEntry.size() - 1, 0, PLDM_BIOS_STRING, 3,
"abc");
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
}
TEST(StringTable, EntryEncodeTest)
{
std::vector<uint8_t> stringEntry{
0, 0, /* string handle*/
7, 0, /* string length */
'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
};
const char* str = "Allowed";
auto str_length = std::strlen(str);
auto encodeLength = pldm_bios_table_string_entry_encode_length(str_length);
EXPECT_EQ(encodeLength, stringEntry.size());
std::vector<uint8_t> encodeEntry(encodeLength, 0);
pldm_bios_table_string_entry_encode(encodeEntry.data(), encodeEntry.size(),
str, str_length);
// set string handle = 0
encodeEntry[0] = 0;
encodeEntry[1] = 0;
EXPECT_EQ(stringEntry, encodeEntry);
EXPECT_DEATH(pldm_bios_table_string_entry_encode(encodeEntry.data(),
encodeEntry.size() - 1,
str, str_length),
"length <= entry_length");
auto rc = pldm_bios_table_string_entry_encode_check(
encodeEntry.data(), encodeEntry.size() - 1, str, str_length);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
}
TEST(StringTable, EntryDecodeTest)
{
std::vector<uint8_t> stringEntry{
4, 0, /* string handle*/
7, 0, /* string length */
'A', 'l', 'l', 'o', 'w', 'e', 'd', /* string */
};
auto entry = reinterpret_cast<struct pldm_bios_string_table_entry*>(
stringEntry.data());
auto handle = pldm_bios_table_string_entry_decode_handle(entry);
EXPECT_EQ(handle, 4);
auto strLength = pldm_bios_table_string_entry_decode_string_length(entry);
EXPECT_EQ(strLength, 7);
std::vector<char> buffer(strLength + 1, 0);
auto decodedLength = pldm_bios_table_string_entry_decode_string(
entry, buffer.data(), buffer.size());
EXPECT_EQ(decodedLength, strLength);
EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
decodedLength =
pldm_bios_table_string_entry_decode_string(entry, buffer.data(), 2);
EXPECT_EQ(decodedLength, 2);
EXPECT_EQ(std::strcmp("Al", buffer.data()), 0);
auto rc = pldm_bios_table_string_entry_decode_string_check(
entry, buffer.data(), buffer.size());
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(std::strcmp("Allowed", buffer.data()), 0);
rc = pldm_bios_table_string_entry_decode_string_check(entry, buffer.data(),
buffer.size() - 1);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
}
TEST(StringTable, IteratorTest)
{
std::vector<uint8_t> stringHello{
0, 0, /* string handle*/
5, 0, /* string length */
'H', 'e', 'l', 'l', 'o', /* string */
};
std::vector<uint8_t> stringWorld{
1, 0, /* string handle*/
6, 0, /* string length */
'W', 'o', 'r', 'l', 'd', '!', /* string */
};
Table table;
buildTable(table, stringHello, stringWorld);
auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
PLDM_BIOS_STRING_TABLE);
auto entry = pldm_bios_table_iter_string_entry_value(iter);
auto rc = std::memcmp(entry, stringHello.data(), stringHello.size());
EXPECT_EQ(rc, 0);
pldm_bios_table_iter_next(iter);
entry = pldm_bios_table_iter_string_entry_value(iter);
rc = std::memcmp(entry, stringWorld.data(), stringWorld.size());
EXPECT_EQ(rc, 0);
pldm_bios_table_iter_next(iter);
EXPECT_TRUE(pldm_bios_table_iter_is_end(iter));
pldm_bios_table_iter_free(iter);
}
TEST(StringTable, FindTest)
{
std::vector<uint8_t> stringHello{
1, 0, /* string handle*/
5, 0, /* string length */
'H', 'e', 'l', 'l', 'o', /* string */
};
std::vector<uint8_t> stringWorld{
2, 0, /* string handle*/
6, 0, /* string length */
'W', 'o', 'r', 'l', 'd', '!', /* string */
};
std::vector<uint8_t> stringHi{
3, 0, /* string handle*/
2, 0, /* string length */
'H', 'i', /* string */
};
Table table;
buildTable(table, stringHello, stringWorld, stringHi);
auto entry = pldm_bios_table_string_find_by_string(table.data(),
table.size(), "World!");
EXPECT_NE(entry, nullptr);
auto handle = pldm_bios_table_string_entry_decode_handle(entry);
EXPECT_EQ(handle, 2);
entry = pldm_bios_table_string_find_by_string(table.data(), table.size(),
"Worl");
EXPECT_EQ(entry, nullptr);
entry =
pldm_bios_table_string_find_by_handle(table.data(), table.size(), 3);
EXPECT_NE(entry, nullptr);
auto str_length = pldm_bios_table_string_entry_decode_string_length(entry);
EXPECT_EQ(str_length, 2);
std::vector<char> strBuf(str_length + 1, 0);
auto rc = pldm_bios_table_string_entry_decode_string_check(
entry, strBuf.data(), strBuf.size());
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(std::strcmp("Hi", strBuf.data()), 0);
entry =
pldm_bios_table_string_find_by_handle(table.data(), table.size(), 4);
EXPECT_EQ(entry, nullptr);
}
TEST(Itearator, DeathTest)
{
Table table(256, 0);
/* first entry */
auto attr_entry =
reinterpret_cast<struct pldm_bios_attr_table_entry*>(table.data());
auto iter = pldm_bios_table_iter_create(table.data(), table.size(),
PLDM_BIOS_ATTR_TABLE);
attr_entry->attr_type = PLDM_BIOS_PASSWORD;
EXPECT_DEATH(pldm_bios_table_iter_next(iter), "attr_table_entry != NULL");
attr_entry->attr_type = PLDM_BIOS_INTEGER;
EXPECT_DEATH(pldm_bios_table_iter_next(iter), "attr_table_entry != NULL");
pldm_bios_table_iter_free(iter);
}