libpldm: Add API to decode package header info

This patch provides API to decode the firmware update package header
information and also do basic validation.

The API works with DSP0267_1.1.0, DSP0267_1.0.1 and DSP0267_1.0.0.

Tested: Unit tests passed

Signed-off-by: Tom Joseph <rushtotom@gmail.com>
Change-Id: I208a219cd4b9c9b9869eb3e286259b2f51206487
diff --git a/libpldm/tests/libpldm_firmware_update_test.cpp b/libpldm/tests/libpldm_firmware_update_test.cpp
index f87fd5b..8f8775c 100644
--- a/libpldm/tests/libpldm_firmware_update_test.cpp
+++ b/libpldm/tests/libpldm_firmware_update_test.cpp
@@ -8,6 +8,142 @@
 

 constexpr auto hdrSize = sizeof(pldm_msg_hdr);

 

+TEST(DecodePackageHeaderInfo, goodPath)

+{

+    // Package header identifier for Version 1.0.x

+    constexpr std::array<uint8_t, PLDM_FWUP_UUID_LENGTH> uuid{

+        0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43,

+        0x98, 0x00, 0xa0, 0x2F, 0x05, 0x9a, 0xca, 0x02};

+    // Package header version for DSP0267 version 1.0.x

+    constexpr uint8_t pkgHeaderFormatRevision = 0x01;

+    // Random PackageHeaderSize

+    constexpr uint16_t pkgHeaderSize = 303;

+    // PackageReleaseDateTime - "25/12/2021 00:00:00"

+    std::array<uint8_t, PLDM_TIMESTAMP104_SIZE> timestamp104{

+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

+        0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00};

+    constexpr uint16_t componentBitmapBitLength = 8;

+    // PackageVersionString

+    constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};

+    constexpr size_t packagerHeaderSize =

+        sizeof(pldm_package_header_information) + packageVersionStr.size();

+

+    constexpr std::array<uint8_t, packagerHeaderSize> packagerHeaderInfo{

+        0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00, 0xa0, 0x2F,

+        0x05, 0x9a, 0xca, 0x02, 0x01, 0x2f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,

+        0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5, 0x07, 0x00, 0x08, 0x00, 0x01, 0x0b,

+        0x4f, 0x70, 0x65, 0x6e, 0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};

+    pldm_package_header_information pkgHeader{};

+    variable_field packageVersion{};

+

+    auto rc = decode_pldm_package_header_info(packagerHeaderInfo.data(),

+                                              packagerHeaderInfo.size(),

+                                              &pkgHeader, &packageVersion);

+

+    EXPECT_EQ(rc, PLDM_SUCCESS);

+    EXPECT_EQ(true,

+              std::equal(pkgHeader.uuid, pkgHeader.uuid + PLDM_FWUP_UUID_LENGTH,

+                         uuid.begin(), uuid.end()));

+    EXPECT_EQ(pkgHeader.package_header_format_version, pkgHeaderFormatRevision);

+    EXPECT_EQ(pkgHeader.package_header_size, pkgHeaderSize);

+    EXPECT_EQ(true, std::equal(pkgHeader.timestamp104,

+                               pkgHeader.timestamp104 + PLDM_TIMESTAMP104_SIZE,

+                               timestamp104.begin(), timestamp104.end()));

+    EXPECT_EQ(pkgHeader.component_bitmap_bit_length, componentBitmapBitLength);

+    EXPECT_EQ(pkgHeader.package_version_string_type, PLDM_STR_TYPE_ASCII);

+    EXPECT_EQ(pkgHeader.package_version_string_length,

+              packageVersionStr.size());

+    std::string packageVersionString(

+        reinterpret_cast<const char*>(packageVersion.ptr),

+        packageVersion.length);

+    EXPECT_EQ(packageVersionString, packageVersionStr);

+}

+

+TEST(DecodePackageHeaderInfo, errorPaths)

+{

+    int rc = 0;

+    constexpr std::string_view packageVersionStr{"OpenBMCv1.0"};

+    constexpr size_t packagerHeaderSize =

+        sizeof(pldm_package_header_information) + packageVersionStr.size();

+

+    // Invalid Package Version String Type - 0x06

+    constexpr std::array<uint8_t, packagerHeaderSize>

+        invalidPackagerHeaderInfo1{

+            0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00,

+            0xa0, 0x2F, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00,

+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5,

+            0x07, 0x00, 0x08, 0x00, 0x06, 0x0b, 0x4f, 0x70, 0x65, 0x6e,

+            0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};

+

+    pldm_package_header_information packageHeader{};

+    variable_field packageVersion{};

+

+    rc = decode_pldm_package_header_info(nullptr,

+                                         invalidPackagerHeaderInfo1.size(),

+                                         &packageHeader, &packageVersion);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo1.data(),

+                                         invalidPackagerHeaderInfo1.size(),

+                                         nullptr, &packageVersion);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo1.data(),

+                                         invalidPackagerHeaderInfo1.size(),

+                                         &packageHeader, nullptr);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    rc = decode_pldm_package_header_info(

+        invalidPackagerHeaderInfo1.data(),

+        sizeof(pldm_package_header_information) - 1, &packageHeader,

+        &packageVersion);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);

+

+    rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo1.data(),

+                                         invalidPackagerHeaderInfo1.size(),

+                                         &packageHeader, &packageVersion);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    // Invalid Package Version String Length - 0x00

+    constexpr std::array<uint8_t, packagerHeaderSize>

+        invalidPackagerHeaderInfo2{

+            0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00,

+            0xa0, 0x2F, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00,

+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5,

+            0x07, 0x00, 0x08, 0x00, 0x01, 0x00, 0x4f, 0x70, 0x65, 0x6e,

+            0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};

+    rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo2.data(),

+                                         invalidPackagerHeaderInfo2.size(),

+                                         &packageHeader, &packageVersion);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+

+    // Package version string length less than in the header information

+    constexpr std::array<uint8_t, packagerHeaderSize - 1>

+        invalidPackagerHeaderInfo3{

+            0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00,

+            0xa0, 0x2F, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00,

+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5,

+            0x07, 0x00, 0x08, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e,

+            0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e};

+    rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo3.data(),

+                                         invalidPackagerHeaderInfo3.size(),

+                                         &packageHeader, &packageVersion);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);

+

+    // ComponentBitmapBitLength not a multiple of 8

+    constexpr std::array<uint8_t, packagerHeaderSize>

+        invalidPackagerHeaderInfo4{

+            0xf0, 0x18, 0x87, 0x8c, 0xcb, 0x7d, 0x49, 0x43, 0x98, 0x00,

+            0xa0, 0x2F, 0x05, 0x9a, 0xca, 0x02, 0x02, 0x2f, 0x01, 0x00,

+            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x0c, 0xe5,

+            0x07, 0x00, 0x09, 0x00, 0x01, 0x0b, 0x4f, 0x70, 0x65, 0x6e,

+            0x42, 0x4d, 0x43, 0x76, 0x31, 0x2e, 0x30};

+    rc = decode_pldm_package_header_info(invalidPackagerHeaderInfo4.data(),

+                                         invalidPackagerHeaderInfo4.size(),

+                                         &packageHeader, &packageVersion);

+    EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);

+}

+

 TEST(DecodeDescriptors, goodPath3Descriptors)

 {

     // In the descriptor data there are 3 descriptor entries