diff options
-rw-r--r-- | Makefile.am | 17 | ||||
-rw-r--r-- | elog-errors.hpp | 67 | ||||
-rw-r--r-- | host-interface.cpp | 7 | ||||
-rw-r--r-- | host-interface.hpp | 28 | ||||
-rw-r--r-- | host-services.cpp | 39 | ||||
-rw-r--r-- | host-services.hpp | 1 | ||||
-rw-r--r-- | ipmid.hpp | 1 | ||||
-rw-r--r-- | systemintfcmds.cpp | 104 | ||||
-rw-r--r-- | systemintfcmds.h | 2 | ||||
-rw-r--r-- | xyz/openbmc_project/Control/Internal/Host.errors.yaml | 3 | ||||
-rw-r--r-- | xyz/openbmc_project/Control/Internal/Host.metadata.yaml | 3 |
11 files changed, 187 insertions, 85 deletions
diff --git a/Makefile.am b/Makefile.am index c9b28c2..1df5216 100644 --- a/Makefile.am +++ b/Makefile.am @@ -43,23 +43,18 @@ libapphandler_la_CXXFLAGS = $(SYSTEMD_CFLAGS) $(libmapper_CFLAGS) $(PHOSPHOR_LOG libsysintfcmdsdir = ${libdir}/ipmid-providers libsysintfcmds_LTLIBRARIES = libsysintfcmds.la libsysintfcmds_la_SOURCES = \ - systemintfcmds.cpp -libsysintfcmds_la_LDFLAGS = $(SYSTEMD_LIBS) $(libmapper_LIBS) -version-info 0:0:0 -shared -libsysintfcmds_la_CXXFLAGS = $(SYSTEMD_CFLAGS) $(libmapper_CFLAGS) - -libhostservicedir = ${libdir}/ipmid-providers -libhostservice_LTLIBRARIES = libhostservice.la -libhostservice_la_SOURCES = \ - host-services.cpp \ + systemintfcmds.cpp \ host-interface.cpp \ utils.cpp -libhostservice_la_LDFLAGS = $(SYSTEMD_LIBS) \ +libsysintfcmds_la_LDFLAGS = $(SYSTEMD_LIBS) \ $(libmapper_LIBS) \ $(PHOSPHOR_DBUS_INTERFACES_LIBS) \ + $(PHOSPHOR_LOGGING_LIBS) \ -version-info 0:0:0 -shared -libhostservice_la_CXXFLAGS = $(SYSTEMD_CFLAGS) \ +libsysintfcmds_la_CXXFLAGS = $(SYSTEMD_CFLAGS) \ + $(libmapper_CFLAGS) \ $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) \ - $(libmapper_CFLAGS) + $(PHOSPHOR_LOGGING_CFLAGS) nobase_include_HEADERS = \ host-ipmid/ipmid-api.h diff --git a/elog-errors.hpp b/elog-errors.hpp new file mode 100644 index 0000000..de74160 --- /dev/null +++ b/elog-errors.hpp @@ -0,0 +1,67 @@ +// This file was autogenerated. Do not edit! +// See elog-gen.py for more details +#pragma once + +#include <string> +#include <tuple> +#include <type_traits> +#include <sdbusplus/exception.hpp> +#include <phosphor-logging/log.hpp> +#include <phosphor-logging/elog.hpp> + + +namespace phosphor +{ + +namespace logging +{ + +namespace xyz +{ +namespace openbmc_project +{ +namespace Control +{ +namespace Internal +{ +namespace Host +{ +namespace _QueueEmpty +{ + + +} // namespace _QueueEmpty + +struct QueueEmpty : public sdbusplus::exception_t +{ + static constexpr auto errName = "xyz.openbmc_project.Control.Internal.Host.QueueEmpty"; + static constexpr auto errDesc = "The host response queue is empty and it should not be!"; + static constexpr auto L = level::ERR; + using metadata_types = std::tuple<>; + + const char* name() const noexcept + { + return errName; + } + + const char* description() const noexcept + { + return errDesc; + } + + const char* what() const noexcept + { + return errName; + } +}; + +} // namespace Host +} // namespace Internal +} // namespace Control +} // namespace openbmc_project +} // namespace xyz + + +} // namespace logging + +} // namespace phosphor diff --git a/host-interface.cpp b/host-interface.cpp index f485516..aa32ff0 100644 --- a/host-interface.cpp +++ b/host-interface.cpp @@ -1,4 +1,3 @@ -#include <queue> #include <phosphor-logging/log.hpp> #include <utils.hpp> #include "host-interface.hpp" @@ -17,17 +16,15 @@ using namespace phosphor::logging; // When you see base:: you know we're referencing our base class namespace base = sdbusplus::xyz::openbmc_project::Control::server; -std::queue<base::Host::Command> workQueue{}; - void Host::execute(base::Host::Command command) { log<level::INFO>("Pushing cmd on to queue", entry("CONTROL_HOST_CMD=%s", convertForMessage(command))); - workQueue.push(command); + this->workQueue.push(command); // If this was the only entry then send the SMS attention - if(workQueue.size() == 1) + if(this->workQueue.size() == 1) { log<level::INFO>("Asserting SMS Attention"); diff --git a/host-interface.hpp b/host-interface.hpp index a3b7efa..36b41d9 100644 --- a/host-interface.hpp +++ b/host-interface.hpp @@ -1,13 +1,18 @@ #pragma once +#include <queue> #include <sdbusplus/bus.hpp> +#include <phosphor-logging/elog.hpp> #include <xyz/openbmc_project/Control/Host/server.hpp> +#include "elog-errors.hpp" namespace phosphor { namespace host { +using namespace phosphor::logging; + /** @class Host * @brief OpenBMC control host interface implementation. * @details A concrete implementation for xyz.openbmc_project.Control.Host @@ -39,10 +44,33 @@ class Host : public sdbusplus::server::object::object< */ void execute(Command command) override; + /** @brief Return the next entry in the queue + * + * Also signal that the command is complete since the interface + * contract is that we emit this signal once the message has been + * passed to the host (which is required when calling this interface) + * + */ + Command getNextCommand() + { + if(this->workQueue.empty()) + { + log<level::ERR>("Control Host work queue is empty!"); + elog<xyz::openbmc_project::Control::Internal::Host::QueueEmpty>(); + } + Command command = this->workQueue.front(); + this->workQueue.pop(); + this->commandComplete(command, Result::Success); + return command; + } + private: /** @brief Persistent sdbusplus DBus bus connection. */ sdbusplus::bus::bus& bus; + + /** @brief Queue to store the requested commands */ + std::queue<Command> workQueue{}; }; } // namespace host diff --git a/host-services.cpp b/host-services.cpp deleted file mode 100644 index c78d90a..0000000 --- a/host-services.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <systemd/sd-bus.h> -#include <mapper.h> -#include "host-ipmid/ipmid-api.h" -#include "host-interface.hpp" -#include <config.h> - -void register_host_services() __attribute__((constructor)); - -//------------------------------------------------------ -// Callback register function -// ----------------------------------------------------- - -// Globals to keep the object alive during process life -std::unique_ptr<sdbusplus::bus::bus> sdbus = nullptr; -// TODO openbmc/openbmc#1581 - unique_ptr causes seg fault -phosphor::host::Host* host = nullptr; - -void register_host_services() -{ - // Gets a hook onto SYSTEM bus used by host-ipmid - sd_bus *bus = ipmid_get_sd_bus_connection(); - - sdbus = std::make_unique<sdbusplus::bus::bus>(bus); - - // Create new xyz.openbmc_project.host object on the bus - auto objPathInst = std::string{CONTROL_HOST_OBJPATH} + '0'; - - // Add sdbusplus ObjectManager. - sdbusplus::server::manager::manager objManager(*sdbus, - objPathInst.c_str()); - - host = new phosphor::host::Host(*sdbus, - objPathInst.c_str()); - - sdbus->request_name(CONTROL_HOST_BUSNAME); -} diff --git a/host-services.hpp b/host-services.hpp deleted file mode 100644 index 4c2ddad..0000000 --- a/host-services.hpp +++ /dev/null @@ -1 +0,0 @@ -#include <systemd/sd-bus.h> @@ -2,7 +2,6 @@ #define __HOST_IPMID_IPMI_H__ #include "host-ipmid/ipmid-api.h" #include <stdio.h> -#include "host-services.hpp" // When the requester sends in a netfn and a command along with data, this // function will look for registered handlers that will handle that [netfn,cmd] diff --git a/systemintfcmds.cpp b/systemintfcmds.cpp index 62d9524..999e710 100644 --- a/systemintfcmds.cpp +++ b/systemintfcmds.cpp @@ -1,26 +1,21 @@ #include "systemintfcmds.h" #include "host-ipmid/ipmid-api.h" #include "config.h" +#include "host-interface.hpp" #include <stdio.h> #include <mapper.h> void register_netfn_app_functions() __attribute__((constructor)); -//------------------------------------------------------------------- -// Called by Host post response from Get_Message_Flags -//------------------------------------------------------------------- -ipmi_ret_t ipmi_app_read_event(ipmi_netfn_t netfn, ipmi_cmd_t cmd, - ipmi_request_t request, ipmi_response_t response, - ipmi_data_len_t data_len, ipmi_context_t context) -{ - ipmi_ret_t rc = IPMI_CC_OK; +using namespace sdbusplus::xyz::openbmc_project::Control::server; - printf("IPMI APP READ EVENT command received\n"); +// Internal function to get next host command +Host::Command getNextHostCmd(); - // TODO : For now, this is catering only to the Soft Power Off via OEM SEL - // mechanism. If we need to make this generically used for some - // other conditions, then we can take advantage of context pointer. +// Notify SofPowerOff application that host is responding to command +void notifySoftOff() +{ constexpr auto iface = "org.freedesktop.DBus.Properties"; constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal." @@ -31,9 +26,6 @@ ipmi_ret_t ipmi_app_read_event(ipmi_netfn_t netfn, ipmi_cmd_t cmd, "SoftPowerOff.HostResponse.SoftOffReceived"; char *busname = nullptr; - struct oem_sel_timestamped soft_off = {0}; - *data_len = sizeof(struct oem_sel_timestamped); - // Get the system bus where most system services are provided. auto bus = ipmid_get_sd_bus_connection(); @@ -56,31 +48,58 @@ ipmi_ret_t ipmi_app_read_event(ipmi_netfn_t netfn, ipmi_cmd_t cmd, } else { - printf("Soft Power Off object is not available. Ignoring watchdog refresh"); + printf("Soft Power Off object is not available. Ignoring watchdog \ + refresh"); } +} + +//------------------------------------------------------------------- +// Called by Host post response from Get_Message_Flags +//------------------------------------------------------------------- +ipmi_ret_t ipmi_app_read_event(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + ipmi_request_t request, ipmi_response_t response, + ipmi_data_len_t data_len, ipmi_context_t context) +{ + ipmi_ret_t rc = IPMI_CC_OK; + + printf("IPMI APP READ EVENT command received\n"); + + struct oem_sel_timestamped oem_sel = {0}; + *data_len = sizeof(struct oem_sel_timestamped); // either id[0] -or- id[1] can be filled in. We will use id[0] - soft_off.id[0] = SEL_OEM_ID_0; - soft_off.id[1] = SEL_OEM_ID_0; - soft_off.type = SEL_RECORD_TYPE_OEM; + oem_sel.id[0] = SEL_OEM_ID_0; + oem_sel.id[1] = SEL_OEM_ID_0; + oem_sel.type = SEL_RECORD_TYPE_OEM; // Following 3 bytes are from IANA Manufactre_Id field. See below - soft_off.manuf_id[0]= 0x41; - soft_off.manuf_id[1]= 0xA7; - soft_off.manuf_id[2]= 0x00; + oem_sel.manuf_id[0]= 0x41; + oem_sel.manuf_id[1]= 0xA7; + oem_sel.manuf_id[2]= 0x00; // per IPMI spec NetFuntion for OEM - soft_off.netfun = 0x3A; + oem_sel.netfun = 0x3A; - // Mechanism to kick start soft shutdown. - soft_off.cmd = CMD_POWER; - soft_off.data[0] = SOFT_OFF; + // Read from the queue to see what our response is here + Host::Command hCmd = getNextHostCmd(); + switch (hCmd) + { + case Host::Command::SoftOff: + notifySoftOff(); + oem_sel.cmd = CMD_POWER; + oem_sel.data[0] = SOFT_OFF; + break; + case Host::Command::Heartbeat: + oem_sel.cmd = CMD_HEARTBEAT; + oem_sel.data[0] = 0x00; + break; + } // All '0xFF' since unused. - memset(&soft_off.data[1], 0xFF, 3); + memset(&oem_sel.data[1], 0xFF, 3); // Pack the actual response - memcpy(response, &soft_off, *data_len); + memcpy(response, &oem_sel, *data_len); return rc; } @@ -125,6 +144,13 @@ ipmi_ret_t ipmi_app_set_bmc_global_enables(ipmi_netfn_t netfn, ipmi_cmd_t cmd, return rc; } +// Globals to keep the object alive during process life +std::unique_ptr<sdbusplus::bus::bus> sdbus = nullptr; +// TODO openbmc/openbmc#1581 - unique_ptr causes seg fault +phosphor::host::Host* host = nullptr; + + +#include <unistd.h> void register_netfn_app_functions() { @@ -144,5 +170,27 @@ void register_netfn_app_functions() ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_MSG_FLAGS, NULL, ipmi_app_get_msg_flags, SYSTEM_INTERFACE); + // Gets a hook onto SYSTEM bus used by host-ipmid + sd_bus *bus = ipmid_get_sd_bus_connection(); + + sdbus = std::make_unique<sdbusplus::bus::bus>(bus); + + // Create new xyz.openbmc_project.host object on the bus + auto objPathInst = std::string{CONTROL_HOST_OBJPATH} + '0'; + + // Add sdbusplus ObjectManager. + sdbusplus::server::manager::manager objManager(*sdbus, + objPathInst.c_str()); + + host = new phosphor::host::Host(*sdbus, + objPathInst.c_str()); + + sdbus->request_name(CONTROL_HOST_BUSNAME); + return; } + +Host::Command getNextHostCmd() +{ + return(host->getNextCommand()); +} diff --git a/systemintfcmds.h b/systemintfcmds.h index 19526f6..d603aaa 100644 --- a/systemintfcmds.h +++ b/systemintfcmds.h @@ -13,6 +13,8 @@ #define SOFT_OFF 0x00 // Major command for Any kind of power ops #define CMD_POWER 0x04 +// Major command for the heartbeat operation (verify host is alive) +#define CMD_HEARTBEAT 0xFF // IPMI commands used via System Interface functions. enum ipmi_netfn_system_intf_cmds diff --git a/xyz/openbmc_project/Control/Internal/Host.errors.yaml b/xyz/openbmc_project/Control/Internal/Host.errors.yaml new file mode 100644 index 0000000..3c14863 --- /dev/null +++ b/xyz/openbmc_project/Control/Internal/Host.errors.yaml @@ -0,0 +1,3 @@ +- name: QueueEmpty + description: The host response queue is empty and it should not be! + diff --git a/xyz/openbmc_project/Control/Internal/Host.metadata.yaml b/xyz/openbmc_project/Control/Internal/Host.metadata.yaml new file mode 100644 index 0000000..3f0b852 --- /dev/null +++ b/xyz/openbmc_project/Control/Internal/Host.metadata.yaml @@ -0,0 +1,3 @@ +- name: QueueEmpty + level: ERR + |