oem ibm: infrastructure for oem handlers
1. This commit adds the framework for an oem handler
which can be used by specific oem use-cases
for implementing various commands.
2. This commit adds implementation for getStateSensorReadings
and setStateEffecterStates commands for oem state sets.
3. Also adds implementation for inband code update.
Change-Id: Ib38a66ee381dd06b93f6a9313d51de1c23e6ee65
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/oem/ibm/libpldmresponder/inband_code_update.cpp b/oem/ibm/libpldmresponder/inband_code_update.cpp
new file mode 100644
index 0000000..f17b209
--- /dev/null
+++ b/oem/ibm/libpldmresponder/inband_code_update.cpp
@@ -0,0 +1,217 @@
+#include "inband_code_update.hpp"
+
+#include "oem_ibm_handler.hpp"
+#include "xyz/openbmc_project/Common/error.hpp"
+
+#include <sdbusplus/server.hpp>
+#include <xyz/openbmc_project/Dump/NewDump/server.hpp>
+
+#include <exception>
+
+namespace pldm
+{
+
+namespace responder
+{
+using namespace oem_ibm_platform;
+
+std::string CodeUpdate::fetchCurrentBootSide()
+{
+ return currBootSide;
+}
+
+std::string CodeUpdate::fetchNextBootSide()
+{
+ return nextBootSide;
+}
+
+int CodeUpdate::setCurrentBootSide(const std::string& currSide)
+{
+ currBootSide = currSide;
+ return PLDM_SUCCESS;
+}
+
+int CodeUpdate::setNextBootSide(const std::string& nextSide)
+{
+ nextBootSide = nextSide;
+ std::string objPath{};
+ if (nextBootSide == currBootSide)
+ {
+ objPath = runningVersion;
+ }
+ else
+ {
+ objPath = nonRunningVersion;
+ }
+ if (objPath.empty())
+ {
+ std::cerr << "no nonRunningVersion present \n";
+ return PLDM_PLATFORM_INVALID_STATE_VALUE;
+ }
+
+ pldm::utils::DBusMapping dbusMapping{objPath, redundancyIntf, "Priority",
+ "uint8_t"};
+ uint8_t val = 0;
+ pldm::utils::PropertyValue value = static_cast<uint8_t>(val);
+ try
+ {
+ dBusIntf->setDbusProperty(dbusMapping, value);
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "failed to set the next boot side to " << objPath.c_str()
+ << " ERROR=" << e.what() << "\n";
+ return PLDM_ERROR;
+ }
+ return PLDM_SUCCESS;
+}
+
+void CodeUpdate::setVersions()
+{
+ static constexpr auto mapperService = "xyz.openbmc_project.ObjectMapper";
+ static constexpr auto functionalObjPath =
+ "/xyz/openbmc_project/software/functional";
+ static constexpr auto activeObjPath =
+ "/xyz/openbmc_project/software/active";
+ static constexpr auto propIntf = "org.freedesktop.DBus.Properties";
+
+ auto& bus = dBusIntf->getBus();
+
+ try
+ {
+ auto method = bus.new_method_call(mapperService, functionalObjPath,
+ propIntf, "Get");
+ method.append("xyz.openbmc_project.Association", "endpoints");
+ std::variant<std::vector<std::string>> paths;
+
+ auto reply = bus.call(method);
+ reply.read(paths);
+
+ runningVersion = std::get<std::vector<std::string>>(paths)[0];
+
+ auto method1 =
+ bus.new_method_call(mapperService, activeObjPath, propIntf, "Get");
+ method1.append("xyz.openbmc_project.Association", "endpoints");
+
+ auto reply1 = bus.call(method1);
+ reply1.read(paths);
+ for (const auto& path : std::get<std::vector<std::string>>(paths))
+ {
+ if (path != runningVersion)
+ {
+ nonRunningVersion = path;
+ break;
+ }
+ }
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "failed to make a d-bus call to Object Mapper "
+ "Association, ERROR="
+ << e.what() << "\n";
+ return;
+ }
+
+ using namespace sdbusplus::bus::match::rules;
+ captureNextBootSideChange.push_back(
+ std::make_unique<sdbusplus::bus::match::match>(
+ pldm::utils::DBusHandler::getBus(),
+ propertiesChanged(runningVersion, redundancyIntf),
+ [this](sdbusplus::message::message& msg) {
+ DbusChangedProps props;
+ std::string iface;
+ msg.read(iface, props);
+ processPriorityChangeNotification(props);
+ }));
+ fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
+ pldm::utils::DBusHandler::getBus(),
+ "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
+ "member='InterfacesAdded',path='/xyz/openbmc_project/software'",
+ [this](sdbusplus::message::message& msg) {
+ DBusInterfaceAdded interfaces;
+ sdbusplus::message::object_path path;
+ msg.read(path, interfaces);
+ for (auto& interface : interfaces)
+ {
+ if (interface.first ==
+ "xyz.openbmc_project.Software.Activation")
+ {
+ newImageId = path.str;
+ break;
+ }
+ }
+ });
+}
+
+void CodeUpdate::processPriorityChangeNotification(
+ const DbusChangedProps& chProperties)
+{
+ static constexpr auto propName = "Priority";
+ const auto it = chProperties.find(propName);
+ if (it == chProperties.end())
+ {
+ return;
+ }
+ uint8_t newVal = std::get<uint8_t>(it->second);
+ nextBootSide = (newVal == 0) ? currBootSide
+ : ((currBootSide == Tside) ? Pside : Tside);
+}
+
+void CodeUpdate::setOemPlatformHandler(
+ pldm::responder::oem_platform::Handler* handler)
+{
+ oemPlatformHandler = handler;
+}
+
+uint8_t fetchBootSide(uint16_t entityInstance, CodeUpdate* codeUpdate)
+{
+ uint8_t sensorOpState = tSideNum;
+
+ if (entityInstance == 0)
+ {
+ auto currSide = codeUpdate->fetchCurrentBootSide();
+ if (currSide == Pside)
+ {
+ sensorOpState = pSideNum;
+ }
+ }
+ else if (entityInstance == 1)
+ {
+ auto nextSide = codeUpdate->fetchNextBootSide();
+ if (nextSide == Pside)
+ {
+ sensorOpState = pSideNum;
+ }
+ }
+ else
+ {
+ sensorOpState = PLDM_SENSOR_UNKNOWN;
+ }
+
+ return sensorOpState;
+}
+
+int setBootSide(uint16_t entityInstance, uint8_t currState,
+ const std::vector<set_effecter_state_field>& stateField,
+ CodeUpdate* codeUpdate)
+{
+ int rc = PLDM_SUCCESS;
+ auto side = (stateField[currState].effecter_state == pSideNum) ? "P" : "T";
+
+ if (entityInstance == 0)
+ {
+ rc = codeUpdate->setCurrentBootSide(side);
+ }
+ else if (entityInstance == 1)
+ {
+ rc = codeUpdate->setNextBootSide(side);
+ }
+ else
+ {
+ rc = PLDM_PLATFORM_INVALID_STATE_VALUE;
+ }
+ return rc;
+}
+
+} // namespace responder
+} // namespace pldm