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