Segregate utility methods
This commit segregates utility methods required commonly by both
openpower-read-vpd and ibm-read-vpd from methods only required by
ibm-read-vpd.
All dependency required by utility methods specific to ibm-read-vpd
is not applicable to utility methods required by openpower-read-vpd.
Hence to avoid un-necessary dependency inclusion, this change is
introduced.
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
Change-Id: I95f2be27dc0c391a45beb1654a99506317aaa52b
diff --git a/ibm_vpd_utils.cpp b/ibm_vpd_utils.cpp
new file mode 100644
index 0000000..d691c84
--- /dev/null
+++ b/ibm_vpd_utils.cpp
@@ -0,0 +1,301 @@
+#include "config.h"
+
+#include "ibm_vpd_utils.hpp"
+
+#include "common_utility.hpp"
+#include "defines.hpp"
+#include "vpd_exceptions.hpp"
+
+#include <fstream>
+#include <iomanip>
+#include <nlohmann/json.hpp>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/server.hpp>
+#include <sstream>
+#include <vector>
+#include <xyz/openbmc_project/Common/error.hpp>
+
+using json = nlohmann::json;
+
+namespace openpower
+{
+namespace vpd
+{
+using namespace openpower::vpd::constants;
+using namespace inventory;
+using namespace phosphor::logging;
+using namespace sdbusplus::xyz::openbmc_project::Common::Error;
+using namespace record;
+using namespace openpower::vpd::exceptions;
+using namespace common::utility;
+namespace inventory
+{
+
+MapperResponse
+ getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
+ const std::vector<std::string>& interfaces)
+{
+ auto bus = sdbusplus::bus::new_default();
+ auto mapperCall = bus.new_method_call(mapperDestination, mapperObjectPath,
+ mapperInterface, "GetSubTree");
+ mapperCall.append(root);
+ mapperCall.append(depth);
+ mapperCall.append(interfaces);
+
+ MapperResponse result = {};
+
+ try
+ {
+ auto response = bus.call(mapperCall);
+
+ response.read(result);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ log<level::ERR>("Error in mapper GetSubTree",
+ entry("ERROR=%s", e.what()));
+ }
+
+ return result;
+}
+
+} // namespace inventory
+
+LE2ByteData readUInt16LE(Binary::const_iterator iterator)
+{
+ LE2ByteData lowByte = *iterator;
+ LE2ByteData highByte = *(iterator + 1);
+ lowByte |= (highByte << 8);
+ return lowByte;
+}
+
+/** @brief Encodes a keyword for D-Bus.
+ */
+string encodeKeyword(const string& kw, const string& encoding)
+{
+ if (encoding == "MAC")
+ {
+ string res{};
+ size_t first = kw[0];
+ res += toHex(first >> 4);
+ res += toHex(first & 0x0f);
+ for (size_t i = 1; i < kw.size(); ++i)
+ {
+ res += ":";
+ res += toHex(kw[i] >> 4);
+ res += toHex(kw[i] & 0x0f);
+ }
+ return res;
+ }
+ else if (encoding == "DATE")
+ {
+ // Date, represent as
+ // <year>-<month>-<day> <hour>:<min>
+ string res{};
+ static constexpr uint8_t skipPrefix = 3;
+
+ auto strItr = kw.begin();
+ advance(strItr, skipPrefix);
+ for_each(strItr, kw.end(), [&res](size_t c) { res += c; });
+
+ res.insert(BD_YEAR_END, 1, '-');
+ res.insert(BD_MONTH_END, 1, '-');
+ res.insert(BD_DAY_END, 1, ' ');
+ res.insert(BD_HOUR_END, 1, ':');
+
+ return res;
+ }
+ else // default to string encoding
+ {
+ return string(kw.begin(), kw.end());
+ }
+}
+
+string readBusProperty(const string& obj, const string& inf, const string& prop)
+{
+ std::string propVal{};
+ std::string object = INVENTORY_PATH + obj;
+ auto bus = sdbusplus::bus::new_default();
+ auto properties = bus.new_method_call(
+ "xyz.openbmc_project.Inventory.Manager", object.c_str(),
+ "org.freedesktop.DBus.Properties", "Get");
+ properties.append(inf);
+ properties.append(prop);
+ auto result = bus.call(properties);
+ if (!result.is_method_error())
+ {
+ variant<Binary, string> val;
+ result.read(val);
+ if (auto pVal = get_if<Binary>(&val))
+ {
+ propVal.assign(reinterpret_cast<const char*>(pVal->data()),
+ pVal->size());
+ }
+ else if (auto pVal = get_if<string>(&val))
+ {
+ propVal.assign(pVal->data(), pVal->size());
+ }
+ }
+ return propVal;
+}
+
+void createPEL(const std::map<std::string, std::string>& additionalData,
+ const std::string& errIntf)
+{
+ try
+ {
+ auto bus = sdbusplus::bus::new_default();
+ auto service = getService(bus, loggerObjectPath, loggerCreateInterface);
+ auto method = bus.new_method_call(service.c_str(), loggerObjectPath,
+ loggerCreateInterface, "Create");
+
+ method.append(errIntf, "xyz.openbmc_project.Logging.Entry.Level.Error",
+ additionalData);
+ auto resp = bus.call(method);
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ throw std::runtime_error(
+ "Error in invoking D-Bus logging create interface to register PEL");
+ }
+}
+
+inventory::VPDfilepath getVpdFilePath(const string& jsonFile,
+ const std::string& ObjPath)
+{
+ ifstream inventoryJson(jsonFile);
+ const auto& jsonObject = json::parse(inventoryJson);
+ inventory::VPDfilepath filePath{};
+
+ if (jsonObject.find("frus") == jsonObject.end())
+ {
+ throw(VpdJsonException(
+ "Invalid JSON structure - frus{} object not found in ", jsonFile));
+ }
+
+ const nlohmann::json& groupFRUS =
+ jsonObject["frus"].get_ref<const nlohmann::json::object_t&>();
+ for (const auto& itemFRUS : groupFRUS.items())
+ {
+ const std::vector<nlohmann::json>& groupEEPROM =
+ itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
+ for (const auto& itemEEPROM : groupEEPROM)
+ {
+ if (itemEEPROM["inventoryPath"]
+ .get_ref<const nlohmann::json::string_t&>() == ObjPath)
+ {
+ filePath = itemFRUS.key();
+ return filePath;
+ }
+ }
+ }
+
+ return filePath;
+}
+
+bool isPathInJson(const std::string& eepromPath)
+{
+ bool present = false;
+ ifstream inventoryJson(INVENTORY_JSON_SYM_LINK);
+
+ try
+ {
+ auto js = json::parse(inventoryJson);
+ if (js.find("frus") == js.end())
+ {
+ throw(VpdJsonException(
+ "Invalid JSON structure - frus{} object not found in ",
+ INVENTORY_JSON_SYM_LINK));
+ }
+ json fruJson = js["frus"];
+
+ if (fruJson.find(eepromPath) != fruJson.end())
+ {
+ present = true;
+ }
+ }
+ catch (json::parse_error& ex)
+ {
+ throw(VpdJsonException("Json Parsing failed", INVENTORY_JSON_SYM_LINK));
+ }
+ return present;
+}
+
+bool isRecKwInDbusJson(const std::string& recordName,
+ const std::string& keyword)
+{
+ ifstream propertyJson(DBUS_PROP_JSON);
+ json dbusProperty;
+ bool present = false;
+
+ if (propertyJson.is_open())
+ {
+ try
+ {
+ auto dbusPropertyJson = json::parse(propertyJson);
+ if (dbusPropertyJson.find("dbusProperties") ==
+ dbusPropertyJson.end())
+ {
+ throw(VpdJsonException("dbusProperties{} object not found in "
+ "DbusProperties json : ",
+ DBUS_PROP_JSON));
+ }
+
+ dbusProperty = dbusPropertyJson["dbusProperties"];
+ if (dbusProperty.contains(recordName))
+ {
+ const vector<string>& kwdsToPublish = dbusProperty[recordName];
+ if (find(kwdsToPublish.begin(), kwdsToPublish.end(), keyword) !=
+ kwdsToPublish.end()) // present
+ {
+ present = true;
+ }
+ }
+ }
+ catch (json::parse_error& ex)
+ {
+ throw(VpdJsonException("Json Parsing failed", DBUS_PROP_JSON));
+ }
+ }
+ else
+ {
+ // If dbus properties json is not available, we assume the given
+ // record-keyword is part of dbus-properties json. So setting the bool
+ // variable to true.
+ present = true;
+ }
+ return present;
+}
+
+vpdType vpdTypeCheck(const Binary& vpdVector)
+{
+ // Read first 3 Bytes to check the 11S bar code format
+ std::string is11SFormat = "";
+ for (uint8_t i = 0; i < FORMAT_11S_LEN; i++)
+ {
+ is11SFormat += vpdVector[MEMORY_VPD_DATA_START + i];
+ }
+
+ if (vpdVector[IPZ_DATA_START] == KW_VAL_PAIR_START_TAG)
+ {
+ // IPZ VPD FORMAT
+ return vpdType::IPZ_VPD;
+ }
+ else if (vpdVector[KW_VPD_DATA_START] == KW_VPD_START_TAG)
+ {
+ // KEYWORD VPD FORMAT
+ return vpdType::KEYWORD_VPD;
+ }
+ else if (is11SFormat.compare(MEMORY_VPD_START_TAG) == 0)
+ {
+ // Memory VPD format
+ return vpdType::MEMORY_VPD;
+ }
+
+ // INVALID VPD FORMAT
+ return vpdType::INVALID_VPD_FORMAT;
+}
+
+} // namespace vpd
+} // namespace openpower