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