1 #include "dbus_to_file_handler.hpp" 2 3 #include "libpldm/requester/pldm.h" 4 #include "oem/ibm/libpldm/file_io.h" 5 6 #include "common/utils.hpp" 7 8 namespace pldm 9 { 10 namespace requester 11 { 12 namespace oem_ibm 13 { 14 15 using namespace pldm::utils; 16 using namespace sdbusplus::bus::match::rules; 17 18 static constexpr auto resDumpObjPath = 19 "/xyz/openbmc_project/dump/resource/entry"; 20 static constexpr auto resDumpEntry = "com.ibm.Dump.Entry.Resource"; 21 static constexpr auto resDumpProgressIntf = 22 "xyz.openbmc_project.Common.Progress"; 23 static constexpr auto resDumpStatus = 24 "xyz.openbmc_project.Common.Progress.OperationStatus.Failed"; 25 26 DbusToFileHandler::DbusToFileHandler( 27 int mctp_fd, uint8_t mctp_eid, dbus_api::Requester* requester, 28 sdbusplus::message::object_path resDumpCurrentObjPath) : 29 mctp_fd(mctp_fd), 30 mctp_eid(mctp_eid), requester(requester), 31 resDumpCurrentObjPath(resDumpCurrentObjPath) 32 {} 33 34 void DbusToFileHandler::sendNewFileAvailableCmd(uint64_t fileSize) 35 { 36 if (requester == NULL) 37 { 38 std::cerr << "Failed to send resource dump parameters as requester is " 39 "not set"; 40 pldm::utils::reportError( 41 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 42 return; 43 } 44 auto instanceId = requester->getInstanceId(mctp_eid); 45 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 46 PLDM_NEW_FILE_REQ_BYTES + fileSize); 47 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 48 // Need to revisit this logic at the time of multiple resource dump support 49 uint32_t fileHandle = 1; 50 51 auto rc = 52 encode_new_file_req(instanceId, PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS, 53 fileHandle, fileSize, request); 54 if (rc != PLDM_SUCCESS) 55 { 56 requester->markFree(mctp_eid, instanceId); 57 std::cerr << "Failed to encode_new_file_req, rc = " << rc << std::endl; 58 return; 59 } 60 61 uint8_t* responseMsg = nullptr; 62 size_t responseMsgSize{}; 63 64 auto requesterRc = 65 pldm_send_recv(mctp_eid, mctp_fd, requestMsg.data(), requestMsg.size(), 66 &responseMsg, &responseMsgSize); 67 68 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg, 69 std::free}; 70 71 requester->markFree(mctp_eid, instanceId); 72 bool isDecodeNewFileRespFailed = false; 73 if (requesterRc != PLDM_REQUESTER_SUCCESS) 74 { 75 std::cerr << "Failed to send resource dump parameters, rc = " 76 << requesterRc << std::endl; 77 } 78 else 79 { 80 uint8_t completionCode{}; 81 auto responsePtr = 82 reinterpret_cast<struct pldm_msg*>(responseMsgPtr.get()); 83 84 rc = decode_new_file_resp(responsePtr, PLDM_NEW_FILE_RESP_BYTES, 85 &completionCode); 86 87 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 88 { 89 std::cerr << "Failed to decode_new_file_resp: " 90 << "rc=" << rc 91 << ", cc=" << static_cast<unsigned>(completionCode) 92 << std::endl; 93 isDecodeNewFileRespFailed = true; 94 } 95 } 96 97 if ((requesterRc != PLDM_REQUESTER_SUCCESS) || (isDecodeNewFileRespFailed)) 98 { 99 pldm::utils::reportError( 100 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 101 102 PropertyValue value{resDumpStatus}; 103 DBusMapping dbusMapping{resDumpCurrentObjPath, resDumpProgressIntf, 104 "Status", "string"}; 105 try 106 { 107 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 108 } 109 catch (const std::exception& e) 110 { 111 std::cerr << "failed to set resource dump operation status, " 112 "ERROR=" 113 << e.what() << "\n"; 114 } 115 } 116 } 117 118 void DbusToFileHandler::processNewResourceDump( 119 const std::string& vspString, const std::string& resDumpReqPass) 120 { 121 // This needs special handling in later point of time. Resource dump without 122 // the vsp string is supposed to be a non-disruptive system dump. 123 if (vspString.empty()) 124 { 125 std::cerr << "Empty vsp string" 126 << "\n"; 127 PropertyValue value{resDumpStatus}; 128 DBusMapping dbusMapping{resDumpCurrentObjPath, resDumpProgressIntf, 129 "Status", "string"}; 130 try 131 { 132 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 133 } 134 catch (const std::exception& e) 135 { 136 std::cerr << "failed to set resource dump operation status, " 137 "ERROR=" 138 << e.what() << "\n"; 139 } 140 return; 141 } 142 143 namespace fs = std::filesystem; 144 const fs::path resDumpDirPath = "/var/lib/pldm/resourcedump"; 145 146 if (!fs::exists(resDumpDirPath)) 147 { 148 fs::create_directories(resDumpDirPath); 149 } 150 151 // Need to reconsider this logic to set the value as "1" when we have the 152 // support to handle multiple resource dumps 153 fs::path resDumpFilePath = resDumpDirPath / "1"; 154 155 std::ofstream fileHandle; 156 fileHandle.open(resDumpFilePath, std::ios::out | std::ofstream::binary); 157 158 if (!fileHandle) 159 { 160 std::cerr << "resource dump file open error: " << resDumpFilePath 161 << "\n"; 162 PropertyValue value{resDumpStatus}; 163 DBusMapping dbusMapping{resDumpCurrentObjPath, resDumpProgressIntf, 164 "Status", "string"}; 165 try 166 { 167 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 168 } 169 catch (const std::exception& e) 170 { 171 std::cerr << "failed to set resource dump operation status, " 172 "ERROR=" 173 << e.what() << "\n"; 174 } 175 return; 176 } 177 178 // Fill up the file with resource dump parameters and respective sizes 179 auto fileFunc = [&fileHandle](auto& paramBuf) { 180 uint32_t paramSize = paramBuf.size(); 181 fileHandle.write((char*)¶mSize, sizeof(paramSize)); 182 fileHandle << paramBuf; 183 }; 184 fileFunc(vspString); 185 fileFunc(resDumpReqPass); 186 187 fileHandle.close(); 188 size_t fileSize = fs::file_size(resDumpFilePath); 189 190 sendNewFileAvailableCmd(fileSize); 191 } 192 193 } // namespace oem_ibm 194 } // namespace requester 195 } // namespace pldm 196