host: Added support to delete system dump

To delete host system dump using pldm oem command "FileAck" with
dump file type and dump id which is present as source dump id (which
is got from pldm after created the host system dump) in system dump entry
dbus object and also, to use pldm oem command added support to indicate
delete host system dump support is not available for other host transport
consumer and for other oem vendors who are using pldm as host transport
to get host dump.

Also, changed existing commited error i.e internal failure into not allowed
for host system dump offload to avoid bmc dump creation in dump path.

Signed-off-by: Ramesh Iyyar <rameshi1@in.ibm.com>
Change-Id: Ib6be5b521fb3c5aa2926497bae0b03c1d9737161
diff --git a/host-transport-extensions/default/default.cpp b/host-transport-extensions/default/default.cpp
index 9eb2bfe..bc49afc 100644
--- a/host-transport-extensions/default/default.cpp
+++ b/host-transport-extensions/default/default.cpp
@@ -12,6 +12,10 @@
     throw std::runtime_error("Hostdump offload method not specified");
 }
 
+void requestDelete(uint32_t)
+{
+    throw std::runtime_error("Hostdump delete method not specified");
+}
 } // namespace host
 } // namespace dump
 } // namespace phosphor
diff --git a/host-transport-extensions/pldm/default/pldm_interface.cpp b/host-transport-extensions/pldm/default/pldm_interface.cpp
index 57658af..7d7139d 100644
--- a/host-transport-extensions/pldm/default/pldm_interface.cpp
+++ b/host-transport-extensions/pldm/default/pldm_interface.cpp
@@ -16,6 +16,11 @@
 {
     throw std::runtime_error("PLDM: Hostdump offload method not specified");
 }
+
+void requestDelete(uint32_t)
+{
+    throw std::runtime_error("PLDM: Hostdump delete method not specified");
+}
 } // namespace host
 } // namespace dump
 } // namespace phosphor
diff --git a/host-transport-extensions/pldm/oem/ibm/pldm_oem_cmds.cpp b/host-transport-extensions/pldm/oem/ibm/pldm_oem_cmds.cpp
index adc9c48..a26a5d3 100644
--- a/host-transport-extensions/pldm/oem/ibm/pldm_oem_cmds.cpp
+++ b/host-transport-extensions/pldm/oem/ibm/pldm_oem_cmds.cpp
@@ -20,6 +20,7 @@
 #include "xyz/openbmc_project/Common/error.hpp"
 
 #include <libpldm/base.h>
+#include <libpldm/file_io.h>
 #include <libpldm/platform.h>
 #include <unistd.h>
 
@@ -44,6 +45,11 @@
 {
     pldm::requestOffload(id);
 }
+
+void requestDelete(uint32_t id)
+{
+    pldm::requestDelete(id);
+}
 } // namespace host
 
 namespace pldm
@@ -54,8 +60,8 @@
 constexpr auto eidPath = "/usr/share/pldm/host_eid";
 constexpr mctp_eid_t defaultEIDValue = 9;
 
-using InternalFailure =
-    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
+using Reason = xyz::openbmc_project::Common::NotAllowed::REASON;
 
 mctp_eid_t readEID()
 {
@@ -65,7 +71,8 @@
     if (!eidFile.good())
     {
         log<level::ERR>("Could not open host EID file");
-        elog<InternalFailure>();
+        elog<NotAllowed>(Reason("Required host dump action via pldm is not "
+                                "allowed due to mctp end point read failed"));
     }
     else
     {
@@ -78,7 +85,9 @@
         else
         {
             log<level::ERR>("EID file was empty");
-            elog<InternalFailure>();
+            elog<NotAllowed>(
+                Reason("Required host dump action via pldm is not "
+                       "allowed due to mctp end point read failed"));
         }
     }
 
@@ -110,7 +119,8 @@
     if (rc != PLDM_SUCCESS)
     {
         log<level::ERR>("Message encode failure. ", entry("RC=%d", rc));
-        elog<InternalFailure>();
+        elog<NotAllowed>(Reason("Host system dump offload via pldm is not "
+                                "allowed due to encode failed"));
     }
 
     uint8_t* responseMsg = nullptr;
@@ -125,7 +135,8 @@
         auto e = errno;
         log<level::ERR>("pldm_send failed", entry("RC=%d", rc),
                         entry("ERRNO=%d", e));
-        elog<InternalFailure>();
+        elog<NotAllowed>(Reason("Host system dump offload via pldm is not "
+                                "allowed due to fileack send failed"));
     }
     pldm_msg* response = reinterpret_cast<pldm_msg*>(responseMsg);
     log<level::INFO>(
@@ -133,6 +144,80 @@
         entry("RC=%d", static_cast<uint16_t>(response->payload[0])));
 }
 
