blob: 6395e5b6848ebf234390e2b0e9f3906d0fb640dc [file] [log] [blame]
#pragma once
#include "const.hpp"
#include "store.hpp"
#include "types.hpp"
#include <nlohmann/json.hpp>
#include <iostream>
#include <optional>
#include <variant>
namespace openpower
{
namespace vpd
{
// Map which holds system vpd keywords which can be restored at standby and via
// vpd-tool and also can be used to reset keywords to its defaults at
// manufacturing. The list of keywords for VSYS record is as per the S0 system.
// Should be updated for another type of systems For those keywords whose
// default value is system specific, the default value field is left empty.
// Record : {Keyword, Default value, Is PEL required on restore failure, Is MFG
// reset required, backupVpdRecName, backupVpdKwName}
static const inventory::SystemKeywordsMap svpdKwdMap{
{"VSYS",
{inventory::SystemKeywordInfo("BR", Binary(2, 0x20), true, true, "VSBK",
"BR"),
inventory::SystemKeywordInfo("TM", Binary(8, 0x20), true, true, "VSBK",
"TM"),
inventory::SystemKeywordInfo("SE", Binary(7, 0x20), true, true, "VSBK",
"SE"),
inventory::SystemKeywordInfo("SU", Binary(6, 0x20), true, true, "VSBK",
"SU"),
inventory::SystemKeywordInfo("RB", Binary(4, 0x20), true, true, "VSBK",
"RB"),
inventory::SystemKeywordInfo("WN", Binary(12, 0x20), true, true, "VSBK",
"WN"),
inventory::SystemKeywordInfo("RG", Binary(4, 0x20), true, true, "VSBK",
"RG"),
inventory::SystemKeywordInfo("FV", Binary(32, 0x20), false, true, "VSBK",
"FV")}},
{"VCEN",
{inventory::SystemKeywordInfo("FC", Binary(8, 0x20), true, false, "VSBK",
"FC"),
inventory::SystemKeywordInfo("SE", Binary(7, 0x20), true, true, "VSBK",
"ES")}},
{"LXR0",
{inventory::SystemKeywordInfo("LX", Binary(8, 0x00), true, false, "VSBK",
"LX")}},
{"UTIL",
{inventory::SystemKeywordInfo("D0", Binary(1, 0x00), true, true, "VSBK",
"D0"),
inventory::SystemKeywordInfo("D1", Binary(1, 0x00), false, true, "VSBK",
"D1"),
inventory::SystemKeywordInfo("F0", Binary(8, 0x00), false, true, "VSBK",
"F0"),
inventory::SystemKeywordInfo("F5", Binary(16, 0x00), false, true, "VSBK",
"F5"),
inventory::SystemKeywordInfo("F6", Binary(16, 0x00), false, true, "VSBK",
"F6")}}};
/** @brief Return the hex representation of the incoming byte
*
* @param [in] c - The input byte
* @returns The hex representation of the byte as a character.
*/
constexpr auto toHex(size_t c)
{
constexpr auto map = "0123456789abcdef";
return map[c];
}
namespace inventory
{
/** @brief API to obtain a dictionary of path -> services
* where path is in subtree and services is of the type
* returned by the GetObject method.
*
* @param [in] root - Root path for object subtree
* @param [in] depth - Maximum subtree depth required
* @param [in] interfaces - Array to interfaces for which
* result is required.
* @return A dictionary of Path -> services
*/
MapperResponse
getObjectSubtreeForInterfaces(const std::string& root, const int32_t depth,
const std::vector<std::string>& interfaces);
/**
* @brief API to call GetObject API of mapper.
*
* @param[in] objectPath - inventory path.
* @param[in] interfaces - List of interfaces.
*
* @return - response of the API call.
*/
MapperGetObjectResponse getObject(const std::string& objectPath,
const std::vector<std::string>& interfaces);
} // namespace inventory
/**@brief This API reads 2 Bytes of data and swap the read data
* @param[in] iterator- Pointer pointing to the data to be read
* @return returns 2 Byte data read at the given pointer
*/
openpower::vpd::constants::LE2ByteData
readUInt16LE(Binary::const_iterator iterator);
/** @brief Encodes a keyword for D-Bus.
* @param[in] kw - kwd data in string format
* @param[in] encoding - required for kwd data
*/
std::string encodeKeyword(const std::string& kw, const std::string& encoding);
/** @brief Reads a property from the inventory manager given object path,
* intreface and property.
* @param[in] obj - object path
* @param[in] inf - interface
* @param[in] prop - property whose value is fetched
* @return [out] - value of the property
*/
std::string readBusProperty(const std::string& obj, const std::string& inf,
const std::string& prop);
/** @brief A templated function to read D-Bus properties.
*
* @param[in] service - Service path
* @param[in] object - object path
* @param[in] inf - interface
* @param[in] prop - property whose value is fetched
* @return The property value of its own type.
*/
template <typename T>
T readDBusProperty(const std::string& service, const std::string& object,
const std::string& inf, const std::string& prop)
{
T retVal{};
try
{
auto bus = sdbusplus::bus::new_default();
auto properties = bus.new_method_call(service.c_str(), object.c_str(),
"org.freedesktop.DBus.Properties",
"Get");
properties.append(inf);
properties.append(prop);
auto result = bus.call(properties);
result.read(retVal);
}
catch (const sdbusplus::exception::SdBusError& e)
{
std::cerr << e.what();
}
return retVal;
}
/** @brief A templated method to get all D-Bus properties
*
* @param[in] service - Service path
* @param[in] object - Object path
* @param[in] inf - Interface
*
* @return All properties under the given interface.
*/
template <typename T>
T getAllDBusProperty(const std::string& service, const std::string& object,
const std::string& inf)
{
T retVal{};
try
{
auto bus = sdbusplus::bus::new_default();
auto allProperties =
bus.new_method_call(service.c_str(), object.c_str(),
"org.freedesktop.DBus.Properties", "GetAll");
allProperties.append(inf);
auto result = bus.call(allProperties);
result.read(retVal);
}
catch (const sdbusplus::exception::SdBusError& e)
{
std::cerr << e.what();
}
return retVal;
}
/**
* @brief API to create PEL entry
* The api makes synchronous call to phosphor-logging create api.
* @param[in] additionalData - Map holding the additional data
* @param[in] sev - Severity
* @param[in] errIntf - error interface
*/
void createSyncPEL(const std::map<std::string, std::string>& additionalData,
const constants::PelSeverity& sev,
const std::string& errIntf);
/**
* @brief Api to create PEL.
* A wrapper api through which sync/async call to phosphor-logging create api
* can be made as and when required.
* sdBus as nullptr will result in sync call else async call will be made with
* just "DESCRIPTION" key/value pair in additional data.
* To make asyn call with more fields in additional data call
* "sd_bus_call_method_async" in place.
*
* @param[in] additionalData - Map of additional data.
* @param[in] sev - severity of the PEL.
* @param[in] errIntf - Error interface to be used in PEL.
* @param[in] sdBus - Pointer to Sd-Bus
*/
void createPEL(const std::map<std::string, std::string>& additionalData,
const constants::PelSeverity& sev, const std::string& errIntf,
sd_bus* sdBus);
/**
* @brief getVpdFilePath
* Get vpd file path corresponding to the given object path.
* @param[in] - json file path
* @param[in] - Object path
* @return - Vpd file path
*/
inventory::VPDfilepath getVpdFilePath(const std::string& jsonFile,
const std::string& ObjPath);
/**
* @brief isPathInJson
* API which checks for the presence of the given eeprom path in the given json.
* @param[in] - eepromPath
* @return - true if the eeprom is present in the json; false otherwise
*/
bool isPathInJson(const std::string& eepromPath);
/**
* @brief isRecKwInDbusJson
* API which checks whether the given keyword under the given record is to be
* published on dbus or not. Checks against the keywords present in
* dbus_property.json.
* @param[in] - record name
* @param[in] - keyword name
* @return - true if the record-keyword pair is present in dbus_property.json;
* false otherwise.
*/
bool isRecKwInDbusJson(const std::string& record, const std::string& keyword);
/**
* @brief Check the type of VPD.
*
* Checks the type of vpd based on the start tag.
* @param[in] vector - Vpd data in vector format
*
* @return enum of type vpdType
*/
constants::vpdType vpdTypeCheck(const Binary& vector);
/*
* @brief This method does nothing. Just an empty function to return null
* at the end of variadic template args
*/
inline std::string getCommand()
{
return "";
}
/**
* @brief This function to arrange all arguments to make commandy
* @param[in] arguments to create the command
* @return cmd - command string
*/
template <typename T, typename... Types>
inline std::string getCommand(T arg1, Types... args)
{
std::string cmd = " " + arg1 + getCommand(args...);
return cmd;
}
/**
* @brief This API takes arguments, creates a shell command line and executes
* them.
* @param[in] arguments for command
* @returns output of that command
*/
template <typename T, typename... Types>
inline std::vector<std::string> executeCmd(T&& path, Types... args)
{
std::vector<std::string> stdOutput;
std::array<char, 128> buffer;
std::string cmd = path + getCommand(args...);
struct custom_file_deleter
{
void operator()(std::FILE* fp)
{
pclose(fp);
}
};
using unique_file_custom_deleter =
std::unique_ptr<std::FILE, custom_file_deleter>;
unique_file_custom_deleter pipe{popen(cmd.c_str(), "r")};
if (!pipe)
{
throw std::runtime_error("popen() failed!");
}
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
{
stdOutput.emplace_back(buffer.data());
}
return stdOutput;
}
/** @brief This API checks for IM and HW keywords, and based
* on these values decides which system json to be used.
* @param[in] vpdMap - parsed vpd
* @returns System json path
*/
std::string getSystemsJson(const Parsed& vpdMap);
/** @brief Reads HW Keyword from the vpd
* @param[in] vpdMap - parsed vpd
* @returns value of HW Keyword
*/
const std::string getHW(const Parsed& vpdMap);
/** @brief Reads IM Keyword from the vpd
* @param[in] vpdMap - parsed vpd
* @returns value of IM Keyword
*/
const std::string getIM(const Parsed& vpdMap);
/** @brief Translate udev event generated path to a generic /sys/bus eeprom path
* @param[io] file - path generated from udev event.
* @param[in] driver - kernel driver used by the device.
*/
void udevToGenericPath(std::string& file, const std::string& driver);
/**
* @brief API to generate a vpd name in some pattern.
* This vpd-name denotes name of the bad vpd file.
* For i2c eeproms - the pattern of the vpd-name will be
* i2c-<bus-number>-<eeprom-address>. For spi eeproms - the pattern of the
* vpd-name will be spi-<spi-number>.
*
* @param[in] file - file path of the vpd
* @return the vpd-name.
*/
std::string getBadVpdName(const std::string& file);
/**
* @brief API which dumps the broken/bad vpd in a directory
* When the vpd is bad, this api places the bad vpd file inside
* "/tmp/bad-vpd" in BMC, in order to collect bad VPD data as a part of user
* initiated BMC dump.
*
* @param[in] file - bad vpd file path
* @param[in] vpdVector - bad vpd vector
*/
void dumpBadVpd(const std::string& file, const Binary& vpdVector);
/*
* @brief This function fetches the value for given keyword in the given record
* from vpd data and returns this value.
*
* @param[in] vpdMap - vpd to find out the data
* @param[in] rec - Record under which desired keyword exists
* @param[in] kwd - keyword to read the data from
*
* @returns keyword value if record/keyword combination found
* empty string if record or keyword is not found.
*/
const std::string getKwVal(const Parsed& vpdMap, const std::string& rec,
const std::string& kwd);
/** @brief This creates a complete command using all it's input parameters,
* to bind or unbind the driver.
* @param[in] devNameAddr - device address on that bus
* @param[in] busType - i2c, spi
* @param[in] driverType - type of driver like at24
* @param[in] bindOrUnbind - either bind or unbind
* @returns Command to bind or unbind the driver.
*/
inline std::string createBindUnbindDriverCmnd(const std::string& devNameAddr,
const std::string& busType,
const std::string& driverType,
const std::string& bindOrUnbind)
{
return ("echo " + devNameAddr + " > /sys/bus/" + busType + "/drivers/" +
driverType + "/" + bindOrUnbind);
}
/**
* @brief Get Printable Value
*
* Checks if the value has non printable characters.
* Returns hex value if non printable char is found else
* returns ascii value.
*
* @param[in] kwVal - Reference of the input data, Keyword value
* @return printable value - either in hex or in ascii.
*/
std::string getPrintableValue(const std::variant<Binary, std::string>& kwVal);
/**
* @brief Convert array to hex string.
* @param[in] kwVal - input data, Keyword value
* @return hexadecimal string of bytes.
*/
std::string hexString(const std::variant<Binary, std::string>& kwVal);
/**
* @brief Return presence of the FRU.
*
* This API returns the presence information of the FRU corresponding to the
* given EEPROM. If the JSON contains no information about presence detect, this
* will return an empty optional. Else it will get the presence GPIO information
* from the JSON and return the appropriate present status.
* In case of GPIO find/read errors, it will return false.
*
* @param[in] json - The VPD JSON
* @param[in] file - EEPROM file path
* @return Empty optional if there is no presence info. Else returns presence
* based on the GPIO read.
*/
std::optional<bool> isPresent(const nlohmann::json& json,
const std::string& file);
/**
* @brief Performs any pre-action needed to get the FRU setup for
* collection.
*
* @param[in] json - json object
* @param[in] file - eeprom file path
* @return - success or failure
*/
bool executePreAction(const nlohmann::json& json, const std::string& file);
/**
* @brief This API will be called at the end of VPD collection to perform any
* post actions.
*
* @param[in] json - json object
* @param[in] file - eeprom file path
*/
void executePostFailAction(const nlohmann::json& json, const std::string& file);
/**
* @brief Helper function to insert or merge in map.
*
* This method checks in the given inventory::InterfaceMap if the given
* interface key is existing or not. If the interface key already exists, given
* property map is inserted into it. If the key does'nt exist then given
* interface and property map pair is newly created. If the property present in
* propertymap already exist in the InterfaceMap, then the new property value is
* ignored.
*
* @param[in,out] map - map object of type inventory::InterfaceMap only.
* @param[in] interface - Interface name.
* @param[in] property - new property map that needs to be emplaced.
*/
void insertOrMerge(inventory::InterfaceMap& map,
const inventory::Interface& interface,
inventory::PropertyMap&& property);
/**
* @brief Utility API to set a D-Bus property
*
* This calls org.freedesktop.DBus.Properties;Set method with the supplied
* arguments
*
* @tparam T Template type of the D-Bus property
* @param service[in] - The D-Bus service name.
* @param object[in] - The D-Bus object on which the property is to be set.
* @param interface[in] - The D-Bus interface to which the property belongs.
* @param propertyName[in] - The name of the property to set.
* @param propertyValue[in] - The value of the property.
*/
template <typename T>
void setBusProperty(const std::string& service, const std::string& object,
const std::string& interface,
const std::string& propertyName,
const std::variant<T>& propertyValue)
{
try
{
auto bus = sdbusplus::bus::new_default();
auto method = bus.new_method_call(service.c_str(), object.c_str(),
"org.freedesktop.DBus.Properties",
"Set");
method.append(interface);
method.append(propertyName);
method.append(propertyValue);
bus.call(method);
}
catch (const sdbusplus::exception::SdBusError& e)
{
std::cerr << e.what() << std::endl;
}
}
/**
* @brief Reads BIOS Attribute by name.
*
* @param attrName[in] - The BIOS attribute name.
* @return std::variant<int64_t, std::string> - The BIOS attribute value.
*/
std::variant<int64_t, std::string>
readBIOSAttribute(const std::string& attrName);
/**
* @brief Returns the power state for chassis0
* @return The chassis power state.
*/
std::string getPowerState();
/**
* @brief Reads VPD from the supplied EEPROM
*
* This function reads the given VPD EEPROM file and returns its contents as a
* byte array. It handles any offsets into the file that need to be taken care
* of by looking up the VPD JSON for a possible offset key.
*
* @param js[in] - The VPD JSON Object
* @param file[in] - The path to the EEPROM to read
* @return A byte array containing the raw VPD.
*/
Binary getVpdDataInVector(const nlohmann::json& js, const std::string& file);
/**
* @brief Get D-bus name for the keyword
* Some of the VPD keywords has different name in PIM when compared with its
* name from hardware. This method returns the D-bus name for the given keyword.
*
* @param[in] keyword - Keyword name
* @return D-bus name for the keyword
*/
std::string getDbusNameForThisKw(const std::string& keyword);
/**
* @brief API to remove VPD data from Dbus on removal of FRU.
*
* @param[in] objPath - Inventory path of the FRU.
* @param[out] interfacesPropMap - Map of interface, property and value.
*/
void clearVpdOnRemoval(const std::string& objPath,
inventory::InterfaceMap& interfacesPropMap);
/**
* @brief Find backup VPD path if any for the system VPD
*
* @param[out] backupEepromPath - Backup VPD path
* @param[out] backupInvPath - Backup inventory path
* @param[in] js - Inventory JSON object
*/
void findBackupVPDPaths(std::string& backupEepromPath,
std::string& backupInvPath, const nlohmann::json& js);
/**
* @brief Get backup VPD's record and keyword for the given system VPD keyword
*
* @param[in,out] record - Record name
* @param[in,out] keyword - Keyword name
*/
void getBackupRecordKeyword(std::string& record, std::string& keyword);
} // namespace vpd
} // namespace openpower