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 #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, pldm::InstanceIdDb* instanceIdDb, 24 const std::vector<uint16_t>& handles, 25 pldm::requester::Handler<pldm::requester::Request>* handler) 26 { 27 using BootProgress = 28 sdbusplus::client::xyz::openbmc_project::state::boot::Progress<>; 29 30 constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0"; 31 constexpr auto hostStateProperty = "BootProgress"; 32 33 try 34 { 35 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( 36 hostStatePath, hostStateProperty, BootProgress::interface); 37 38 using Stages = BootProgress::ProgressStages; 39 auto currHostState = sdbusplus::message::convert_from_string<Stages>( 40 std::get<std::string>(propVal)) 41 .value(); 42 43 if (currHostState != Stages::SystemInitComplete && 44 currHostState != Stages::OSRunning && 45 currHostState != Stages::SystemSetup) 46 { 47 return PLDM_SUCCESS; 48 } 49 } 50 catch ( 51 const sdbusplus::xyz::openbmc_project::Common::Error::ResourceNotFound&) 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 = instanceIdDb->next(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 instanceIdDb->free(eid, instanceId); 85 return rc; 86 } 87 88 auto platformEventMessageResponseHandler = 89 [](mctp_eid_t /*eid*/, const pldm_msg* response, size_t respMsgLen) { 90 if (response == nullptr || !respMsgLen) 91 { 92 error("Failed to receive response for platform event message"); 93 return; 94 } 95 uint8_t completionCode{}; 96 uint8_t status{}; 97 auto rc = decode_platform_event_message_resp(response, respMsgLen, 98 &completionCode, &status); 99 if (rc || completionCode) 100 { 101 error( 102 "Failed to decode BIOS Attribute update platform_event_message_resp: rc = {RC}, cc= {CC}", 103 "RC", rc, "CC", static_cast<unsigned>(completionCode)); 104 } 105 }; 106 rc = handler->registerRequest( 107 eid, instanceId, PLDM_PLATFORM, PLDM_PLATFORM_EVENT_MESSAGE, 108 std::move(requestMsg), std::move(platformEventMessageResponseHandler)); 109 if (rc) 110 { 111 error( 112 "Failed to send BIOS Attribute update the platform event message"); 113 } 114 115 return rc; 116 } 117 118 } // namespace platform 119 120 } // namespace responder 121 122 } // namespace pldm 123