Initial commit

This commit is contained in:
Your Name
2026-04-23 17:07:55 +08:00
commit b7e39e063b
16725 changed files with 1625565 additions and 0 deletions
@@ -0,0 +1 @@
PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin
@@ -0,0 +1,9 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += "file://defaut-env.sh"
do_install:append(){
install -d ${D}/${sysconfdir}/profile.d/
install -m 0755 ${S}/defaut-env.sh ${D}/${sysconfdir}/profile.d/
}
@@ -0,0 +1,24 @@
SUMMARY = "factory-reset-reboot"
DESCRIPTION = "factory reset reboot delay"
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
RDEPENDS:${PN} += "bash"
PR = "r1"
LICENSE = "CLOSED"
inherit allarch
SRC_URI = " \
file://obmc-reboot-delay \
file://obmc-reboot-delay.service \
"
inherit obmc-phosphor-systemd
SYSTEMD_SERVICE:${PN} += "obmc-reboot-delay.service"
do_install() {
install -d ${D}${bindir}
install -m 0755 ${WORKDIR}/obmc-reboot-delay ${D}${bindir}
}
@@ -0,0 +1,13 @@
#!/bin/bash
set -e
STATE_SERVICE="xyz.openbmc_project.State.BMC"
STATE_PATH="/xyz/openbmc_project/state/bmc0"
STATE_INTERFACE="xyz.openbmc_project.State.BMC"
STATE_PROPERTY="RequestedBMCTransition"
STATE_PROPERTY_VALUE="xyz.openbmc_project.State.BMC.Transition.Reboot"
echo "sleep 5"
sleep 5
busctl set-property "${STATE_SERVICE}" "${STATE_PATH}" "${STATE_INTERFACE}" \
"${STATE_PROPERTY}" s "${STATE_PROPERTY_VALUE}"
@@ -0,0 +1,7 @@
[Unit]
Description=BMC reboot delay
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/usr/bin/obmc-reboot-delay
@@ -0,0 +1,10 @@
IMAGE_INSTALL += " ipmitool \
webui-vue \
callback-manager \
system-watchdog \
ipmi-oem \
ipmi-standard-override \
i3c-tools \
factory-reset-reboot \
clear-once \
"
@@ -0,0 +1,23 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
LICENSE = "CLOSED"
SUMMARY = "IPMI OEM Commands"
TARGET_CC_ARCH += "${LDFLAGS}"
SRC_URI += " file://ipmi-oem.hpp file://ipmi-oem.cpp file://meson.build "
SRCREV = "${AUTOREV}"
PR = "r1"
S = "${WORKDIR}"
DEPENDS = " boost sdbusplus phosphor-ipmi-host phosphor-dbus-interfaces phosphor-logging i2c-tools"
RDEPENDS:${PN} += " phosphor-ipmi-host"
inherit pkgconfig obmc-phosphor-ipmiprovider-symlink meson
HOSTIPMI_PROVIDER_LIBRARY += "libipmioem.so"
FILES:${PN}:append = " ${libdir}/host-ipmid/lib*${SOLIBS}"
FILES:${PN}:append = " ${libdir}/ipmid-providers/lib*${SOLIBS}"
FILES:${PN}:append = " ${libdir}/net-ipmid/lib*${SOLIBS}"
FILES:${PN}-dev:append = " ${libdir}/ipmid-providers/lib*${SOLIBSDEV} ${libdir}/ipmid-providers/*.la"
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,141 @@
#include <ipmid/api-types.hpp>
#include <ipmid/api.hpp>
#include <ipmid/message.hpp>
#include <ipmid/utils.hpp>
#include <sdbusplus/message/types.hpp>
typedef struct {
uint8_t socket_id;
uint8_t channel_id;
uint8_t dimm_id;
uint8_t temp_integer;
uint8_t temp_decimal;
/*Memory temperature infomation(unit °C)*/
}memory_info_t;
#pragma pack(1)
enum class DataType {
TEMPERATURE,
CURRENT,
POWER,
VOLTAGE,
STATUS
};
enum class TempSensor {
TS0,
TS1,
SPD_TS,
MAX_TS01
};
enum class ReqId {
TS0 = 0,
TS1 = 1,
SPD_TEMP = 2,
MAX_TEMP = 3,
VOLTAGE = 4,
CURRENT = 5,
STATUS_REG = 6
};
enum class RailChannel {
SWA,
SWB,
SWC,
SWD,
SWE,
SWF
};
enum class StatusReg {
REG_04 = 0x04,
REG_05 = 0x05,
REG_06 = 0x06,
REG_07 = 0x07,
REG_08 = 0x08,
REG_09 = 0x09,
REG_0A = 0x0A,
REG_0B = 0x0B
};
typedef struct {
int8_t int_part;
uint8_t frac_part;
} dimm_temp_sensor_t;
typedef struct {
int8_t TS0_int;
uint8_t TS0_frac;
int8_t TS1_int;
uint8_t TS1_frac;
int8_t SPD_int;
uint8_t SPD_frac;
} dimm_temp_t;
typedef struct {
uint16_t SWA;
uint16_t SWB;
uint16_t SWC;
uint16_t SWD;
uint16_t SWE;
uint16_t SWF;
} dimm_rail_t;
typedef struct {
uint8_t dimmId;
dimm_temp_t dimmTemp;
dimm_rail_t dimmVolt;
dimm_rail_t dimmCur;
dimm_rail_t dimmPow;
} oem_dimm_info_t;
#pragma pack()
#define MAX_FSC_PWM_CHANNEL 29
#define FSC_FAN_TABLE_AUTO 0
#define FSC_FAN_TABLE_MANUAL 1
typedef struct
{
uint8_t u8ControlMode;
uint8_t u8PWM[MAX_FSC_PWM_CHANNEL];
}SFscControlMode;
namespace ipmi {
constexpr Iana oemIANA =
56799; // 0x00dddf https://www.iana.org/assignments/enterprise-numbers/?page=568
constexpr int prioOem = ipmi::prioMax;
constexpr NetFn netFnOemSelf = ipmi::netFnOemFour; // NetFn is 0x36
namespace ipmiOem {
constexpr Cmd cmdGetDeviceFWVersion = 0x01;
constexpr Cmd cmdSetFanSpeedControlMode = 0x04;
constexpr Cmd cmdGetFanSpeedControlMode = 0x05;
constexpr Cmd cmdSetBIOSPasswordConfig = 0x0E;
constexpr Cmd cmdGetBIOSPasswordConfig = 0x0F;
constexpr Cmd cmdGetPSUInfo = 0x20;
constexpr Cmd cmdSwitchBMCFw = 0x23;
constexpr Cmd cmdGetSetBiosVer = 0x34;
constexpr Cmd cmdRestoreFactoryDefault = 0x35;
constexpr Cmd cmdSetSOLBitrate = 0x36;
constexpr Cmd cmdGet12VPSUADCValue = 0x60;
constexpr Cmd cmdSet12VPSUADCValue = 0x61;
constexpr Cmd cmdDIMMTemperatureValue = 0x62;
constexpr Cmd cmdSetDIMMSetPoint = 0x63;
constexpr Cmd cmdGetDIMMSetPoint = 0x64;
constexpr Cmd cmdSetCoverStatus = 0x65;
constexpr Cmd cmdGetCoverStatus = 0x66;
constexpr Cmd cmdSetCoverPreHeatTemperature = 0x67;
constexpr Cmd cmdGetCoverPreHeatTemperature = 0x68;
constexpr Cmd cmdBiosSetDimmState = 0x69;
constexpr Cmd cmdBiosSetDimmPara = 0x6a;
constexpr Cmd cmdBiosGetDimmPara = 0x6b;
constexpr Cmd cmdGetDimmTemp = 0x6c;
constexpr Cmd cmdGetCoverCurrentTemp = 0x6d;
constexpr Cmd cmdSetCoverFSCEnableStatus = 0x6e;
constexpr Cmd cmdGetCoverFSCEnableStatus = 0x6f;
constexpr Cmd cmdOemI2CReadWrite = 0xA4;
constexpr Cc ccOemInvalidIANA = 0x80;
} // namespace ipmiOem
} // namespace ipmi
@@ -0,0 +1,65 @@
project(
'ipmi-oem',
'cpp',
version: '0.1',
meson_version: '>=1.1.1',
default_options: [
'werror=true',
'warning_level=3',
'cpp_std=c++23',
])
root = meson.current_source_dir()
root_inc = include_directories('.')
cpp = meson.get_compiler('cpp')
# i2c-tools doesn't ship a pkg-config file for libi2c
i2c = cpp.find_library('i2c')
add_project_arguments(
cpp.get_supported_arguments([
'-DBOOST_ERROR_CODE_HEADER_ONLY',
'-DBOOST_SYSTEM_NO_DEPRECATED',
'-DBOOST_COROUTINES_NO_DEPRECATION_WARNING',
'-DBOOST_ASIO_DISABLE_THREADS',
'-DBOOST_ALL_NO_LIB',
]),
language : 'cpp')
add_project_arguments(
cpp.get_supported_arguments([
'-Wno-psabi',
'-Wno-missing-field-initializers',
'-Wno-pedantic',
'-Wno-non-virtual-dtor'
]),
language: 'cpp')
phosphor_logging_dep = dependency('phosphor-logging')
phosphor_dbus_interfaces_dep = dependency('phosphor-dbus-interfaces')
systemd = dependency('systemd')
boost_coroutine = cpp.find_library('boost_coroutine', required: true)
sdbusplus_dep = dependency('sdbusplus')
ipmid_dep = dependency('libipmid')
libs = declare_dependency(
include_directories: root_inc,
dependencies: [
phosphor_dbus_interfaces_dep,
phosphor_logging_dep,
sdbusplus_dep,
ipmid_dep,
systemd,
i2c
])
ipmi_oem_lib = library(
'ipmioem',
'ipmi-oem.cpp',
implicit_include_directories: false,
dependencies: libs,
version: meson.project_version(),
override_options: ['b_lundef=false'],
install: true,
install_dir: get_option('libdir') / 'ipmid-providers')
@@ -0,0 +1,18 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
LICENSE = "CLOSED"
SUMMARY = "Override Standard IPMI Commands"
TARGET_CC_ARCH += "${LDFLAGS}"
SRC_URI += " file://ipmi-standard-override.hpp file://ipmi-override-app.cpp file://meson.build "
SRCREV = "${AUTOREV}"
PR = "r1"
S = "${WORKDIR}"
DEPENDS = " boost sdbusplus phosphor-ipmi-host "
RDEPENDS:${PN} += " phosphor-ipmi-host"
inherit pkgconfig obmc-phosphor-ipmiprovider-symlink meson
HOSTIPMI_PROVIDER_LIBRARY += "libipmioverride.so"
FILES:${PN}:append = " ${libdir}/host-ipmid/lib*${SOLIBS}"
FILES:${PN}:append = " ${libdir}/ipmid-providers/lib*${SOLIBS}"
FILES:${PN}:append = " ${libdir}/net-ipmid/lib*${SOLIBS}"
FILES:${PN}-dev:append = " ${libdir}/ipmid-providers/lib*${SOLIBSDEV} ${libdir}/ipmid-providers/*.la"
@@ -0,0 +1,37 @@
#include "ipmi-standard-override.hpp"
void register_ipmi_override_functions() __attribute__((constructor));
auto ipmiAppGetSelfTestResultsOverride() -> ipmi::RspType<uint8_t, uint8_t> {
// Byte 2:
// 55h - No error.
// 56h - Self Test function not implemented in this controller.
// 57h - Corrupted or inaccesssible data or devices.
// 58h - Fatal hardware error.
// FFh - reserved.
// all other: Device-specific 'internal failure'.
// Byte 3:
// For byte 2 = 55h, 56h, FFh: 00h
// For byte 2 = 58h, all other: Device-specific
// For byte 2 = 57h: self-test error bitfield.
// Note: returning 57h does not imply that all test were run.
// [7] 1b = Cannot access SEL device.
// [6] 1b = Cannot access SDR Repository.
// [5] 1b = Cannot access BMC FRU device.
// [4] 1b = IPMB signal lines do not respond.
// [3] 1b = SDR Repository empty.
// [2] 1b = Internal Use Area of BMC FRU corrupted.
// [1] 1b = controller update 'boot block' firmware corrupted.
// [0] 1b = controller operational firmware corrupted.
constexpr uint8_t noError = 0x55;
constexpr uint8_t bmcOK = 0x55;
return ipmi::responseSuccess(noError, bmcOK);
}
void register_ipmi_override_functions() {
// <Get Self Test Results>
ipmi::registerHandler(ipmi::prioOverride, ipmi::netFnApp,
ipmi::app::cmdGetSelfTestResults, ipmi::Privilege::User,
ipmiAppGetSelfTestResultsOverride);
}
@@ -0,0 +1,9 @@
#include <ipmid/api.hpp>
#include <ipmid/message.hpp>
#include <ipmid/utils.hpp>
#include <sdbusplus/message/types.hpp>
namespace ipmi {
constexpr int prioOverride = ipmi::prioMax;
namespace ipmiOverride {} // namespace ipmiOverride
} // namespace ipmi
@@ -0,0 +1,60 @@
project(
'ipmi-oem',
'cpp',
version: '0.1',
meson_version: '>=1.1.1',
default_options: [
'werror=true',
'warning_level=3',
'cpp_std=c++23',
])
root = meson.current_source_dir()
root_inc = include_directories('.')
cpp = meson.get_compiler('cpp')
add_project_arguments(
cpp.get_supported_arguments([
'-DBOOST_ERROR_CODE_HEADER_ONLY',
'-DBOOST_SYSTEM_NO_DEPRECATED',
'-DBOOST_COROUTINES_NO_DEPRECATION_WARNING',
'-DBOOST_ASIO_DISABLE_THREADS',
'-DBOOST_ALL_NO_LIB',
]),
language : 'cpp')
add_project_arguments(
cpp.get_supported_arguments([
'-Wno-psabi',
'-Wno-missing-field-initializers',
'-Wno-pedantic',
'-Wno-non-virtual-dtor'
]),
language: 'cpp')
phosphor_logging_dep = dependency('phosphor-logging')
phosphor_dbus_interfaces_dep = dependency('phosphor-dbus-interfaces')
systemd = dependency('systemd')
boost_coroutine = cpp.find_library('boost_coroutine', required: true)
sdbusplus_dep = dependency('sdbusplus')
ipmid_dep = dependency('libipmid')
libs = declare_dependency(
include_directories: root_inc,
dependencies: [
phosphor_dbus_interfaces_dep,
phosphor_logging_dep,
sdbusplus_dep,
ipmid_dep,
systemd
])
ipmi_override_lib = library(
'ipmioverride',
'ipmi-override-app.cpp',
implicit_include_directories: false,
dependencies: libs,
version: meson.project_version(),
override_options: ['b_lundef=false'],
install: true,
install_dir: get_option('libdir') / 'ipmid-providers')
@@ -0,0 +1,26 @@
From 0852966f5ef9821c291007cfedf7e744d8577215 Mon Sep 17 00:00:00 2001
From: hliangs90 <hliangs90@gmail.com>
Date: Fri, 23 Aug 2024 21:55:31 +0800
Subject: [PATCH] Modify OEM Command to 0x36 to support IANA register
Signed-off-by: hliangs90 <hliangs90@gmail.com>
---
ipmid-new.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ipmid-new.cpp b/ipmid-new.cpp
index 2a78c68..8f5cd32 100644
--- a/ipmid-new.cpp
+++ b/ipmid-new.cpp
@@ -318,7 +318,7 @@ message::Response::ptr executeIpmiCommand(message::Request::ptr request)
{
return executeIpmiGroupCommand(request);
}
- else if (netFnOem == netFn)
+ else if (netFnOemFour == netFn || netFn == netFnOem)
{
return executeIpmiOemCommand(request);
}
--
2.25.1
@@ -0,0 +1,30 @@
From 7305120634cef58af46e98b81418a38a753ffaf5 Mon Sep 17 00:00:00 2001
From: hliangs90 <hliangs90@gmail.com>
Date: Sat, 24 Aug 2024 02:57:40 +0800
Subject: [PATCH] Remove INAN Header In IPMI Response For OEM Command Support
Signed-off-by: hliangs90 <hliangs90@gmail.com>
---
ipmid-new.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/ipmid-new.cpp b/ipmid-new.cpp
index 8f5cd32..baa6a19 100644
--- a/ipmid-new.cpp
+++ b/ipmid-new.cpp
@@ -305,9 +305,9 @@ message::Response::ptr executeIpmiOemCommand(message::Request::ptr request)
auto iana = static_cast<Iana>(bytes);
message::Response::ptr response = executeIpmiCommandCommon(oemHandlerMap,
iana, request);
- ipmi::message::Payload prefix;
- prefix.pack(bytes);
- response->prepend(prefix);
+ // ipmi::message::Payload prefix;
+ // prefix.pack(bytes);
+ // response->prepend(prefix);
return response;
}
--
2.25.1
@@ -0,0 +1,4 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += " file://0001-Modify-OEM-Command-to-0x36-to-support-IANA-register.patch \
file://0002-Remove-INAN-Header-In-IPMI-Response-For-OEM-Command-.patch "
@@ -0,0 +1,82 @@
From 573d74d5938907e5c7c110997b1fedac716b0a6c Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Thu, 17 Oct 2024 13:28:54 +0800
Subject: [PATCH] Add DIMM Status discrete sensors
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
fault-monitor/fru-fault-monitor.cpp | 17 +++++++++++------
fault-monitor/fru-fault-monitor.hpp | 2 +-
2 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index d5d6703..8ff5294 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -360,7 +360,7 @@ void fillSensorDescription(const std::string& sensorPath, int eventOffset)
//}
}
-AlarmType parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
+void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
const std::string& sensorPath,
const SensorType& sensorType,
const std::string& eventData,
@@ -384,7 +384,7 @@ AlarmType parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
}
default:
{
- return alarmStatus;
+ return;
}
}
break;
@@ -405,13 +405,18 @@ AlarmType parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
{
alarmStatus = NORMAL;
}
- return alarmStatus;
+ return;
}
}
break;
}
+ case SENSOR_TYPE_MEMORY:
+ {
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+ break;
+ }
default:
- return alarmStatus;
+ return;
}
sensorStatusRec[sensorPath].eventType = SPECIFIC_SENSOR_TYPE;
sensorStatusRec[sensorPath].sensorType = sensorType;
@@ -420,9 +425,9 @@ AlarmType parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
{
fillSensorDescription(sensorPath, ev1Offset);
setDiscreteSensorDiscription(bus, sensorPath);
- setDiscreteSensorHealth(bus, sensorPath);
+ setDiscreteSensorHealth(bus, sensorPath);
}
- return alarmStatus;
+ return;
}
diff --git a/fault-monitor/fru-fault-monitor.hpp b/fault-monitor/fru-fault-monitor.hpp
index 652fefa..e196287 100644
--- a/fault-monitor/fru-fault-monitor.hpp
+++ b/fault-monitor/fru-fault-monitor.hpp
@@ -34,7 +34,7 @@ enum SensorType
{
SENSOR_TYPE_EVENT_LOGGING_DISABLED = 0x10,
SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE = 0x22,
-
+ SENSOR_TYPE_MEMORY = 0x0C,
SENSOR_TYPE_MAX_NUMBER = 0x100 // Senor Type 为1个byte,最大为0~255,即:256个
};
--
2.34.1
@@ -0,0 +1,27 @@
From 9560938ad1542c78d977672960bc4e2a90bfb696 Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Thu, 31 Oct 2024 10:59:57 +0800
Subject: [PATCH] Add PROCESSOR sensor type
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
fault-monitor/fru-fault-monitor.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index 2e99e45..fffb6f7 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -678,6 +678,11 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
setDimmLEDState(bus, sensorPath, "FAULT");
break;
}
+ case SENSOR_TYPE_PROCESSOR:
+ {
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+ break;
+ }
default:
break;
}
@@ -0,0 +1,601 @@
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index e6b6a61..3c63735 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -5,7 +5,9 @@
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/exception.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
-
+#include <string>
+#include <vector>
+#include <iostream>
namespace phosphor
{
namespace led
@@ -24,7 +26,9 @@ static constexpr auto mapperObjPath = "/xyz/openbmc_project/object_mapper";
static constexpr auto mapperIntf = "xyz.openbmc_project.ObjectMapper";
static constexpr auto objMgrIntf = "org.freedesktop.DBus.ObjectManager";
static constexpr auto ledGroups = "/xyz/openbmc_project/led/groups/";
+static constexpr auto logPath = "/xyz/openbmc_project/logging";
static constexpr auto logIntf = "xyz.openbmc_project.Logging.Entry";
+static constexpr auto logService = "xyz.openbmc_project.Logging";
using AssociationList =
std::vector<std::tuple<std::string, std::string, std::string>>;
@@ -46,6 +50,96 @@ using ResourceNotFoundErr =
using InvalidArgumentErr =
sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
+constexpr const char* discreteSensorNs = "No state defined";
+
+// 10H
+constexpr auto SYSTEM_EVENT_LOG_CLEARED = 2;
+
+// 22H
+constexpr auto ACPI_S0_STATE = 0;
+constexpr auto ACPI_S5_STATE = 6;
+
+/*sensor object, SensorStatusInfo*/
+std::unordered_map<std::string, SensorStatusInfo> sensorStatusRec;
+std::unordered_map<std::string, std::unordered_map<uint8_t, DriveStatus>> driveStatusRec;
+
+enum AlarmType
+{
+ NORMAL = 0,
+ NONCRITICAL = 1,
+ CRITICAL = 2,
+ NONRECOV = 4,
+};
+
+struct SelSeverityInfo
+{
+ std::string sensorPath;
+ SensorType sensorType;
+ uint8_t eventType;
+ std::string eventData;
+ std::string eventDir;
+ AlarmType severity;
+ bool assertToAlarm;
+};
+std::unordered_map<Path, std::vector<SelSeverityInfo>> getPathfailedRec;
+
+
+constexpr auto SENSOR_EVENT_DATA1_EVENT_OFFSET = 0x0F;
+
+const std::unordered_map<uint64_t, std::string> healthStr{
+ {0, "Ok"},
+ {1, "Warning"},
+ {2, "Critical"},
+ {4, "Critical"},
+};
+
+using discrectSensorEvent = std::unordered_map<uint8_t, std::string>;
+
+using AdditionalList = std::vector<std::string>;
+using sensorCodes = std::vector<uint8_t>;
+using ipmiSensorsInfo = std::unordered_map<std::string, sensorCodes>;
+std::optional<ipmiSensorsInfo> ipmiSensors;
+
+const std::unordered_map<SensorType, discrectSensorEvent> sensorSpecificTypes{
+ {SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE,
+ {
+ {ACPI_S0_STATE, "S0/G0: working"},
+ {ACPI_S5_STATE, "S4/S5: soft-off"},
+ }},
+ {SENSOR_TYPE_EVENT_LOGGING_DISABLED,
+ {
+ {SYSTEM_EVENT_LOG_CLEARED, "Log area reset/cleared"},
+ }}
+};
+
+std::optional<ipmiSensorsInfo> initIPMISensorInfo(sdbusplus::bus::bus& bus)
+{
+ constexpr auto service = "xyz.openbmc_project.Ipmi.Host";
+ constexpr auto obj = "/xyz/openbmc_project/Ipmi/SensorInfo";
+ constexpr auto interface = "xyz.openbmc_project.IPMI.SensorInfo";
+ constexpr auto property = "SensorInfo";
+
+ std::variant<ipmiSensorsInfo> propertyValue{};
+
+ auto method = bus.new_method_call(service, obj,
+ "org.freedesktop.DBus.Properties", "Get");
+ method.append(interface, property);
+
+ try
+ {
+ auto reply = bus.call(method);
+ reply.read(propertyValue);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ lg2::error("Failed to get ipmi sensor info, ERROR = {ERROR}", "ERROR",
+ e);
+ return {};
+ }
+
+ return std::make_optional(std::get<ipmiSensorsInfo>(propertyValue));
+}
+
std::string getService(sdbusplus::bus_t& bus, const std::string& path)
{
auto mapper = bus.new_method_call(mapperBusName, mapperObjPath, mapperIntf,
@@ -76,6 +170,102 @@ std::string getService(sdbusplus::bus_t& bus, const std::string& path)
return mapperResponse.cbegin()->first;
}
+static void setDiscreteSensorStatusValue(sdbusplus::bus::bus& bus,
+ const std::string& sensorPath,const std::string& sensorData)
+{
+ // IPMI spec Table 35-15
+ // For discrete reading sensors only. (Optional)
+ // [7] - reserved. Returned as 1b. Ignore on read.
+ uint16_t reserved = 0x8000;
+
+ // ipmi spec 42.2 set the sensor-specific offset
+ double statusValue = reserved;
+
+ constexpr auto service = "xyz.openbmc_project.dissen";
+ constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
+ constexpr auto statusInterface = "xyz.openbmc_project.Configuration.Status";
+
+ unsigned long dataValue = strtoul(sensorData.c_str(), NULL, 16);
+ statusValue = static_cast<double>(statusValue +
+ (0x01 << ((dataValue & 0x0f0000) >> 16)));
+ auto method = bus.new_method_call(service, sensorPath.c_str(),
+ dbusProperties, "Set");
+ std::variant<double> value{(double)statusValue};
+
+ method.append(statusInterface, "Status", value);
+ try
+ {
+ bus.call_noreply(method);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ lg2::info("Error setting discrete sensor status, ERROR = {ERROR}",
+ "ERROR", e);
+ }
+
+ return;
+}
+
+static void setDiscreteSensorDiscription(sdbusplus::bus::bus& bus,
+ const std::string& sensorPath)
+{
+ constexpr auto service = "xyz.openbmc_project.EntityManager";
+ constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
+ constexpr auto statusInterface = "xyz.openbmc_project.Configuration.Status";
+ auto description = sensorStatusRec[sensorPath].description;
+ // set discrete sensor description
+ auto method = bus.new_method_call(service, sensorPath.c_str(),
+ dbusProperties, "Set");
+ std::variant<std::string> value{description};
+
+ method.append(statusInterface, "Description", value);
+ try
+ {
+ bus.call_noreply(method);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ lg2::info("Error setting discrete sensor description, ERROR = {ERROR}",
+ "ERROR", e);
+ }
+
+ return;
+}
+
+static void setDiscreteSensorHealth(sdbusplus::bus::bus& bus,
+ const std::string& sensorPath)
+{
+ constexpr auto service = "xyz.openbmc_project.EntityManager";
+ constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
+ constexpr auto statusInterface = "xyz.openbmc_project.Configuration.Status";
+
+ // convert alarmStatus to string
+ std::string health = "ns";
+ auto it = healthStr.find(sensorStatusRec[sensorPath].alarmStatus);
+ if (it != healthStr.end())
+ {
+ health = it->second;
+ }
+
+ // set discrete sensor health
+ auto method = bus.new_method_call(service, sensorPath.c_str(),
+ dbusProperties, "Set");
+ std::variant<std::string> value{health};
+
+ method.append(statusInterface, "Health", value);
+ try
+ {
+ bus.call_noreply(method);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ lg2::info("Error setting discrete sensor health, ERROR = {ERROR}",
+ "ERROR", e);
+ }
+
+ return;
+}
+
void action(sdbusplus::bus_t& bus, const std::string& path, bool assert)
{
std::string service;
@@ -124,6 +314,232 @@ void action(sdbusplus::bus_t& bus, const std::string& path, bool assert)
return;
}
+enum
+{
+ UNSPECIFY_SENSOR_TYPE = 0x00,
+ THRESHOLD_SENSOR_TYPE = 0x01,
+ GENERIC_S_SENSOR_TYPE = 0x02,
+ GENERIC_E_SENSOR_TYPE = 0x0C,
+ SPECIFIC_SENSOR_TYPE = 0x6F,
+ OEM_S_SENSOR_TYPE = 0x70,
+ OEM_E_SENSOR_TYPE = 0x7F
+};
+
+void fillSensorDescription(const std::string& sensorPath, int eventOffset)
+{
+ sensorStatusRec[sensorPath].description = discreteSensorNs;
+ // find event description for generic type
+ //auto eventType = sensorStatusRec[sensorPath].eventType;
+ // if (eventType != SPECIFIC_SENSOR_TYPE)
+ // {
+ // auto it = genericEventTypes.find(eventType);
+ // if (it != genericEventTypes.end())
+ // {
+ // auto eventType = it->second;
+ // auto health = eventType.find(eventOffset);
+ // if (health != eventType.end())
+ // {
+ // sensorStatusRec[sensorPath].description = health->second;
+ // }
+ // }
+ // }
+ // else
+ //{
+ // find event description for sensor specific type
+ auto it =
+ sensorSpecificTypes.find(sensorStatusRec[sensorPath].sensorType);
+ if (it != sensorSpecificTypes.end())
+ {
+ auto eventType = it->second;
+ auto health = eventType.find(eventOffset);
+ if (health != eventType.end())
+ {
+ sensorStatusRec[sensorPath].description = health->second;
+ }
+ }
+ //}
+}
+
+AlarmType parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
+ const std::string& sensorPath,
+ const SensorType& sensorType,
+ const std::string& eventData,
+ const std::string& eventDir)
+{
+ std::string eventData1 = eventData.substr(0, 2);
+ int ev = std::stol(eventData1, nullptr, 16);
+ int ed = std::stol(eventDir);
+ AlarmType alarmStatus = NORMAL;
+ int ev1Offset = ev & SENSOR_EVENT_DATA1_EVENT_OFFSET;
+ switch (sensorType)
+ {
+ case SENSOR_TYPE_EVENT_LOGGING_DISABLED:
+ {
+ switch (ev1Offset)
+ {
+ case SYSTEM_EVENT_LOG_CLEARED:
+ {
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+ break;
+ }
+ default:
+ {
+ return alarmStatus;
+ }
+ }
+ break;
+ }
+ case SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE:
+ {
+ switch (ev1Offset)
+ {
+ case ACPI_S0_STATE:
+ case ACPI_S5_STATE:
+ {
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+ break;
+ }
+ default:
+ {
+ if (!ed)
+ {
+ alarmStatus = NORMAL;
+ }
+ return alarmStatus;
+ }
+ }
+ break;
+ }
+ default:
+ return alarmStatus;
+ }
+ sensorStatusRec[sensorPath].eventType = SPECIFIC_SENSOR_TYPE;
+ sensorStatusRec[sensorPath].sensorType = sensorType;
+ setDiscreteSensorStatusValue(bus, sensorPath, eventData);
+ if(0)
+ {
+ fillSensorDescription(sensorPath, ev1Offset);
+ setDiscreteSensorDiscription(bus, sensorPath);
+ setDiscreteSensorHealth(bus, sensorPath);
+ }
+ return alarmStatus;
+ }
+
+
+
+
+void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
+{
+ //AlarmType severity = NORMAL;
+ auto method = bus.new_method_call(logService, path.c_str(),
+ "org.freedesktop.DBus.Properties", "Get");
+ method.append("xyz.openbmc_project.Logging.Entry");
+ method.append("AdditionalData");
+ std::cerr << "filterSEL path " << path <<"\n";
+ std::variant<AdditionalList> additionalData;
+ try
+ {
+ auto reply = bus.call(method);
+ reply.read(additionalData);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ lg2::error(
+ "Failed to parse existing callouts AdditionalData message. {ERROR}",
+ "ERROR", e.what());
+ }
+
+ auto& additionalDatas = std::get<AdditionalList>(additionalData);
+ if (additionalDatas.empty())
+ {
+ lg2::error("additionalDatas is empty");
+ return;
+ }
+
+ uint8_t typeCode = 0;
+ uint8_t sensorType = 0;
+ std::string sensorData, sensorPath, eventDir;
+ for (auto& item : additionalDatas)
+ {
+ std::string::size_type nStr;
+
+ if (eventDir.empty())
+ {
+ nStr = item.find("EVENT_DIR=");
+ if (std::string::npos != nStr)
+ {
+ eventDir = item.substr(nStr + strlen("EVENT_DIR="));
+ }
+ }
+
+ if (sensorData.empty())
+ {
+ nStr = item.find("SENSOR_DATA=");
+ if (std::string::npos != nStr)
+ {
+ sensorData = item.substr(nStr + strlen("SENSOR_DATA="));
+ }
+ }
+
+ if (sensorPath.empty())
+ {
+ nStr = item.find("SENSOR_PATH=");
+ if (std::string::npos != nStr)
+ {
+ sensorPath = item.substr(nStr + strlen("SENSOR_PATH="));
+ std::string sensorPathTmp = sensorPath;
+ size_t pos = sensorPathTmp.rfind('/');
+ if (pos != std::string::npos){
+ sensorPath = "/xyz/openbmc_project/sensors/status/" + sensorPathTmp.substr(pos + 1);
+ }
+ std::cerr << "sensorPath " << sensorPath <<"\n";
+ }
+ }
+ }
+
+ if (!ipmiSensors)
+ {
+ ipmiSensors = initIPMISensorInfo(bus);
+ }
+
+ if (ipmiSensors)
+ {
+ auto iter = ipmiSensors->find(sensorPath);
+ if (iter != ipmiSensors->end())
+ {
+ sensorType = iter->second[0];
+ typeCode = iter->second[1];
+ }
+ }
+
+ if (sensorData == "" || typeCode == 0 || eventDir == "" || sensorType == 0)
+ {
+ lg2::error(
+ "ERROR: Additional Data parse failed, sensorData = {SENSORDATA} sensorPath = {SENSORPATH} sensorType = {SENSORTYPE} typeCode = {TYPECODE} eventDir = {EVENTDIR}",
+ "SENSORDATA", sensorData, "SENSORPATH", sensorPath, "SENSORTYPE",
+ sensorType, "TYPECODE", typeCode, "EVENTDIR", eventDir);
+
+ return;
+ }
+
+ if (typeCode == THRESHOLD_SENSOR_TYPE)
+ {
+ // parse threshold sensors
+ //parseThresholdSelSeverity(sensorData, eventDir);
+ }
+ else if (typeCode == SPECIFIC_SENSOR_TYPE)
+ {
+ // discrete
+ parseSpecificSensorSelSeverity(
+ bus, sensorPath, static_cast<SensorType>(sensorType), sensorData,
+ eventDir);
+ }
+
+ //controlHealthLed(bus);
+
+ return;
+}
+
void Add::created(sdbusplus::message_t& msg)
{
auto bus = msg.get_bus();
@@ -147,7 +563,8 @@ void Add::created(sdbusplus::message_t& msg)
// Not a new error entry skip
return;
}
- auto iter = interfaces.find("xyz.openbmc_project.Association.Definitions");
+ // auto iter = interfaces.find("xyz.openbmc_project.Association.Definitions");
+ auto iter = interfaces.find("xyz.openbmc_project.Logging.Entry");
if (iter == interfaces.end())
{
return;
@@ -157,29 +574,32 @@ void Add::created(sdbusplus::message_t& msg)
// has been created. Do it here.
lg2::info("{PATH} created", "PATH", objectPath);
- auto attr = iter->second.find("Associations");
+ //auto attr = iter->second.find("Associations");
+ auto attr = iter->second.find("AdditionalData");
if (attr == iter->second.end())
{
+ lg2::info("No AdditionalData");
return;
}
- auto& assocs = std::get<AssociationList>(attr->second);
- if (assocs.empty())
- {
- // No associations skip
- return;
- }
-
- for (const auto& item : assocs)
- {
- if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
- {
- removeWatches.emplace_back(
- std::make_unique<Remove>(bus, std::get<2>(item)));
- action(bus, std::get<2>(item), true);
- }
- }
-
+ // auto& assocs = std::get<AssociationList>(attr->second);
+ // if (assocs.empty())
+ // {
+ // // No associations skip
+ // return;
+ // }
+
+ // for (const auto& item : assocs)
+ // {
+ // if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
+ // {
+ // removeWatches.emplace_back(
+ // std::make_unique<Remove>(bus, std::get<2>(item)));
+ // action(bus, std::get<2>(item), true);
+ // }
+ // }
+
+ filterSEL(bus, objectPath.str);
return;
}
diff --git a/fault-monitor/fru-fault-monitor.hpp b/fault-monitor/fru-fault-monitor.hpp
index 028e873..652fefa 100644
--- a/fault-monitor/fru-fault-monitor.hpp
+++ b/fault-monitor/fru-fault-monitor.hpp
@@ -6,7 +6,7 @@
#include <sdbusplus/server.hpp>
#include <string>
-
+#include <iostream>
namespace phosphor
{
namespace led
@@ -27,6 +27,33 @@ void action(sdbusplus::bus_t& bus, const std::string& path, bool assert);
class Remove;
+/*
+ * IPMI Standard Sensor Type Define
+ */
+enum SensorType
+{
+ SENSOR_TYPE_EVENT_LOGGING_DISABLED = 0x10,
+ SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE = 0x22,
+
+ SENSOR_TYPE_MAX_NUMBER = 0x100 // Senor Type 为1个byte,最大为0~255,即:256个
+};
+
+struct SensorStatusInfo
+{
+ uint8_t eventType;
+ SensorType sensorType;
+ uint16_t sensorStatus;
+ uint64_t alarmStatus;
+ std::string description; // add description for discrete sensor
+};
+
+struct DriveStatus
+{
+ uint16_t sensorStatus; /*entity status*/
+ uint64_t alarmStatus; /*alarm status*/
+};
+
+
/** @class Add
* @brief Implementation of LED handling during FRU fault
* @details This implements methods for watching for a FRU fault
@@ -46,17 +73,19 @@ class Add
* @param[in] bus - The Dbus bus object
*/
explicit Add(sdbusplus::bus_t& bus) :
- matchCreated(
- bus,
- sdbusplus::bus::match::rules::interfacesAdded() +
- sdbusplus::bus::match::rules::path_namespace(
- "/xyz/openbmc_project/logging"),
- std::bind(std::mem_fn(&Add::created), this, std::placeholders::_1))
+ bus(bus), matchCreated(bus,
+ sdbusplus::bus::match::rules::interfacesAdded() +
+ sdbusplus::bus::match::rules::path_namespace(
+ "/xyz/openbmc_project/logging"),
+ std::bind(std::mem_fn(&Add::created), this,
+ std::placeholders::_1))
{
+ std::cerr << "wangbin matchCreated \n";
processExistingCallouts(bus);
}
private:
+ sdbusplus::bus::bus& bus;
/** @brief sdbusplus signal match for fault created */
sdbusplus::bus::match_t matchCreated;
@@ -67,6 +96,8 @@ class Add
*/
void created(sdbusplus::message_t& msg);
+ void filterSEL(sdbusplus::bus::bus& bus, const std::string& path);
+
/** @brief This function process all callouts at application start
* @param[in] bus - The Dbus bus object
*/
@@ -0,0 +1,38 @@
From 7f310f1f1c9f32ec9d94fcc06b25e26faf0b66c4 Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Thu, 12 Dec 2024 09:59:32 +0800
Subject: [PATCH] Add watchdog2 sensor type
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
fault-monitor/fru-fault-monitor.cpp | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index 737c90d..b9f687c 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -919,6 +919,11 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
break;
}
+ case SENSOR_TYPE_WATCHDOG_2:
+ {
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+ break;
+ }
default:
break;
}
@@ -987,7 +992,7 @@ using EventAlarm = std::unordered_map<uint8_t, EventActions>;
// 'Status'. See: initDiscreteSensorStatusInfo() and sensorMatchHandler().
// If true, it means that the 'Status' has been initialized
// and the status sensor object on the entity-manager has been created.
-
+
// if (sensorStatusRec.find(sensorPath) == sensorStatusRec.end())
// {
// lg2::error(
--
2.34.1
@@ -0,0 +1,56 @@
From 4b33a41ddbb3dc745a41248070f02d69e21ddf46 Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Mon, 11 Nov 2024 15:29:45 +0800
Subject: [PATCH] Enable Orange LED to indicate if dimm is present
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
fault-monitor/fru-fault-monitor.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index fffb6f7..aa7b8cc 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -42,7 +42,7 @@ static constexpr auto logService = "xyz.openbmc_project.Logging";
#define SET_GREEN_LED(x) (~(uint8_t(1 << (x*2))))
#define SET_RED_LED(x) (~(uint8_t(1 << (x*2 + 1))))
-#define SET_ORANGE_LED(x) (SET_GREEN_LED(x) | SET_RED_LED(x))
+#define SET_ORANGE_LED(x) (SET_GREEN_LED(x) & SET_RED_LED(x))
#define UNSET_GREEN_LED(x) (uint8_t(1 << (x*2)))
#define UNSET_RED_LED(x) (uint8_t(1 << (x*2 + 1)))
#define SET_LED_OFF(x) ((uint8_t(1 << (x*2))) | (uint8_t(1 << (x*2+1))))
@@ -1008,10 +1008,6 @@ void Add::updateDimmLed(int cpuId, int dimmRank, std::string ledState)
int ret = -1;
std::string i2cBus = "/dev/i2c-5";
- if constexpr (debug) {
- std::cout << "cpuId: " << cpuId << " dimmrank: " << dimmRank << " ledState: " << ledState <<std::endl;
- }
-
uint8_t preset = (cpuId * 12 + dimmRank) / 8;
if(preset >= 3)
{
@@ -1041,11 +1037,16 @@ void Add::updateDimmLed(int cpuId, int dimmRank, std::string ledState)
wdata = (readBuf[0] & SET_RED_LED(ledSlot)) | UNSET_GREEN_LED(ledSlot);
else if(ledState == "OFF")
wdata = readBuf[0] | SET_LED_OFF(ledSlot);
- else if(ledState == "WAR")
- wdata = readBuf[0] | SET_LED_OFF(ledSlot);
+ else if(ledState == "NA")
+ wdata = readBuf[0] & SET_ORANGE_LED(ledSlot);
else
std::cerr << " Invalid DIMM CPU" << cpuId << " rank" << dimmRank << " LED State " << ledState << "\n";
+ if constexpr (debug) {
+ std::cout << "cpuId: " << cpuId << " dimmrank: " << dimmRank << " ledState: " << ledState << " wdata:"
+ << (int)wdata <<std::endl;
+ }
+
writeData.push_back(wdata);
readBuf.resize(0);
ret = i2cWriteRead(i2cBus, i2cAddrs[preset], writeData, readBuf);
--
2.34.1
@@ -0,0 +1,568 @@
From 685ddf56f7f7d5d01ec6285d72dad653962753ef Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Thu, 24 Oct 2024 20:30:19 +0800
Subject: [PATCH] Implement DIMM LED control
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
fault-monitor/fru-fault-monitor.cpp | 313 +++++++++++++++++++++++++++-
fault-monitor/fru-fault-monitor.hpp | 72 ++++++-
fault-monitor/meson.build | 5 +-
fault-monitor/monitor-main.cpp | 13 +-
meson.build | 2 +
5 files changed, 392 insertions(+), 13 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index 4946065..03e1700 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -8,6 +8,16 @@
#include <string>
#include <vector>
#include <iostream>
+
+extern "C"
+{
+#include <i2c/smbus.h>
+#include <linux/i2c-dev.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+}
+
namespace phosphor
{
namespace led
@@ -30,6 +40,13 @@ static constexpr auto logPath = "/xyz/openbmc_project/logging";
static constexpr auto logIntf = "xyz.openbmc_project.Logging.Entry";
static constexpr auto logService = "xyz.openbmc_project.Logging";
+#define SET_GREEN_LED(x) (~(uint8_t(1 << (x*2))))
+#define SET_RED_LED(x) (~(uint8_t(1 << (x*2 + 1))))
+#define SET_ORANGE_LED(x) (SET_GREEN_LED(x) | SET_RED_LED(x))
+#define UNSET_GREEN_LED(x) (uint8_t(1 << (x*2)))
+#define UNSET_RED_LED(x) (uint8_t(1 << (x*2 + 1)))
+#define SET_LED_OFF(x) ((uint8_t(1 << (x*2))) | (uint8_t(1 << (x*2+1))))
+
using AssociationList =
std::vector<std::tuple<std::string, std::string, std::string>>;
using Attributes = std::variant<bool, AssociationList>;
@@ -68,6 +85,7 @@ constexpr auto ACPI_S5_STATE = 6;
std::unordered_map<std::string, SensorStatusInfo> sensorStatusRec;
std::unordered_map<std::string, std::unordered_map<uint8_t, DriveStatus>> driveStatusRec;
+
enum AlarmType
{
NORMAL = 0,
@@ -237,6 +255,41 @@ static void setDiscreteSensorDiscription(sdbusplus::bus::bus& bus,
return;
}
+static void setDimmLEDState(sdbusplus::bus::bus& bus,
+ const std::string& sensorPath,const std::string& ledState)
+{
+ std::string sensorName;
+ std::string ledStatePath;
+ size_t lastSlashPos = sensorPath.rfind('/');
+ size_t statusPos = sensorPath.find("_Status");
+
+ if (lastSlashPos != std::string::npos && statusPos != std::string::npos) {
+ sensorName = sensorPath.substr(lastSlashPos + 1, statusPos - lastSlashPos - 1);
+ ledStatePath = "/xyz/openbmc_project/sensors/temperature/" + sensorName + "_Temp";
+ } else {
+ lg2::info("Invalid sensorPath, sensorPath = {PATH}",
+ "PATH", sensorPath);
+ return;
+ }
+
+ auto method = bus.new_method_call(DIMMTempSensorBusname, ledStatePath.c_str(),
+ dbusProperties, "Set");
+
+ std::variant<std::string> value{ledState};
+ method.append(dimmLEDInterface, "LEDState", value);
+ try
+ {
+ bus.call_noreply(method);
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ lg2::info("Error setting Dimm LED State, ERROR = {ERROR}",
+ "ERROR", e);
+ }
+
+ return;
+}
+
static void setDiscreteSensorHealth(sdbusplus::bus::bus& bus,
const std::string& sensorPath)
{
@@ -441,6 +494,7 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
case SENSOR_TYPE_MEMORY:
{
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+ setDimmLEDState(bus, sensorPath, "FAULT");
break;
}
default:
@@ -458,9 +512,6 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
return;
}
-
-
-
void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
{
//AlarmType severity = NORMAL;
@@ -631,6 +682,250 @@ void Add::created(sdbusplus::message_t& msg)
return;
}
+std::string getFileName(const std::string& path) {
+ size_t lastSlash = path.find_last_of("/\\");
+ return (lastSlash == std::string::npos) ? "" : path.substr(lastSlash + 1);
+}
+
+static int i2cWriteRead(std::string& i2cBus, const uint8_t slaveAddr,
+ std::vector<uint8_t> writeData,
+ std::vector<uint8_t>& readBuf)
+{
+ int fd = open(i2cBus.c_str(), O_RDWR);
+ if (fd < 0)
+ {
+ std::cerr << " unable to open i2c device" << i2cBus << " err=" << fd
+ << "\n";
+ return -1;
+ }
+
+ uint8_t writeCount = writeData.size();
+ uint8_t readCount = readBuf.size();
+ int msgCount = 0;
+ struct i2c_msg i2cmsg[2]; // = {0};
+
+ memset(i2cmsg, 0, sizeof(i2cmsg));
+
+ if (writeCount)
+ {
+ // Data will be writtern to the slave address
+ i2cmsg[msgCount].addr = slaveAddr;
+ i2cmsg[msgCount].flags = 0x00;
+ i2cmsg[msgCount].len = writeCount;
+ i2cmsg[msgCount].buf = writeData.data();
+ msgCount++;
+ }
+
+ if (readCount)
+ {
+ // Data will be read into the buffer from the slave address
+ i2cmsg[msgCount].addr = slaveAddr;
+ i2cmsg[msgCount].flags = I2C_M_RD;
+ i2cmsg[msgCount].len = readCount;
+ i2cmsg[msgCount].buf = readBuf.data();
+ msgCount++;
+ }
+
+ struct i2c_rdwr_ioctl_data msgReadWrite; // = {0};
+ memset((void*)&msgReadWrite, 0, sizeof(msgReadWrite));
+ msgReadWrite.msgs = i2cmsg;
+ msgReadWrite.nmsgs = msgCount;
+
+ // Perform the combined write/read
+ int ret = ioctl(fd, I2C_RDWR, &msgReadWrite);
+ close(fd);
+ if (ret < 0)
+ {
+ std::cerr << "getDIMMRegsInfoWord I2C Write Failed!"
+ << "\n";
+ return -1;
+ }
+
+ if (readCount)
+ {
+ readBuf.resize(msgReadWrite.msgs[msgCount - 1].len);
+ }
+
+ return 0;
+}
+
+void Add::dimmledInit()
+{
+ int ret = -1;
+ std::string i2cBus = "/dev/i2c-5";
+
+ for(uint8_t addr : i2cAddrs) {
+ std::vector<uint8_t> writeData{regConfig[0], 0x0};
+ std::vector<uint8_t> readBuf(0);
+ ret = i2cWriteRead(i2cBus, addr, writeData, readBuf);
+ if (ret < 0)
+ goto err;
+
+ writeData[0] = regConfig[1];
+ ret = i2cWriteRead(i2cBus, addr, writeData, readBuf);
+ if (ret < 0)
+ goto err;
+
+ writeData[0] = regOutput[0];
+ writeData[1] = 0xff;
+ ret = i2cWriteRead(i2cBus, addr, writeData, readBuf);
+ if (ret < 0)
+ goto err;
+
+ writeData[0] = regOutput[1];
+ ret = i2cWriteRead(i2cBus, addr, writeData, readBuf);
+ if (ret < 0)
+ goto err;
+ }
+
+ return;
+ err:
+ std::cerr << "i2c read/write error, DIMM ledInit failed. \n";
+ return;
+}
+
+void Add::updateSysHealthLED(std::pair<std::string, std::string>& pair)
+{
+ if(pair.second == "FAULT") {
+ setHealthLED(pair.first);
+ } else {
+ unsetHealthLED(pair.first);
+ }
+}
+
+void Add::setHealthLED(const std::string& path)
+{
+ if constexpr (debug) {
+ std::cout << "setHealthLED path: " << path << std::endl;
+ }
+
+ std::vector<Association> associations;
+ associations.emplace_back("", "dimmfault", path.c_str());
+
+ faultMonitorAssociation->set_property("Associations", associations);
+}
+
+void Add::unsetHealthLED(const std::string& path)
+{
+ if constexpr (debug) {
+ std::cout << "unsetHealthLED path: " << path << std::endl;
+ }
+
+ std::vector<Association> associations;
+ associations.emplace_back("", "", path.c_str());
+
+ faultMonitorAssociation->set_property("Associations", associations);
+}
+
+void Add::updateDimmLed(int cpuId, int dimmRank, std::string ledState)
+{
+ int ret = -1;
+ std::string i2cBus = "/dev/i2c-5";
+
+ if constexpr (debug) {
+ std::cout << "cpuId: " << cpuId << " dimmrank: " << dimmRank << " ledState: " << ledState <<std::endl;
+ }
+
+ uint8_t preset = (cpuId * 12 + dimmRank) / 8;
+ if(preset >= 3)
+ {
+ std::cerr << " fail to update Dimm LED, invalid preset. \n";
+ return;
+ }
+
+ uint8_t port = ((cpuId * 12 + dimmRank) % 8) / 4;
+ if(port >= 2)
+ {
+ std::cerr << " fail to update Dimm LED, invalid port. \n";
+ return;
+ }
+
+ uint8_t ledSlot = ((cpuId * 12 + dimmRank) % 8) % 4;
+
+ std::vector<uint8_t> writeData{regOutput[port]};
+ std::vector<uint8_t> readBuf(1);
+ ret = i2cWriteRead(i2cBus, i2cAddrs[preset], writeData, readBuf);
+ if (ret < 0)
+ goto err;
+
+ uint8_t wdata;
+ if(ledState == "ON")
+ wdata = (readBuf[0] & SET_GREEN_LED(ledSlot)) | UNSET_RED_LED(ledSlot);
+ else if(ledState == "FAULT")
+ wdata = (readBuf[0] & SET_RED_LED(ledSlot)) | UNSET_GREEN_LED(ledSlot);
+ else if(ledState == "OFF")
+ wdata = readBuf[0] | SET_LED_OFF(ledSlot);
+ else if(ledState == "WAR")
+ wdata = readBuf[0] | SET_LED_OFF(ledSlot);
+ else
+ std::cerr << " Invalid DIMM CPU" << cpuId << " rank" << dimmRank << " LED State " << ledState << "\n";
+
+ writeData.push_back(wdata);
+ readBuf.resize(0);
+ ret = i2cWriteRead(i2cBus, i2cAddrs[preset], writeData, readBuf);
+ if (ret < 0)
+ goto err;
+
+ return;
+
+err:
+ std::cerr << "i2c read/write error, update DIMM led failed. \n";
+ return;
+}
+
+void Add::dimmLEDMatchHandler(sdbusplus::message_t& msg)
+{
+ // Get the ObjectPath of the `xyz.openbmc_project.Inventory.Manager`
+ // service
+ int cpuId, dimmrank;
+ std::pair<std::string, std::string> dimmSensorLEDStatus;
+ std::string* ledState;
+ std::string dimmTempSensorPath = msg.get_path();
+
+ std::string dimmTempSenName = getFileName(dimmTempSensorPath);
+ if(dimmTempSenName != "" && dimmTempSenName.find("DIMM_CPU") != std::string::npos)
+ {
+ std::regex regex(R"(CPU(\d+)_([A-Z]))");
+ std::smatch match;
+
+ if (std::regex_search(dimmTempSenName, match, regex)) {
+ cpuId = std::stoi(match[1].str());
+ dimmrank = match[2].str()[0] - 'A';
+ }
+ } else {
+ lg2::error(
+ "Faild to get the DIMM temp sensor path, PATH = {PATH}",
+ "PATH", dimmTempSensorPath);
+ return;
+ }
+
+ // Get all the properties of
+ // "xyz.openbmc_project.State.Decorator.OperationalStatus" interface
+ std::string interfaceName{};
+ std::unordered_map<std::string, std::variant<std::string>> properties;
+ msg.read(interfaceName, properties);
+
+ const auto it = properties.find("LEDState");
+ if (it != properties.end())
+ {
+ ledState = std::get_if<std::string>(&it->second);
+ if (!ledState)
+ {
+ lg2::error(
+ "Faild to get the Functional property, INVENTORY_PATH = {PATH}",
+ "PATH", dimmTempSensorPath);
+ return;
+ }
+ }
+
+ dimmSensorLEDStatus.first = dimmTempSensorPath;
+ dimmSensorLEDStatus.second = *ledState;
+
+ updateDimmLed(cpuId, dimmrank, *ledState);
+
+ updateSysHealthLED(dimmSensorLEDStatus);
+}
+
void getLoggingSubTree(sdbusplus::bus_t& bus, MapperResponseType& subtree)
{
auto depth = 0;
@@ -653,6 +948,18 @@ void getLoggingSubTree(sdbusplus::bus_t& bus, MapperResponseType& subtree)
}
}
+void Add::createAssociation(sdbusplus::asio::object_server& objectServer)
+{
+ // Associations interface for led status
+ std::vector<Association> associations;
+ associations.emplace_back("", "", "");
+
+ faultMonitorAssociation = objectServer.add_interface(
+ monitorPath, associationPath);
+ faultMonitorAssociation->register_property("Associations", associations);
+ faultMonitorAssociation->initialize();
+}
+
void Add::processExistingCallouts(sdbusplus::bus_t& bus)
{
MapperResponseType mapperResponse;
diff --git a/fault-monitor/fru-fault-monitor.hpp b/fault-monitor/fru-fault-monitor.hpp
index 065e8c8..bd4a852 100644
--- a/fault-monitor/fru-fault-monitor.hpp
+++ b/fault-monitor/fru-fault-monitor.hpp
@@ -4,9 +4,18 @@
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/container/flat_map.hpp>
#include <string>
#include <iostream>
+#include <regex>
+#include <vector>
+
+constexpr const bool debug = false;
+
namespace phosphor
{
namespace led
@@ -17,6 +26,25 @@ namespace fault
{
namespace monitor
{
+constexpr auto faultLedPath = "/xyz/openbmc_project/led/groups/status_fault";
+constexpr auto dimmfaultLedPath = "/xyz/openbmc_project/led/groups/dimm_fault";
+constexpr auto okLedPath = "/xyz/openbmc_project/led/groups/status_ok";
+constexpr auto ledIface = "xyz.openbmc_project.Led.Group";
+constexpr auto ledAssertProp = "Asserted";
+constexpr auto ledManagerBusname = "xyz.openbmc_project.LED.GroupManager";
+constexpr auto DIMMTempSensorBusname = "xyz.openbmc_project.DIMMTempSensor";
+constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
+constexpr auto dimmLEDInterface = "xyz.openbmc_project.Sensor.dimmLED";
+constexpr auto dimmSensorPath = "/xyz/openbmc_project/sensors/temperature";
+constexpr auto monitorPath = "/xyz/openbmc_project/led/fault/monitor";
+constexpr auto callbackMgrPath = "/xyz/openbmc_project/CallbackManager";
+constexpr auto associationPath = "xyz.openbmc_project.Association.Definitions";
+
+using Association = std::tuple<std::string, std::string, std::string>;
+
+const std::vector<uint8_t> i2cAddrs = {0x20, 0x21, 0x22};
+const std::vector<uint8_t> regConfig = {0x06, 0x07};
+const std::vector<uint8_t> regOutput = {0x02, 0x03};
/** @brief Assert or deassert an LED based on the input FRU
* @param[in] bus - The Dbus bus object
@@ -117,31 +145,61 @@ class Add
/** @brief constructs Add a watch for FRU faults.
* @param[in] bus - The Dbus bus object
*/
- explicit Add(sdbusplus::bus_t& bus) :
- bus(bus), matchCreated(bus,
- sdbusplus::bus::match::rules::interfacesAdded() +
- sdbusplus::bus::match::rules::path_namespace(
- "/xyz/openbmc_project/logging"),
- std::bind(std::mem_fn(&Add::created), this,
- std::placeholders::_1))
+
+ explicit Add(sdbusplus::bus_t& bus, sdbusplus::asio::object_server& objectServer) :
+ bus(bus),
+ matchCreated(bus,
+ sdbusplus::bus::match::rules::interfacesAdded() +
+ sdbusplus::bus::match::rules::path_namespace(
+ "/xyz/openbmc_project/logging"),
+ std::bind(std::mem_fn(&Add::created), this,
+ std::placeholders::_1)),
+ dimmLEDMatch(bus,
+ "type='signal',member='PropertiesChanged',path_namespace='" +
+ std::string(dimmSensorPath) + "',arg0namespace='" +
+ std::string(dimmLEDInterface) + "'",
+ std::bind(std::mem_fn(&Add::dimmLEDMatchHandler), this,
+ std::placeholders::_1))
{
+
+ createAssociation(objectServer);
+ dimmledInit();
processExistingCallouts(bus);
}
+
private:
sdbusplus::bus::bus& bus;
/** @brief sdbusplus signal match for fault created */
sdbusplus::bus::match_t matchCreated;
+ sdbusplus::bus::match_t dimmLEDMatch;
+
std::vector<std::unique_ptr<Remove>> removeWatches;
+ std::shared_ptr<sdbusplus::asio::dbus_interface> faultMonitorAssociation;
+
/** @brief Callback function for fru fault created
* @param[in] msg - Data associated with subscribed signal
*/
void created(sdbusplus::message_t& msg);
+ void dimmLEDMatchHandler(sdbusplus::message_t& msg);
+
void filterSEL(sdbusplus::bus::bus& bus, const std::string& path);
+ void dimmledInit();
+
+ void updateDimmLed(int cpuId, int dimmRank, std::string ledState);
+
+ void updateSysHealthLED(std::pair<std::string, std::string>& pair);
+
+ void setHealthLED(const std::string& path);
+
+ void unsetHealthLED(const std::string& path);
+
+ void createAssociation(sdbusplus::asio::object_server& objectServer);
+
/** @brief This function process all callouts at application start
* @param[in] bus - The Dbus bus object
*/
diff --git a/fault-monitor/meson.build b/fault-monitor/meson.build
index 39ec458..7ced362 100644
--- a/fault-monitor/meson.build
+++ b/fault-monitor/meson.build
@@ -17,7 +17,10 @@ executable(
'phosphor-fru-fault-monitor',
fault_monitor_sources,
include_directories: ['.', '../'],
- dependencies: deps,
+ dependencies: [
+ deps,
+ i2c,
+ ],
install: true,
install_dir: get_option('bindir')
)
diff --git a/fault-monitor/monitor-main.cpp b/fault-monitor/monitor-main.cpp
index 92b332d..3083c13 100644
--- a/fault-monitor/monitor-main.cpp
+++ b/fault-monitor/monitor-main.cpp
@@ -6,15 +6,24 @@
#include "fru-fault-monitor.hpp"
#endif
+constexpr auto busName = "xyz.openbmc_project.led.fault.monitor";
+
int main(void)
{
+ boost::asio::io_context io;
+ auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
+ systemBus->request_name(busName);
+
+ sdbusplus::asio::object_server server =
+ sdbusplus::asio::object_server(systemBus);
+
/** @brief Dbus constructs used by Fault Monitor */
- sdbusplus::bus_t bus = sdbusplus::bus::new_default();
+ sdbusplus::bus_t& bus = static_cast<sdbusplus::bus_t&>(*systemBus);
#ifdef MONITOR_OPERATIONAL_STATUS
phosphor::led::Operational::status::monitor::Monitor monitor(bus);
#else
- phosphor::led::fru::fault::monitor::Add monitor(bus);
+ phosphor::led::fru::fault::monitor::Add monitor(bus, server);
#endif
/** @brief Wait for client requests */
while (true)
diff --git a/meson.build b/meson.build
index f1a65a8..bf5fc76 100644
--- a/meson.build
+++ b/meson.build
@@ -31,6 +31,8 @@ phosphor_logging_dep = dependency('phosphor-logging')
prog_python = find_program('python3', required: true)
realpath_prog = find_program('realpath')
+i2c = meson.get_compiler('cpp').find_library('i2c')
+
cpp = meson.get_compiler('cpp')
if cpp.has_header('nlohmann/json.hpp')
nlohmann_json_dep = declare_dependency()
--
2.34.1
@@ -0,0 +1,25 @@
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index 3c63735..d5d6703 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -181,7 +181,7 @@ static void setDiscreteSensorStatusValue(sdbusplus::bus::bus& bus,
// ipmi spec 42.2 set the sensor-specific offset
double statusValue = reserved;
- constexpr auto service = "xyz.openbmc_project.dissen";
+ constexpr auto service = "xyz.openbmc_project.EntityManager";
constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
constexpr auto statusInterface = "xyz.openbmc_project.Configuration.Status";
@@ -487,11 +487,6 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
if (std::string::npos != nStr)
{
sensorPath = item.substr(nStr + strlen("SENSOR_PATH="));
- std::string sensorPathTmp = sensorPath;
- size_t pos = sensorPathTmp.rfind('/');
- if (pos != std::string::npos){
- sensorPath = "/xyz/openbmc_project/sensors/status/" + sensorPathTmp.substr(pos + 1);
- }
std::cerr << "sensorPath " << sensorPath <<"\n";
}
}
@@ -0,0 +1,127 @@
From 757268065e51263dc760951c535e53f76dac2ffe Mon Sep 17 00:00:00 2001
From: "Wang.Bin" <Bin-B.Wang@luxshare-ict.com>
Date: Wed, 23 Oct 2024 13:29:51 +0800
Subject: [PATCH 2/2] Add power button and PSU status sensor
---
fault-monitor/fru-fault-monitor.cpp | 28 +++++++++++++++++
fault-monitor/fru-fault-monitor.hpp | 48 +++++++++++++++++++++++++++--
2 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index 8ff5294..4946065 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -55,6 +55,11 @@ constexpr const char* discreteSensorNs = "No state defined";
// 10H
constexpr auto SYSTEM_EVENT_LOG_CLEARED = 2;
+// 14H
+constexpr auto POWER_BUTTON_PRESSED = 0;
+constexpr auto SLEEP_BUTTON_PRESSED = 1;
+constexpr auto RESET_BUTTON_PRESSED = 2;
+
// 22H
constexpr auto ACPI_S0_STATE = 0;
constexpr auto ACPI_S5_STATE = 6;
@@ -389,6 +394,29 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
}
break;
}
+ case SENSOR_TYPE_BUTTON_SWITCH:
+ {
+ switch (ev1Offset)
+ {
+ case POWER_BUTTON_PRESSED:
+ case SLEEP_BUTTON_PRESSED:
+ case RESET_BUTTON_PRESSED:
+ {
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+ break;
+ }
+ default:
+ {
+ return;
+ }
+ }
+ break;
+ }
+ case SENSOR_TYPE_POWER_SUPPLY:
+ {
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+ break;
+ }
case SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE:
{
switch (ev1Offset)
diff --git a/fault-monitor/fru-fault-monitor.hpp b/fault-monitor/fru-fault-monitor.hpp
index e196287..065e8c8 100644
--- a/fault-monitor/fru-fault-monitor.hpp
+++ b/fault-monitor/fru-fault-monitor.hpp
@@ -32,9 +32,54 @@ class Remove;
*/
enum SensorType
{
+ SENSOR_TYPE_TEMPERATURE = 0x01,
+ SENSOR_TYPE_VOLTAGE = 0x02,
+ SENSOR_TYPE_CURRENT = 0x03,
+ SENSOR_TYPE_FAN = 0x04,
+ SENSOR_TYPE_PHYSICAL_SECURITY = 0x05,
+ SENSOR_TYPE_PLATFORM_SECURITY = 0x06,
+ SENSOR_TYPE_PROCESSOR = 0x07,
+ SENSOR_TYPE_POWER_SUPPLY = 0x08,
+ SENSOR_TYPE_POWER_FAULT = 0x09,
+ SENSOR_TYPE_COOLING_DEVICE = 0x0A,
+ SENSOR_TYPE_OHTER_UNITE_BASED_SENSOR = 0x0B,
+ SENSOR_TYPE_MEMORY = 0x0C,
+ SENSOR_TYPE_DRIVE_SLOT = 0x0D,
+
+ SENSOR_TYPE_SYSTEM_FIRMWARE_PROGRESS = 0x0F, // formerly POST error
SENSOR_TYPE_EVENT_LOGGING_DISABLED = 0x10,
+ SENSOR_TYPE_WATCHDOG_1 = 0x11,
+ SENSOR_TYPE_SYSTEM_EVENT = 0x12,
+ SENSOR_TYPE_CRITICAL_INTERRUPT = 0x13,
+ SENSOR_TYPE_BUTTON_SWITCH = 0x14,
+ SENSOR_TYPE_BOARD_MODULE = 0x15,
+ SENSOR_TYPE_MICROCONTROLLER_COPROCESSOR = 0x16,
+ SENSOR_TYPE__RESOURCERATE = 0xC1, // jss
+
+ SENSOR_TYPE_ADD_IN_CARD = 0x17,
+ SENSOR_TYPE_CHASSIS = 0x18,
+ SENSOR_TYPE_CHIP_SET = 0x19,
+
+ SENSOR_TYPE_CABLE_INTERCONNECT = 0x1B,
+
+ SENSOR_TYPE_SYSTEM_BOOT = 0x1D, // Restart Initiated
+ SENSOR_TYPE_BOOT_ERROR = 0x1E,
+ SENSOR_TYPE_OS_BOOT = 0x1F,
+ SENSOR_TYPE_OS_STOP = 0x20,
+ SENSOR_TYPE_SLOT_CONNECTOR = 0x21,
SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE = 0x22,
- SENSOR_TYPE_MEMORY = 0x0C,
+ SENSOR_TYPE_WATCHDOG_2 = 0x23,
+ SENSOR_TYPE_PLATFORM_ALERT = 0x24,
+ SENSOR_TYPE_ENTITY_PRESENCE = 0x25,
+
+ SENSOR_TYPE_LAN = 0x27,
+ SENSOR_TYPE_MANAGEMENT_SUBSYSTEM_HEALTH = 0x28,
+ SENSOR_TYPE_BATTERY = 0x29,
+ SENSOR_TYPE_SESSION_AUDIT = 0x2A,
+ SENSOR_TYPE_HYPERCARD = 0xC0,
+
+ SENSOR_TYPE_VERSION_CHANGE = 0x2B,
+ SENSOR_TYPE_FRU_STATE = 0x2C,
SENSOR_TYPE_MAX_NUMBER = 0x100 // Senor Type 为1个byte,最大为0~255,即:256个
};
@@ -80,7 +125,6 @@ class Add
std::bind(std::mem_fn(&Add::created), this,
std::placeholders::_1))
{
- std::cerr << "wangbin matchCreated \n";
processExistingCallouts(bus);
}
--
2.25.1
@@ -0,0 +1,253 @@
From d8b014ef95adfc1ec2d336968cd60c5961ec9824 Mon Sep 17 00:00:00 2001
From: "Wang.Bin" <Bin-B.Wang@luxshare-ict.com>
Date: Fri, 25 Oct 2024 15:46:54 +0800
Subject: [PATCH 3/3] Add BMC Boot sensor
---
fault-monitor/fru-fault-monitor.cpp | 191 +++++++++++++++++++++++++++-
1 file changed, 186 insertions(+), 5 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index 03e1700..2e99e45 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -69,18 +69,99 @@ using InvalidArgumentErr =
constexpr const char* discreteSensorNs = "No state defined";
+/*discrete sensor specific offset*/
+// 07H
+constexpr auto IPMI_CPU_IERR = 0;
+constexpr auto IPMI_CPU_THERMALTRIP = 1;
+constexpr auto IPMI_CPU_FBR1_BIST_FAILURE = 2;
+constexpr auto IPMI_CPU_FRB2_HANG = 3;
+constexpr auto IPMI_CPU_FRB3_STARTUP_FAILURE = 4;
+constexpr auto IPMI_CPU_CONFIG_ERROR = 5;
+constexpr auto IPMI_CPU_SMBIOS_UC_ERROR = 6;
+constexpr auto IPMI_CPU_PRESENT = 7;
+constexpr auto IPMI_CPU_DISABLED = 8;
+constexpr auto IPMI_CPU_THROTTLED = 10;
+constexpr auto IPMI_CPU_MCE = 11;
+constexpr auto IPMI_CPU_CMCE = 12;
+
+// 08H
+constexpr auto POWER_SUPPLY_PRESENT = 0;
+constexpr auto POWER_SUPPLY_FAILURE = 1;
+constexpr auto POWER_SUPPLY_PREDICTIVE_FAILURE = 2;
+constexpr auto POWER_SUPPLY_AC_LOST = 3;
+constexpr auto POWER_SUPPLY_AC_OUT_OF_RANGE = 5;
+constexpr auto POWER_SUPPLY_CONFIG_ERROR = 6;
+
+// 0CH
+constexpr auto MEMORY_OFFSET_CORRECTABLE_ECC = 0;
+constexpr auto MEMORY_OFFSET_UNCORRECTABLE_ECC = 1;
+constexpr auto MEMORY_OFFSET_PARITY = 2;
+constexpr auto MEMORY_OFFSET_MEMORY_SCRUB_FAILED = 3;
+constexpr auto MEMORY_OFFSET_MEMORY_DEVICE_DISABLED = 4;
+constexpr auto MEMORY_OFFSET_CORRECTABLE_ECC_LOG_LIMIT_REACHED = 5;
+constexpr auto MEMORY_OFFSET_PRESENCE_DETECTED = 6;
+constexpr auto MEMORY_OFFSET_CONFIGURATION_ERROR = 7;
+constexpr auto MEMORY_OFFSET_SPARE = 8;
+constexpr auto MEMORY_OFFSET_MEMORY_AUTOMATICALLY_THROTTLED = 9;
+constexpr auto MEMORY_OFFSET_CRITICAL_OVER_TEMMPERATURE = 10;
+
+// 0FH
+constexpr auto SYSTEM_FIRMWARE_PROGRESS_OFFSET_ERROR = 0;
+constexpr auto SYSTEM_FIRMWARE_PROGRESS_OFFSET_HANG = 1;
+
+// 0DH
+constexpr auto DRIVE_OFFSET_PRESENT = 0;
+constexpr auto DRIVE_OFFSET_FAULT = 1;
+
// 10H
constexpr auto SYSTEM_EVENT_LOG_CLEARED = 2;
+// 13H
+constexpr auto CRITICAL_INTERRUPT_OFFSET_FRONT_PANEL_NMI = 0;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_BUS_TIMEOUT = 1;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_IO_CHANNLE_CHECK_NMI = 2;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_SOFTWARE_NMI = 3;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_PCI_PERR = 4;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_PCI_SERR = 5;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_EISA_FAIL_SAFE_TIMEOUT = 6;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_BUS_CORRECTABLE_ERROR = 7;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_BUS_UNCORRECTABLE_ERRPR = 8;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_FATAL_NMI = 9;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_BUS_FATAL_ERROR = 10;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_BUS_DEGRADED = 11;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_BANDWITH_REDUCTION = 12;
+constexpr auto CRITICAL_INTERRUPT_OFFSET_RATE_REDUCTION = 13;
+
// 14H
constexpr auto POWER_BUTTON_PRESSED = 0;
constexpr auto SLEEP_BUTTON_PRESSED = 1;
constexpr auto RESET_BUTTON_PRESSED = 2;
+// 1BH
+constexpr auto CABLE_CONNECTED = 0;
+constexpr auto CABLE_CONFIG_ERROR = 1;
+
+// 1DH
+constexpr auto INIT_BY_POWER_UP = 0;
+constexpr auto INIT_BY_HARD_RESET = 1;
+constexpr auto INIT_BY_WARM_RESET = 2;
+
+// 1EH
+constexpr auto NO_BOOTABLE_MEDIA = 0;
+constexpr auto NON_BOOTABLE_DISKETTE = 1;
+constexpr auto PXE_SERVER_NOT_FOUND = 2;
+constexpr auto INVALID_BOOT_SECTOR = 3;
+
+// 1FH
+constexpr auto OS_BOOT_COMPLETE = 6;
+
// 22H
constexpr auto ACPI_S0_STATE = 0;
constexpr auto ACPI_S5_STATE = 6;
+// 2BH
+constexpr auto FIRMWARE_UPDATE_SUCCESS = 7;
+
/*sensor object, SensorStatusInfo*/
std::unordered_map<std::string, SensorStatusInfo> sensorStatusRec;
std::unordered_map<std::string, std::unordered_map<uint8_t, DriveStatus>> driveStatusRec;
@@ -124,15 +205,115 @@ using ipmiSensorsInfo = std::unordered_map<std::string, sensorCodes>;
std::optional<ipmiSensorsInfo> ipmiSensors;
const std::unordered_map<SensorType, discrectSensorEvent> sensorSpecificTypes{
+ {SENSOR_TYPE_PROCESSOR,
+ {
+ {IPMI_CPU_IERR, "IERR"},
+ {IPMI_CPU_THERMALTRIP, "Thermal Trip"},
+ {IPMI_CPU_FBR1_BIST_FAILURE, "FRB1/BIST failure"},
+ {IPMI_CPU_FRB2_HANG, "FRB2/Hang in POST failure"},
+ {IPMI_CPU_FRB3_STARTUP_FAILURE, "FRB3/Processor startup/init failure"},
+ {IPMI_CPU_CONFIG_ERROR, "Configuration Error"},
+ {IPMI_CPU_SMBIOS_UC_ERROR, "SM BIOS Uncorrectable CPU-complex Error"},
+ {IPMI_CPU_PRESENT, "Presence detected"},
+ {IPMI_CPU_DISABLED, "Disabled"},
+ {IPMI_CPU_THROTTLED, "Throttled"},
+ {IPMI_CPU_MCE, "Uncorrectable machine check exception"},
+ {IPMI_CPU_CMCE, "Correctable machine check error"},
+ }},
+ {SENSOR_TYPE_POWER_SUPPLY,
+ {
+ {POWER_SUPPLY_PRESENT, "Presence detected"},
+ {POWER_SUPPLY_FAILURE, "Failure detected"},
+ {POWER_SUPPLY_PREDICTIVE_FAILURE, "Predictive failure"},
+ {POWER_SUPPLY_AC_LOST, "Power Supply AC lost"},
+ {POWER_SUPPLY_AC_OUT_OF_RANGE, "AC out-of-range, but present"},
+ {POWER_SUPPLY_CONFIG_ERROR, "Config Error: Vendor Mismatch"},
+ }},
+ {SENSOR_TYPE_MEMORY,
+ {
+ {MEMORY_OFFSET_CORRECTABLE_ECC, "Correctable ECC"},
+ {MEMORY_OFFSET_UNCORRECTABLE_ECC, "Uncorrectable ECC"},
+ {MEMORY_OFFSET_PARITY, "Parity"},
+ {MEMORY_OFFSET_MEMORY_SCRUB_FAILED, "Memory Scrub Failed"},
+ {MEMORY_OFFSET_MEMORY_DEVICE_DISABLED, "Memory Device Disabled"},
+ {MEMORY_OFFSET_CORRECTABLE_ECC_LOG_LIMIT_REACHED,
+ "Correctable ECC logging limit reached"},
+ {MEMORY_OFFSET_PRESENCE_DETECTED, "Presence Detected"},
+ {MEMORY_OFFSET_CONFIGURATION_ERROR, "Configuration Error"},
+ {MEMORY_OFFSET_SPARE, "Spare"},
+ {MEMORY_OFFSET_MEMORY_AUTOMATICALLY_THROTTLED, "Throttled"},
+ {MEMORY_OFFSET_CRITICAL_OVER_TEMMPERATURE, "Critical Overtemperature"},
+ }},
+ {SENSOR_TYPE_DRIVE_SLOT,
+ {
+ {DRIVE_OFFSET_PRESENT, "Drive Present"},
+ {DRIVE_OFFSET_FAULT, "Drive Fault"},
+ }},
+ {SENSOR_TYPE_SYSTEM_FIRMWARE_PROGRESS,
+ {
+ {SYSTEM_FIRMWARE_PROGRESS_OFFSET_ERROR, "System Firmware Error"},
+ {SYSTEM_FIRMWARE_PROGRESS_OFFSET_HANG, "System Firmware Hang"},
+ }},
+ {SENSOR_TYPE_EVENT_LOGGING_DISABLED,
+ {
+ {SYSTEM_EVENT_LOG_CLEARED, "Log area reset/cleared"},
+ }},
+ {SENSOR_TYPE_CRITICAL_INTERRUPT,
+ {
+ {CRITICAL_INTERRUPT_OFFSET_FRONT_PANEL_NMI, "NMI/Diag Interrupt"},
+ {CRITICAL_INTERRUPT_OFFSET_BUS_TIMEOUT, "Bus Timeout"},
+ {CRITICAL_INTERRUPT_OFFSET_IO_CHANNLE_CHECK_NMI,
+ "I/O Channel check NMI"},
+ {CRITICAL_INTERRUPT_OFFSET_SOFTWARE_NMI, "Software NMI"},
+ {CRITICAL_INTERRUPT_OFFSET_PCI_PERR, "PCI PERR"},
+ {CRITICAL_INTERRUPT_OFFSET_PCI_SERR, "PCI SERR"},
+ {CRITICAL_INTERRUPT_OFFSET_EISA_FAIL_SAFE_TIMEOUT,
+ "EISA failsafe timeout"},
+ {CRITICAL_INTERRUPT_OFFSET_BUS_CORRECTABLE_ERROR,
+ "Bus Correctable error"},
+ {CRITICAL_INTERRUPT_OFFSET_BUS_UNCORRECTABLE_ERRPR,
+ "Bus Uncorrectable error"},
+ {CRITICAL_INTERRUPT_OFFSET_FATAL_NMI, "Fatal NMI"},
+ {CRITICAL_INTERRUPT_OFFSET_BUS_FATAL_ERROR, "Bus Fatal Error"},
+ {CRITICAL_INTERRUPT_OFFSET_BUS_DEGRADED, "Bus Degraded"},
+ }},
+ {SENSOR_TYPE_BUTTON_SWITCH,
+ {
+ {POWER_BUTTON_PRESSED, "Power Button pressed"},
+ {SLEEP_BUTTON_PRESSED, "Sleep Button pressed"},
+ {RESET_BUTTON_PRESSED, "Reset Button pressed"},
+ }},
+ {SENSOR_TYPE_CABLE_INTERCONNECT,
+ {
+ {CABLE_CONNECTED, "Connected"},
+ {CABLE_CONFIG_ERROR, "Config Error"},
+ }},
+ {SENSOR_TYPE_SYSTEM_BOOT,
+ {
+ {INIT_BY_POWER_UP, "Initiated by power up"},
+ {INIT_BY_HARD_RESET, "Initiated by hard reset"},
+ {INIT_BY_WARM_RESET, "Initiated by warm reset"},
+ }},
+ {SENSOR_TYPE_BOOT_ERROR,
+ {
+ {NO_BOOTABLE_MEDIA, "No bootable media"},
+ {NON_BOOTABLE_DISKETTE, "Non-bootable disk in drive"},
+ {PXE_SERVER_NOT_FOUND, "PXE server not found"},
+ {INVALID_BOOT_SECTOR, "Invalid boot sector"},
+ }},
+ {SENSOR_TYPE_OS_BOOT,
+ {
+ {OS_BOOT_COMPLETE, "boot completed - device not specified"},
+ }},
{SENSOR_TYPE_SYSTEM_ACPI_POWER_STATE,
{
{ACPI_S0_STATE, "S0/G0: working"},
{ACPI_S5_STATE, "S4/S5: soft-off"},
}},
- {SENSOR_TYPE_EVENT_LOGGING_DISABLED,
+ {SENSOR_TYPE_VERSION_CHANGE,
{
- {SYSTEM_EVENT_LOG_CLEARED, "Log area reset/cleared"},
- }}
+ {FIRMWARE_UPDATE_SUCCESS, "Firmware or software change success"},
+ }},
};
std::optional<ipmiSensorsInfo> initIPMISensorInfo(sdbusplus::bus::bus& bus)
@@ -214,7 +395,7 @@ static void setDiscreteSensorStatusValue(sdbusplus::bus::bus& bus,
auto method = bus.new_method_call(service, sensorPath.c_str(),
dbusProperties, "Set");
std::variant<double> value{(double)statusValue};
-
+ std::cerr << "SEL:sensorData = " << sensorData << std::endl;
method.append(statusInterface, "Status", value);
try
{
@@ -498,7 +679,7 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
break;
}
default:
- return;
+ break;
}
sensorStatusRec[sensorPath].eventType = SPECIFIC_SENSOR_TYPE;
sensorStatusRec[sensorPath].sensorType = sensorType;
--
2.25.1
@@ -0,0 +1,501 @@
From 80cb5c7e022af367dd17981f2a0ffe7d5cf4052a Mon Sep 17 00:00:00 2001
From: "Wang.Bin" <Bin-B.Wang@luxshare-ict.com>
Date: Wed, 20 Nov 2024 19:14:14 +0800
Subject: [PATCH 4/4] Support discrete generic sensors
---
fault-monitor/fru-fault-monitor.cpp | 393 ++++++++++++++++++++++++++--
fault-monitor/fru-fault-monitor.hpp | 3 +-
2 files changed, 379 insertions(+), 17 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index aa7b8cc..737c90d 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -69,6 +69,37 @@ using InvalidArgumentErr =
constexpr const char* discreteSensorNs = "No state defined";
+enum AlarmType : uint64_t
+{
+ NORMAL = 0,
+ NONCRITICAL = 1,
+ CRITICAL = 2,
+ NONRECOV = 4,
+};
+
+/*alarms bits: nr, nc, c*/
+constexpr auto ALARM_BIT_NUM = 3;
+constexpr auto ALARM_ALL_BITS = NONCRITICAL | CRITICAL | NONRECOV;
+constexpr uint64_t ALARM_STATUS_MASK_NR = 0x4924924924924924;
+constexpr uint64_t ALARM_STATUS_MASK_C = 0x2492492492492492;
+constexpr uint64_t ALARM_STATUS_MASK_NC = 0x1249249249249249;
+
+/*discrete generic offset*/
+
+constexpr auto EVENT_TYPE_03H_STATE_DEASSERT = 0;
+constexpr auto EVENT_TYPE_03H_STATE_ASSERT = 1;
+
+constexpr auto EVENT_TYPE_07H_TRANSITION_TO_OK = 0;
+constexpr auto EVENT_TYPE_07H_TRANSITION_TO_NC_FROM_OK = 1;
+
+constexpr auto EVENT_TYPE_08H_ABSENT = 0;
+constexpr auto EVENT_TYPE_08H_PRESENT = 1;
+
+constexpr auto EVENT_TYPE_0BH_FULLY_REDUNDANT = 0;
+constexpr auto EVENT_TYPE_0BH_REDUNDANT_LOST = 1;
+
+/*discrete sensor specific offset*/
+
/*discrete sensor specific offset*/
// 07H
constexpr auto IPMI_CPU_IERR = 0;
@@ -164,16 +195,8 @@ constexpr auto FIRMWARE_UPDATE_SUCCESS = 7;
/*sensor object, SensorStatusInfo*/
std::unordered_map<std::string, SensorStatusInfo> sensorStatusRec;
-std::unordered_map<std::string, std::unordered_map<uint8_t, DriveStatus>> driveStatusRec;
-
-
-enum AlarmType
-{
- NORMAL = 0,
- NONCRITICAL = 1,
- CRITICAL = 2,
- NONRECOV = 4,
-};
+std::unordered_map<std::string, std::unordered_map<uint8_t, SensorStatus>> driveStatusRec;
+std::unordered_map<uint8_t, SensorStatus> powerFaultStatusRec;
struct SelSeverityInfo
{
@@ -204,6 +227,30 @@ using sensorCodes = std::vector<uint8_t>;
using ipmiSensorsInfo = std::unordered_map<std::string, sensorCodes>;
std::optional<ipmiSensorsInfo> ipmiSensors;
+const std::unordered_map<uint8_t, discrectSensorEvent> genericEventTypes{
+ {0x03,
+ {
+ {EVENT_TYPE_03H_STATE_DEASSERT, "State Deasserted"},
+ {EVENT_TYPE_03H_STATE_ASSERT, "State Asserted"},
+ }},
+ {0x07,
+ {
+ {EVENT_TYPE_07H_TRANSITION_TO_OK, "Transition to OK"},
+ {EVENT_TYPE_07H_TRANSITION_TO_NC_FROM_OK,
+ "Transition to Non-critical from OK"},
+ }},
+ {0x08,
+ {
+ {EVENT_TYPE_08H_ABSENT, "Device Absent"},
+ {EVENT_TYPE_08H_PRESENT, "Device Present"},
+ }},
+ {0x0B,
+ {
+ {EVENT_TYPE_0BH_FULLY_REDUNDANT, "Fully Redundant"},
+ {EVENT_TYPE_0BH_REDUNDANT_LOST, "Redundancy Lost"},
+ }},
+};
+
const std::unordered_map<SensorType, discrectSensorEvent> sensorSpecificTypes{
{SENSOR_TYPE_PROCESSOR,
{
@@ -316,6 +363,15 @@ const std::unordered_map<SensorType, discrectSensorEvent> sensorSpecificTypes{
}},
};
+static const std::unordered_map<std::string, std::vector<uint8_t>>
+ flipStateSel = {
+ {"Redundant_PSU",
+ {EVENT_TYPE_0BH_FULLY_REDUNDANT, EVENT_TYPE_0BH_REDUNDANT_LOST}},
+ {"SYS_FAN_Status",
+ {EVENT_TYPE_07H_TRANSITION_TO_OK,
+ EVENT_TYPE_07H_TRANSITION_TO_NC_FROM_OK}},
+};
+
std::optional<ipmiSensorsInfo> initIPMISensorInfo(sdbusplus::bus::bus& bus)
{
constexpr auto service = "xyz.openbmc_project.Ipmi.Host";
@@ -557,13 +613,192 @@ enum
{
UNSPECIFY_SENSOR_TYPE = 0x00,
THRESHOLD_SENSOR_TYPE = 0x01,
- GENERIC_S_SENSOR_TYPE = 0x02,
- GENERIC_E_SENSOR_TYPE = 0x0C,
+ GENERIC_START_SENSOR_TYPE = 0x02,
+ GENERIC_END_SENSOR_TYPE = 0x0C,
SPECIFIC_SENSOR_TYPE = 0x6F,
- OEM_S_SENSOR_TYPE = 0x70,
- OEM_E_SENSOR_TYPE = 0x7F
+ OEM_START_SENSOR_TYPE = 0x70,
+ OEM_END_SENSOR_TYPE = 0x7F
+};
+
+inline void recordAlarmStatus(const std::string& sensorPath,
+ AlarmType alarmStatus, int evOffset, int ed,
+ bool assertAlarm,
+ const bool& isGenericDiscreteSensor)
+{
+ uint64_t statusBit = static_cast<uint64_t>(alarmStatus);
+
+ std::string sensorName{sensorPath};
+ size_t lastPos = sensorPath.find_last_of('/');
+ if (lastPos != std::string::npos)
+ {
+ // Get sensor name from the sensor full path
+ sensorName = sensorPath.substr(lastPos + 1);
+ }
+
+ if (assertAlarm)
+ {
+ if (ed != 0)
+ {
+ sensorStatusRec[sensorPath].alarmStatus |=
+ statusBit << (evOffset * ALARM_BIT_NUM);
+
+ auto it = flipStateSel.find(sensorName);
+ if (it != flipStateSel.end())
+ {
+ auto eventOffsets = it->second;
+ auto targetIt = std::find(eventOffsets.begin(),
+ eventOffsets.begin(), evOffset);
+ if (targetIt != eventOffsets.end())
+ {
+ for (const auto& offset : eventOffsets)
+ {
+ if (offset == evOffset)
+ {
+ continue;
+ }
+ sensorStatusRec[sensorPath].alarmStatus &=
+ ~(statusBit << (offset * ALARM_BIT_NUM));
+ }
+ }
+ }
+ }
+ else
+ {
+ sensorStatusRec[sensorPath].alarmStatus &=
+ ~(statusBit << (evOffset * ALARM_BIT_NUM));
+ }
+ }
+ else
+ {
+ if (ed != 0)
+ {
+ sensorStatusRec[sensorPath].alarmStatus &=
+ ~(statusBit << (evOffset * ALARM_BIT_NUM));
+
+ auto it = flipStateSel.find(sensorName);
+ if (it != flipStateSel.end())
+ {
+ auto eventOffsets = it->second;
+ auto targetIt = std::find(eventOffsets.begin(),
+ eventOffsets.end(), evOffset);
+ if (targetIt != eventOffsets.end())
+ {
+ for (const auto& offset : eventOffsets)
+ {
+ if (offset == evOffset)
+ {
+ continue;
+ }
+ sensorStatusRec[sensorPath].alarmStatus &=
+ ~(statusBit << (offset * ALARM_BIT_NUM));
+ }
+ }
+ }
+ }
+ else
+ {
+ sensorStatusRec[sensorPath].alarmStatus |=
+ statusBit << (evOffset * ALARM_BIT_NUM);
+ }
+ }
+
+ if (isGenericDiscreteSensor)
+ {
+ if (ed != 0)
+ {
+ // Generic discrete sensor's events are mutually exclusive,
+ // and at the same time, only one bit of 'sensorStatus' will be set,
+ // so there is '=', not '|='
+ sensorStatusRec[sensorPath].sensorStatus = 1 << evOffset;
+ }
+ else
+ {
+ sensorStatusRec[sensorPath].sensorStatus &= ~(1 << evOffset);
+ }
+ }
+ else
+ {
+ if (ed != 0)
+ {
+ sensorStatusRec[sensorPath].sensorStatus |= 1 << evOffset;
+ }
+ else
+ {
+ sensorStatusRec[sensorPath].sensorStatus &= ~(1 << evOffset);
+ }
+ }
+}
+
+/*record led status and entity manager status*/
+inline void recordAlarmStatus(SensorStatus& statusRec,
+ const AlarmType& alarmStatus, const int& evOffset,
+ const int& ed, const bool& assertAlarm,
+ const bool& isGenericDiscreteSensor)
+{
+ uint64_t statusBit = static_cast<uint64_t>(alarmStatus);
+ if (assertAlarm)
+ {
+ if (ed)
+ {
+ statusRec.alarmStatus |= statusBit << (evOffset * ALARM_BIT_NUM);
+ }
+ else
+ {
+ statusRec.alarmStatus &= ~(statusBit << (evOffset * ALARM_BIT_NUM));
+ }
+ }
+ else
+ {
+ if (ed)
+ {
+ statusRec.alarmStatus &= ~(statusBit << (evOffset * ALARM_BIT_NUM));
+ }
+ else
+ {
+ statusRec.alarmStatus |= statusBit << (evOffset * ALARM_BIT_NUM);
+ }
+ }
+
+ if (isGenericDiscreteSensor)
+ {
+ if (ed)
+ {
+ // Generic discrete sensor's events are mutually exclusive,
+ // and at the same time, only one bit of 'sensorStatus' will be set,
+ // so there is '=', not '|='
+ statusRec.sensorStatus = 1 << evOffset;
+ }
+ else
+ {
+ statusRec.sensorStatus &= ~(1 << evOffset);
+ }
+ }
+ else
+ {
+ if (ed)
+ {
+ statusRec.sensorStatus |= 1 << evOffset;
+ }
+ else
+ {
+ statusRec.sensorStatus &= ~(1 << evOffset);
+ }
+ }
+}
+
+enum
+{
+ SYSTEM_FIRMWARE_ERROR_INDEX_START = 0x00,
+ SYSTEM_FIRMWARE_ERROR_INDEX_END = 0x0D,
+};
+
+enum
+{
+ POWER_FAULT_START_EVENT_INDEX = 0x00,
+ POWER_FAULT_END_EVENT_INDEX = 0x08,
};
+
void fillSensorDescription(const std::string& sensorPath, int eventOffset)
{
sensorStatusRec[sensorPath].description = discreteSensorNs;
@@ -599,6 +834,7 @@ void fillSensorDescription(const std::string& sensorPath, int eventOffset)
//}
}
+
void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
const std::string& sensorPath,
const SensorType& sensorType,
@@ -698,6 +934,109 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
return;
}
+void powerFaultRecAlarmStatus(const std::string& sensorPath)
+{
+ uint16_t sensorStatus = 0;
+ uint64_t alarmStatus = 0;
+ constexpr uint64_t eventType03hStateMask =
+ (1 << EVENT_TYPE_03H_STATE_DEASSERT) |
+ (1 << EVENT_TYPE_03H_STATE_ASSERT);
+
+ for (const auto& [evIndex, status] : powerFaultStatusRec)
+ {
+ sensorStatus |= (status.sensorStatus & eventType03hStateMask);
+ /*only need to record an alarm on bit0-bit2*/
+ uint64_t alarm = status.alarmStatus;
+ if (ALARM_STATUS_MASK_C & alarm)
+ {
+ alarmStatus |= CRITICAL;
+ }
+ else if (ALARM_STATUS_MASK_NR & alarm)
+ {
+ alarmStatus |= NONRECOV;
+ }
+ else if (ALARM_STATUS_MASK_NC & alarm)
+ {
+ alarmStatus |= NONCRITICAL;
+ }
+ }
+
+ sensorStatusRec[sensorPath].sensorStatus = sensorStatus;
+ sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
+}
+
+struct AlarmAction
+{
+ AlarmType alarmStatus;
+ bool assertToAlarm; /*true: assert to alarm; false: deassert to alarm*/
+};
+
+/*event offset, action*/
+using EventActions = std::unordered_map<uint8_t, AlarmAction>;
+
+/*event type, all actions*/
+using EventAlarm = std::unordered_map<uint8_t, EventActions>;
+
+ void parseDiscreteGenericSelSeverity(
+ sdbusplus::bus::bus& bus, const std::string& sensorPath,
+ const SensorType& sensorType, const uint8_t& eventType,
+ const std::string& eventData, const std::string& eventDir,
+ const AlarmType& severity, const bool& assertToAlarm)
+{
+ // The sensorStatusRec[sensorPath] obj will be created when init the
+ // 'Status'. See: initDiscreteSensorStatusInfo() and sensorMatchHandler().
+ // If true, it means that the 'Status' has been initialized
+ // and the status sensor object on the entity-manager has been created.
+
+ // if (sensorStatusRec.find(sensorPath) == sensorStatusRec.end())
+ // {
+ // lg2::error(
+ // "sensorPath not found in sensorStatusRec: {PATH}, add sensorPath into getPathfailedRec",
+ // "PATH", sensorPath);
+ // SelSeverityInfo severityInfo(sensorPath, sensorType, eventType,
+ // eventData, eventDir, severity,
+ // assertToAlarm);
+ // getPathfailedRec[sensorPath].push_back(severityInfo);
+ // return;
+ // }
+
+ std::string eventData1 = eventData.substr(0, 2);
+ int ev = std::stol(eventData1, nullptr, 16);
+ int ed = std::stol(eventDir);
+ int ev1Offset = ev & SENSOR_EVENT_DATA1_EVENT_OFFSET;
+
+ if (sensorType != SENSOR_TYPE_POWER_FAULT)
+ {
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertToAlarm,
+ true);
+ }
+ else
+ {
+ std::string eventData2 = eventData.substr(2, 2);
+ int ev2Index = std::stol(eventData2, nullptr, 16);
+
+ if (ev2Index < POWER_FAULT_START_EVENT_INDEX ||
+ ev2Index > POWER_FAULT_END_EVENT_INDEX)
+ {
+ lg2::error("Invalid event index = {INDEX}", "INDEX", ev2Index);
+ return;
+ }
+
+ recordAlarmStatus(powerFaultStatusRec[ev2Index], severity, ev1Offset,
+ ed, assertToAlarm, true);
+ powerFaultRecAlarmStatus(sensorPath);
+ }
+
+ sensorStatusRec[sensorPath].eventType = eventType;
+ sensorStatusRec[sensorPath].sensorType = sensorType;
+
+ setDiscreteSensorStatusValue(bus, sensorPath, eventData);
+
+ //updateSensorStatus(bus, sensorPath);
+
+ //controlHealthLed(bus);
+}
+
void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
{
//AlarmType severity = NORMAL;
@@ -728,7 +1067,9 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
uint8_t typeCode = 0;
uint8_t sensorType = 0;
- std::string sensorData, sensorPath, eventDir;
+ std::string sensorData, sensorPath, eventDir, assertAlarm;
+ bool assertToAlarm;
+ AlarmType confSeverity = AlarmType::NORMAL;
for (auto& item : additionalDatas)
{
std::string::size_type nStr;
@@ -760,6 +1101,16 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
std::cerr << "sensorPath " << sensorPath <<"\n";
}
}
+
+ if (assertAlarm.empty())
+ {
+ nStr = item.find("ASSERT_ALARM=");
+ if (std::string::npos != nStr)
+ {
+ assertAlarm = item.substr(nStr + strlen("ASSERT_ALARM="));
+ assertToAlarm = std::stol(assertAlarm, nullptr, 10);
+ }
+ }
}
if (!ipmiSensors)
@@ -795,9 +1146,19 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
else if (typeCode == SPECIFIC_SENSOR_TYPE)
{
// discrete
- parseSpecificSensorSelSeverity(
+ parseSpecificSensorSelSeverity(
bus, sensorPath, static_cast<SensorType>(sensorType), sensorData,
eventDir);
+ }else if (typeCode >= GENERIC_START_SENSOR_TYPE &&
+ typeCode <= GENERIC_END_SENSOR_TYPE)
+ {
+ parseDiscreteGenericSelSeverity(
+ bus, sensorPath, static_cast<SensorType>(sensorType), typeCode,
+ sensorData, eventDir, confSeverity, assertToAlarm);
+ }
+ else
+ {
+ return;
}
//controlHealthLed(bus);
diff --git a/fault-monitor/fru-fault-monitor.hpp b/fault-monitor/fru-fault-monitor.hpp
index bd4a852..0dacc0c 100644
--- a/fault-monitor/fru-fault-monitor.hpp
+++ b/fault-monitor/fru-fault-monitor.hpp
@@ -118,9 +118,10 @@ struct SensorStatusInfo
uint16_t sensorStatus;
uint64_t alarmStatus;
std::string description; // add description for discrete sensor
+ uint8_t sdrType; // Only for discrete sensors
};
-struct DriveStatus
+struct SensorStatus
{
uint16_t sensorStatus; /*entity status*/
uint64_t alarmStatus; /*alarm status*/
--
2.25.1
@@ -0,0 +1,626 @@
From 133f696e0a75c446b012822473d39b793c77ebc5 Mon Sep 17 00:00:00 2001
From: "Wang.Bin" <Bin-B.Wang@luxshare-ict.com>
Date: Sat, 14 Dec 2024 14:42:08 +0800
Subject: [PATCH 5/5] Clear Status of sensors when power on
---
fault-monitor/fru-fault-monitor.cpp | 300 +++++++++++++++++++++-------
fault-monitor/fru-fault-monitor.hpp | 62 +++++-
fault-monitor/meson.build | 1 +
3 files changed, 282 insertions(+), 81 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index b9f687c..1bc41aa 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -7,6 +7,8 @@
#include <xyz/openbmc_project/Common/error.hpp>
#include <string>
#include <vector>
+#include <string>
+#include <vector>
#include <iostream>
extern "C"
@@ -67,6 +69,8 @@ using ResourceNotFoundErr =
using InvalidArgumentErr =
sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
+bool Add::isPoweredOn = false;
+
constexpr const char* discreteSensorNs = "No state defined";
enum AlarmType : uint64_t
@@ -430,8 +434,10 @@ std::string getService(sdbusplus::bus_t& bus, const std::string& path)
return mapperResponse.cbegin()->first;
}
+using AdditionalList = std::vector<std::string>;
+
static void setDiscreteSensorStatusValue(sdbusplus::bus::bus& bus,
- const std::string& sensorPath,const std::string& sensorData)
+ const std::string& sensorPath)
{
// IPMI spec Table 35-15
// For discrete reading sensors only. (Optional)
@@ -445,13 +451,13 @@ static void setDiscreteSensorStatusValue(sdbusplus::bus::bus& bus,
constexpr auto dbusProperties = "org.freedesktop.DBus.Properties";
constexpr auto statusInterface = "xyz.openbmc_project.Configuration.Status";
- unsigned long dataValue = strtoul(sensorData.c_str(), NULL, 16);
statusValue = static_cast<double>(statusValue +
- (0x01 << ((dataValue & 0x0f0000) >> 16)));
+ sensorStatusRec[sensorPath].sensorStatus);
auto method = bus.new_method_call(service, sensorPath.c_str(),
dbusProperties, "Set");
std::variant<double> value{(double)statusValue};
- std::cerr << "SEL:sensorData = " << sensorData << std::endl;
+ std::cerr << "SEL:sensorData = " << sensorPath << std::endl;
+ std::cerr << "SEL:sensorStatus = " << sensorStatusRec[sensorPath].sensorStatus << std::endl;
method.append(statusInterface, "Status", value);
try
{
@@ -576,18 +582,16 @@ void action(sdbusplus::bus_t& bus, const std::string& path, bool assert)
return;
}
- auto pos = path.rfind("/");
- if (pos == std::string::npos)
+ std::string ledPath = ledGroups + path;
+
+ if (assert)
{
- using namespace xyz::openbmc_project::Common;
- report<InvalidArgumentErr>(
- InvalidArgument::ARGUMENT_NAME("path"),
- InvalidArgument::ARGUMENT_VALUE(path.c_str()));
- return;
+ lg2::info("{PATH} is on", "PATH", ledPath);
+ }
+ else
+ {
+ lg2::info("{PATH} is off", "PATH", ledPath);
}
- auto unit = path.substr(pos + 1);
-
- std::string ledPath = ledGroups + unit + '_' + LED_FAULT;
auto method = bus.new_method_call(service.c_str(), ledPath.c_str(),
"org.freedesktop.DBus.Properties", "Set");
@@ -609,6 +613,24 @@ void action(sdbusplus::bus_t& bus, const std::string& path, bool assert)
return;
}
+enum
+{
+ NC_L2L_SEVERITY = 0x00,
+ NC_L2H_SEVERITY = 0x01,
+ NC_H2L_SEVERITY = 0x06,
+ NC_H2H_SEVERITY = 0x07,
+
+ CR_L2L_SEVERITY = 0x02,
+ CR_L2H_SEVERITY = 0x03,
+ CR_H2L_SEVERITY = 0x08,
+ CR_H2H_SEVERITY = 0x09,
+
+ NR_L2L_SEVERITY = 0x04,
+ NR_L2H_SEVERITY = 0x05,
+ NR_H2L_SEVERITY = 0x0A,
+ NR_H2H_SEVERITY = 0x0B
+};
+
enum
{
UNSPECIFY_SENSOR_TYPE = 0x00,
@@ -620,6 +642,41 @@ enum
OEM_END_SENSOR_TYPE = 0x7F
};
+void lightUpHealthLed(sdbusplus::bus::bus& bus, AlarmType ledStatus)
+{
+ switch (ledStatus)
+ {
+ case NORMAL:
+ action(bus, "status_ok", true);
+ action(bus, "status_non_critical", false);
+ action(bus, "status_critical", false);
+ action(bus, "status_non_recoverable", false);
+ break;
+ case NONCRITICAL:
+ action(bus, "status_ok", false);
+ action(bus, "status_non_critical", true);
+ action(bus, "status_critical", false);
+ action(bus, "status_non_recoverable", false);
+ break;
+ case CRITICAL:
+ action(bus, "status_ok", false);
+ action(bus, "status_non_critical", false);
+ action(bus, "status_critical", true);
+ action(bus, "status_non_recoverable", false);
+ break;
+ case NONRECOV:
+ action(bus, "status_ok", false);
+ action(bus, "status_non_critical", false);
+ action(bus, "status_critical", false);
+ action(bus, "status_non_recoverable", true);
+ break;
+ default:
+ lg2::error("ERROR: Invalid led status {STATUS}", "STATUS",
+ static_cast<int>(ledStatus));
+ break;
+ }
+}
+
inline void recordAlarmStatus(const std::string& sensorPath,
AlarmType alarmStatus, int evOffset, int ed,
bool assertAlarm,
@@ -834,12 +891,34 @@ void fillSensorDescription(const std::string& sensorPath, int eventOffset)
//}
}
+// void parseThresholdSelSeverity(sdbusplus::bus::bus& bus,
+// const std::string& sensorPath,
+// const SensorType& sensorType,
+// const std::string& eventData,
+// const std::string& eventDir,
+// const AlarmType& severity,
+// const bool& assertToAlarm)
+// {
+// std::string eventData1 = eventData.substr(0, 2);
+// int ev = std::stol(eventData1, nullptr, 16);
+// int ed = std::stol(eventDir);
+
+// ev = (ev & SENSOR_EVENT_DATA1_EVENT_OFFSET);
+
+// recordAlarmStatus(sensorPath, severity, ev, ed, assertToAlarm, false);
+
+// sensorStatusRec[sensorPath].eventType = THRESHOLD_SENSOR_TYPE;
+// sensorStatusRec[sensorPath].sensorType = sensorType;
+
+// }
void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
const std::string& sensorPath,
const SensorType& sensorType,
const std::string& eventData,
- const std::string& eventDir)
+ const std::string& eventDir,
+ const AlarmType& severity,
+ const bool& assertAlarm)
{
std::string eventData1 = eventData.substr(0, 2);
int ev = std::stol(eventData1, nullptr, 16);
@@ -854,6 +933,8 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
{
case SYSTEM_EVENT_LOG_CLEARED:
{
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertAlarm,
+ false);
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
break;
}
@@ -872,6 +953,8 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
case SLEEP_BUTTON_PRESSED:
case RESET_BUTTON_PRESSED:
{
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertAlarm,
+ false);
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
break;
}
@@ -884,6 +967,8 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
}
case SENSOR_TYPE_POWER_SUPPLY:
{
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertAlarm,
+ true);
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
break;
}
@@ -894,6 +979,11 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
case ACPI_S0_STATE:
case ACPI_S5_STATE:
{
+ // The S0 State and S5 State of ACPI State will only exist
+ // one, so the passed in arg6: isGenericDiscreteSensor is
+ // true.
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed,
+ assertAlarm, true);
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
break;
}
@@ -910,26 +1000,34 @@ void parseSpecificSensorSelSeverity(sdbusplus::bus::bus& bus,
}
case SENSOR_TYPE_MEMORY:
{
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertAlarm,
+ false);
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
setDimmLEDState(bus, sensorPath, "FAULT");
break;
}
case SENSOR_TYPE_PROCESSOR:
{
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertAlarm,
+ false);
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
break;
}
case SENSOR_TYPE_WATCHDOG_2:
{
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertAlarm,
+ false);
sensorStatusRec[sensorPath].alarmStatus = alarmStatus;
break;
}
default:
+ recordAlarmStatus(sensorPath, severity, ev1Offset, ed, assertAlarm,
+ false);
break;
}
sensorStatusRec[sensorPath].eventType = SPECIFIC_SENSOR_TYPE;
sensorStatusRec[sensorPath].sensorType = sensorType;
- setDiscreteSensorStatusValue(bus, sensorPath, eventData);
+ setDiscreteSensorStatusValue(bus, sensorPath);
if(0)
{
fillSensorDescription(sensorPath, ev1Offset);
@@ -992,7 +1090,6 @@ using EventAlarm = std::unordered_map<uint8_t, EventActions>;
// 'Status'. See: initDiscreteSensorStatusInfo() and sensorMatchHandler().
// If true, it means that the 'Status' has been initialized
// and the status sensor object on the entity-manager has been created.
-
// if (sensorStatusRec.find(sensorPath) == sensorStatusRec.end())
// {
// lg2::error(
@@ -1034,17 +1131,14 @@ using EventAlarm = std::unordered_map<uint8_t, EventActions>;
sensorStatusRec[sensorPath].eventType = eventType;
sensorStatusRec[sensorPath].sensorType = sensorType;
-
- setDiscreteSensorStatusValue(bus, sensorPath, eventData);
+ setDiscreteSensorStatusValue(bus, sensorPath);
//updateSensorStatus(bus, sensorPath);
- //controlHealthLed(bus);
}
void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
{
- //AlarmType severity = NORMAL;
auto method = bus.new_method_call(logService, path.c_str(),
"org.freedesktop.DBus.Properties", "Get");
method.append("xyz.openbmc_project.Logging.Entry");
@@ -1072,7 +1166,7 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
uint8_t typeCode = 0;
uint8_t sensorType = 0;
- std::string sensorData, sensorPath, eventDir, assertAlarm;
+ std::string sensorData, sensorPath, eventDir, assertAlarm, confSeverityStr;
bool assertToAlarm;
AlarmType confSeverity = AlarmType::NORMAL;
for (auto& item : additionalDatas)
@@ -1153,7 +1247,7 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
// discrete
parseSpecificSensorSelSeverity(
bus, sensorPath, static_cast<SensorType>(sensorType), sensorData,
- eventDir);
+ eventDir, confSeverity, assertToAlarm);
}else if (typeCode >= GENERIC_START_SENSOR_TYPE &&
typeCode <= GENERIC_END_SENSOR_TYPE)
{
@@ -1166,8 +1260,6 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
return;
}
- //controlHealthLed(bus);
-
return;
}
@@ -1479,6 +1571,100 @@ void Add::dimmLEDMatchHandler(sdbusplus::message_t& msg)
updateSysHealthLED(dimmSensorLEDStatus);
}
+void Add::clearCPUStatusAlarm(SensorStatusInfo& statusInfo)
+{
+ constexpr std::array<uint16_t, 7> cpuStatToClear{
+ IPMI_CPU_IERR, IPMI_CPU_FRB2_HANG, IPMI_CPU_CONFIG_ERROR,
+ IPMI_CPU_THROTTLED, IPMI_CPU_DISABLED, IPMI_CPU_MCE,
+ IPMI_CPU_CMCE};
+
+ for (const auto& offset : cpuStatToClear)
+ {
+ statusInfo.sensorStatus &= ~(1 << offset);
+ statusInfo.alarmStatus &= ~(ALARM_ALL_BITS << (offset * ALARM_BIT_NUM));
+ }
+}
+
+void Add::clearMEMStatusAlarm(SensorStatusInfo& statusInfo)
+{
+ constexpr std::array<uint16_t, 5> memStatToClear{
+ MEMORY_OFFSET_CORRECTABLE_ECC, MEMORY_OFFSET_UNCORRECTABLE_ECC,
+ MEMORY_OFFSET_MEMORY_DEVICE_DISABLED,
+ MEMORY_OFFSET_CORRECTABLE_ECC_LOG_LIMIT_REACHED,
+ MEMORY_OFFSET_CONFIGURATION_ERROR};
+
+ for (const auto& offset : memStatToClear)
+ {
+ statusInfo.sensorStatus &= ~(1 << offset);
+ statusInfo.alarmStatus &= ~(ALARM_ALL_BITS << (offset * ALARM_BIT_NUM));
+ }
+}
+
+void Add::clearPCIEStatusAlarm(SensorStatusInfo& statusInfo)
+{
+ constexpr std::array<uint16_t, 6> pcieStatToClear{
+ CRITICAL_INTERRUPT_OFFSET_PCI_PERR,
+ CRITICAL_INTERRUPT_OFFSET_PCI_SERR,
+ CRITICAL_INTERRUPT_OFFSET_BUS_CORRECTABLE_ERROR,
+ CRITICAL_INTERRUPT_OFFSET_BUS_UNCORRECTABLE_ERRPR,
+ CRITICAL_INTERRUPT_OFFSET_BUS_FATAL_ERROR,
+ CRITICAL_INTERRUPT_OFFSET_BUS_DEGRADED};
+
+ for (const auto& offset : pcieStatToClear)
+ {
+ statusInfo.sensorStatus &= ~(1 << offset);
+ statusInfo.alarmStatus &= ~(ALARM_ALL_BITS << (offset * ALARM_BIT_NUM));
+ }
+}
+
+void Add::clearFirmwareProgressAlarm(SensorStatusInfo& statusInfo)
+{
+ constexpr std::array<uint16_t, 2> statusToClear{
+ SYSTEM_FIRMWARE_PROGRESS_OFFSET_ERROR,
+ SYSTEM_FIRMWARE_PROGRESS_OFFSET_HANG};
+
+ for (const auto& offset : statusToClear)
+ {
+ statusInfo.sensorStatus &= ~(1 << offset);
+ statusInfo.alarmStatus &= ~(ALARM_ALL_BITS << (offset * ALARM_BIT_NUM));
+ }
+}
+
+void Add::deassertOnPowerReset(void)
+{
+ for (auto& [sensorObj, statusInfo] : sensorStatusRec)
+ {
+ if (statusInfo.eventType != SPECIFIC_SENSOR_TYPE)
+ {
+ continue;
+ }
+
+ if (SENSOR_TYPE_PROCESSOR == statusInfo.sensorType)
+ {
+ clearCPUStatusAlarm(statusInfo);
+ }
+ else if (SENSOR_TYPE_MEMORY == statusInfo.sensorType)
+ {
+ clearMEMStatusAlarm(statusInfo);
+ }
+ else if (SENSOR_TYPE_CRITICAL_INTERRUPT == statusInfo.sensorType)
+ {
+ clearPCIEStatusAlarm(statusInfo);
+ }
+ else if (SENSOR_TYPE_SYSTEM_FIRMWARE_PROGRESS == statusInfo.sensorType)
+ {
+ clearFirmwareProgressAlarm(statusInfo);
+ }
+ else
+ {
+ continue;
+ }
+
+ setDiscreteSensorStatusValue(bus, sensorObj);
+ }
+
+}
+
void getLoggingSubTree(sdbusplus::bus_t& bus, MapperResponseType& subtree)
{
auto depth = 0;
@@ -1513,60 +1699,22 @@ void Add::createAssociation(sdbusplus::asio::object_server& objectServer)
faultMonitorAssociation->initialize();
}
-void Add::processExistingCallouts(sdbusplus::bus_t& bus)
+void Add::initPowerStatus()
{
- MapperResponseType mapperResponse;
-
- getLoggingSubTree(bus, mapperResponse);
- if (mapperResponse.empty())
- {
- // No errors to process.
- return;
- }
-
- for (const auto& elem : mapperResponse)
+ try
{
- auto method = bus.new_method_call(
- elem.second.begin()->first.c_str(), elem.first.c_str(),
- "org.freedesktop.DBus.Properties", "Get");
- method.append("xyz.openbmc_project.Association.Definitions");
- method.append("Associations");
- auto reply = bus.call(method);
- if (reply.is_method_error())
- {
- // do not stop, continue with next elog
- lg2::error("Error in getting associations");
- continue;
- }
-
- std::variant<AssociationList> assoc;
- try
- {
- reply.read(assoc);
- }
- catch (const sdbusplus::exception_t& e)
- {
- lg2::error(
- "Failed to parse existing callouts associations message, ERROR = {ERROR}",
- "ERROR", e);
- continue;
- }
- auto& assocs = std::get<AssociationList>(assoc);
- if (assocs.empty())
- {
- // no associations, skip
- continue;
- }
-
- for (const auto& item : assocs)
- {
- if (std::get<1>(item).compare(CALLOUT_REV_ASSOCIATION) == 0)
- {
- removeWatches.emplace_back(
- std::make_unique<Remove>(bus, std::get<2>(item)));
- action(bus, std::get<2>(item), true);
- }
+ auto ret = dBusHandler.getProperty(hostPath, hostInterface,
+ hostProperty);
+ auto status = std::get<std::string>(ret);
+ if (status.size() >= running.size()){
+ isPoweredOn = (status.compare(status.size() - running.size(),
+ running.size(), running.data()) == 0);
}
+ }
+ catch (const sdbusplus::exception::exception& e)
+ {
+ log<level::ERR>("Failed to get power status",
+ entry("ERROR=%s", e.what()));
}
}
diff --git a/fault-monitor/fru-fault-monitor.hpp b/fault-monitor/fru-fault-monitor.hpp
index 0dacc0c..185693b 100644
--- a/fault-monitor/fru-fault-monitor.hpp
+++ b/fault-monitor/fru-fault-monitor.hpp
@@ -2,7 +2,10 @@
#include "config.h"
+#include "../utils.hpp"
+
#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/server.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
@@ -26,6 +29,13 @@ namespace fault
{
namespace monitor
{
+constexpr auto hostBusname = "xyz.openbmc_project.State.Host";
+constexpr auto hostInterface = "xyz.openbmc_project.State.Host";
+constexpr auto hostPath = "/xyz/openbmc_project/state/host0";
+constexpr auto hostProperty = "CurrentHostState";
+constexpr std::string_view running = "Running";
+
+using namespace phosphor::led::utils;
constexpr auto faultLedPath = "/xyz/openbmc_project/led/groups/status_fault";
constexpr auto dimmfaultLedPath = "/xyz/openbmc_project/led/groups/dimm_fault";
constexpr auto okLedPath = "/xyz/openbmc_project/led/groups/status_ok";
@@ -155,6 +165,19 @@ class Add
"/xyz/openbmc_project/logging"),
std::bind(std::mem_fn(&Add::created), this,
std::placeholders::_1)),
+ powerMatch(bus,
+ sdbusplus::bus::match::rules::propertiesChanged(
+ hostPath, hostInterface),
+ [this](sdbusplus::message::message& message) {
+ std::string objectName;
+ std::map<std::string, std::variant<std::string>> values;
+ message.read(objectName, values);
+ auto findState = values.find(hostProperty);
+ if (findState != values.end())
+ {
+ deassertOnPowerReset();
+ }
+ }),
dimmLEDMatch(bus,
"type='signal',member='PropertiesChanged',path_namespace='" +
std::string(dimmSensorPath) + "',arg0namespace='" +
@@ -165,7 +188,7 @@ class Add
createAssociation(objectServer);
dimmledInit();
- processExistingCallouts(bus);
+ initPowerStatus();
}
@@ -174,12 +197,45 @@ class Add
/** @brief sdbusplus signal match for fault created */
sdbusplus::bus::match_t matchCreated;
+ /** Match for host power monitor */
+ sdbusplus::bus::match::match powerMatch;
+
sdbusplus::bus::match_t dimmLEDMatch;
std::vector<std::unique_ptr<Remove>> removeWatches;
std::shared_ptr<sdbusplus::asio::dbus_interface> faultMonitorAssociation;
+ /** @brief Initialize the host power status*/
+ void initPowerStatus();
+
+ /** @brief clear CPU alarm status
+ */
+ void clearCPUStatusAlarm(SensorStatusInfo& statusInfo);
+
+ /** @brief clear MEM alarm status
+ */
+ void clearMEMStatusAlarm(SensorStatusInfo& statusInfo);
+
+ /** @brief clear PCIE alarm status
+ */
+ void clearPCIEStatusAlarm(SensorStatusInfo& statusInfo);
+
+ /** @brief clear FIRMWARE alarm status
+ */
+ void clearFirmwareProgressAlarm(SensorStatusInfo& statusInfo);
+
+ /** @brief deassert some alarm bits when the host power restarts.
+ */
+ void deassertOnPowerReset(void);
+
+ /* DBusHandler class handles the D-Bus operations */
+ DBusHandler dBusHandler;
+
+ public:
+ /** @brief Indicate if the host status is power on */
+ static bool isPoweredOn;
+
/** @brief Callback function for fru fault created
* @param[in] msg - Data associated with subscribed signal
*/
@@ -201,10 +257,6 @@ class Add
void createAssociation(sdbusplus::asio::object_server& objectServer);
- /** @brief This function process all callouts at application start
- * @param[in] bus - The Dbus bus object
- */
- void processExistingCallouts(sdbusplus::bus_t& bus);
};
/** @class Remove
diff --git a/fault-monitor/meson.build b/fault-monitor/meson.build
index 7ced362..a36ef80 100644
--- a/fault-monitor/meson.build
+++ b/fault-monitor/meson.build
@@ -10,6 +10,7 @@ if get_option('monitor-operational-status').enabled()
else
fault_monitor_sources += [
'fru-fault-monitor.cpp',
+ '../utils.cpp',
]
endif
--
2.25.1
@@ -0,0 +1,110 @@
From 16a84c977b6a360d7f6a12f578d0480f4c00ec76 Mon Sep 17 00:00:00 2001
From: "Wang.Bin" <Bin-B.Wang@luxshare-ict.com>
Date: Thu, 19 Dec 2024 15:42:26 +0800
Subject: [PATCH 6/6] Fix sensor status being cleared due to warm reset during
the power on
---
fault-monitor/fru-fault-monitor.cpp | 36 +++++++++++++++++++++++++++++
fault-monitor/fru-fault-monitor.hpp | 12 +++++++++-
2 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index 1bc41aa..f8cac9b 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -1632,6 +1632,37 @@ void Add::clearFirmwareProgressAlarm(SensorStatusInfo& statusInfo)
void Add::deassertOnPowerReset(void)
{
+ std::cout << "Get the current host state" <<std::endl;
+ std::this_thread::sleep_for(std::chrono::milliseconds(5000));
+ // Get the current host state
+ constexpr auto HOST_INTERFACE = "xyz.openbmc_project.State.Host";
+ std::string HOST_PATH = "/xyz/openbmc_project/state/host0";
+ std::string HOST_PROP = "CurrentHostState";
+ sdbusplus::bus_t bus= sdbusplus::bus::new_default();;
+ std::string settingService = "xyz.openbmc_project.State.Host";
+ auto method = bus.new_method_call(settingService.c_str(), HOST_PATH.c_str(),
+ "org.freedesktop.DBus.Properties", "Get");
+ method.append(HOST_INTERFACE, HOST_PROP);
+ std::variant<std::string> propertyValue{};
+ std::string value;
+ try
+ {
+ auto reply = bus.call(method);
+ reply.read(propertyValue);
+ value = std::get<std::string>(propertyValue);
+ std::cerr << "value:" << value << "\n";
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "exception:" << e.what() << "\n";
+ }
+
+ if (value == "xyz.openbmc_project.State.Host.HostState.Running"){
+ std::cout << "power onDo not clear the sensor status" <<std::endl;
+ return;
+ }
+ // Clear the sensor status
+ std::cout << "Clear the sensor status" <<std::endl;
for (auto& [sensorObj, statusInfo] : sensorStatusRec)
{
if (statusInfo.eventType != SPECIFIC_SENSOR_TYPE)
@@ -1641,18 +1672,22 @@ void Add::deassertOnPowerReset(void)
if (SENSOR_TYPE_PROCESSOR == statusInfo.sensorType)
{
+ std::cout << "clearCPUStatusAlarm" <<std::endl;
clearCPUStatusAlarm(statusInfo);
}
else if (SENSOR_TYPE_MEMORY == statusInfo.sensorType)
{
+ std::cout << "clearMEMStatusAlarm" <<std::endl;
clearMEMStatusAlarm(statusInfo);
}
else if (SENSOR_TYPE_CRITICAL_INTERRUPT == statusInfo.sensorType)
{
+ std::cout << "clearPCIEStatusAlarm" <<std::endl;
clearPCIEStatusAlarm(statusInfo);
}
else if (SENSOR_TYPE_SYSTEM_FIRMWARE_PROGRESS == statusInfo.sensorType)
{
+ std::cout << "clearFirmwareProgressAlarm" <<std::endl;
clearFirmwareProgressAlarm(statusInfo);
}
else
@@ -1701,6 +1736,7 @@ void Add::createAssociation(sdbusplus::asio::object_server& objectServer)
void Add::initPowerStatus()
{
+ std::cout << "initPowerStatus." <<std::endl;
try
{
auto ret = dBusHandler.getProperty(hostPath, hostInterface,
diff --git a/fault-monitor/fru-fault-monitor.hpp b/fault-monitor/fru-fault-monitor.hpp
index 185693b..8eeb6e5 100644
--- a/fault-monitor/fru-fault-monitor.hpp
+++ b/fault-monitor/fru-fault-monitor.hpp
@@ -175,7 +175,17 @@ class Add
auto findState = values.find(hostProperty);
if (findState != values.end())
{
- deassertOnPowerReset();
+ auto status = std::get<std::string>(findState->second);
+ if (status.size() >= running.size())
+ {
+ isPoweredOn =
+ (status.compare(status.size() - running.size(),
+ running.size(), running.data()) == 0);
+ if (!isPoweredOn)
+ {
+ deassertOnPowerReset();
+ }
+ }
}
}),
dimmLEDMatch(bus,
--
2.25.1
@@ -0,0 +1,147 @@
From baa59772c55c45a237d471b1227296d09b33705d Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Thu, 19 Dec 2024 19:11:25 +0800
Subject: [PATCH] Retrieve SEL sensor info from JSON file instead of calling
from IPMI service
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
fault-monitor/fru-fault-monitor.cpp | 95 +++++++++++++++++++++++++----
1 file changed, 83 insertions(+), 12 deletions(-)
diff --git a/fault-monitor/fru-fault-monitor.cpp b/fault-monitor/fru-fault-monitor.cpp
index 1bc41aa..a64f375 100644
--- a/fault-monitor/fru-fault-monitor.cpp
+++ b/fault-monitor/fru-fault-monitor.cpp
@@ -5,11 +5,16 @@
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/exception.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
+#include <nlohmann/json.hpp>
+#include <phosphor-logging/lg2.hpp>
#include <string>
#include <vector>
#include <string>
#include <vector>
#include <iostream>
+#include <unordered_map>
+#include <filesystem>
+#include <fstream>
extern "C"
{
@@ -230,6 +235,14 @@ using AdditionalList = std::vector<std::string>;
using sensorCodes = std::vector<uint8_t>;
using ipmiSensorsInfo = std::unordered_map<std::string, sensorCodes>;
std::optional<ipmiSensorsInfo> ipmiSensors;
+struct SensorInfo
+{
+ std::string sensorName;
+ uint8_t readingType;
+ uint8_t sensorType;
+};
+
+using SensorMessages = std::unordered_map<std::string, SensorInfo>;
const std::unordered_map<uint8_t, discrectSensorEvent> genericEventTypes{
{0x03,
@@ -376,6 +389,72 @@ static const std::unordered_map<std::string, std::vector<uint8_t>>
EVENT_TYPE_07H_TRANSITION_TO_NC_FROM_OK}},
};
+static constexpr auto sensorJsonPath =
+ "/usr/share/ipmi-providers/sensor-data-record.json";
+
+SensorMessages loadSensorFromJson()
+{
+ try
+ {
+ const std::filesystem::path path(sensorJsonPath);
+ SensorMessages sensorMessages;
+ const nlohmann::json empty{};
+ nlohmann::json js;
+ if (!std::filesystem::exists(path) || std::filesystem::is_empty(path))
+ {
+ std::cout << "Incorrect File Path or empty file, FILE_PATH = "
+ << path << std::endl;
+ return sensorMessages;
+ }
+
+ try
+ {
+ std::ifstream jsonFile(path);
+ js = nlohmann::json::parse(jsonFile);
+ }
+ catch (const std::exception& e)
+ {
+ std::cout << "Failed to parse config file, ERROR = " << e.what()
+ << ", FILE_PATH = " << path << std::endl;
+ throw std::runtime_error("Failed to parse config file");
+ }
+
+ for (const auto& sensor : js.items())
+ {
+ SensorInfo info;
+ std::string sensorPath = sensor.key();
+ auto sensorParam = sensor.value();
+ info.sensorName = sensorParam["sensorName"];
+ info.readingType = sensorParam["sensorReadingType"];
+ info.sensorType = sensorParam["sensorType"];
+ sensorMessages.insert(std::make_pair(sensorPath, std::move(info)));
+ }
+ return sensorMessages;
+ }
+ catch (const std::exception& e)
+ {
+ throw std::runtime_error("Failed to parse sensor config file");
+ }
+}
+
+const SensorMessages& getSensorMessages()
+{
+ static const SensorMessages sensorMessages = loadSensorFromJson();
+ return sensorMessages;
+}
+
+std::optional<SensorInfo>
+ getSensorInfo(const std::string& sensorPath)
+{
+ const auto& sensorMessages = getSensorMessages();
+ auto ite = sensorMessages.find(sensorPath);
+ if (ite == sensorMessages.end())
+ {
+ return std::nullopt;
+ }
+ return std::make_optional(ite->second);
+}
+
std::optional<ipmiSensorsInfo> initIPMISensorInfo(sdbusplus::bus::bus& bus)
{
constexpr auto service = "xyz.openbmc_project.Ipmi.Host";
@@ -1212,19 +1291,11 @@ void Add::filterSEL(sdbusplus::bus::bus& bus, const std::string& path)
}
}
- if (!ipmiSensors)
+ auto sensorInfo = getSensorInfo(sensorPath);
+ if (sensorInfo != std::nullopt)
{
- ipmiSensors = initIPMISensorInfo(bus);
- }
-
- if (ipmiSensors)
- {
- auto iter = ipmiSensors->find(sensorPath);
- if (iter != ipmiSensors->end())
- {
- sensorType = iter->second[0];
- typeCode = iter->second[1];
- }
+ sensorType = sensorInfo->sensorType;
+ typeCode = sensorInfo->readingType;
}
if (sensorData == "" || typeCode == 0 || eventDir == "" || sensorType == 0)
--
2.34.1
@@ -0,0 +1,22 @@
#!/bin/bash
if [ "$#" -ne 3 ]; then
echo "Usage: ./dimm_led_test.sh <CPU> <LETTER> <LED_STATE>"
echo "CPU: 0~1"
echo "LETTER: A~L"
echo "LED_STATE: ON, FAULT, OFF, NA"
echo "Example: ./dimm_led_test.sh 0 A ON"
exit 1
fi
CPU=\$1
LETTER=\$2
LED_STATE=\$3
BASE_COMMAND="busctl set-property xyz.openbmc_project.DIMMTempSensor"
COMMAND="${BASE_COMMAND} /xyz/openbmc_project/sensors/temperature/DIMM_CPU${CPU}_${LETTER}_Temp xyz.openbmc_project.Sensor.dimmLED LEDState s \"${LED_STATE}\""
echo "Executing: $COMMAND at $(date)"
eval $COMMAND
@@ -0,0 +1,24 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
DEPENDS += "i2c-tools"
SRC_URI += "file://0001-Add-discrete-sensor-status-parsing-according-to-sel.patch \
file://0001-Remove-dissen-path-update-sensor-status.patch \
file://0001-Add-DIMM-Status-discrete-sensors.patch \
file://0002-Add-power-button-and-PSU-status-sensor.patch \
file://0001-Implement-DIMM-LED-control.patch \
file://0003-Add-BMC-Boot-sensor.patch \
file://0001-Add-PROCESSOR-sensor-type.patch \
file://0001-Enable-Orange-LED-to-indicate-if-dimm-is-present.patch \
file://0004-Support-discrete-generic-sensors.patch \
file://0001-Add-watchdog2-sensor-type.patch \
file://0005-Clear-Status-of-sensors-when-power-on.patch \
file://0006-Fix-sensor-status-being-cleared-due-to-warm-reset.patch \
file://0007-Retrieve-SEL-sensor-info-from-JSON-file-instead-of-c.patch \
file://dimm_led_test.sh \
"
do_install:append () {
install -d ${D}${bindir}
install -m 0755 ${WORKDIR}/dimm_led_test.sh ${D}${bindir}/
}