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 30 PLDMInstanceManager::PLDMInstanceManager() 31 { 32 initPLDMInstanceIdDb(); 33 } 34 35 PLDMInstanceManager::~PLDMInstanceManager() 36 { 37 destroyPLDMInstanceIdDb(); 38 } 39 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 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 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 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 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 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 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