Added PLDM Dump offload command
Added support to sending the SetNumericEffecterValue
PLDM command to the host to start dump offload.
Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
Change-Id: I30fe59b198b55ad439a182877c6b21cfd070245b
diff --git a/Makefile.am b/Makefile.am
index b9c9928..751f3a7 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,7 +9,8 @@
dump_utils.hpp \
watch.hpp \
elog_watch.hpp \
- dump_serialize.hpp
+ dump_serialize.hpp \
+ pldm_interface.hpp
nobase_nodist_include_HEADERS = \
xyz/openbmc_project/Dump/Internal/Create/server.hpp
@@ -26,7 +27,9 @@
watch.cpp \
xyz/openbmc_project/Dump/Internal/Create/server.cpp \
elog_watch.cpp \
- dump_serialize.cpp
+ dump_serialize.cpp \
+ pldm_interface.cpp \
+ dump_utils.cpp
phosphor_dump_monitor_SOURCES = \
watch.cpp \
@@ -36,7 +39,8 @@
phosphor_dump_manager_CXXFLAGS = \
$(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
$(SDBUSPLUS_CFLAGS) \
- $(PHOSPHOR_LOGGING_CFLAGS)
+ $(PHOSPHOR_LOGGING_CFLAGS) \
+ $(LIBPLDM_CFLAGS)
phosphor_dump_monitor_CXXFLAGS = \
$(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \
@@ -46,7 +50,8 @@
$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
$(SDBUSPLUS_LIBS) \
$(PHOSPHOR_LOGGING_LIBS) \
- -lstdc++fs
+ -lstdc++fs \
+ $(LIBPLDM_LIBS)
phosphor_dump_monitor_LDADD = \
$(PHOSPHOR_DBUS_INTERFACES_LIBS) \
diff --git a/configure.ac b/configure.ac
old mode 100644
new mode 100755
index c6dcb65..5a3eb3a
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,7 @@
PKG_CHECK_MODULES([PHOSPHOR_DBUS_INTERFACES], [phosphor-dbus-interfaces])
PKG_CHECK_MODULES([SDBUSPLUS], [sdbusplus])
PKG_CHECK_MODULES([PHOSPHOR_LOGGING], [phosphor-logging])
+PKG_CHECK_MODULES([LIBPLDM], [libpldm])
# Check for sdbus++
AC_PATH_PROG([SDBUSPLUSPLUS], [sdbus++])
diff --git a/dump_utils.cpp b/dump_utils.cpp
new file mode 100644
index 0000000..b013706
--- /dev/null
+++ b/dump_utils.cpp
@@ -0,0 +1,49 @@
+#include "dump_utils.hpp"
+
+#include <phosphor-logging/log.hpp>
+
+namespace phosphor
+{
+namespace dump
+{
+
+std::string getService(sdbusplus::bus::bus& bus, const std::string& path,
+ const std::string& interface)
+{
+ constexpr auto objectMapperName = "xyz.openbmc_project.ObjectMapper";
+ constexpr auto objectMapperPath = "/xyz/openbmc_project/object_mapper";
+ using namespace phosphor::logging;
+
+ auto method = bus.new_method_call(objectMapperName, objectMapperPath,
+ objectMapperName, "GetObject");
+
+ method.append(path);
+ method.append(std::vector<std::string>({interface}));
+
+ std::vector<std::pair<std::string, std::vector<std::string>>> response;
+
+ try
+ {
+ auto reply = bus.call(method);
+ reply.read(response);
+ if (response.empty())
+ {
+ log<level::ERR>("Error in mapper response for getting service name",
+ entry("PATH=%s", path.c_str()),
+ entry("INTERFACE=%s", interface.c_str()));
+ return std::string{};
+ }
+ }
+ catch (const sdbusplus::exception::SdBusError& e)
+ {
+ log<level::ERR>("Error in mapper method call",
+ entry("ERROR=%s", e.what()),
+ entry("PATH=%s", path.c_str()),
+ entry("INTERFACE=%s", interface.c_str()));
+ return std::string{};
+ }
+ return response[0].first;
+}
+
+} // namespace dump
+} // namespace phosphor
diff --git a/dump_utils.hpp b/dump_utils.hpp
index ba351e1..a2c2604 100644
--- a/dump_utils.hpp
+++ b/dump_utils.hpp
@@ -4,6 +4,7 @@
#include <unistd.h>
#include <memory>
+#include <sdbusplus/bus.hpp>
namespace phosphor
{
@@ -59,5 +60,16 @@
}
};
+/**
+ * @brief Get the bus service
+ *
+ * @param[in] bus - Bus to attach to.
+ * @param[in] path - D-Bus path name.
+ * @param[in] interface - D-Bus interface name.
+ * @return the bus service as a string
+ **/
+std::string getService(sdbusplus::bus::bus& bus, const std::string& path,
+ const std::string& interface);
+
} // namespace dump
} // namespace phosphor
diff --git a/pldm_interface.cpp b/pldm_interface.cpp
new file mode 100644
index 0000000..57d7a2c
--- /dev/null
+++ b/pldm_interface.cpp
@@ -0,0 +1,166 @@
+/**
+ * Copyright © 2019 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "pldm_interface.hpp"
+
+#include "dump_utils.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <libpldm/base.h>
+#include <libpldm/platform.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <phosphor-logging/elog-errors.hpp>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus.hpp>
+
+namespace phosphor
+{
+namespace dump
+{
+namespace pldm
+{
+
+using namespace phosphor::logging;
+
+constexpr auto eidPath = "/usr/share/pldm/host_eid";
+constexpr mctp_eid_t defaultEIDValue = 9;
+
+using InternalFailure =
+ sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+void closeFD(int fd)
+{
+ if (fd >= 0)
+ {
+ close(fd);
+ }
+}
+
+mctp_eid_t readEID()
+{
+ mctp_eid_t eid = defaultEIDValue;
+
+ std::ifstream eidFile{eidPath};
+ if (!eidFile.good())
+ {
+ log<level::ERR>("Could not open host EID file");
+ elog<InternalFailure>();
+ }
+ else
+ {
+ std::string eid;
+ eidFile >> eid;
+ if (!eid.empty())
+ {
+ eid = strtol(eid.c_str(), nullptr, 10);
+ }
+ else
+ {
+ log<level::ERR>("EID file was empty");
+ elog<InternalFailure>();
+ }
+ }
+
+ return eid;
+}
+
+int open()
+{
+ auto fd = pldm_open();
+ if (fd < 0)
+ {
+ auto e = errno;
+ log<level::ERR>("pldm_open failed", entry("ERRNO=%d", e),
+ entry("FD=%d\n", fd));
+ elog<InternalFailure>();
+ }
+ return fd;
+}
+
+void requestOffload(uint32_t id)
+{
+ uint16_t effecterId = 0x05; // TODO PhyP temporary Hardcoded value.
+
+ std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(id) +
+ sizeof(uint8_t)>
+ requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ std::array<uint8_t, sizeof(id)> effecterValue{};
+
+ memcpy(effecterValue.data(), &id, sizeof(id));
+
+ mctp_eid_t eid = readEID();
+
+ auto instanceID = getPLDMInstanceID(eid);
+
+ auto rc = encode_set_numeric_effecter_value_req(
+ instanceID, effecterId, PLDM_EFFECTER_DATA_SIZE_UINT32,
+ effecterValue.data(), request,
+ requestMsg.size() - sizeof(pldm_msg_hdr));
+
+ if (rc != PLDM_SUCCESS)
+ {
+ log<level::ERR>("Message encode failure. ", entry("RC=%d", rc));
+ elog<InternalFailure>();
+ }
+
+ uint8_t* responseMsg = nullptr;
+ size_t responseMsgSize{};
+
+ auto fd = open();
+
+ rc = pldm_send_recv(eid, fd, requestMsg.data(), requestMsg.size(),
+ &responseMsg, &responseMsgSize);
+ if (rc < 0)
+ {
+ closeFD(fd);
+ auto e = errno;
+ log<level::ERR>("pldm_send failed", entry("RC=%d", rc),
+ entry("ERRNO=%d", e));
+ elog<InternalFailure>();
+ }
+ pldm_msg* response = reinterpret_cast<pldm_msg*>(responseMsg);
+ log<level::INFO>(
+ "Done. PLDM message",
+ entry("RC=%d", static_cast<uint16_t>(response->payload[0])));
+
+ closeFD(fd);
+}
+
+uint8_t getPLDMInstanceID(uint8_t eid)
+{
+
+ constexpr auto pldmRequester = "xyz.openbmc_project.PLDM.Requester";
+ constexpr auto pldm = "/xyz/openbmc_project/pldm";
+
+ auto bus = sdbusplus::bus::new_default();
+ auto service = phosphor::dump::getService(bus, pldm, pldmRequester);
+
+ auto method = bus.new_method_call(service.c_str(), pldm, pldmRequester,
+ "GetInstanceId");
+ method.append(eid);
+ auto reply = bus.call(method);
+
+ uint8_t instanceID = 0;
+ reply.read(instanceID);
+
+ return instanceID;
+}
+} // namespace pldm
+} // namespace dump
+} // namespace phosphor
diff --git a/pldm_interface.hpp b/pldm_interface.hpp
new file mode 100644
index 0000000..fffa682
--- /dev/null
+++ b/pldm_interface.hpp
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <libpldm/pldm.h>
+
+namespace phosphor
+{
+namespace dump
+{
+namespace pldm
+{
+
+/**
+ * PLDMInterface
+ *
+ * Handles sending the SetNumericEffecterValue PLDM
+ * command to the host to start dump offload.
+ *
+ */
+
+/**
+ * @brief Kicks of the SetNumericEffecterValue command to
+ * start offload the dump
+ *
+ * @param[in] id - The Dump Source ID.
+ *
+ */
+
+void requestOffload(uint32_t id);
+
+/**
+ * @brief Reads the MCTP endpoint ID out of a file
+ */
+mctp_eid_t readEID();
+
+/**
+ * @brief Opens the PLDM file descriptor
+ */
+int open();
+
+/**
+ * @brief Closes the PLDM file descriptor
+ */
+void closeFD(int fd);
+
+/**
+ * @brief Returns the PLDM instance ID to use for PLDM commands
+ *
+ * @param[in] eid - The PLDM EID
+ *
+ * @return uint8_t - The instance ID
+ **/
+uint8_t getPLDMInstanceID(uint8_t eid);
+
+} // namespace pldm
+} // namespace dump
+} // namespace phosphor