| #pragma once |
| |
| #include "constants.hpp" |
| #include "types.hpp" |
| |
| #include <nlohmann/json.hpp> |
| |
| #include <mutex> |
| #include <optional> |
| #include <semaphore> |
| #include <tuple> |
| |
| namespace vpd |
| { |
| /** |
| * @brief A class to process and publish VPD data. |
| * |
| * The class works on VPD and is mainly responsible for following tasks: |
| * 1) Select appropriate device tree and JSON. Reboot if required. |
| * 2) Get desired parser using parser factory. |
| * 3) Calling respective parser class to get parsed VPD. |
| * 4) Arranging VPD data under required interfaces. |
| * 5) Calling PIM to publish VPD. |
| * |
| * The class may also implement helper functions required for VPD handling. |
| */ |
| class Worker |
| { |
| public: |
| /** |
| * List of deleted functions. |
| */ |
| Worker(const Worker&); |
| Worker& operator=(const Worker&); |
| Worker(Worker&&) = delete; |
| |
| /** |
| * @brief Constructor. |
| * |
| * In case the processing is not JSON based, no argument needs to be passed. |
| * Constructor will also, based on symlink pick the correct JSON and |
| * initialize the parsed JSON variable. |
| * |
| * @param[in] pathToConfigJSON - Path to the config JSON, if applicable. |
| * @param[in] i_maxThreadCount - Maximum thread while collecting FRUs VPD. |
| * |
| * Note: Throws std::exception in case of construction failure. Caller needs |
| * to handle to detect successful object creation. |
| */ |
| Worker(std::string pathToConfigJson = std::string(), |
| uint8_t i_maxThreadCount = constants::MAX_THREADS); |
| |
| /** |
| * @brief Destructor |
| */ |
| ~Worker() = default; |
| |
| #ifdef IBM_SYSTEM |
| /** |
| * @brief API to perform initial setup before manager claims Bus name. |
| * |
| * Before BUS name for VPD-Manager is claimed, fitconfig whould be set for |
| * corret device tree, inventory JSON w.r.t system should be linked and |
| * system VPD should be on DBus. |
| */ |
| void performInitialSetup(); |
| #endif |
| |
| /** |
| * @brief An API to check if system VPD is already published. |
| * |
| * @return Status, true if system is already collected else false. |
| */ |
| bool isSystemVPDOnDBus() const; |
| |
| /** |
| * @brief API to process all FRUs presnt in config JSON file. |
| * |
| * This API based on config JSON passed/selected for the system, will |
| * trigger parser for all the FRUs and publish it on DBus. |
| * |
| * Note: Config JSON file path should be passed to worker class constructor |
| * to make use of this API. |
| * |
| */ |
| void collectFrusFromJson(); |
| |
| /** |
| * @brief API to parse VPD data |
| * |
| * @param[in] i_vpdFilePath - Path to the VPD file. |
| */ |
| types::VPDMapVariant parseVpdFile(const std::string& i_vpdFilePath); |
| |
| /** |
| * @brief An API to populate DBus interfaces for a FRU. |
| * |
| * Note: Call this API to populate D-Bus. Also caller should handle empty |
| * objectInterfaceMap. |
| * |
| * @param[in] parsedVpdMap - Parsed VPD as a map. |
| * @param[out] objectInterfaceMap - Object and its interfaces map. |
| * @param[in] vpdFilePath - EEPROM path of FRU. |
| */ |
| void populateDbus(const types::VPDMapVariant& parsedVpdMap, |
| types::ObjectMap& objectInterfaceMap, |
| const std::string& vpdFilePath); |
| |
| /** |
| * @brief An API to delete FRU VPD over DBus. |
| * |
| * @param[in] i_dbusObjPath - Dbus object path of the FRU. |
| * |
| * @throw std::runtime_error if given input path is empty. |
| */ |
| void deleteFruVpd(const std::string& i_dbusObjPath); |
| |
| /** |
| * @brief API to get status of VPD collection process. |
| * |
| * @return - True when done, false otherwise. |
| */ |
| inline bool isAllFruCollectionDone() const |
| { |
| return m_isAllFruCollected; |
| } |
| |
| /** |
| * @brief API to get system config JSON object |
| * |
| * @return System config JSON object. |
| */ |
| inline nlohmann::json getSysCfgJsonObj() const |
| { |
| return m_parsedJson; |
| } |
| |
| /** |
| * @brief API to get active thread count. |
| * |
| * Each FRU is collected in a separate thread. This API gives the active |
| * thread collecting FRU's VPD at any given time. |
| * |
| * @return Count of active threads. |
| */ |
| size_t getActiveThreadCount() const |
| { |
| return m_activeCollectionThreadCount; |
| } |
| |
| /** |
| * @brief API to get list of EEPROMs for which thread creation failed. |
| * |
| * This API returns reference to list of EEPROM paths for which VPD |
| * collection thread creation has failed. Manager needs to process this list |
| * of EEPROMs and take appropriate action. |
| * |
| * @return reference to list of EEPROM paths for which VPD collection thread |
| * creation has failed |
| */ |
| inline std::forward_list<std::string>& getFailedEepromPaths() noexcept |
| { |
| return m_failedEepromPaths; |
| } |
| |
| private: |
| /** |
| * @brief An API to parse and publish a FRU VPD over D-Bus. |
| * |
| * Note: This API will handle all the exceptions internally and will only |
| * return status of parsing and publishing of VPD over D-Bus. |
| * |
| * @param[in] i_vpdFilePath - Path of file containing VPD. |
| * @return Tuple of status and file path. Status, true if successfull else |
| * false. |
| */ |
| std::tuple<bool, std::string> parseAndPublishVPD( |
| const std::string& i_vpdFilePath); |
| |
| /** |
| * @brief An API to set appropriate device tree and JSON. |
| * |
| * This API based on system chooses corresponding device tree and JSON. |
| * If device tree change is required, it updates the "fitconfig" and reboots |
| * the system. Else it is NOOP. |
| * |
| * @throw std::exception |
| */ |
| void setDeviceTreeAndJson(); |
| |
| /** |
| * @brief API to select system specific JSON. |
| * |
| * The API based on the IM value of VPD, will select appropriate JSON for |
| * the system. In case no system is found corresponding to the extracted IM |
| * value, error will be logged. |
| * |
| * @param[out] systemJson - System JSON name. |
| * @param[in] parsedVpdMap - Parsed VPD map. |
| */ |
| void getSystemJson(std::string& systemJson, |
| const types::VPDMapVariant& parsedVpdMap); |
| |
| /** |
| * @brief An API to read IM value from VPD. |
| * |
| * Note: Throws exception in case of error. Caller need to handle. |
| * |
| * @param[in] parsedVpd - Parsed VPD. |
| */ |
| std::string getIMValue(const types::IPZVpdMap& parsedVpd) const; |
| |
| /** |
| * @brief An API to read HW version from VPD. |
| * |
| * Note: Throws exception in case of error. Caller need to handle. |
| * |
| * @param[in] parsedVpd - Parsed VPD. |
| */ |
| std::string getHWVersion(const types::IPZVpdMap& parsedVpd) const; |
| |
| /** |
| * @brief An API to parse given VPD file path. |
| * |
| * @throw std::exception |
| * |
| * @param[in] vpdFilePath - EEPROM file path. |
| * @param[out] parsedVpd - Parsed VPD as a map. |
| */ |
| void fillVPDMap(const std::string& vpdFilePath, |
| types::VPDMapVariant& parsedVpd); |
| |
| /** |
| * @brief An API to parse and publish system VPD on D-Bus. |
| * |
| * Note: Throws exception in case of invalid VPD format. |
| * |
| * @param[in] parsedVpdMap - Parsed VPD as a map. |
| */ |
| void publishSystemVPD(const types::VPDMapVariant& parsedVpdMap); |
| |
| /** |
| * @brief An API to process extrainterfaces w.r.t a FRU. |
| * |
| * @param[in] singleFru - JSON block for a single FRU. |
| * @param[out] interfaces - Map to hold interface along with its properties. |
| * @param[in] parsedVpdMap - Parsed VPD as a map. |
| */ |
| void processExtraInterfaces(const nlohmann::json& singleFru, |
| types::InterfaceMap& interfaces, |
| const types::VPDMapVariant& parsedVpdMap); |
| |
| /** |
| * @brief An API to process embedded and synthesized FRUs. |
| * |
| * @param[in] singleFru - FRU to be processed. |
| * @param[out] interfaces - Map to hold interface along with its properties. |
| */ |
| void processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru, |
| types::InterfaceMap& interfaces); |
| |
| /** |
| * @brief An API to read process FRU based in CCIN. |
| * |
| * For some FRUs VPD can be processed only if the FRU has some specific |
| * value for CCIN. In case the value is not from that set, VPD for those |
| * FRUs can't be processed. |
| * |
| * @param[in] singleFru - Fru whose CCIN value needs to be matched. |
| * @param[in] parsedVpdMap - Parsed VPD map. |
| */ |
| bool processFruWithCCIN(const nlohmann::json& singleFru, |
| const types::VPDMapVariant& parsedVpdMap); |
| |
| /** |
| * @brief API to process json's inherit flag. |
| * |
| * Inherit flag denotes that some property in the child FRU needs to be |
| * inherited from parent FRU. |
| * |
| * @param[in] parsedVpdMap - Parsed VPD as a map. |
| * @param[out] interfaces - Map to hold interface along with its properties. |
| */ |
| void processInheritFlag(const types::VPDMapVariant& parsedVpdMap, |
| types::InterfaceMap& interfaces); |
| |
| /** |
| * @brief API to process json's "copyRecord" flag. |
| * |
| * copyRecord flag denotes if some record data needs to be copies in the |
| * given FRU. |
| * |
| * @param[in] singleFru - FRU being processed. |
| * @param[in] parsedVpdMap - Parsed VPD as a map. |
| * @param[out] interfaces - Map to hold interface along with its properties. |
| */ |
| void processCopyRecordFlag(const nlohmann::json& singleFru, |
| const types::VPDMapVariant& parsedVpdMap, |
| types::InterfaceMap& interfaces); |
| |
| /** |
| * @brief An API to populate IPZ VPD property map. |
| * |
| * @param[out] interfacePropMap - Map of interface and properties under it. |
| * @param[in] keyordValueMap - Keyword value map of IPZ VPD. |
| * @param[in] interfaceName - Name of the interface. |
| */ |
| void populateIPZVPDpropertyMap(types::InterfaceMap& interfacePropMap, |
| const types::IPZKwdValueMap& keyordValueMap, |
| const std::string& interfaceName); |
| |
| /** |
| * @brief An API to populate Kwd VPD property map. |
| * |
| * @param[in] keyordValueMap - Keyword value map of Kwd VPD. |
| * @param[out] interfaceMap - interface and property,value under it. |
| */ |
| void populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap, |
| types::InterfaceMap& interfaceMap); |
| |
| /** |
| * @brief API to populate all required interface for a FRU. |
| * |
| * @param[in] interfaceJson - JSON containing interfaces to be populated. |
| * @param[out] interfaceMap - Map to hold populated interfaces. |
| * @param[in] parsedVpdMap - Parsed VPD as a map. |
| */ |
| void populateInterfaces(const nlohmann::json& interfaceJson, |
| types::InterfaceMap& interfaceMap, |
| const types::VPDMapVariant& parsedVpdMap); |
| |
| /** |
| * @brief Check if the given CPU is an IO only chip. |
| * |
| * The CPU is termed as IO, whose all of the cores are bad and can never be |
| * used. Those CPU chips can be used for IO purpose like connecting PCIe |
| * devices etc., The CPU whose every cores are bad, can be identified from |
| * the CP00 record's PG keyword, only if all of the 8 EQs' value equals |
| * 0xE7F9FF. (1EQ has 4 cores grouped together by sharing its cache memory.) |
| * |
| * @param [in] pgKeyword - PG Keyword of CPU. |
| * @return true if the given cpu is an IO, false otherwise. |
| */ |
| bool isCPUIOGoodOnly(const std::string& pgKeyword); |
| |
| /** |
| * @brief API to prime inventory Objects. |
| * |
| * @param[in] i_vpdFilePath - EEPROM file path. |
| * @return true if the prime inventory is success, false otherwise. |
| */ |
| bool primeInventory(const std::string& i_vpdFilePath); |
| |
| /** |
| * @brief API to process preAction(base_action) defined in config JSON. |
| * |
| * @note sequence of tags under any given flag of preAction is EXTREMELY |
| * important to ensure proper processing. The API will process all the |
| * nested items under the base action sequentially. Also if any of the tag |
| * processing fails, the code will not process remaining tags under the |
| * flag. |
| * ******** sample format ************** |
| * fru EEPROM path: { |
| * base_action: { |
| * flag1: { |
| * tag1: { |
| * }, |
| * tag2: { |
| * } |
| * } |
| * flag2: { |
| * tags: { |
| * } |
| * } |
| * } |
| * } |
| * ************************************* |
| * |
| * @param[in] i_vpdFilePath - Path to the EEPROM file. |
| * @param[in] i_flagToProcess - To identify which flag(s) needs to be |
| * processed under PreAction tag of config JSON. |
| * @return Execution status. |
| */ |
| bool processPreAction(const std::string& i_vpdFilePath, |
| const std::string& i_flagToProcess); |
| |
| /** |
| * @brief API to process postAction(base_action) defined in config JSON. |
| * |
| * @note Sequence of tags under any given flag of postAction is EXTREMELY |
| * important to ensure proper processing. The API will process all the |
| * nested items under the base action sequentially. Also if any of the tag |
| * processing fails, the code will not process remaining tags under the |
| * flag. |
| * ******** sample format ************** |
| * fru EEPROM path: { |
| * base_action: { |
| * flag1: { |
| * tag1: { |
| * }, |
| * tag2: { |
| * } |
| * } |
| * flag2: { |
| * tags: { |
| * } |
| * } |
| * } |
| * } |
| * ************************************* |
| * Also, if post action is required to be processed only for FRUs with |
| * certain CCIN then CCIN list can be provided under flag. |
| * |
| * @param[in] i_vpdFruPath - Path to the EEPROM file. |
| * @param[in] i_flagToProcess - To identify which flag(s) needs to be |
| * processed under postAction tag of config JSON. |
| * @param[in] i_parsedVpd - Optional Parsed VPD map. If CCIN match is |
| * required. |
| * @return Execution status. |
| */ |
| bool processPostAction( |
| const std::string& i_vpdFruPath, const std::string& i_flagToProcess, |
| const std::optional<types::VPDMapVariant> i_parsedVpd = std::nullopt); |
| |
| /** |
| * @brief Function to enable and bring MUX out of idle state. |
| * |
| * This finds all the MUX defined in the system json and enables them by |
| * setting the holdidle parameter to 0. |
| * |
| * @throw std::runtime_error |
| */ |
| void enableMuxChips(); |
| |
| /** |
| * @brief An API to perform backup or restore of VPD. |
| * |
| * @param[in,out] io_srcVpdMap - Source VPD map. |
| */ |
| void performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap); |
| |
| /** |
| * @brief API to update "Functional" property. |
| * |
| * The API sets the default value for "Functional" property once if the |
| * property is not yet populated over DBus. As the property value is not |
| * controlled by the VPD-Collection process, if it is found already |
| * populated, the functions skips re-populating the property so that already |
| * existing value can be retained. |
| * |
| * @param[in] i_inventoryObjPath - Inventory path as read from config JSON. |
| * @param[in] io_interfaces - Map to hold all the interfaces for the FRU. |
| */ |
| void processFunctionalProperty(const std::string& i_inventoryObjPath, |
| types::InterfaceMap& io_interfaces); |
| |
| /** |
| * @brief API to update "enabled" property. |
| * |
| * The API sets the default value for "enabled" property once if the |
| * property is not yet populated over DBus. As the property value is not |
| * controlled by the VPD-Collection process, if it is found already |
| * populated, the functions skips re-populating the property so that already |
| * existing value can be retained. |
| * |
| * @param[in] i_inventoryObjPath - Inventory path as read from config JSON. |
| * @param[in] io_interfaces - Map to hold all the interfaces for the FRU. |
| */ |
| void processEnabledProperty(const std::string& i_inventoryObjPath, |
| types::InterfaceMap& io_interfaces); |
| |
| /** |
| * @brief API to form asset tag string for the system. |
| * |
| * @param[in] i_parsedVpdMap - Parsed VPD map. |
| * |
| * @throw std::runtime_error |
| * |
| * @return - Formed asset tag string. |
| */ |
| std::string createAssetTagString( |
| const types::VPDMapVariant& i_parsedVpdMap); |
| |
| /** |
| * @brief API to prime system blueprint. |
| * |
| * The API will traverse the system config JSON and will prime all the FRU |
| * paths which qualifies for priming. |
| */ |
| void primeSystemBlueprint(); |
| |
| /** |
| * @brief API to set symbolic link for system config JSON. |
| * |
| * Once correct device tree is set, symbolic link to the correct sytsem |
| * config JSON is set to be used in subsequent BMC boot. |
| * |
| * @param[in] i_systemJson - system config JSON. |
| */ |
| void setJsonSymbolicLink(const std::string& i_systemJson); |
| |
| /** |
| * @brief API to set present property. |
| * |
| * This API updates the present property of the given FRU with the given |
| * value. Note: It is the responsibility of the caller to determine whether |
| * the present property for the FRU should be updated or not. |
| * |
| * @param[in] i_vpdPath - EEPROM or inventory path. |
| * @param[in] i_value - value to be set. |
| */ |
| void setPresentProperty(const std::string& i_fruPath, const bool& i_value); |
| |
| /** |
| * @brief API to check if the path needs to be skipped for collection. |
| * |
| * Some FRUs, under some given scenarios should not be collected and |
| * skipped. |
| * |
| * @param[in] i_vpdFilePath - EEPROM path. |
| * |
| * @return True - if path is empty or should be skipped, false otherwise. |
| */ |
| bool skipPathForCollection(const std::string& i_vpdFilePath); |
| |
| /** |
| * @brief API to check if present property should be handled for given FRU. |
| * |
| * vpd-manager should update present property for a FRU if and only if it's |
| * not synthesized and vpd-manager handles present property for the FRU. |
| * This API assumes "handlePresence" tag is a subset of "synthesized" tag. |
| * |
| * @param[in] i_fru - JSON block for a single FRU. |
| * |
| * @return true if present property should be handled, false otherwise. |
| */ |
| inline bool isPresentPropertyHandlingRequired( |
| const nlohmann::json& i_fru) const noexcept |
| { |
| // TODO: revisit this to see if this logic can be optimized. |
| return !i_fru.value("synthesized", false) && |
| i_fru.value("handlePresence", true); |
| } |
| |
| // Parsed JSON file. |
| nlohmann::json m_parsedJson{}; |
| |
| // Hold if symlink is present or not. |
| bool m_isSymlinkPresent = false; |
| |
| // Path to config JSON if applicable. |
| std::string& m_configJsonPath; |
| |
| // Keeps track of active thread(s) doing VPD collection. |
| size_t m_activeCollectionThreadCount = 0; |
| |
| // Holds status, if VPD collection has been done or not. |
| // Note: This variable does not give information about successfull or failed |
| // collection. It just states, if the VPD collection process is over or not. |
| bool m_isAllFruCollected = false; |
| |
| // To distinguish the factory reset path. |
| bool m_isFactoryResetDone = false; |
| |
| // Mutex to guard critical resource m_activeCollectionThreadCount. |
| std::mutex m_mutex; |
| |
| // Counting semaphore to limit the number of threads. |
| std::counting_semaphore<constants::MAX_THREADS> m_semaphore; |
| |
| // List of EEPROM paths for which VPD collection thread creation has failed. |
| std::forward_list<std::string> m_failedEepromPaths; |
| }; |
| } // namespace vpd |