psutils: Enhance PSU Update retry logic

- Update retry logic to align with IBM chart specifications.
- Add firmware file existence check before starting PSU update process.
- Switched log to lg2 in the updater for consistency.
- Fixed device intermittent issue during binding device.
- Modified the update flow to proceed even if the device driver is not
  available in sysfs.

These changes improve the robustness of the PSU update process and
enhance logging for better debug isolation.

Test:
  - Verified the updater does not start if the firmware file is missing.
  - Checked some of the logs correctly reflect the changes using lg2
  - Confirmed the PSU binds every time after FW update.
  - Test PSU update process continue when the device driver not
    available in sysfs.

Change-Id: Iaff5eaf9b9f3ee02d109cf3218f9b0614fa2bd92
Signed-off-by: Faisal Awada <faisal@us.ibm.com>
diff --git a/tools/power-utils/aei_updater.cpp b/tools/power-utils/aei_updater.cpp
index ffe2d1d..27da440 100644
--- a/tools/power-utils/aei_updater.cpp
+++ b/tools/power-utils/aei_updater.cpp
@@ -76,15 +76,26 @@
     {
         throw std::runtime_error("I2C interface error");
     }
+    if (!getFirmwarePath() || !isFirmwareFileValid())
+    {
+        return 1;                  // No firmware file abort download
+    }
     bool downloadFwFailed = false; // Download Firmware status
     int retryProcessTwo(0);
     int retryProcessOne(0);
+    int serviceableEvent(0);
     while ((retryProcessTwo < MAX_RETRIES) && (retryProcessOne < MAX_RETRIES))
     {
         retryProcessTwo++;
         // Write AEI PSU ISP key
         if (!writeIspKey())
         {
+            serviceableEvent++;
+            if (serviceableEvent == MAX_RETRIES)
+            {
+                createServiceableError(
+                    "createServiceableError: ISP key failed");
+            }
             lg2::error("Failed to set ISP Key");
             downloadFwFailed = true; // Download Firmware status
             continue;
@@ -117,6 +128,13 @@
                 }
                 else
                 {
+                    if (retryProcessOne == MAX_RETRIES)
+                    {
+                        // no more retries report serviceable error
+                        createServiceableError(
+                            "serviceableError: Download firmware failed");
+                        ispReboot(); // Try to set PSU to normal mode
+                    }
                     downloadFwFailed = true;
                     continue;
                 }
@@ -201,6 +219,7 @@
                        e);
         }
     }
+    createServiceableError("createServiceableError: ISP Status failed");
     lg2::error("Failed to set ISP Mode");
     return false; // Failed to set ISP Mode after retries
 }
@@ -246,34 +265,34 @@
                        "ERROR", e);
         }
     }
+    createServiceableError("createServiceableError: Failed to reset ISP");
     lg2::error("Failed to reset ISP Status");
     ispReboot();
     return false;
 }
 
-std::string AeiUpdater::getFirmwarePath()
+bool AeiUpdater::getFirmwarePath()
 {
-    const std::string fspath =
-        updater::internal::getFWFilenamePath(getImageDir());
+    fspath = updater::internal::getFWFilenamePath(getImageDir());
     if (fspath.empty())
     {
         lg2::error("Firmware file path not found");
-    }
-    return fspath;
-}
-
-bool AeiUpdater::isFirmwareFileValid(const std::string& fspath)
-{
-    if (!updater::internal::validateFWFile(fspath))
-    {
-        lg2::error("Firmware validation failed");
         return false;
     }
     return true;
 }
 
-std::unique_ptr<std::ifstream> AeiUpdater::openFirmwareFile(
-    const std::string& fspath)
+bool AeiUpdater::isFirmwareFileValid()
+{
+    if (!updater::internal::validateFWFile(fspath))
+    {
+        lg2::error("Firmware validation failed, fspath={PATH}", "PATH", fspath);
+        return false;
+    }
+    return true;
+}
+
+std::unique_ptr<std::ifstream> AeiUpdater::openFirmwareFile()
 {
     auto inputFile = updater::internal::openFirmwareFile(fspath);
     if (!inputFile)
@@ -313,22 +332,8 @@
 
 bool AeiUpdater::downloadPsuFirmware()
 {
-    // Get firmware path
-    const std::string fspath = getFirmwarePath();
-    if (fspath.empty())
-    {
-        lg2::error("Unable to find path");
-        return false;
-    }
-    // Validate firmware file
-    if (!isFirmwareFileValid(fspath))
-    {
-        lg2::error("Invalid file path");
-        return false;
-    }
-
     // Open firmware file
-    auto inputFile = openFirmwareFile(fspath);
+    auto inputFile = openFirmwareFile();
     if (!inputFile)
     {
         lg2::error("Unable to open firmware file {FILE}", "FILE", fspath);
@@ -386,7 +391,13 @@
         try
         {
             performI2cWriteRead(regAddr, readReplySize, readData, delayTime);
-            if ((readData[STATUS_CML_INDEX] == 0) &&
+            if ((readData[STATUS_CML_INDEX] == 0 ||
+                 // The first firmware data packet sent to the PSU have a
+                 // response of 0x80 which indicates firmware update in
+                 // progress. If retry to send the first packet again reply will
+                 // be 0.
+                 (readData[STATUS_CML_INDEX] == 0x80 &&
+                  delayTime == MEM_WRITE_DELAY)) &&
                 (readReplySize == expectedReadSize) &&
                 !std::equal(readData, readData + 4, byteSwappedIndex.begin()))
             {
@@ -395,7 +406,15 @@
             }
             else
             {
-                lg2::error("I2C write/read block failed");
+                uint32_t littleEndianValue =
+                    *reinterpret_cast<uint32_t*>(readData);
+                uint32_t bigEndianValue =
+                    ((littleEndianValue & 0x000000FF) << 24) |
+                    ((littleEndianValue & 0x0000FF00) << 8) |
+                    ((littleEndianValue & 0x00FF0000) >> 8) |
+                    ((littleEndianValue & 0xFF000000) >> 24);
+                lg2::error("Write/read block {NUM} failed", "NUM",
+                           bigEndianValue);
             }
         }
         catch (const std::exception& e)