oem-ibm: Support system reboot after inband code update
This commit adds a bmc effecter that causes a system reboot(
phyp, chassis and bmc)
After bmc sends an end update successful event, Host will
set this new effecter. Upon getting the setStateEffecterStates
call bmc-pldm does the following:
1. Set the power restore to reboot the host once the BMC
is rebooted
2. power off Host and Chassis
3. reboot the bmc
Tested with pldmtool
Steps after patching changes:
1. Boot host to STANDBY
2. Fetch the effecter to note the effecterId
Ex: ./pldmtool platform GetPDR -d 28
3. Trigger the system reboot by toggling the effecter
./pldmtool platform SetStateEffecterStates -i 10 -c 1
-d 1 1
Signed-off-by: Sagar Srinivas <sagar.srinivas@ibm.com>
Change-Id: Id2d4201a7d61ae335adc64f2583571a37dc7879d
diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
index 2f06bc5..43e0de4 100644
--- a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
+++ b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp
@@ -120,6 +120,19 @@
// sendCodeUpdateEvent(effecterId, REJECT, END);
}
}
+ else if (entityType == PLDM_ENTITY_SYSTEM_CHASSIS &&
+ stateSetId == PLDM_OEM_IBM_SYSTEM_POWER_STATE)
+ {
+ if (stateField[currState].effecter_state == POWER_CYCLE_HARD)
+ {
+ systemRebootEvent =
+ std::make_unique<sdeventplus::source::Defer>(
+ event,
+ std::bind(std::mem_fn(&oem_ibm_platform::Handler::
+ _processSystemReboot),
+ this, std::placeholders::_1));
+ }
+ }
else
{
rc = PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE;
@@ -134,8 +147,8 @@
}
void buildAllCodeUpdateEffecterPDR(platform::Handler* platformHandler,
- uint16_t entityInstance, uint16_t stateSetID,
- pdr_utils::Repo& repo)
+ uint16_t entityType, uint16_t entityInstance,
+ uint16_t stateSetID, pdr_utils::Repo& repo)
{
size_t pdrSize = 0;
pdrSize = sizeof(pldm_state_effecter_pdr) +
@@ -156,7 +169,7 @@
pdr->hdr.length = sizeof(pldm_state_effecter_pdr) - sizeof(pldm_pdr_hdr);
pdr->terminus_handle = pdr::BmcPldmTerminusHandle;
pdr->effecter_id = platformHandler->getNextEffecterId();
- pdr->entity_type = PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE;
+ pdr->entity_type = entityType;
pdr->entity_instance = entityInstance;
pdr->container_id = 0;
pdr->effecter_semantic_id = 0;
@@ -175,6 +188,8 @@
state->states[0].byte = 6;
else if (stateSetID == PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE)
state->states[0].byte = 126;
+ else if (stateSetID == PLDM_OEM_IBM_SYSTEM_POWER_STATE)
+ state->states[0].byte = 2;
pldm::responder::pdr_utils::PdrEntry pdrEntry{};
pdrEntry.data = entry.data();
pdrEntry.size = pdrSize;
@@ -232,12 +247,18 @@
void pldm::responder::oem_ibm_platform::Handler::buildOEMPDR(
pdr_utils::Repo& repo)
{
- buildAllCodeUpdateEffecterPDR(platformHandler, ENTITY_INSTANCE_0,
- PLDM_OEM_IBM_BOOT_STATE, repo);
- buildAllCodeUpdateEffecterPDR(platformHandler, ENTITY_INSTANCE_1,
- PLDM_OEM_IBM_BOOT_STATE, repo);
- buildAllCodeUpdateEffecterPDR(platformHandler, ENTITY_INSTANCE_0,
- PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
+ buildAllCodeUpdateEffecterPDR(
+ platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0,
+ PLDM_OEM_IBM_BOOT_STATE, repo);
+ buildAllCodeUpdateEffecterPDR(
+ platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_1,
+ PLDM_OEM_IBM_BOOT_STATE, repo);
+ buildAllCodeUpdateEffecterPDR(
+ platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0,
+ PLDM_OEM_IBM_FIRMWARE_UPDATE_STATE, repo);
+ buildAllCodeUpdateEffecterPDR(platformHandler, PLDM_ENTITY_SYSTEM_CHASSIS,
+ ENTITY_INSTANCE_0,
+ PLDM_OEM_IBM_SYSTEM_POWER_STATE, repo);
buildAllCodeUpdateSensorPDR(
platformHandler, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE, ENTITY_INSTANCE_0,
@@ -329,7 +350,6 @@
uint16_t sensorId, enum sensor_event_class_states sensorEventClass,
uint8_t sensorOffset, uint8_t eventState, uint8_t prevEventState)
{
-
std::vector<uint8_t> sensorEventDataVec{};
size_t sensorEventSize = PLDM_SENSOR_EVENT_DATA_MIN_LENGTH + 1;
sensorEventDataVec.resize(sensorEventSize);
@@ -397,6 +417,80 @@
uint8_t(CodeUpdateState::END));
}
+void pldm::responder::oem_ibm_platform::Handler::_processSystemReboot(
+ sdeventplus::source::EventBase& /*source */)
+{
+ pldm::utils::PropertyValue value =
+ "xyz.openbmc_project.State.Chassis.Transition.Off";
+ pldm::utils::DBusMapping dbusMapping{"/xyz/openbmc_project/state/chassis0",
+ "xyz.openbmc_project.State.Chassis",
+ "RequestedPowerTransition", "string"};
+ try
+ {
+ dBusIntf->setDbusProperty(dbusMapping, value);
+ }
+ catch (const std::exception& e)
+ {
+
+ std::cerr << "Chassis State transition to Off failed,"
+ << "unable to set property RequestedPowerTransition"
+ << "ERROR=" << e.what() << "\n";
+ }
+
+ using namespace sdbusplus::bus::match::rules;
+ chassisOffMatch = std::make_unique<sdbusplus::bus::match::match>(
+ pldm::utils::DBusHandler::getBus(),
+ propertiesChanged("/xyz/openbmc_project/state/chassis0",
+ "xyz.openbmc_project.State.Chassis"),
+ [this](sdbusplus::message::message& msg) {
+ DbusChangedProps props{};
+ std::string intf;
+ msg.read(intf, props);
+ const auto itr = props.find("CurrentPowerState");
+ if (itr != props.end())
+ {
+ PropertyValue value = itr->second;
+ auto propVal = std::get<std::string>(value);
+ if (propVal ==
+ "xyz.openbmc_project.State.Chassis.PowerState.Off")
+ {
+ pldm::utils::DBusMapping dbusMapping{
+ "/xyz/openbmc_project/control/host0/"
+ "power_restore_policy/one_time",
+ "xyz.openbmc_project.Control.Power.RestorePolicy",
+ "PowerRestorePolicy", "string"};
+ value = "xyz.openbmc_project.Control.Power.RestorePolicy."
+ "Policy.AlwaysOn";
+ try
+ {
+ dBusIntf->setDbusProperty(dbusMapping, value);
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Setting one-time restore policy failed,"
+ << "unable to set property PowerRestorePolicy"
+ << "ERROR=" << e.what() << "\n";
+ }
+ dbusMapping = pldm::utils::DBusMapping{
+ "/xyz/openbmc_project/state/bmc0",
+ "xyz.openbmc_project.State.BMC",
+ "RequestedBMCTransition", "string"};
+ value = "xyz.openbmc_project.State.BMC.Transition.Reboot";
+ try
+ {
+ dBusIntf->setDbusProperty(dbusMapping, value);
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "BMC state transition to reboot failed,"
+ << "unable to set property "
+ "RequestedBMCTransition"
+ << "ERROR=" << e.what() << "\n";
+ }
+ }
+ }
+ });
+}
} // namespace oem_ibm_platform
} // namespace responder
} // namespace pldm