1abb87edaSPriyangaRamasamy #include "config.h"
2abb87edaSPriyangaRamasamy 
3abb87edaSPriyangaRamasamy #include "defines.hpp"
4abb87edaSPriyangaRamasamy #include "keyword_vpd_parser.hpp"
5*a00936f8SAlpana Kumari #include "memory_vpd_parser.hpp"
6abb87edaSPriyangaRamasamy #include "parser.hpp"
7abb87edaSPriyangaRamasamy #include "utils.hpp"
8abb87edaSPriyangaRamasamy 
98ea3f6d0SAlpana Kumari #include <ctype.h>
108ea3f6d0SAlpana Kumari 
11abb87edaSPriyangaRamasamy #include <CLI/CLI.hpp>
1288edeb6fSSantosh Puranik #include <algorithm>
13abb87edaSPriyangaRamasamy #include <exception>
1483a1d5deSPriyangaRamasamy #include <filesystem>
15abb87edaSPriyangaRamasamy #include <fstream>
16abb87edaSPriyangaRamasamy #include <iostream>
17abb87edaSPriyangaRamasamy #include <iterator>
18abb87edaSPriyangaRamasamy #include <nlohmann/json.hpp>
19abb87edaSPriyangaRamasamy 
20abb87edaSPriyangaRamasamy using namespace std;
21abb87edaSPriyangaRamasamy using namespace openpower::vpd;
22abb87edaSPriyangaRamasamy using namespace CLI;
23abb87edaSPriyangaRamasamy using namespace vpd::keyword::parser;
2483a1d5deSPriyangaRamasamy using namespace openpower::vpd::constants;
2583a1d5deSPriyangaRamasamy namespace fs = filesystem;
2683a1d5deSPriyangaRamasamy using json = nlohmann::json;
27945a02d3SSunnySrivastava1984 using namespace openpower::vpd::inventory;
28*a00936f8SAlpana Kumari using namespace openpower::vpd::memory::parser;
29abb87edaSPriyangaRamasamy 
3088edeb6fSSantosh Puranik /**
3188edeb6fSSantosh Puranik  * @brief Expands location codes
3288edeb6fSSantosh Puranik  */
3388edeb6fSSantosh Puranik static auto expandLocationCode(const string& unexpanded, const Parsed& vpdMap,
3488edeb6fSSantosh Puranik                                bool isSystemVpd)
3588edeb6fSSantosh Puranik {
3688edeb6fSSantosh Puranik     auto expanded{unexpanded};
3788edeb6fSSantosh Puranik     static constexpr auto SYSTEM_OBJECT = "/system/chassis/motherboard";
3888edeb6fSSantosh Puranik     static constexpr auto VCEN_IF = "com.ibm.ipzvpd.VCEN";
3988edeb6fSSantosh Puranik     static constexpr auto VSYS_IF = "com.ibm.ipzvpd.VSYS";
4088edeb6fSSantosh Puranik     size_t idx = expanded.find("fcs");
4188edeb6fSSantosh Puranik     try
4288edeb6fSSantosh Puranik     {
4388edeb6fSSantosh Puranik         if (idx != string::npos)
4488edeb6fSSantosh Puranik         {
4588edeb6fSSantosh Puranik             string fc{};
4688edeb6fSSantosh Puranik             string se{};
4788edeb6fSSantosh Puranik             if (isSystemVpd)
4888edeb6fSSantosh Puranik             {
4988edeb6fSSantosh Puranik                 const auto& fcData = vpdMap.at("VCEN").at("FC");
5088edeb6fSSantosh Puranik                 const auto& seData = vpdMap.at("VCEN").at("SE");
5188edeb6fSSantosh Puranik                 fc = string(fcData.data(), fcData.size());
5288edeb6fSSantosh Puranik                 se = string(seData.data(), seData.size());
5388edeb6fSSantosh Puranik             }
5488edeb6fSSantosh Puranik             else
5588edeb6fSSantosh Puranik             {
5688edeb6fSSantosh Puranik                 fc = readBusProperty(SYSTEM_OBJECT, VCEN_IF, "FC");
5788edeb6fSSantosh Puranik                 se = readBusProperty(SYSTEM_OBJECT, VCEN_IF, "SE");
5888edeb6fSSantosh Puranik             }
5988edeb6fSSantosh Puranik 
6088edeb6fSSantosh Puranik             // TODO: See if ND1 can be placed in the JSON
6188edeb6fSSantosh Puranik             expanded.replace(idx, 3, fc.substr(0, 4) + ".ND1." + se);
6288edeb6fSSantosh Puranik         }
6388edeb6fSSantosh Puranik         else
6488edeb6fSSantosh Puranik         {
6588edeb6fSSantosh Puranik             idx = expanded.find("mts");
6688edeb6fSSantosh Puranik             if (idx != string::npos)
6788edeb6fSSantosh Puranik             {
6888edeb6fSSantosh Puranik                 string mt{};
6988edeb6fSSantosh Puranik                 string se{};
7088edeb6fSSantosh Puranik                 if (isSystemVpd)
7188edeb6fSSantosh Puranik                 {
7288edeb6fSSantosh Puranik                     const auto& mtData = vpdMap.at("VSYS").at("TM");
7388edeb6fSSantosh Puranik                     const auto& seData = vpdMap.at("VSYS").at("SE");
7488edeb6fSSantosh Puranik                     mt = string(mtData.data(), mtData.size());
7588edeb6fSSantosh Puranik                     se = string(seData.data(), seData.size());
7688edeb6fSSantosh Puranik                 }
7788edeb6fSSantosh Puranik                 else
7888edeb6fSSantosh Puranik                 {
7988edeb6fSSantosh Puranik                     mt = readBusProperty(SYSTEM_OBJECT, VSYS_IF, "TM");
8088edeb6fSSantosh Puranik                     se = readBusProperty(SYSTEM_OBJECT, VSYS_IF, "SE");
8188edeb6fSSantosh Puranik                 }
8288edeb6fSSantosh Puranik 
8388edeb6fSSantosh Puranik                 replace(mt.begin(), mt.end(), '-', '.');
8488edeb6fSSantosh Puranik                 expanded.replace(idx, 3, mt + "." + se);
8588edeb6fSSantosh Puranik             }
8688edeb6fSSantosh Puranik         }
8788edeb6fSSantosh Puranik     }
8888edeb6fSSantosh Puranik     catch (std::exception& e)
8988edeb6fSSantosh Puranik     {
9088edeb6fSSantosh Puranik         std::cerr << "Failed to expand location code with exception: "
9188edeb6fSSantosh Puranik                   << e.what() << "\n";
9288edeb6fSSantosh Puranik     }
9388edeb6fSSantosh Puranik     return expanded;
9488edeb6fSSantosh Puranik }
95abb87edaSPriyangaRamasamy /**
96abb87edaSPriyangaRamasamy  * @brief Populate FRU specific interfaces.
97abb87edaSPriyangaRamasamy  *
98abb87edaSPriyangaRamasamy  * This is a common method which handles both
99abb87edaSPriyangaRamasamy  * ipz and keyword specific interfaces thus,
100abb87edaSPriyangaRamasamy  * reducing the code redundancy.
101abb87edaSPriyangaRamasamy  * @param[in] map - Reference to the innermost keyword-value map.
102abb87edaSPriyangaRamasamy  * @param[in] preIntrStr - Reference to the interface string.
103abb87edaSPriyangaRamasamy  * @param[out] interfaces - Reference to interface map.
104abb87edaSPriyangaRamasamy  */
105abb87edaSPriyangaRamasamy template <typename T>
106abb87edaSPriyangaRamasamy static void populateFruSpecificInterfaces(const T& map,
107abb87edaSPriyangaRamasamy                                           const string& preIntrStr,
108abb87edaSPriyangaRamasamy                                           inventory::InterfaceMap& interfaces)
109abb87edaSPriyangaRamasamy {
110abb87edaSPriyangaRamasamy     inventory::PropertyMap prop;
111abb87edaSPriyangaRamasamy 
112abb87edaSPriyangaRamasamy     for (const auto& kwVal : map)
113abb87edaSPriyangaRamasamy     {
114abb87edaSPriyangaRamasamy         std::vector<uint8_t> vec(kwVal.second.begin(), kwVal.second.end());
115abb87edaSPriyangaRamasamy 
116abb87edaSPriyangaRamasamy         auto kw = kwVal.first;
117abb87edaSPriyangaRamasamy 
118abb87edaSPriyangaRamasamy         if (kw[0] == '#')
119abb87edaSPriyangaRamasamy         {
120abb87edaSPriyangaRamasamy             kw = std::string("PD_") + kw[1];
121abb87edaSPriyangaRamasamy         }
1228ea3f6d0SAlpana Kumari         else if (isdigit(kw[0]))
1238ea3f6d0SAlpana Kumari         {
1248ea3f6d0SAlpana Kumari             kw = std::string("N_") + kw;
1258ea3f6d0SAlpana Kumari         }
126abb87edaSPriyangaRamasamy         prop.emplace(move(kw), move(vec));
127abb87edaSPriyangaRamasamy     }
128abb87edaSPriyangaRamasamy 
129abb87edaSPriyangaRamasamy     interfaces.emplace(preIntrStr, move(prop));
130abb87edaSPriyangaRamasamy }
131abb87edaSPriyangaRamasamy 
132abb87edaSPriyangaRamasamy /**
133abb87edaSPriyangaRamasamy  * @brief Populate Interfaces.
134abb87edaSPriyangaRamasamy  *
135abb87edaSPriyangaRamasamy  * This method populates common and extra interfaces to dbus.
136abb87edaSPriyangaRamasamy  * @param[in] js - json object
137abb87edaSPriyangaRamasamy  * @param[out] interfaces - Reference to interface map
138abb87edaSPriyangaRamasamy  * @param[in] vpdMap - Reference to the parsed vpd map.
13988edeb6fSSantosh Puranik  * @param[in] isSystemVpd - Denotes whether we are collecting the system VPD.
140abb87edaSPriyangaRamasamy  */
141abb87edaSPriyangaRamasamy template <typename T>
142abb87edaSPriyangaRamasamy static void populateInterfaces(const nlohmann::json& js,
143abb87edaSPriyangaRamasamy                                inventory::InterfaceMap& interfaces,
14488edeb6fSSantosh Puranik                                const T& vpdMap, bool isSystemVpd)
145abb87edaSPriyangaRamasamy {
146abb87edaSPriyangaRamasamy     for (const auto& ifs : js.items())
147abb87edaSPriyangaRamasamy     {
14888edeb6fSSantosh Puranik         string inf = ifs.key();
149abb87edaSPriyangaRamasamy         inventory::PropertyMap props;
150abb87edaSPriyangaRamasamy 
151abb87edaSPriyangaRamasamy         for (const auto& itr : ifs.value().items())
152abb87edaSPriyangaRamasamy         {
15388edeb6fSSantosh Puranik             const string& busProp = itr.key();
15488edeb6fSSantosh Puranik 
15531970dedSAlpana Kumari             if (itr.value().is_boolean())
15631970dedSAlpana Kumari             {
15788edeb6fSSantosh Puranik                 props.emplace(busProp, itr.value().get<bool>());
15888edeb6fSSantosh Puranik             }
15988edeb6fSSantosh Puranik             else if (itr.value().is_string())
16088edeb6fSSantosh Puranik             {
16188edeb6fSSantosh Puranik                 if constexpr (std::is_same<T, Parsed>::value)
16288edeb6fSSantosh Puranik                 {
16388edeb6fSSantosh Puranik                     if (busProp == "LocationCode" &&
16488edeb6fSSantosh Puranik                         inf == "com.ibm.ipzvpd.Location")
16588edeb6fSSantosh Puranik                     {
16688edeb6fSSantosh Puranik                         auto prop = expandLocationCode(
16788edeb6fSSantosh Puranik                             itr.value().get<string>(), vpdMap, isSystemVpd);
16888edeb6fSSantosh Puranik                         props.emplace(busProp, prop);
16988edeb6fSSantosh Puranik                     }
17088edeb6fSSantosh Puranik                     else
17188edeb6fSSantosh Puranik                     {
17288edeb6fSSantosh Puranik                         props.emplace(busProp, itr.value().get<string>());
17388edeb6fSSantosh Puranik                     }
17488edeb6fSSantosh Puranik                 }
17588edeb6fSSantosh Puranik                 else
17688edeb6fSSantosh Puranik                 {
17788edeb6fSSantosh Puranik                     props.emplace(busProp, itr.value().get<string>());
17888edeb6fSSantosh Puranik                 }
17931970dedSAlpana Kumari             }
18031970dedSAlpana Kumari             else if (itr.value().is_object())
18131970dedSAlpana Kumari             {
182abb87edaSPriyangaRamasamy                 const string& rec = itr.value().value("recordName", "");
183abb87edaSPriyangaRamasamy                 const string& kw = itr.value().value("keywordName", "");
184abb87edaSPriyangaRamasamy                 const string& encoding = itr.value().value("encoding", "");
185abb87edaSPriyangaRamasamy 
186abb87edaSPriyangaRamasamy                 if constexpr (std::is_same<T, Parsed>::value)
187abb87edaSPriyangaRamasamy                 {
18888edeb6fSSantosh Puranik                     if (!rec.empty() && !kw.empty() && vpdMap.count(rec) &&
18988edeb6fSSantosh Puranik                         vpdMap.at(rec).count(kw))
190abb87edaSPriyangaRamasamy                     {
191abb87edaSPriyangaRamasamy                         auto encoded =
192abb87edaSPriyangaRamasamy                             encodeKeyword(vpdMap.at(rec).at(kw), encoding);
19388edeb6fSSantosh Puranik                         props.emplace(busProp, encoded);
194abb87edaSPriyangaRamasamy                     }
195abb87edaSPriyangaRamasamy                 }
196abb87edaSPriyangaRamasamy                 else if constexpr (std::is_same<T, KeywordVpdMap>::value)
197abb87edaSPriyangaRamasamy                 {
198abb87edaSPriyangaRamasamy                     if (!kw.empty() && vpdMap.count(kw))
199abb87edaSPriyangaRamasamy                     {
200abb87edaSPriyangaRamasamy                         auto prop =
201abb87edaSPriyangaRamasamy                             string(vpdMap.at(kw).begin(), vpdMap.at(kw).end());
202abb87edaSPriyangaRamasamy                         auto encoded = encodeKeyword(prop, encoding);
20388edeb6fSSantosh Puranik                         props.emplace(busProp, encoded);
204abb87edaSPriyangaRamasamy                     }
205abb87edaSPriyangaRamasamy                 }
206abb87edaSPriyangaRamasamy             }
20731970dedSAlpana Kumari         }
208abb87edaSPriyangaRamasamy         interfaces.emplace(inf, move(props));
209abb87edaSPriyangaRamasamy     }
210abb87edaSPriyangaRamasamy }
211abb87edaSPriyangaRamasamy 
212abb87edaSPriyangaRamasamy /**
2138e140a1cSPriyangaRamasamy  * @brief Prime the Inventory
2148e140a1cSPriyangaRamasamy  * Prime the inventory by populating only the location code,
2158e140a1cSPriyangaRamasamy  * type interface and the inventory object for the frus
2168e140a1cSPriyangaRamasamy  * which are not system vpd fru.
217abb87edaSPriyangaRamasamy  *
2188e140a1cSPriyangaRamasamy  * @param[in] jsObject - Reference to vpd inventory json object
2198e140a1cSPriyangaRamasamy  * @param[in] vpdMap -  Reference to the parsed vpd map
2208e140a1cSPriyangaRamasamy  *
2218e140a1cSPriyangaRamasamy  * @returns Map of items in extraInterface.
2228e140a1cSPriyangaRamasamy  */
2238e140a1cSPriyangaRamasamy template <typename T>
2248e140a1cSPriyangaRamasamy inventory::ObjectMap primeInventory(const nlohmann::json& jsObject,
2258e140a1cSPriyangaRamasamy                                     const T& vpdMap)
2268e140a1cSPriyangaRamasamy {
2278e140a1cSPriyangaRamasamy     inventory::ObjectMap objects;
2288e140a1cSPriyangaRamasamy 
2298e140a1cSPriyangaRamasamy     for (auto& itemFRUS : jsObject["frus"].items())
2308e140a1cSPriyangaRamasamy     {
2318e140a1cSPriyangaRamasamy         for (auto& itemEEPROM : itemFRUS.value())
2328e140a1cSPriyangaRamasamy         {
2338e140a1cSPriyangaRamasamy             inventory::InterfaceMap interfaces;
2348e140a1cSPriyangaRamasamy             auto isSystemVpd = itemEEPROM.value("isSystemVpd", false);
2358e140a1cSPriyangaRamasamy             inventory::Object object(itemEEPROM.at("inventoryPath"));
2368e140a1cSPriyangaRamasamy 
2378e140a1cSPriyangaRamasamy             if (!isSystemVpd && !itemEEPROM.value("noprime", false))
2388e140a1cSPriyangaRamasamy             {
2398e140a1cSPriyangaRamasamy                 if (itemEEPROM.find("extraInterfaces") != itemEEPROM.end())
2408e140a1cSPriyangaRamasamy                 {
2418e140a1cSPriyangaRamasamy                     for (const auto& eI : itemEEPROM["extraInterfaces"].items())
2428e140a1cSPriyangaRamasamy                     {
2438e140a1cSPriyangaRamasamy                         inventory::PropertyMap props;
2448e140a1cSPriyangaRamasamy                         if (eI.key() ==
2458e140a1cSPriyangaRamasamy                             openpower::vpd::constants::LOCATION_CODE_INF)
2468e140a1cSPriyangaRamasamy                         {
2478e140a1cSPriyangaRamasamy                             if constexpr (std::is_same<T, Parsed>::value)
2488e140a1cSPriyangaRamasamy                             {
2498e140a1cSPriyangaRamasamy                                 for (auto& lC : eI.value().items())
2508e140a1cSPriyangaRamasamy                                 {
2518e140a1cSPriyangaRamasamy                                     auto propVal = expandLocationCode(
2528e140a1cSPriyangaRamasamy                                         lC.value().get<string>(), vpdMap, true);
2538e140a1cSPriyangaRamasamy 
2548e140a1cSPriyangaRamasamy                                     props.emplace(move(lC.key()),
2558e140a1cSPriyangaRamasamy                                                   move(propVal));
2568e140a1cSPriyangaRamasamy                                     interfaces.emplace(move(eI.key()),
2578e140a1cSPriyangaRamasamy                                                        move(props));
2588e140a1cSPriyangaRamasamy                                 }
2598e140a1cSPriyangaRamasamy                             }
2608e140a1cSPriyangaRamasamy                         }
2618e140a1cSPriyangaRamasamy                         else if (eI.key().find("Inventory.Item.") !=
2628e140a1cSPriyangaRamasamy                                  string::npos)
2638e140a1cSPriyangaRamasamy                         {
2648e140a1cSPriyangaRamasamy                             interfaces.emplace(move(eI.key()), move(props));
2658e140a1cSPriyangaRamasamy                         }
2668e140a1cSPriyangaRamasamy                     }
2678e140a1cSPriyangaRamasamy                 }
2688e140a1cSPriyangaRamasamy                 objects.emplace(move(object), move(interfaces));
2698e140a1cSPriyangaRamasamy             }
2708e140a1cSPriyangaRamasamy         }
2718e140a1cSPriyangaRamasamy     }
2728e140a1cSPriyangaRamasamy     return objects;
2738e140a1cSPriyangaRamasamy }
2748e140a1cSPriyangaRamasamy 
2758e140a1cSPriyangaRamasamy /**
2768e140a1cSPriyangaRamasamy  * @brief Populate Dbus.
277abb87edaSPriyangaRamasamy  * This method invokes all the populateInterface functions
278abb87edaSPriyangaRamasamy  * and notifies PIM about dbus object.
2798e140a1cSPriyangaRamasamy  * @param[in] vpdMap - Either IPZ vpd map or Keyword vpd map based on the
2808e140a1cSPriyangaRamasamy  * input.
281abb87edaSPriyangaRamasamy  * @param[in] js - Inventory json object
282abb87edaSPriyangaRamasamy  * @param[in] filePath - Path of the vpd file
283abb87edaSPriyangaRamasamy  * @param[in] preIntrStr - Interface string
284abb87edaSPriyangaRamasamy  */
285abb87edaSPriyangaRamasamy template <typename T>
286abb87edaSPriyangaRamasamy static void populateDbus(const T& vpdMap, nlohmann::json& js,
287abb87edaSPriyangaRamasamy                          const string& filePath, const string& preIntrStr)
288abb87edaSPriyangaRamasamy {
289abb87edaSPriyangaRamasamy     inventory::InterfaceMap interfaces;
290abb87edaSPriyangaRamasamy     inventory::ObjectMap objects;
291abb87edaSPriyangaRamasamy     inventory::PropertyMap prop;
292abb87edaSPriyangaRamasamy 
2938e140a1cSPriyangaRamasamy     bool isSystemVpd;
294abb87edaSPriyangaRamasamy     for (const auto& item : js["frus"][filePath])
295abb87edaSPriyangaRamasamy     {
296abb87edaSPriyangaRamasamy         const auto& objectPath = item["inventoryPath"];
297abb87edaSPriyangaRamasamy         sdbusplus::message::object_path object(objectPath);
2988e140a1cSPriyangaRamasamy         isSystemVpd = item.value("isSystemVpd", false);
299abb87edaSPriyangaRamasamy         // Populate the VPD keywords and the common interfaces only if we
300abb87edaSPriyangaRamasamy         // are asked to inherit that data from the VPD, else only add the
301abb87edaSPriyangaRamasamy         // extraInterfaces.
302abb87edaSPriyangaRamasamy         if (item.value("inherit", true))
303abb87edaSPriyangaRamasamy         {
304abb87edaSPriyangaRamasamy             if constexpr (std::is_same<T, Parsed>::value)
305abb87edaSPriyangaRamasamy             {
3068e140a1cSPriyangaRamasamy                 // Each record in the VPD becomes an interface and all
3078e140a1cSPriyangaRamasamy                 // keyword within the record are properties under that
3088e140a1cSPriyangaRamasamy                 // interface.
309abb87edaSPriyangaRamasamy                 for (const auto& record : vpdMap)
310abb87edaSPriyangaRamasamy                 {
311abb87edaSPriyangaRamasamy                     populateFruSpecificInterfaces(
312abb87edaSPriyangaRamasamy                         record.second, preIntrStr + record.first, interfaces);
313abb87edaSPriyangaRamasamy                 }
314abb87edaSPriyangaRamasamy             }
315abb87edaSPriyangaRamasamy             else if constexpr (std::is_same<T, KeywordVpdMap>::value)
316abb87edaSPriyangaRamasamy             {
317abb87edaSPriyangaRamasamy                 populateFruSpecificInterfaces(vpdMap, preIntrStr, interfaces);
318abb87edaSPriyangaRamasamy             }
31988edeb6fSSantosh Puranik             if (js.find("commonInterfaces") != js.end())
32088edeb6fSSantosh Puranik             {
32188edeb6fSSantosh Puranik                 populateInterfaces(js["commonInterfaces"], interfaces, vpdMap,
32288edeb6fSSantosh Puranik                                    isSystemVpd);
32388edeb6fSSantosh Puranik             }
324abb87edaSPriyangaRamasamy         }
3250859eb65SSantosh Puranik         else
3260859eb65SSantosh Puranik         {
3270859eb65SSantosh Puranik             // Check if we have been asked to inherit specific record(s)
3280859eb65SSantosh Puranik             if constexpr (std::is_same<T, Parsed>::value)
3290859eb65SSantosh Puranik             {
3300859eb65SSantosh Puranik                 if (item.find("copyRecords") != item.end())
3310859eb65SSantosh Puranik                 {
3320859eb65SSantosh Puranik                     for (const auto& record : item["copyRecords"])
3330859eb65SSantosh Puranik                     {
3340859eb65SSantosh Puranik                         const string& recordName = record;
3350859eb65SSantosh Puranik                         if (vpdMap.find(recordName) != vpdMap.end())
3360859eb65SSantosh Puranik                         {
3370859eb65SSantosh Puranik                             populateFruSpecificInterfaces(
3380859eb65SSantosh Puranik                                 vpdMap.at(recordName), preIntrStr + recordName,
3390859eb65SSantosh Puranik                                 interfaces);
3400859eb65SSantosh Puranik                         }
3410859eb65SSantosh Puranik                     }
3420859eb65SSantosh Puranik                 }
3430859eb65SSantosh Puranik             }
3440859eb65SSantosh Puranik         }
345abb87edaSPriyangaRamasamy 
346abb87edaSPriyangaRamasamy         // Populate interfaces and properties that are common to every FRU
3478e140a1cSPriyangaRamasamy         // and additional interface that might be defined on a per-FRU
3488e140a1cSPriyangaRamasamy         // basis.
349abb87edaSPriyangaRamasamy         if (item.find("extraInterfaces") != item.end())
350abb87edaSPriyangaRamasamy         {
35188edeb6fSSantosh Puranik             populateInterfaces(item["extraInterfaces"], interfaces, vpdMap,
35288edeb6fSSantosh Puranik                                isSystemVpd);
353abb87edaSPriyangaRamasamy         }
354abb87edaSPriyangaRamasamy         objects.emplace(move(object), move(interfaces));
355abb87edaSPriyangaRamasamy     }
356abb87edaSPriyangaRamasamy 
3578e140a1cSPriyangaRamasamy     if (isSystemVpd)
3588e140a1cSPriyangaRamasamy     {
35983a1d5deSPriyangaRamasamy         vector<uint8_t> imVal;
36083a1d5deSPriyangaRamasamy         if constexpr (is_same<T, Parsed>::value)
36183a1d5deSPriyangaRamasamy         {
36283a1d5deSPriyangaRamasamy             auto property = vpdMap.find("VSBP");
36383a1d5deSPriyangaRamasamy             if (property != vpdMap.end())
36483a1d5deSPriyangaRamasamy             {
36583a1d5deSPriyangaRamasamy                 auto value = (property->second).find("IM");
36683a1d5deSPriyangaRamasamy                 if (value != (property->second).end())
36783a1d5deSPriyangaRamasamy                 {
36883a1d5deSPriyangaRamasamy                     copy(value->second.begin(), value->second.end(),
36983a1d5deSPriyangaRamasamy                          back_inserter(imVal));
37083a1d5deSPriyangaRamasamy                 }
37183a1d5deSPriyangaRamasamy             }
37283a1d5deSPriyangaRamasamy         }
37383a1d5deSPriyangaRamasamy 
37483a1d5deSPriyangaRamasamy         fs::path target;
37583a1d5deSPriyangaRamasamy         fs::path link = INVENTORY_JSON_SYM_LINK;
37683a1d5deSPriyangaRamasamy 
37783a1d5deSPriyangaRamasamy         ostringstream oss;
37883a1d5deSPriyangaRamasamy         for (auto& i : imVal)
37983a1d5deSPriyangaRamasamy         {
38083a1d5deSPriyangaRamasamy             oss << setw(2) << setfill('0') << hex << static_cast<int>(i);
38183a1d5deSPriyangaRamasamy         }
38283a1d5deSPriyangaRamasamy         string imValStr = oss.str();
38383a1d5deSPriyangaRamasamy 
38483a1d5deSPriyangaRamasamy         if (imValStr == SYSTEM_4U) // 4U
38583a1d5deSPriyangaRamasamy         {
38683a1d5deSPriyangaRamasamy             target = INVENTORY_JSON_4U;
38783a1d5deSPriyangaRamasamy         }
38883a1d5deSPriyangaRamasamy 
38983a1d5deSPriyangaRamasamy         else if (imValStr == SYSTEM_2U) // 2U
39083a1d5deSPriyangaRamasamy         {
39183a1d5deSPriyangaRamasamy             target = INVENTORY_JSON_2U;
39283a1d5deSPriyangaRamasamy         }
39383a1d5deSPriyangaRamasamy 
39483a1d5deSPriyangaRamasamy         // unlink the symlink which is created at build time
39583a1d5deSPriyangaRamasamy         remove(INVENTORY_JSON_SYM_LINK);
39683a1d5deSPriyangaRamasamy         // create a new symlink based on the system
39783a1d5deSPriyangaRamasamy         fs::create_symlink(target, link);
39883a1d5deSPriyangaRamasamy 
39983a1d5deSPriyangaRamasamy         // Reloading the json
40083a1d5deSPriyangaRamasamy         ifstream inventoryJson(link);
40183a1d5deSPriyangaRamasamy         auto js = json::parse(inventoryJson);
40283a1d5deSPriyangaRamasamy         inventoryJson.close();
40383a1d5deSPriyangaRamasamy 
4048e140a1cSPriyangaRamasamy         inventory::ObjectMap primeObject = primeInventory(js, vpdMap);
4058e140a1cSPriyangaRamasamy         objects.insert(primeObject.begin(), primeObject.end());
4068e140a1cSPriyangaRamasamy     }
4078e140a1cSPriyangaRamasamy 
408abb87edaSPriyangaRamasamy     // Notify PIM
409abb87edaSPriyangaRamasamy     inventory::callPIM(move(objects));
410abb87edaSPriyangaRamasamy }
411abb87edaSPriyangaRamasamy 
412abb87edaSPriyangaRamasamy int main(int argc, char** argv)
413abb87edaSPriyangaRamasamy {
414abb87edaSPriyangaRamasamy     int rc = 0;
415abb87edaSPriyangaRamasamy 
416abb87edaSPriyangaRamasamy     try
417abb87edaSPriyangaRamasamy     {
418abb87edaSPriyangaRamasamy         App app{"ibm-read-vpd - App to read IPZ format VPD, parse it and store "
419abb87edaSPriyangaRamasamy                 "in DBUS"};
420abb87edaSPriyangaRamasamy         string file{};
421abb87edaSPriyangaRamasamy 
422abb87edaSPriyangaRamasamy         app.add_option("-f, --file", file, "File containing VPD (IPZ/KEYWORD)")
423abb87edaSPriyangaRamasamy             ->required()
424abb87edaSPriyangaRamasamy             ->check(ExistingFile);
425abb87edaSPriyangaRamasamy 
426abb87edaSPriyangaRamasamy         CLI11_PARSE(app, argc, argv);
427abb87edaSPriyangaRamasamy 
428abb87edaSPriyangaRamasamy         // Make sure that the file path we get is for a supported EEPROM
429abb87edaSPriyangaRamasamy         ifstream inventoryJson(INVENTORY_JSON);
430abb87edaSPriyangaRamasamy         auto js = json::parse(inventoryJson);
431abb87edaSPriyangaRamasamy 
432abb87edaSPriyangaRamasamy         if ((js.find("frus") == js.end()) ||
433abb87edaSPriyangaRamasamy             (js["frus"].find(file) == js["frus"].end()))
434abb87edaSPriyangaRamasamy         {
43588edeb6fSSantosh Puranik             cout << "Device path not in JSON, ignoring" << std::endl;
43688edeb6fSSantosh Puranik             return 0;
437abb87edaSPriyangaRamasamy         }
438abb87edaSPriyangaRamasamy 
4398ea3f6d0SAlpana Kumari         uint32_t offset = 0;
4408ea3f6d0SAlpana Kumari         // check if offset present?
4418ea3f6d0SAlpana Kumari         for (const auto& item : js["frus"][file])
4428ea3f6d0SAlpana Kumari         {
4438ea3f6d0SAlpana Kumari             if (item.find("offset") != item.end())
4448ea3f6d0SAlpana Kumari             {
4458ea3f6d0SAlpana Kumari                 offset = item["offset"];
4468ea3f6d0SAlpana Kumari             }
4478ea3f6d0SAlpana Kumari         }
4488ea3f6d0SAlpana Kumari 
4498ea3f6d0SAlpana Kumari         // TODO: Figure out a better way to get max possible VPD size.
4508ea3f6d0SAlpana Kumari         Binary vpdVector;
4518ea3f6d0SAlpana Kumari         vpdVector.resize(65504);
4528ea3f6d0SAlpana Kumari         ifstream vpdFile;
4538ea3f6d0SAlpana Kumari         vpdFile.open(file, ios::binary);
4548ea3f6d0SAlpana Kumari 
4558ea3f6d0SAlpana Kumari         vpdFile.seekg(offset, ios_base::cur);
4568ea3f6d0SAlpana Kumari         vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), 65504);
4578ea3f6d0SAlpana Kumari         vpdVector.resize(vpdFile.gcount());
458abb87edaSPriyangaRamasamy 
459abb87edaSPriyangaRamasamy         vpdType type = vpdTypeCheck(vpdVector);
460abb87edaSPriyangaRamasamy 
461abb87edaSPriyangaRamasamy         switch (type)
462abb87edaSPriyangaRamasamy         {
463abb87edaSPriyangaRamasamy             case IPZ_VPD:
464abb87edaSPriyangaRamasamy             {
465abb87edaSPriyangaRamasamy                 // Invoking IPZ Vpd Parser
466abb87edaSPriyangaRamasamy                 auto vpdStore = parse(move(vpdVector));
467abb87edaSPriyangaRamasamy                 const Parsed& vpdMap = vpdStore.getVpdMap();
468abb87edaSPriyangaRamasamy                 string preIntrStr = "com.ibm.ipzvpd.";
469abb87edaSPriyangaRamasamy                 // Write it to the inventory
470abb87edaSPriyangaRamasamy                 populateDbus(vpdMap, js, file, preIntrStr);
471abb87edaSPriyangaRamasamy             }
472abb87edaSPriyangaRamasamy             break;
473abb87edaSPriyangaRamasamy 
474abb87edaSPriyangaRamasamy             case KEYWORD_VPD:
475abb87edaSPriyangaRamasamy             {
476abb87edaSPriyangaRamasamy                 // Creating Keyword Vpd Parser Object
477abb87edaSPriyangaRamasamy                 KeywordVpdParser parserObj(move(vpdVector));
478abb87edaSPriyangaRamasamy                 // Invoking KW Vpd Parser
479abb87edaSPriyangaRamasamy                 const auto& kwValMap = parserObj.parseKwVpd();
480*a00936f8SAlpana Kumari                 string preIntrStr = "com.ibm.ipzvpd.VINI";
481abb87edaSPriyangaRamasamy                 populateDbus(kwValMap, js, file, preIntrStr);
482abb87edaSPriyangaRamasamy             }
483abb87edaSPriyangaRamasamy             break;
484*a00936f8SAlpana Kumari 
485*a00936f8SAlpana Kumari             case MEMORY_VPD:
486*a00936f8SAlpana Kumari             {
487*a00936f8SAlpana Kumari                 // Get an object to call API & get the key-value map
488*a00936f8SAlpana Kumari                 memoryVpdParser vpdParser(move(vpdVector));
489*a00936f8SAlpana Kumari                 const auto& memKwValMap = vpdParser.parseMemVpd();
490*a00936f8SAlpana Kumari 
491*a00936f8SAlpana Kumari                 string preIntrStr = "com.ibm.kwvpd.KWVPD";
492*a00936f8SAlpana Kumari                 // js(define dimm sys path in js), ObjPath(define in JS)
493*a00936f8SAlpana Kumari                 populateDbus(memKwValMap, js, file, preIntrStr);
494*a00936f8SAlpana Kumari             }
495*a00936f8SAlpana Kumari             break;
496*a00936f8SAlpana Kumari 
497abb87edaSPriyangaRamasamy             default:
498abb87edaSPriyangaRamasamy                 throw std::runtime_error("Invalid VPD format");
499abb87edaSPriyangaRamasamy         }
500abb87edaSPriyangaRamasamy     }
501abb87edaSPriyangaRamasamy     catch (exception& e)
502abb87edaSPriyangaRamasamy     {
503abb87edaSPriyangaRamasamy         cerr << e.what() << "\n";
504abb87edaSPriyangaRamasamy         rc = -1;
505abb87edaSPriyangaRamasamy     }
506abb87edaSPriyangaRamasamy 
507abb87edaSPriyangaRamasamy     return rc;
508abb87edaSPriyangaRamasamy }
509