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