VPD Tool: Update Hardware

Vpd tool has --Hardware/-H flag which should be given along
with writeKeyword flags, if the user wants to write directly to "Hardware".

In general the user should give only the object path in
--path/-P value.

Only if --Hardware/-H flag is given, the user has an
option to give either eeprom path or the object path in
--path/-P value.

Test:
Tested on simics.

./vpd-tool --writeKeyword -H --path < hardware path/object path > -R < record name > -K < keyword > -V < value in hex/ascii >

CASE 1: <updating eeprom path> < update directly on hardware using -H.>
./vpd-tool -u -H -P /sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem -R VINI -K PN -V 0x717273
updation successful on both dbus and hardware.

CASE 2:
./vpd-tool -u -H -P /sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem -R DINF -K FL -V 0x717273
updation successful on hardware. <this wont get updated in dbus as the given record-keyword pair is not required to update in dbus(only those record keywords
present in dbus_properties.json are required to be updated in dbus).

CASE 3: <failure case - invalid eeprom path>
root@rainier:/tmp# ./vpd-tool -u -H -P /sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a490.i2c-bus/i2c-8/8-0051/8-00510/nvmem -R VINI -K PN -V 0x717273
Invalid object path : /sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a490.i2c-bus/i2c-8/8-0051/8-00510/nvmem. Unable to find the corresponding EEPROM path for the given object path : /sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e7$

Signed-off-by: PriyangaRamasamy <priyanga24@in.ibm.com>
Change-Id: I6b893e699fe343c90c3a3fd2b07fd8b9a4711687
diff --git a/vpd_tool_impl.cpp b/vpd_tool_impl.cpp
index 5ffb041..647bf50 100644
--- a/vpd_tool_impl.cpp
+++ b/vpd_tool_impl.cpp
@@ -1,18 +1,52 @@
 #include "vpd_tool_impl.hpp"
 
+#include "vpd_exceptions.hpp"
+
 #include <cstdlib>
 #include <filesystem>
-#include <iomanip>
 #include <iostream>
 #include <sdbusplus/bus.hpp>
-#include <sstream>
 #include <variant>
 #include <vector>
 
 using namespace std;
 using sdbusplus::exception::SdBusError;
 using namespace openpower::vpd;
+using namespace inventory;
+using namespace openpower::vpd::manager::editor;
 namespace fs = std::filesystem;
+using json = nlohmann::json;
+using namespace openpower::vpd::exceptions;
+
+Binary VpdTool::toBinary(const std::string& value)
+{
+    Binary val{};
+    if (value.find("0x") == string::npos)
+    {
+        val.assign(value.begin(), value.end());
+    }
+    else if (value.find("0x") != string::npos)
+    {
+        stringstream ss;
+        ss.str(value.substr(2));
+        string byteStr{};
+
+        while (!ss.eof())
+        {
+            ss >> setw(2) >> byteStr;
+            uint8_t byte = strtoul(byteStr.c_str(), nullptr, 16);
+
+            val.push_back(byte);
+        }
+    }
+
+    else
+    {
+        throw runtime_error("The value to be updated should be either in ascii "
+                            "or in hex. Refer --help option");
+    }
+    return val;
+}
 
 void VpdTool::printReturnCode(int returnCode)
 {
@@ -351,35 +385,7 @@
 
 int VpdTool::updateKeyword()
 {
-    Binary val;
-
-    if (value.find("0x") == string::npos)
-    {
-        val.assign(value.begin(), value.end());
-    }
-    else if (value.find("0x") != string::npos)
-    {
-        stringstream ss;
-        ss.str(value.substr(2));
-        string byteStr{};
-
-        while (!ss.eof())
-        {
-            ss >> setw(2) >> byteStr;
-            uint8_t byte = strtoul(byteStr.c_str(), nullptr, 16);
-
-            val.push_back(byte);
-        }
-    }
-
-    else
-    {
-        throw runtime_error("The value to be updated should be either in ascii "
-                            "or in hex. Refer --help option");
-    }
-
-    // writeKeyword(fruPath, recordName, keyword, val);
-
+    Binary val = toBinary(value);
     auto bus = sdbusplus::bus::new_default();
     auto properties =
         bus.new_method_call(BUSNAME, OBJPATH, IFACE, "WriteKeyword");
@@ -442,3 +448,27 @@
     returnCode = system(udevAdd.c_str());
     printReturnCode(returnCode);
 }
+
+int VpdTool::updateHardware()
+{
+    int rc = 0;
+    bool updCache = true;
+    const Binary& val = static_cast<const Binary&>(toBinary(value));
+    ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
+    try
+    {
+        auto json = nlohmann::json::parse(inventoryJson);
+        EditorImpl edit(fruPath, json, recordName, keyword);
+        if (!((isPathInJson(fruPath)) &&
+              (isRecKwInDbusJson(recordName, keyword))))
+        {
+            updCache = false;
+        }
+        edit.updateKeyword(val, updCache);
+    }
+    catch (json::parse_error& ex)
+    {
+        throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
+    }
+    return rc;
+}