xref: /openbmc/phosphor-debug-collector/host-transport-extensions/pldm/common/pldm_utils.cpp (revision 03414ffa629d290c16d9561d780d140fa1f0ccfa)
1 // SPDX-License-Identifier: Apache-2.0
2 
3 #include "pldm_utils.hpp"
4 
5 #include "dump_utils.hpp"
6 #include "xyz/openbmc_project/Common/error.hpp"
7 
8 #include <libpldm/transport.h>
9 #include <libpldm/transport/mctp-demux.h>
10 #include <poll.h>
11 
12 #include <phosphor-logging/elog-errors.hpp>
13 #include <phosphor-logging/lg2.hpp>
14 
15 namespace phosphor
16 {
17 namespace dump
18 {
19 namespace pldm
20 {
21 
22 using namespace phosphor::logging;
23 using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
24 using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
25 
26 pldm_instance_db* pldmInstanceIdDb = nullptr;
27 pldm_transport* pldmTransport = nullptr;
28 pldm_transport_mctp_demux* mctpDemux = nullptr;
29 
PLDMInstanceManager()30 PLDMInstanceManager::PLDMInstanceManager()
31 {
32     initPLDMInstanceIdDb();
33 }
34 
~PLDMInstanceManager()35 PLDMInstanceManager::~PLDMInstanceManager()
36 {
37     destroyPLDMInstanceIdDb();
38 }
39 
initPLDMInstanceIdDb()40 void PLDMInstanceManager::initPLDMInstanceIdDb()
41 {
42     auto rc = pldm_instance_db_init_default(&pldmInstanceIdDb);
43     if (rc)
44     {
45         lg2::error("Error calling pldm_instance_db_init_default, rc = {RC}",
46                    "RC", rc);
47         elog<NotAllowed>(Reason(
48             "Required host dump action via pldm is not allowed due "
49             "to pldm_open failed"));
50     }
51 }
52 
destroyPLDMInstanceIdDb()53 void PLDMInstanceManager::destroyPLDMInstanceIdDb()
54 {
55     auto rc = pldm_instance_db_destroy(pldmInstanceIdDb);
56     if (rc)
57     {
58         lg2::error("pldm_instance_db_destroy failed rc = {RC}", "RC", rc);
59     }
60 }
61 
getPLDMInstanceID(uint8_t tid)62 pldm_instance_id_t getPLDMInstanceID(uint8_t tid)
63 {
64     pldm_instance_id_t instanceID = 0;
65 
66     auto rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &instanceID);
67     if (rc == -EAGAIN)
68     {
69         std::this_thread::sleep_for(std::chrono::milliseconds(100));
70         rc = pldm_instance_id_alloc(pldmInstanceIdDb, tid, &instanceID);
71     }
72 
73     if (rc)
74     {
75         lg2::error("Failed to get instance id, rc = {RC}", "RC", rc);
76         elog<NotAllowed>(Reason(
77             "Failure in communicating with libpldm service, "
78             "service may not be running"));
79     }
80     lg2::info("Got instanceId: {INSTANCE_ID} from PLDM eid: {EID}",
81               "INSTANCE_ID", instanceID, "EID", tid);
82 
83     return instanceID;
84 }
85 
freePLDMInstanceID(pldm_instance_id_t instanceID,uint8_t tid)86 void freePLDMInstanceID(pldm_instance_id_t instanceID, uint8_t tid)
87 {
88     auto rc = pldm_instance_id_free(pldmInstanceIdDb, tid, instanceID);
89     if (rc)
90     {
91         lg2::error(
92             "pldm_instance_id_free failed to free id = {ID} of tid = {TID} rc = {RC}",
93             "ID", instanceID, "TID", tid, "RC", rc);
94     }
95 }
96 
openPLDM(mctp_eid_t eid)97 int openPLDM(mctp_eid_t eid)
98 {
99     auto fd = -1;
100     if (pldmTransport)
101     {
102         lg2::error("open: pldmTransport already setup!");
103         elog<NotAllowed>(Reason(
104             "Required host dump action via pldm is not allowed due "
105             "to openPLDM failed"));
106         return fd;
107     }
108 
109     fd = openMctpDemuxTransport(eid);
110     if (fd < 0)
111     {
112         auto e = errno;
113         lg2::error("openPLDM failed, errno: {ERRNO}, FD: FD", "ERRNO", e, "FD",
114                    fd);
115         elog<NotAllowed>(Reason(
116             "Required host dump action via pldm is not allowed due "
117             "to openPLDM failed"));
118     }
119     return fd;
120 }
121 
openMctpDemuxTransport(mctp_eid_t eid)122 int openMctpDemuxTransport(mctp_eid_t eid)
123 {
124     int rc = pldm_transport_mctp_demux_init(&mctpDemux);
125     if (rc)
126     {
127         lg2::error(
128             "openMctpDemuxTransport: Failed to init MCTP demux transport. rc = {RC}",
129             "RC", rc);
130         return rc;
131     }
132 
133     rc = pldm_transport_mctp_demux_map_tid(mctpDemux, eid, eid);
134     if (rc)
135     {
136         lg2::error(
137             "openMctpDemuxTransport: Failed to setup tid to eid mapping. rc = {RC}",
138             "RC", rc);
139         pldmClose();
140         return rc;
141     }
142     pldmTransport = pldm_transport_mctp_demux_core(mctpDemux);
143 
144     struct pollfd pollfd;
145     rc = pldm_transport_mctp_demux_init_pollfd(pldmTransport, &pollfd);
146     if (rc)
147     {
148         lg2::error("openMctpDemuxTransport: Failed to get pollfd. rc = {RC}",
149                    "RC", rc);
150         pldmClose();
151         return rc;
152     }
153     return pollfd.fd;
154 }
155 
pldmClose()156 void pldmClose()
157 {
158     pldm_transport_mctp_demux_destroy(mctpDemux);
159     mctpDemux = nullptr;
160     pldmTransport = nullptr;
161 }
162 
163 } // namespace pldm
164 } // namespace dump
165 } // namespace phosphor
166