Add base support for BMC state management
This is the starting code needing to
build the application. Still more to do,
this is just the layout for the additional
commits that will be done for the state
management.
Change-Id: Ief1dc96c84b34630e60ef40c99d4faf5b6f6e02e
Signed-off-by: Josh D. King <jdking@us.ibm.com>
diff --git a/.gitignore b/.gitignore
index 9a0bf0d..54fd4f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@
/config.status
/phosphor-host-state-manager
/phosphor-chassis-state-manager
+/phosphor-bmc-state-manager
Makefile
.deps
*-libtool
diff --git a/Makefile.am b/Makefile.am
index 7e4cc20..baef5a6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,8 @@
sbin_PROGRAMS = \
phosphor-host-state-manager \
- phosphor-chassis-state-manager
+ phosphor-chassis-state-manager \
+ phosphor-bmc-state-manager
phosphor_host_state_manager_SOURCES = \
host_state_manager.cpp \
@@ -14,5 +15,11 @@
xyz.openbmc_project.State.Chassis.cpp \
chassis_state_manager_main.cpp
+phosphor_bmc_state_manager_SOURCES = \
+ bmc_state_manager.cpp \
+ xyz.openbmc_project.State.BMC.cpp \
+ bmc_state_manager_main.cpp
+
phosphor_host_state_manager_LDFLAGS = $(SYSTEMD_LIBS)
-phosphor_chassis_state_manager_LDFLAGS = $(SYSTEMD_LIBS)
\ No newline at end of file
+phosphor_chassis_state_manager_LDFLAGS = $(SYSTEMD_LIBS)
+phosphor_bmc_state_manager_LDFLAGS = $(SYSTEMD_LIBS)
diff --git a/bmc_state_manager.cpp b/bmc_state_manager.cpp
new file mode 100644
index 0000000..6eeec58
--- /dev/null
+++ b/bmc_state_manager.cpp
@@ -0,0 +1,14 @@
+#include <iostream>
+#include "bmc_state_manager.hpp"
+
+namespace phosphor
+{
+namespace state
+{
+namespace manager
+{
+
+} // namespace manager
+} // namespace state
+} // namepsace phosphor
+
diff --git a/bmc_state_manager.hpp b/bmc_state_manager.hpp
new file mode 100644
index 0000000..6b1f62d
--- /dev/null
+++ b/bmc_state_manager.hpp
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <sdbusplus/bus.hpp>
+#include "xyz/openbmc_project/State/BMC/server.hpp"
+
+namespace phosphor
+{
+namespace state
+{
+namespace manager
+{
+
+/** @class BMC
+ * @brief OpenBMC BMC state management implementation.
+ * @details A concrete implementation for xyz.openbmc_project.State.BMC
+ * DBus API.
+ */
+class BMC : public sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::State::server::BMC>
+{
+ public:
+ /** @brief Constructs BMC State Manager
+ *
+ * @param[in] bus - The Dbus bus object
+ * @param[in] busName - The Dbus name to own
+ * @param[in] objPath - The Dbus object path
+ */
+ BMC(sdbusplus::bus::bus& bus,
+ const char* objPath) :
+ sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::State::server::BMC>(
+ bus, objPath) {};
+
+};
+
+} // namespace manager
+} // namespace state
+} // namespace phosphor
diff --git a/bmc_state_manager_main.cpp b/bmc_state_manager_main.cpp
new file mode 100644
index 0000000..196522e
--- /dev/null
+++ b/bmc_state_manager_main.cpp
@@ -0,0 +1,30 @@
+#include <sdbusplus/bus.hpp>
+#include "config.h"
+#include "bmc_state_manager.hpp"
+
+
+int main(int argc, char**)
+{
+ auto bus = sdbusplus::bus::new_default();
+
+ // For now, we only have one instance of the BMC
+ // 0 is for the current instance
+ auto objPathInst = std::string(BMC_OBJPATH) + '0';
+
+ // Add sdbusplus ObjectManager.
+ sdbusplus::server::manager::manager objManager(bus, objPathInst.c_str());
+
+ phosphor::state::manager::BMC manager(bus,
+ objPathInst.c_str());
+
+ bus.request_name(BMC_BUSNAME);
+
+ while(true)
+ {
+ bus.process_discard();
+ bus.wait();
+ }
+
+ exit(EXIT_SUCCESS);
+
+}
diff --git a/configure.ac b/configure.ac
index 81a03af..e976bff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,7 +18,7 @@
AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS])
# Checks for library functions
-LT_INIT # Required for systemd linking
+LT_INIT # Removes WARNING: unrecognized options: --with-libtool-sysroot
AC_ARG_VAR(HOST_BUSNAME, [The Host Dbus busname to own])
AS_IF([test "x$HOST_BUSNAME" == "x"], [HOST_BUSNAME="xyz.openbmc_project.State.Host"])
@@ -36,6 +36,14 @@
AS_IF([test "x$CHASSIS_OBJPATH" == "x"], [CHASSIS_OBJPATH="/xyz/openbmc_project/state/chassis"])
AC_DEFINE_UNQUOTED([CHASSIS_OBJPATH], ["$CHASSIS_OBJPATH"], [The chassis state manager Dbus root])
+AC_ARG_VAR(BMC_BUSNAME, [The BMC Dbus busname to own])
+AS_IF([test "x$BMC_BUSNAME" == "x"], [BMC_BUSNAME="xyz.openbmc_project.State.BMC"])
+AC_DEFINE_UNQUOTED([BMC_BUSNAME], ["$BMC_BUSNAME"], [The BMC DBus busname to own])
+
+AC_ARG_VAR(BMC_OBJPATH, [The BMC state manager Dbus root])
+AS_IF([test "x$BMC_OBJPATH" == "x"], [BMC_OBJPATH="/xyz/openbmc_project/state/BMC"])
+AC_DEFINE_UNQUOTED([BMC_OBJPATH], ["$BMC_OBJPATH"], [The BMC state manager Dbus root])
+
# Check for header files.
AC_CHECK_HEADER(systemd/sd-bus.h, ,[AC_MSG_ERROR([Could not find systemd/sd-bus.h...systemd developement package required])])
AC_CHECK_HEADER(sdbusplus/server.hpp, ,[AC_MSG_ERROR([Could not find sdbusplus/server.hpp...openbmc/sdbusplus package required])])
diff --git a/xyz.openbmc_project.State.BMC.cpp b/xyz.openbmc_project.State.BMC.cpp
new file mode 100644
index 0000000..6495d52
--- /dev/null
+++ b/xyz.openbmc_project.State.BMC.cpp
@@ -0,0 +1,271 @@
+#include <algorithm>
+#include <sdbusplus/server.hpp>
+#include <sdbusplus/exception.hpp>
+#include <xyz/openbmc_project/State/BMC/server.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace server
+{
+
+BMC::BMC(bus::bus& bus, const char* path)
+ : _xyz_openbmc_project_State_BMC_interface(
+ bus, path, _interface, _vtable, this)
+{
+}
+
+
+
+auto BMC::requestedBMCTransition() const ->
+ Transition
+{
+ return _requestedBMCTransition;
+}
+
+int BMC::_callback_get_RequestedBMCTransition(
+ sd_bus* bus, const char* path, const char* interface,
+ const char* property, sd_bus_message* reply, void* context,
+ sd_bus_error* error)
+{
+ using sdbusplus::server::binding::details::convertForMessage;
+
+ try
+ {
+ auto m = message::message(sd_bus_message_ref(reply));
+
+ auto o = static_cast<BMC*>(context);
+ m.append(convertForMessage(o->requestedBMCTransition()));
+ }
+ catch(sdbusplus::internal_exception_t& e)
+ {
+ sd_bus_error_set_const(error, e.name(), e.description());
+ return -EINVAL;
+ }
+
+ return true;
+}
+
+auto BMC::requestedBMCTransition(Transition value) ->
+ Transition
+{
+ if (_requestedBMCTransition != value)
+ {
+ _requestedBMCTransition = value;
+ _xyz_openbmc_project_State_BMC_interface.property_changed("RequestedBMCTransition");
+ }
+
+ return _requestedBMCTransition;
+}
+
+int BMC::_callback_set_RequestedBMCTransition(
+ sd_bus* bus, const char* path, const char* interface,
+ const char* property, sd_bus_message* value, void* context,
+ sd_bus_error* error)
+{
+ try
+ {
+ auto m = message::message(sd_bus_message_ref(value));
+
+ auto o = static_cast<BMC*>(context);
+
+ std::string v{};
+ m.read(v);
+ o->requestedBMCTransition(convertTransitionFromString(v));
+ }
+ catch(sdbusplus::internal_exception_t& e)
+ {
+ sd_bus_error_set_const(error, e.name(), e.description());
+ return -EINVAL;
+ }
+
+ return true;
+}
+
+namespace details
+{
+namespace BMC
+{
+static const auto _property_RequestedBMCTransition =
+ utility::tuple_to_array(message::types::type_id<
+ std::string>());
+}
+}
+auto BMC::currentBMCState() const ->
+ BMCState
+{
+ return _currentBMCState;
+}
+
+int BMC::_callback_get_CurrentBMCState(
+ sd_bus* bus, const char* path, const char* interface,
+ const char* property, sd_bus_message* reply, void* context,
+ sd_bus_error* error)
+{
+ using sdbusplus::server::binding::details::convertForMessage;
+
+ try
+ {
+ auto m = message::message(sd_bus_message_ref(reply));
+
+ auto o = static_cast<BMC*>(context);
+ m.append(convertForMessage(o->currentBMCState()));
+ }
+ catch(sdbusplus::internal_exception_t& e)
+ {
+ sd_bus_error_set_const(error, e.name(), e.description());
+ return -EINVAL;
+ }
+
+ return true;
+}
+
+auto BMC::currentBMCState(BMCState value) ->
+ BMCState
+{
+ if (_currentBMCState != value)
+ {
+ _currentBMCState = value;
+ _xyz_openbmc_project_State_BMC_interface.property_changed("CurrentBMCState");
+ }
+
+ return _currentBMCState;
+}
+
+int BMC::_callback_set_CurrentBMCState(
+ sd_bus* bus, const char* path, const char* interface,
+ const char* property, sd_bus_message* value, void* context,
+ sd_bus_error* error)
+{
+ try
+ {
+ auto m = message::message(sd_bus_message_ref(value));
+
+ auto o = static_cast<BMC*>(context);
+
+ std::string v{};
+ m.read(v);
+ o->currentBMCState(convertBMCStateFromString(v));
+ }
+ catch(sdbusplus::internal_exception_t& e)
+ {
+ sd_bus_error_set_const(error, e.name(), e.description());
+ return -EINVAL;
+ }
+
+ return true;
+}
+
+namespace details
+{
+namespace BMC
+{
+static const auto _property_CurrentBMCState =
+ utility::tuple_to_array(message::types::type_id<
+ std::string>());
+}
+}
+
+
+namespace
+{
+/** String to enum mapping for BMC::Transition */
+static const std::tuple<const char*, BMC::Transition> mappingBMCTransition[] =
+ {
+ std::make_tuple( "xyz.openbmc_project.State.BMC.Transition.Reboot", BMC::Transition::Reboot ),
+ std::make_tuple( "xyz.openbmc_project.State.BMC.Transition.None", BMC::Transition::None ),
+ };
+
+} // anonymous namespace
+
+auto BMC::convertTransitionFromString(std::string& s) ->
+ Transition
+{
+ auto i = std::find_if(
+ std::begin(mappingBMCTransition),
+ std::end(mappingBMCTransition),
+ [&s](auto& e){ return 0 == strcmp(s.c_str(), std::get<0>(e)); } );
+ if (std::end(mappingBMCTransition) == i)
+ {
+ throw sdbusplus::exception::InvalidEnumString();
+ }
+ else
+ {
+ return std::get<1>(*i);
+ }
+}
+
+std::string convertForMessage(BMC::Transition v)
+{
+ auto i = std::find_if(
+ std::begin(mappingBMCTransition),
+ std::end(mappingBMCTransition),
+ [v](auto& e){ return v == std::get<1>(e); });
+ return std::get<0>(*i);
+}
+
+namespace
+{
+/** String to enum mapping for BMC::BMCState */
+static const std::tuple<const char*, BMC::BMCState> mappingBMCBMCState[] =
+ {
+ std::make_tuple( "xyz.openbmc_project.State.BMC.BMCState.Ready", BMC::BMCState::Ready ),
+ std::make_tuple( "xyz.openbmc_project.State.BMC.BMCState.NotReady", BMC::BMCState::NotReady ),
+ };
+
+} // anonymous namespace
+
+auto BMC::convertBMCStateFromString(std::string& s) ->
+ BMCState
+{
+ auto i = std::find_if(
+ std::begin(mappingBMCBMCState),
+ std::end(mappingBMCBMCState),
+ [&s](auto& e){ return 0 == strcmp(s.c_str(), std::get<0>(e)); } );
+ if (std::end(mappingBMCBMCState) == i)
+ {
+ throw sdbusplus::exception::InvalidEnumString();
+ }
+ else
+ {
+ return std::get<1>(*i);
+ }
+}
+
+std::string convertForMessage(BMC::BMCState v)
+{
+ auto i = std::find_if(
+ std::begin(mappingBMCBMCState),
+ std::end(mappingBMCBMCState),
+ [v](auto& e){ return v == std::get<1>(e); });
+ return std::get<0>(*i);
+}
+
+const vtable::vtable_t BMC::_vtable[] = {
+ vtable::start(),
+ vtable::property("RequestedBMCTransition",
+ details::BMC::_property_RequestedBMCTransition
+ .data(),
+ _callback_get_RequestedBMCTransition,
+ _callback_set_RequestedBMCTransition,
+ vtable::property_::emits_change),
+ vtable::property("CurrentBMCState",
+ details::BMC::_property_CurrentBMCState
+ .data(),
+ _callback_get_CurrentBMCState,
+ _callback_set_CurrentBMCState,
+ vtable::property_::emits_change),
+ vtable::end()
+};
+
+} // namespace server
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+
diff --git a/xyz/openbmc_project/State/BMC/server.hpp b/xyz/openbmc_project/State/BMC/server.hpp
new file mode 100644
index 0000000..b66fbf2
--- /dev/null
+++ b/xyz/openbmc_project/State/BMC/server.hpp
@@ -0,0 +1,132 @@
+#pragma once
+#include <tuple>
+#include <systemd/sd-bus.h>
+#include <sdbusplus/server.hpp>
+
+namespace sdbusplus
+{
+namespace xyz
+{
+namespace openbmc_project
+{
+namespace State
+{
+namespace server
+{
+
+class BMC
+{
+ public:
+ /* Define all of the basic class operations:
+ * Not allowed:
+ * - Default constructor to avoid nullptrs.
+ * - Copy operations due to internal unique_ptr.
+ * - Move operations due to 'this' being registered as the
+ * 'context' with sdbus.
+ * Allowed:
+ * - Destructor.
+ */
+ BMC() = delete;
+ BMC(const BMC&) = delete;
+ BMC& operator=(const BMC&) = delete;
+ BMC(BMC&&) = delete;
+ BMC& operator=(BMC&&) = delete;
+ virtual ~BMC() = default;
+
+ /** @brief Constructor to put object onto bus at a dbus path.
+ * @param[in] bus - Bus to attach to.
+ * @param[in] path - Path to attach at.
+ */
+ BMC(bus::bus& bus, const char* path);
+
+ enum class Transition
+ {
+ Reboot,
+ None,
+ };
+ enum class BMCState
+ {
+ Ready,
+ NotReady,
+ };
+
+
+
+ /** Get value of RequestedBMCTransition */
+ virtual Transition requestedBMCTransition() const;
+ /** Set value of RequestedBMCTransition */
+ virtual Transition requestedBMCTransition(Transition value);
+ /** Get value of CurrentBMCState */
+ virtual BMCState currentBMCState() const;
+ /** Set value of CurrentBMCState */
+ virtual BMCState currentBMCState(BMCState value);
+
+ /** @brief Convert a string to an appropriate enum value.
+ * @param[in] s - The string to convert in the form of
+ * "xyz.openbmc_project.State.BMC.<value name>"
+ * @return - The enum value.
+ */
+ static Transition convertTransitionFromString(std::string& s);
+ /** @brief Convert a string to an appropriate enum value.
+ * @param[in] s - The string to convert in the form of
+ * "xyz.openbmc_project.State.BMC.<value name>"
+ * @return - The enum value.
+ */
+ static BMCState convertBMCStateFromString(std::string& s);
+
+ private:
+
+ /** @brief sd-bus callback for get-property 'RequestedBMCTransition' */
+ static int _callback_get_RequestedBMCTransition(
+ sd_bus*, const char*, const char*, const char*,
+ sd_bus_message*, void*, sd_bus_error*);
+ /** @brief sd-bus callback for set-property 'RequestedBMCTransition' */
+ static int _callback_set_RequestedBMCTransition(
+ sd_bus*, const char*, const char*, const char*,
+ sd_bus_message*, void*, sd_bus_error*);
+
+ /** @brief sd-bus callback for get-property 'CurrentBMCState' */
+ static int _callback_get_CurrentBMCState(
+ sd_bus*, const char*, const char*, const char*,
+ sd_bus_message*, void*, sd_bus_error*);
+ /** @brief sd-bus callback for set-property 'CurrentBMCState' */
+ static int _callback_set_CurrentBMCState(
+ sd_bus*, const char*, const char*, const char*,
+ sd_bus_message*, void*, sd_bus_error*);
+
+
+ static constexpr auto _interface = "xyz.openbmc_project.State.BMC";
+ static const vtable::vtable_t _vtable[];
+ sdbusplus::server::interface::interface
+ _xyz_openbmc_project_State_BMC_interface;
+
+ Transition _requestedBMCTransition = Transition::None;
+ BMCState _currentBMCState{};
+
+};
+
+/* Specialization of sdbusplus::server::bindings::details::convertForMessage
+ * for enum-type BMC::Transition.
+ *
+ * This converts from the enum to a constant c-string representing the enum.
+ *
+ * @param[in] e - Enum value to convert.
+ * @return C-string representing the name for the enum value.
+ */
+std::string convertForMessage(BMC::Transition e);
+/* Specialization of sdbusplus::server::bindings::details::convertForMessage
+ * for enum-type BMC::BMCState.
+ *
+ * This converts from the enum to a constant c-string representing the enum.
+ *
+ * @param[in] e - Enum value to convert.
+ * @return C-string representing the name for the enum value.
+ */
+std::string convertForMessage(BMC::BMCState e);
+
+} // namespace server
+} // namespace State
+} // namespace openbmc_project
+} // namespace xyz
+} // namespace sdbusplus
+