IBM VPD Parser support for both 2U & 4U system

Based on motherboard IM keyword the type of the system is identified
and the corresponding json is linked at the runtime.

Currently 2U system has support for single dasd-backplane
whereas 4U system has support for more than one dasd-backplanes.

Tested on simics.

Change-Id: Ia3eb48661fe565f6286c079a8f87736bb136210a
Signed-off-by: Priyanga Ramasamy <priyanga24@in.ibm.com>
diff --git a/const.hpp b/const.hpp
index c2ff5b3..1ee8c89 100644
--- a/const.hpp
+++ b/const.hpp
@@ -46,6 +46,8 @@
 constexpr uint8_t EXP_LOCATIN_CODE_MIN_LENGTH = 17;
 static constexpr auto SE_KWD_LENGTH = 7;
 static constexpr auto INVALID_NODE_NUMBER = -1;
+static constexpr auto SYSTEM_2U = "50001001";
+static constexpr auto SYSTEM_4U = "50001000";
 
 namespace lengths
 {
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index 4c3aba4..9022e3d 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -9,6 +9,7 @@
 #include <CLI/CLI.hpp>
 #include <algorithm>
 #include <exception>
+#include <filesystem>
 #include <fstream>
 #include <iostream>
 #include <iterator>
@@ -19,6 +20,9 @@
 using namespace CLI;
 using namespace vpd::keyword::parser;
 using namespace vpdFormat;
+using namespace openpower::vpd::constants;
+namespace fs = filesystem;
+using json = nlohmann::json;
 
 /**
  * @brief Expands location codes
@@ -345,6 +349,51 @@
 
     if (isSystemVpd)
     {
+        vector<uint8_t> imVal;
+        if constexpr (is_same<T, Parsed>::value)
+        {
+            auto property = vpdMap.find("VSBP");
+            if (property != vpdMap.end())
+            {
+                auto value = (property->second).find("IM");
+                if (value != (property->second).end())
+                {
+                    copy(value->second.begin(), value->second.end(),
+                         back_inserter(imVal));
+                }
+            }
+        }
+
+        fs::path target;
+        fs::path link = INVENTORY_JSON_SYM_LINK;
+
+        ostringstream oss;
+        for (auto& i : imVal)
+        {
+            oss << setw(2) << setfill('0') << hex << static_cast<int>(i);
+        }
+        string imValStr = oss.str();
+
+        if (imValStr == SYSTEM_4U) // 4U
+        {
+            target = INVENTORY_JSON_4U;
+        }
+
+        else if (imValStr == SYSTEM_2U) // 2U
+        {
+            target = INVENTORY_JSON_2U;
+        }
+
+        // unlink the symlink which is created at build time
+        remove(INVENTORY_JSON_SYM_LINK);
+        // create a new symlink based on the system
+        fs::create_symlink(target, link);
+
+        // Reloading the json
+        ifstream inventoryJson(link);
+        auto js = json::parse(inventoryJson);
+        inventoryJson.close();
+
         inventory::ObjectMap primeObject = primeInventory(js, vpdMap);
         objects.insert(primeObject.begin(), primeObject.end());
     }
@@ -359,8 +408,6 @@
 
     try
     {
-        using json = nlohmann::json;
-
         App app{"ibm-read-vpd - App to read IPZ format VPD, parse it and store "
                 "in DBUS"};
         string file{};
diff --git a/meson.build b/meson.build
index 0b20e5c..35947a2 100644
--- a/meson.build
+++ b/meson.build
@@ -32,7 +32,10 @@
                        'OBJECT_MAPPER_SERVICE' : '"'+get_option('OBJECT_MAPPER_SERVICE')+'"',
                        'OBJECT_MAPPER_OBJECT' : '"'+get_option('OBJECT_MAPPER_OBJECT')+'"',
                        'POWER_SUPPLY_TYPE_INTERFACE' : '"'+get_option('POWER_SUPPLY_TYPE_INTERFACE')+'"',
-                       'INVENTORY_MANAGER_CACHE' : '"'+get_option('INVENTORY_MANAGER_CACHE')+'"'
+                       'INVENTORY_MANAGER_CACHE' : '"'+get_option('INVENTORY_MANAGER_CACHE')+'"',
+		       'INVENTORY_JSON_SYM_LINK': '"'+get_option('INVENTORY_JSON_SYM_LINK')+'"',
+		       'INVENTORY_JSON_2U': '"'+get_option('INVENTORY_JSON_2U')+'"',
+		       'INVENTORY_JSON_4U': '"'+get_option('INVENTORY_JSON_4U')+'"'
                        }
   )
 
diff --git a/meson_options.txt b/meson_options.txt
index 50ce922..2f43526 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -3,7 +3,7 @@
 option('FRU_YAML',type: 'string', value: 'writefru.yaml',  description: 'YAML STRING')
 option('PROP_YAML',type: 'string', value: 'extra-properties-example.yaml',  description: 'YAML PROPERTY')
 option('ibm-parser', type: 'feature', description: 'ENABLE IBM PARSER')
-option('INVENTORY_JSON',type: 'string', value: '/usr/share/vpd/vpd_inventory.json',  description: 'JSON file that defines inventory blueprint')
+option('INVENTORY_JSON',type: 'string', value: '/var/lib/vpd/vpd_inventory.json',  description: 'JSON file that defines inventory blueprint')
 option('INVENTORY_PATH',type: 'string', value: '/xyz/openbmc_project/inventory', description: 'Prefix for inventory D-Bus objects')
 option('INVENTORY_MANAGER_SERVICE',type: 'string', value: 'xyz.openbmc_project.Inventory.Manager', description: 'Inventory manager service')
 option('IPZ_INTERFACE', type: 'string', value: 'com.ibm.ipzvpd', description: 'IPZ VPD interface')
@@ -15,3 +15,6 @@
 option('OBJECT_MAPPER_OBJECT', type : 'string', value : '/xyz/openbmc_project/object_mapper', description : 'One of the objects in Object Mapper service')
 option('POWER_SUPPLY_TYPE_INTERFACE', type : 'string', value : 'xyz.openbmc_project.Inventory.Item.PowerSupply', description : 'Power Supply Type Interface')
 option('INVENTORY_MANAGER_CACHE', type : 'string', value : '/var/lib/phosphor-inventory-manager', description : 'Path to inventory manager cache')
+option('INVENTORY_JSON_SYM_LINK',type: 'string', value: '/var/lib/vpd/vpd_inventory.json',  description: 'Symbolic link to vpd inventory json.')
+option('INVENTORY_JSON_2U',type: 'string', value: '/usr/share/vpd/50001001.json',  description: 'Inventory JSON for 2U system.')
+option('INVENTORY_JSON_4U',type: 'string', value: '/usr/share/vpd/50001000.json',  description: 'Inventory JSON for 4U system.')