hiomap: Plumb DBus signals through as SELs
Change-Id: Ifc33497f0f0572b0e41b235654719d9f17360885
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
diff --git a/hiomap.cpp b/hiomap.cpp
index f623e61..b5b9e81 100644
--- a/hiomap.cpp
+++ b/hiomap.cpp
@@ -11,10 +11,17 @@
#include <systemd/sd-bus.h>
#include <fstream>
+#include <functional>
+#include <host-ipmid/ipmid-host-cmd-utils.hpp>
+#include <host-ipmid/ipmid-host-cmd.hpp>
+#include <iostream>
+#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/exception.hpp>
using namespace sdbusplus;
+using namespace phosphor::host::command;
static void register_openpower_hiomap_commands() __attribute__((constructor));
@@ -22,6 +29,33 @@
{
namespace flash
{
+constexpr auto BMC_EVENT_DAEMON_READY = 1 << 7;
+constexpr auto BMC_EVENT_FLASH_CTRL_LOST = 1 << 6;
+constexpr auto BMC_EVENT_WINDOW_RESET = 1 << 1;
+constexpr auto BMC_EVENT_PROTOCOL_RESET = 1 << 0;
+
+constexpr auto IPMI_CMD_HIOMAP_EVENT = 0x0f;
+
+constexpr auto HIOMAPD_SERVICE = "xyz.openbmc_project.Hiomapd";
+constexpr auto HIOMAPD_OBJECT = "/xyz/openbmc_project/Hiomapd";
+constexpr auto HIOMAPD_IFACE = "xyz.openbmc_project.Hiomapd.Protocol";
+constexpr auto HIOMAPD_IFACE_V2 = "xyz.openbmc_project.Hiomapd.Protocol.V2";
+
+constexpr auto DBUS_IFACE_PROPERTIES = "org.freedesktop.DBus.Properties";
+
+struct hiomap
+{
+ bus::bus *bus;
+
+ /* Signals */
+ bus::match::match *properties;
+ bus::match::match *window_reset;
+ bus::match::match *bmc_reboot;
+
+ /* Protocol state */
+ std::map<std::string, int> event_lookup;
+ uint8_t bmc_events;
+};
/* TODO: Replace get/put with packed structs and direct assignment */
template <typename T> static inline T get(void *buf)
@@ -71,26 +105,131 @@
return entry->cc;
}
+static void ipmi_hiomap_event_response(IpmiCmdData cmd, bool status)
+{
+ using namespace phosphor::logging;
+
+ if (!status)
+ {
+ log<level::ERR>("Failed to deliver host command",
+ entry("SEL_COMMAND=%x:%x", cmd.first, cmd.second));
+ }
+}
+
+static int hiomap_handle_property_update(struct hiomap *ctx,
+ sdbusplus::message::message &msg)
+{
+ std::map<std::string, sdbusplus::message::variant<bool>> msgData;
+
+ std::string iface;
+ msg.read(iface, msgData);
+
+ for (auto const &x : msgData)
+ {
+ if (!ctx->event_lookup.count(x.first))
+ {
+ /* Unsupported event? */
+ continue;
+ }
+
+ uint8_t mask = ctx->event_lookup[x.first];
+ auto value = sdbusplus::message::variant_ns::get<bool>(x.second);
+
+ if (value)
+ {
+ ctx->bmc_events |= mask;
+ }
+ else
+ {
+ ctx->bmc_events &= ~mask;
+ }
+ }
+
+ auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events);
+
+ ipmid_send_cmd_to_host(std::make_tuple(cmd, ipmi_hiomap_event_response));
+
+ return 0;
+}
+
+static bus::match::match hiomap_match_properties(struct hiomap *ctx)
+{
+ auto properties =
+ bus::match::rules::propertiesChanged(HIOMAPD_OBJECT, HIOMAPD_IFACE_V2);
+
+ bus::match::match match(
+ *ctx->bus, properties,
+ std::bind(hiomap_handle_property_update, ctx, std::placeholders::_1));
+
+ return match;
+}
+
+static int hiomap_handle_signal_v2(struct hiomap *ctx, const char *name)
+{
+ ctx->bmc_events |= ctx->event_lookup[name];
+
+ auto cmd = std::make_pair(IPMI_CMD_HIOMAP_EVENT, ctx->bmc_events);
+
+ ipmid_send_cmd_to_host(std::make_tuple(cmd, ipmi_hiomap_event_response));
+
+ return 0;
+}
+
+static bus::match::match hiomap_match_signal_v2(struct hiomap *ctx,
+ const char *name)
+{
+ using namespace bus::match;
+
+ auto signals = rules::type::signal() + rules::path(HIOMAPD_OBJECT) +
+ rules::interface(HIOMAPD_IFACE_V2) + rules::member(name);
+
+ bus::match::match match(*ctx->bus, signals,
+ std::bind(hiomap_handle_signal_v2, ctx, name));
+
+ return match;
+}
+
+static ipmi_ret_t hiomap_reset(ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t data_len, ipmi_context_t context)
+{
+ struct hiomap *ctx = static_cast<struct hiomap *>(context);
+
+ auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
+ HIOMAPD_IFACE, "Reset");
+ try
+ {
+ ctx->bus->call(m);
+
+ *data_len = 0;
+ }
+ catch (const exception::SdBusError &e)
+ {
+ return hiomap_xlate_errno(e.get_errno());
+ }
+
+ return IPMI_CC_OK;
+}
+
static ipmi_ret_t hiomap_get_info(ipmi_request_t request,
ipmi_response_t response,
ipmi_data_len_t data_len,
ipmi_context_t context)
{
+ struct hiomap *ctx = static_cast<struct hiomap *>(context);
+
if (*data_len < 1)
{
return IPMI_CC_REQ_DATA_LEN_INVALID;
}
uint8_t *reqdata = (uint8_t *)request;
- auto b = bus::new_system();
- auto m = b.new_method_call(
- "xyz.openbmc_project.Hiomapd", "/xyz/openbmc_project/Hiomapd",
- "xyz.openbmc_project.Hiomapd.Protocol", "GetInfo");
+ auto m = ctx->bus->new_method_call(HIOMAPD_SERVICE, HIOMAPD_OBJECT,
+ HIOMAPD_IFACE, "GetInfo");
m.append(reqdata[0]);
try
{
- auto reply = b.call(m);
+ auto reply = ctx->bus->call(m);
uint8_t version;
uint8_t blockSizeShift;
@@ -116,7 +255,7 @@
static const hiomap_command hiomap_commands[] = {
[0] = NULL, /* 0 is an invalid command ID */
- [1] = NULL, /* RESET */
+ [1] = hiomap_reset,
[2] = hiomap_get_info,
};
@@ -130,6 +269,8 @@
ipmi_data_len_t data_len,
ipmi_context_t context)
{
+ struct hiomap *ctx = static_cast<struct hiomap *>(context);
+
if (*data_len < 2)
{
*data_len = 0;
@@ -158,8 +299,8 @@
}
/* Populate the response command and sequence */
- put(&ipmi_resp[0], ipmi_req[0]);
- put(&ipmi_resp[1], ipmi_req[1]);
+ ipmi_resp[0] = hiomap_cmd;
+ ipmi_resp[1] = ipmi_req[1];
*data_len = flash_len + 2;
@@ -170,6 +311,32 @@
static void register_openpower_hiomap_commands()
{
- ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_HIOMAP, NULL,
+ using namespace openpower::flash;
+
+ /* FIXME: Clean this up? Can we unregister? */
+ struct hiomap *ctx = new hiomap();
+
+ /* Initialise mapping from signal and property names to status bit */
+ ctx->event_lookup["DaemonReady"] = BMC_EVENT_DAEMON_READY;
+ ctx->event_lookup["FlashControlLost"] = BMC_EVENT_FLASH_CTRL_LOST;
+ ctx->event_lookup["WindowReset"] = BMC_EVENT_WINDOW_RESET;
+ ctx->event_lookup["ProtocolReset"] = BMC_EVENT_PROTOCOL_RESET;
+
+ ctx->bus = new bus::bus(ipmid_get_sd_bus_connection());
+
+ /* Initialise signal handling */
+
+ /*
+ * Can't use temporaries here because that causes SEGFAULTs due to slot
+ * destruction (!?), so enjoy the weird wrapping.
+ */
+ ctx->properties =
+ new bus::match::match(std::move(hiomap_match_properties(ctx)));
+ ctx->bmc_reboot = new bus::match::match(
+ std::move(hiomap_match_signal_v2(ctx, "ProtocolReset")));
+ ctx->window_reset = new bus::match::match(
+ std::move(hiomap_match_signal_v2(ctx, "WindowReset")));
+
+ ipmi_register_callback(NETFUN_IBM_OEM, IPMI_CMD_HIOMAP, ctx,
openpower::flash::hiomap_dispatch, SYSTEM_INTERFACE);
}