16c71c9dcSSunny Srivastava #include "config.h" 26c71c9dcSSunny Srivastava 36c71c9dcSSunny Srivastava #include "ibm_vpd_utils.hpp" 46c71c9dcSSunny Srivastava 56c71c9dcSSunny Srivastava #include "common_utility.hpp" 66c71c9dcSSunny Srivastava #include "defines.hpp" 76c71c9dcSSunny Srivastava #include "vpd_exceptions.hpp" 86c71c9dcSSunny Srivastava 96bd095f9SAlpana Kumari #include <boost/algorithm/string.hpp> 10c2fe40f8SPriyangaRamasamy #include <filesystem> 116c71c9dcSSunny Srivastava #include <fstream> 12735dee9bSAlpana Kumari #include <gpiod.hpp> 136c71c9dcSSunny Srivastava #include <iomanip> 146c71c9dcSSunny Srivastava #include <nlohmann/json.hpp> 156c71c9dcSSunny Srivastava #include <phosphor-logging/elog-errors.hpp> 166c71c9dcSSunny Srivastava #include <phosphor-logging/log.hpp> 17647868edSPriyangaRamasamy #include <regex> 186c71c9dcSSunny Srivastava #include <sdbusplus/server.hpp> 196c71c9dcSSunny Srivastava #include <sstream> 206c71c9dcSSunny Srivastava #include <vector> 216c71c9dcSSunny Srivastava #include <xyz/openbmc_project/Common/error.hpp> 226c71c9dcSSunny Srivastava 236c71c9dcSSunny Srivastava using json = nlohmann::json; 246c71c9dcSSunny Srivastava 256c71c9dcSSunny Srivastava namespace openpower 266c71c9dcSSunny Srivastava { 276c71c9dcSSunny Srivastava namespace vpd 286c71c9dcSSunny Srivastava { 296c71c9dcSSunny Srivastava using namespace openpower::vpd::constants; 306c71c9dcSSunny Srivastava using namespace inventory; 316c71c9dcSSunny Srivastava using namespace phosphor::logging; 326c71c9dcSSunny Srivastava using namespace sdbusplus::xyz::openbmc_project::Common::Error; 336c71c9dcSSunny Srivastava using namespace record; 346c71c9dcSSunny Srivastava using namespace openpower::vpd::exceptions; 356c71c9dcSSunny Srivastava using namespace common::utility; 360746eeebSSunny Srivastava using Severity = openpower::vpd::constants::PelSeverity; 37c2fe40f8SPriyangaRamasamy namespace fs = std::filesystem; 380746eeebSSunny Srivastava 390746eeebSSunny Srivastava // mapping of severity enum to severity interface 400746eeebSSunny Srivastava static std::unordered_map<Severity, std::string> sevMap = { 410746eeebSSunny Srivastava {Severity::INFORMATIONAL, 420746eeebSSunny Srivastava "xyz.openbmc_project.Logging.Entry.Level.Informational"}, 430746eeebSSunny Srivastava {Severity::DEBUG, "xyz.openbmc_project.Logging.Entry.Level.Debug"}, 440746eeebSSunny Srivastava {Severity::NOTICE, "xyz.openbmc_project.Logging.Entry.Level.Notice"}, 450746eeebSSunny Srivastava {Severity::WARNING, "xyz.openbmc_project.Logging.Entry.Level.Warning"}, 460746eeebSSunny Srivastava {Severity::CRITICAL, "xyz.openbmc_project.Logging.Entry.Level.Critical"}, 470746eeebSSunny Srivastava {Severity::EMERGENCY, "xyz.openbmc_project.Logging.Entry.Level.Emergency"}, 480746eeebSSunny Srivastava {Severity::ERROR, "xyz.openbmc_project.Logging.Entry.Level.Error"}, 490746eeebSSunny Srivastava {Severity::ALERT, "xyz.openbmc_project.Logging.Entry.Level.Alert"}}; 500746eeebSSunny Srivastava 516c71c9dcSSunny Srivastava namespace inventory 526c71c9dcSSunny Srivastava { 536c71c9dcSSunny Srivastava 546c71c9dcSSunny Srivastava MapperResponse 556c71c9dcSSunny Srivastava getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth, 566c71c9dcSSunny Srivastava const std::vector<std::string>& interfaces) 576c71c9dcSSunny Srivastava { 586c71c9dcSSunny Srivastava auto bus = sdbusplus::bus::new_default(); 596c71c9dcSSunny Srivastava auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath, 606c71c9dcSSunny Srivastava mapperInterface, "GetSubTree"); 616c71c9dcSSunny Srivastava mapperCall.append(root); 626c71c9dcSSunny Srivastava mapperCall.append(depth); 636c71c9dcSSunny Srivastava mapperCall.append(interfaces); 646c71c9dcSSunny Srivastava 656c71c9dcSSunny Srivastava MapperResponse result = {}; 666c71c9dcSSunny Srivastava 676c71c9dcSSunny Srivastava try 686c71c9dcSSunny Srivastava { 696c71c9dcSSunny Srivastava auto response = bus.call(mapperCall); 706c71c9dcSSunny Srivastava 716c71c9dcSSunny Srivastava response.read(result); 726c71c9dcSSunny Srivastava } 73*2eb0176cSPatrick Williams catch (const sdbusplus::exception_t& e) 746c71c9dcSSunny Srivastava { 756c71c9dcSSunny Srivastava log<level::ERR>("Error in mapper GetSubTree", 766c71c9dcSSunny Srivastava entry("ERROR=%s", e.what())); 776c71c9dcSSunny Srivastava } 786c71c9dcSSunny Srivastava 796c71c9dcSSunny Srivastava return result; 806c71c9dcSSunny Srivastava } 816c71c9dcSSunny Srivastava 826c71c9dcSSunny Srivastava } // namespace inventory 836c71c9dcSSunny Srivastava 846c71c9dcSSunny Srivastava LE2ByteData readUInt16LE(Binary::const_iterator iterator) 856c71c9dcSSunny Srivastava { 866c71c9dcSSunny Srivastava LE2ByteData lowByte = *iterator; 876c71c9dcSSunny Srivastava LE2ByteData highByte = *(iterator + 1); 886c71c9dcSSunny Srivastava lowByte |= (highByte << 8); 896c71c9dcSSunny Srivastava return lowByte; 906c71c9dcSSunny Srivastava } 916c71c9dcSSunny Srivastava 926c71c9dcSSunny Srivastava /** @brief Encodes a keyword for D-Bus. 936c71c9dcSSunny Srivastava */ 946c71c9dcSSunny Srivastava string encodeKeyword(const string& kw, const string& encoding) 956c71c9dcSSunny Srivastava { 966c71c9dcSSunny Srivastava if (encoding == "MAC") 976c71c9dcSSunny Srivastava { 986c71c9dcSSunny Srivastava string res{}; 996c71c9dcSSunny Srivastava size_t first = kw[0]; 1006c71c9dcSSunny Srivastava res += toHex(first >> 4); 1016c71c9dcSSunny Srivastava res += toHex(first & 0x0f); 1026c71c9dcSSunny Srivastava for (size_t i = 1; i < kw.size(); ++i) 1036c71c9dcSSunny Srivastava { 1046c71c9dcSSunny Srivastava res += ":"; 1056c71c9dcSSunny Srivastava res += toHex(kw[i] >> 4); 1066c71c9dcSSunny Srivastava res += toHex(kw[i] & 0x0f); 1076c71c9dcSSunny Srivastava } 1086c71c9dcSSunny Srivastava return res; 1096c71c9dcSSunny Srivastava } 1106c71c9dcSSunny Srivastava else if (encoding == "DATE") 1116c71c9dcSSunny Srivastava { 1126c71c9dcSSunny Srivastava // Date, represent as 1136c71c9dcSSunny Srivastava // <year>-<month>-<day> <hour>:<min> 1146c71c9dcSSunny Srivastava string res{}; 1156c71c9dcSSunny Srivastava static constexpr uint8_t skipPrefix = 3; 1166c71c9dcSSunny Srivastava 1176c71c9dcSSunny Srivastava auto strItr = kw.begin(); 1186c71c9dcSSunny Srivastava advance(strItr, skipPrefix); 1196c71c9dcSSunny Srivastava for_each(strItr, kw.end(), [&res](size_t c) { res += c; }); 1206c71c9dcSSunny Srivastava 1216c71c9dcSSunny Srivastava res.insert(BD_YEAR_END, 1, '-'); 1226c71c9dcSSunny Srivastava res.insert(BD_MONTH_END, 1, '-'); 1236c71c9dcSSunny Srivastava res.insert(BD_DAY_END, 1, ' '); 1246c71c9dcSSunny Srivastava res.insert(BD_HOUR_END, 1, ':'); 1256c71c9dcSSunny Srivastava 1266c71c9dcSSunny Srivastava return res; 1276c71c9dcSSunny Srivastava } 1286c71c9dcSSunny Srivastava else // default to string encoding 1296c71c9dcSSunny Srivastava { 1306c71c9dcSSunny Srivastava return string(kw.begin(), kw.end()); 1316c71c9dcSSunny Srivastava } 1326c71c9dcSSunny Srivastava } 1336c71c9dcSSunny Srivastava 1346c71c9dcSSunny Srivastava string readBusProperty(const string& obj, const string& inf, const string& prop) 1356c71c9dcSSunny Srivastava { 1366c71c9dcSSunny Srivastava std::string propVal{}; 1376c71c9dcSSunny Srivastava std::string object = INVENTORY_PATH + obj; 1386c71c9dcSSunny Srivastava auto bus = sdbusplus::bus::new_default(); 1396c71c9dcSSunny Srivastava auto properties = bus.new_method_call( 1406c71c9dcSSunny Srivastava "xyz.openbmc_project.Inventory.Manager", object.c_str(), 1416c71c9dcSSunny Srivastava "org.freedesktop.DBus.Properties", "Get"); 1426c71c9dcSSunny Srivastava properties.append(inf); 1436c71c9dcSSunny Srivastava properties.append(prop); 1446c71c9dcSSunny Srivastava auto result = bus.call(properties); 1456c71c9dcSSunny Srivastava if (!result.is_method_error()) 1466c71c9dcSSunny Srivastava { 1476c71c9dcSSunny Srivastava variant<Binary, string> val; 1486c71c9dcSSunny Srivastava result.read(val); 1496c71c9dcSSunny Srivastava if (auto pVal = get_if<Binary>(&val)) 1506c71c9dcSSunny Srivastava { 1516c71c9dcSSunny Srivastava propVal.assign(reinterpret_cast<const char*>(pVal->data()), 1526c71c9dcSSunny Srivastava pVal->size()); 1536c71c9dcSSunny Srivastava } 1546c71c9dcSSunny Srivastava else if (auto pVal = get_if<string>(&val)) 1556c71c9dcSSunny Srivastava { 1566c71c9dcSSunny Srivastava propVal.assign(pVal->data(), pVal->size()); 1576c71c9dcSSunny Srivastava } 1586c71c9dcSSunny Srivastava } 1596c71c9dcSSunny Srivastava return propVal; 1606c71c9dcSSunny Srivastava } 1616c71c9dcSSunny Srivastava 1626c71c9dcSSunny Srivastava void createPEL(const std::map<std::string, std::string>& additionalData, 1630746eeebSSunny Srivastava const Severity& sev, const std::string& errIntf) 1646c71c9dcSSunny Srivastava { 1656c71c9dcSSunny Srivastava try 1666c71c9dcSSunny Srivastava { 1670746eeebSSunny Srivastava std::string pelSeverity = 1680746eeebSSunny Srivastava "xyz.openbmc_project.Logging.Entry.Level.Error"; 1696c71c9dcSSunny Srivastava auto bus = sdbusplus::bus::new_default(); 1706c71c9dcSSunny Srivastava auto service = getService(bus, loggerObjectPath, loggerCreateInterface); 1716c71c9dcSSunny Srivastava auto method = bus.new_method_call(service.c_str(), loggerObjectPath, 1726c71c9dcSSunny Srivastava loggerCreateInterface, "Create"); 1736c71c9dcSSunny Srivastava 1740746eeebSSunny Srivastava auto itr = sevMap.find(sev); 1750746eeebSSunny Srivastava if (itr != sevMap.end()) 1760746eeebSSunny Srivastava { 1770746eeebSSunny Srivastava pelSeverity = itr->second; 1780746eeebSSunny Srivastava } 1790746eeebSSunny Srivastava 1800746eeebSSunny Srivastava method.append(errIntf, pelSeverity, additionalData); 1816c71c9dcSSunny Srivastava auto resp = bus.call(method); 1826c71c9dcSSunny Srivastava } 183*2eb0176cSPatrick Williams catch (const sdbusplus::exception_t& e) 1846c71c9dcSSunny Srivastava { 1856c71c9dcSSunny Srivastava throw std::runtime_error( 1866c71c9dcSSunny Srivastava "Error in invoking D-Bus logging create interface to register PEL"); 1876c71c9dcSSunny Srivastava } 1886c71c9dcSSunny Srivastava } 1896c71c9dcSSunny Srivastava 1906c71c9dcSSunny Srivastava inventory::VPDfilepath getVpdFilePath(const string& jsonFile, 1916c71c9dcSSunny Srivastava const std::string& ObjPath) 1926c71c9dcSSunny Srivastava { 1936c71c9dcSSunny Srivastava ifstream inventoryJson(jsonFile); 1946c71c9dcSSunny Srivastava const auto& jsonObject = json::parse(inventoryJson); 1956c71c9dcSSunny Srivastava inventory::VPDfilepath filePath{}; 1966c71c9dcSSunny Srivastava 1976c71c9dcSSunny Srivastava if (jsonObject.find("frus") == jsonObject.end()) 1986c71c9dcSSunny Srivastava { 1996c71c9dcSSunny Srivastava throw(VpdJsonException( 2006c71c9dcSSunny Srivastava "Invalid JSON structure - frus{} object not found in ", jsonFile)); 2016c71c9dcSSunny Srivastava } 2026c71c9dcSSunny Srivastava 2036c71c9dcSSunny Srivastava const nlohmann::json& groupFRUS = 2046c71c9dcSSunny Srivastava jsonObject["frus"].get_ref<const nlohmann::json::object_t&>(); 2056c71c9dcSSunny Srivastava for (const auto& itemFRUS : groupFRUS.items()) 2066c71c9dcSSunny Srivastava { 2076c71c9dcSSunny Srivastava const std::vector<nlohmann::json>& groupEEPROM = 2086c71c9dcSSunny Srivastava itemFRUS.value().get_ref<const nlohmann::json::array_t&>(); 2096c71c9dcSSunny Srivastava for (const auto& itemEEPROM : groupEEPROM) 2106c71c9dcSSunny Srivastava { 2116c71c9dcSSunny Srivastava if (itemEEPROM["inventoryPath"] 2126c71c9dcSSunny Srivastava .get_ref<const nlohmann::json::string_t&>() == ObjPath) 2136c71c9dcSSunny Srivastava { 2146c71c9dcSSunny Srivastava filePath = itemFRUS.key(); 2156c71c9dcSSunny Srivastava return filePath; 2166c71c9dcSSunny Srivastava } 2176c71c9dcSSunny Srivastava } 2186c71c9dcSSunny Srivastava } 2196c71c9dcSSunny Srivastava 2206c71c9dcSSunny Srivastava return filePath; 2216c71c9dcSSunny Srivastava } 2226c71c9dcSSunny Srivastava 2236c71c9dcSSunny Srivastava bool isPathInJson(const std::string& eepromPath) 2246c71c9dcSSunny Srivastava { 2256c71c9dcSSunny Srivastava bool present = false; 2266c71c9dcSSunny Srivastava ifstream inventoryJson(INVENTORY_JSON_SYM_LINK); 2276c71c9dcSSunny Srivastava 2286c71c9dcSSunny Srivastava try 2296c71c9dcSSunny Srivastava { 2306c71c9dcSSunny Srivastava auto js = json::parse(inventoryJson); 2316c71c9dcSSunny Srivastava if (js.find("frus") == js.end()) 2326c71c9dcSSunny Srivastava { 2336c71c9dcSSunny Srivastava throw(VpdJsonException( 2346c71c9dcSSunny Srivastava "Invalid JSON structure - frus{} object not found in ", 2356c71c9dcSSunny Srivastava INVENTORY_JSON_SYM_LINK)); 2366c71c9dcSSunny Srivastava } 2376c71c9dcSSunny Srivastava json fruJson = js["frus"]; 2386c71c9dcSSunny Srivastava 2396c71c9dcSSunny Srivastava if (fruJson.find(eepromPath) != fruJson.end()) 2406c71c9dcSSunny Srivastava { 2416c71c9dcSSunny Srivastava present = true; 2426c71c9dcSSunny Srivastava } 2436c71c9dcSSunny Srivastava } 2448e15b93aSPatrick Williams catch (const json::parse_error& ex) 2456c71c9dcSSunny Srivastava { 2466c71c9dcSSunny Srivastava throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK)); 2476c71c9dcSSunny Srivastava } 2486c71c9dcSSunny Srivastava return present; 2496c71c9dcSSunny Srivastava } 2506c71c9dcSSunny Srivastava 2516c71c9dcSSunny Srivastava bool isRecKwInDbusJson(const std::string& recordName, 2526c71c9dcSSunny Srivastava const std::string& keyword) 2536c71c9dcSSunny Srivastava { 2546c71c9dcSSunny Srivastava ifstream propertyJson(DBUS_PROP_JSON); 2556c71c9dcSSunny Srivastava json dbusProperty; 2566c71c9dcSSunny Srivastava bool present = false; 2576c71c9dcSSunny Srivastava 2586c71c9dcSSunny Srivastava if (propertyJson.is_open()) 2596c71c9dcSSunny Srivastava { 2606c71c9dcSSunny Srivastava try 2616c71c9dcSSunny Srivastava { 2626c71c9dcSSunny Srivastava auto dbusPropertyJson = json::parse(propertyJson); 2636c71c9dcSSunny Srivastava if (dbusPropertyJson.find("dbusProperties") == 2646c71c9dcSSunny Srivastava dbusPropertyJson.end()) 2656c71c9dcSSunny Srivastava { 2666c71c9dcSSunny Srivastava throw(VpdJsonException("dbusProperties{} object not found in " 2676c71c9dcSSunny Srivastava "DbusProperties json : ", 2686c71c9dcSSunny Srivastava DBUS_PROP_JSON)); 2696c71c9dcSSunny Srivastava } 2706c71c9dcSSunny Srivastava 2716c71c9dcSSunny Srivastava dbusProperty = dbusPropertyJson["dbusProperties"]; 2726c71c9dcSSunny Srivastava if (dbusProperty.contains(recordName)) 2736c71c9dcSSunny Srivastava { 2746c71c9dcSSunny Srivastava const vector<string>& kwdsToPublish = dbusProperty[recordName]; 2756c71c9dcSSunny Srivastava if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) != 2766c71c9dcSSunny Srivastava kwdsToPublish.end()) // present 2776c71c9dcSSunny Srivastava { 2786c71c9dcSSunny Srivastava present = true; 2796c71c9dcSSunny Srivastava } 2806c71c9dcSSunny Srivastava } 2816c71c9dcSSunny Srivastava } 2828e15b93aSPatrick Williams catch (const json::parse_error& ex) 2836c71c9dcSSunny Srivastava { 2846c71c9dcSSunny Srivastava throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON)); 2856c71c9dcSSunny Srivastava } 2866c71c9dcSSunny Srivastava } 2876c71c9dcSSunny Srivastava else 2886c71c9dcSSunny Srivastava { 2896c71c9dcSSunny Srivastava // If dbus properties json is not available, we assume the given 2906c71c9dcSSunny Srivastava // record-keyword is part of dbus-properties json. So setting the bool 2916c71c9dcSSunny Srivastava // variable to true. 2926c71c9dcSSunny Srivastava present = true; 2936c71c9dcSSunny Srivastava } 2946c71c9dcSSunny Srivastava return present; 2956c71c9dcSSunny Srivastava } 2966c71c9dcSSunny Srivastava 2976c71c9dcSSunny Srivastava vpdType vpdTypeCheck(const Binary& vpdVector) 2986c71c9dcSSunny Srivastava { 2996c71c9dcSSunny Srivastava // Read first 3 Bytes to check the 11S bar code format 3006c71c9dcSSunny Srivastava std::string is11SFormat = ""; 3016c71c9dcSSunny Srivastava for (uint8_t i = 0; i < FORMAT_11S_LEN; i++) 3026c71c9dcSSunny Srivastava { 3036c71c9dcSSunny Srivastava is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i]; 3046c71c9dcSSunny Srivastava } 3056c71c9dcSSunny Srivastava 3066c71c9dcSSunny Srivastava if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG) 3076c71c9dcSSunny Srivastava { 3086c71c9dcSSunny Srivastava // IPZ VPD FORMAT 3096c71c9dcSSunny Srivastava return vpdType::IPZ_VPD; 3106c71c9dcSSunny Srivastava } 3116c71c9dcSSunny Srivastava else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG) 3126c71c9dcSSunny Srivastava { 3136c71c9dcSSunny Srivastava // KEYWORD VPD FORMAT 3146c71c9dcSSunny Srivastava return vpdType::KEYWORD_VPD; 3156c71c9dcSSunny Srivastava } 3166c71c9dcSSunny Srivastava else if (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0) 3176c71c9dcSSunny Srivastava { 3186c71c9dcSSunny Srivastava // Memory VPD format 3196c71c9dcSSunny Srivastava return vpdType::MEMORY_VPD; 3206c71c9dcSSunny Srivastava } 3216c71c9dcSSunny Srivastava 3226c71c9dcSSunny Srivastava // INVALID VPD FORMAT 3236c71c9dcSSunny Srivastava return vpdType::INVALID_VPD_FORMAT; 3246c71c9dcSSunny Srivastava } 3256c71c9dcSSunny Srivastava 326f05effdbSAlpana Kumari const string getIM(const Parsed& vpdMap) 327f05effdbSAlpana Kumari { 328f05effdbSAlpana Kumari Binary imVal; 329f05effdbSAlpana Kumari auto property = vpdMap.find("VSBP"); 330f05effdbSAlpana Kumari if (property != vpdMap.end()) 331f05effdbSAlpana Kumari { 332f05effdbSAlpana Kumari auto kw = (property->second).find("IM"); 333f05effdbSAlpana Kumari if (kw != (property->second).end()) 334f05effdbSAlpana Kumari { 335f05effdbSAlpana Kumari copy(kw->second.begin(), kw->second.end(), back_inserter(imVal)); 336f05effdbSAlpana Kumari } 337f05effdbSAlpana Kumari } 338f05effdbSAlpana Kumari 339f05effdbSAlpana Kumari ostringstream oss; 340f05effdbSAlpana Kumari for (auto& i : imVal) 341f05effdbSAlpana Kumari { 342f05effdbSAlpana Kumari oss << setw(2) << setfill('0') << hex << static_cast<int>(i); 343f05effdbSAlpana Kumari } 344f05effdbSAlpana Kumari 345f05effdbSAlpana Kumari return oss.str(); 346f05effdbSAlpana Kumari } 347f05effdbSAlpana Kumari 348f05effdbSAlpana Kumari const string getHW(const Parsed& vpdMap) 349f05effdbSAlpana Kumari { 350f05effdbSAlpana Kumari Binary hwVal; 351f05effdbSAlpana Kumari auto prop = vpdMap.find("VINI"); 352f05effdbSAlpana Kumari if (prop != vpdMap.end()) 353f05effdbSAlpana Kumari { 354f05effdbSAlpana Kumari auto kw = (prop->second).find("HW"); 355f05effdbSAlpana Kumari if (kw != (prop->second).end()) 356f05effdbSAlpana Kumari { 357f05effdbSAlpana Kumari copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal)); 358f05effdbSAlpana Kumari } 359f05effdbSAlpana Kumari } 360f05effdbSAlpana Kumari 36188d2ae82SAlpana Kumari // The planar pass only comes from the LSB of the HW keyword, 36288d2ae82SAlpana Kumari // where as the MSB is used for other purposes such as signifying clock 36388d2ae82SAlpana Kumari // termination. 36488d2ae82SAlpana Kumari hwVal[0] = 0x00; 36588d2ae82SAlpana Kumari 366f05effdbSAlpana Kumari ostringstream hwString; 367f05effdbSAlpana Kumari for (auto& i : hwVal) 368f05effdbSAlpana Kumari { 369f05effdbSAlpana Kumari hwString << setw(2) << setfill('0') << hex << static_cast<int>(i); 370f05effdbSAlpana Kumari } 371f05effdbSAlpana Kumari 372f05effdbSAlpana Kumari return hwString.str(); 373f05effdbSAlpana Kumari } 374f05effdbSAlpana Kumari 375f05effdbSAlpana Kumari string getSystemsJson(const Parsed& vpdMap) 376f05effdbSAlpana Kumari { 377f05effdbSAlpana Kumari string jsonPath = "/usr/share/vpd/"; 378f05effdbSAlpana Kumari string jsonName{}; 379f05effdbSAlpana Kumari 380f05effdbSAlpana Kumari ifstream systemJson(SYSTEM_JSON); 381f05effdbSAlpana Kumari if (!systemJson) 382f05effdbSAlpana Kumari { 383f05effdbSAlpana Kumari throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON))); 384f05effdbSAlpana Kumari } 385f05effdbSAlpana Kumari 386f05effdbSAlpana Kumari try 387f05effdbSAlpana Kumari { 388f05effdbSAlpana Kumari auto js = json::parse(systemJson); 389f05effdbSAlpana Kumari 3901b026119SAlpana Kumari string hwKeyword = getHW(vpdMap); 391f05effdbSAlpana Kumari const string imKeyword = getIM(vpdMap); 392f05effdbSAlpana Kumari 3931b026119SAlpana Kumari transform(hwKeyword.begin(), hwKeyword.end(), hwKeyword.begin(), 3941b026119SAlpana Kumari ::toupper); 3951b026119SAlpana Kumari 396f05effdbSAlpana Kumari if (js.find("system") == js.end()) 397f05effdbSAlpana Kumari { 398f05effdbSAlpana Kumari throw runtime_error("Invalid systems Json"); 399f05effdbSAlpana Kumari } 400f05effdbSAlpana Kumari 401f05effdbSAlpana Kumari if (js["system"].find(imKeyword) == js["system"].end()) 402f05effdbSAlpana Kumari { 403f05effdbSAlpana Kumari throw runtime_error( 404f05effdbSAlpana Kumari "Invalid system. This system type is not present " 405f05effdbSAlpana Kumari "in the systemsJson. IM: " + 406f05effdbSAlpana Kumari imKeyword); 407f05effdbSAlpana Kumari } 408f05effdbSAlpana Kumari 409f05effdbSAlpana Kumari if ((js["system"][imKeyword].find("constraint") != 410f05effdbSAlpana Kumari js["system"][imKeyword].end()) && 4111b026119SAlpana Kumari js["system"][imKeyword]["constraint"].find("HW") != 4121b026119SAlpana Kumari js["system"][imKeyword]["constraint"].end()) 4131b026119SAlpana Kumari { 4141b026119SAlpana Kumari // collect hw versions from json, and check hwKeyword is part of it 4151b026119SAlpana Kumari // if hwKeyword is found there then load respective json 4161b026119SAlpana Kumari // otherwise load default one. 4171b026119SAlpana Kumari for (const auto& hwVersion : 4181b026119SAlpana Kumari js["system"][imKeyword]["constraint"]["HW"]) 4191b026119SAlpana Kumari { 4201b026119SAlpana Kumari string hw = hwVersion; 4211b026119SAlpana Kumari transform(hw.begin(), hw.end(), hw.begin(), ::toupper); 4221b026119SAlpana Kumari 4231b026119SAlpana Kumari if (hw == hwKeyword) 424f05effdbSAlpana Kumari { 425f05effdbSAlpana Kumari jsonName = js["system"][imKeyword]["constraint"]["json"]; 4261b026119SAlpana Kumari break; 4271b026119SAlpana Kumari } 4281b026119SAlpana Kumari } 4291b026119SAlpana Kumari 4301b026119SAlpana Kumari if (jsonName.empty() && js["system"][imKeyword].find("default") != 4311b026119SAlpana Kumari js["system"][imKeyword].end()) 4321b026119SAlpana Kumari { 4331b026119SAlpana Kumari jsonName = js["system"][imKeyword]["default"]; 4341b026119SAlpana Kumari } 435f05effdbSAlpana Kumari } 436f05effdbSAlpana Kumari else if (js["system"][imKeyword].find("default") != 437f05effdbSAlpana Kumari js["system"][imKeyword].end()) 438f05effdbSAlpana Kumari { 439f05effdbSAlpana Kumari jsonName = js["system"][imKeyword]["default"]; 440f05effdbSAlpana Kumari } 441f05effdbSAlpana Kumari else 442f05effdbSAlpana Kumari { 443f05effdbSAlpana Kumari throw runtime_error( 444f05effdbSAlpana Kumari "Bad System json. Neither constraint nor default found"); 445f05effdbSAlpana Kumari } 446f05effdbSAlpana Kumari 447f05effdbSAlpana Kumari jsonPath += jsonName; 448f05effdbSAlpana Kumari } 449f05effdbSAlpana Kumari 4508e15b93aSPatrick Williams catch (const json::parse_error& ex) 451f05effdbSAlpana Kumari { 452f05effdbSAlpana Kumari throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON)); 453f05effdbSAlpana Kumari } 454f05effdbSAlpana Kumari return jsonPath; 455f05effdbSAlpana Kumari } 456f05effdbSAlpana Kumari 457647868edSPriyangaRamasamy void udevToGenericPath(string& file) 458647868edSPriyangaRamasamy { 459647868edSPriyangaRamasamy // Sample udevEvent i2c path : 460647868edSPriyangaRamasamy // "/sys/devices/platform/ahb/ahb:apb/ahb:apb:bus@1e78a000/1e78a480.i2c-bus/i2c-8/8-0051/8-00510/nvmem" 461647868edSPriyangaRamasamy // find if the path contains the word i2c in it. 462647868edSPriyangaRamasamy if (file.find("i2c") != string::npos) 463647868edSPriyangaRamasamy { 464647868edSPriyangaRamasamy string i2cBusAddr{}; 465647868edSPriyangaRamasamy 466647868edSPriyangaRamasamy // Every udev i2c path should have the common pattern 467647868edSPriyangaRamasamy // "i2c-bus_number/bus_number-vpd_address". Search for 468647868edSPriyangaRamasamy // "bus_number-vpd_address". 469647868edSPriyangaRamasamy regex i2cPattern("((i2c)-[0-9]+\\/)([0-9]+-[0-9]{4})"); 470647868edSPriyangaRamasamy smatch match; 471647868edSPriyangaRamasamy if (regex_search(file, match, i2cPattern)) 472647868edSPriyangaRamasamy { 473647868edSPriyangaRamasamy i2cBusAddr = match.str(3); 474647868edSPriyangaRamasamy } 475647868edSPriyangaRamasamy else 476647868edSPriyangaRamasamy { 477647868edSPriyangaRamasamy cerr << "The given udev path < " << file 478647868edSPriyangaRamasamy << " > doesn't match the required pattern. Skipping VPD " 479647868edSPriyangaRamasamy "collection." 480647868edSPriyangaRamasamy << endl; 481647868edSPriyangaRamasamy exit(EXIT_SUCCESS); 482647868edSPriyangaRamasamy } 483647868edSPriyangaRamasamy // Forming the generic file path 484647868edSPriyangaRamasamy file = i2cPathPrefix + i2cBusAddr + "/eeprom"; 485647868edSPriyangaRamasamy } 486647868edSPriyangaRamasamy // Sample udevEvent spi path : 487647868edSPriyangaRamasamy // "/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" 488647868edSPriyangaRamasamy // find if the path contains the word spi in it. 489647868edSPriyangaRamasamy else if (file.find("spi") != string::npos) 490647868edSPriyangaRamasamy { 491647868edSPriyangaRamasamy // Every udev spi path will have common pattern "spi<Digit>/", which 492647868edSPriyangaRamasamy // describes the spi bus number at which the fru is connected; Followed 493647868edSPriyangaRamasamy // by a slash following the vpd address of the fru. Taking the above 494647868edSPriyangaRamasamy // input as a common key, we try to search for the pattern "spi<Digit>/" 495647868edSPriyangaRamasamy // using regular expression. 496647868edSPriyangaRamasamy regex spiPattern("((spi)[0-9]+)(\\/)"); 497647868edSPriyangaRamasamy string spiBus{}; 498647868edSPriyangaRamasamy smatch match; 499647868edSPriyangaRamasamy if (regex_search(file, match, spiPattern)) 500647868edSPriyangaRamasamy { 501647868edSPriyangaRamasamy spiBus = match.str(1); 502647868edSPriyangaRamasamy } 503647868edSPriyangaRamasamy else 504647868edSPriyangaRamasamy { 505647868edSPriyangaRamasamy cerr << "The given udev path < " << file 506647868edSPriyangaRamasamy << " > doesn't match the required pattern. Skipping VPD " 507647868edSPriyangaRamasamy "collection." 508647868edSPriyangaRamasamy << endl; 509647868edSPriyangaRamasamy exit(EXIT_SUCCESS); 510647868edSPriyangaRamasamy } 511647868edSPriyangaRamasamy // Forming the generic path 512647868edSPriyangaRamasamy file = spiPathPrefix + spiBus + ".0/eeprom"; 513647868edSPriyangaRamasamy } 514647868edSPriyangaRamasamy else 515647868edSPriyangaRamasamy { 516647868edSPriyangaRamasamy cerr << "\n The given EEPROM path < " << file 517647868edSPriyangaRamasamy << " > is not valid. It's neither I2C nor " 518647868edSPriyangaRamasamy "SPI path. Skipping VPD collection.." 519647868edSPriyangaRamasamy << endl; 520647868edSPriyangaRamasamy exit(EXIT_SUCCESS); 521647868edSPriyangaRamasamy } 522647868edSPriyangaRamasamy } 523c2fe40f8SPriyangaRamasamy string getBadVpdName(const string& file) 524c2fe40f8SPriyangaRamasamy { 525c2fe40f8SPriyangaRamasamy string badVpd = BAD_VPD_DIR; 526c2fe40f8SPriyangaRamasamy if (file.find("i2c") != string::npos) 527c2fe40f8SPriyangaRamasamy { 528c2fe40f8SPriyangaRamasamy badVpd += "i2c-"; 529c2fe40f8SPriyangaRamasamy regex i2cPattern("(at24/)([0-9]+-[0-9]+)\\/"); 530c2fe40f8SPriyangaRamasamy smatch match; 531c2fe40f8SPriyangaRamasamy if (regex_search(file, match, i2cPattern)) 532c2fe40f8SPriyangaRamasamy { 533c2fe40f8SPriyangaRamasamy badVpd += match.str(2); 534c2fe40f8SPriyangaRamasamy } 535c2fe40f8SPriyangaRamasamy } 536c2fe40f8SPriyangaRamasamy else if (file.find("spi") != string::npos) 537c2fe40f8SPriyangaRamasamy { 538c2fe40f8SPriyangaRamasamy regex spiPattern("((spi)[0-9]+)(.0)"); 539c2fe40f8SPriyangaRamasamy smatch match; 540c2fe40f8SPriyangaRamasamy if (regex_search(file, match, spiPattern)) 541c2fe40f8SPriyangaRamasamy { 542c2fe40f8SPriyangaRamasamy badVpd += match.str(1); 543c2fe40f8SPriyangaRamasamy } 544c2fe40f8SPriyangaRamasamy } 545c2fe40f8SPriyangaRamasamy return badVpd; 546c2fe40f8SPriyangaRamasamy } 547c2fe40f8SPriyangaRamasamy 548c2fe40f8SPriyangaRamasamy void dumpBadVpd(const string& file, const Binary& vpdVector) 549c2fe40f8SPriyangaRamasamy { 550c2fe40f8SPriyangaRamasamy fs::path badVpdDir = BAD_VPD_DIR; 551c2fe40f8SPriyangaRamasamy fs::create_directory(badVpdDir); 552c2fe40f8SPriyangaRamasamy string badVpdPath = getBadVpdName(file); 553c2fe40f8SPriyangaRamasamy if (fs::exists(badVpdPath)) 554c2fe40f8SPriyangaRamasamy { 555c2fe40f8SPriyangaRamasamy std::error_code ec; 556c2fe40f8SPriyangaRamasamy fs::remove(badVpdPath, ec); 557c2fe40f8SPriyangaRamasamy if (ec) // error code 558c2fe40f8SPriyangaRamasamy { 559c2fe40f8SPriyangaRamasamy string error = "Error removing the existing broken vpd in "; 560c2fe40f8SPriyangaRamasamy error += badVpdPath; 561c2fe40f8SPriyangaRamasamy error += ". Error code : "; 562c2fe40f8SPriyangaRamasamy error += ec.value(); 563c2fe40f8SPriyangaRamasamy error += ". Error message : "; 564c2fe40f8SPriyangaRamasamy error += ec.message(); 565c2fe40f8SPriyangaRamasamy throw runtime_error(error); 566c2fe40f8SPriyangaRamasamy } 567c2fe40f8SPriyangaRamasamy } 568c2fe40f8SPriyangaRamasamy ofstream badVpdFileStream(badVpdPath, ofstream::binary); 569c2fe40f8SPriyangaRamasamy if (!badVpdFileStream) 570c2fe40f8SPriyangaRamasamy { 571c2fe40f8SPriyangaRamasamy throw runtime_error("Failed to open bad vpd file path in /tmp/bad-vpd. " 572c2fe40f8SPriyangaRamasamy "Unable to dump the broken/bad vpd file."); 573c2fe40f8SPriyangaRamasamy } 574c2fe40f8SPriyangaRamasamy badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()), 575c2fe40f8SPriyangaRamasamy vpdVector.size()); 576c2fe40f8SPriyangaRamasamy } 5777ce68724Salpana07 5787ce68724Salpana07 const string getKwVal(const Parsed& vpdMap, const string& rec, 5797ce68724Salpana07 const string& kwd) 5807ce68724Salpana07 { 5817ce68724Salpana07 string kwVal{}; 5827ce68724Salpana07 5837ce68724Salpana07 auto findRec = vpdMap.find(rec); 5847ce68724Salpana07 5857ce68724Salpana07 // check if record is found in map we got by parser 5867ce68724Salpana07 if (findRec != vpdMap.end()) 5877ce68724Salpana07 { 5887ce68724Salpana07 auto findKwd = findRec->second.find(kwd); 5897ce68724Salpana07 5907ce68724Salpana07 if (findKwd != findRec->second.end()) 5917ce68724Salpana07 { 5927ce68724Salpana07 kwVal = findKwd->second; 5937ce68724Salpana07 } 5947ce68724Salpana07 } 5957ce68724Salpana07 5967ce68724Salpana07 return kwVal; 5977ce68724Salpana07 } 5987ce68724Salpana07 599c9ecf8eaSPriyanga Ramasamy string byteArrayToHexString(const Binary& vec) 60002434931SPriyanga Ramasamy { 60102434931SPriyanga Ramasamy stringstream ss; 60202434931SPriyanga Ramasamy string hexRep = "0x"; 60302434931SPriyanga Ramasamy ss << hexRep; 604c9ecf8eaSPriyanga Ramasamy string str = ss.str(); 60502434931SPriyanga Ramasamy 606c9ecf8eaSPriyanga Ramasamy // convert Decimal to Hex string 60702434931SPriyanga Ramasamy for (auto& v : vec) 60802434931SPriyanga Ramasamy { 60902434931SPriyanga Ramasamy ss << setfill('0') << setw(2) << hex << (int)v; 61002434931SPriyanga Ramasamy str = ss.str(); 61102434931SPriyanga Ramasamy } 612c9ecf8eaSPriyanga Ramasamy return str; 613c9ecf8eaSPriyanga Ramasamy } 614c9ecf8eaSPriyanga Ramasamy 615c9ecf8eaSPriyanga Ramasamy string getPrintableValue(const Binary& vec) 616c9ecf8eaSPriyanga Ramasamy { 617c9ecf8eaSPriyanga Ramasamy string str{}; 618c9ecf8eaSPriyanga Ramasamy 619c9ecf8eaSPriyanga Ramasamy // find for a non printable value in the vector 620c9ecf8eaSPriyanga Ramasamy const auto it = std::find_if(vec.begin(), vec.end(), 621c9ecf8eaSPriyanga Ramasamy [](const auto& ele) { return !isprint(ele); }); 622c9ecf8eaSPriyanga Ramasamy 623c9ecf8eaSPriyanga Ramasamy if (it != vec.end()) // if the given vector has any non printable value 624c9ecf8eaSPriyanga Ramasamy { 625c9ecf8eaSPriyanga Ramasamy for (auto itr = it; itr != vec.end(); itr++) 626c9ecf8eaSPriyanga Ramasamy { 627c9ecf8eaSPriyanga Ramasamy if (*itr != 0x00) 628c9ecf8eaSPriyanga Ramasamy { 629c9ecf8eaSPriyanga Ramasamy str = byteArrayToHexString(vec); 630c9ecf8eaSPriyanga Ramasamy return str; 631c9ecf8eaSPriyanga Ramasamy } 632c9ecf8eaSPriyanga Ramasamy } 633c9ecf8eaSPriyanga Ramasamy str = string(vec.begin(), it); 63402434931SPriyanga Ramasamy } 63502434931SPriyanga Ramasamy else 63602434931SPriyanga Ramasamy { 63702434931SPriyanga Ramasamy str = string(vec.begin(), vec.end()); 63802434931SPriyanga Ramasamy } 63902434931SPriyanga Ramasamy return str; 64002434931SPriyanga Ramasamy } 64102434931SPriyanga Ramasamy 6426bd095f9SAlpana Kumari /* 6436bd095f9SAlpana Kumari * @brief Log PEL for GPIO exception 6446bd095f9SAlpana Kumari * 6456bd095f9SAlpana Kumari * @param[in] gpioErr gpioError type exception 6466bd095f9SAlpana Kumari * @param[in] i2cBusAddr I2C bus and address 6476bd095f9SAlpana Kumari */ 6486bd095f9SAlpana Kumari void logGpioPel(const string& gpioErr, const string& i2cBusAddr) 6496bd095f9SAlpana Kumari { 6506bd095f9SAlpana Kumari // Get the IIC details 6516bd095f9SAlpana Kumari vector<string> i2cReg; 6526bd095f9SAlpana Kumari boost::split(i2cReg, i2cBusAddr, boost::is_any_of("-")); 6536bd095f9SAlpana Kumari 6546bd095f9SAlpana Kumari PelAdditionalData additionalData{}; 6556bd095f9SAlpana Kumari if (i2cReg.size() == 2) 6566bd095f9SAlpana Kumari { 6576bd095f9SAlpana Kumari additionalData.emplace("CALLOUT_IIC_BUS", i2cReg[0]); 6586bd095f9SAlpana Kumari additionalData.emplace("CALLOUT_IIC_ADDR", "0x" + i2cReg[1]); 6596bd095f9SAlpana Kumari } 6606bd095f9SAlpana Kumari 6616bd095f9SAlpana Kumari additionalData.emplace("DESCRIPTION", gpioErr); 6626bd095f9SAlpana Kumari createPEL(additionalData, PelSeverity::WARNING, errIntfForGpioError); 6636bd095f9SAlpana Kumari } 6646bd095f9SAlpana Kumari 665735dee9bSAlpana Kumari void executePostFailAction(const nlohmann::json& json, const string& file) 666735dee9bSAlpana Kumari { 667735dee9bSAlpana Kumari if ((json["frus"][file].at(0)).find("postActionFail") == 668735dee9bSAlpana Kumari json["frus"][file].at(0).end()) 669735dee9bSAlpana Kumari { 670735dee9bSAlpana Kumari return; 671735dee9bSAlpana Kumari } 672735dee9bSAlpana Kumari 673735dee9bSAlpana Kumari uint8_t pinValue = 0; 674735dee9bSAlpana Kumari string pinName; 675735dee9bSAlpana Kumari 676735dee9bSAlpana Kumari for (const auto& postAction : 677735dee9bSAlpana Kumari (json["frus"][file].at(0))["postActionFail"].items()) 678735dee9bSAlpana Kumari { 679735dee9bSAlpana Kumari if (postAction.key() == "pin") 680735dee9bSAlpana Kumari { 681735dee9bSAlpana Kumari pinName = postAction.value(); 682735dee9bSAlpana Kumari } 683735dee9bSAlpana Kumari else if (postAction.key() == "value") 684735dee9bSAlpana Kumari { 685735dee9bSAlpana Kumari // Get the value to set 686735dee9bSAlpana Kumari pinValue = postAction.value(); 687735dee9bSAlpana Kumari } 688735dee9bSAlpana Kumari } 689735dee9bSAlpana Kumari 690735dee9bSAlpana Kumari cout << "Setting GPIO: " << pinName << " to " << (int)pinValue << endl; 691735dee9bSAlpana Kumari 692735dee9bSAlpana Kumari try 693735dee9bSAlpana Kumari { 694735dee9bSAlpana Kumari gpiod::line outputLine = gpiod::find_line(pinName); 695735dee9bSAlpana Kumari 696735dee9bSAlpana Kumari if (!outputLine) 697735dee9bSAlpana Kumari { 6986bd095f9SAlpana Kumari throw runtime_error( 6996bd095f9SAlpana Kumari "Couldn't find output line for the GPIO. Skipping " 7006bd095f9SAlpana Kumari "this GPIO action."); 701735dee9bSAlpana Kumari } 702735dee9bSAlpana Kumari outputLine.request( 703735dee9bSAlpana Kumari {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0}, 704735dee9bSAlpana Kumari pinValue); 705735dee9bSAlpana Kumari } 7066bd095f9SAlpana Kumari catch (const exception& e) 707735dee9bSAlpana Kumari { 7086bd095f9SAlpana Kumari string i2cBusAddr; 7096bd095f9SAlpana Kumari string errMsg = e.what(); 7106bd095f9SAlpana Kumari errMsg += "\nGPIO: " + pinName; 7116bd095f9SAlpana Kumari 7126bd095f9SAlpana Kumari if ((json["frus"][file].at(0)["postActionFail"].find( 7136bd095f9SAlpana Kumari "gpioI2CAddress")) != 7146bd095f9SAlpana Kumari json["frus"][file].at(0)["postActionFail"].end()) 7156bd095f9SAlpana Kumari { 7166bd095f9SAlpana Kumari i2cBusAddr = 7176bd095f9SAlpana Kumari json["frus"][file].at(0)["postActionFail"]["gpioI2CAddress"]; 718735dee9bSAlpana Kumari } 7196bd095f9SAlpana Kumari 7206bd095f9SAlpana Kumari logGpioPel(errMsg, i2cBusAddr); 7216bd095f9SAlpana Kumari } 7226bd095f9SAlpana Kumari 7236bd095f9SAlpana Kumari return; 724735dee9bSAlpana Kumari } 725735dee9bSAlpana Kumari 72653b38ed0SSantosh Puranik std::optional<bool> isPresent(const nlohmann::json& json, const string& file) 72753b38ed0SSantosh Puranik 728735dee9bSAlpana Kumari { 729735dee9bSAlpana Kumari if ((json["frus"][file].at(0)).find("presence") != 730735dee9bSAlpana Kumari json["frus"][file].at(0).end()) 731735dee9bSAlpana Kumari { 732735dee9bSAlpana Kumari if (((json["frus"][file].at(0)["presence"]).find("pin") != 733735dee9bSAlpana Kumari json["frus"][file].at(0)["presence"].end()) && 734735dee9bSAlpana Kumari ((json["frus"][file].at(0)["presence"]).find("value") != 735735dee9bSAlpana Kumari json["frus"][file].at(0)["presence"].end())) 736735dee9bSAlpana Kumari { 737735dee9bSAlpana Kumari string presPinName = json["frus"][file].at(0)["presence"]["pin"]; 738735dee9bSAlpana Kumari Byte presPinValue = json["frus"][file].at(0)["presence"]["value"]; 739735dee9bSAlpana Kumari 740735dee9bSAlpana Kumari try 741735dee9bSAlpana Kumari { 742735dee9bSAlpana Kumari gpiod::line presenceLine = gpiod::find_line(presPinName); 743735dee9bSAlpana Kumari 744735dee9bSAlpana Kumari if (!presenceLine) 745735dee9bSAlpana Kumari { 74640d1c196SAlpana Kumari cerr << "Couldn't find the presence line for - " 74740d1c196SAlpana Kumari << presPinName << endl; 74840d1c196SAlpana Kumari 7496bd095f9SAlpana Kumari throw runtime_error( 7506bd095f9SAlpana Kumari "Couldn't find the presence line for the " 7516bd095f9SAlpana Kumari "GPIO. Skipping this GPIO action."); 752735dee9bSAlpana Kumari } 753735dee9bSAlpana Kumari 754735dee9bSAlpana Kumari presenceLine.request({"Read the presence line", 755735dee9bSAlpana Kumari gpiod::line_request::DIRECTION_INPUT, 0}); 756735dee9bSAlpana Kumari 757735dee9bSAlpana Kumari Byte gpioData = presenceLine.get_value(); 758735dee9bSAlpana Kumari 75953b38ed0SSantosh Puranik return (gpioData == presPinValue); 760735dee9bSAlpana Kumari } 7616bd095f9SAlpana Kumari catch (const exception& e) 762735dee9bSAlpana Kumari { 7636bd095f9SAlpana Kumari string i2cBusAddr; 7646bd095f9SAlpana Kumari string errMsg = e.what(); 7656bd095f9SAlpana Kumari errMsg += " GPIO : " + presPinName; 7666bd095f9SAlpana Kumari 7676bd095f9SAlpana Kumari if ((json["frus"][file].at(0)["presence"]) 7686bd095f9SAlpana Kumari .find("gpioI2CAddress") != 7696bd095f9SAlpana Kumari json["frus"][file].at(0)["presence"].end()) 7706bd095f9SAlpana Kumari { 7716bd095f9SAlpana Kumari i2cBusAddr = 7726bd095f9SAlpana Kumari json["frus"][file].at(0)["presence"]["gpioI2CAddress"]; 7736bd095f9SAlpana Kumari } 7746bd095f9SAlpana Kumari 7756bd095f9SAlpana Kumari logGpioPel(errMsg, i2cBusAddr); 77640d1c196SAlpana Kumari // Take failure postAction 77740d1c196SAlpana Kumari executePostFailAction(json, file); 778735dee9bSAlpana Kumari return false; 779735dee9bSAlpana Kumari } 780735dee9bSAlpana Kumari } 78140d1c196SAlpana Kumari else 78240d1c196SAlpana Kumari { 78340d1c196SAlpana Kumari // missing required informations 78440d1c196SAlpana Kumari cerr << "VPD inventory JSON missing basic informations of presence " 78540d1c196SAlpana Kumari "for this FRU : [" 78640d1c196SAlpana Kumari << file << "]. Executing executePostFailAction." << endl; 78740d1c196SAlpana Kumari 78840d1c196SAlpana Kumari // Take failure postAction 78940d1c196SAlpana Kumari executePostFailAction(json, file); 79040d1c196SAlpana Kumari 79140d1c196SAlpana Kumari return false; 79240d1c196SAlpana Kumari } 793735dee9bSAlpana Kumari } 79453b38ed0SSantosh Puranik return std::optional<bool>{}; 79553b38ed0SSantosh Puranik } 79653b38ed0SSantosh Puranik 79753b38ed0SSantosh Puranik bool executePreAction(const nlohmann::json& json, const string& file) 79853b38ed0SSantosh Puranik { 79953b38ed0SSantosh Puranik auto present = isPresent(json, file); 80053b38ed0SSantosh Puranik if (present && !present.value()) 80153b38ed0SSantosh Puranik { 80253b38ed0SSantosh Puranik executePostFailAction(json, file); 80353b38ed0SSantosh Puranik return false; 80453b38ed0SSantosh Puranik } 805735dee9bSAlpana Kumari 806735dee9bSAlpana Kumari if ((json["frus"][file].at(0)).find("preAction") != 807735dee9bSAlpana Kumari json["frus"][file].at(0).end()) 808735dee9bSAlpana Kumari { 809735dee9bSAlpana Kumari if (((json["frus"][file].at(0)["preAction"]).find("pin") != 810735dee9bSAlpana Kumari json["frus"][file].at(0)["preAction"].end()) && 811735dee9bSAlpana Kumari ((json["frus"][file].at(0)["preAction"]).find("value") != 812735dee9bSAlpana Kumari json["frus"][file].at(0)["preAction"].end())) 813735dee9bSAlpana Kumari { 814735dee9bSAlpana Kumari string pinName = json["frus"][file].at(0)["preAction"]["pin"]; 815735dee9bSAlpana Kumari // Get the value to set 816735dee9bSAlpana Kumari Byte pinValue = json["frus"][file].at(0)["preAction"]["value"]; 817735dee9bSAlpana Kumari 818735dee9bSAlpana Kumari cout << "Setting GPIO: " << pinName << " to " << (int)pinValue 819735dee9bSAlpana Kumari << endl; 820735dee9bSAlpana Kumari try 821735dee9bSAlpana Kumari { 822735dee9bSAlpana Kumari gpiod::line outputLine = gpiod::find_line(pinName); 823735dee9bSAlpana Kumari 824735dee9bSAlpana Kumari if (!outputLine) 825735dee9bSAlpana Kumari { 82640d1c196SAlpana Kumari cerr << "Couldn't find the line for output pin - " 82740d1c196SAlpana Kumari << pinName << endl; 8286bd095f9SAlpana Kumari throw runtime_error( 8296bd095f9SAlpana Kumari "Couldn't find output line for the GPIO. " 8306bd095f9SAlpana Kumari "Skipping this GPIO action."); 831735dee9bSAlpana Kumari } 832735dee9bSAlpana Kumari outputLine.request({"FRU pre-action", 833735dee9bSAlpana Kumari ::gpiod::line_request::DIRECTION_OUTPUT, 0}, 834735dee9bSAlpana Kumari pinValue); 835735dee9bSAlpana Kumari } 8366bd095f9SAlpana Kumari catch (const exception& e) 837735dee9bSAlpana Kumari { 8386bd095f9SAlpana Kumari string i2cBusAddr; 8396bd095f9SAlpana Kumari string errMsg = e.what(); 8406bd095f9SAlpana Kumari errMsg += " GPIO : " + pinName; 8416bd095f9SAlpana Kumari 8426bd095f9SAlpana Kumari if ((json["frus"][file].at(0)["preAction"]) 8436bd095f9SAlpana Kumari .find("gpioI2CAddress") != 8446bd095f9SAlpana Kumari json["frus"][file].at(0)["preAction"].end()) 8456bd095f9SAlpana Kumari { 8466bd095f9SAlpana Kumari i2cBusAddr = 8476bd095f9SAlpana Kumari json["frus"][file].at(0)["preAction"]["gpioI2CAddress"]; 8486bd095f9SAlpana Kumari } 8496bd095f9SAlpana Kumari 8506bd095f9SAlpana Kumari logGpioPel(errMsg, i2cBusAddr); 85140d1c196SAlpana Kumari 85240d1c196SAlpana Kumari // Take failure postAction 85340d1c196SAlpana Kumari executePostFailAction(json, file); 85440d1c196SAlpana Kumari 855735dee9bSAlpana Kumari return false; 856735dee9bSAlpana Kumari } 857735dee9bSAlpana Kumari } 85840d1c196SAlpana Kumari else 85940d1c196SAlpana Kumari { 86040d1c196SAlpana Kumari // missing required informations 86140d1c196SAlpana Kumari cerr 86240d1c196SAlpana Kumari << "VPD inventory JSON missing basic informations of preAction " 86340d1c196SAlpana Kumari "for this FRU : [" 86440d1c196SAlpana Kumari << file << "]. Executing executePostFailAction." << endl; 86540d1c196SAlpana Kumari 86640d1c196SAlpana Kumari // Take failure postAction 86740d1c196SAlpana Kumari executePostFailAction(json, file); 86840d1c196SAlpana Kumari 86940d1c196SAlpana Kumari return false; 87040d1c196SAlpana Kumari } 871735dee9bSAlpana Kumari } 872735dee9bSAlpana Kumari return true; 873735dee9bSAlpana Kumari } 874735dee9bSAlpana Kumari 875aa8a893eSPriyanga Ramasamy void insertOrMerge(inventory::InterfaceMap& map, 876aa8a893eSPriyanga Ramasamy const inventory::Interface& interface, 877aa8a893eSPriyanga Ramasamy inventory::PropertyMap&& property) 878aa8a893eSPriyanga Ramasamy { 879aa8a893eSPriyanga Ramasamy if (map.find(interface) != map.end()) 880aa8a893eSPriyanga Ramasamy { 881aa8a893eSPriyanga Ramasamy auto& prop = map.at(interface); 882aa8a893eSPriyanga Ramasamy prop.insert(property.begin(), property.end()); 883aa8a893eSPriyanga Ramasamy } 884aa8a893eSPriyanga Ramasamy else 885aa8a893eSPriyanga Ramasamy { 886aa8a893eSPriyanga Ramasamy map.emplace(interface, property); 887aa8a893eSPriyanga Ramasamy } 888aa8a893eSPriyanga Ramasamy } 889f2d3b53dSSantosh Puranik 890f2d3b53dSSantosh Puranik BIOSAttrValueType readBIOSAttribute(const std::string& attrName) 891f2d3b53dSSantosh Puranik { 892f2d3b53dSSantosh Puranik std::tuple<std::string, BIOSAttrValueType, BIOSAttrValueType> attrVal; 893f2d3b53dSSantosh Puranik auto bus = sdbusplus::bus::new_default(); 894f2d3b53dSSantosh Puranik auto method = bus.new_method_call( 895f2d3b53dSSantosh Puranik "xyz.openbmc_project.BIOSConfigManager", 896f2d3b53dSSantosh Puranik "/xyz/openbmc_project/bios_config/manager", 897f2d3b53dSSantosh Puranik "xyz.openbmc_project.BIOSConfig.Manager", "GetAttribute"); 898f2d3b53dSSantosh Puranik method.append(attrName); 899f2d3b53dSSantosh Puranik try 900f2d3b53dSSantosh Puranik { 901f2d3b53dSSantosh Puranik auto result = bus.call(method); 902f2d3b53dSSantosh Puranik result.read(std::get<0>(attrVal), std::get<1>(attrVal), 903f2d3b53dSSantosh Puranik std::get<2>(attrVal)); 904f2d3b53dSSantosh Puranik } 905f2d3b53dSSantosh Puranik catch (const sdbusplus::exception::SdBusError& e) 906f2d3b53dSSantosh Puranik { 907f2d3b53dSSantosh Puranik std::cerr << "Failed to read BIOS Attribute: " << attrName << std::endl; 908f2d3b53dSSantosh Puranik std::cerr << e.what() << std::endl; 909f2d3b53dSSantosh Puranik } 910f2d3b53dSSantosh Puranik return std::get<1>(attrVal); 911f2d3b53dSSantosh Puranik } 912335873f6SPriyanga Ramasamy 913335873f6SPriyanga Ramasamy std::string getPowerState() 914335873f6SPriyanga Ramasamy { 915335873f6SPriyanga Ramasamy // TODO: How do we handle multiple chassis? 916335873f6SPriyanga Ramasamy string powerState{}; 917335873f6SPriyanga Ramasamy auto bus = sdbusplus::bus::new_default(); 918335873f6SPriyanga Ramasamy auto properties = 919335873f6SPriyanga Ramasamy bus.new_method_call("xyz.openbmc_project.State.Chassis", 920335873f6SPriyanga Ramasamy "/xyz/openbmc_project/state/chassis0", 921335873f6SPriyanga Ramasamy "org.freedesktop.DBus.Properties", "Get"); 922335873f6SPriyanga Ramasamy properties.append("xyz.openbmc_project.State.Chassis"); 923335873f6SPriyanga Ramasamy properties.append("CurrentPowerState"); 924335873f6SPriyanga Ramasamy auto result = bus.call(properties); 925335873f6SPriyanga Ramasamy if (!result.is_method_error()) 926335873f6SPriyanga Ramasamy { 927335873f6SPriyanga Ramasamy variant<string> val; 928335873f6SPriyanga Ramasamy result.read(val); 929335873f6SPriyanga Ramasamy if (auto pVal = get_if<string>(&val)) 930335873f6SPriyanga Ramasamy { 931335873f6SPriyanga Ramasamy powerState = *pVal; 932335873f6SPriyanga Ramasamy } 933335873f6SPriyanga Ramasamy } 934335873f6SPriyanga Ramasamy cout << "Power state is: " << powerState << endl; 935335873f6SPriyanga Ramasamy return powerState; 936335873f6SPriyanga Ramasamy } 9376b2b5374SSantosh Puranik 9386b2b5374SSantosh Puranik Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file) 9396b2b5374SSantosh Puranik { 9406b2b5374SSantosh Puranik uint32_t offset = 0; 9416b2b5374SSantosh Puranik // check if offset present? 9426b2b5374SSantosh Puranik for (const auto& item : js["frus"][file]) 9436b2b5374SSantosh Puranik { 9446b2b5374SSantosh Puranik if (item.find("offset") != item.end()) 9456b2b5374SSantosh Puranik { 9466b2b5374SSantosh Puranik offset = item["offset"]; 9476b2b5374SSantosh Puranik } 9486b2b5374SSantosh Puranik } 9496b2b5374SSantosh Puranik 9506b2b5374SSantosh Puranik // TODO: Figure out a better way to get max possible VPD size. 9516b2b5374SSantosh Puranik auto maxVPDSize = std::min(std::filesystem::file_size(file), 9526b2b5374SSantosh Puranik static_cast<uintmax_t>(65504)); 9536b2b5374SSantosh Puranik 9546b2b5374SSantosh Puranik Binary vpdVector; 9556b2b5374SSantosh Puranik vpdVector.resize(maxVPDSize); 9566b2b5374SSantosh Puranik ifstream vpdFile; 9576b2b5374SSantosh Puranik vpdFile.open(file, ios::binary); 9586b2b5374SSantosh Puranik 9596b2b5374SSantosh Puranik vpdFile.seekg(offset, ios_base::cur); 9606b2b5374SSantosh Puranik vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), maxVPDSize); 9616b2b5374SSantosh Puranik vpdVector.resize(vpdFile.gcount()); 9626b2b5374SSantosh Puranik 9636b2b5374SSantosh Puranik // Make sure we reset the EEPROM pointer to a "safe" location if it was DIMM 9646b2b5374SSantosh Puranik // SPD that we just read. 9656b2b5374SSantosh Puranik for (const auto& item : js["frus"][file]) 9666b2b5374SSantosh Puranik { 9676b2b5374SSantosh Puranik if (item.find("extraInterfaces") != item.end()) 9686b2b5374SSantosh Puranik { 9696b2b5374SSantosh Puranik if (item["extraInterfaces"].find( 9706b2b5374SSantosh Puranik "xyz.openbmc_project.Inventory.Item.Dimm") != 9716b2b5374SSantosh Puranik item["extraInterfaces"].end()) 9726b2b5374SSantosh Puranik { 9736b2b5374SSantosh Puranik // moves the EEPROM pointer to 2048 'th byte. 9746b2b5374SSantosh Puranik vpdFile.seekg(2047, std::ios::beg); 9756b2b5374SSantosh Puranik // Read that byte and discard - to affirm the move 9766b2b5374SSantosh Puranik // operation. 9776b2b5374SSantosh Puranik char ch; 9786b2b5374SSantosh Puranik vpdFile.read(&ch, sizeof(ch)); 9796b2b5374SSantosh Puranik break; 9806b2b5374SSantosh Puranik } 9816b2b5374SSantosh Puranik } 9826b2b5374SSantosh Puranik } 9836b2b5374SSantosh Puranik 9846b2b5374SSantosh Puranik return vpdVector; 9856b2b5374SSantosh Puranik } 9866c71c9dcSSunny Srivastava } // namespace vpd 9876c71c9dcSSunny Srivastava } // namespace openpower 988