blob: 84adc15b092049f60d6ce2f67163bcc8e7c7025d [file] [log] [blame]
#include <cstring>
#include "libpldm/base.h"
#include "libpldm/firmware_update.h"
#include <gtest/gtest.h>
constexpr auto hdrSize = sizeof(pldm_msg_hdr);
TEST(DecodeDescriptors, goodPath3Descriptors)
{
// In the descriptor data there are 3 descriptor entries
// 1) IANA enterprise ID
constexpr std::array<uint8_t, PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH> iana{
0x0a, 0x0b, 0x0c, 0xd};
// 2) UUID
constexpr std::array<uint8_t, PLDM_FWUP_UUID_LENGTH> uuid{
0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18,
0xa0, 0x30, 0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b};
// 3) Vendor Defined
constexpr std::string_view vendorTitle{"OpenBMC"};
constexpr size_t vendorDescriptorLen = 2;
constexpr std::array<uint8_t, vendorDescriptorLen> vendorDescriptorData{
0x01, 0x02};
constexpr size_t vendorDefinedDescriptorLen =
sizeof(pldm_vendor_defined_descriptor_title_data()
.vendor_defined_descriptor_title_str_type) +
sizeof(pldm_vendor_defined_descriptor_title_data()
.vendor_defined_descriptor_title_str_len) +
vendorTitle.size() + vendorDescriptorData.size();
constexpr size_t descriptorsLength =
3 * (sizeof(pldm_descriptor_tlv().descriptor_type) +
sizeof(pldm_descriptor_tlv().descriptor_length)) +
iana.size() + uuid.size() + vendorDefinedDescriptorLen;
constexpr std::array<uint8_t, descriptorsLength> descriptors{
0x01, 0x00, 0x04, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x02, 0x00, 0x10,
0x00, 0x12, 0x44, 0xd2, 0x64, 0x8d, 0x7d, 0x47, 0x18, 0xa0, 0x30,
0xfc, 0x8a, 0x56, 0x58, 0x7d, 0x5b, 0xFF, 0xFF, 0x0B, 0x00, 0x01,
0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x01, 0x02};
size_t descriptorCount = 1;
size_t descriptorsRemainingLength = descriptorsLength;
int rc = 0;
while (descriptorsRemainingLength && (descriptorCount <= 3))
{
uint16_t descriptorType = 0;
uint16_t descriptorLen = 0;
variable_field descriptorData{};
rc = decode_descriptor_type_length_value(
descriptors.data() + descriptorsLength - descriptorsRemainingLength,
descriptorsRemainingLength, &descriptorType, &descriptorData);
EXPECT_EQ(rc, PLDM_SUCCESS);
if (descriptorCount == 1)
{
EXPECT_EQ(descriptorType, PLDM_FWUP_IANA_ENTERPRISE_ID);
EXPECT_EQ(descriptorData.length,
PLDM_FWUP_IANA_ENTERPRISE_ID_LENGTH);
EXPECT_EQ(true,
std::equal(descriptorData.ptr,
descriptorData.ptr + descriptorData.length,
iana.begin(), iana.end()));
}
else if (descriptorCount == 2)
{
EXPECT_EQ(descriptorType, PLDM_FWUP_UUID);
EXPECT_EQ(descriptorData.length, PLDM_FWUP_UUID_LENGTH);
EXPECT_EQ(true,
std::equal(descriptorData.ptr,
descriptorData.ptr + descriptorData.length,
uuid.begin(), uuid.end()));
}
else if (descriptorCount == 3)
{
EXPECT_EQ(descriptorType, PLDM_FWUP_VENDOR_DEFINED);
EXPECT_EQ(descriptorData.length, vendorDefinedDescriptorLen);
uint8_t descriptorTitleStrType = 0;
variable_field descriptorTitleStr{};
variable_field vendorDefinedDescriptorData{};
rc = decode_vendor_defined_descriptor_value(
descriptorData.ptr, descriptorData.length,
&descriptorTitleStrType, &descriptorTitleStr,
&vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(descriptorTitleStrType, PLDM_STR_TYPE_ASCII);
EXPECT_EQ(descriptorTitleStr.length, vendorTitle.size());
std::string vendorTitleStr(
reinterpret_cast<const char*>(descriptorTitleStr.ptr),
descriptorTitleStr.length);
EXPECT_EQ(vendorTitleStr, vendorTitle);
EXPECT_EQ(vendorDefinedDescriptorData.length,
vendorDescriptorData.size());
EXPECT_EQ(true, std::equal(vendorDefinedDescriptorData.ptr,
vendorDefinedDescriptorData.ptr +
vendorDefinedDescriptorData.length,
vendorDescriptorData.begin(),
vendorDescriptorData.end()));
}
descriptorsRemainingLength -= sizeof(descriptorType) +
sizeof(descriptorLen) +
descriptorData.length;
descriptorCount++;
}
}
TEST(DecodeDescriptors, errorPathDecodeDescriptorTLV)
{
int rc = 0;
// IANA Enterprise ID descriptor length incorrect
constexpr std::array<uint8_t, 7> invalidIANADescriptor1{
0x01, 0x00, 0x03, 0x00, 0x0a, 0x0b, 0x0c};
uint16_t descriptorType = 0;
variable_field descriptorData{};
rc = decode_descriptor_type_length_value(nullptr,
invalidIANADescriptor1.size(),
&descriptorType, &descriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(),
invalidIANADescriptor1.size(),
nullptr, &descriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(),
invalidIANADescriptor1.size(),
&descriptorType, nullptr);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = decode_descriptor_type_length_value(
invalidIANADescriptor1.data(), PLDM_FWUP_DEVICE_DESCRIPTOR_MIN_LEN - 1,
&descriptorType, &descriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
rc = decode_descriptor_type_length_value(invalidIANADescriptor1.data(),
invalidIANADescriptor1.size(),
&descriptorType, &descriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
// IANA Enterprise ID descriptor data less than length
std::array<uint8_t, 7> invalidIANADescriptor2{0x01, 0x00, 0x04, 0x00,
0x0a, 0x0b, 0x0c};
rc = decode_descriptor_type_length_value(invalidIANADescriptor2.data(),
invalidIANADescriptor2.size(),
&descriptorType, &descriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
}
TEST(DecodeDescriptors, errorPathVendorDefinedDescriptor)
{
int rc = 0;
// VendorDefinedDescriptorTitleStringType is invalid
constexpr std::array<uint8_t, 9> invalidVendorDescriptor1{
0x06, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43};
uint8_t descriptorStringType = 0;
variable_field descriptorTitleStr{};
variable_field vendorDefinedDescriptorData{};
rc = decode_vendor_defined_descriptor_value(
nullptr, invalidVendorDescriptor1.size(), &descriptorStringType,
&descriptorTitleStr, &vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = decode_vendor_defined_descriptor_value(
invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
&descriptorStringType, &descriptorTitleStr,
&vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = decode_vendor_defined_descriptor_value(
invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
nullptr, &descriptorTitleStr, &vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = decode_vendor_defined_descriptor_value(
invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
&descriptorStringType, nullptr, &vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = decode_vendor_defined_descriptor_value(
invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
&descriptorStringType, &descriptorTitleStr, nullptr);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
rc = decode_vendor_defined_descriptor_value(
invalidVendorDescriptor1.data(),
sizeof(pldm_vendor_defined_descriptor_title_data) - 1,
&descriptorStringType, &descriptorTitleStr,
&vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
rc = decode_vendor_defined_descriptor_value(
invalidVendorDescriptor1.data(), invalidVendorDescriptor1.size(),
&descriptorStringType, &descriptorTitleStr,
&vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
// VendorDefinedDescriptorTitleStringLength is 0
std::array<uint8_t, 9> invalidVendorDescriptor2{
0x01, 0x00, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43};
rc = decode_vendor_defined_descriptor_value(
invalidVendorDescriptor2.data(), invalidVendorDescriptor2.size(),
&descriptorStringType, &descriptorTitleStr,
&vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
// VendorDefinedDescriptorData not present in the data
std::array<uint8_t, 9> invalidVendorDescriptor3{
0x01, 0x07, 0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43};
rc = decode_vendor_defined_descriptor_value(
invalidVendorDescriptor3.data(), invalidVendorDescriptor3.size(),
&descriptorStringType, &descriptorTitleStr,
&vendorDefinedDescriptorData);
EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
}
TEST(QueryDeviceIdentifiers, goodPathEncodeRequest)
{
std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
uint8_t instanceId = 0x01;
auto rc = encode_query_device_identifiers_req(
instanceId, PLDM_QUERY_DEVICE_IDENTIFIERS_REQ_BYTES, requestPtr);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
EXPECT_EQ(requestPtr->hdr.instance_id, instanceId);
EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP);
EXPECT_EQ(requestPtr->hdr.command, PLDM_QUERY_DEVICE_IDENTIFIERS);
}
TEST(QueryDeviceIdentifiers, goodPathDecodeResponse)
{
// descriptorDataLen is not fixed here taking it as 6
constexpr uint8_t descriptorDataLen = 6;
std::array<uint8_t, hdrSize +
sizeof(struct pldm_query_device_identifiers_resp) +
descriptorDataLen>
responseMsg{};
auto inResp = reinterpret_cast<struct pldm_query_device_identifiers_resp*>(
responseMsg.data() + hdrSize);
inResp->completion_code = PLDM_SUCCESS;
inResp->device_identifiers_len = htole32(descriptorDataLen);
inResp->descriptor_count = 1;
// filling descriptor data
std::fill_n(responseMsg.data() + hdrSize +
sizeof(struct pldm_query_device_identifiers_resp),
descriptorDataLen, 0xFF);
auto response = reinterpret_cast<pldm_msg*>(responseMsg.data());
uint8_t completionCode = PLDM_SUCCESS;
uint32_t deviceIdentifiersLen = 0;
uint8_t descriptorCount = 0;
uint8_t* outDescriptorData = nullptr;
auto rc = decode_query_device_identifiers_resp(
response, responseMsg.size() - hdrSize, &completionCode,
&deviceIdentifiersLen, &descriptorCount, &outDescriptorData);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(completionCode, PLDM_SUCCESS);
EXPECT_EQ(deviceIdentifiersLen, inResp->device_identifiers_len);
EXPECT_EQ(descriptorCount, inResp->descriptor_count);
EXPECT_EQ(true,
std::equal(outDescriptorData,
outDescriptorData + deviceIdentifiersLen,
responseMsg.begin() + hdrSize +
sizeof(struct pldm_query_device_identifiers_resp),
responseMsg.end()));
}
TEST(GetFirmwareParameters, goodPathEncodeRequest)
{
std::array<uint8_t, sizeof(pldm_msg_hdr)> requestMsg{};
auto requestPtr = reinterpret_cast<pldm_msg*>(requestMsg.data());
uint8_t instanceId = 0x01;
auto rc = encode_get_firmware_parameters_req(
instanceId, PLDM_GET_FIRMWARE_PARAMETERS_REQ_BYTES, requestPtr);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(requestPtr->hdr.request, PLDM_REQUEST);
EXPECT_EQ(requestPtr->hdr.instance_id, instanceId);
EXPECT_EQ(requestPtr->hdr.type, PLDM_FWUP);
EXPECT_EQ(requestPtr->hdr.command, PLDM_GET_FIRMWARE_PARAMETERS);
}
TEST(GetFirmwareParameters, goodPathDecodeResponseComponentSetInfo)
{
// Random value for capabilities during update
constexpr uint32_t capabilitiesDuringUpdate = 0xBADBEEFE;
// Random value for component count
constexpr uint16_t componentCount = 0xAABB;
// ActiveCompImageSetVerStrLen is not fixed here taking it as 8
constexpr uint8_t activeCompImageSetVerStrLen = 8;
// PendingCompImageSetVerStrLen is not fixed here taking it as 8
constexpr uint8_t pendingCompImageSetVerStrLen = 8;
constexpr size_t payloadLen =
sizeof(struct pldm_get_firmware_parameters_resp) +
activeCompImageSetVerStrLen + pendingCompImageSetVerStrLen;
std::array<uint8_t, hdrSize + payloadLen> response{};
auto inResp = reinterpret_cast<struct pldm_get_firmware_parameters_resp*>(
response.data() + hdrSize);
inResp->completion_code = PLDM_SUCCESS;
inResp->capabilities_during_update.value =
htole32(capabilitiesDuringUpdate);
inResp->comp_count = htole16(componentCount);
inResp->active_comp_image_set_ver_str_type = 1;
inResp->active_comp_image_set_ver_str_len = activeCompImageSetVerStrLen;
inResp->pending_comp_image_set_ver_str_type = 1;
inResp->pending_comp_image_set_ver_str_len = pendingCompImageSetVerStrLen;
constexpr size_t activeCompImageSetVerStrPos =
hdrSize + sizeof(struct pldm_get_firmware_parameters_resp);
// filling default values for ActiveComponentImageSetVersionString
std::fill_n(response.data() + activeCompImageSetVerStrPos,
activeCompImageSetVerStrLen, 0xFF);
constexpr size_t pendingCompImageSetVerStrPos =
hdrSize + sizeof(struct pldm_get_firmware_parameters_resp) +
activeCompImageSetVerStrLen;
// filling default values for ActiveComponentImageSetVersionString
std::fill_n(response.data() + pendingCompImageSetVerStrPos,
pendingCompImageSetVerStrLen, 0xFF);
auto responseMsg = reinterpret_cast<pldm_msg*>(response.data());
struct pldm_get_firmware_parameters_resp outResp;
struct variable_field outActiveCompImageSetVerStr;
struct variable_field outPendingCompImageSetVerStr;
auto rc = decode_get_firmware_parameters_resp_comp_set_info(
responseMsg, payloadLen, &outResp, &outActiveCompImageSetVerStr,
&outPendingCompImageSetVerStr);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(outResp.completion_code, PLDM_SUCCESS);
EXPECT_EQ(outResp.capabilities_during_update.value,
capabilitiesDuringUpdate);
EXPECT_EQ(outResp.comp_count, componentCount);
EXPECT_EQ(inResp->active_comp_image_set_ver_str_type,
outResp.active_comp_image_set_ver_str_type);
EXPECT_EQ(inResp->active_comp_image_set_ver_str_len,
outResp.active_comp_image_set_ver_str_len);
EXPECT_EQ(0, memcmp(outActiveCompImageSetVerStr.ptr,
response.data() + activeCompImageSetVerStrPos,
outActiveCompImageSetVerStr.length));
EXPECT_EQ(inResp->pending_comp_image_set_ver_str_type,
outResp.pending_comp_image_set_ver_str_type);
EXPECT_EQ(inResp->pending_comp_image_set_ver_str_len,
outResp.pending_comp_image_set_ver_str_len);
EXPECT_EQ(0, memcmp(outPendingCompImageSetVerStr.ptr,
response.data() + pendingCompImageSetVerStrPos,
outPendingCompImageSetVerStr.length));
}
TEST(GetFirmwareParameters, goodPathDecodeComponentParameterEntry)
{
// Random value for component classification
constexpr uint16_t compClassification = 0x0A0B;
// Random value for component classification
constexpr uint16_t compIdentifier = 0x0C0D;
// Random value for component classification
constexpr uint32_t timestamp = 0X12345678;
// Random value for component activation methods
constexpr uint16_t compActivationMethods = 0xBBDD;
// Random value for capabilities during update
constexpr uint32_t capabilitiesDuringUpdate = 0xBADBEEFE;
// ActiveCompImageSetVerStrLen is not fixed here taking it as 8
constexpr uint8_t activeCompVerStrLen = 8;
// PendingCompImageSetVerStrLen is not fixed here taking it as 8
constexpr uint8_t pendingCompVerStrLen = 8;
constexpr size_t entryLength =
sizeof(struct pldm_component_parameter_entry) + activeCompVerStrLen +
pendingCompVerStrLen;
std::array<uint8_t, entryLength> entry{};
auto inEntry =
reinterpret_cast<struct pldm_component_parameter_entry*>(entry.data());
inEntry->comp_classification = htole16(compClassification);
inEntry->comp_identifier = htole16(compIdentifier);
inEntry->comp_classification_index = 0x0F;
inEntry->active_comp_comparison_stamp = htole32(timestamp);
inEntry->active_comp_ver_str_type = 1;
inEntry->active_comp_ver_str_len = activeCompVerStrLen;
std::fill_n(inEntry->active_comp_release_date,
sizeof(inEntry->active_comp_release_date), 0xFF);
inEntry->pending_comp_comparison_stamp = htole32(timestamp);
inEntry->pending_comp_ver_str_type = 1;
inEntry->pending_comp_ver_str_len = pendingCompVerStrLen;
std::fill_n(inEntry->pending_comp_release_date,
sizeof(inEntry->pending_comp_release_date), 0xFF);
inEntry->comp_activation_methods.value = htole16(compActivationMethods);
inEntry->capabilities_during_update.value =
htole32(capabilitiesDuringUpdate);
constexpr auto activeCompVerStrPos =
sizeof(struct pldm_component_parameter_entry);
std::fill_n(entry.data() + activeCompVerStrPos, activeCompVerStrLen, 0xAA);
constexpr auto pendingCompVerStrPos =
activeCompVerStrPos + activeCompVerStrLen;
std::fill_n(entry.data() + pendingCompVerStrPos, pendingCompVerStrLen,
0xBB);
struct pldm_component_parameter_entry outEntry;
struct variable_field outActiveCompVerStr;
struct variable_field outPendingCompVerStr;
auto rc = decode_get_firmware_parameters_resp_comp_entry(
entry.data(), entryLength, &outEntry, &outActiveCompVerStr,
&outPendingCompVerStr);
EXPECT_EQ(rc, PLDM_SUCCESS);
EXPECT_EQ(outEntry.comp_classification, compClassification);
EXPECT_EQ(outEntry.comp_identifier, compIdentifier);
EXPECT_EQ(inEntry->comp_classification_index,
outEntry.comp_classification_index);
EXPECT_EQ(outEntry.active_comp_comparison_stamp, timestamp);
EXPECT_EQ(inEntry->active_comp_ver_str_type,
outEntry.active_comp_ver_str_type);
EXPECT_EQ(inEntry->active_comp_ver_str_len,
outEntry.active_comp_ver_str_len);
EXPECT_EQ(0, memcmp(inEntry->active_comp_release_date,
outEntry.active_comp_release_date,
sizeof(inEntry->active_comp_release_date)));
EXPECT_EQ(outEntry.pending_comp_comparison_stamp, timestamp);
EXPECT_EQ(inEntry->pending_comp_ver_str_type,
outEntry.pending_comp_ver_str_type);
EXPECT_EQ(inEntry->pending_comp_ver_str_len,
outEntry.pending_comp_ver_str_len);
EXPECT_EQ(0, memcmp(inEntry->pending_comp_release_date,
outEntry.pending_comp_release_date,
sizeof(inEntry->pending_comp_release_date)));
EXPECT_EQ(outEntry.comp_activation_methods.value, compActivationMethods);
EXPECT_EQ(outEntry.capabilities_during_update.value,
capabilitiesDuringUpdate);
EXPECT_EQ(0, memcmp(outActiveCompVerStr.ptr,
entry.data() + activeCompVerStrPos,
outActiveCompVerStr.length));
EXPECT_EQ(0, memcmp(outPendingCompVerStr.ptr,
entry.data() + pendingCompVerStrPos,
outPendingCompVerStr.length));
}