1 #include "platform_oem_ibm.hpp" 2 3 #include "libpldm/platform_oem_ibm.h" 4 #include "libpldm/requester/pldm.h" 5 6 #include "common/utils.hpp" 7 #include "libpldmresponder/pdr.hpp" 8 9 #include <iostream> 10 11 namespace pldm 12 { 13 namespace responder 14 { 15 namespace platform 16 { 17 18 int sendBiosAttributeUpdateEvent(int fd, uint8_t eid, 19 dbus_api::Requester* requester, 20 const std::vector<uint16_t>& handles) 21 { 22 constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0"; 23 constexpr auto hostStateInterface = 24 "xyz.openbmc_project.State.Boot.Progress"; 25 constexpr auto hostStateProperty = "BootProgress"; 26 27 try 28 { 29 auto propVal = pldm::utils::DBusHandler().getDbusPropertyVariant( 30 hostStatePath, hostStateProperty, hostStateInterface); 31 const auto& currHostState = std::get<std::string>(propVal); 32 if ((currHostState != "xyz.openbmc_project.State.Boot.Progress." 33 "ProgressStages.SystemInitComplete") && 34 (currHostState != "xyz.openbmc_project.State.Boot.Progress." 35 "ProgressStages.OSRunning") && 36 (currHostState != "xyz.openbmc_project.State.Boot.Progress." 37 "ProgressStages.OSStart")) 38 { 39 return PLDM_SUCCESS; 40 } 41 } 42 catch (const sdbusplus::exception::SdBusError& e) 43 { 44 std::cerr << "Error in getting current host state, continue ... \n"; 45 } 46 47 auto instanceId = requester->getInstanceId(eid); 48 49 std::vector<uint8_t> requestMsg( 50 sizeof(pldm_msg_hdr) + sizeof(pldm_bios_attribute_update_event_req) - 51 1 + (handles.size() * sizeof(uint16_t)), 52 0); 53 54 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 55 56 auto rc = encode_bios_attribute_update_event_req( 57 instanceId, PLDM_PLATFORM_EVENT_MESSAGE_FORMAT_VERSION, 58 pldm::responder::pdr::BmcMctpEid, handles.size(), 59 reinterpret_cast<const uint8_t*>(handles.data()), 60 requestMsg.size() - sizeof(pldm_msg_hdr), request); 61 if (rc != PLDM_SUCCESS) 62 { 63 std::cerr << "Message encode failure 1. PLDM error code = " << std::hex 64 << std::showbase << rc << "\n"; 65 requester->markFree(eid, instanceId); 66 return rc; 67 } 68 69 if (requestMsg.size()) 70 { 71 std::ostringstream tempStream; 72 for (int byte : requestMsg) 73 { 74 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte 75 << " "; 76 } 77 std::cout << tempStream.str() << std::endl; 78 } 79 80 uint8_t* responseMsg = nullptr; 81 size_t responseMsgSize{}; 82 83 rc = pldm_send_recv(eid, fd, requestMsg.data(), requestMsg.size(), 84 &responseMsg, &responseMsgSize); 85 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg, 86 std::free}; 87 requester->markFree(eid, instanceId); 88 89 if (rc != PLDM_REQUESTER_SUCCESS) 90 { 91 std::cerr << "Failed to send BIOS attribute update event. RC = " << rc 92 << ", errno = " << errno << "\n"; 93 pldm::utils::reportError( 94 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 95 return rc; 96 } 97 98 auto responsePtr = reinterpret_cast<struct pldm_msg*>(responseMsgPtr.get()); 99 uint8_t completionCode{}; 100 uint8_t status{}; 101 rc = decode_platform_event_message_resp( 102 responsePtr, responseMsgSize - sizeof(pldm_msg_hdr), &completionCode, 103 &status); 104 if (rc != PLDM_SUCCESS) 105 { 106 std::cerr << "Failed to decode PlatformEventMessage response, rc = " 107 << rc << "\n"; 108 return rc; 109 } 110 111 if (completionCode != PLDM_SUCCESS) 112 { 113 std::cerr << "Failed to send the BIOS attribute update event, rc = " 114 << (uint32_t)completionCode << "\n"; 115 pldm::utils::reportError( 116 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 117 } 118 119 return completionCode; 120 } 121 122 } // namespace platform 123 124 } // namespace responder 125 126 } // namespace pldm