+/*
+ * Using FileAck pldm command with file type as PLDM_FILE_TYPE_DUMP
+ * to delete host system dump
+ */
+void requestDelete(uint32_t dumpId)
+{
+    const size_t pldmMsgHdrSize = sizeof(pldm_msg_hdr);
+    std::array<uint8_t, pldmMsgHdrSize + PLDM_FILE_ACK_REQ_BYTES> fileAckReqMsg;
+
+    mctp_eid_t mctpEndPointId = readEID();
+
+    auto pldmInstanceId = getPLDMInstanceID(mctpEndPointId);
+
+    // - PLDM_FILE_TYPE_DUMP - To indicate FileAck for Host system dump
+    // - PLDM_SUCCESS - To indicate dump was readed (offloaded) or user decided,
+    //   no longer host system dump is not required so, initiate deletion from
+    //   host memory
+    int retCode = encode_file_ack_req(
+        pldmInstanceId, PLDM_FILE_TYPE_DUMP, dumpId, PLDM_SUCCESS,
+        reinterpret_cast<pldm_msg*>(fileAckReqMsg.data()));
+
+    if (retCode != PLDM_SUCCESS)
+    {
+        log<level::ERR>(
+            "Failed to encode pldm FileAck to delete host system dump",
+            entry("SRC_DUMP_ID=%d", dumpId),
+            entry("PLDM_RETURN_CODE=%d", retCode));
+        elog<NotAllowed>(Reason("Host system dump deletion via pldm is not "
+                                "allowed due to encode fileack failed"));
+    }
+
+    uint8_t* pldmRespMsg = nullptr;
+    size_t pldmRespMsgSize;
+
+    CustomFd pldmFd(openPLDM());
+
+    retCode =
+        pldm_send_recv(mctpEndPointId, pldmFd(), fileAckReqMsg.data(),
+                       fileAckReqMsg.size(), &pldmRespMsg, &pldmRespMsgSize);
+
+    std::unique_ptr<uint8_t, decltype(std::free)*> pldmRespMsgPtr{pldmRespMsg,
+                                                                  std::free};
+    if (retCode != PLDM_REQUESTER_SUCCESS)
+    {
+        auto errorNumber = errno;
+        log<level::ERR>(
+            "Failed to send pldm FileAck to delete host system dump",
+            entry("SRC_DUMP_ID=%d", dumpId),
+            entry("PLDM_RETURN_CODE=%d", retCode),
+            entry("ERRNO=%d", errorNumber),
+            entry("ERRMSG=%s", strerror(errorNumber)));
+        elog<NotAllowed>(Reason("Host system dump deletion via pldm is not "
+                                "allowed due to fileack send failed"));
+    }
+
+    uint8_t completionCode;
+
+    retCode =
+        decode_file_ack_resp(reinterpret_cast<pldm_msg*>(pldmRespMsgPtr.get()),
+                             pldmRespMsgSize - pldmMsgHdrSize, &completionCode);
+
+    if (retCode || completionCode)
+    {
+        log<level::ERR>("Failed to delete host system dump",
+                        entry("SRC_DUMP_ID=%d", dumpId),
+                        entry("PLDM_RETURN_CODE=%d", retCode),
+                        entry("PLDM_COMPLETION_CODE=%d", completionCode));
+        elog<NotAllowed>(Reason("Host system dump deletion via pldm is "
+                                "failed"));
+    }
+
+    log<level::INFO>("Deleted host system dump",
+                     entry("SRC_DUMP_ID=%d", dumpId));
+}
 } // namespace pldm
 } // namespace dump
 } // namespace phosphor
diff --git a/host-transport-extensions/pldm/oem/ibm/pldm_oem_cmds.hpp b/host-transport-extensions/pldm/oem/ibm/pldm_oem_cmds.hpp
index 9b2fdb3..1ab099a 100644
--- a/host-transport-extensions/pldm/oem/ibm/pldm_oem_cmds.hpp
+++ b/host-transport-extensions/pldm/oem/ibm/pldm_oem_cmds.hpp
@@ -15,6 +15,15 @@
  *
  */
 void requestOffload(uint32_t id);
+
+/**
+ * @brief Request to delete dump
+ *
+ * @param[in] id - The Dump Source ID.
+ * @return NULL
+ *
+ */
+void requestDelete(uint32_t id);
 } // namespace host
 
 namespace pldm
@@ -43,6 +52,14 @@
  */
 mctp_eid_t readEID();
 
+/**
+ * @brief Request to delete dump
+ *
+ * @param[in] id - The Dump Source ID.
+ * @return NULL
+ *
+ */
+void requestDelete(uint32_t id);
 } // namespace pldm
 } // namespace dump
 } // namespace phosphor