16c71c9dcSSunny Srivastava #include "config.h"
26c71c9dcSSunny Srivastava 
36c71c9dcSSunny Srivastava #include "ibm_vpd_utils.hpp"
46c71c9dcSSunny Srivastava 
56c71c9dcSSunny Srivastava #include "common_utility.hpp"
6e2b0383aSJinu Joy Thomas #include "const.hpp"
76c71c9dcSSunny Srivastava #include "defines.hpp"
86c71c9dcSSunny Srivastava #include "vpd_exceptions.hpp"
96c71c9dcSSunny Srivastava 
106bd095f9SAlpana Kumari #include <boost/algorithm/string.hpp>
11735dee9bSAlpana Kumari #include <gpiod.hpp>
126c71c9dcSSunny Srivastava #include <nlohmann/json.hpp>
136c71c9dcSSunny Srivastava #include <phosphor-logging/elog-errors.hpp>
146c71c9dcSSunny Srivastava #include <phosphor-logging/log.hpp>
156c71c9dcSSunny Srivastava #include <sdbusplus/server.hpp>
16c78d887cSPatrick Williams #include <xyz/openbmc_project/Common/error.hpp>
17c78d887cSPatrick Williams 
18c78d887cSPatrick Williams #include <filesystem>
19c78d887cSPatrick Williams #include <fstream>
20c78d887cSPatrick Williams #include <iomanip>
21c78d887cSPatrick Williams #include <regex>
226c71c9dcSSunny Srivastava #include <sstream>
236c71c9dcSSunny Srivastava #include <vector>
246c71c9dcSSunny Srivastava 
256c71c9dcSSunny Srivastava using json = nlohmann::json;
266c71c9dcSSunny Srivastava 
276c71c9dcSSunny Srivastava namespace openpower
286c71c9dcSSunny Srivastava {
296c71c9dcSSunny Srivastava namespace vpd
306c71c9dcSSunny Srivastava {
316c71c9dcSSunny Srivastava using namespace openpower::vpd::constants;
326c71c9dcSSunny Srivastava using namespace inventory;
336c71c9dcSSunny Srivastava using namespace phosphor::logging;
346c71c9dcSSunny Srivastava using namespace sdbusplus::xyz::openbmc_project::Common::Error;
356c71c9dcSSunny Srivastava using namespace record;
366c71c9dcSSunny Srivastava using namespace openpower::vpd::exceptions;
376c71c9dcSSunny Srivastava using namespace common::utility;
380746eeebSSunny Srivastava using Severity = openpower::vpd::constants::PelSeverity;
39c2fe40f8SPriyangaRamasamy namespace fs = std::filesystem;
400746eeebSSunny Srivastava 
410746eeebSSunny Srivastava // mapping of severity enum to severity interface
420746eeebSSunny Srivastava static std::unordered_map<Severity, std::string> sevMap = {
430746eeebSSunny Srivastava     {Severity::INFORMATIONAL,
440746eeebSSunny Srivastava      "xyz.openbmc_project.Logging.Entry.Level.Informational"},
450746eeebSSunny Srivastava     {Severity::DEBUG, "xyz.openbmc_project.Logging.Entry.Level.Debug"},
460746eeebSSunny Srivastava     {Severity::NOTICE, "xyz.openbmc_project.Logging.Entry.Level.Notice"},
470746eeebSSunny Srivastava     {Severity::WARNING, "xyz.openbmc_project.Logging.Entry.Level.Warning"},
480746eeebSSunny Srivastava     {Severity::CRITICAL, "xyz.openbmc_project.Logging.Entry.Level.Critical"},
490746eeebSSunny Srivastava     {Severity::EMERGENCY, "xyz.openbmc_project.Logging.Entry.Level.Emergency"},
500746eeebSSunny Srivastava     {Severity::ERROR, "xyz.openbmc_project.Logging.Entry.Level.Error"},
510746eeebSSunny Srivastava     {Severity::ALERT, "xyz.openbmc_project.Logging.Entry.Level.Alert"}};
520746eeebSSunny Srivastava 
536c71c9dcSSunny Srivastava namespace inventory
546c71c9dcSSunny Srivastava {
556c71c9dcSSunny Srivastava 
566c71c9dcSSunny Srivastava MapperResponse
getObjectSubtreeForInterfaces(const std::string & root,const int32_t depth,const std::vector<std::string> & interfaces)576c71c9dcSSunny Srivastava     getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
586c71c9dcSSunny Srivastava                                   const std::vector<std::string>& interfaces)
596c71c9dcSSunny Srivastava {
606c71c9dcSSunny Srivastava     auto bus = sdbusplus::bus::new_default();
616c71c9dcSSunny Srivastava     auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
626c71c9dcSSunny Srivastava                                           mapperInterface, "GetSubTree");
636c71c9dcSSunny Srivastava     mapperCall.append(root);
646c71c9dcSSunny Srivastava     mapperCall.append(depth);
656c71c9dcSSunny Srivastava     mapperCall.append(interfaces);
666c71c9dcSSunny Srivastava 
676c71c9dcSSunny Srivastava     MapperResponse result = {};
686c71c9dcSSunny Srivastava 
696c71c9dcSSunny Srivastava     try
706c71c9dcSSunny Srivastava     {
716c71c9dcSSunny Srivastava         auto response = bus.call(mapperCall);
726c71c9dcSSunny Srivastava 
736c71c9dcSSunny Srivastava         response.read(result);
746c71c9dcSSunny Srivastava     }
752eb0176cSPatrick Williams     catch (const sdbusplus::exception_t& e)
766c71c9dcSSunny Srivastava     {
776c71c9dcSSunny Srivastava         log<level::ERR>("Error in mapper GetSubTree",
786c71c9dcSSunny Srivastava                         entry("ERROR=%s", e.what()));
796c71c9dcSSunny Srivastava     }
806c71c9dcSSunny Srivastava 
816c71c9dcSSunny Srivastava     return result;
826c71c9dcSSunny Srivastava }
836c71c9dcSSunny Srivastava 
getObject(const std::string & objectPath,const std::vector<std::string> & interfaces)84c6e7ea92SSunny Srivastava MapperGetObjectResponse getObject(const std::string& objectPath,
85c6e7ea92SSunny Srivastava                                   const std::vector<std::string>& interfaces)
86c6e7ea92SSunny Srivastava {
87c6e7ea92SSunny Srivastava     auto bus = sdbusplus::bus::new_default();
88c6e7ea92SSunny Srivastava     auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
89c6e7ea92SSunny Srivastava                                           mapperInterface, "GetObject");
90c6e7ea92SSunny Srivastava     mapperCall.append(objectPath);
91c6e7ea92SSunny Srivastava     mapperCall.append(interfaces);
92c6e7ea92SSunny Srivastava 
93c6e7ea92SSunny Srivastava     MapperGetObjectResponse result = {};
94c6e7ea92SSunny Srivastava 
95c6e7ea92SSunny Srivastava     try
96c6e7ea92SSunny Srivastava     {
97c6e7ea92SSunny Srivastava         auto response = bus.call(mapperCall);
98c6e7ea92SSunny Srivastava 
99c6e7ea92SSunny Srivastava         response.read(result);
100c6e7ea92SSunny Srivastava     }
101c6e7ea92SSunny Srivastava     catch (const sdbusplus::exception_t& e)
102c6e7ea92SSunny Srivastava     {
103c6e7ea92SSunny Srivastava         log<level::ERR>("Error in mapper GetObject",
104c6e7ea92SSunny Srivastava                         entry("ERROR=%s", e.what()));
105c6e7ea92SSunny Srivastava     }
106c6e7ea92SSunny Srivastava 
107c6e7ea92SSunny Srivastava     return result;
108c6e7ea92SSunny Srivastava }
109c6e7ea92SSunny Srivastava 
1106c71c9dcSSunny Srivastava } // namespace inventory
1116c71c9dcSSunny Srivastava 
readUInt16LE(Binary::const_iterator iterator)1126c71c9dcSSunny Srivastava LE2ByteData readUInt16LE(Binary::const_iterator iterator)
1136c71c9dcSSunny Srivastava {
1146c71c9dcSSunny Srivastava     LE2ByteData lowByte = *iterator;
1156c71c9dcSSunny Srivastava     LE2ByteData highByte = *(iterator + 1);
1166c71c9dcSSunny Srivastava     lowByte |= (highByte << 8);
1176c71c9dcSSunny Srivastava     return lowByte;
1186c71c9dcSSunny Srivastava }
1196c71c9dcSSunny Srivastava 
1206c71c9dcSSunny Srivastava /** @brief Encodes a keyword for D-Bus.
1216c71c9dcSSunny Srivastava  */
encodeKeyword(const std::string & kw,const std::string & encoding)122e008432aSPriyanga Ramasamy std::string encodeKeyword(const std::string& kw, const std::string& encoding)
1236c71c9dcSSunny Srivastava {
1246c71c9dcSSunny Srivastava     if (encoding == "MAC")
1256c71c9dcSSunny Srivastava     {
126e008432aSPriyanga Ramasamy         std::string res{};
1276c71c9dcSSunny Srivastava         size_t first = kw[0];
1286c71c9dcSSunny Srivastava         res += toHex(first >> 4);
1296c71c9dcSSunny Srivastava         res += toHex(first & 0x0f);
1306c71c9dcSSunny Srivastava         for (size_t i = 1; i < kw.size(); ++i)
1316c71c9dcSSunny Srivastava         {
1326c71c9dcSSunny Srivastava             res += ":";
1336c71c9dcSSunny Srivastava             res += toHex(kw[i] >> 4);
1346c71c9dcSSunny Srivastava             res += toHex(kw[i] & 0x0f);
1356c71c9dcSSunny Srivastava         }
1366c71c9dcSSunny Srivastava         return res;
1376c71c9dcSSunny Srivastava     }
1386c71c9dcSSunny Srivastava     else if (encoding == "DATE")
1396c71c9dcSSunny Srivastava     {
1406c71c9dcSSunny Srivastava         // Date, represent as
1416c71c9dcSSunny Srivastava         // <year>-<month>-<day> <hour>:<min>
142e008432aSPriyanga Ramasamy         std::string res{};
1436c71c9dcSSunny Srivastava         static constexpr uint8_t skipPrefix = 3;
1446c71c9dcSSunny Srivastava 
1456c71c9dcSSunny Srivastava         auto strItr = kw.begin();
1466c71c9dcSSunny Srivastava         advance(strItr, skipPrefix);
1476c71c9dcSSunny Srivastava         for_each(strItr, kw.end(), [&res](size_t c) { res += c; });
1486c71c9dcSSunny Srivastava 
1496c71c9dcSSunny Srivastava         res.insert(BD_YEAR_END, 1, '-');
1506c71c9dcSSunny Srivastava         res.insert(BD_MONTH_END, 1, '-');
1516c71c9dcSSunny Srivastava         res.insert(BD_DAY_END, 1, ' ');
1526c71c9dcSSunny Srivastava         res.insert(BD_HOUR_END, 1, ':');
1536c71c9dcSSunny Srivastava 
1546c71c9dcSSunny Srivastava         return res;
1556c71c9dcSSunny Srivastava     }
1566c71c9dcSSunny Srivastava     else // default to string encoding
1576c71c9dcSSunny Srivastava     {
158e008432aSPriyanga Ramasamy         return std::string(kw.begin(), kw.end());
1596c71c9dcSSunny Srivastava     }
1606c71c9dcSSunny Srivastava }
1616c71c9dcSSunny Srivastava 
readBusProperty(const std::string & obj,const std::string & inf,const std::string & prop)162e008432aSPriyanga Ramasamy std::string readBusProperty(const std::string& obj, const std::string& inf,
163e008432aSPriyanga Ramasamy                             const std::string& prop)
1646c71c9dcSSunny Srivastava {
1656c71c9dcSSunny Srivastava     std::string propVal{};
1666c71c9dcSSunny Srivastava     std::string object = INVENTORY_PATH + obj;
1676c71c9dcSSunny Srivastava     auto bus = sdbusplus::bus::new_default();
1686c71c9dcSSunny Srivastava     auto properties = bus.new_method_call(
1696c71c9dcSSunny Srivastava         "xyz.openbmc_project.Inventory.Manager", object.c_str(),
1706c71c9dcSSunny Srivastava         "org.freedesktop.DBus.Properties", "Get");
1716c71c9dcSSunny Srivastava     properties.append(inf);
1726c71c9dcSSunny Srivastava     properties.append(prop);
1736c71c9dcSSunny Srivastava     auto result = bus.call(properties);
1746c71c9dcSSunny Srivastava     if (!result.is_method_error())
1756c71c9dcSSunny Srivastava     {
17628abd6e4SSunny Srivastava         inventory::Value val;
1776c71c9dcSSunny Srivastava         result.read(val);
178e008432aSPriyanga Ramasamy         if (auto pVal = std::get_if<Binary>(&val))
1796c71c9dcSSunny Srivastava         {
1806c71c9dcSSunny Srivastava             propVal.assign(reinterpret_cast<const char*>(pVal->data()),
1816c71c9dcSSunny Srivastava                            pVal->size());
1826c71c9dcSSunny Srivastava         }
183e008432aSPriyanga Ramasamy         else if (auto pVal = std::get_if<std::string>(&val))
1846c71c9dcSSunny Srivastava         {
1856c71c9dcSSunny Srivastava             propVal.assign(pVal->data(), pVal->size());
1866c71c9dcSSunny Srivastava         }
18728abd6e4SSunny Srivastava         else if (auto pVal = get_if<bool>(&val))
18828abd6e4SSunny Srivastava         {
18928abd6e4SSunny Srivastava             if (*pVal == false)
19028abd6e4SSunny Srivastava             {
19128abd6e4SSunny Srivastava                 propVal = "false";
19228abd6e4SSunny Srivastava             }
19328abd6e4SSunny Srivastava             else
19428abd6e4SSunny Srivastava             {
19528abd6e4SSunny Srivastava                 propVal = "true";
19628abd6e4SSunny Srivastava             }
19728abd6e4SSunny Srivastava         }
1986c71c9dcSSunny Srivastava     }
1996c71c9dcSSunny Srivastava     return propVal;
2006c71c9dcSSunny Srivastava }
2016c71c9dcSSunny Srivastava 
createPEL(const std::map<std::string,std::string> & additionalData,const Severity & sev,const std::string & errIntf,sd_bus * sdBus)2026c71c9dcSSunny Srivastava void createPEL(const std::map<std::string, std::string>& additionalData,
203a2ddc96eSSunny Srivastava                const Severity& sev, const std::string& errIntf, sd_bus* sdBus)
204a2ddc96eSSunny Srivastava {
205a2ddc96eSSunny Srivastava     // This pointer will be NULL in case the call is made from ibm-read-vpd. In
206a2ddc96eSSunny Srivastava     // that case a sync call will do.
207a2ddc96eSSunny Srivastava     if (sdBus == nullptr)
208a2ddc96eSSunny Srivastava     {
209a2ddc96eSSunny Srivastava         createSyncPEL(additionalData, sev, errIntf);
210a2ddc96eSSunny Srivastava     }
211a2ddc96eSSunny Srivastava     else
212a2ddc96eSSunny Srivastava     {
213a2ddc96eSSunny Srivastava         std::string errDescription{};
214a2ddc96eSSunny Srivastava         auto pos = additionalData.find("DESCRIPTION");
215a2ddc96eSSunny Srivastava         if (pos != additionalData.end())
216a2ddc96eSSunny Srivastava         {
217a2ddc96eSSunny Srivastava             errDescription = pos->second;
218a2ddc96eSSunny Srivastava         }
219a2ddc96eSSunny Srivastava         else
220a2ddc96eSSunny Srivastava         {
221a2ddc96eSSunny Srivastava             errDescription = "Description field missing in additional data";
222a2ddc96eSSunny Srivastava         }
223a2ddc96eSSunny Srivastava 
224a2ddc96eSSunny Srivastava         std::string pelSeverity =
225a2ddc96eSSunny Srivastava             "xyz.openbmc_project.Logging.Entry.Level.Error";
226a2ddc96eSSunny Srivastava         auto itr = sevMap.find(sev);
227a2ddc96eSSunny Srivastava         if (itr != sevMap.end())
228a2ddc96eSSunny Srivastava         {
229a2ddc96eSSunny Srivastava             pelSeverity = itr->second;
230a2ddc96eSSunny Srivastava         }
231a2ddc96eSSunny Srivastava 
232a2ddc96eSSunny Srivastava         // Implies this is a call from Manager. Hence we need to make an async
233a2ddc96eSSunny Srivastava         // call to avoid deadlock with Phosphor-logging.
234a2ddc96eSSunny Srivastava         auto rc = sd_bus_call_method_async(
235a2ddc96eSSunny Srivastava             sdBus, NULL, loggerService, loggerObjectPath, loggerCreateInterface,
236a2ddc96eSSunny Srivastava             "Create", NULL, NULL, "ssa{ss}", errIntf.c_str(),
237a2ddc96eSSunny Srivastava             pelSeverity.c_str(), 1, "DESCRIPTION", errDescription.c_str());
238a2ddc96eSSunny Srivastava 
239a2ddc96eSSunny Srivastava         if (rc < 0)
240a2ddc96eSSunny Srivastava         {
241a2ddc96eSSunny Srivastava             log<level::ERR>("Error calling sd_bus_call_method_async",
242a2ddc96eSSunny Srivastava                             entry("RC=%d", rc), entry("MSG=%s", strerror(-rc)));
243a2ddc96eSSunny Srivastava         }
244a2ddc96eSSunny Srivastava     }
245a2ddc96eSSunny Srivastava }
246a2ddc96eSSunny Srivastava 
createSyncPEL(const std::map<std::string,std::string> & additionalData,const Severity & sev,const std::string & errIntf)247a2ddc96eSSunny Srivastava void createSyncPEL(const std::map<std::string, std::string>& additionalData,
2480746eeebSSunny Srivastava                    const Severity& sev, const std::string& errIntf)
2496c71c9dcSSunny Srivastava {
2506c71c9dcSSunny Srivastava     try
2516c71c9dcSSunny Srivastava     {
2520746eeebSSunny Srivastava         std::string pelSeverity =
2530746eeebSSunny Srivastava             "xyz.openbmc_project.Logging.Entry.Level.Error";
2546c71c9dcSSunny Srivastava         auto bus = sdbusplus::bus::new_default();
2556c71c9dcSSunny Srivastava         auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
2566c71c9dcSSunny Srivastava         auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
2576c71c9dcSSunny Srivastava                                           loggerCreateInterface, "Create");
2586c71c9dcSSunny Srivastava 
2590746eeebSSunny Srivastava         auto itr = sevMap.find(sev);
2600746eeebSSunny Srivastava         if (itr != sevMap.end())
2610746eeebSSunny Srivastava         {
2620746eeebSSunny Srivastava             pelSeverity = itr->second;
2630746eeebSSunny Srivastava         }
2640746eeebSSunny Srivastava 
2650746eeebSSunny Srivastava         method.append(errIntf, pelSeverity, additionalData);
2666c71c9dcSSunny Srivastava         auto resp = bus.call(method);
2676c71c9dcSSunny Srivastava     }
2682eb0176cSPatrick Williams     catch (const sdbusplus::exception_t& e)
2696c71c9dcSSunny Srivastava     {
2705ef6ccc0SSunny Srivastava         std::cerr << "Dbus call to phosphor-logging Create failed. Reason:"
2715ef6ccc0SSunny Srivastava                   << e.what();
2726c71c9dcSSunny Srivastava     }
2736c71c9dcSSunny Srivastava }
2746c71c9dcSSunny Srivastava 
getVpdFilePath(const std::string & jsonFile,const std::string & ObjPath)275e008432aSPriyanga Ramasamy inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile,
2766c71c9dcSSunny Srivastava                                       const std::string& ObjPath)
2776c71c9dcSSunny Srivastava {
278e008432aSPriyanga Ramasamy     std::ifstream inventoryJson(jsonFile);
2796c71c9dcSSunny Srivastava     const auto& jsonObject = json::parse(inventoryJson);
2806c71c9dcSSunny Srivastava     inventory::VPDfilepath filePath{};
2816c71c9dcSSunny Srivastava 
2826c71c9dcSSunny Srivastava     if (jsonObject.find("frus") == jsonObject.end())
2836c71c9dcSSunny Srivastava     {
2846c71c9dcSSunny Srivastava         throw(VpdJsonException(
2856c71c9dcSSunny Srivastava             "Invalid JSON structure - frus{} object not found in ", jsonFile));
2866c71c9dcSSunny Srivastava     }
2876c71c9dcSSunny Srivastava 
2886c71c9dcSSunny Srivastava     const nlohmann::json& groupFRUS =
2896c71c9dcSSunny Srivastava         jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
2906c71c9dcSSunny Srivastava     for (const auto& itemFRUS : groupFRUS.items())
2916c71c9dcSSunny Srivastava     {
2926c71c9dcSSunny Srivastava         const std::vector<nlohmann::json>& groupEEPROM =
2936c71c9dcSSunny Srivastava             itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
2946c71c9dcSSunny Srivastava         for (const auto& itemEEPROM : groupEEPROM)
2956c71c9dcSSunny Srivastava         {
2966c71c9dcSSunny Srivastava             if (itemEEPROM["inventoryPath"]
2976c71c9dcSSunny Srivastava                     .get_ref<const nlohmann::json::string_t&>() == ObjPath)
2986c71c9dcSSunny Srivastava             {
2996c71c9dcSSunny Srivastava                 filePath = itemFRUS.key();
3006c71c9dcSSunny Srivastava                 return filePath;
3016c71c9dcSSunny Srivastava             }
3026c71c9dcSSunny Srivastava         }
3036c71c9dcSSunny Srivastava     }
3046c71c9dcSSunny Srivastava 
3056c71c9dcSSunny Srivastava     return filePath;
3066c71c9dcSSunny Srivastava }
3076c71c9dcSSunny Srivastava 
isPathInJson(const std::string & eepromPath)3086c71c9dcSSunny Srivastava bool isPathInJson(const std::string& eepromPath)
3096c71c9dcSSunny Srivastava {
3106c71c9dcSSunny Srivastava     bool present = false;
311e008432aSPriyanga Ramasamy     std::ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
3126c71c9dcSSunny Srivastava 
3136c71c9dcSSunny Srivastava     try
3146c71c9dcSSunny Srivastava     {
3156c71c9dcSSunny Srivastava         auto js = json::parse(inventoryJson);
3166c71c9dcSSunny Srivastava         if (js.find("frus") == js.end())
3176c71c9dcSSunny Srivastava         {
3186c71c9dcSSunny Srivastava             throw(VpdJsonException(
3196c71c9dcSSunny Srivastava                 "Invalid JSON structure - frus{} object not found in ",
3206c71c9dcSSunny Srivastava                 INVENTORY_JSON_SYM_LINK));
3216c71c9dcSSunny Srivastava         }
3226c71c9dcSSunny Srivastava         json fruJson = js["frus"];
3236c71c9dcSSunny Srivastava 
3246c71c9dcSSunny Srivastava         if (fruJson.find(eepromPath) != fruJson.end())
3256c71c9dcSSunny Srivastava         {
3266c71c9dcSSunny Srivastava             present = true;
3276c71c9dcSSunny Srivastava         }
3286c71c9dcSSunny Srivastava     }
3298e15b93aSPatrick Williams     catch (const json::parse_error& ex)
3306c71c9dcSSunny Srivastava     {
3316c71c9dcSSunny Srivastava         throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
3326c71c9dcSSunny Srivastava     }
3336c71c9dcSSunny Srivastava     return present;
3346c71c9dcSSunny Srivastava }
3356c71c9dcSSunny Srivastava 
isRecKwInDbusJson(const std::string & recordName,const std::string & keyword)3366c71c9dcSSunny Srivastava bool isRecKwInDbusJson(const std::string& recordName,
3376c71c9dcSSunny Srivastava                        const std::string& keyword)
3386c71c9dcSSunny Srivastava {
339e008432aSPriyanga Ramasamy     std::ifstream propertyJson(DBUS_PROP_JSON);
3406c71c9dcSSunny Srivastava     json dbusProperty;
3416c71c9dcSSunny Srivastava     bool present = false;
3426c71c9dcSSunny Srivastava 
3436c71c9dcSSunny Srivastava     if (propertyJson.is_open())
3446c71c9dcSSunny Srivastava     {
3456c71c9dcSSunny Srivastava         try
3466c71c9dcSSunny Srivastava         {
3476c71c9dcSSunny Srivastava             auto dbusPropertyJson = json::parse(propertyJson);
3486c71c9dcSSunny Srivastava             if (dbusPropertyJson.find("dbusProperties") ==
3496c71c9dcSSunny Srivastava                 dbusPropertyJson.end())
3506c71c9dcSSunny Srivastava             {
3516c71c9dcSSunny Srivastava                 throw(VpdJsonException("dbusProperties{} object not found in "
3526c71c9dcSSunny Srivastava                                        "DbusProperties json : ",
3536c71c9dcSSunny Srivastava                                        DBUS_PROP_JSON));
3546c71c9dcSSunny Srivastava             }
3556c71c9dcSSunny Srivastava 
3566c71c9dcSSunny Srivastava             dbusProperty = dbusPropertyJson["dbusProperties"];
3576c71c9dcSSunny Srivastava             if (dbusProperty.contains(recordName))
3586c71c9dcSSunny Srivastava             {
359e008432aSPriyanga Ramasamy                 const std::vector<std::string>& kwdsToPublish =
360e008432aSPriyanga Ramasamy                     dbusProperty[recordName];
3616c71c9dcSSunny Srivastava                 if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
3626c71c9dcSSunny Srivastava                     kwdsToPublish.end()) // present
3636c71c9dcSSunny Srivastava                 {
3646c71c9dcSSunny Srivastava                     present = true;
3656c71c9dcSSunny Srivastava                 }
3666c71c9dcSSunny Srivastava             }
3676c71c9dcSSunny Srivastava         }
3688e15b93aSPatrick Williams         catch (const json::parse_error& ex)
3696c71c9dcSSunny Srivastava         {
3706c71c9dcSSunny Srivastava             throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
3716c71c9dcSSunny Srivastava         }
3726c71c9dcSSunny Srivastava     }
3736c71c9dcSSunny Srivastava     else
3746c71c9dcSSunny Srivastava     {
3756c71c9dcSSunny Srivastava         // If dbus properties json is not available, we assume the given
3766c71c9dcSSunny Srivastava         // record-keyword is part of dbus-properties json. So setting the bool
3776c71c9dcSSunny Srivastava         // variable to true.
3786c71c9dcSSunny Srivastava         present = true;
3796c71c9dcSSunny Srivastava     }
3806c71c9dcSSunny Srivastava     return present;
3816c71c9dcSSunny Srivastava }
3826c71c9dcSSunny Srivastava 
vpdTypeCheck(const Binary & vpdVector)3836c71c9dcSSunny Srivastava vpdType vpdTypeCheck(const Binary& vpdVector)
3846c71c9dcSSunny Srivastava {
3856c71c9dcSSunny Srivastava     // Read first 3 Bytes to check the 11S bar code format
3866c71c9dcSSunny Srivastava     std::string is11SFormat = "";
3876c71c9dcSSunny Srivastava     for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
3886c71c9dcSSunny Srivastava     {
3896c71c9dcSSunny Srivastava         is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
3906c71c9dcSSunny Srivastava     }
3916c71c9dcSSunny Srivastava 
3926c71c9dcSSunny Srivastava     if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
3936c71c9dcSSunny Srivastava     {
3946c71c9dcSSunny Srivastava         // IPZ VPD FORMAT
3956c71c9dcSSunny Srivastava         return vpdType::IPZ_VPD;
3966c71c9dcSSunny Srivastava     }
3976c71c9dcSSunny Srivastava     else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
3986c71c9dcSSunny Srivastava     {
3996c71c9dcSSunny Srivastava         // KEYWORD VPD FORMAT
4006c71c9dcSSunny Srivastava         return vpdType::KEYWORD_VPD;
4016c71c9dcSSunny Srivastava     }
4026555e7efSjinuthomas     else if (((vpdVector[SPD_BYTE_3] & SPD_BYTE_BIT_0_3_MASK) ==
4036555e7efSjinuthomas               SPD_MODULE_TYPE_DDIMM) &&
4040abbb9c9Sjinuthomas              (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0))
4056c71c9dcSSunny Srivastava     {
4066555e7efSjinuthomas         // DDIMM Memory VPD format
4076555e7efSjinuthomas         if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR5)
4086555e7efSjinuthomas         {
4096555e7efSjinuthomas             return vpdType::DDR5_DDIMM_MEMORY_VPD;
4106555e7efSjinuthomas         }
4116555e7efSjinuthomas         else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR4)
4126555e7efSjinuthomas         {
4136555e7efSjinuthomas             return vpdType::DDR4_DDIMM_MEMORY_VPD;
4146555e7efSjinuthomas         }
4156555e7efSjinuthomas     }
4166555e7efSjinuthomas     else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR5)
4176555e7efSjinuthomas     {
4186555e7efSjinuthomas         // ISDIMM Memory VPD format
4196555e7efSjinuthomas         return vpdType::DDR5_ISDIMM_MEMORY_VPD;
4206555e7efSjinuthomas     }
4216555e7efSjinuthomas     else if ((vpdVector[SPD_BYTE_2] & SPD_BYTE_MASK) == SPD_DRAM_TYPE_DDR4)
4226555e7efSjinuthomas     {
4236555e7efSjinuthomas         // ISDIMM Memory VPD format
4246555e7efSjinuthomas         return vpdType::DDR4_ISDIMM_MEMORY_VPD;
4256c71c9dcSSunny Srivastava     }
4266c71c9dcSSunny Srivastava 
4276c71c9dcSSunny Srivastava     // INVALID VPD FORMAT
4286c71c9dcSSunny Srivastava     return vpdType::INVALID_VPD_FORMAT;
4296c71c9dcSSunny Srivastava }
4306c71c9dcSSunny Srivastava 
getIM(const Parsed & vpdMap)431e008432aSPriyanga Ramasamy const std::string getIM(const Parsed& vpdMap)
432f05effdbSAlpana Kumari {
433f05effdbSAlpana Kumari     Binary imVal;
434f05effdbSAlpana Kumari     auto property = vpdMap.find("VSBP");
435f05effdbSAlpana Kumari     if (property != vpdMap.end())
436f05effdbSAlpana Kumari     {
437f05effdbSAlpana Kumari         auto kw = (property->second).find("IM");
438f05effdbSAlpana Kumari         if (kw != (property->second).end())
439f05effdbSAlpana Kumari         {
440f05effdbSAlpana Kumari             copy(kw->second.begin(), kw->second.end(), back_inserter(imVal));
441f05effdbSAlpana Kumari         }
442f05effdbSAlpana Kumari     }
443f05effdbSAlpana Kumari 
444e008432aSPriyanga Ramasamy     std::ostringstream oss;
445f05effdbSAlpana Kumari     for (auto& i : imVal)
446f05effdbSAlpana Kumari     {
447e008432aSPriyanga Ramasamy         oss << std::setw(2) << std::setfill('0') << std::hex
448e008432aSPriyanga Ramasamy             << static_cast<int>(i);
449f05effdbSAlpana Kumari     }
450f05effdbSAlpana Kumari 
451f05effdbSAlpana Kumari     return oss.str();
452f05effdbSAlpana Kumari }
453f05effdbSAlpana Kumari 
getHW(const Parsed & vpdMap)454e008432aSPriyanga Ramasamy const std::string getHW(const Parsed& vpdMap)
455f05effdbSAlpana Kumari {
456f05effdbSAlpana Kumari     Binary hwVal;
457f05effdbSAlpana Kumari     auto prop = vpdMap.find("VINI");
458f05effdbSAlpana Kumari     if (prop != vpdMap.end())
459f05effdbSAlpana Kumari     {
460f05effdbSAlpana Kumari         auto kw = (prop->second).find("HW");
461f05effdbSAlpana Kumari         if (kw != (prop->second).end())
462f05effdbSAlpana Kumari         {
463f05effdbSAlpana Kumari             copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal));
464f05effdbSAlpana Kumari         }
465f05effdbSAlpana Kumari     }
466f05effdbSAlpana Kumari 
46788d2ae82SAlpana Kumari     // The planar pass only comes from the LSB of the HW keyword,
46888d2ae82SAlpana Kumari     // where as the MSB is used for other purposes such as signifying clock
46988d2ae82SAlpana Kumari     // termination.
47088d2ae82SAlpana Kumari     hwVal[0] = 0x00;
47188d2ae82SAlpana Kumari 
472e008432aSPriyanga Ramasamy     std::ostringstream hwString;
473f05effdbSAlpana Kumari     for (auto& i : hwVal)
474f05effdbSAlpana Kumari     {
475e008432aSPriyanga Ramasamy         hwString << std::setw(2) << std::setfill('0') << std::hex
476e008432aSPriyanga Ramasamy                  << static_cast<int>(i);
477f05effdbSAlpana Kumari     }
478f05effdbSAlpana Kumari 
479f05effdbSAlpana Kumari     return hwString.str();
480f05effdbSAlpana Kumari }
481f05effdbSAlpana Kumari 
getSystemsJson(const Parsed & vpdMap)482e008432aSPriyanga Ramasamy std::string getSystemsJson(const Parsed& vpdMap)
483f05effdbSAlpana Kumari {
484e008432aSPriyanga Ramasamy     std::string jsonPath = "/usr/share/vpd/";
485e008432aSPriyanga Ramasamy     std::string jsonName{};
486f05effdbSAlpana Kumari 
487e008432aSPriyanga Ramasamy     std::ifstream systemJson(SYSTEM_JSON);
488f05effdbSAlpana Kumari     if (!systemJson)
489f05effdbSAlpana Kumari     {
490f05effdbSAlpana Kumari         throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON)));
491f05effdbSAlpana Kumari     }
492f05effdbSAlpana Kumari 
493f05effdbSAlpana Kumari     try
494f05effdbSAlpana Kumari     {
495f05effdbSAlpana Kumari         auto js = json::parse(systemJson);
496f05effdbSAlpana Kumari 
497e008432aSPriyanga Ramasamy         std::string hwKeyword = getHW(vpdMap);
498e008432aSPriyanga Ramasamy         const std::string imKeyword = getIM(vpdMap);
499f05effdbSAlpana Kumari 
5001b026119SAlpana Kumari         transform(hwKeyword.begin(), hwKeyword.end(), hwKeyword.begin(),
5011b026119SAlpana Kumari                   ::toupper);
5021b026119SAlpana Kumari 
503f05effdbSAlpana Kumari         if (js.find("system") == js.end())
504f05effdbSAlpana Kumari         {
505e008432aSPriyanga Ramasamy             throw std::runtime_error("Invalid systems Json");
506f05effdbSAlpana Kumari         }
507f05effdbSAlpana Kumari 
508f05effdbSAlpana Kumari         if (js["system"].find(imKeyword) == js["system"].end())
509f05effdbSAlpana Kumari         {
510e008432aSPriyanga Ramasamy             throw std::runtime_error(
511f05effdbSAlpana Kumari                 "Invalid system. This system type is not present "
512f05effdbSAlpana Kumari                 "in the systemsJson. IM: " +
513f05effdbSAlpana Kumari                 imKeyword);
514f05effdbSAlpana Kumari         }
515f05effdbSAlpana Kumari 
516f05effdbSAlpana Kumari         if ((js["system"][imKeyword].find("constraint") !=
517f05effdbSAlpana Kumari              js["system"][imKeyword].end()) &&
5181b026119SAlpana Kumari             js["system"][imKeyword]["constraint"].find("HW") !=
5191b026119SAlpana Kumari                 js["system"][imKeyword]["constraint"].end())
5201b026119SAlpana Kumari         {
5211b026119SAlpana Kumari             // collect hw versions from json, and check hwKeyword  is part of it
5221b026119SAlpana Kumari             // if hwKeyword is found there then load respective json
5231b026119SAlpana Kumari             // otherwise load default one.
5241b026119SAlpana Kumari             for (const auto& hwVersion :
5251b026119SAlpana Kumari                  js["system"][imKeyword]["constraint"]["HW"])
5261b026119SAlpana Kumari             {
527e008432aSPriyanga Ramasamy                 std::string hw = hwVersion;
5281b026119SAlpana Kumari                 transform(hw.begin(), hw.end(), hw.begin(), ::toupper);
5291b026119SAlpana Kumari 
5301b026119SAlpana Kumari                 if (hw == hwKeyword)
531f05effdbSAlpana Kumari                 {
532f05effdbSAlpana Kumari                     jsonName = js["system"][imKeyword]["constraint"]["json"];
5331b026119SAlpana Kumari                     break;
5341b026119SAlpana Kumari                 }
5351b026119SAlpana Kumari             }
5361b026119SAlpana Kumari 
5371b026119SAlpana Kumari             if (jsonName.empty() && js["system"][imKeyword].find("default") !=
5381b026119SAlpana Kumari                                         js["system"][imKeyword].end())
5391b026119SAlpana Kumari             {
5401b026119SAlpana Kumari                 jsonName = js["system"][imKeyword]["default"];
5411b026119SAlpana Kumari             }
542f05effdbSAlpana Kumari         }
543f05effdbSAlpana Kumari         else if (js["system"][imKeyword].find("default") !=
544f05effdbSAlpana Kumari                  js["system"][imKeyword].end())
545f05effdbSAlpana Kumari         {
546f05effdbSAlpana Kumari             jsonName = js["system"][imKeyword]["default"];
547f05effdbSAlpana Kumari         }
548f05effdbSAlpana Kumari         else
549f05effdbSAlpana Kumari         {
550e008432aSPriyanga Ramasamy             throw std::runtime_error(
551f05effdbSAlpana Kumari                 "Bad System json. Neither constraint nor default found");
552f05effdbSAlpana Kumari         }
553f05effdbSAlpana Kumari 
554f05effdbSAlpana Kumari         jsonPath += jsonName;
555f05effdbSAlpana Kumari     }
556f05effdbSAlpana Kumari 
5578e15b93aSPatrick Williams     catch (const json::parse_error& ex)
558f05effdbSAlpana Kumari     {
559f05effdbSAlpana Kumari         throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON));
560f05effdbSAlpana Kumari     }
561f05effdbSAlpana Kumari     return jsonPath;
562f05effdbSAlpana Kumari }
563f05effdbSAlpana Kumari 
udevToGenericPath(std::string & file,const std::string & driver)564f457a3efSjinuthomas void udevToGenericPath(std::string& file, const std::string& driver)
565647868edSPriyangaRamasamy {
566647868edSPriyangaRamasamy     // Sample udevEvent i2c path :
567647868edSPriyangaRamasamy     // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem"
568647868edSPriyangaRamasamy     // find if the path contains the word i2c in it.
569e008432aSPriyanga Ramasamy     if (file.find("i2c") != std::string::npos)
570647868edSPriyangaRamasamy     {
571e008432aSPriyanga Ramasamy         std::string i2cBusAddr{};
572647868edSPriyangaRamasamy 
573647868edSPriyangaRamasamy         // Every udev i2c path should have the common pattern
574647868edSPriyangaRamasamy         // "i2c-bus_number/bus_number-vpd_address". Search for
575647868edSPriyangaRamasamy         // "bus_number-vpd_address".
576e008432aSPriyanga Ramasamy         std::regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})");
577e008432aSPriyanga Ramasamy         std::smatch match;
578e008432aSPriyanga Ramasamy         if (std::regex_search(file, match, i2cPattern))
579647868edSPriyangaRamasamy         {
580647868edSPriyangaRamasamy             i2cBusAddr = match.str(3);
581647868edSPriyangaRamasamy         }
582647868edSPriyangaRamasamy         else
583647868edSPriyangaRamasamy         {
584e008432aSPriyanga Ramasamy             std::cerr << "The given udev path < " << file
585647868edSPriyangaRamasamy                       << " > doesn't match the required pattern. Skipping VPD "
586647868edSPriyangaRamasamy                          "collection."
587e008432aSPriyanga Ramasamy                       << std::endl;
588647868edSPriyangaRamasamy             exit(EXIT_SUCCESS);
589647868edSPriyangaRamasamy         }
590647868edSPriyangaRamasamy         // Forming the generic file path
591f457a3efSjinuthomas         file = i2cPathPrefix + driver + "/" + i2cBusAddr + "/eeprom";
592647868edSPriyangaRamasamy     }
593647868edSPriyangaRamasamy     // Sample udevEvent spi path :
594647868edSPriyangaRamasamy     // "/sys/devices/platform/ahb/ahb:apb/1e79b000.fsi/fsi-master/fsi0/slave@00:00/00:00:00:04/spi_master/spi2/spi2.0/spi2.00/nvmem"
595647868edSPriyangaRamasamy     // find if the path contains the word spi in it.
596e008432aSPriyanga Ramasamy     else if (file.find("spi") != std::string::npos)
597647868edSPriyangaRamasamy     {
598647868edSPriyangaRamasamy         // Every udev spi path will have common pattern "spi<Digit>/", which
599647868edSPriyangaRamasamy         // describes the spi bus number at which the fru is connected; Followed
600647868edSPriyangaRamasamy         // by a slash following the vpd address of the fru. Taking the above
601647868edSPriyangaRamasamy         // input as a common key, we try to search for the pattern "spi<Digit>/"
602647868edSPriyangaRamasamy         // using regular expression.
603e008432aSPriyanga Ramasamy         std::regex spiPattern("((spi)[0-9]+)(\\/)");
604e008432aSPriyanga Ramasamy         std::string spiBus{};
605e008432aSPriyanga Ramasamy         std::smatch match;
606e008432aSPriyanga Ramasamy         if (std::regex_search(file, match, spiPattern))
607647868edSPriyangaRamasamy         {
608647868edSPriyangaRamasamy             spiBus = match.str(1);
609647868edSPriyangaRamasamy         }
610647868edSPriyangaRamasamy         else
611647868edSPriyangaRamasamy         {
612e008432aSPriyanga Ramasamy             std::cerr << "The given udev path < " << file
613647868edSPriyangaRamasamy                       << " > doesn't match the required pattern. Skipping VPD "
614647868edSPriyangaRamasamy                          "collection."
615e008432aSPriyanga Ramasamy                       << std::endl;
616647868edSPriyangaRamasamy             exit(EXIT_SUCCESS);
617647868edSPriyangaRamasamy         }
618647868edSPriyangaRamasamy         // Forming the generic path
619f457a3efSjinuthomas         file = spiPathPrefix + driver + "/" + spiBus + ".0/eeprom";
620647868edSPriyangaRamasamy     }
621647868edSPriyangaRamasamy     else
622647868edSPriyangaRamasamy     {
623e008432aSPriyanga Ramasamy         std::cerr << "\n The given EEPROM path < " << file
624647868edSPriyangaRamasamy                   << " > is not valid. It's neither I2C nor "
625647868edSPriyangaRamasamy                      "SPI path. Skipping VPD collection.."
626e008432aSPriyanga Ramasamy                   << std::endl;
627647868edSPriyangaRamasamy         exit(EXIT_SUCCESS);
628647868edSPriyangaRamasamy     }
629647868edSPriyangaRamasamy }
getBadVpdName(const std::string & file)630e008432aSPriyanga Ramasamy std::string getBadVpdName(const std::string& file)
631c2fe40f8SPriyangaRamasamy {
632e008432aSPriyanga Ramasamy     std::string badVpd = BAD_VPD_DIR;
633e008432aSPriyanga Ramasamy     if (file.find("i2c") != std::string::npos)
634c2fe40f8SPriyangaRamasamy     {
635c2fe40f8SPriyangaRamasamy         badVpd += "i2c-";
636e008432aSPriyanga Ramasamy         std::regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/");
637e008432aSPriyanga Ramasamy         std::smatch match;
638e008432aSPriyanga Ramasamy         if (std::regex_search(file, match, i2cPattern))
639c2fe40f8SPriyangaRamasamy         {
640c2fe40f8SPriyangaRamasamy             badVpd += match.str(2);
641c2fe40f8SPriyangaRamasamy         }
642c2fe40f8SPriyangaRamasamy     }
643e008432aSPriyanga Ramasamy     else if (file.find("spi") != std::string::npos)
644c2fe40f8SPriyangaRamasamy     {
645e008432aSPriyanga Ramasamy         std::regex spiPattern("((spi)[0-9]+)(.0)");
646e008432aSPriyanga Ramasamy         std::smatch match;
647e008432aSPriyanga Ramasamy         if (std::regex_search(file, match, spiPattern))
648c2fe40f8SPriyangaRamasamy         {
649c2fe40f8SPriyangaRamasamy             badVpd += match.str(1);
650c2fe40f8SPriyangaRamasamy         }
651c2fe40f8SPriyangaRamasamy     }
652c2fe40f8SPriyangaRamasamy     return badVpd;
653c2fe40f8SPriyangaRamasamy }
654c2fe40f8SPriyangaRamasamy 
dumpBadVpd(const std::string & file,const Binary & vpdVector)655e008432aSPriyanga Ramasamy void dumpBadVpd(const std::string& file, const Binary& vpdVector)
656c2fe40f8SPriyangaRamasamy {
657c2fe40f8SPriyangaRamasamy     fs::path badVpdDir = BAD_VPD_DIR;
658c2fe40f8SPriyangaRamasamy     fs::create_directory(badVpdDir);
659e008432aSPriyanga Ramasamy     std::string badVpdPath = getBadVpdName(file);
660c2fe40f8SPriyangaRamasamy     if (fs::exists(badVpdPath))
661c2fe40f8SPriyangaRamasamy     {
662c2fe40f8SPriyangaRamasamy         std::error_code ec;
663c2fe40f8SPriyangaRamasamy         fs::remove(badVpdPath, ec);
664c2fe40f8SPriyangaRamasamy         if (ec) // error code
665c2fe40f8SPriyangaRamasamy         {
666e008432aSPriyanga Ramasamy             std::string error = "Error removing the existing broken vpd in ";
667c2fe40f8SPriyangaRamasamy             error += badVpdPath;
668c2fe40f8SPriyangaRamasamy             error += ". Error code : ";
669c2fe40f8SPriyangaRamasamy             error += ec.value();
670c2fe40f8SPriyangaRamasamy             error += ". Error message : ";
671c2fe40f8SPriyangaRamasamy             error += ec.message();
672e008432aSPriyanga Ramasamy             throw std::runtime_error(error);
673c2fe40f8SPriyangaRamasamy         }
674c2fe40f8SPriyangaRamasamy     }
675e008432aSPriyanga Ramasamy     std::ofstream badVpdFileStream(badVpdPath, std::ofstream::binary);
676c2fe40f8SPriyangaRamasamy     if (!badVpdFileStream)
677c2fe40f8SPriyangaRamasamy     {
678e008432aSPriyanga Ramasamy         throw std::runtime_error(
679e008432aSPriyanga Ramasamy             "Failed to open bad vpd file path in /tmp/bad-vpd. "
680c2fe40f8SPriyangaRamasamy             "Unable to dump the broken/bad vpd file.");
681c2fe40f8SPriyangaRamasamy     }
682c2fe40f8SPriyangaRamasamy     badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
683c2fe40f8SPriyangaRamasamy                            vpdVector.size());
684c2fe40f8SPriyangaRamasamy }
6857ce68724Salpana07 
getKwVal(const Parsed & vpdMap,const std::string & rec,const std::string & kwd)686e008432aSPriyanga Ramasamy const std::string getKwVal(const Parsed& vpdMap, const std::string& rec,
687e008432aSPriyanga Ramasamy                            const std::string& kwd)
6887ce68724Salpana07 {
689e008432aSPriyanga Ramasamy     std::string kwVal{};
6907ce68724Salpana07 
6917ce68724Salpana07     auto findRec = vpdMap.find(rec);
6927ce68724Salpana07 
6937ce68724Salpana07     // check if record is found in map we got by parser
6947ce68724Salpana07     if (findRec != vpdMap.end())
6957ce68724Salpana07     {
6967ce68724Salpana07         auto findKwd = findRec->second.find(kwd);
6977ce68724Salpana07 
6987ce68724Salpana07         if (findKwd != findRec->second.end())
6997ce68724Salpana07         {
7007ce68724Salpana07             kwVal = findKwd->second;
7017ce68724Salpana07         }
70237992a65SSunny Srivastava         else
70337992a65SSunny Srivastava         {
70437992a65SSunny Srivastava             std::cout << "Keyword not found" << std::endl;
70537992a65SSunny Srivastava         }
70637992a65SSunny Srivastava     }
70737992a65SSunny Srivastava     else
70837992a65SSunny Srivastava     {
70937992a65SSunny Srivastava         std::cerr << "Record not found" << std::endl;
7107ce68724Salpana07     }
7117ce68724Salpana07 
7127ce68724Salpana07     return kwVal;
7137ce68724Salpana07 }
7147ce68724Salpana07 
hexString(const std::variant<Binary,std::string> & kw)71563639101SGiridhariKrishnan std::string hexString(const std::variant<Binary, std::string>& kw)
71663639101SGiridhariKrishnan {
71763639101SGiridhariKrishnan     std::string hexString;
71863639101SGiridhariKrishnan     std::visit(
71963639101SGiridhariKrishnan         [&hexString](auto&& kw) {
720e008432aSPriyanga Ramasamy             std::stringstream ss;
721e008432aSPriyanga Ramasamy             std::string hexRep = "0x";
72202434931SPriyanga Ramasamy             ss << hexRep;
723b498cd3cSgirik             for (auto& kwVal : kw)
724b498cd3cSgirik             {
72563639101SGiridhariKrishnan                 ss << std::setfill('0') << std::setw(2) << std::hex
72663639101SGiridhariKrishnan                    << static_cast<int>(kwVal);
72702434931SPriyanga Ramasamy             }
728b498cd3cSgirik             hexString = ss.str();
72963639101SGiridhariKrishnan         },
73063639101SGiridhariKrishnan         kw);
73163639101SGiridhariKrishnan     return hexString;
732c9ecf8eaSPriyanga Ramasamy }
733c9ecf8eaSPriyanga Ramasamy 
getPrintableValue(const std::variant<Binary,std::string> & kwVal)73463639101SGiridhariKrishnan std::string getPrintableValue(const std::variant<Binary, std::string>& kwVal)
735c9ecf8eaSPriyanga Ramasamy {
73663639101SGiridhariKrishnan     std::string kwString{};
73763639101SGiridhariKrishnan     std::visit(
73863639101SGiridhariKrishnan         [&kwString](auto&& kwVal) {
73963639101SGiridhariKrishnan             const auto it =
74063639101SGiridhariKrishnan                 std::find_if(kwVal.begin(), kwVal.end(),
74163639101SGiridhariKrishnan                              [](const auto& kw) { return !isprint(kw); });
74263639101SGiridhariKrishnan             if (it != kwVal.end())
743c9ecf8eaSPriyanga Ramasamy             {
74463639101SGiridhariKrishnan                 kwString = hexString(kwVal);
74502434931SPriyanga Ramasamy             }
74602434931SPriyanga Ramasamy             else
74702434931SPriyanga Ramasamy             {
74863639101SGiridhariKrishnan                 kwString = std::string(kwVal.begin(), kwVal.end());
74902434931SPriyanga Ramasamy             }
75063639101SGiridhariKrishnan         },
75163639101SGiridhariKrishnan         kwVal);
75263639101SGiridhariKrishnan     return kwString;
75302434931SPriyanga Ramasamy }
75402434931SPriyanga Ramasamy 
executePostFailAction(const nlohmann::json & json,const std::string & file)755e008432aSPriyanga Ramasamy void executePostFailAction(const nlohmann::json& json, const std::string& file)
756735dee9bSAlpana Kumari {
757735dee9bSAlpana Kumari     if ((json["frus"][file].at(0)).find("postActionFail") ==
758735dee9bSAlpana Kumari         json["frus"][file].at(0).end())
759735dee9bSAlpana Kumari     {
760735dee9bSAlpana Kumari         return;
761735dee9bSAlpana Kumari     }
762735dee9bSAlpana Kumari 
763735dee9bSAlpana Kumari     uint8_t pinValue = 0;
764e008432aSPriyanga Ramasamy     std::string pinName;
765735dee9bSAlpana Kumari 
766735dee9bSAlpana Kumari     for (const auto& postAction :
767735dee9bSAlpana Kumari          (json["frus"][file].at(0))["postActionFail"].items())
768735dee9bSAlpana Kumari     {
769735dee9bSAlpana Kumari         if (postAction.key() == "pin")
770735dee9bSAlpana Kumari         {
771735dee9bSAlpana Kumari             pinName = postAction.value();
772735dee9bSAlpana Kumari         }
773735dee9bSAlpana Kumari         else if (postAction.key() == "value")
774735dee9bSAlpana Kumari         {
775735dee9bSAlpana Kumari             // Get the value to set
776735dee9bSAlpana Kumari             pinValue = postAction.value();
777735dee9bSAlpana Kumari         }
778735dee9bSAlpana Kumari     }
779735dee9bSAlpana Kumari 
780e008432aSPriyanga Ramasamy     std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
781e008432aSPriyanga Ramasamy               << std::endl;
782735dee9bSAlpana Kumari 
783735dee9bSAlpana Kumari     try
784735dee9bSAlpana Kumari     {
785735dee9bSAlpana Kumari         gpiod::line outputLine = gpiod::find_line(pinName);
786735dee9bSAlpana Kumari 
787735dee9bSAlpana Kumari         if (!outputLine)
788735dee9bSAlpana Kumari         {
789a2ddc96eSSunny Srivastava             throw GpioException(
7906bd095f9SAlpana Kumari                 "Couldn't find output line for the GPIO. Skipping "
7916bd095f9SAlpana Kumari                 "this GPIO action.");
792735dee9bSAlpana Kumari         }
793735dee9bSAlpana Kumari         outputLine.request(
794735dee9bSAlpana Kumari             {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
795735dee9bSAlpana Kumari             pinValue);
796735dee9bSAlpana Kumari     }
797e008432aSPriyanga Ramasamy     catch (const std::exception& e)
798735dee9bSAlpana Kumari     {
799e008432aSPriyanga Ramasamy         std::string i2cBusAddr;
800e008432aSPriyanga Ramasamy         std::string errMsg = e.what();
8016bd095f9SAlpana Kumari         errMsg += "\nGPIO: " + pinName;
8026bd095f9SAlpana Kumari 
8036bd095f9SAlpana Kumari         if ((json["frus"][file].at(0)["postActionFail"].find(
8046bd095f9SAlpana Kumari                 "gpioI2CAddress")) !=
8056bd095f9SAlpana Kumari             json["frus"][file].at(0)["postActionFail"].end())
8066bd095f9SAlpana Kumari         {
8076bd095f9SAlpana Kumari             i2cBusAddr =
8086bd095f9SAlpana Kumari                 json["frus"][file].at(0)["postActionFail"]["gpioI2CAddress"];
809fdf9ff2aSSunny Srivastava             errMsg += " i2cBusAddress: " + i2cBusAddr;
810735dee9bSAlpana Kumari         }
8116bd095f9SAlpana Kumari 
812a2ddc96eSSunny Srivastava         throw GpioException(e.what());
8136bd095f9SAlpana Kumari     }
8146bd095f9SAlpana Kumari 
8156bd095f9SAlpana Kumari     return;
816735dee9bSAlpana Kumari }
817735dee9bSAlpana Kumari 
isPresent(const nlohmann::json & json,const std::string & file)818e008432aSPriyanga Ramasamy std::optional<bool> isPresent(const nlohmann::json& json,
819e008432aSPriyanga Ramasamy                               const std::string& file)
82053b38ed0SSantosh Puranik 
821735dee9bSAlpana Kumari {
822735dee9bSAlpana Kumari     if ((json["frus"][file].at(0)).find("presence") !=
823735dee9bSAlpana Kumari         json["frus"][file].at(0).end())
824735dee9bSAlpana Kumari     {
825735dee9bSAlpana Kumari         if (((json["frus"][file].at(0)["presence"]).find("pin") !=
826735dee9bSAlpana Kumari              json["frus"][file].at(0)["presence"].end()) &&
827735dee9bSAlpana Kumari             ((json["frus"][file].at(0)["presence"]).find("value") !=
828735dee9bSAlpana Kumari              json["frus"][file].at(0)["presence"].end()))
829735dee9bSAlpana Kumari         {
830e008432aSPriyanga Ramasamy             std::string presPinName =
831e008432aSPriyanga Ramasamy                 json["frus"][file].at(0)["presence"]["pin"];
832735dee9bSAlpana Kumari             Byte presPinValue = json["frus"][file].at(0)["presence"]["value"];
833735dee9bSAlpana Kumari 
834735dee9bSAlpana Kumari             try
835735dee9bSAlpana Kumari             {
836735dee9bSAlpana Kumari                 gpiod::line presenceLine = gpiod::find_line(presPinName);
837735dee9bSAlpana Kumari 
838735dee9bSAlpana Kumari                 if (!presenceLine)
839735dee9bSAlpana Kumari                 {
840e008432aSPriyanga Ramasamy                     std::cerr << "Couldn't find the presence line for - "
841e008432aSPriyanga Ramasamy                               << presPinName << std::endl;
84240d1c196SAlpana Kumari 
843a2ddc96eSSunny Srivastava                     throw GpioException(
8446bd095f9SAlpana Kumari                         "Couldn't find the presence line for the "
8456bd095f9SAlpana Kumari                         "GPIO. Skipping this GPIO action.");
846735dee9bSAlpana Kumari                 }
847735dee9bSAlpana Kumari 
848735dee9bSAlpana Kumari                 presenceLine.request({"Read the presence line",
849735dee9bSAlpana Kumari                                       gpiod::line_request::DIRECTION_INPUT, 0});
850735dee9bSAlpana Kumari 
851735dee9bSAlpana Kumari                 Byte gpioData = presenceLine.get_value();
852735dee9bSAlpana Kumari 
85353b38ed0SSantosh Puranik                 return (gpioData == presPinValue);
854735dee9bSAlpana Kumari             }
855e008432aSPriyanga Ramasamy             catch (const std::exception& e)
856735dee9bSAlpana Kumari             {
857e008432aSPriyanga Ramasamy                 std::string i2cBusAddr;
858e008432aSPriyanga Ramasamy                 std::string errMsg = e.what();
8596bd095f9SAlpana Kumari                 errMsg += " GPIO : " + presPinName;
8606bd095f9SAlpana Kumari 
8616bd095f9SAlpana Kumari                 if ((json["frus"][file].at(0)["presence"])
8626bd095f9SAlpana Kumari                         .find("gpioI2CAddress") !=
8636bd095f9SAlpana Kumari                     json["frus"][file].at(0)["presence"].end())
8646bd095f9SAlpana Kumari                 {
8656bd095f9SAlpana Kumari                     i2cBusAddr =
8666bd095f9SAlpana Kumari                         json["frus"][file].at(0)["presence"]["gpioI2CAddress"];
867fdf9ff2aSSunny Srivastava                     errMsg += " i2cBusAddress: " + i2cBusAddr;
8686bd095f9SAlpana Kumari                 }
8696bd095f9SAlpana Kumari 
87040d1c196SAlpana Kumari                 // Take failure postAction
87140d1c196SAlpana Kumari                 executePostFailAction(json, file);
872a2ddc96eSSunny Srivastava                 throw GpioException(errMsg);
873735dee9bSAlpana Kumari             }
874735dee9bSAlpana Kumari         }
87540d1c196SAlpana Kumari         else
87640d1c196SAlpana Kumari         {
877af921756SManojkiran Eda             // missing required information
878e008432aSPriyanga Ramasamy             std::cerr
879af921756SManojkiran Eda                 << "VPD inventory JSON missing basic information of presence "
88040d1c196SAlpana Kumari                    "for this FRU : ["
881e008432aSPriyanga Ramasamy                 << file << "]. Executing executePostFailAction." << std::endl;
88240d1c196SAlpana Kumari 
88340d1c196SAlpana Kumari             // Take failure postAction
88440d1c196SAlpana Kumari             executePostFailAction(json, file);
88540d1c196SAlpana Kumari 
88640d1c196SAlpana Kumari             return false;
88740d1c196SAlpana Kumari         }
888735dee9bSAlpana Kumari     }
88953b38ed0SSantosh Puranik     return std::optional<bool>{};
89053b38ed0SSantosh Puranik }
89153b38ed0SSantosh Puranik 
executePreAction(const nlohmann::json & json,const std::string & file)892e008432aSPriyanga Ramasamy bool executePreAction(const nlohmann::json& json, const std::string& file)
89353b38ed0SSantosh Puranik {
89453b38ed0SSantosh Puranik     auto present = isPresent(json, file);
89553b38ed0SSantosh Puranik     if (present && !present.value())
89653b38ed0SSantosh Puranik     {
89753b38ed0SSantosh Puranik         executePostFailAction(json, file);
89853b38ed0SSantosh Puranik         return false;
89953b38ed0SSantosh Puranik     }
900735dee9bSAlpana Kumari 
901735dee9bSAlpana Kumari     if ((json["frus"][file].at(0)).find("preAction") !=
902735dee9bSAlpana Kumari         json["frus"][file].at(0).end())
903735dee9bSAlpana Kumari     {
904735dee9bSAlpana Kumari         if (((json["frus"][file].at(0)["preAction"]).find("pin") !=
905735dee9bSAlpana Kumari              json["frus"][file].at(0)["preAction"].end()) &&
906735dee9bSAlpana Kumari             ((json["frus"][file].at(0)["preAction"]).find("value") !=
907735dee9bSAlpana Kumari              json["frus"][file].at(0)["preAction"].end()))
908735dee9bSAlpana Kumari         {
909e008432aSPriyanga Ramasamy             std::string pinName = json["frus"][file].at(0)["preAction"]["pin"];
910735dee9bSAlpana Kumari             // Get the value to set
911735dee9bSAlpana Kumari             Byte pinValue = json["frus"][file].at(0)["preAction"]["value"];
912735dee9bSAlpana Kumari 
913e008432aSPriyanga Ramasamy             std::cout << "Setting GPIO: " << pinName << " to " << (int)pinValue
914e008432aSPriyanga Ramasamy                       << std::endl;
915735dee9bSAlpana Kumari             try
916735dee9bSAlpana Kumari             {
917735dee9bSAlpana Kumari                 gpiod::line outputLine = gpiod::find_line(pinName);
918735dee9bSAlpana Kumari 
919735dee9bSAlpana Kumari                 if (!outputLine)
920735dee9bSAlpana Kumari                 {
921e008432aSPriyanga Ramasamy                     std::cerr << "Couldn't find the line for output pin - "
922e008432aSPriyanga Ramasamy                               << pinName << std::endl;
923a2ddc96eSSunny Srivastava                     throw GpioException(
9246bd095f9SAlpana Kumari                         "Couldn't find output line for the GPIO. "
9256bd095f9SAlpana Kumari                         "Skipping this GPIO action.");
926735dee9bSAlpana Kumari                 }
927735dee9bSAlpana Kumari                 outputLine.request({"FRU pre-action",
928735dee9bSAlpana Kumari                                     ::gpiod::line_request::DIRECTION_OUTPUT, 0},
929735dee9bSAlpana Kumari                                    pinValue);
930735dee9bSAlpana Kumari             }
931e008432aSPriyanga Ramasamy             catch (const std::exception& e)
932735dee9bSAlpana Kumari             {
933e008432aSPriyanga Ramasamy                 std::string i2cBusAddr;
934e008432aSPriyanga Ramasamy                 std::string errMsg = e.what();
9356bd095f9SAlpana Kumari                 errMsg += " GPIO : " + pinName;
9366bd095f9SAlpana Kumari 
9376bd095f9SAlpana Kumari                 if ((json["frus"][file].at(0)["preAction"])
9386bd095f9SAlpana Kumari                         .find("gpioI2CAddress") !=
9396bd095f9SAlpana Kumari                     json["frus"][file].at(0)["preAction"].end())
9406bd095f9SAlpana Kumari                 {
9416bd095f9SAlpana Kumari                     i2cBusAddr =
9426bd095f9SAlpana Kumari                         json["frus"][file].at(0)["preAction"]["gpioI2CAddress"];
943fdf9ff2aSSunny Srivastava                     errMsg += " i2cBusAddress: " + i2cBusAddr;
9446bd095f9SAlpana Kumari                 }
9456bd095f9SAlpana Kumari 
94640d1c196SAlpana Kumari                 // Take failure postAction
94740d1c196SAlpana Kumari                 executePostFailAction(json, file);
948a2ddc96eSSunny Srivastava                 throw GpioException(errMsg);
949735dee9bSAlpana Kumari             }
950735dee9bSAlpana Kumari         }
95140d1c196SAlpana Kumari         else
95240d1c196SAlpana Kumari         {
953af921756SManojkiran Eda             // missing required information
954e008432aSPriyanga Ramasamy             std::cerr
955af921756SManojkiran Eda                 << "VPD inventory JSON missing basic information of preAction "
95640d1c196SAlpana Kumari                    "for this FRU : ["
957e008432aSPriyanga Ramasamy                 << file << "]. Executing executePostFailAction." << std::endl;
95840d1c196SAlpana Kumari 
95940d1c196SAlpana Kumari             // Take failure postAction
96040d1c196SAlpana Kumari             executePostFailAction(json, file);
96140d1c196SAlpana Kumari             return false;
96240d1c196SAlpana Kumari         }
963735dee9bSAlpana Kumari     }
964735dee9bSAlpana Kumari     return true;
965735dee9bSAlpana Kumari }
966735dee9bSAlpana Kumari 
insertOrMerge(inventory::InterfaceMap & map,const inventory::Interface & interface,inventory::PropertyMap && property)967aa8a893eSPriyanga Ramasamy void insertOrMerge(inventory::InterfaceMap& map,
968aa8a893eSPriyanga Ramasamy                    const inventory::Interface& interface,
969aa8a893eSPriyanga Ramasamy                    inventory::PropertyMap&& property)
970aa8a893eSPriyanga Ramasamy {
971aa8a893eSPriyanga Ramasamy     if (map.find(interface) != map.end())
972aa8a893eSPriyanga Ramasamy     {
973aa8a893eSPriyanga Ramasamy         auto& prop = map.at(interface);
974aa8a893eSPriyanga Ramasamy         prop.insert(property.begin(), property.end());
975aa8a893eSPriyanga Ramasamy     }
976aa8a893eSPriyanga Ramasamy     else
977aa8a893eSPriyanga Ramasamy     {
978aa8a893eSPriyanga Ramasamy         map.emplace(interface, property);
979aa8a893eSPriyanga Ramasamy     }
980aa8a893eSPriyanga Ramasamy }
981f2d3b53dSSantosh Puranik 
readBIOSAttribute(const std::string & attrName)982f2d3b53dSSantosh Puranik BIOSAttrValueType readBIOSAttribute(const std::string& attrName)
983f2d3b53dSSantosh Puranik {
984f2d3b53dSSantosh Puranik     std::tuple<std::string, BIOSAttrValueType, BIOSAttrValueType> attrVal;
985f2d3b53dSSantosh Puranik     auto bus = sdbusplus::bus::new_default();
986f2d3b53dSSantosh Puranik     auto method = bus.new_method_call(
987f2d3b53dSSantosh Puranik         "xyz.openbmc_project.BIOSConfigManager",
988f2d3b53dSSantosh Puranik         "/xyz/openbmc_project/bios_config/manager",
989f2d3b53dSSantosh Puranik         "xyz.openbmc_project.BIOSConfig.Manager", "GetAttribute");
990f2d3b53dSSantosh Puranik     method.append(attrName);
991f2d3b53dSSantosh Puranik     try
992f2d3b53dSSantosh Puranik     {
993f2d3b53dSSantosh Puranik         auto result = bus.call(method);
994f2d3b53dSSantosh Puranik         result.read(std::get<0>(attrVal), std::get<1>(attrVal),
995f2d3b53dSSantosh Puranik                     std::get<2>(attrVal));
996f2d3b53dSSantosh Puranik     }
997f2d3b53dSSantosh Puranik     catch (const sdbusplus::exception::SdBusError& e)
998f2d3b53dSSantosh Puranik     {
999f2d3b53dSSantosh Puranik         std::cerr << "Failed to read BIOS Attribute: " << attrName << std::endl;
1000f2d3b53dSSantosh Puranik         std::cerr << e.what() << std::endl;
1001f2d3b53dSSantosh Puranik     }
1002f2d3b53dSSantosh Puranik     return std::get<1>(attrVal);
1003f2d3b53dSSantosh Puranik }
1004335873f6SPriyanga Ramasamy 
getPowerState()1005335873f6SPriyanga Ramasamy std::string getPowerState()
1006335873f6SPriyanga Ramasamy {
1007335873f6SPriyanga Ramasamy     // TODO: How do we handle multiple chassis?
1008e008432aSPriyanga Ramasamy     std::string powerState{};
1009335873f6SPriyanga Ramasamy     auto bus = sdbusplus::bus::new_default();
101008dc31cdSPatrick Williams     auto properties =
101108dc31cdSPatrick Williams         bus.new_method_call("xyz.openbmc_project.State.Chassis0",
1012335873f6SPriyanga Ramasamy                             "/xyz/openbmc_project/state/chassis0",
101308dc31cdSPatrick Williams                             "org.freedesktop.DBus.Properties", "Get");
1014335873f6SPriyanga Ramasamy     properties.append("xyz.openbmc_project.State.Chassis");
1015335873f6SPriyanga Ramasamy     properties.append("CurrentPowerState");
1016335873f6SPriyanga Ramasamy     auto result = bus.call(properties);
1017335873f6SPriyanga Ramasamy     if (!result.is_method_error())
1018335873f6SPriyanga Ramasamy     {
1019e008432aSPriyanga Ramasamy         std::variant<std::string> val;
1020335873f6SPriyanga Ramasamy         result.read(val);
1021e008432aSPriyanga Ramasamy         if (auto pVal = std::get_if<std::string>(&val))
1022335873f6SPriyanga Ramasamy         {
1023335873f6SPriyanga Ramasamy             powerState = *pVal;
1024335873f6SPriyanga Ramasamy         }
1025335873f6SPriyanga Ramasamy     }
1026e008432aSPriyanga Ramasamy     std::cout << "Power state is: " << powerState << std::endl;
1027335873f6SPriyanga Ramasamy     return powerState;
1028335873f6SPriyanga Ramasamy }
10296b2b5374SSantosh Puranik 
getVpdDataInVector(const nlohmann::json & js,const std::string & file)10306b2b5374SSantosh Puranik Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file)
10316b2b5374SSantosh Puranik {
10326b2b5374SSantosh Puranik     uint32_t offset = 0;
10336b2b5374SSantosh Puranik     // check if offset present?
10346b2b5374SSantosh Puranik     for (const auto& item : js["frus"][file])
10356b2b5374SSantosh Puranik     {
10366b2b5374SSantosh Puranik         if (item.find("offset") != item.end())
10376b2b5374SSantosh Puranik         {
10386b2b5374SSantosh Puranik             offset = item["offset"];
10396b2b5374SSantosh Puranik         }
10406b2b5374SSantosh Puranik     }
10416b2b5374SSantosh Puranik 
10426b2b5374SSantosh Puranik     // TODO: Figure out a better way to get max possible VPD size.
10436b2b5374SSantosh Puranik     auto maxVPDSize = std::min(std::filesystem::file_size(file),
10446b2b5374SSantosh Puranik                                static_cast<uintmax_t>(65504));
10456b2b5374SSantosh Puranik 
10466b2b5374SSantosh Puranik     Binary vpdVector;
10476b2b5374SSantosh Puranik     vpdVector.resize(maxVPDSize);
1048e008432aSPriyanga Ramasamy     std::ifstream vpdFile;
104945d54976Sjinuthomas     vpdFile.exceptions(std::ifstream::badbit | std::ifstream::failbit);
105045d54976Sjinuthomas     try
105145d54976Sjinuthomas     {
1052e2b0383aSJinu Joy Thomas         vpdFile.open(file, std::ios::binary | std::ios::in);
1053e008432aSPriyanga Ramasamy         vpdFile.seekg(offset, std::ios_base::cur);
10546b2b5374SSantosh Puranik         vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), maxVPDSize);
10556b2b5374SSantosh Puranik         vpdVector.resize(vpdFile.gcount());
105645d54976Sjinuthomas     }
105745d54976Sjinuthomas     catch (const std::ifstream::failure& fail)
105845d54976Sjinuthomas     {
105945d54976Sjinuthomas         std::cerr << "Exception in file handling [" << file
106045d54976Sjinuthomas                   << "] error : " << fail.what();
106145d54976Sjinuthomas         std::cerr << "EEPROM file size =" << std::filesystem::file_size(file)
106245d54976Sjinuthomas                   << std::endl;
106345d54976Sjinuthomas         std::cerr << "Stream file size = " << vpdFile.gcount() << std::endl;
106445d54976Sjinuthomas         std::cerr << " Vector size" << vpdVector.size() << std::endl;
106545d54976Sjinuthomas         throw;
106645d54976Sjinuthomas     }
10676b2b5374SSantosh Puranik 
1068e2b0383aSJinu Joy Thomas     // Make sure we reset the EEPROM pointer to a "safe" location if it was
1069e2b0383aSJinu Joy Thomas     // a DDIMM SPD that we just read.
10706b2b5374SSantosh Puranik     for (const auto& item : js["frus"][file])
10716b2b5374SSantosh Puranik     {
10726b2b5374SSantosh Puranik         if (item.find("extraInterfaces") != item.end())
10736b2b5374SSantosh Puranik         {
10746b2b5374SSantosh Puranik             if (item["extraInterfaces"].find(
10756b2b5374SSantosh Puranik                     "xyz.openbmc_project.Inventory.Item.Dimm") !=
10766b2b5374SSantosh Puranik                 item["extraInterfaces"].end())
10776b2b5374SSantosh Puranik             {
1078af921756SManojkiran Eda                 // check added here for DDIMM only workaround
1079e2b0383aSJinu Joy Thomas                 vpdType dimmType = vpdTypeCheck(vpdVector);
1080e2b0383aSJinu Joy Thomas                 if (dimmType == constants::DDR4_DDIMM_MEMORY_VPD ||
1081e2b0383aSJinu Joy Thomas                     dimmType == constants::DDR5_DDIMM_MEMORY_VPD)
1082e2b0383aSJinu Joy Thomas                 {
108345d54976Sjinuthomas                     try
108445d54976Sjinuthomas                     {
10856b2b5374SSantosh Puranik                         // moves the EEPROM pointer to 2048 'th byte.
10866b2b5374SSantosh Puranik                         vpdFile.seekg(2047, std::ios::beg);
10876b2b5374SSantosh Puranik                         // Read that byte and discard - to affirm the move
10886b2b5374SSantosh Puranik                         // operation.
10896b2b5374SSantosh Puranik                         char ch;
10906b2b5374SSantosh Puranik                         vpdFile.read(&ch, sizeof(ch));
109145d54976Sjinuthomas                     }
109245d54976Sjinuthomas                     catch (const std::ifstream::failure& fail)
109345d54976Sjinuthomas                     {
109445d54976Sjinuthomas                         std::cerr << "Exception in file handling [" << file
109545d54976Sjinuthomas                                   << "] error : " << fail.what();
109645d54976Sjinuthomas                         std::cerr << "Stream file size = " << vpdFile.gcount()
109745d54976Sjinuthomas                                   << std::endl;
109845d54976Sjinuthomas                         throw;
109945d54976Sjinuthomas                     }
1100e2b0383aSJinu Joy Thomas                 }
11016b2b5374SSantosh Puranik                 break;
11026b2b5374SSantosh Puranik             }
11036b2b5374SSantosh Puranik         }
11046b2b5374SSantosh Puranik     }
11056b2b5374SSantosh Puranik 
11066b2b5374SSantosh Puranik     return vpdVector;
11076b2b5374SSantosh Puranik }
11085629fbc0SPriyanga Ramasamy 
getDbusNameForThisKw(const std::string & keyword)11095629fbc0SPriyanga Ramasamy std::string getDbusNameForThisKw(const std::string& keyword)
11105629fbc0SPriyanga Ramasamy {
11115629fbc0SPriyanga Ramasamy     if (keyword[0] == constants::POUND_KW)
11125629fbc0SPriyanga Ramasamy     {
11135629fbc0SPriyanga Ramasamy         return (std::string(constants::POUND_KW_PREFIX) + keyword[1]);
11145629fbc0SPriyanga Ramasamy     }
11155629fbc0SPriyanga Ramasamy     else if (isdigit(keyword[0]))
11165629fbc0SPriyanga Ramasamy     {
11175629fbc0SPriyanga Ramasamy         return (std::string(constants::NUMERIC_KW_PREFIX) + keyword);
11185629fbc0SPriyanga Ramasamy     }
11195629fbc0SPriyanga Ramasamy     return keyword;
11205629fbc0SPriyanga Ramasamy }
11215629fbc0SPriyanga Ramasamy 
clearVpdOnRemoval(const std::string & objPath,inventory::InterfaceMap & interfacesPropMap)1122c6e7ea92SSunny Srivastava void clearVpdOnRemoval(const std::string& objPath,
1123c6e7ea92SSunny Srivastava                        inventory::InterfaceMap& interfacesPropMap)
1124c6e7ea92SSunny Srivastava {
1125c6e7ea92SSunny Srivastava     std::vector<std::string> vpdRelatedInterfaces{
1126c6e7ea92SSunny Srivastava         constants::invOperationalStatusIntf, constants::invItemIntf,
1127c6e7ea92SSunny Srivastava         constants::invAssetIntf};
1128c6e7ea92SSunny Srivastava 
1129c6e7ea92SSunny Srivastava     std::vector<std::string> interfaces{};
1130c6e7ea92SSunny Srivastava     auto mapperResponse = inventory::getObject(objPath, interfaces);
1131c6e7ea92SSunny Srivastava 
1132c6e7ea92SSunny Srivastava     for (const auto& [service, interfaceList] : mapperResponse)
1133c6e7ea92SSunny Srivastava     {
1134c6e7ea92SSunny Srivastava         // Handle FRUs under PIM
1135c6e7ea92SSunny Srivastava         if (service.compare(pimService) != 0)
1136c6e7ea92SSunny Srivastava         {
1137c6e7ea92SSunny Srivastava             continue;
1138c6e7ea92SSunny Srivastava         }
1139c6e7ea92SSunny Srivastava 
1140c6e7ea92SSunny Srivastava         for (const auto& interface : interfaceList)
1141c6e7ea92SSunny Srivastava         {
1142c6e7ea92SSunny Srivastava             // Only process for VPD related interfaces.
1143c6e7ea92SSunny Srivastava             if ((interface.find("com.ibm.ipzvpd") != std::string::npos) ||
1144c6e7ea92SSunny Srivastava                 ((std::find(vpdRelatedInterfaces.begin(),
1145c6e7ea92SSunny Srivastava                             vpdRelatedInterfaces.end(), interface)) !=
1146c6e7ea92SSunny Srivastava                  vpdRelatedInterfaces.end()))
1147c6e7ea92SSunny Srivastava             {
1148c6e7ea92SSunny Srivastava                 const auto propertyList = getAllDBusProperty<GetAllResultType>(
1149c6e7ea92SSunny Srivastava                     service, objPath, interface);
1150c6e7ea92SSunny Srivastava 
1151c6e7ea92SSunny Srivastava                 inventory::PropertyMap propertyValueMap;
1152c6e7ea92SSunny Srivastava                 for (auto aProperty : propertyList)
1153c6e7ea92SSunny Srivastava                 {
1154c6e7ea92SSunny Srivastava                     const auto& propertyName = std::get<0>(aProperty);
1155c6e7ea92SSunny Srivastava                     const auto& propertyValue = std::get<1>(aProperty);
1156c6e7ea92SSunny Srivastava 
1157c6e7ea92SSunny Srivastava                     if (std::holds_alternative<Binary>(propertyValue))
1158c6e7ea92SSunny Srivastava                     {
1159c6e7ea92SSunny Srivastava                         propertyValueMap.emplace(propertyName, Binary{});
1160c6e7ea92SSunny Srivastava                     }
1161c6e7ea92SSunny Srivastava                     else if (std::holds_alternative<std::string>(propertyValue))
1162c6e7ea92SSunny Srivastava                     {
1163c6e7ea92SSunny Srivastava                         propertyValueMap.emplace(propertyName, std::string{});
1164c6e7ea92SSunny Srivastava                     }
1165c6e7ea92SSunny Srivastava                     else if (std::holds_alternative<bool>(propertyValue))
1166c6e7ea92SSunny Srivastava                     {
1167c6e7ea92SSunny Srivastava                         if (propertyName.compare("Present") == 0)
1168c6e7ea92SSunny Srivastava                         {
1169c6e7ea92SSunny Srivastava                             propertyValueMap.emplace(propertyName, false);
1170c6e7ea92SSunny Srivastava                         }
1171c6e7ea92SSunny Srivastava                         else if (propertyName.compare("Functional") == 0)
1172c6e7ea92SSunny Srivastava                         {
1173c6e7ea92SSunny Srivastava                             propertyValueMap.emplace(propertyName, true);
1174c6e7ea92SSunny Srivastava                         }
1175c6e7ea92SSunny Srivastava                     }
1176c6e7ea92SSunny Srivastava                 }
1177c6e7ea92SSunny Srivastava                 interfacesPropMap.emplace(interface,
1178c6e7ea92SSunny Srivastava                                           std::move(propertyValueMap));
1179c6e7ea92SSunny Srivastava             }
1180c6e7ea92SSunny Srivastava         }
1181c6e7ea92SSunny Srivastava     }
1182c6e7ea92SSunny Srivastava }
11830eb8caccSpriyaram 
findBackupVPDPaths(std::string & backupEepromPath,std::string & backupInvPath,const nlohmann::json & js)11840eb8caccSpriyaram void findBackupVPDPaths(std::string& backupEepromPath,
11850eb8caccSpriyaram                         std::string& backupInvPath, const nlohmann::json& js)
11860eb8caccSpriyaram {
11870eb8caccSpriyaram     for (const auto& item : js["frus"][constants::systemVpdFilePath])
11880eb8caccSpriyaram     {
11890eb8caccSpriyaram         if (item.find("systemVpdBackupPath") != item.end())
11900eb8caccSpriyaram         {
11910eb8caccSpriyaram             backupEepromPath = item["systemVpdBackupPath"];
11920eb8caccSpriyaram             for (const auto& item : js["frus"][backupEepromPath])
11930eb8caccSpriyaram             {
11940eb8caccSpriyaram                 if (item.find("inventoryPath") != item.end())
11950eb8caccSpriyaram                 {
11960eb8caccSpriyaram                     backupInvPath = item["inventoryPath"];
11970eb8caccSpriyaram                     break;
11980eb8caccSpriyaram                 }
11990eb8caccSpriyaram             }
12000eb8caccSpriyaram             break;
12010eb8caccSpriyaram         }
12020eb8caccSpriyaram     }
12030eb8caccSpriyaram }
12040eb8caccSpriyaram 
getBackupRecordKeyword(std::string & record,std::string & keyword)12050eb8caccSpriyaram void getBackupRecordKeyword(std::string& record, std::string& keyword)
12060eb8caccSpriyaram {
12070eb8caccSpriyaram     for (const auto& recordKw : svpdKwdMap)
12080eb8caccSpriyaram     {
12090eb8caccSpriyaram         if (record == recordKw.first)
12100eb8caccSpriyaram         {
12110eb8caccSpriyaram             for (const auto& keywordInfo : recordKw.second)
12120eb8caccSpriyaram             {
12130eb8caccSpriyaram                 if (keyword == get<0>(keywordInfo))
12140eb8caccSpriyaram                 {
12150eb8caccSpriyaram                     record = get<4>(keywordInfo);
12160eb8caccSpriyaram                     keyword = get<5>(keywordInfo);
12170eb8caccSpriyaram                     break;
12180eb8caccSpriyaram                 }
12190eb8caccSpriyaram             }
12200eb8caccSpriyaram             break;
12210eb8caccSpriyaram         }
12220eb8caccSpriyaram     }
12230eb8caccSpriyaram }
1224*44fca017SPriyangaRamasamy 
isReadOnlyEEPROM(const std::string & vpdPath,const nlohmann::json & jsObject)1225*44fca017SPriyangaRamasamy bool isReadOnlyEEPROM(const std::string& vpdPath,
1226*44fca017SPriyangaRamasamy                       const nlohmann::json& jsObject)
1227*44fca017SPriyangaRamasamy {
1228*44fca017SPriyangaRamasamy     // check if given path is FRU path
1229*44fca017SPriyangaRamasamy     if (jsObject["frus"].contains(vpdPath))
1230*44fca017SPriyangaRamasamy     {
1231*44fca017SPriyangaRamasamy         return jsObject["frus"][vpdPath].at(0).value("readOnly", false);
1232*44fca017SPriyangaRamasamy     }
1233*44fca017SPriyangaRamasamy 
1234*44fca017SPriyangaRamasamy     const nlohmann::json& fruList =
1235*44fca017SPriyangaRamasamy         jsObject["frus"].get_ref<const nlohmann::json::object_t&>();
1236*44fca017SPriyangaRamasamy 
1237*44fca017SPriyangaRamasamy     for (const auto& fru : fruList.items())
1238*44fca017SPriyangaRamasamy     {
1239*44fca017SPriyangaRamasamy         const auto fruPath = fru.key();
1240*44fca017SPriyangaRamasamy 
1241*44fca017SPriyangaRamasamy         // If given VPD path is either the inventory path or redundant EEPROM
1242*44fca017SPriyangaRamasamy         // path.
1243*44fca017SPriyangaRamasamy         if ((vpdPath ==
1244*44fca017SPriyangaRamasamy              jsObject["frus"][fruPath].at(0).value("inventoryPath", "")) ||
1245*44fca017SPriyangaRamasamy             (vpdPath ==
1246*44fca017SPriyangaRamasamy              jsObject["frus"][fruPath].at(0).value("redundantEeprom", "")))
1247*44fca017SPriyangaRamasamy         {
1248*44fca017SPriyangaRamasamy             return jsObject["frus"][fruPath].at(0).value("readOnly", false);
1249*44fca017SPriyangaRamasamy         }
1250*44fca017SPriyangaRamasamy     }
1251*44fca017SPriyangaRamasamy 
1252*44fca017SPriyangaRamasamy     // Given path not found in JSON
1253*44fca017SPriyangaRamasamy     return false;
1254*44fca017SPriyangaRamasamy }
12556c71c9dcSSunny Srivastava } // namespace vpd
12566c71c9dcSSunny Srivastava } // namespace openpower
1257