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 void DbusToFileHandler::newCsrFileAvailable(const std::string& csr, 194 const std::string fileHandle) 195 { 196 namespace fs = std::filesystem; 197 std::string dirPath = "/var/lib/ibm/bmcweb"; 198 const fs::path certDirPath = dirPath; 199 200 if (!fs::exists(certDirPath)) 201 { 202 fs::create_directories(certDirPath); 203 fs::permissions(certDirPath, 204 fs::perms::others_read | fs::perms::owner_write); 205 } 206 207 fs::path certFilePath = certDirPath / ("CSR_" + fileHandle); 208 std::ofstream certFile; 209 210 certFile.open(certFilePath, std::ios::out | std::ofstream::binary); 211 212 if (!certFile) 213 { 214 std::cerr << "cert file open error: " << certFilePath << "\n"; 215 return; 216 } 217 218 // Add csr to file 219 certFile << csr << std::endl; 220 221 certFile.close(); 222 uint32_t fileSize = fs::file_size(certFilePath); 223 224 newFileAvailableSendToHost(fileSize, (uint32_t)stoi(fileHandle), 225 PLDM_FILE_TYPE_CERT_SIGNING_REQUEST); 226 } 227 228 void DbusToFileHandler::newFileAvailableSendToHost(const uint32_t fileSize, 229 const uint32_t fileHandle, 230 const uint16_t type) 231 { 232 if (requester == NULL) 233 { 234 std::cerr << "Failed to send csr to host."; 235 pldm::utils::reportError( 236 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 237 return; 238 } 239 auto instanceId = requester->getInstanceId(mctp_eid); 240 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 241 PLDM_NEW_FILE_REQ_BYTES); 242 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 243 244 auto rc = 245 encode_new_file_req(instanceId, type, fileHandle, fileSize, request); 246 if (rc != PLDM_SUCCESS) 247 { 248 requester->markFree(mctp_eid, instanceId); 249 std::cerr << "Failed to encode_new_file_req, rc = " << rc << std::endl; 250 return; 251 } 252 253 uint8_t* responseMsg = nullptr; 254 size_t responseMsgSize{}; 255 256 auto requesterRc = 257 pldm_send_recv(mctp_eid, mctp_fd, requestMsg.data(), requestMsg.size(), 258 &responseMsg, &responseMsgSize); 259 260 std::unique_ptr<uint8_t, decltype(std::free)*> responseMsgPtr{responseMsg, 261 std::free}; 262 263 requester->markFree(mctp_eid, instanceId); 264 bool isDecodeNewFileRespFailed = false; 265 if (requesterRc != PLDM_REQUESTER_SUCCESS) 266 { 267 std::cerr << "Failed to send file to host, rc = " << requesterRc 268 << std::endl; 269 } 270 else 271 { 272 uint8_t completionCode{}; 273 auto responsePtr = 274 reinterpret_cast<struct pldm_msg*>(responseMsgPtr.get()); 275 276 rc = decode_new_file_resp(responsePtr, PLDM_NEW_FILE_RESP_BYTES, 277 &completionCode); 278 279 std::vector<uint8_t> responseMsgVec; 280 responseMsgVec.resize(responseMsgSize); 281 memcpy(responseMsgVec.data(), responseMsg, responseMsgVec.size()); 282 283 if (rc != PLDM_SUCCESS || completionCode != PLDM_SUCCESS) 284 { 285 std::cerr << "Failed to decode_new_file_resp: " 286 << "rc=" << rc 287 << ", cc=" << static_cast<unsigned>(completionCode) 288 << std::endl; 289 isDecodeNewFileRespFailed = true; 290 } 291 } 292 if ((requesterRc != PLDM_REQUESTER_SUCCESS) || (isDecodeNewFileRespFailed)) 293 { 294 pldm::utils::reportError( 295 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 296 } 297 } 298 299 } // namespace oem_ibm 300 } // namespace requester 301 } // namespace pldm 302