IPMI COMMAND: Get LED status
LED status includes system identify/amber/green status.
They are handled by led.controller and defined by Physical.interface.yaml
uint8_t status; //LED Status
//[1:0] = Reserved
//[3:2] = Status(Amber)
//[5:4] = Status(Green)
//[7:6] = System Identify
//Status definitions:
//00b = Off
//01b = Blink
//10b = On
//11b = invalid
TestBy: ipmitool raw 0x30 0xb0
Change-Id: Ifce7c037f332cbe3fafd19e4e0acd9da6e06d12b
Signed-off-by: Kuiying Wang <kuiying.wang@intel.com>
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index 4270330..01dca7d 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -29,6 +29,7 @@
cmdGetChassisIdentifier = 0x92,
cmdGetProcessorErrConfig = 0x9A,
cmdSetProcessorErrConfig = 0x9B,
+ cmdGetLEDStatus = 0xB0,
};
enum class IPMIIntelOEMReturnCodes
@@ -96,6 +97,14 @@
static constexpr const char* postCodesIntf =
"xyz.openbmc_project.State.Boot.PostCode";
+static constexpr const char* identifyLEDObjPath =
+ "/xyz/openbmc_project/led/physical/identify";
+static constexpr const char* ledIntf = "xyz.openbmc_project.Led.Physical";
+static constexpr const char* statusAmberObjPath =
+ "/xyz/openbmc_project/led/physical/status_amber";
+static constexpr const char* statusGreenObjPath =
+ "/xyz/openbmc_project/led/physical/status_green";
+
static constexpr const uint8_t noShutdownOnOCOT = 0;
static constexpr const uint8_t shutdownOnOCOT = 1;
static constexpr const uint8_t noShutdownPolicySupported = 0;
@@ -232,4 +241,5 @@
uint8_t policy;
uint8_t policySupport;
};
-#pragma pack(pop)
\ No newline at end of file
+
+#pragma pack(pop)
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 0806317..724d8e5 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -15,6 +15,7 @@
*/
#include "xyz/openbmc_project/Common/error.hpp"
+#include "xyz/openbmc_project/Led/Physical/server.hpp"
#include <ipmid/api.h>
@@ -422,7 +423,7 @@
if (*dataLen != 0)
{
phosphor::logging::log<phosphor::logging::level::ERR>(
- "oem_set_shutdown_policy: invalid input len!");
+ "oem_get_shutdown_policy: invalid input len!");
*dataLen = 0;
return IPMI_CC_REQ_DATA_LEN_INVALID;
}
@@ -494,6 +495,84 @@
return IPMI_CC_OK;
}
+namespace ledAction
+{
+using namespace sdbusplus::xyz::openbmc_project::Led::server;
+std::map<Physical::Action, uint8_t> actionDbusToIpmi = {
+ {Physical::Action::Off, 0x00},
+ {Physical::Action::On, 0x10},
+ {Physical::Action::Blink, 0x01}};
+
+std::map<uint8_t, std::string> offsetObjPath = {
+ {2, statusAmberObjPath}, {4, statusGreenObjPath}, {6, identifyLEDObjPath}};
+
+} // namespace ledAction
+
+int8_t getLEDState(sdbusplus::bus::bus& bus, const std::string& intf,
+ const std::string& objPath, uint8_t& state)
+{
+ try
+ {
+ std::string service = getService(bus, intf, objPath);
+ Value stateValue =
+ getDbusProperty(bus, service, objPath, intf, "State");
+ std::string strState =
+ sdbusplus::message::variant_ns::get<std::string>(stateValue);
+ state = ledAction::actionDbusToIpmi.at(
+ sdbusplus::xyz::openbmc_project::Led::server::Physical::
+ convertActionFromString(strState));
+ }
+ catch (sdbusplus::exception::SdBusError& e)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
+ return -1;
+ }
+ return 0;
+}
+
+ipmi_ret_t ipmiOEMGetLEDStatus(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+ ipmi_request_t request, ipmi_response_t response,
+ ipmi_data_len_t dataLen, ipmi_context_t context)
+{
+ uint8_t* resp = reinterpret_cast<uint8_t*>(response);
+ // LED Status
+ //[1:0] = Reserved
+ //[3:2] = Status(Amber)
+ //[5:4] = Status(Green)
+ //[7:6] = System Identify
+ // Status definitions:
+ // 00b = Off
+ // 01b = Blink
+ // 10b = On
+ // 11b = invalid
+ if (*dataLen != 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "oem_get_led_status: invalid input len!");
+ *dataLen = 0;
+ return IPMI_CC_REQ_DATA_LEN_INVALID;
+ }
+
+ phosphor::logging::log<phosphor::logging::level::DEBUG>("GET led status");
+ *resp = 0;
+ *dataLen = 0;
+ for (auto it = ledAction::offsetObjPath.begin();
+ it != ledAction::offsetObjPath.end(); ++it)
+ {
+ uint8_t state = 0;
+ if (-1 == getLEDState(dbus, ledIntf, it->second, state))
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "oem_get_led_status: fail to get ID LED status!");
+ return IPMI_CC_UNSPECIFIED_ERROR;
+ }
+ *resp |= state << it->first;
+ }
+
+ *dataLen = sizeof(*resp);
+ return IPMI_CC_OK;
+}
+
static void registerOEMFunctions(void)
{
phosphor::logging::log<phosphor::logging::level::INFO>(
@@ -556,6 +635,10 @@
static_cast<ipmi_cmd_t>(
IPMINetfnIntelOEMGeneralCmd::cmdGetShutdownPolicy),
NULL, ipmiOEMGetShutdownPolicy, PRIVILEGE_ADMIN);
+ ipmiPrintAndRegister(
+ netfnIntcOEMGeneral,
+ static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdGetLEDStatus),
+ NULL, ipmiOEMGetLEDStatus, PRIVILEGE_ADMIN);
return;
}