1815f9f55STom Joseph #include "pldm.hpp" 2815f9f55STom Joseph 300325238STom Joseph #include "file.hpp" 400325238STom Joseph 5a8857c50SChris Cain #include <fmt/core.h> 6815f9f55STom Joseph #include <libpldm/entity.h> 7815f9f55STom Joseph #include <libpldm/platform.h> 8815f9f55STom Joseph #include <libpldm/state_set.h> 936313c71SEddie James #include <libpldm/state_set_oem_ibm.h> 10815f9f55STom Joseph 11815f9f55STom Joseph #include <phosphor-logging/log.hpp> 12bae4d07eSChris Cain #include <sdbusplus/bus.hpp> 13bae4d07eSChris Cain #include <sdeventplus/clock.hpp> 14bae4d07eSChris Cain #include <sdeventplus/exception.hpp> 15bae4d07eSChris Cain #include <sdeventplus/source/io.hpp> 16bae4d07eSChris Cain #include <sdeventplus/source/time.hpp> 17bae4d07eSChris Cain 18bae4d07eSChris Cain #include <algorithm> 19815f9f55STom Joseph 20815f9f55STom Joseph namespace pldm 21815f9f55STom Joseph { 22815f9f55STom Joseph 23815f9f55STom Joseph using namespace phosphor::logging; 24815f9f55STom Joseph 25bae4d07eSChris Cain using namespace sdeventplus; 26bae4d07eSChris Cain using namespace sdeventplus::source; 27bae4d07eSChris Cain constexpr auto clockId = sdeventplus::ClockId::RealTime; 28bae4d07eSChris Cain using Clock = sdeventplus::Clock<clockId>; 29bae4d07eSChris Cain using Timer = Time<clockId>; 30bae4d07eSChris Cain 31cbad219eSEddie James void Interface::fetchSensorInfo(uint16_t stateSetId, 32cbad219eSEddie James SensorToInstance& sensorInstanceMap, 33815f9f55STom Joseph SensorOffset& sensorOffset) 34815f9f55STom Joseph { 35cbad219eSEddie James PdrList pdrs{}; 36bae4d07eSChris Cain static bool tracedError = false; 37cbad219eSEddie James 38cbad219eSEddie James auto& bus = open_power::occ::utils::getBus(); 39cbad219eSEddie James try 40cbad219eSEddie James { 41cbad219eSEddie James auto method = bus.new_method_call( 42cbad219eSEddie James "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm", 43cbad219eSEddie James "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR"); 44bae4d07eSChris Cain method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId); 45cbad219eSEddie James 46cbad219eSEddie James auto responseMsg = bus.call(method); 47cbad219eSEddie James responseMsg.read(pdrs); 48cbad219eSEddie James } 49af40808fSPatrick Williams catch (const sdbusplus::exception_t& e) 50cbad219eSEddie James { 51bae4d07eSChris Cain if (!tracedError) 52bae4d07eSChris Cain { 53bae4d07eSChris Cain log<level::ERR>( 54bae4d07eSChris Cain fmt::format( 55bae4d07eSChris Cain "fetchSensorInfo: Failed to find stateSetID:{} PDR: {}", 56bae4d07eSChris Cain stateSetId, e.what()) 57bae4d07eSChris Cain .c_str()); 58bae4d07eSChris Cain tracedError = true; 59bae4d07eSChris Cain } 60cbad219eSEddie James } 61cbad219eSEddie James 62cbad219eSEddie James if (pdrs.empty()) 63cbad219eSEddie James { 64bae4d07eSChris Cain if (!tracedError) 65bae4d07eSChris Cain { 66bae4d07eSChris Cain log<level::ERR>( 67bae4d07eSChris Cain fmt::format( 68bae4d07eSChris Cain "fetchSensorInfo: state sensor PDRs ({}) not present", 69bae4d07eSChris Cain stateSetId) 70bae4d07eSChris Cain .c_str()); 71bae4d07eSChris Cain tracedError = true; 72bae4d07eSChris Cain } 73cbad219eSEddie James return; 74cbad219eSEddie James } 75cbad219eSEddie James 76bae4d07eSChris Cain // Found PDR 77bae4d07eSChris Cain if (tracedError) 78bae4d07eSChris Cain { 79bae4d07eSChris Cain log<level::INFO>( 80bae4d07eSChris Cain fmt::format("fetchSensorInfo: found {} PDRs", pdrs.size()).c_str()); 81bae4d07eSChris Cain tracedError = false; 82bae4d07eSChris Cain } 83bae4d07eSChris Cain 84815f9f55STom Joseph bool offsetFound = false; 85f3a4a69fSGeorge Liu auto stateSensorPDR = 86815f9f55STom Joseph reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data()); 87f3a4a69fSGeorge Liu auto possibleStatesPtr = stateSensorPDR->possible_states; 88f3a4a69fSGeorge Liu for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count; 89f3a4a69fSGeorge Liu offset++) 90815f9f55STom Joseph { 91815f9f55STom Joseph auto possibleStates = 92815f9f55STom Joseph reinterpret_cast<const state_sensor_possible_states*>( 93815f9f55STom Joseph possibleStatesPtr); 94815f9f55STom Joseph 95cbad219eSEddie James if (possibleStates->state_set_id == stateSetId) 96815f9f55STom Joseph { 97815f9f55STom Joseph sensorOffset = offset; 98815f9f55STom Joseph offsetFound = true; 99815f9f55STom Joseph break; 100815f9f55STom Joseph } 101815f9f55STom Joseph possibleStatesPtr += sizeof(possibleStates->state_set_id) + 102815f9f55STom Joseph sizeof(possibleStates->possible_states_size) + 103815f9f55STom Joseph possibleStates->possible_states_size; 104815f9f55STom Joseph } 105815f9f55STom Joseph 106815f9f55STom Joseph if (!offsetFound) 107815f9f55STom Joseph { 108cbad219eSEddie James log<level::ERR>("pldm: state sensor PDR not found"); 109815f9f55STom Joseph return; 110815f9f55STom Joseph } 111815f9f55STom Joseph 1121339ab60SMatt Spinler // To order SensorID based on the EntityInstance. 1131339ab60SMatt Spinler // Note that when a proc is on a DCM, the PDRs for these sensors 1141339ab60SMatt Spinler // could have the same instance IDs but different container IDs. 1151339ab60SMatt Spinler std::map<uint32_t, SensorID> entityInstMap{}; 116815f9f55STom Joseph for (auto& pdr : pdrs) 117815f9f55STom Joseph { 118815f9f55STom Joseph auto pdrPtr = 119815f9f55STom Joseph reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data()); 12072d01aabSChris Cain uint32_t key = pdrPtr->sensor_id; 1211339ab60SMatt Spinler entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->sensor_id)); 122815f9f55STom Joseph } 123815f9f55STom Joseph 124815f9f55STom Joseph open_power::occ::instanceID count = start; 125815f9f55STom Joseph for (auto const& pair : entityInstMap) 126815f9f55STom Joseph { 127815f9f55STom Joseph sensorInstanceMap.emplace(pair.second, count); 128815f9f55STom Joseph count++; 129815f9f55STom Joseph } 130815f9f55STom Joseph } 131815f9f55STom Joseph 132af40808fSPatrick Williams void Interface::sensorEvent(sdbusplus::message_t& msg) 133815f9f55STom Joseph { 134815f9f55STom Joseph if (!isOCCSensorCacheValid()) 135815f9f55STom Joseph { 136cbad219eSEddie James fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 137cbad219eSEddie James sensorToOCCInstance, OCCSensorOffset); 138815f9f55STom Joseph } 139815f9f55STom Joseph 140cbad219eSEddie James if (sensorToSBEInstance.empty()) 141815f9f55STom Joseph { 142cbad219eSEddie James fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSBEInstance, 143cbad219eSEddie James SBESensorOffset); 144815f9f55STom Joseph } 145815f9f55STom Joseph 14672d01aabSChris Cain TerminusID sensorTid{}; 147815f9f55STom Joseph SensorID sensorId{}; 148815f9f55STom Joseph SensorOffset msgSensorOffset{}; 149815f9f55STom Joseph EventState eventState{}; 150815f9f55STom Joseph EventState previousEventState{}; 151815f9f55STom Joseph 15272d01aabSChris Cain msg.read(sensorTid, sensorId, msgSensorOffset, eventState, 15372d01aabSChris Cain previousEventState); 154815f9f55STom Joseph 155cbad219eSEddie James if (msgSensorOffset == OCCSensorOffset) 156815f9f55STom Joseph { 157cbad219eSEddie James auto sensorEntry = sensorToOCCInstance.find(sensorId); 158cbad219eSEddie James 159432dc486SEddie James if (sensorEntry != sensorToOCCInstance.end()) 160cbad219eSEddie James { 1618b508bfbSChris Cain const uint8_t instance = sensorEntry->second; 162*7b00cde2SChris Cain bool isRunning = false; 163cbad219eSEddie James if (eventState == 164cbad219eSEddie James static_cast<EventState>( 165815f9f55STom Joseph PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE)) 166815f9f55STom Joseph { 167a8857c50SChris Cain log<level::INFO>( 1688b508bfbSChris Cain fmt::format("PLDM: OCC{} is RUNNING", instance).c_str()); 169*7b00cde2SChris Cain isRunning = true; 170815f9f55STom Joseph } 171815f9f55STom Joseph else if (eventState == 172815f9f55STom Joseph static_cast<EventState>( 173815f9f55STom Joseph PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED)) 174815f9f55STom Joseph { 1758b508bfbSChris Cain log<level::INFO>( 1768b508bfbSChris Cain fmt::format("PLDM: OCC{} has now STOPPED", instance) 177a8857c50SChris Cain .c_str()); 178815f9f55STom Joseph } 179bae4d07eSChris Cain else if (eventState == 180bae4d07eSChris Cain static_cast<EventState>( 181bae4d07eSChris Cain PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT)) 182bae4d07eSChris Cain { 183bae4d07eSChris Cain log<level::INFO>( 184bae4d07eSChris Cain fmt::format( 185bae4d07eSChris Cain "PLDM: OCC{} has now STOPPED and system is in SAFE MODE", 1868b508bfbSChris Cain instance) 187bae4d07eSChris Cain .c_str()); 18831a2f13aSSheldon Bailey 18931a2f13aSSheldon Bailey // Setting safe mode true 19031a2f13aSSheldon Bailey safeModeCallBack(true); 191bae4d07eSChris Cain } 192bae4d07eSChris Cain else 193bae4d07eSChris Cain { 194bae4d07eSChris Cain log<level::INFO>( 195bae4d07eSChris Cain fmt::format("PLDM: Unexpected PLDM state {} for OCC{}", 1968b508bfbSChris Cain eventState, instance) 197bae4d07eSChris Cain .c_str()); 198bae4d07eSChris Cain } 199*7b00cde2SChris Cain 200*7b00cde2SChris Cain if (!open_power::occ::utils::isHostRunning()) 201*7b00cde2SChris Cain { 202*7b00cde2SChris Cain log<level::INFO>("PLDM: HOST is not running"); 203*7b00cde2SChris Cain isRunning = false; 204*7b00cde2SChris Cain } 205*7b00cde2SChris Cain callBack(instance, isRunning); 206*7b00cde2SChris Cain 207432dc486SEddie James return; 208cbad219eSEddie James } 209432dc486SEddie James } 210432dc486SEddie James 211432dc486SEddie James if (msgSensorOffset == SBESensorOffset) 212cbad219eSEddie James { 213cbad219eSEddie James auto sensorEntry = sensorToSBEInstance.find(sensorId); 214815f9f55STom Joseph 215432dc486SEddie James if (sensorEntry != sensorToSBEInstance.end()) 216cbad219eSEddie James { 21712d0b828SChris Cain const uint8_t instance = sensorEntry->second; 21812d0b828SChris Cain auto match = std::find(outstandingHResets.begin(), 21912d0b828SChris Cain outstandingHResets.end(), instance); 22012d0b828SChris Cain if (match != outstandingHResets.end()) 22112d0b828SChris Cain { 22212d0b828SChris Cain outstandingHResets.erase(match); 223cbad219eSEddie James if (eventState == static_cast<EventState>(SBE_HRESET_NOT_READY)) 224cbad219eSEddie James { 225bae4d07eSChris Cain log<level::INFO>( 226bae4d07eSChris Cain fmt::format("pldm: HRESET is NOT READY (OCC{})", 22712d0b828SChris Cain instance) 228bae4d07eSChris Cain .c_str()); 229cbad219eSEddie James } 23012d0b828SChris Cain else if (eventState == 23112d0b828SChris Cain static_cast<EventState>(SBE_HRESET_READY)) 232cbad219eSEddie James { 23312d0b828SChris Cain sbeCallBack(instance, true); 234cbad219eSEddie James } 23512d0b828SChris Cain else if (eventState == 23612d0b828SChris Cain static_cast<EventState>(SBE_HRESET_FAILED)) 237cbad219eSEddie James { 23812d0b828SChris Cain sbeCallBack(instance, false); 239cbad219eSEddie James } 240cbad219eSEddie James } 24112d0b828SChris Cain // else request was not from us 24212d0b828SChris Cain } 243cbad219eSEddie James } 244432dc486SEddie James } 245cbad219eSEddie James 246af40808fSPatrick Williams void Interface::hostStateEvent(sdbusplus::message_t& msg) 247157467d0SChris Cain { 248157467d0SChris Cain std::map<std::string, std::variant<std::string>> properties{}; 249157467d0SChris Cain std::string interface; 250157467d0SChris Cain msg.read(interface, properties); 251157467d0SChris Cain const auto stateEntry = properties.find("CurrentHostState"); 252157467d0SChris Cain if (stateEntry != properties.end()) 253157467d0SChris Cain { 254157467d0SChris Cain auto stateEntryValue = stateEntry->second; 255157467d0SChris Cain auto propVal = std::get<std::string>(stateEntryValue); 256157467d0SChris Cain if (propVal == "xyz.openbmc_project.State.Host.HostState.Off") 257157467d0SChris Cain { 258157467d0SChris Cain clearData(); 259157467d0SChris Cain } 260157467d0SChris Cain } 261157467d0SChris Cain } 262157467d0SChris Cain 263bae4d07eSChris Cain void Interface::clearData() 264bae4d07eSChris Cain { 26572d01aabSChris Cain if (!sensorToOCCInstance.empty()) 26672d01aabSChris Cain { 26772d01aabSChris Cain log<level::INFO>( 26872d01aabSChris Cain fmt::format("clearData: Clearing sensorToOCCInstance ({} entries)", 26972d01aabSChris Cain sensorToOCCInstance.size()) 27072d01aabSChris Cain .c_str()); 27172d01aabSChris Cain for (auto entry : sensorToOCCInstance) 27272d01aabSChris Cain { 27372d01aabSChris Cain log<level::INFO>( 27472d01aabSChris Cain fmt::format("clearData: OCC{} / sensorID: 0x{:04X}", 27572d01aabSChris Cain entry.second, entry.first) 27672d01aabSChris Cain .c_str()); 27772d01aabSChris Cain } 278815f9f55STom Joseph sensorToOCCInstance.clear(); 27972d01aabSChris Cain } 28072d01aabSChris Cain if (!occInstanceToEffecter.empty()) 28172d01aabSChris Cain { 28272d01aabSChris Cain log<level::DEBUG>( 28372d01aabSChris Cain fmt::format( 28472d01aabSChris Cain "clearData: Clearing occInstanceToEffecter ({} entries)", 28572d01aabSChris Cain occInstanceToEffecter.size()) 28672d01aabSChris Cain .c_str()); 28700325238STom Joseph occInstanceToEffecter.clear(); 28872d01aabSChris Cain } 28972d01aabSChris Cain if (!sensorToSBEInstance.empty()) 29072d01aabSChris Cain { 29172d01aabSChris Cain log<level::DEBUG>( 29272d01aabSChris Cain fmt::format("clearData: Clearing sensorToSBEInstance ({} entries)", 29372d01aabSChris Cain sensorToSBEInstance.size()) 29472d01aabSChris Cain .c_str()); 295cbad219eSEddie James sensorToSBEInstance.clear(); 29672d01aabSChris Cain } 29772d01aabSChris Cain if (!sbeInstanceToEffecter.empty()) 29872d01aabSChris Cain { 29972d01aabSChris Cain log<level::DEBUG>( 30072d01aabSChris Cain fmt::format( 30172d01aabSChris Cain "clearData: Clearing sbeInstanceToEffecter ({} entries)", 30272d01aabSChris Cain sbeInstanceToEffecter.size()) 30372d01aabSChris Cain .c_str()); 304cbad219eSEddie James sbeInstanceToEffecter.clear(); 305815f9f55STom Joseph } 30672d01aabSChris Cain } 307815f9f55STom Joseph 308432dc486SEddie James void Interface::fetchEffecterInfo(uint16_t stateSetId, 309cbad219eSEddie James InstanceToEffecter& instanceToEffecterMap, 310cbad219eSEddie James CompositeEffecterCount& effecterCount, 311cbad219eSEddie James uint8_t& stateIdPos) 31200325238STom Joseph { 313cbad219eSEddie James PdrList pdrs{}; 314cbad219eSEddie James 315cbad219eSEddie James auto& bus = open_power::occ::utils::getBus(); 316cbad219eSEddie James try 317cbad219eSEddie James { 318cbad219eSEddie James auto method = bus.new_method_call( 319cbad219eSEddie James "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm", 320cbad219eSEddie James "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR"); 321bae4d07eSChris Cain method.append(tid, static_cast<uint16_t>(PLDM_ENTITY_PROC), stateSetId); 322cbad219eSEddie James 323cbad219eSEddie James auto responseMsg = bus.call(method); 324cbad219eSEddie James responseMsg.read(pdrs); 325cbad219eSEddie James } 326af40808fSPatrick Williams catch (const sdbusplus::exception_t& e) 327cbad219eSEddie James { 328cbad219eSEddie James log<level::ERR>("pldm: Failed to fetch the state effecter PDRs", 329cbad219eSEddie James entry("ERROR=%s", e.what())); 330cbad219eSEddie James } 331cbad219eSEddie James 332cbad219eSEddie James if (!pdrs.size()) 333cbad219eSEddie James { 334cbad219eSEddie James log<level::ERR>("pldm: state effecter PDRs not present"); 335cbad219eSEddie James return; 336cbad219eSEddie James } 337cbad219eSEddie James 33800325238STom Joseph bool offsetFound = false; 339f3a4a69fSGeorge Liu auto stateEffecterPDR = 34000325238STom Joseph reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data()); 341f3a4a69fSGeorge Liu auto possibleStatesPtr = stateEffecterPDR->possible_states; 342f3a4a69fSGeorge Liu for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count; 343f3a4a69fSGeorge Liu offset++) 34400325238STom Joseph { 34500325238STom Joseph auto possibleStates = 34600325238STom Joseph reinterpret_cast<const state_effecter_possible_states*>( 34700325238STom Joseph possibleStatesPtr); 34800325238STom Joseph 349cbad219eSEddie James if (possibleStates->state_set_id == stateSetId) 35000325238STom Joseph { 351cbad219eSEddie James stateIdPos = offset; 352f3a4a69fSGeorge Liu effecterCount = stateEffecterPDR->composite_effecter_count; 35300325238STom Joseph offsetFound = true; 35400325238STom Joseph break; 35500325238STom Joseph } 35600325238STom Joseph possibleStatesPtr += sizeof(possibleStates->state_set_id) + 35700325238STom Joseph sizeof(possibleStates->possible_states_size) + 35800325238STom Joseph possibleStates->possible_states_size; 35900325238STom Joseph } 36000325238STom Joseph 36100325238STom Joseph if (!offsetFound) 36200325238STom Joseph { 36300325238STom Joseph return; 36400325238STom Joseph } 36500325238STom Joseph 3660f516528SChris Cain std::map<uint32_t, EffecterID> entityInstMap{}; 36700325238STom Joseph for (auto& pdr : pdrs) 36800325238STom Joseph { 36900325238STom Joseph auto pdrPtr = 37000325238STom Joseph reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data()); 37172d01aabSChris Cain uint32_t key = pdrPtr->effecter_id; 3721339ab60SMatt Spinler entityInstMap.emplace(key, static_cast<SensorID>(pdrPtr->effecter_id)); 37300325238STom Joseph } 37400325238STom Joseph 37500325238STom Joseph open_power::occ::instanceID position = start; 37600325238STom Joseph for (auto const& pair : entityInstMap) 37700325238STom Joseph { 378cbad219eSEddie James instanceToEffecterMap.emplace(position, pair.second); 37900325238STom Joseph position++; 38000325238STom Joseph } 38100325238STom Joseph } 38200325238STom Joseph 38300325238STom Joseph std::vector<uint8_t> 3848b508bfbSChris Cain Interface::prepareSetEffecterReq(EffecterID effecterId, 38500325238STom Joseph CompositeEffecterCount effecterCount, 386cbad219eSEddie James uint8_t stateIdPos, uint8_t stateSetValue) 38700325238STom Joseph { 3888b508bfbSChris Cain if (!getMctpInstanceId()) 3898b508bfbSChris Cain { 3908b508bfbSChris Cain return std::vector<uint8_t>(); 3918b508bfbSChris Cain } 3928b508bfbSChris Cain 39300325238STom Joseph std::vector<uint8_t> request( 39400325238STom Joseph sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) + 39500325238STom Joseph (effecterCount * sizeof(set_effecter_state_field))); 39600325238STom Joseph auto requestMsg = reinterpret_cast<pldm_msg*>(request.data()); 39700325238STom Joseph std::vector<set_effecter_state_field> stateField; 39800325238STom Joseph 39900325238STom Joseph for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++) 40000325238STom Joseph { 401cbad219eSEddie James if (effecterPos == stateIdPos) 40200325238STom Joseph { 403cbad219eSEddie James stateField.emplace_back( 404cbad219eSEddie James set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue}); 40500325238STom Joseph } 40600325238STom Joseph else 40700325238STom Joseph { 40800325238STom Joseph stateField.emplace_back( 40900325238STom Joseph set_effecter_state_field{PLDM_NO_CHANGE, 0}); 41000325238STom Joseph } 41100325238STom Joseph } 41200325238STom Joseph auto rc = encode_set_state_effecter_states_req( 4138b508bfbSChris Cain mctpInstance.value(), effecterId, effecterCount, stateField.data(), 4148b508bfbSChris Cain requestMsg); 41500325238STom Joseph if (rc != PLDM_SUCCESS) 41600325238STom Joseph { 41700325238STom Joseph log<level::ERR>("encode set effecter states request returned error ", 41800325238STom Joseph entry("RC=%d", rc)); 41900325238STom Joseph request.clear(); 42000325238STom Joseph } 42100325238STom Joseph return request; 42200325238STom Joseph } 42300325238STom Joseph 42400325238STom Joseph void Interface::resetOCC(open_power::occ::instanceID occInstanceId) 42500325238STom Joseph { 426bae4d07eSChris Cain if (open_power::occ::utils::isHostRunning()) 427bae4d07eSChris Cain { 42800325238STom Joseph if (!isPDREffecterCacheValid()) 42900325238STom Joseph { 430432dc486SEddie James fetchEffecterInfo(PLDM_STATE_SET_BOOT_RESTART_CAUSE, 431432dc486SEddie James occInstanceToEffecter, OCCEffecterCount, 432432dc486SEddie James bootRestartPosition); 43300325238STom Joseph } 43400325238STom Joseph 43500325238STom Joseph // Find the matching effecter for the OCC instance 43600325238STom Joseph auto effecterEntry = occInstanceToEffecter.find(occInstanceId); 43700325238STom Joseph if (effecterEntry == occInstanceToEffecter.end()) 43800325238STom Joseph { 43900325238STom Joseph log<level::ERR>( 4400f516528SChris Cain fmt::format( 4410f516528SChris Cain "pldm: Failed to find a matching effecter for OCC instance {}", 4420f516528SChris Cain occInstanceId) 4430f516528SChris Cain .c_str()); 44400325238STom Joseph 44500325238STom Joseph return; 44600325238STom Joseph } 44700325238STom Joseph 448cbad219eSEddie James // Prepare the SetStateEffecterStates request to reset the OCC 449cbad219eSEddie James auto request = prepareSetEffecterReq( 4508b508bfbSChris Cain effecterEntry->second, OCCEffecterCount, bootRestartPosition, 4518b508bfbSChris Cain PLDM_STATE_SET_BOOT_RESTART_CAUSE_WARM_RESET); 452cbad219eSEddie James 453cbad219eSEddie James if (request.empty()) 454cbad219eSEddie James { 455bae4d07eSChris Cain log<level::ERR>( 456bae4d07eSChris Cain "pldm: SetStateEffecterStates OCC reset request empty"); 457cbad219eSEddie James return; 458cbad219eSEddie James } 459cbad219eSEddie James 460bae4d07eSChris Cain // Send request to reset the OCCs/PM Complex (ignore response) 461bae4d07eSChris Cain sendPldm(request, occInstanceId, false); 462bae4d07eSChris Cain } 463bae4d07eSChris Cain else 464bae4d07eSChris Cain { 465bae4d07eSChris Cain log<level::ERR>( 466bae4d07eSChris Cain fmt::format("resetOCC: HOST is not running (OCC{})", occInstanceId) 467bae4d07eSChris Cain .c_str()); 468bae4d07eSChris Cain clearData(); 469bae4d07eSChris Cain } 470cbad219eSEddie James } 471cbad219eSEddie James 472cbad219eSEddie James void Interface::sendHRESET(open_power::occ::instanceID sbeInstanceId) 473cbad219eSEddie James { 474bae4d07eSChris Cain if (open_power::occ::utils::isHostRunning()) 475bae4d07eSChris Cain { 476cbad219eSEddie James if (sbeInstanceToEffecter.empty()) 477cbad219eSEddie James { 478432dc486SEddie James fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE, 479cbad219eSEddie James sbeInstanceToEffecter, SBEEffecterCount, 480cbad219eSEddie James sbeMaintenanceStatePosition); 481cbad219eSEddie James } 482cbad219eSEddie James 483cbad219eSEddie James auto effecterEntry = sbeInstanceToEffecter.find(sbeInstanceId); 484cbad219eSEddie James if (effecterEntry == sbeInstanceToEffecter.end()) 485cbad219eSEddie James { 486cbad219eSEddie James log<level::ERR>( 487cbad219eSEddie James "pldm: Failed to find a matching effecter for SBE instance", 488cbad219eSEddie James entry("SBE=%d", sbeInstanceId)); 489cbad219eSEddie James return; 490cbad219eSEddie James } 491cbad219eSEddie James 492cbad219eSEddie James // Prepare the SetStateEffecterStates request to HRESET the SBE 493cbad219eSEddie James auto request = prepareSetEffecterReq( 4948b508bfbSChris Cain effecterEntry->second, SBEEffecterCount, 495cbad219eSEddie James sbeMaintenanceStatePosition, SBE_RETRY_REQUIRED); 496cbad219eSEddie James 497cbad219eSEddie James if (request.empty()) 498cbad219eSEddie James { 499bae4d07eSChris Cain log<level::ERR>( 500bae4d07eSChris Cain "pldm: SetStateEffecterStates HRESET request empty"); 501cbad219eSEddie James return; 502cbad219eSEddie James } 503cbad219eSEddie James 504bae4d07eSChris Cain // Send request to issue HRESET of SBE (ignore response) 505bae4d07eSChris Cain sendPldm(request, sbeInstanceId, false); 50612d0b828SChris Cain outstandingHResets.insert(sbeInstanceId); 507bae4d07eSChris Cain } 508bae4d07eSChris Cain else 509bae4d07eSChris Cain { 510bae4d07eSChris Cain log<level::ERR>(fmt::format("sendHRESET: HOST is not running (OCC{})", 511bae4d07eSChris Cain sbeInstanceId) 512bae4d07eSChris Cain .c_str()); 513bae4d07eSChris Cain clearData(); 514bae4d07eSChris Cain } 515cbad219eSEddie James } 516cbad219eSEddie James 5178b508bfbSChris Cain bool Interface::getMctpInstanceId() 518cbad219eSEddie James { 5198b508bfbSChris Cain if (!mctpInstance) 5208b508bfbSChris Cain { 5218b508bfbSChris Cain // Request new instance ID 52248330578SChris Cain auto& bus = open_power::occ::utils::getBus(); 52300325238STom Joseph try 52400325238STom Joseph { 52500325238STom Joseph auto method = bus.new_method_call( 52600325238STom Joseph "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm", 52700325238STom Joseph "xyz.openbmc_project.PLDM.Requester", "GetInstanceId"); 52800325238STom Joseph method.append(mctpEid); 52900325238STom Joseph auto reply = bus.call(method); 5308b508bfbSChris Cain uint8_t newInstanceId; 5318b508bfbSChris Cain reply.read(newInstanceId); 5328b508bfbSChris Cain mctpInstance = newInstanceId; 5338b508bfbSChris Cain log<level::INFO>(fmt::format("pldm: got new InstanceId: {}", 5348b508bfbSChris Cain mctpInstance.value()) 5358b508bfbSChris Cain .c_str()); 53600325238STom Joseph } 537af40808fSPatrick Williams catch (const sdbusplus::exception_t& e) 53800325238STom Joseph { 539bd551de3SChris Cain log<level::ERR>( 5408b508bfbSChris Cain fmt::format("pldm: GetInstanceId failed: {}", e.what()) 5418b508bfbSChris Cain .c_str()); 542cbad219eSEddie James return false; 54300325238STom Joseph } 5448b508bfbSChris Cain } 54500325238STom Joseph 546cbad219eSEddie James return true; 547cbad219eSEddie James } 54800325238STom Joseph 549bae4d07eSChris Cain void Interface::sendPldm(const std::vector<uint8_t>& request, 550bae4d07eSChris Cain const uint8_t instance, const bool rspExpected) 55100325238STom Joseph { 5528b508bfbSChris Cain if (!mctpInstance) 5538b508bfbSChris Cain { 5548b508bfbSChris Cain log<level::ERR>("sendPldm: No MCTP Instance ID found!"); 5558b508bfbSChris Cain return; 5568b508bfbSChris Cain } 5578b508bfbSChris Cain 558c9dc4418SChris Cain // Connect to MCTP socket 559bae4d07eSChris Cain pldmFd = pldm_open(); 560bae4d07eSChris Cain auto openErrno = errno; 561bae4d07eSChris Cain if (pldmFd == PLDM_REQUESTER_OPEN_FAIL) 56200325238STom Joseph { 563d1b6826aSChris Cain log<level::ERR>( 564bae4d07eSChris Cain fmt::format( 565bae4d07eSChris Cain "sendPldm: Failed to connect to MCTP socket, errno={}/{}", 566bae4d07eSChris Cain openErrno, strerror(openErrno)) 567d1b6826aSChris Cain .c_str()); 56800325238STom Joseph return; 56900325238STom Joseph } 570cbad219eSEddie James 57100325238STom Joseph // Send the PLDM request message to HBRT 572bae4d07eSChris Cain if (rspExpected) 573d1b6826aSChris Cain { 574bae4d07eSChris Cain // Register callback when response is available 575bae4d07eSChris Cain registerPldmRspCallback(); 576bae4d07eSChris Cain 577bae4d07eSChris Cain // Send PLDM request 578bae4d07eSChris Cain log<level::INFO>( 579bae4d07eSChris Cain fmt::format( 580bae4d07eSChris Cain "sendPldm: calling pldm_send(OCC{}, instance:{}, {} bytes)", 5818b508bfbSChris Cain instance, mctpInstance.value(), request.size()) 582bae4d07eSChris Cain .c_str()); 583bae4d07eSChris Cain pldmResponseReceived = false; 584bae4d07eSChris Cain pldmResponseTimeout = false; 585bae4d07eSChris Cain pldmResponseOcc = instance; 586bae4d07eSChris Cain auto pldmRc = 587bae4d07eSChris Cain pldm_send(mctpEid, pldmFd, request.data(), request.size()); 588bae4d07eSChris Cain auto sendErrno = errno; 589bae4d07eSChris Cain if (pldmRc != PLDM_REQUESTER_SUCCESS) 590bae4d07eSChris Cain { 591bae4d07eSChris Cain log<level::ERR>( 592bae4d07eSChris Cain fmt::format( 593bae4d07eSChris Cain "sendPldm: pldm_send failed with rc={} and errno={}/{}", 594bae4d07eSChris Cain pldmRc, sendErrno, strerror(sendErrno)) 595bae4d07eSChris Cain .c_str()); 596bae4d07eSChris Cain pldmClose(); 597bae4d07eSChris Cain return; 598bae4d07eSChris Cain } 599bae4d07eSChris Cain 600bae4d07eSChris Cain // start timer waiting for the response 601bae4d07eSChris Cain using namespace std::literals::chrono_literals; 602bd551de3SChris Cain pldmRspTimer.restartOnce(8s); 603bae4d07eSChris Cain 604bae4d07eSChris Cain // Wait for response/timeout 605bae4d07eSChris Cain } 606bae4d07eSChris Cain else // not expecting the response 607bae4d07eSChris Cain { 608bae4d07eSChris Cain log<level::INFO>( 609bae4d07eSChris Cain fmt::format( 610bae4d07eSChris Cain "sendPldm: calling pldm_send(mctpID:{}, fd:{}, {} bytes) for OCC{}", 611bae4d07eSChris Cain mctpEid, pldmFd, request.size(), instance) 612bae4d07eSChris Cain .c_str()); 613bae4d07eSChris Cain auto rc = pldm_send(mctpEid, pldmFd, request.data(), request.size()); 614bae4d07eSChris Cain auto sendErrno = errno; 61500325238STom Joseph if (rc) 61600325238STom Joseph { 617d1b6826aSChris Cain log<level::ERR>( 618d1b6826aSChris Cain fmt::format( 619bae4d07eSChris Cain "sendPldm: pldm_send(mctpID:{}, fd:{}, {} bytes) failed with rc={} and errno={}/{}", 620bae4d07eSChris Cain mctpEid, pldmFd, request.size(), rc, sendErrno, 621bae4d07eSChris Cain strerror(sendErrno)) 622d1b6826aSChris Cain .c_str()); 62300325238STom Joseph } 6248b508bfbSChris Cain else 6258b508bfbSChris Cain { 6268b508bfbSChris Cain // Not waiting for response, instance ID should be freed 6278b508bfbSChris Cain mctpInstance = std::nullopt; 6288b508bfbSChris Cain } 629bae4d07eSChris Cain pldmClose(); 630bae4d07eSChris Cain } 631bae4d07eSChris Cain } 63200325238STom Joseph 633bae4d07eSChris Cain // Attaches the FD to event loop and registers the callback handler 634bae4d07eSChris Cain void Interface::registerPldmRspCallback() 635bae4d07eSChris Cain { 636bae4d07eSChris Cain decltype(eventSource.get()) sourcePtr = nullptr; 637bae4d07eSChris Cain auto rc = sd_event_add_io(event.get(), &sourcePtr, pldmFd, EPOLLIN, 638bae4d07eSChris Cain pldmRspCallback, this); 639bae4d07eSChris Cain if (rc < 0) 64000325238STom Joseph { 64100325238STom Joseph log<level::ERR>( 642d1b6826aSChris Cain fmt::format( 643bae4d07eSChris Cain "registerPldmRspCallback: sd_event_add_io: Error({})={} : fd={}", 644bae4d07eSChris Cain rc, strerror(-rc), pldmFd) 645d1b6826aSChris Cain .c_str()); 646d1b6826aSChris Cain } 647d1b6826aSChris Cain else 648d1b6826aSChris Cain { 649bae4d07eSChris Cain // puts sourcePtr in the event source. 650bae4d07eSChris Cain eventSource.reset(sourcePtr); 651bae4d07eSChris Cain } 652bae4d07eSChris Cain } 653bae4d07eSChris Cain 654bae4d07eSChris Cain // Add a timer to the event loop, default 30s. 655bae4d07eSChris Cain void Interface::pldmRspExpired() 656bae4d07eSChris Cain { 657bae4d07eSChris Cain if (!pldmResponseReceived) 658bae4d07eSChris Cain { 659bae4d07eSChris Cain log<level::ERR>( 660bae4d07eSChris Cain fmt::format( 661bae4d07eSChris Cain "pldmRspExpired: timerCallback - timeout waiting for pldm response for OCC{}", 662bae4d07eSChris Cain pldmResponseOcc) 663d1b6826aSChris Cain .c_str()); 664bae4d07eSChris Cain pldmResponseTimeout = true; 665bae4d07eSChris Cain if (pldmFd) 666bae4d07eSChris Cain { 667bae4d07eSChris Cain pldmClose(); 668bae4d07eSChris Cain } 669bae4d07eSChris Cain } 670bae4d07eSChris Cain return; 671bae4d07eSChris Cain }; 672bae4d07eSChris Cain 673bae4d07eSChris Cain void Interface::pldmClose() 674bae4d07eSChris Cain { 675bae4d07eSChris Cain if (pldmRspTimer.isEnabled()) 676bae4d07eSChris Cain { 677bae4d07eSChris Cain // stop PLDM response timer 678bae4d07eSChris Cain pldmRspTimer.setEnabled(false); 679bae4d07eSChris Cain } 680bae4d07eSChris Cain close(pldmFd); 681bae4d07eSChris Cain pldmFd = -1; 682bae4d07eSChris Cain eventSource.reset(); 683bae4d07eSChris Cain } 684bae4d07eSChris Cain 685bae4d07eSChris Cain int Interface::pldmRspCallback(sd_event_source* /*es*/, int fd, 686bae4d07eSChris Cain uint32_t revents, void* userData) 687bae4d07eSChris Cain { 688bae4d07eSChris Cain if (!(revents & EPOLLIN)) 689bae4d07eSChris Cain { 690bae4d07eSChris Cain log<level::INFO>( 691bae4d07eSChris Cain fmt::format("pldmRspCallback - revents={:08X}", revents).c_str()); 692bae4d07eSChris Cain return -1; 693bae4d07eSChris Cain } 694bae4d07eSChris Cain 695bae4d07eSChris Cain auto pldmIface = static_cast<Interface*>(userData); 696bae4d07eSChris Cain 6978b508bfbSChris Cain if (!pldmIface->mctpInstance) 6988b508bfbSChris Cain { 6998b508bfbSChris Cain log<level::ERR>( 7008b508bfbSChris Cain "pldmRspCallback: No outstanding MCTP Instance ID found"); 7018b508bfbSChris Cain return -1; 7028b508bfbSChris Cain } 7038b508bfbSChris Cain 704bae4d07eSChris Cain uint8_t* responseMsg = nullptr; 705bae4d07eSChris Cain size_t responseMsgSize{}; 706bae4d07eSChris Cain 707bae4d07eSChris Cain log<level::INFO>( 708bae4d07eSChris Cain fmt::format("pldmRspCallback: calling pldm_recv() instance:{}", 7098b508bfbSChris Cain pldmIface->mctpInstance.value()) 710bae4d07eSChris Cain .c_str()); 7118b508bfbSChris Cain auto rc = pldm_recv(mctpEid, fd, pldmIface->mctpInstance.value(), 7128b508bfbSChris Cain &responseMsg, &responseMsgSize); 713bae4d07eSChris Cain int lastErrno = errno; 714d1b6826aSChris Cain if (rc) 715d1b6826aSChris Cain { 716d1b6826aSChris Cain log<level::ERR>( 717d1b6826aSChris Cain fmt::format( 718bae4d07eSChris Cain "pldmRspCallback: pldm_recv failed with rc={}, errno={}/{}", rc, 719bae4d07eSChris Cain lastErrno, strerror(lastErrno)) 720bae4d07eSChris Cain .c_str()); 721bae4d07eSChris Cain return -1; 722bae4d07eSChris Cain } 7238b508bfbSChris Cain 7248b508bfbSChris Cain // We got the response for the PLDM request msg that was sent 725bae4d07eSChris Cain log<level::INFO>( 726bae4d07eSChris Cain fmt::format("pldmRspCallback: pldm_recv() rsp was {} bytes", 727bae4d07eSChris Cain responseMsgSize) 728bae4d07eSChris Cain .c_str()); 729bae4d07eSChris Cain 730bae4d07eSChris Cain if (pldmIface->pldmRspTimer.isEnabled()) 731bae4d07eSChris Cain { 732bae4d07eSChris Cain // stop PLDM response timer 733bae4d07eSChris Cain pldmIface->pldmRspTimer.setEnabled(false); 734bae4d07eSChris Cain } 735bae4d07eSChris Cain 7368b508bfbSChris Cain // instance ID should be freed 7378b508bfbSChris Cain pldmIface->mctpInstance = std::nullopt; 7388b508bfbSChris Cain 739bae4d07eSChris Cain // Set pointer to autodelete 740bae4d07eSChris Cain std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg, 741bae4d07eSChris Cain std::free}; 742bae4d07eSChris Cain 743bae4d07eSChris Cain auto response = reinterpret_cast<pldm_msg*>(responseMsgPtr.get()); 744bae4d07eSChris Cain if (response->payload[0] != PLDM_SUCCESS) 745bae4d07eSChris Cain { 746bae4d07eSChris Cain log<level::ERR>( 747bae4d07eSChris Cain fmt::format("pldmRspCallback: payload[0] was not success: {}", 748bae4d07eSChris Cain response->payload[0]) 749bae4d07eSChris Cain .c_str()); 750bae4d07eSChris Cain pldmIface->pldmClose(); 751bae4d07eSChris Cain return -1; 752bae4d07eSChris Cain } 753bae4d07eSChris Cain 754bae4d07eSChris Cain // Decode the response 755bae4d07eSChris Cain uint8_t compCode = 0, sensorCount = 1; 756bae4d07eSChris Cain get_sensor_state_field field[6]; 757bae4d07eSChris Cain responseMsgSize -= sizeof(pldm_msg_hdr); 758bae4d07eSChris Cain auto msgRc = decode_get_state_sensor_readings_resp( 759bae4d07eSChris Cain response, responseMsgSize, &compCode, &sensorCount, field); 760bae4d07eSChris Cain if ((msgRc != PLDM_SUCCESS) || (compCode != PLDM_SUCCESS)) 761bae4d07eSChris Cain { 762bae4d07eSChris Cain log<level::ERR>( 763bae4d07eSChris Cain fmt::format( 764bae4d07eSChris Cain "pldmRspCallback: decode_get_state_sensor_readings failed with rc={} and compCode={}", 765bae4d07eSChris Cain msgRc, compCode) 766bae4d07eSChris Cain .c_str()); 767bae4d07eSChris Cain pldmIface->pldmClose(); 768bae4d07eSChris Cain return -1; 769bae4d07eSChris Cain } 770bae4d07eSChris Cain 771bae4d07eSChris Cain pldmIface->pldmClose(); 772bae4d07eSChris Cain 773bae4d07eSChris Cain const uint8_t instance = pldmIface->pldmResponseOcc; 774bae4d07eSChris Cain const uint8_t occSensorState = field[0].present_state; 775bae4d07eSChris Cain pldmIface->pldmResponseReceived = true; 776bae4d07eSChris Cain 777bae4d07eSChris Cain if (occSensorState == PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_IN_SERVICE) 778bae4d07eSChris Cain { 779bae4d07eSChris Cain log<level::INFO>( 780bae4d07eSChris Cain fmt::format("pldmRspCallback: OCC{} is RUNNING", instance).c_str()); 781bae4d07eSChris Cain pldmIface->callBack(instance, true); 782bae4d07eSChris Cain } 783733b201fSChris Cain else if (occSensorState == 784733b201fSChris Cain PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_DORMANT) 785733b201fSChris Cain { 786733b201fSChris Cain log<level::INFO>( 787733b201fSChris Cain fmt::format( 788733b201fSChris Cain "pldmRspCallback: OCC{} has now STOPPED and system is in SAFE MODE", 789733b201fSChris Cain instance) 790733b201fSChris Cain .c_str()); 79131a2f13aSSheldon Bailey 79231a2f13aSSheldon Bailey // Setting safe mode true 79331a2f13aSSheldon Bailey pldmIface->safeModeCallBack(true); 79431a2f13aSSheldon Bailey 795733b201fSChris Cain pldmIface->callBack(instance, false); 796733b201fSChris Cain } 797bae4d07eSChris Cain else 798bae4d07eSChris Cain { 799bae4d07eSChris Cain log<level::INFO>( 8008b508bfbSChris Cain fmt::format( 8018b508bfbSChris Cain "pldmRspCallback: OCC{} is not running (sensor state:{})", 802bae4d07eSChris Cain instance, occSensorState) 803bae4d07eSChris Cain .c_str()); 804c9dc4418SChris Cain if (occSensorState != PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS_STOPPED) 805c9dc4418SChris Cain { 806c9dc4418SChris Cain const size_t rspLength = responseMsgSize + sizeof(pldm_msg_hdr); 807c9dc4418SChris Cain std::vector<std::uint8_t> pldmResponse(rspLength); 808c9dc4418SChris Cain memcpy(&pldmResponse[0], reinterpret_cast<std::uint8_t*>(response), 809c9dc4418SChris Cain rspLength); 810c9dc4418SChris Cain log<level::ERR>( 811c9dc4418SChris Cain fmt::format( 812c9dc4418SChris Cain "pldmRspCallback: Bad State - PLDM response ({} bytes) for OCC{}:", 813c9dc4418SChris Cain rspLength, instance) 814c9dc4418SChris Cain .c_str()); 815c9dc4418SChris Cain dump_hex(pldmResponse); 816c9dc4418SChris Cain } 817bae4d07eSChris Cain pldmIface->callBack(instance, false); 818bae4d07eSChris Cain } 819bae4d07eSChris Cain 820bae4d07eSChris Cain return 0; 821bae4d07eSChris Cain }; 822bae4d07eSChris Cain 823bae4d07eSChris Cain std::vector<uint8_t> Interface::encodeGetStateSensorRequest(uint8_t instance, 824bae4d07eSChris Cain uint16_t sensorId) 825bae4d07eSChris Cain { 8268b508bfbSChris Cain if (!getMctpInstanceId()) 8278b508bfbSChris Cain { 8288b508bfbSChris Cain log<level::ERR>( 8298b508bfbSChris Cain "encodeGetStateSensorRequest: failed to getMctpInstanceId"); 8308b508bfbSChris Cain return std::vector<uint8_t>(); 8318b508bfbSChris Cain } 8328b508bfbSChris Cain 833bae4d07eSChris Cain bitfield8_t sRearm = {0}; 834bae4d07eSChris Cain const size_t msgSize = 835bae4d07eSChris Cain sizeof(pldm_msg_hdr) + PLDM_GET_STATE_SENSOR_READINGS_REQ_BYTES; 836bae4d07eSChris Cain std::vector<uint8_t> request(msgSize); 8378b508bfbSChris Cain 838bae4d07eSChris Cain auto msg = reinterpret_cast<pldm_msg*>(request.data()); 8398b508bfbSChris Cain auto msgRc = encode_get_state_sensor_readings_req(mctpInstance.value(), 8408b508bfbSChris Cain sensorId, sRearm, 0, msg); 841bae4d07eSChris Cain if (msgRc != PLDM_SUCCESS) 842bae4d07eSChris Cain { 843bae4d07eSChris Cain log<level::ERR>( 844bae4d07eSChris Cain fmt::format( 845bae4d07eSChris Cain "encodeGetStateSensorRequest: Failed to encode sensorId:0x{:08X} for OCC{} (rc={})", 846bae4d07eSChris Cain sensorId, instance, msgRc) 847d1b6826aSChris Cain .c_str()); 848d1b6826aSChris Cain } 849bae4d07eSChris Cain return request; 850bae4d07eSChris Cain } 851bae4d07eSChris Cain 852bae4d07eSChris Cain // Initiate query of the specified OCC Active Sensor 853bae4d07eSChris Cain void Interface::checkActiveSensor(uint8_t instance) 854bae4d07eSChris Cain { 855bae4d07eSChris Cain static bool tracedOnce = false; 856bae4d07eSChris Cain if (pldmFd > 0) 857bae4d07eSChris Cain { 858bae4d07eSChris Cain if (!tracedOnce) 859bae4d07eSChris Cain { 860bae4d07eSChris Cain log<level::ERR>( 861bae4d07eSChris Cain fmt::format( 862bae4d07eSChris Cain "checkActiveSensor: already waiting on OCC{} (fd={})", 863bae4d07eSChris Cain pldmResponseOcc, pldmFd) 864bae4d07eSChris Cain .c_str()); 865bae4d07eSChris Cain tracedOnce = true; 866bae4d07eSChris Cain } 867bae4d07eSChris Cain return; 868bae4d07eSChris Cain } 869bae4d07eSChris Cain tracedOnce = false; 870bae4d07eSChris Cain 871bae4d07eSChris Cain if (!isOCCSensorCacheValid()) 872bae4d07eSChris Cain { 873bae4d07eSChris Cain fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 874bae4d07eSChris Cain sensorToOCCInstance, OCCSensorOffset); 875bae4d07eSChris Cain } 876bae4d07eSChris Cain 877bae4d07eSChris Cain // look up sensor id (key) based on instance 878bae4d07eSChris Cain auto entry = std::find_if( 879bae4d07eSChris Cain sensorToOCCInstance.begin(), sensorToOCCInstance.end(), 880bae4d07eSChris Cain [instance](const auto& entry) { return instance == entry.second; }); 881bae4d07eSChris Cain if (entry != sensorToOCCInstance.end()) 882bae4d07eSChris Cain { 883bae4d07eSChris Cain // Query the OCC Active Sensor state for this instance 884bae4d07eSChris Cain // SensorID sID = entry->first; 885bae4d07eSChris Cain log<level::INFO>( 886bae4d07eSChris Cain fmt::format("checkActiveSensor: OCC{} / sensorID: 0x{:04X}", 887bae4d07eSChris Cain instance, entry->first) 888bae4d07eSChris Cain .c_str()); 889bae4d07eSChris Cain 890bae4d07eSChris Cain // Encode GetStateSensorReadings PLDM message 891bae4d07eSChris Cain auto request = encodeGetStateSensorRequest(instance, entry->first); 892bae4d07eSChris Cain if (request.empty()) 893bae4d07eSChris Cain { 894bae4d07eSChris Cain return; 895bae4d07eSChris Cain } 896bae4d07eSChris Cain 897bae4d07eSChris Cain // Send request to PLDM and setup callback for response 898bae4d07eSChris Cain sendPldm(request, instance, true); 899bae4d07eSChris Cain } 900bae4d07eSChris Cain else 901bae4d07eSChris Cain { 902bae4d07eSChris Cain log<level::ERR>( 903bae4d07eSChris Cain fmt::format( 904bae4d07eSChris Cain "checkActiveSensor: Unable to find PLDM sensor for OCC{}", 905bae4d07eSChris Cain instance) 906bae4d07eSChris Cain .c_str()); 9078cf7496bSChris Cain log<level::INFO>( 9088cf7496bSChris Cain "checkActiveSensor: fetching STATE_SET_OPERATIONAL_RUNNING_STATUS"); 9098cf7496bSChris Cain fetchSensorInfo(PLDM_STATE_SET_OPERATIONAL_RUNNING_STATUS, 9108cf7496bSChris Cain sensorToOCCInstance, OCCSensorOffset); 91100325238STom Joseph } 91200325238STom Joseph } 91300325238STom Joseph 914815f9f55STom Joseph } // namespace pldm 915