Enabled PFR image validation support for PFR ptfms.
Added support for validating the PFR image in ipmi firmware write
data command.
Tested:
Tested firmware update utility via KCS interface
Signed-off-by: Rajashekar Gade Reddy <raja.sekhar.reddy.gade@linux.intel.com>
Change-Id: I16d66af593dd2ab03759281d4cef8ba238c1d85a
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 546f726..218c5c6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -104,3 +104,8 @@
target_link_libraries (zinteloemcmds ${OPENSSL_CRYPTO_LIBRARY})
install (TARGETS zinteloemcmds DESTINATION lib/ipmid-providers)
+option (INTEL_PFR_ENABLED "Intel PFR Enabled" OFF)
+target_compile_definitions (
+ zinteloemcmds PRIVATE
+ $<$<BOOL:${INTEL_PFR_ENABLED}>: -DINTEL_PFR_ENABLED>
+)
diff --git a/src/firmware-update.cpp b/src/firmware-update.cpp
index 99402e8..4fdee8b 100644
--- a/src/firmware-update.cpp
+++ b/src/firmware-update.cpp
@@ -26,6 +26,13 @@
#include <sdbusplus/timer.hpp>
#include <sstream>
+#ifdef INTEL_PFR_ENABLED
+uint32_t imgLength = 0;
+uint32_t imgType = 0;
+bool block0Mapped = false;
+static constexpr uint32_t perBlock0MagicNum = 0xB6EAFD19;
+#endif
+
static constexpr const char *secondaryFitImageStartAddr = "22480000";
static uint8_t getActiveBootImage(void);
static void register_netfn_firmware_functions() __attribute__((constructor));
@@ -846,6 +853,11 @@
{
xfer_hash_check->clear();
}
+#ifdef INTEL_PFR_ENABLED
+ imgLength = 0;
+ imgType = 0;
+ block0Mapped = false;
+#endif
if (DEBUG)
std::cerr << "transfer start\n";
}
@@ -1564,7 +1576,9 @@
{
return IPMI_CC_UNSPECIFIED_ERROR;
}
- if (out.tellp() > FIRMWARE_BUFFER_MAX_SIZE)
+
+ uint64_t fileDataLen = out.tellp();
+ if (fileDataLen > FIRMWARE_BUFFER_MAX_SIZE)
{
return IPMI_CC_INVALID_FIELD_REQUEST;
}
@@ -1576,7 +1590,44 @@
xfer_hash_check->hash({data, data + bytes_in});
}
- // Status code.
+#ifdef INTEL_PFR_ENABLED
+ /* PFR image block 0 - As defined in HAS */
+ struct PFRImageBlock0
+ {
+ uint32_t tag;
+ uint32_t pcLength;
+ uint32_t pcType;
+ uint32_t reserved1;
+ uint8_t hash256[32];
+ uint8_t hash384[48];
+ uint8_t reserved2[32];
+ } __attribute__((packed));
+
+ /* Get the PFR block 0 data and read the uploaded image
+ * information( Image type, length etc) */
+ if ((fileDataLen >= sizeof(PFRImageBlock0)) && (!block0Mapped))
+ {
+ struct PFRImageBlock0 block0Data = {0};
+
+ std::ifstream inFile(FIRMWARE_BUFFER_FILE,
+ std::ios::binary | std::ios::in);
+ inFile.read(reinterpret_cast<char *>(&block0Data), sizeof(block0Data));
+ inFile.close();
+
+ uint32_t magicNum = block0Data.tag;
+
+ /* Validate the magic number */
+ if (magicNum != perBlock0MagicNum)
+ {
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+ // Note:imgLength, imgType and block0Mapped are in global scope, as
+ // these are used in cascaded updates.
+ imgLength = block0Data.pcLength;
+ imgType = block0Data.pcType;
+ block0Mapped = true;
+ }
+#endif // end of INTEL_PFR_ENABLED
return IPMI_CC_OK;
}