1 /* 2 // Copyright (c) 2019 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #include <boost/algorithm/string/join.hpp> 18 #include <me_to_redfish_hooks.hpp> 19 #include <phosphor-logging/log.hpp> 20 21 #include <string_view> 22 23 namespace intel_oem::ipmi::sel::redfish_hooks::me 24 { 25 namespace health_event 26 { 27 namespace smbus_failure 28 { 29 30 static bool messageHook(const SELData& selData, std::string& eventId, 31 std::vector<std::string>& args) 32 { 33 static const boost::container::flat_map<uint8_t, std::string> smlink = { 34 {0x01, "SmLink0/0B"}, 35 {0x02, "SmLink1"}, 36 {0x03, "SmLink2"}, 37 {0x04, "SmLink3"}, 38 {0x05, "SmLink4"}}; 39 40 const auto errorDetails = selData.eventData3; 41 const auto faultySmlink = smlink.find(selData.eventData2); 42 if (faultySmlink == smlink.end()) 43 { 44 return false; 45 } 46 47 eventId = "MESmbusLinkFailure"; 48 49 args.push_back(faultySmlink->second); 50 args.push_back(utils::toHex(errorDetails)); 51 52 return true; 53 } 54 } // namespace smbus_failure 55 56 namespace fw_status 57 { 58 static const boost::container::flat_map<uint8_t, std::string> 59 manufacturingError = { 60 {0x00, "Generic error"}, 61 {0x01, "Wrong or missing VSCC table"}, 62 {0x02, "Wrong sensor scanning period in PIA"}, 63 {0x03, "Wrong device definition in PIA"}, 64 {0x04, "Reserved (Wrong SMART/CLST configuration)"}, 65 {0x05, "Intel ME FW configuration is inconsistent or out of range"}, 66 {0x06, "Reserved"}, 67 {0x07, "Intel ME FW configuration is corrupted"}, 68 {0x08, "SMLink0/0B misconfiguration"}}; 69 70 static const boost::container::flat_map<uint8_t, std::string> peciOverDmiError = 71 {{0x01, "DRAM Init Done HECI message not received by Intel ME before EOP"}, 72 {0x02, "System PCIe bus configuration not known or not valid on DID HECI " 73 "message arrival to Intel ME"}, 74 {0x03, "PECI over DMI run-time failure"}}; 75 76 static const boost::container::flat_map<uint8_t, std::string> 77 mctpInterfaceError = { 78 {0x01, "No DID HECI message received before EOP"}, 79 {0x02, "No MCTP_SET_BUS_OWNER HECI message received by Intel ME on EOP " 80 "arrival " 81 "to ME while MCTP stack is configured in Bus Owner Proxy mode"}}; 82 83 static const boost::container::flat_map<uint8_t, std::string> 84 unsupportedFeature = {{0x00, "Other Segment Defined Feature"}, 85 {0x01, "Fast NM limiting"}, 86 {0x02, "Volumetric Airflow and Outlet Temperature"}, 87 {0x03, "CUPS"}, 88 {0x04, "Thermal policies and Inlet Temperature"}, 89 {0x05, "Platform limiting with MICs"}, 90 {0x07, "Shared power supplies"}, 91 {0x08, "MIC Proxy"}, 92 {0x09, "Reset warning"}, 93 {0x0A, "PMBus Proxy"}, 94 {0x0B, "Always on"}, 95 {0x0C, "IPMI Intel ME FW update"}, 96 {0x0D, "MCTP bus owner"}, 97 {0x0E, "MCTP bus owner proxy"}, 98 {0x0F, "Dual BIOS"}, 99 {0x10, "Battery less"}}; 100 101 static const boost::container::flat_map<uint8_t, std::string> umaError = { 102 {0x00, "UMA Read integrity error. Checksum of data read from UMA differs " 103 "from expected one."}, 104 {0x01, "UMA Read/Write timeout. Timeout occurred during copying data " 105 "from/to UMA."}, 106 {0x02, 107 "UMA not granted. BIOS did not grant any UMA or DRAM INIT done message " 108 "was not received from BIOS before EOP. Intel ME FW goes to recovery."}, 109 {0x03, "UMA size granted by BIOS differs from requested. ME FW goes to " 110 "recovery."}}; 111 112 static const boost::container::flat_map<uint8_t, std::string> pttHealthEvent = { 113 {0x00, "Intel PTT disabled (PTT region is not present)."}, 114 {0x01, "Intel PTT downgrade (PTT data should be not available)."}, 115 {0x02, "Intel PTT disabled (battery less configuration)."}}; 116 117 static const boost::container::flat_map<uint8_t, std::string> 118 bootGuardHealthEvent = { 119 {0x00, "Boot Guard flow error (possible reasons: verification timeout; " 120 "verification error; BIOS Protection error)."}}; 121 122 static const boost::container::flat_map<uint8_t, std::string> restrictedMode = { 123 {0x01, "Firmware entered restricted mode – UMA is not available. " 124 "Restricted features set."}, 125 {0x02, "Firmware exited restricted mode."}}; 126 127 static const boost::container::flat_map<uint8_t, std::string> 128 multiPchModeMisconfig = { 129 {0x01, "BIOS did not set reset synchronization in multiPCH mode"}, 130 {0x02, 131 "PMC indicates different non/legacy mode for the PCH than BMC set " 132 "on the GPIO"}, 133 {0x03, 134 "Misconfiguration MPCH support enabled due to BTG support enabled"}}; 135 136 static const boost::container::flat_map<uint8_t, std::string> 137 flashVerificationError = { 138 {0x00, "OEM Public Key verification error"}, 139 {0x01, "Flash Descriptor Region Manifest verification error"}, 140 {0x02, "Soft Straps verification error"}}; 141 142 namespace autoconfiguration 143 { 144 145 bool messageHook(const SELData& selData, std::string& eventId, 146 std::vector<std::string>& args) 147 { 148 static const boost::container::flat_map<uint8_t, std::string> dcSource = { 149 {0b00, "BMC"}, {0b01, "PSU"}, {0b10, "On-board power sensor"}}; 150 151 static const boost::container::flat_map<uint8_t, std::string> 152 chassisSource = {{0b00, "BMC"}, 153 {0b01, "PSU"}, 154 {0b10, "On-board power sensor"}, 155 {0b11, "Not supported"}}; 156 157 static const boost::container::flat_map<uint8_t, std::string> 158 efficiencySource = { 159 {0b00, "BMC"}, {0b01, "PSU"}, {0b11, "Not supported"}}; 160 161 static const boost::container::flat_map<uint8_t, std::string> 162 unmanagedSource = {{0b00, "BMC"}, {0b01, "Estimated"}}; 163 164 static const boost::container::flat_map<uint8_t, std::string> 165 failureReason = {{0b00, "BMC discovery failure"}, 166 {0b01, "Insufficient factory configuration"}, 167 {0b10, "Unknown sensor type"}, 168 {0b11, "Other error encountered"}}; 169 170 auto succeeded = selData.eventData3 >> 7 & 0b1; 171 if (succeeded) 172 { 173 eventId = "MEAutoConfigSuccess"; 174 175 auto dc = dcSource.find(selData.eventData3 >> 5 & 0b11); 176 auto chassis = chassisSource.find(selData.eventData3 >> 3 & 0b11); 177 auto efficiency = efficiencySource.find(selData.eventData3 >> 1 & 0b11); 178 auto unmanaged = unmanagedSource.find(selData.eventData3 & 0b1); 179 if (dc == dcSource.end() || chassis == chassisSource.end() || 180 efficiency == efficiencySource.end() || 181 unmanaged == unmanagedSource.end()) 182 { 183 return false; 184 } 185 186 args.push_back(dc->second); 187 args.push_back(chassis->second); 188 args.push_back(efficiency->second); 189 args.push_back(unmanaged->second); 190 } 191 else 192 { 193 eventId = "MEAutoConfigFailed"; 194 195 const auto it = failureReason.find(selData.eventData3 >> 5 & 0b11); 196 if (it == failureReason.end()) 197 { 198 return false; 199 } 200 201 args.push_back(it->second); 202 } 203 204 return true; 205 } 206 } // namespace autoconfiguration 207 208 namespace factory_reset 209 { 210 bool messageHook(const SELData& selData, std::string& eventId, 211 std::vector<std::string>& args) 212 { 213 static const boost::container::flat_map<uint8_t, std::string> 214 restoreToFactoryPreset = { 215 {0x00, 216 "Flash file system error detected. Automatic restore to factory " 217 "presets has been triggered."}, 218 {0x01, "Automatic restore to factory presets has been completed."}, 219 {0x02, "Restore to factory presets triggered by Force ME Recovery " 220 "IPMI command has been completed."}, 221 {0x03, 222 "Restore to factory presets triggered by AC power cycle with " 223 "Recovery jumper asserted has been completed."}}; 224 225 auto param = restoreToFactoryPreset.find(selData.eventData3); 226 if (param == restoreToFactoryPreset.end()) 227 { 228 return false; 229 } 230 231 if (selData.eventData3 == 0x00) 232 { 233 eventId = "MEFactoryResetError"; 234 } 235 else 236 { 237 eventId = "MEFactoryRestore"; 238 } 239 240 args.push_back(param->second); 241 return true; 242 } 243 } // namespace factory_reset 244 245 namespace flash_state 246 { 247 bool messageHook(const SELData& selData, std::string& eventId, 248 std::vector<std::string>& args) 249 { 250 static const boost::container::flat_map<uint8_t, std::string> 251 flashStateInformation = { 252 {0x00, 253 "Flash partition table, recovery image or factory presets image " 254 "corrupted"}, 255 {0x01, "Flash erase limit has been reached"}, 256 {0x02, 257 "Flash write limit has been reached. Writing to flash has been " 258 "disabled"}, 259 {0x03, "Writing to the flash has been enabled"}}; 260 261 auto param = flashStateInformation.find(selData.eventData3); 262 if (param == flashStateInformation.end()) 263 { 264 return false; 265 } 266 267 if (selData.eventData3 == 0x03) 268 { 269 eventId = "MEFlashStateInformationWritingEnabled"; 270 } 271 else 272 { 273 eventId = "MEFlashStateInformation"; 274 } 275 276 args.push_back(param->second); 277 return true; 278 } 279 } // namespace flash_state 280 281 static bool messageHook(const SELData& selData, std::string& eventId, 282 std::vector<std::string>& args) 283 { 284 static const boost::container::flat_map< 285 uint8_t, 286 std::pair<std::string, std::optional<std::variant<utils::ParserFunc, 287 utils::MessageMap>>>> 288 eventMap = { 289 {0x00, {"MERecoveryGpioForced", {}}}, 290 {0x01, {"MEImageExecutionFailed", {}}}, 291 {0x02, {"MEFlashEraseError", {}}}, 292 {0x03, {{}, flash_state::messageHook}}, 293 {0x04, {"MEInternalError", {}}}, 294 {0x05, {"MEExceptionDuringShutdown", {}}}, 295 {0x06, {"MEDirectFlashUpdateRequested", {}}}, 296 {0x07, {"MEManufacturingError", manufacturingError}}, 297 {0x08, {{}, factory_reset::messageHook}}, 298 {0x09, {"MEFirmwareException", utils::logByteHex<2>}}, 299 {0x0A, {"MEFlashWearOutWarning", utils::logByteDec<2>}}, 300 {0x0D, {"MEPeciOverDmiError", peciOverDmiError}}, 301 {0x0E, {"MEMctpInterfaceError", mctpInterfaceError}}, 302 {0x0F, {{}, autoconfiguration::messageHook}}, 303 {0x10, {"MEUnsupportedFeature", unsupportedFeature}}, 304 {0x12, {"MECpuDebugCapabilityDisabled", {}}}, 305 {0x13, {"MEUmaError", umaError}}, 306 {0x16, {"MEPttHealthEvent", pttHealthEvent}}, 307 {0x17, {"MEBootGuardHealthEvent", bootGuardHealthEvent}}, 308 {0x18, {"MERestrictedMode", restrictedMode}}, 309 {0x19, {"MEMultiPchModeMisconfig", multiPchModeMisconfig}}, 310 {0x1A, {"MEFlashVerificationError", flashVerificationError}}}; 311 312 return utils::genericMessageHook(eventMap, selData, eventId, args); 313 } 314 } // namespace fw_status 315 316 static bool messageHook(const SELData& selData, std::string& eventId, 317 std::vector<std::string>& args) 318 { 319 const HealthEventType healthEventType = 320 static_cast<HealthEventType>(selData.offset); 321 322 switch (healthEventType) 323 { 324 case HealthEventType::FirmwareStatus: 325 return fw_status::messageHook(selData, eventId, args); 326 break; 327 328 case HealthEventType::SmbusLinkFailure: 329 return smbus_failure::messageHook(selData, eventId, args); 330 break; 331 } 332 333 return false; 334 } 335 } // namespace health_event 336 337 /** 338 * @brief Main entry point for parsing ME IPMI Platform Events 339 * 340 * @brief selData - IPMI Platform Event structure 341 * @brief ipmiRaw - the same event in raw binary form 342 * 343 * @returns true if event was successfully parsed and consumed 344 */ 345 bool messageHook(const SELData& selData, const std::string& ipmiRaw) 346 { 347 const EventSensor meSensor = static_cast<EventSensor>(selData.sensorNum); 348 std::string eventId; 349 std::vector<std::string> args; 350 351 switch (meSensor) 352 { 353 case EventSensor::MeFirmwareHealth: 354 if (health_event::messageHook(selData, eventId, args)) 355 { 356 utils::storeRedfishEvent(ipmiRaw, eventId, args); 357 return true; 358 } 359 break; 360 } 361 362 return defaultMessageHook(ipmiRaw); 363 } 364 } // namespace intel_oem::ipmi::sel::redfish_hooks::me 365