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