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