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 pldm::requester::Handler<pldm::requester::Request>* handler) : 30 mctp_fd(mctp_fd), 31 mctp_eid(mctp_eid), requester(requester), 32 resDumpCurrentObjPath(resDumpCurrentObjPath), handler(handler) 33 {} 34 35 void DbusToFileHandler::sendNewFileAvailableCmd(uint64_t fileSize) 36 { 37 if (requester == NULL) 38 { 39 std::cerr << "Failed to send resource dump parameters as requester is " 40 "not set"; 41 pldm::utils::reportError( 42 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 43 return; 44 } 45 auto instanceId = requester->getInstanceId(mctp_eid); 46 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 47 PLDM_NEW_FILE_REQ_BYTES + fileSize); 48 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 49 // Need to revisit this logic at the time of multiple resource dump support 50 uint32_t fileHandle = 1; 51 52 auto rc = 53 encode_new_file_req(instanceId, PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS, 54 fileHandle, fileSize, request); 55 if (rc != PLDM_SUCCESS) 56 { 57 requester->markFree(mctp_eid, instanceId); 58 std::cerr << "Failed to encode_new_file_req, rc = " << rc << std::endl; 59 return; 60 } 61 62 auto newFileAvailableRespHandler = [this](mctp_eid_t /*eid*/, 63 const pldm_msg* response, 64 size_t respMsgLen) { 65 if (response == nullptr || !respMsgLen) 66 { 67 std::cerr 68 << "Failed to receive response for NewFileAvailable command \n"; 69 return; 70 } 71 uint8_t completionCode{}; 72 auto rc = decode_new_file_resp(response, respMsgLen, &completionCode); 73 if (rc || completionCode) 74 { 75 std::cerr << "Failed to decode_new_file_resp or" 76 << " Host returned error for new_file_available" 77 << " rc=" << rc 78 << ", cc=" << static_cast<unsigned>(completionCode) 79 << "\n"; 80 reportResourceDumpFailure(); 81 } 82 }; 83 rc = handler->registerRequest( 84 mctp_eid, instanceId, PLDM_OEM, PLDM_NEW_FILE_AVAILABLE, 85 std::move(requestMsg), std::move(newFileAvailableRespHandler)); 86 if (rc) 87 { 88 std::cerr << "Failed to send NewFileAvailable Request to Host \n"; 89 reportResourceDumpFailure(); 90 } 91 } 92 93 void DbusToFileHandler::reportResourceDumpFailure() 94 { 95 96 pldm::utils::reportError("xyz.openbmc_project.bmc.pldm.InternalFailure"); 97 98 PropertyValue value{resDumpStatus}; 99 DBusMapping dbusMapping{resDumpCurrentObjPath, resDumpProgressIntf, 100 "Status", "string"}; 101 try 102 { 103 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 104 } 105 catch (const std::exception& e) 106 { 107 std::cerr << "failed to set resource dump operation status, " 108 "ERROR=" 109 << e.what() << "\n"; 110 } 111 } 112 113 void DbusToFileHandler::processNewResourceDump( 114 const std::string& vspString, const std::string& resDumpReqPass) 115 { 116 namespace fs = std::filesystem; 117 const fs::path resDumpDirPath = "/var/lib/pldm/resourcedump"; 118 119 if (!fs::exists(resDumpDirPath)) 120 { 121 fs::create_directories(resDumpDirPath); 122 } 123 124 // Need to reconsider this logic to set the value as "1" when we have the 125 // support to handle multiple resource dumps 126 fs::path resDumpFilePath = resDumpDirPath / "1"; 127 128 std::ofstream fileHandle; 129 fileHandle.open(resDumpFilePath, std::ios::out | std::ofstream::binary); 130 131 if (!fileHandle) 132 { 133 std::cerr << "resource dump file open error: " << resDumpFilePath 134 << "\n"; 135 PropertyValue value{resDumpStatus}; 136 DBusMapping dbusMapping{resDumpCurrentObjPath, resDumpProgressIntf, 137 "Status", "string"}; 138 try 139 { 140 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value); 141 } 142 catch (const std::exception& e) 143 { 144 std::cerr << "failed to set resource dump operation status, " 145 "ERROR=" 146 << e.what() << "\n"; 147 } 148 return; 149 } 150 151 // Fill up the file with resource dump parameters and respective sizes 152 auto fileFunc = [&fileHandle](auto& paramBuf) { 153 uint32_t paramSize = paramBuf.size(); 154 fileHandle.write((char*)¶mSize, sizeof(paramSize)); 155 fileHandle << paramBuf; 156 }; 157 fileFunc(vspString); 158 fileFunc(resDumpReqPass); 159 160 fileHandle.close(); 161 size_t fileSize = fs::file_size(resDumpFilePath); 162 163 sendNewFileAvailableCmd(fileSize); 164 } 165 166 void DbusToFileHandler::newCsrFileAvailable(const std::string& csr, 167 const std::string fileHandle) 168 { 169 namespace fs = std::filesystem; 170 std::string dirPath = "/var/lib/ibm/bmcweb"; 171 const fs::path certDirPath = dirPath; 172 173 if (!fs::exists(certDirPath)) 174 { 175 fs::create_directories(certDirPath); 176 fs::permissions(certDirPath, 177 fs::perms::others_read | fs::perms::owner_write); 178 } 179 180 fs::path certFilePath = certDirPath / ("CSR_" + fileHandle); 181 std::ofstream certFile; 182 183 certFile.open(certFilePath, std::ios::out | std::ofstream::binary); 184 185 if (!certFile) 186 { 187 std::cerr << "cert file open error: " << certFilePath << "\n"; 188 return; 189 } 190 191 // Add csr to file 192 certFile << csr << std::endl; 193 194 certFile.close(); 195 uint32_t fileSize = fs::file_size(certFilePath); 196 197 newFileAvailableSendToHost(fileSize, (uint32_t)stoi(fileHandle), 198 PLDM_FILE_TYPE_CERT_SIGNING_REQUEST); 199 } 200 201 void DbusToFileHandler::newFileAvailableSendToHost(const uint32_t fileSize, 202 const uint32_t fileHandle, 203 const uint16_t type) 204 { 205 if (requester == NULL) 206 { 207 std::cerr << "Failed to send csr to host."; 208 pldm::utils::reportError( 209 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 210 return; 211 } 212 auto instanceId = requester->getInstanceId(mctp_eid); 213 std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) + 214 PLDM_NEW_FILE_REQ_BYTES); 215 auto request = reinterpret_cast<pldm_msg*>(requestMsg.data()); 216 217 auto rc = 218 encode_new_file_req(instanceId, type, fileHandle, fileSize, request); 219 if (rc != PLDM_SUCCESS) 220 { 221 requester->markFree(mctp_eid, instanceId); 222 std::cerr << "Failed to encode_new_file_req, rc = " << rc << std::endl; 223 return; 224 } 225 auto newFileAvailableRespHandler = [](mctp_eid_t /*eid*/, 226 const pldm_msg* response, 227 size_t respMsgLen) { 228 if (response == nullptr || !respMsgLen) 229 { 230 std::cerr << "Failed to receive response for NewFileAvailable " 231 "command for vmi \n"; 232 return; 233 } 234 uint8_t completionCode{}; 235 auto rc = decode_new_file_resp(response, respMsgLen, &completionCode); 236 if (rc || completionCode) 237 { 238 std::cerr << "Failed to decode_new_file_resp for vmi, or" 239 << " Host returned error for new_file_available" 240 << " rc=" << rc 241 << ", cc=" << static_cast<unsigned>(completionCode) 242 << "\n"; 243 pldm::utils::reportError( 244 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 245 } 246 }; 247 rc = handler->registerRequest( 248 mctp_eid, instanceId, PLDM_OEM, PLDM_NEW_FILE_AVAILABLE, 249 std::move(requestMsg), std::move(newFileAvailableRespHandler)); 250 if (rc) 251 { 252 std::cerr 253 << "Failed to send NewFileAvailable Request to Host for vmi \n"; 254 pldm::utils::reportError( 255 "xyz.openbmc_project.bmc.pldm.InternalFailure"); 256 } 257 } 258 259 } // namespace oem_ibm 260 } // namespace requester 261 } // namespace pldm 262