diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile.am | 11 | ||||
-rw-r--r-- | bmc_state_manager.cpp | 14 | ||||
-rw-r--r-- | bmc_state_manager.hpp | 38 | ||||
-rw-r--r-- | bmc_state_manager_main.cpp | 30 | ||||
-rw-r--r-- | configure.ac | 10 | ||||
-rw-r--r-- | xyz.openbmc_project.State.BMC.cpp | 271 | ||||
-rw-r--r-- | xyz/openbmc_project/State/BMC/server.hpp | 132 |
8 files changed, 504 insertions, 3 deletions
@@ -43,6 +43,7 @@ Makefile.in /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 @@ AM_DEFAULT_SOURCE_EXT = .cpp 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 @@ phosphor_chassis_state_manager_SOURCES = \ 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_CXX_COMPILE_STDCXX_14([noext]) 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 @@ AC_ARG_VAR(CHASSIS_OBJPATH, [The chassis state manager Dbus root]) 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 + |