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