1 #include "platform_oem_ibm.hpp" 2 3 #include "common/utils.hpp" 4 #include "libpldmresponder/pdr.hpp" 5 6 #include <libpldm/platform_oem_ibm.h> 7 #include <libpldm/pldm.h> 8 9 #include <phosphor-logging/lg2.hpp> 10 #include <xyz/openbmc_project/Common/error.hpp> 11 12 #include <iostream> 13 14 PHOSPHOR_LOG2_USING; 15 16 namespace pldm 17 { 18 namespace responder 19 { 20 namespace platform 21 { 22 int sendBiosAttributeUpdateEvent( 23 uint8_t eid, dbus_api::Requester* requester, 24 const std::vector<uint16_t>& handles, 25 pldm::requester::Handler<pldm::requester::Request>* handler) 26 { 27 constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0"; 28 constexpr auto hostStateInterface = 29 "xyz.openbmc_project.State.Boot.Progress"; 30 constexpr auto hostStateProperty = "BootProgress"; 31 32 try 33 { 34 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( 35 hostStatePath, hostStateProperty, hostStateInterface); 36 const auto& currHostState = std::get<std::string>(propVal); 37 if ((currHostState != "xyz.openbmc_project.State.Boot.Progress." 38 "ProgressStages.SystemInitComplete") && 39 (currHostState != "xyz.openbmc_project.State.Boot.Progress." 40 "ProgressStages.OSRunning") && 41 (currHostState != "xyz.openbmc_project.State.Boot.Progress." 42 "ProgressStages.OSStart") && 43 (currHostState != "xyz.openbmc_project.State.Boot.Progress." 44 "ProgressStages.SystemSetup")) 45 { 46 return PLDM_SUCCESS; 47 } 48 } 49 catch ( 50 const sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound& 51 e) 52 { 53 /* Exception is expected to happen in the case when state manager is 54 * started after pldm, this is expected to happen in reboot case 55 * where host is considered to be up. As host is up pldm is expected 56 * to send attribute update event to host so this is not an error 57 * case */ 58 } 59 catch (const sdbusplus::exception_t& e) 60 { 61 error( 62 "Error in getting current host state, {EXCEP_NAME} Continue sending the bios attribute update event ...", 63 "EXCEP_NAME", e.name()); 64 } 65 66 auto instanceId = requester->getInstanceId(eid); 67 68 std::vector<uint8_t> requestMsg( 69 sizeof(pldm_msg_hdr) + sizeof(pldm_bios_attribute_update_event_req) - 70 1 + (handles.size() * sizeof(uint16_t)), 71 0); 72 73 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 74 75 auto rc = encode_bios_attribute_update_event_req( 76 instanceId, PLDM_PLATFORM_EVENT_MESSAGE_FORMAT_VERSION, TERMINUS_ID, 77 handles.size(), reinterpret_cast<const uint8_t*>(handles.data()), 78 requestMsg.size() - sizeof(pldm_msg_hdr), request); 79 if (rc != PLDM_SUCCESS) 80 { 81 error( 82 "BIOS Attribute update event message encode failure. PLDM error code = {RC}", 83 "RC", lg2::hex, rc); 84 requester->markFree(eid, instanceId); 85 return rc; 86 } 87 88 auto platformEventMessageResponseHandler = [](mctp_eid_t /*eid*/, 89 const pldm_msg* response, 90 size_t respMsgLen) { 91 if (response == nullptr || !respMsgLen) 92 { 93 error("Failed to receive response for platform event message"); 94 return; 95 } 96 uint8_t completionCode{}; 97 uint8_t status{}; 98 auto rc = decode_platform_event_message_resp(response, respMsgLen, 99 &completionCode, &status); 100 if (rc || completionCode) 101 { 102 error( 103 "Failed to decode BIOS Attribute update platform_event_message_resp: rc = {RC}, cc= {CC}", 104 "RC", rc, "CC", static_cast<unsigned>(completionCode)); 105 } 106 }; 107 rc = handler->registerRequest( 108 eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE, 109 std::move(requestMsg), std::move(platformEventMessageResponseHandler)); 110 if (rc) 111 { 112 error( 113 "Failed to send BIOS Attribute update the platform event message"); 114 } 115 116 return rc; 117 } 118 119 } // namespace platform 120 121 } // namespace responder 122 123 } // namespace pldm 124