1 #include "phal_service_actions.hpp" 2 3 #include <attributes_info.H> 4 #include <libphal.H> 5 6 #include <libguard/guard_interface.hpp> 7 #include <libguard/include/guard_record.hpp> 8 #include <phosphor-logging/lg2.hpp> 9 10 #include <format> 11 12 using GardType = openpower::guard::GardType; 13 14 namespace openpower 15 { 16 namespace pels 17 { 18 namespace phal 19 { 20 21 /** 22 * @brief Helper function to get gard type based on 23 * the given GardType string 24 * 25 * @param[in] guardTypeStr guard type enum value as a string 26 * 27 * @return GardType on success 28 * Empty optional on failure 29 */ 30 std::optional<GardType> getGardType(const std::string& guardTypeStr) 31 { 32 const std::unordered_map<std::string, GardType> gardTypeMap = { 33 {"GARD_Fatal", GardType::GARD_Fatal}, 34 {"GARD_User_Manual", GardType::GARD_User_Manual}, 35 {"GARD_Predictive", GardType::GARD_Predictive}, 36 {"GARD_Spare", GardType::GARD_Spare}, 37 {"GARD_Unrecoverable", GardType::GARD_Unrecoverable}, 38 }; 39 40 auto it = gardTypeMap.find(guardTypeStr); 41 if (it != gardTypeMap.end()) 42 { 43 return it->second; 44 } 45 else 46 { 47 lg2::error("Invalid GardType ({GUARDTYPE})", "GUARDTYPE", guardTypeStr); 48 } 49 return std::nullopt; 50 } 51 52 /** 53 * @brief Helper function to create guard records. 54 * 55 * User need to fill the JSON callouts array with below keywords/data 56 * "Entitypath": entity path of the hardware from the PHAL device tree. 57 * "Guardtype": The hardware isolation severity which is defined in 58 * xyz.openbmc_project.HardwareIsolation.Entry 59 * "Guarded": boolean, true to create gurad records. 60 * 61 * @param[in] jsonCallouts - The array of JSON callouts, or an empty object. 62 * @param[in] plid - The PEL ID to be associated with the guard 63 * @param[in] dataIface - The DataInterface object 64 */ 65 void createGuardRecords(const nlohmann::json& jsonCallouts, uint32_t plid, 66 const DataInterfaceBase& dataIface) 67 { 68 if (jsonCallouts.empty()) 69 { 70 return; 71 } 72 73 if (!jsonCallouts.is_array()) 74 { 75 lg2::error("GUARD: Callout JSON isn't an array"); 76 return; 77 } 78 for (const auto& _callout : jsonCallouts) 79 { 80 try 81 { 82 // Check Callout data conatains Guarded requests. 83 if (!_callout.contains("Guarded")) 84 { 85 continue; 86 } 87 if (!_callout.at("Guarded").get<bool>()) 88 { 89 continue; 90 } 91 // Get Entity path required for guard D-bus method 92 // "CreateWithEntityPath" 93 if (!_callout.contains("EntityPath")) 94 { 95 lg2::error( 96 "GUARD: Callout data, missing EntityPath information"); 97 continue; 98 } 99 using EntityPath = std::vector<uint8_t>; 100 101 auto entityPath = _callout.at("EntityPath").get<EntityPath>(); 102 103 std::stringstream ss; 104 std::ranges::for_each(entityPath, [&ss](const auto& ele) { 105 ss << std::format("{:02x} ", ele); 106 }); 107 108 std::string s = ss.str(); 109 lg2::info("GUARD: ({GUARD_TARGET})", "GUARD_TARGET", s); 110 111 // Get Guard type 112 std::string guardTypeStr = "GARD_Predictive"; 113 if (!_callout.contains("GuardType")) 114 { 115 lg2::error( 116 "GUARD: doesn't have Severity, setting to GARD_Predictive"); 117 } 118 else 119 { 120 guardTypeStr = _callout.at("GuardType").get<std::string>(); 121 } 122 123 GardType eGuardType = 124 getGardType(guardTypeStr).value_or(GardType::GARD_Predictive); 125 dataIface.createGuardRecord(entityPath, eGuardType, plid); 126 } 127 catch (const std::exception& e) 128 { 129 lg2::info("GUARD: Failed entry creation exception:({EXCEPTION})", 130 "EXCEPTION", e); 131 } 132 } 133 } 134 135 /** 136 * @brief Helper function to create deconfig records. 137 * 138 * User need to fill the JSON callouts array with below keywords/data 139 * "EntityPath": entity path of the hardware from the PHAL device tree. 140 * "Deconfigured": boolean, true to create deconfigure records. 141 * 142 * libphal api is used for creating deconfigure records, which includes 143 * update HWAS_STATE attribute to non functional with PLID information. 144 * 145 * @param[in] jsonCallouts - The array of JSON callouts, or an empty object. 146 * @param[in] plid - PLID value 147 */ 148 void createDeconfigRecords(const nlohmann::json& jsonCallouts, uint32_t plid) 149 { 150 using namespace openpower::phal::pdbg; 151 152 if (jsonCallouts.empty()) 153 { 154 return; 155 } 156 157 if (!jsonCallouts.is_array()) 158 { 159 lg2::error("Deconfig: Callout JSON isn't an array"); 160 return; 161 } 162 for (const auto& _callout : jsonCallouts) 163 { 164 try 165 { 166 // Check Callout data conatains Guarded requests. 167 if (!_callout.contains("Deconfigured")) 168 { 169 continue; 170 } 171 172 if (!_callout.at("Deconfigured").get<bool>()) 173 { 174 continue; 175 } 176 177 if (!_callout.contains("EntityPath")) 178 { 179 lg2::error( 180 "Deconfig: Callout data missing EntityPath information"); 181 continue; 182 } 183 using EntityPath = std::vector<uint8_t>; 184 auto entityPath = _callout.at("EntityPath").get<EntityPath>(); 185 lg2::info("Deconfig: adding deconfigure record"); 186 // convert to libphal required format. 187 ATTR_PHYS_BIN_PATH_Type physBinPath; 188 std::copy(entityPath.begin(), entityPath.end(), physBinPath); 189 // libphal api to deconfigure the target 190 openpower::phal::pdbg::deconfigureTgt(physBinPath, plid); 191 } 192 catch (const std::exception& e) 193 { 194 lg2::info( 195 "Deconfig: Failed to create records, exception:({EXCEPTION})", 196 "EXCEPTION", e); 197 } 198 } 199 } 200 201 void createServiceActions(const nlohmann::json& jsonCallouts, 202 const DataInterfaceBase& dataIface, uint32_t plid) 203 { 204 // Create Guard records. 205 createGuardRecords(jsonCallouts, plid, dataIface); 206 // Create Deconfigure records. 207 createDeconfigRecords(jsonCallouts, plid); 208 } 209 210 } // namespace phal 211 } // namespace pels 212 } // namespace openpower 213