psutils: Add necessary firmware update functions

doUpdate: Adds the main logic for orchestrating the PSU firmware update
process, including ISP setup, firmware download, and verification.

performI2cWriteReadWithRetries: Introduces functionality to perform I2C
write-read operations with configurable retries, and error handling for
robustness.

performI2cReadWrite: Provides the implementation for direct I2C
write-read operations with a customizable delay to ensure timing
requirements are met.

downloadPsuFirmware: Implements the functionality to read and process
PSU firmware in blocks, ensuring data integrity during transfer.

verifyDownloadFwStatus: Adds a mechanism to validate the success of
firmware downloads by checking the PSU's checksum status register.

getClassInstance: Add logic to dynamically instantiate updater class
based on PSU model.

Test:
 Placed latest firmware and MANIFEST files in "/usr/share/obmc/51E9"
 then retrieved the current PSU FW level. Ran "psutils" on the command
 line as follow:
 /usr/bin/psutils --update
  /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
  /usr/share/obmc/51E9

 Retrieved the FW level and verified the PSU FW was updated as
 expected.

    Signed-off-by: Faisal Awada <faisal@us.ibm.com>
Change-Id: I65d0c015eab0322110e85b954a38590332aaa67a
Signed-off-by: Faisal Awada <faisal@us.ibm.com>
diff --git a/tools/power-utils/utils.cpp b/tools/power-utils/utils.cpp
index e70004d..9517680 100644
--- a/tools/power-utils/utils.cpp
+++ b/tools/power-utils/utils.cpp
@@ -176,6 +176,10 @@
 
 std::string getDeviceName(std::string devPath)
 {
+    if (devPath.empty())
+    {
+        return devPath;
+    }
     if (devPath.back() == '/')
     {
         devPath.pop_back();