| #include "phal_service_actions.hpp" | 
 |  | 
 | #include <attributes_info.H> | 
 | #include <libphal.H> | 
 |  | 
 | #include <libguard/guard_interface.hpp> | 
 | #include <libguard/include/guard_record.hpp> | 
 | #include <phosphor-logging/lg2.hpp> | 
 |  | 
 | #include <format> | 
 |  | 
 | using GardType = openpower::guard::GardType; | 
 |  | 
 | namespace openpower | 
 | { | 
 | namespace pels | 
 | { | 
 | namespace phal | 
 | { | 
 |  | 
 | /** | 
 |  * @brief Helper function to get gard type based on | 
 |  *        the given GardType string | 
 |  * | 
 |  * @param[in] guardTypeStr guard type enum value as a string | 
 |  * | 
 |  * @return GardType on success | 
 |  *         Empty optional on failure | 
 |  */ | 
 | std::optional<GardType> getGardType(const std::string& guardTypeStr) | 
 | { | 
 |     const std::unordered_map<std::string, GardType> gardTypeMap = { | 
 |         {"GARD_Fatal", GardType::GARD_Fatal}, | 
 |         {"GARD_User_Manual", GardType::GARD_User_Manual}, | 
 |         {"GARD_Predictive", GardType::GARD_Predictive}, | 
 |         {"GARD_Spare", GardType::GARD_Spare}, | 
 |         {"GARD_Unrecoverable", GardType::GARD_Unrecoverable}, | 
 |     }; | 
 |  | 
 |     auto it = gardTypeMap.find(guardTypeStr); | 
 |     if (it != gardTypeMap.end()) | 
 |     { | 
 |         return it->second; | 
 |     } | 
 |     else | 
 |     { | 
 |         lg2::error("Invalid GardType ({GUARDTYPE})", "GUARDTYPE", guardTypeStr); | 
 |     } | 
 |     return std::nullopt; | 
 | } | 
 |  | 
 | /** | 
 |  * @brief Helper function to create guard records. | 
 |  * | 
 |  * User need to fill the JSON callouts array with below keywords/data | 
 |  * "Entitypath": entity path of the hardware from the PHAL device tree. | 
 |  * "Guardtype": The hardware isolation severity which is defined in | 
 |  *              xyz.openbmc_project.HardwareIsolation.Entry | 
 |  * "Guarded": boolean, true to create gurad records. | 
 |  * | 
 |  * @param[in] jsonCallouts - The array of JSON callouts, or an empty object. | 
 |  * @param[in] plid - The PEL ID to be associated with the guard | 
 |  * @param[in] dataIface - The DataInterface object | 
 |  */ | 
 | void createGuardRecords(const nlohmann::json& jsonCallouts, uint32_t plid, | 
 |                         const DataInterfaceBase& dataIface) | 
 | { | 
 |     if (jsonCallouts.empty()) | 
 |     { | 
 |         return; | 
 |     } | 
 |  | 
 |     if (!jsonCallouts.is_array()) | 
 |     { | 
 |         lg2::error("GUARD: Callout JSON isn't an array"); | 
 |         return; | 
 |     } | 
 |     for (const auto& _callout : jsonCallouts) | 
 |     { | 
 |         try | 
 |         { | 
 |             // Check Callout data conatains Guarded requests. | 
 |             if (!_callout.contains("Guarded")) | 
 |             { | 
 |                 continue; | 
 |             } | 
 |             if (!_callout.at("Guarded").get<bool>()) | 
 |             { | 
 |                 continue; | 
 |             } | 
 |             // Get Entity path required for guard D-bus method | 
 |             // "CreateWithEntityPath" | 
 |             if (!_callout.contains("EntityPath")) | 
 |             { | 
 |                 lg2::error( | 
 |                     "GUARD: Callout data, missing EntityPath information"); | 
 |                 continue; | 
 |             } | 
 |             using EntityPath = std::vector<uint8_t>; | 
 |  | 
 |             auto entityPath = _callout.at("EntityPath").get<EntityPath>(); | 
 |  | 
 |             std::stringstream ss; | 
 |             std::ranges::for_each(entityPath, [&ss](const auto& ele) { | 
 |                 ss << std::format("{:02x} ", ele); | 
 |             }); | 
 |  | 
 |             std::string s = ss.str(); | 
 |             lg2::info("GUARD: ({GUARD_TARGET})", "GUARD_TARGET", s); | 
 |  | 
 |             // Get Guard type | 
 |             std::string guardTypeStr = "GARD_Predictive"; | 
 |             if (!_callout.contains("GuardType")) | 
 |             { | 
 |                 lg2::error( | 
 |                     "GUARD: doesn't have Severity, setting to GARD_Predictive"); | 
 |             } | 
 |             else | 
 |             { | 
 |                 guardTypeStr = _callout.at("GuardType").get<std::string>(); | 
 |             } | 
 |  | 
 |             GardType eGuardType = | 
 |                 getGardType(guardTypeStr).value_or(GardType::GARD_Predictive); | 
 |             dataIface.createGuardRecord(entityPath, eGuardType, plid); | 
 |         } | 
 |         catch (const std::exception& e) | 
 |         { | 
 |             lg2::info("GUARD: Failed entry creation exception:({EXCEPTION})", | 
 |                       "EXCEPTION", e); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | /** | 
 |  * @brief Helper function to create deconfig records. | 
 |  * | 
 |  * User need to fill the JSON callouts array with below keywords/data | 
 |  * "EntityPath": entity path of the hardware from the PHAL device tree. | 
 |  * "Deconfigured": boolean, true to create deconfigure records. | 
 |  * | 
 |  * libphal api is used for creating deconfigure records, which includes | 
 |  * update HWAS_STATE attribute to non functional with PLID information. | 
 |  * | 
 |  * @param[in] jsonCallouts - The array of JSON callouts, or an empty object. | 
 |  * @param[in] plid - PLID value | 
 |  */ | 
 | void createDeconfigRecords(const nlohmann::json& jsonCallouts, uint32_t plid) | 
 | { | 
 |     using namespace openpower::phal::pdbg; | 
 |  | 
 |     if (jsonCallouts.empty()) | 
 |     { | 
 |         return; | 
 |     } | 
 |  | 
 |     if (!jsonCallouts.is_array()) | 
 |     { | 
 |         lg2::error("Deconfig: Callout JSON isn't an array"); | 
 |         return; | 
 |     } | 
 |     for (const auto& _callout : jsonCallouts) | 
 |     { | 
 |         try | 
 |         { | 
 |             // Check Callout data conatains Guarded requests. | 
 |             if (!_callout.contains("Deconfigured")) | 
 |             { | 
 |                 continue; | 
 |             } | 
 |  | 
 |             if (!_callout.at("Deconfigured").get<bool>()) | 
 |             { | 
 |                 continue; | 
 |             } | 
 |  | 
 |             if (!_callout.contains("EntityPath")) | 
 |             { | 
 |                 lg2::error( | 
 |                     "Deconfig: Callout data missing EntityPath information"); | 
 |                 continue; | 
 |             } | 
 |             using EntityPath = std::vector<uint8_t>; | 
 |             auto entityPath = _callout.at("EntityPath").get<EntityPath>(); | 
 |             lg2::info("Deconfig: adding deconfigure record"); | 
 |             // convert to libphal required format. | 
 |             ATTR_PHYS_BIN_PATH_Type physBinPath; | 
 |             std::copy(entityPath.begin(), entityPath.end(), physBinPath); | 
 |             // libphal api to deconfigure the target | 
 |             openpower::phal::pdbg::deconfigureTgt(physBinPath, plid); | 
 |         } | 
 |         catch (const std::exception& e) | 
 |         { | 
 |             lg2::info( | 
 |                 "Deconfig: Failed to create records, exception:({EXCEPTION})", | 
 |                 "EXCEPTION", e); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | void createServiceActions(const nlohmann::json& jsonCallouts, | 
 |                           const DataInterfaceBase& dataIface, uint32_t plid) | 
 | { | 
 |     // Create Guard records. | 
 |     createGuardRecords(jsonCallouts, plid, dataIface); | 
 |     // Create Deconfigure records. | 
 |     createDeconfigRecords(jsonCallouts, plid); | 
 | } | 
 |  | 
 | } // namespace phal | 
 | } // namespace pels | 
 | } // namespace openpower |