433 lines
16 KiB
Diff
Executable File
433 lines
16 KiB
Diff
Executable File
From 8b6def70a95ddab05ec565db1c5437ad17423d20 Mon Sep 17 00:00:00 2001
|
|
From: "Wang.Bin" <Bin-B.Wang@luxshare-ict.com>
|
|
Date: Tue, 3 Dec 2024 21:23:28 +0800
|
|
Subject: [PATCH 10/10] Fix soft-shutdown without SEL
|
|
|
|
---
|
|
src/power_control.cpp | 275 +++++++++++++++++++++++++++++++++++-------
|
|
1 file changed, 233 insertions(+), 42 deletions(-)
|
|
|
|
diff --git a/src/power_control.cpp b/src/power_control.cpp
|
|
index 2a72473..cfe6e57 100644
|
|
--- a/src/power_control.cpp
|
|
+++ b/src/power_control.cpp
|
|
@@ -94,6 +94,22 @@ static ConfigData idButtonConfig;
|
|
static ConfigData nmiButtonConfig;
|
|
static ConfigData slotPowerConfig;
|
|
|
|
+struct LogData
|
|
+{
|
|
+ bool assert;
|
|
+ uint16_t generatorID;
|
|
+ std::vector<uint8_t> selData;
|
|
+ std::string sensorPath;
|
|
+};
|
|
+
|
|
+struct LogData acpiStatusOffSensor = {true, 0x0020, {6, 255, 255}, "null"};
|
|
+struct LogData acpiStatusOnSensor = {true, 0x0020, {0, 255, 255}, "null"};
|
|
+struct LogData osBootSensor = {true, 0x0020, {6, 255, 255}, "null"};
|
|
+struct LogData sysBootPowerUpSensor = {true, 0x0020, {0, 255, 255}, "null"};
|
|
+struct LogData sysBootHardResetSensor = {true, 0x0020, {1, 255, 255}, "null"};
|
|
+struct LogData sysBootWarmResetSensor = {true, 0x0020, {2, 255, 255}, "null"};
|
|
+struct LogData powerButtonPressedSensor = {true, 0x0020, {0, 255, 255}, "null"};
|
|
+
|
|
// map for storing list of gpio parameters whose config are to be read from x86
|
|
// power control json config
|
|
boost::container::flat_map<std::string, ConfigData*> powerSignalMap = {
|
|
@@ -578,47 +594,48 @@ static void powerStateLog(const PowerState state)
|
|
constexpr const char* selPath = "/xyz/openbmc_project/Logging/IPMI";
|
|
constexpr const char* selInterface = "xyz.openbmc_project.Logging.IPMI";
|
|
constexpr const char* selMethod = "IpmiSelAdd";
|
|
- std::string sensorPath =
|
|
- "/xyz/openbmc_project/inventory/system/board/Lux_Baseboard/ACPI_State";
|
|
+ struct LogData powerStatusSensor;
|
|
|
|
auto bus = sdbusplus::bus::new_default();
|
|
- std::string stateStr = std::string(getChassisState(state));
|
|
+
|
|
|
|
auto method =
|
|
bus.new_method_call(selService, selPath, selInterface, selMethod);
|
|
|
|
- method.append("SEL Entry");
|
|
-
|
|
- if (stateStr == "xyz.openbmc_project.State.Chassis.PowerState.On")
|
|
- {
|
|
- std::cerr << "Send Power State On SEL Log\n";
|
|
- method.append(sensorPath.c_str());
|
|
- method.append(
|
|
- std::array<uint8_t, 3>({0x00, 0xFF, 0xFF})); // S0/G0: working
|
|
- }
|
|
- else if (stateStr == "xyz.openbmc_project.State.Chassis.PowerState.Off")
|
|
- {
|
|
- std::cerr << "Send Power State Off SEL Log\n";
|
|
- method.append(sensorPath.c_str());
|
|
- method.append(
|
|
- std::array<uint8_t, 3>({0x06, 0xFF, 0xFF})); // S4/S5: soft-off
|
|
- }
|
|
- else if (stateStr == "ButtonPressed")
|
|
- {
|
|
- std::cerr << "Send Power State Button Pressed SEL Log\n";
|
|
- sensorPath = "/xyz/openbmc_project/inventory/system/board/Lux_Baseboard/Power_Button";
|
|
- method.append(sensorPath.c_str());
|
|
- method.append(
|
|
- std::array<uint8_t, 3>({0x00, 0xFF, 0xFF})); // power button pressed
|
|
- }
|
|
- else
|
|
+ switch (state)
|
|
{
|
|
- std::cerr << "Send Power State SEL Log Error\n";
|
|
- return;
|
|
+ case PowerState::on:
|
|
+ std::cout << "PowerState:: on" << std::endl;
|
|
+ powerStatusSensor = acpiStatusOnSensor;
|
|
+ break;
|
|
+ // both off and cycleOff will call acpiStatusOffSensor
|
|
+ case PowerState::off:
|
|
+ case PowerState::cycleOff:
|
|
+ std::cout << "PowerState:: off" << std::endl;
|
|
+ powerStatusSensor = acpiStatusOffSensor;
|
|
+ break;
|
|
+ case PowerState::transitionToCycleOff:
|
|
+ powerStatusSensor = sysBootHardResetSensor;
|
|
+ break;
|
|
+ case PowerState::waitForPSPowerOK:
|
|
+ powerStatusSensor = sysBootPowerUpSensor;
|
|
+ break;
|
|
+ case PowerState::checkForWarmReset:
|
|
+ powerStatusSensor = sysBootWarmResetSensor;
|
|
+ break;
|
|
+ case PowerState::powerButtonPressed:
|
|
+ powerStatusSensor = powerButtonPressedSensor;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
}
|
|
|
|
- method.append(true); // assert is true and deassert is false
|
|
- method.append(uint16_t(0x0020)); // generator ID
|
|
+ method.append("SEL Entry");
|
|
+ method.append(powerStatusSensor.sensorPath);
|
|
+ method.append(powerStatusSensor.selData);
|
|
+ method.append(
|
|
+ powerStatusSensor.assert); // assert is true and deassert is false
|
|
+ method.append(powerStatusSensor.generatorID); // generator ID
|
|
try
|
|
{
|
|
bus.call_noreply(method);
|
|
@@ -851,6 +868,7 @@ static void powerButtonPressLog()
|
|
// sd_journal_send("MESSAGE=PowerControl: power button pressed", "PRIORITY=%i",
|
|
// LOG_INFO, "REDFISH_MESSAGE_ID=%s",
|
|
// "OpenBMC.0.1.PowerButtonPressed", NULL);
|
|
+ std::cout << "power button pressed" << __LINE__ << std::endl;
|
|
powerStateLog(PowerState::powerButtonPressed);
|
|
|
|
}
|
|
@@ -1829,9 +1847,10 @@ static void currentHostStateMonitor()
|
|
pohCounterTimerStart();
|
|
// Clear the restart cause set for the next restart
|
|
clearRestartCause();
|
|
- sd_journal_send("MESSAGE=Host system DC power is on", "PRIORITY=%i",
|
|
- LOG_INFO, "REDFISH_MESSAGE_ID=%s",
|
|
- "OpenBMC.0.1.DCPowerOn", NULL);
|
|
+ std::cout << "Host system DC power is on" << __LINE__ << std::endl;
|
|
+ //sd_journal_send("MESSAGE=Host system DC power is on", "PRIORITY=%i",
|
|
+ // LOG_INFO, "REDFISH_MESSAGE_ID=%s",
|
|
+ // "OpenBMC.0.1.DCPowerOn", NULL);
|
|
}
|
|
else
|
|
{
|
|
@@ -1848,9 +1867,10 @@ static void currentHostStateMonitor()
|
|
#ifdef USE_ACBOOT
|
|
resetACBootProperty();
|
|
#endif // USE_ACBOOT
|
|
- sd_journal_send("MESSAGE=Host system DC power is off",
|
|
- "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
|
|
- "OpenBMC.0.1.DCPowerOff", NULL);
|
|
+ std::cout << "Host system DC power is off" << __LINE__ << std::endl;
|
|
+ //sd_journal_send("MESSAGE=Host system DC power is off",
|
|
+ // "PRIORITY=%i", LOG_INFO, "REDFISH_MESSAGE_ID=%s",
|
|
+ // "OpenBMC.0.1.DCPowerOff", NULL);
|
|
}
|
|
});
|
|
}
|
|
@@ -1966,6 +1986,7 @@ static void powerStateWaitForPSPowerOK(const Event event)
|
|
else
|
|
{
|
|
setPowerState(PowerState::on);
|
|
+ std::cout << "powerStateWaitForPSPowerOK" << __LINE__ << std::endl;
|
|
powerStateLog(PowerState::on);
|
|
}
|
|
break;
|
|
@@ -2018,7 +2039,6 @@ static void powerStateOff(const Event event)
|
|
else
|
|
{
|
|
setPowerState(PowerState::on);
|
|
- powerStateLog(PowerState::on);
|
|
}
|
|
break;
|
|
}
|
|
@@ -2053,6 +2073,7 @@ static void powerStateTransitionToOff(const Event event)
|
|
// Cancel any GPIO assertions held during the transition
|
|
gpioAssertTimer.cancel();
|
|
setPowerState(PowerState::off);
|
|
+ std::cout << "powerStateTransitionToOff" << __LINE__ << std::endl;
|
|
powerStateLog(PowerState::off);
|
|
break;
|
|
default:
|
|
@@ -2069,6 +2090,8 @@ static void powerStateGracefulTransitionToOff(const Event event)
|
|
case Event::psPowerOKDeAssert:
|
|
gracefulPowerOffTimer.cancel();
|
|
setPowerState(PowerState::off);
|
|
+ std::cout << "powerStateGracefulTransitionToOff power off" << __LINE__ << std::endl;
|
|
+ powerStateLog(PowerState::off);
|
|
break;
|
|
case Event::gracefulPowerOffTimerExpired:
|
|
setPowerState(PowerState::on);
|
|
@@ -2110,6 +2133,7 @@ static void powerStateCycleOff(const Event event)
|
|
else
|
|
{
|
|
setPowerState(PowerState::on);
|
|
+ std::cout << "powerStateCycleOff:power on" << __LINE__ << std::endl;
|
|
}
|
|
break;
|
|
}
|
|
@@ -2143,6 +2167,7 @@ static void powerStateTransitionToCycleOff(const Event event)
|
|
// Cancel any GPIO assertions held during the transition
|
|
gpioAssertTimer.cancel();
|
|
setPowerState(PowerState::cycleOff);
|
|
+ std::cout << "powerStateTransitionToCycleOff power off" << __LINE__ << std::endl;
|
|
powerStateLog(PowerState::cycleOff);
|
|
powerCycleTimerStart();
|
|
break;
|
|
@@ -2160,6 +2185,8 @@ static void powerStateGracefulTransitionToCycleOff(const Event event)
|
|
case Event::psPowerOKDeAssert:
|
|
gracefulPowerOffTimer.cancel();
|
|
setPowerState(PowerState::cycleOff);
|
|
+ std::cout << "powerStateGracefulTransitionToCycleOff power off" << __LINE__ << std::endl;
|
|
+ powerStateLog(PowerState::cycleOff);
|
|
powerCycleTimerStart();
|
|
break;
|
|
case Event::gracefulPowerOffTimerExpired:
|
|
@@ -2201,6 +2228,8 @@ static void powerStateCheckForWarmReset(const Event event)
|
|
case Event::psPowerOKDeAssert:
|
|
warmResetCheckTimer.cancel();
|
|
setPowerState(PowerState::off);
|
|
+ std::cout << "powerStateCheckForWarmReset power off" << __LINE__ << std::endl;
|
|
+ powerStateLog(PowerState::cycleOff);
|
|
// DC power is unexpectedly lost, beep
|
|
beep(beepPowerFail);
|
|
break;
|
|
@@ -2496,12 +2525,43 @@ static void pltRstHandler(bool pltRst)
|
|
}
|
|
}
|
|
|
|
+static void postCompleteLog()
|
|
+{
|
|
+ constexpr const char* selService = "xyz.openbmc_project.Logging.IPMI";
|
|
+ constexpr const char* selPath = "/xyz/openbmc_project/Logging/IPMI";
|
|
+ constexpr const char* selInterface = "xyz.openbmc_project.Logging.IPMI";
|
|
+ constexpr const char* selMethod = "IpmiSelAdd";
|
|
+
|
|
+ auto bus = sdbusplus::bus::new_default();
|
|
+
|
|
+ auto method =
|
|
+ bus.new_method_call(selService, selPath, selInterface, selMethod);
|
|
+
|
|
+ method.append("SEL Entry");
|
|
+ method.append(osBootSensor.sensorPath);
|
|
+ method.append(osBootSensor.selData);
|
|
+ method.append(osBootSensor.assert); // assert is true and deassert is false
|
|
+ method.append(osBootSensor.generatorID); // generator ID
|
|
+ try
|
|
+ {
|
|
+ bus.call_noreply(method);
|
|
+ }
|
|
+ catch (const sdbusplus::exception::SdBusError& ex)
|
|
+ {
|
|
+ lg2::error(
|
|
+ "Failed to call sel log {SELPATH}, {SELINTERFACE}, {SELMRTHOD}",
|
|
+ "SELPATH", selPath, "SELINTERFACE", selInterface, "SELMRTHOD",
|
|
+ selMethod);
|
|
+ }
|
|
+}
|
|
+
|
|
static void postCompleteHandler(bool state)
|
|
{
|
|
if (!state)
|
|
{
|
|
sendPowerControlEvent(Event::postCompleteAssert);
|
|
setOperatingSystemState(OperatingSystemStateStage::Inactive);
|
|
+ //postCompleteLog();
|
|
}
|
|
else
|
|
{
|
|
@@ -2510,6 +2570,107 @@ static void postCompleteHandler(bool state)
|
|
}
|
|
}
|
|
|
|
+std::optional<std::string> getDiscretePrefixFromFile()
|
|
+{
|
|
+ constexpr auto boardNameFile = "/usr/share/boardname/boardname.conf";
|
|
+ constexpr auto boardPrefix = "/xyz/openbmc_project/inventory/system/board/";
|
|
+
|
|
+ std::ifstream file(boardNameFile);
|
|
+ if (!file.is_open())
|
|
+ {
|
|
+ lg2::error("Fail to open {FILE}", "FILE", boardNameFile);
|
|
+ return std::nullopt;
|
|
+ }
|
|
+
|
|
+ std::string boardName{};
|
|
+ std::getline(file, boardName);
|
|
+ if (boardName.empty())
|
|
+ {
|
|
+ lg2::error("Fail to read {FILE}", "FILE", boardNameFile);
|
|
+ return std::nullopt;
|
|
+ }
|
|
+ lg2::info("Board name is {BOARD}", "BOARD", boardName);
|
|
+ return boardPrefix + boardName;
|
|
+}
|
|
+
|
|
+std::optional<std::vector<std::string>>
|
|
+ getSubTreePaths(sdbusplus::bus::bus& bus, const std::string& objectPath,
|
|
+ const std::string& interface)
|
|
+{
|
|
+ constexpr auto mapperBusname = "xyz.openbmc_project.ObjectMapper";
|
|
+ constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
|
|
+ constexpr auto mapperIface = "xyz.openbmc_project.ObjectMapper";
|
|
+ std::vector<std::string> paths;
|
|
+
|
|
+ auto method = bus.new_method_call(mapperBusname, mapperObjPath, mapperIface,
|
|
+ "GetSubTreePaths");
|
|
+ method.append(objectPath.c_str());
|
|
+ method.append(0); // Depth 0 to search all
|
|
+ method.append(std::vector<std::string>({interface.c_str()}));
|
|
+
|
|
+ try
|
|
+ {
|
|
+ auto reply = bus.call(method);
|
|
+ reply.read(paths);
|
|
+ return paths;
|
|
+ }
|
|
+ catch (const sdbusplus::exception::SdBusError& e)
|
|
+ {
|
|
+ lg2::error("Fail to get chassis path");
|
|
+ return std::nullopt;
|
|
+ }
|
|
+
|
|
+ return std::nullopt;
|
|
+}
|
|
+
|
|
+std::optional<std::string> getDiscreteSensorPath(const std::string& sensorName)
|
|
+{
|
|
+ static std::string discreteSensorPathPrefix{};
|
|
+ if (discreteSensorPathPrefix.empty())
|
|
+ {
|
|
+ // First try to get the path from the file
|
|
+ auto prefix = getDiscretePrefixFromFile();
|
|
+ if (prefix)
|
|
+ {
|
|
+ discreteSensorPathPrefix = *prefix;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ // If the file doesn't exist, get the path from the dbus
|
|
+ constexpr auto discreteSensorUpperPath =
|
|
+ "/xyz/openbmc_project/inventory";
|
|
+ constexpr auto discreteSensorInterface =
|
|
+ "xyz.openbmc_project.Configuration.Status";
|
|
+ auto bus = sdbusplus::bus::new_default();
|
|
+ auto sensorPaths = getSubTreePaths(bus, discreteSensorUpperPath,
|
|
+ discreteSensorInterface);
|
|
+ // if call fail or empty, return nullopt
|
|
+ if (!sensorPaths || sensorPaths.value().size() == 0)
|
|
+ {
|
|
+ return std::nullopt;
|
|
+ }
|
|
+ // if any sensor path is find, get the prefix of the path
|
|
+ // because all discrete sensor path in the inventory has the same
|
|
+ // prefix
|
|
+ for (const auto& sensorPath : sensorPaths.value())
|
|
+ {
|
|
+ discreteSensorPathPrefix =
|
|
+ sensorPath.substr(0, sensorPath.find_last_of('/'));
|
|
+ break;
|
|
+ }
|
|
+ if (discreteSensorPathPrefix.empty())
|
|
+ {
|
|
+ return std::nullopt;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ std::string path = discreteSensorPathPrefix;
|
|
+ path.append("/");
|
|
+ path.append(sensorName);
|
|
+ return path;
|
|
+}
|
|
+
|
|
static int loadConfigValues()
|
|
{
|
|
const std::string configFilePath =
|
|
@@ -2661,6 +2822,33 @@ static int loadConfigValues()
|
|
nmiWhenPoweredOff = events.value("NMIWhenPoweredOff", true);
|
|
}
|
|
|
|
+ auto acpiSensorPath = getDiscreteSensorPath("ACPI_State");
|
|
+ if (acpiSensorPath != std::nullopt)
|
|
+ {
|
|
+ acpiStatusOnSensor.sensorPath = acpiSensorPath.value();
|
|
+ acpiStatusOffSensor.sensorPath = acpiSensorPath.value();
|
|
+ }
|
|
+
|
|
+ auto sysbootSensorPath = getDiscreteSensorPath("SYS_Boot");
|
|
+ if (sysbootSensorPath != std::nullopt)
|
|
+ {
|
|
+ sysBootPowerUpSensor.sensorPath = sysbootSensorPath.value();
|
|
+ sysBootHardResetSensor.sensorPath = sysbootSensorPath.value();
|
|
+ sysBootWarmResetSensor.sensorPath = sysbootSensorPath.value();
|
|
+ }
|
|
+
|
|
+ auto osbootSensorPath = getDiscreteSensorPath("OS_Boot");
|
|
+ if (osbootSensorPath != std::nullopt)
|
|
+ {
|
|
+ osBootSensor.sensorPath = osbootSensorPath.value();
|
|
+ }
|
|
+
|
|
+ auto powerbuttonSensorPath = getDiscreteSensorPath("Power_Button");
|
|
+ if (powerbuttonSensorPath != std::nullopt)
|
|
+ {
|
|
+ powerButtonPressedSensor.sensorPath = powerbuttonSensorPath.value();
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -2840,7 +3028,7 @@ void reschedulePropertyRead(const ConfigData& configData)
|
|
}
|
|
});
|
|
}
|
|
-
|
|
+bool bmcReset = true;
|
|
static void ACPIStateSel(void)
|
|
{
|
|
const static constexpr int TimeMs = 20000;
|
|
@@ -2856,8 +3044,11 @@ static void ACPIStateSel(void)
|
|
ec.message());
|
|
}
|
|
}
|
|
- lg2::info("ACPI State sel");
|
|
- powerStateLog(powerState);
|
|
+ std::cout << "BMC reboot:power state" << __LINE__ << std::endl;
|
|
+ if (bmcReset == true){
|
|
+ powerStateLog(powerState);
|
|
+ }
|
|
+ bmcReset = false;
|
|
});
|
|
|
|
}
|
|
--
|
|
2.25.1
|
|
|