| Jayashankar Padath | db12436 | 2021-01-28 21:12:34 -0600 | [diff] [blame] | 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 |  | 
| Varsha Kaverappa | 219ace9 | 2021-04-01 02:50:11 -0500 | [diff] [blame] | 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 |  | 
| Jayashankar Padath | db12436 | 2021-01-28 21:12:34 -0600 | [diff] [blame] | 299 | } // namespace oem_ibm | 
 | 300 | } // namespace requester | 
 | 301 | } // namespace pldm |