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,24 @@
From 36194f5e0e2ba0b7839b84b47a1622ca5c0a0653 Mon Sep 17 00:00:00 2001
From: hliangs90 <hliangs90@gmail.com>
Date: Wed, 14 Aug 2024 22:36:47 +0800
Subject: [PATCH] Add VersionPurpose CPLD To Support CPLD Component.
Signed-off-by: hliangs90 <hliangs90@gmail.com>
---
yaml/xyz/openbmc_project/Software/Version.interface.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/yaml/xyz/openbmc_project/Software/Version.interface.yaml b/yaml/xyz/openbmc_project/Software/Version.interface.yaml
index ee4d5ac..3826af0 100644
--- a/yaml/xyz/openbmc_project/Software/Version.interface.yaml
+++ b/yaml/xyz/openbmc_project/Software/Version.interface.yaml
@@ -42,3 +42,6 @@ enumerations:
- name: PSU
description: >
The version is a version for a PSU.
+ - name: CPLD
+ description: >
+ The version is a version for a CPLD.
--
2.25.1
@@ -0,0 +1,117 @@
From f3b3366fbbba20f0b713bcc87ef3dfe47d53909f Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Fri, 17 Jan 2025 10:00:40 +0800
Subject: [PATCH] Add rsyslog dbus interface
---
.../Logging/Rsyslog/meson.build | 15 ++++++
gen/xyz/openbmc_project/Logging/meson.build | 15 ++++++
.../Logging/Rsyslog.interface.yaml | 48 +++++++++++++++++++
3 files changed, 78 insertions(+)
create mode 100755 gen/xyz/openbmc_project/Logging/Rsyslog/meson.build
create mode 100755 yaml/xyz/openbmc_project/Logging/Rsyslog.interface.yaml
diff --git a/gen/xyz/openbmc_project/Logging/Rsyslog/meson.build b/gen/xyz/openbmc_project/Logging/Rsyslog/meson.build
new file mode 100755
index 0000000..429f7e2
--- /dev/null
+++ b/gen/xyz/openbmc_project/Logging/Rsyslog/meson.build
@@ -0,0 +1,15 @@
+# Generated file; do not modify.
+generated_sources += custom_target(
+ 'xyz/openbmc_project/Logging/Rsyslog__cpp'.underscorify(),
+ input: [ '../../../../../yaml/xyz/openbmc_project/Logging/Rsyslog.interface.yaml', ],
+ output: [ 'common.hpp', 'server.cpp', 'server.hpp', 'client.hpp', ],
+ depend_files: sdbusplusplus_depfiles,
+ command: [
+ sdbuspp_gen_meson_prog, '--command', 'cpp',
+ '--output', meson.current_build_dir(),
+ '--tool', sdbusplusplus_prog,
+ '--directory', meson.current_source_dir() / '../../../../../yaml',
+ 'xyz/openbmc_project/Logging/Rsyslog',
+ ],
+)
+
diff --git a/gen/xyz/openbmc_project/Logging/meson.build b/gen/xyz/openbmc_project/Logging/meson.build
index 3fbbcbb..197c3ec 100644
--- a/gen/xyz/openbmc_project/Logging/meson.build
+++ b/gen/xyz/openbmc_project/Logging/meson.build
@@ -74,6 +74,21 @@ generated_others += custom_target(
],
)
+subdir('Rsyslog')
+generated_others += custom_target(
+ 'xyz/openbmc_project/Logging/Rsyslog__markdown'.underscorify(),
+ input: [ '../../../../yaml/xyz/openbmc_project/Logging/Rsyslog.interface.yaml', ],
+ output: [ 'Rsyslog.md' ],
+ depend_files: sdbusplusplus_depfiles,
+ command: [
+ sdbuspp_gen_meson_prog, '--command', 'markdown',
+ '--output', meson.current_build_dir(),
+ '--tool', sdbusplusplus_prog,
+ '--directory', meson.current_source_dir() / '../../../../yaml',
+ 'xyz/openbmc_project/Logging/Rsyslog',
+ ],
+)
+
subdir('SEL')
generated_others += custom_target(
'xyz/openbmc_project/Logging/SEL__markdown'.underscorify(),
diff --git a/yaml/xyz/openbmc_project/Logging/Rsyslog.interface.yaml b/yaml/xyz/openbmc_project/Logging/Rsyslog.interface.yaml
new file mode 100755
index 0000000..6696426
--- /dev/null
+++ b/yaml/xyz/openbmc_project/Logging/Rsyslog.interface.yaml
@@ -0,0 +1,48 @@
+description: >
+ This defines the rsyslog server configuration.
+
+properties:
+ - name: Status
+ type: boolean
+ description: >
+ Status of the rsyslog server.
+ - name: AddressType
+ type: enum[self.Type]
+ description: >
+ server adrress type which can be IPv4 or IPv6 etc.
+ errors:
+ - xyz.openbmc_project.Common.Error.NotAllowed
+ - name: Address
+ type: string
+ description: >
+ The value of this property can be IP of the rsyslog.
+ errors:
+ - xyz.openbmc_project.Common.Error.InvalidArgument
+ - xyz.openbmc_project.Common.Error.InternalFailure
+ - name: Port
+ type: uint16
+ description: >
+ The value of this property is the network port number.
+ errors:
+ - xyz.openbmc_project.Common.Error.InternalFailure
+ - name: ProtocolType
+ type: enum[self.Protocol]
+ description: >
+ IP protocol type which can be TCP or UDP etc.
+ errors:
+ - xyz.openbmc_project.Common.Error.NotAllowed
+
+enumerations:
+ - name: Type
+ description: >
+ Possible IP adress types.
+ values:
+ - name: IPv4
+ - name: IPv6
+
+ - name: Protocol
+ description: >
+ Possible IP protocol types..
+ values:
+ - name: UDP
+ - name: TCP
--
2.25.1
@@ -0,0 +1,6 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += " \
file://0001-Add-VersionPurpose-CPLD-To-Support-CPLD-Component.patch \
file://0001-Add-rsyslog-dbus-interface.patch \
"
@@ -0,0 +1,36 @@
From a351cc544f6e949a26b53e294aa2e496622feba6 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Fri, 17 Jan 2025 10:11:24 +0800
Subject: [PATCH] Add persustent log
---
tools/dreport.d/plugins.d/persistent_log | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100755 tools/dreport.d/plugins.d/persistent_log
diff --git a/tools/dreport.d/plugins.d/persistent_log b/tools/dreport.d/plugins.d/persistent_log
new file mode 100755
index 0000000..fc4ef54
--- /dev/null
+++ b/tools/dreport.d/plugins.d/persistent_log
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# config: 24 25
+# @brief: Collect persistent log.
+#
+
+# shellcheck source=/dev/null
+. "$DREPORT_INCLUDE"/functions
+
+desc="persistent log"
+path="/var/persistent/log/"
+files=$(ls $path)
+
+for file_name in $files
+do
+ add_copy_file "$path$file_name" "$desc"
+done
--
2.25.1
@@ -0,0 +1,5 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append = " \
file://0001-Add-persustent-log.patch \
"
@@ -0,0 +1,295 @@
From 21929dbc4fae5aa78be51ee389523f6cdb638759 Mon Sep 17 00:00:00 2001
From: "hliangs90" <hliangs90@gmail.com>
Date: Thu, 15 Aug 2024 13:11:23 +0800
Subject: [PATCH] Add CPLD Update for SoftWare Manager.
Signed-off-by: hliangs90 <hliangs90@gmail.com>
---
activation.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++
activation.hpp | 8 +++++
item_updater.cpp | 37 +++++++++++++++++++
item_updater.hpp | 19 ++++++++++
meson.build | 5 +++
meson_options.txt | 8 +++++
6 files changed, 169 insertions(+)
diff --git a/activation.cpp b/activation.cpp
index d9ee2d0..f866461 100644
--- a/activation.cpp
+++ b/activation.cpp
@@ -143,6 +143,23 @@ auto Activation::activation(Activations value) -> Activations
}
#endif
+#ifdef CPLD_UPGRADE
+ auto purposeTemp = parent.versions.find(versionId)->second->purpose();
+ if (purposeTemp == VersionPurpose::CPLD)
+ {
+ // Enable systemd signals
+ subscribeToSystemdSignals();
+
+ // Set initial progress
+ activationProgress->progress(20);
+
+ // Initiate image writing to flash
+ flashWriteCPLD();
+
+ return softwareServer::Activation::activation(value);
+ }
+#endif
+
activationProgress->progress(10);
parent.freeSpace(*this);
@@ -318,6 +335,15 @@ void Activation::unitStateChange(sdbusplus::message_t& msg)
}
#endif
+#ifdef CPLD_UPGRADE
+ auto purposeTemp = parent.versions.find(versionId)->second->purpose();
+ if (purposeTemp == VersionPurpose::CPLD)
+ {
+ onStateChangesCPLD(msg);
+ return;
+ }
+#endif
+
onStateChanges(msg);
return;
@@ -456,6 +482,72 @@ void Activation::onStateChangesBios(sdbusplus::message_t& msg)
#endif
+#ifdef CPLD_UPGRADE
+void Activation::flashWriteCPLD()
+{
+ auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
+ SYSTEMD_INTERFACE, "StartUnit");
+ auto cpldServiceFile = "obmc-flash-cpld@" + versionId + ".service";
+ method.append(cpldServiceFile, "replace");
+ try
+ {
+ auto reply = bus.call(method);
+ }
+ catch (const sdbusplus::exception_t& e)
+ {
+ error("Error in trying to upgrade CPLD: {ERROR}", "ERROR", e);
+ report<InternalFailure>();
+ }
+}
+
+void Activation::onStateChangesCPLD(sdbusplus::message_t& msg)
+{
+ uint32_t newStateID{};
+ sdbusplus::message::object_path newStateObjPath;
+ std::string newStateUnit{};
+ std::string newStateResult{};
+
+ // Read the msg and populate each variable
+ msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+ auto cpldServiceFile = "obmc-flash-cpld@" + versionId + ".service";
+
+ if (newStateUnit == cpldServiceFile)
+ {
+ // unsubscribe to systemd signals
+ unsubscribeFromSystemdSignals();
+
+ if (newStateResult == "done")
+ {
+ // Set activation progress to 100
+ activationProgress->progress(100);
+
+ // Set Activation value to active
+ activation(softwareServer::Activation::Activations::Active);
+
+ info("CPLD upgrade completed successfully.");
+ parent.cpldVersion->version(
+ parent.versions.find(versionId)->second->version());
+
+ // Delete the uploaded activation
+ boost::asio::post(getIOContext(), [this]() {
+ this->parent.erase(this->versionId);
+ });
+ }
+ else if (newStateResult == "failed")
+ {
+ // Set Activation value to Failed
+ activation(softwareServer::Activation::Activations::Failed);
+
+ error("CPLD upgrade failed.");
+ }
+ }
+
+ return;
+}
+
+#endif
+
void Activation::rebootBmc()
{
auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
diff --git a/activation.hpp b/activation.hpp
index 94cc1bb..7d10472 100644
--- a/activation.hpp
+++ b/activation.hpp
@@ -247,6 +247,14 @@ class Activation : public ActivationInherit, public Flash
void onStateChangesBios(sdbusplus::message_t&);
#endif
+#ifdef CPLD_UPGRADE
+ /* @brief write to CPLD flash function */
+ void flashWriteCPLD();
+
+ /** @brief Function that acts on CPLD upgrade service file state changes */
+ void onStateChangesCPLD(sdbusplus::message_t&);
+#endif
+
/** @brief Overloaded function that acts on service file state changes */
void onStateChanges(sdbusplus::message_t&) override;
diff --git a/item_updater.cpp b/item_updater.cpp
index 5613a49..76f72d4 100644
--- a/item_updater.cpp
+++ b/item_updater.cpp
@@ -71,6 +71,9 @@ void ItemUpdater::createActivation(sdbusplus::message_t& msg)
if (value == VersionPurpose::BMC ||
#ifdef HOST_BIOS_UPGRADE
value == VersionPurpose::Host ||
+#endif
+#ifdef CPLD_UPGRADE
+ value == VersionPurpose::CPLD ||
#endif
value == VersionPurpose::System)
{
@@ -879,6 +882,40 @@ void ItemUpdater::createBIOSObject()
}
#endif
+#ifdef CPLD_UPGRADE
+void ItemUpdater::createCPLDObject()
+{
+ std::string path = CPLD_OBJPATH;
+ // Get version id from last item in the path
+ auto pos = path.rfind("/");
+ if (pos == std::string::npos)
+ {
+ error("No version id found in object path {PATH}", "PATH", path);
+ return;
+ }
+
+ createActiveAssociation(path);
+ createFunctionalAssociation(path);
+
+ auto versionId = path.substr(pos + 1);
+ auto version = "null";
+ AssociationList assocs = {};
+ cpldActivation = std::make_unique<Activation>(
+ bus, path, *this, versionId, server::Activation::Activations::Active,
+ assocs);
+ auto dummyErase = [](std::string /*entryId*/) {
+ // Do nothing;
+ };
+ cpldVersion = std::make_unique<VersionClass>(
+ bus, path, version, VersionPurpose::CPLD, "", "",
+ std::vector<std::string>(),
+ std::bind(dummyErase, std::placeholders::_1), "");
+ cpldVersion->deleteObject =
+ std::make_unique<phosphor::software::manager::Delete>(bus, path,
+ *cpldVersion);
+}
+#endif
+
void ItemUpdater::getRunningSlot()
{
// Check /run/media/slot to get the slot number
diff --git a/item_updater.hpp b/item_updater.hpp
index c50d9de..26b657d 100644
--- a/item_updater.hpp
+++ b/item_updater.hpp
@@ -67,6 +67,9 @@ class ItemUpdater : public ItemUpdaterInherit
restoreFieldModeStatus();
#ifdef HOST_BIOS_UPGRADE
createBIOSObject();
+#endif
+#ifdef CPLD_UPGRADE
+ createCPLDObject();
#endif
emit_object_added();
};
@@ -280,6 +283,22 @@ class ItemUpdater : public ItemUpdaterInherit
std::unique_ptr<VersionClass> biosVersion;
#endif
+#ifdef CPLD_UPGRADE
+ /** @brief Create the CPLD object without knowing the version.
+ *
+ * The object is created only to provide the DBus access so that an
+ * external service could set the correct CPLD version.
+ * On CPLD code update, the version is updated accordingly.
+ */
+ void createCPLDObject();
+
+ /** @brief Persistent Activation D-Bus object for CPLD */
+ std::unique_ptr<Activation> cpldActivation;
+
+ public:
+ /** @brief Persistent Version D-Bus object for CPLD */
+ std::unique_ptr<VersionClass> cpldVersion;
+#endif
/** @brief Get the slot number of running image */
void getRunningSlot();
};
diff --git a/meson.build b/meson.build
index 41adfde..509d9f7 100644
--- a/meson.build
+++ b/meson.build
@@ -67,6 +67,7 @@ conf.set('MMC_LAYOUT', get_option('bmc-layout').contains('mmc'))
# Configurable features
conf.set('HOST_BIOS_UPGRADE', get_option('host-bios-upgrade').enabled())
+conf.set('CPLD_UPGRADE', get_option('cpld-upgrade').enabled())
conf.set('WANT_SIGNATURE_VERIFY', \
get_option('verify-signature').enabled() or \
get_option('verify-full-signature').enabled())
@@ -96,6 +97,10 @@ if get_option('host-bios-upgrade').enabled()
conf.set_quoted('BIOS_OBJPATH', get_option('bios-object-path'))
endif
+if get_option('cpld-upgrade').enabled()
+ conf.set_quoted('CPLD_OBJPATH', get_option('cpld-object-path'))
+endif
+
if get_option('bmc-static-dual-image').enabled()
conf.set('BMC_STATIC_DUAL_IMAGE', get_option('bmc-static-dual-image').enabled())
conf.set_quoted('ALT_ROFS_DIR', get_option('alt-rofs-dir'))
diff --git a/meson_options.txt b/meson_options.txt
index d14ed3b..d638c93 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -11,6 +11,8 @@ option('bmc-layout', type: 'combo',
# Features
option('host-bios-upgrade', type: 'feature', value: 'enabled',
description: 'Enable host bios upgrade support.')
+option('cpld-upgrade', type: 'feature', value: 'enabled',
+ description: 'Enable cpld upgrade support.')
option('sync-bmc-files', type: 'feature', value: 'enabled',
description: 'Enable sync of filesystem files.')
@@ -121,6 +123,12 @@ option(
description: 'The BIOS DBus object path.',
)
+option(
+ 'cpld-object-path', type: 'string',
+ value: '/xyz/openbmc_project/software/cpld_active',
+ description: 'The CPLD DBus object path.',
+)
+
option('bmc-static-dual-image', type: 'feature', value: 'enabled',
description: 'Enable the dual image support for static layout.')
--
2.25.1
@@ -0,0 +1,78 @@
From 88d810c49f7101a8bb46b2a1af17626bd61a5d07 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Wed, 18 Dec 2024 13:55:03 +0800
Subject: [PATCH] Detect boot image source
---
detect-slot-aspeed | 21 +++++++++++++++++----
reset-cs0-aspeed | 12 +++++++++++-
2 files changed, 28 insertions(+), 5 deletions(-)
diff --git a/detect-slot-aspeed b/detect-slot-aspeed
index 231eb33..6631722 100644
--- a/detect-slot-aspeed
+++ b/detect-slot-aspeed
@@ -1,16 +1,29 @@
#!/bin/bash
set -eo pipefail
-# Check the /sys/class/watchdog/watchdog1/access_cs0 and tell if it's running on the primary or the secondary flash.
-
-ACCESS_CS0="/sys/class/watchdog/watchdog1/access_cs0"
SLOT_FILE="/run/media/slot"
+if [ -f ${SLOT_FILE} ]; then
+ # Slot info already detected
+ exit 0
+fi
+
+# Check the sysfs attribute and tell if it's running on the primary or the secondary flash.
+SOC_FAMILY=$(cat /sys/bus/soc/devices/soc0/family)
+if [ "${SOC_FAMILY}" = "AST2500" ]; then
+ ACCESS_PRIMARY="/sys/class/watchdog/watchdog1/access_cs0"
+elif [ "${SOC_FAMILY}" = "AST2600" ]; then
+ ACCESS_PRIMARY="/sys/devices/platform/ahb/1e620000.spi/access_primary"
+else
+ echo "SOC Family is neither AST2500 nor AST2600"
+ exit 1
+fi
+
# Create directory if not exist
mkdir -p "$(dirname "${SLOT_FILE}")"
# Write slot info
-if [ -f ${ACCESS_CS0} ]; then
+if [ -f ${ACCESS_PRIMARY} ]; then
echo "1" > ${SLOT_FILE}
else
echo "0" > ${SLOT_FILE}
diff --git a/reset-cs0-aspeed b/reset-cs0-aspeed
index e2cf1e0..e761e77 100644
--- a/reset-cs0-aspeed
+++ b/reset-cs0-aspeed
@@ -11,11 +11,21 @@ SHUTDOWN_EXTRA_SCRIPT="/run/initramfs/shutdown_task_after_umount"
cat <<'EOF' >"${SHUTDOWN_EXTRA_SCRIPT}"
#!/bin/sh
-ACCESS_CS0="/sys/class/watchdog/watchdog1/access_cs0"
+
+ACCESS_CS0=""
+
+SOC_FAMILY=$(cat /sys/bus/soc/devices/soc0/family)
+if [ "${SOC_FAMILY}" = "AST2500" ]; then
+ ACCESS_CS0="/sys/class/watchdog/watchdog1/access_cs0"
+elif [ "${SOC_FAMILY}" = "AST2600" ]; then
+ ACCESS_CS0="/sys/devices/platform/ahb/1e620000.spi/access_primary"
+fi
+
if [ -f "${ACCESS_CS0}" ]; then
echo "Reset aspeed chip select"
echo 1 > "${ACCESS_CS0}"
fi
+
EOF
chmod +x "${SHUTDOWN_EXTRA_SCRIPT}"
--
2.25.1
@@ -0,0 +1,192 @@
From f96d61f5a96db2deaf34f5ca38b77b3d18704ae6 Mon Sep 17 00:00:00 2001
From: "alex-hl.huang" <alex-hl.huang@luxshare-ict.com>
Date: Thu, 17 Feb 2022 13:52:46 +0800
Subject: [PATCH] add shell script for generate cpld image tar
---
gen-cpld-tar | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 176 insertions(+)
create mode 100755 gen-cpld-tar
diff --git a/gen-cpld-tar b/gen-cpld-tar
new file mode 100755
index 0000000..d0d59c6
--- /dev/null
+++ b/gen-cpld-tar
@@ -0,0 +1,176 @@
+#!/bin/bash
+set -eo pipefail
+
+help=$'Generate Tarball with Cpld image and MANIFEST Script
+
+Generates a Cpld image tarball from given file as input.
+Creates a MANIFEST for image verification and recreation
+Packages the image and MANIFEST together in a tarball
+
+usage: gen-Cpld-tar [OPTION] <Cpld FILE>...
+
+Options:
+-o, --out <file> Specify destination file. Defaults to
+`pwd`/obmc-cpld.tar.gz if unspecified.
+-s, --sign <path> Sign the image. The optional path argument specifies
+the private key file. Defaults to the bash variable
+PRIVATE_KEY_PATH if available, or else uses the
+open-source private key in this script.
+-m, --machine <name> Optionally specify the target machine name of this
+image.
+-v, --version <name> Specify the version of Cpld image file
+-h, --help Display this help text and exit.
+'
+
+#################################################################
+# It's the OpenBMC "public" private key (currently under
+# meta-phosphor/recipes-phosphor/flash/files/OpenBMC.priv):
+# https://gerrit.openbmc-project.xyz/c/openbmc/openbmc/+/8949/15/
+# meta-phosphor/common/recipes-phosphor/flash/files/OpenBMC.priv
+#
+#################################################################
+private_key=$'-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAPvSDLu6slkP1gri
+PaeQXL9ysD69J/HjbBCIQ0RPfeWBb75US1tRTjPP0Ub8CtH8ExVf8iF1ulsZA78B
+zIjBYZVp9pyD6LbpZ/hjV7rIH6dTNhoVpdA+F8LzmQ7cyhHG8l2JMvdunwF2uX5k
+D4WDcZt/ITKZNQNavPtmIyD5HprdAgMBAAECgYEAuQkTSi5ZNpAoWz76xtGRFSwU
+zUT4wQi3Mz6tDtjKTYXasiQGa0dHC1M9F8fDu6BZ9W7W4Dc9hArRcdzEighuxoI/
+nZI/0uL89iUEywnDEIHuS6D5JlZaj86/nx9YvQnO8F/seM+MX0EAWVrd5wC7aAF1
+h6Fu7ykZB4ggUjQAWwECQQD+AUiDOEO+8btLJ135dQfSGc5VFcZiequnKWVm6uXt
+rX771hEYjYMjLqWGFg9G4gE3GuABM5chMINuQQUivy8tAkEA/cxfy19XkjtqcMgE
+x/UDt6Nr+Ky/tk+4Y65WxPRDas0uxFOPk/vEjgVmz1k/TAy9G4giisluTvtmltr5
+DCLocQJBAJnRHx9PiD7uVhRJz6/L/iNuOzPtTsi+Loq5F83+O6T15qsM1CeBMsOw
+cM5FN5UeMcwz+yjfHAsePMkcmMaU7jUCQHlg9+N8upXuIo7Dqj2zOU7nMmkgvSNE
+5yuNImRZabC3ZolwaTdd7nf5r1y1Eyec5Ag5yENV6JKPe1Xkbb1XKJECQDngA0h4
+6ATvfP1Vrx4CbP11eKXbCsZ9OGPHSgyvVjn68oY5ZP3uPsIattoN7dE2BRfuJm7m
+F0nIdUAhR0yTfKM=
+-----END PRIVATE KEY-----
+'
+
+do_sign=false
+PRIVATE_KEY_PATH=${PRIVATE_KEY_PATH:-}
+private_key_path="${PRIVATE_KEY_PATH}"
+outfile=""
+machine=""
+version=""
+default_cpld_name="cpld.svf"
+while [[ $# -gt 0 ]]; do
+ key="$1"
+ case $key in
+ -o|--out)
+ outfile="$2"
+ shift 2
+ ;;
+ -s|--sign)
+ do_sign=true
+ if [[ -n "${2}" && "${2}" != -* ]]; then
+ private_key_path="$2"
+ shift 2
+ else
+ shift 1
+ fi
+ ;;
+ -m|--machine)
+ machine="$2"
+ shift 2
+ ;;
+ -v|--version)
+ version="$2"
+ shift 2
+ ;;
+ -h|--help)
+ echo "$help"
+ exit
+ ;;
+ -*)
+ echo "Unrecognised option $1"
+ echo "$help"
+ exit
+ ;;
+ *)
+ file="$1"
+ shift 1
+ ;;
+ esac
+done
+
+if [ ! -f "${file}" ]; then
+ echo "${file} not found, Please enter a valid Cpld image file"
+ echo "$help"
+ exit 1
+else
+ cp "$file" $default_cpld_name
+ echo "$file"
+fi
+
+if [[ -z $version ]]; then
+ echo "Please provide version of image with -v option"
+ exit 1
+fi
+
+if [[ -z $outfile ]]; then
+ outfile=$(pwd)/obmc-cpld.tar.gz
+else
+ if [[ $outfile != /* ]]; then
+ outfile=$(pwd)/$outfile
+ fi
+fi
+
+scratch_dir=$(mktemp -d)
+# Remove the temp directory on exit.
+# The files in the temp directory may contain read-only files, so add
+# --interactive=never to skip the prompt.
+trap '{ rm -r --interactive=never ${scratch_dir}; }' EXIT
+
+if [[ "${do_sign}" == true ]]; then
+ if [[ -z "${private_key_path}" ]]; then
+ private_key_path=${scratch_dir}/OpenBMC.priv
+ echo "${private_key}" > "${private_key_path}"
+ echo "Image is NOT secure!! Signing with the open private key!"
+ else
+ if [[ ! -f "${private_key_path}" ]]; then
+ echo "Couldn't find private key ${private_key_path}."
+ exit 1
+ fi
+
+ echo "Signing with ${private_key_path}."
+ fi
+
+ public_key_file=publickey
+ public_key_path=${scratch_dir}/$public_key_file
+ openssl pkey -in "${private_key_path}" -pubout -out "${public_key_path}"
+fi
+
+manifest_location="MANIFEST"
+files_to_sign="$manifest_location $public_key_file"
+
+# Go to scratch_dir
+cp "${file}" "${scratch_dir}"
+cd "${scratch_dir}"
+mv "${file}" ${default_cpld_name}
+file=${default_cpld_name}
+files_to_sign+=" $(basename ${file})"
+
+echo "Creating MANIFEST for the image"
+echo -e "purpose=xyz.openbmc_project.Software.Version.VersionPurpose.CPLD\n\
+version=$version" > $manifest_location
+
+if [[ -n "${machine}" ]]; then
+ echo -e "MachineName=${machine}" >> $manifest_location
+fi
+
+if [[ "${do_sign}" == true ]]; then
+ private_key_name=$(basename "${private_key_path}")
+ key_type="${private_key_name%.*}"
+ echo KeyType="${key_type}" >> $manifest_location
+ echo HashType="RSA-SHA256" >> $manifest_location
+
+ for file in $files_to_sign; do
+ openssl dgst -sha256 -sign "${private_key_path}" -out "${file}.sig" "$file"
+ done
+
+ additional_files="*.sig"
+fi
+# shellcheck disable=SC2086
+tar -czvf $outfile $files_to_sign $additional_files
+echo "Cpld image tarball is at $outfile"
@@ -0,0 +1,128 @@
#!/bin/bash
bios_image=$(ls $1/*.bin)
bios_mtd="/dev/mtd/bios"
bios_id=$(basename "$1")
bios_slot=""
power_obj="xyz.openbmc_project.State.Chassis"
power_path="/xyz/openbmc_project/state/chassis0"
power_intf="xyz.openbmc_project.State.Chassis"
power_prop="CurrentPowerState"
update_obj="xyz.openbmc_project.Software.BMC.Updater"
update_path="/xyz/openbmc_project/software/"
target_intf="xyz.openbmc_project.Software.UpdateTarget"
target_prop="UpdateTargetSlot"
check_env() {
echo "[Info]: Check Environment."
#check power status. if On, set to Off.
#power_status=$(busctl get-property $power_obj $power_path $power_intf $power_prop)
#if [[ $power_status == *On* ]]; then
# busctl set-property $power_obj $power_path $power_intf RequestedPowerTransition s xyz.openbmc_project.State.Chassis.Transition.Off
#fi
sleep 10
#add other action to prepare flash bios.
bios_slot=$(busctl get-property $update_obj $update_path$bios_id $target_intf $target_prop)
bios_slot=$(echo "$bios_slot" |cut -d "\"" -f2)
if [ "$bios_slot" = "xyz.openbmc_project.Software.UpdateTarget.TargetSlot.Primary" ]; then
bios_slot="Primary"
elif [ "$bios_slot" = "xyz.openbmc_project.Software.UpdateTarget.TargetSlot.Secondary" ]; then
bios_slot="Backup"
elif [ "$bios_slot" = "xyz.openbmc_project.Software.UpdateTarget.TargetSlot.Both" ]; then
bios_slot="Both"
fi
}
switch_primary_flash_to_bmc() {
echo "[Info]: Switch Main BIOS Flash To BMC."
if [ -d /sys/bus/platform/drivers/spi-aspeed-smc/1e630000.spi ]; then
echo -n "1e630000.spi" > /sys/bus/platform/drivers/spi-aspeed-smc/unbind
fi
#Set Mux to bmc.
i2ctransfer -y -a 0 w3@0x0d 0xa0 0x03 0x80
#Switch to primary BIOS flash
i2ctransfer -y -a 0 w3@0x0d 0xa1 0x03 0x80
#mount bios flash to BMC
echo -n "1e630000.spi" > /sys/bus/platform/drivers/spi-aspeed-smc/bind
sleep 5
cat /proc/mtd
}
switch_secondary_flash_to_bmc() {
echo "[Info]: Switch Backup BIOS Flash To BMC."
if [ -d /sys/bus/platform/drivers/spi-aspeed-smc/1e630000.spi ]; then
echo -n "1e630000.spi" > /sys/bus/platform/drivers/spi-aspeed-smc/unbind
fi
#Set Mux to bmc.
i2ctransfer -y -a 0 w3@0x0d 0xa0 0x03 0x80
#Switch to backup BIOS flash
i2ctransfer -y -a 0 w3@0x0d 0xa1 0x03 0x40
#mount bios flash to BMC
echo -n "1e630000.spi" > /sys/bus/platform/drivers/spi-aspeed-smc/bind
sleep 5
cat /proc/mtd
}
flash_bios() {
echo "[Info]: Flash BIOS."
#Which flash need to be update, e.g. get for Manifest or Settings.
# bios_update_select=
#Check MTD Exist
if [[ ! -e $bios_mtd ]]; then
echo "[Error]: bios flash not found in $bios_mtd"
exit 3
fi
echo "[Info]: bios_image=$bios_image"
echo "[Info]: bios_mtd=$bios_mtd"
echo "/usr/sbin/flashcp $bios_image $bios_mtd"
/usr/sbin/flashcp $bios_image $bios_mtd
}
switch_flash_to_cpu() {
echo "[Info]: Switch Main BIOS Flash To CPU."
echo -n "1e630000.spi" > /sys/bus/platform/drivers/spi-aspeed-smc/unbind
sleep 5
#Set Mux to CPU.
i2ctransfer -y -a 0 w3@0x0d 0xa0 0x03 0x00
}
power_on_system() {
echo "[Info]: Power On System After Update BIOS."
#check power status. if Off, set to On.
power_status=$(busctl get-property $power_obj $power_path $power_intf $power_prop)
if [[ $power_status == *Off* ]]; then
sleep 5
busctl set-property $power_obj $power_path $power_intf RequestedPowerTransition s xyz.openbmc_project.State.Chassis.Transition.On
fi
}
check_env
if [ "$bios_slot" = "Primary" ]; then
switch_primary_flash_to_bmc
flash_bios
elif [ "$bios_slot" = "Backup" ]; then
switch_secondary_flash_to_bmc
flash_bios
elif [ "$bios_slot" = "Both" ]; then
switch_primary_flash_to_bmc
flash_bios
sleep 5
switch_secondary_flash_to_bmc
flash_bios
fi
switch_flash_to_cpu
#power_on_system
sleep 5
@@ -0,0 +1,29 @@
#!/bin/bash
cpld_image=$(ls $1/*.svf)
jtag_node="/dev/jtag1"
check_env() {
echo "[Info]: Check Environment."
#add action to prepare flash cpld.
#check cpld exist ?
}
flash_cpld() {
echo "[Info]: Flash CPLD."
echo "[Info]: Switch CPLD JTAG mux to BMC."
gpioset 0 124=1
gpioset 0 122=0
echo "[Info]: CPLD Image:$cpld_image"
/usr/bin/svf -n $jtag_node -s -p $cpld_image
}
enable_new_fw() {
echo "[Info]: Enable New Firmware."
}
check_env
flash_cpld
enable_new_fw
@@ -0,0 +1,9 @@
[Unit]
Description=Flash image %I to CPLD
[Service]
Type=oneshot
RemainAfterExit=no
ExecStartPre=/bin/sh -c 'touch /tmp/mbcpld_update_status'
ExecStart=/usr/bin/flashcpld /tmp/images/%i
ExecStopPost=/bin/sh -c 'echo $EXIT_STATUS > /tmp/mbcpld_update_status'
@@ -0,0 +1,9 @@
[Unit]
Description=Flash Host Bios image %I to Host
[Service]
Type=oneshot
RemainAfterExit=no
ExecStartPre=/bin/sh -c 'touch /tmp/bios_update_status'
ExecStart=/usr/bin/flashbios /tmp/images/%i
ExecStopPost=/bin/sh -c 'echo $EXIT_STATUS > /tmp/bios_update_status'
@@ -0,0 +1,32 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += " \
file://obmc-flash-cpld@.service \
file://obmc-flash-host-bios@.service \
file://flashbios \
file://flashcpld "
SRC_URI += " \
file://0001-Add-CPLD-Update-for-SoftWare-Manager.patch \
file://0003-add-shell-script-for-generate-cpld-image-tar.patch \
file://0001-Detect-boot-image-source.patch \
"
PACKAGECONFIG[cpld_update] = "-Dcpld-upgrade=enabled, -Dcpld-upgrade=disabled"
PACKAGECONFIG += " cpld_update flash_bios static-dual-image"
DEPENDS += "${@bb.utils.contains('PACKAGECONFIG', 'cpld_update', 'svf', '', d)}"
do_install:append() {
install -d ${D}${bindir}
install -d ${D}${systemd_system_unitdir}
install -m 0755 ${WORKDIR}/flashbios ${D}${bindir}
install -m 0755 ${WORKDIR}/flashcpld ${D}${bindir}
install -m 0644 ${WORKDIR}/obmc-flash-cpld@.service ${D}${systemd_system_unitdir}
install -m 0644 ${WORKDIR}/obmc-flash-host-bios@.service ${D}${systemd_system_unitdir}
}
FILES:${PN}-updater += "\
${systemd_system_unitdir}/obmc-flash-cpld@.service \
${systemd_system_unitdir}/obmc-flash-host-bios@.service \
${bindir}/flashbios \
${bindir}/flashcpld "
+19
View File
@@ -0,0 +1,19 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
LICENSE = "CLOSED"
SRC_URI += " \
file://ast-jtag.c \
file://ast-jtag.h \
file://jtag.h \
file://main.c \
file://Makefile \
file://svf.c \
file://svf.h"
TARGET_CC_ARCH += "${LDFLAGS}"
inherit pkgconfig
S = "${WORKDIR}"
EXTRA_OEMAKE += "INSTALL_DIR=${D}${bindir}"
do_install(){
install -d ${D}${bindir}
install -m 0755 ${S}/svf ${D}${bindir}
}
@@ -0,0 +1,55 @@
STATE RESET;
HDR 0;
HIR 0;
TDR 0;
TIR 0;
ENDDR DRPAUSE;
ENDIR IRPAUSE;
! FREQUENCY 1.00e+006 HZ;
STATE IDLE;
SIR 8 TDI (E0);
SDR 32 TDI (00000000)
TDO (012B5043)
MASK (FFFFFFFF);
SIR 8 TDI (1C);
SDR 664 TDI (FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
FFFFFF);
SIR 8 TDI (3C);
RUNTEST IDLE 2 TCK 1.00E-003 SEC;
SDR 32 TDI (00000000)
TDO (00000000)
MASK (00000020);
SIR 8 TDI (C6);
SDR 8 TDI (00);
RUNTEST IDLE 2 TCK 1.00E-003 SEC;
SIR 8 TDI (0E);
SDR 8 TDI (01);
RUNTEST IDLE 2 TCK 1.00E+000 SEC;
SIR 8 TDI (FF)
TDO (00)
MASK (C0);
SIR 8 TDI (C6);
SDR 8 TDI (08);
RUNTEST IDLE 2 TCK 1.00E-003 SEC;
SIR 8 TDI (3C);
RUNTEST IDLE 2 TCK 1.00E-003 SEC;
SDR 32 TDI (00000000)
TDO (00000000)
MASK (00024040);
SIR 8 TDI (0E);
SDR 8 TDI (0E);
RUNTEST IDLE 2 TCK 3.00E+001 SEC;
SIR 8 TDI (F0);
SDR 1 TDI (0)
TDO (0);
SIR 8 TDI (3C);
RUNTEST IDLE 2 TCK 1.00E-003 SEC;
SDR 32 TDI (00000000)
TDO (00000000)
MASK (00003000);
SIR 8 TDI (26);
RUNTEST IDLE 2 TCK 1.00E+000 SEC;
SIR 8 TDI (FF);
RUNTEST IDLE 100 TCK 1.00E-001 SEC;
STATE RESET;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+13
View File
@@ -0,0 +1,13 @@
CFLAGS += -Wall
OBJS = main.o ast-jtag.o svf.o
EXE = svf
.c.o:
$(CC) -c $<
$(EXE): $(OBJS)
$(CC) $(OBJS) -o $@
all:$(EXE)
clean:
rm -f $(EXE) $(OBJS)
install:
cp $(EXE) $(INSTALL_DIR)
+159
View File
@@ -0,0 +1,159 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2020 Aspeed Technology Inc.
*/
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <termios.h>
#include <sys/mman.h>
#include "ast-jtag.h"
int jtag_fd;
#define DEBUG 0
#if DEBUG
#define ast_jtag_printf(...) printf(__VA_ARGS__)
#else
#define ast_jtag_printf(...)
#endif
/*************************************************************************************/
/* AST JTAG LIB */
int ast_jtag_open(char *dev)
{
jtag_fd = open(dev, O_RDWR);
if (jtag_fd == -1) {
printf("Can't open %s, please install driver!! \n", dev);
return -1;
}
return 0;
}
void ast_jtag_close(void)
{
close(jtag_fd);
}
unsigned int ast_get_jtag_freq(void)
{
int retval;
unsigned int freq = 0;
retval = ioctl(jtag_fd, JTAG_GIOCFREQ, &freq);
if (retval == -1) {
perror("ioctl JTAG get freq fail!\n");
return 0;
}
return freq;
}
int ast_set_jtag_mode(uint8_t sw_mode)
{
struct jtag_mode jtag_mode;
int retval;
jtag_mode.feature = JTAG_XFER_MODE;
jtag_mode.mode = sw_mode ? JTAG_XFER_SW_MODE : JTAG_XFER_HW_MODE;
retval = ioctl(jtag_fd, JTAG_SIOCMODE, &jtag_mode);
if (retval == -1) {
perror("ioctl JTAG set mode fail!\n");
return -1;
}
return 0;
}
int ast_set_jtag_freq(unsigned int freq)
{
int retval;
unsigned int jtag_freq = freq;
retval = ioctl(jtag_fd, JTAG_SIOCFREQ, &jtag_freq);
if (retval == -1) {
perror("ioctl JTAG set freq fail!\n");
return -1;
}
return 0;
}
int ast_get_tap_state(enum jtag_tapstate* tap_state)
{
int retval;
if (tap_state == NULL)
return -1;
retval = ioctl(jtag_fd, JTAG_GIOCSTATUS, tap_state);
if (retval == -1) {
perror("ioctl JTAG get tap state fail!\n");
return -1;
}
return 0;
}
int ast_jtag_run_test_idle(unsigned char end, unsigned int tck)
{
int retval;
struct jtag_tap_state run_idle;
run_idle.from = JTAG_STATE_CURRENT;
run_idle.reset = JTAG_NO_RESET;
run_idle.endstate = end;
run_idle.tck = tck;
ast_jtag_printf("from:%d, reset:%d, endstate:%d, tck:%d\n", run_idle.from, run_idle.reset, run_idle.endstate, run_idle.tck);
retval = ioctl(jtag_fd, JTAG_SIOCSTATE, &run_idle);
if (retval == -1) {
printf("ioctl JTAG run reset fail! error:%s\n",strerror(errno));
return -1;
}
if(end)
usleep(tck*2);
return 0;
}
extern int svf_line_number;
int ast_jtag_xfer(unsigned char endsts, unsigned int len, unsigned int *out, unsigned int *in, enum jtag_xfer_type type)
{
int retval;
enum jtag_tapstate current_state;
struct jtag_xfer xfer;
unsigned int send_len_byte;
ast_get_tap_state(&current_state);
xfer.type = type;
xfer.direction = JTAG_READ_WRITE_XFER;
xfer.from = current_state;
xfer.endstate = endsts;
xfer.padding = 0;
xfer.length = len;
xfer.tdio = (unsigned int)out;
send_len_byte = DIV_ROUND_UP(xfer.length, BITS_PER_BYTE);
#if DEBUG
int i;
for (i = 0; i < DIV_ROUND_UP(send_len_byte, 4); i++)
printf("tdo:%08x\n", out[i]);
#endif
retval = ioctl(jtag_fd, JTAG_IOCXFER, &xfer);
if (retval == -1) {
perror("ioctl JTAG sir fail!\n");
return -1;
}
memcpy(in, out, send_len_byte);
#if DEBUG
for (i = 0; i < DIV_ROUND_UP(send_len_byte, 4); i++)
printf("tdi:%08x\n",out[i]);
#endif
return 0;
}
+21
View File
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright 2020 Aspeed Technology Inc.
*/
#include "stdint.h"
typedef uint8_t __u8;
typedef uint32_t __u32;
typedef unsigned long long __u64;
#include "jtag.h"
#define DIV_ROUND_UP(n, d) (((n) + (d)-1) / (d))
#define BITS_PER_BYTE 8
/******************************************************************************************************************/
int ast_jtag_open(char *dev);
void ast_jtag_close(void);
int ast_set_jtag_mode(uint8_t sw_mode);
unsigned int ast_get_jtag_freq(void);
int ast_set_jtag_freq(unsigned int freq);
int ast_jtag_run_test_idle(unsigned char end, unsigned int tck);
int ast_jtag_xfer(unsigned char endsts, unsigned int len, unsigned int *out, unsigned int *in, enum jtag_xfer_type type);
+246
View File
@@ -0,0 +1,246 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2018 Mellanox Technologies. All rights reserved. */
/* Copyright (c) 2018 Oleksandr Shamray <oleksandrs@mellanox.com> */
/* Copyright (c) 2019 Intel Corporation */
#ifndef __UAPI_LINUX_JTAG_H
#define __UAPI_LINUX_JTAG_H
/*
* JTAG_XFER_MODE: JTAG transfer mode. Used to set JTAG controller transfer mode
* This is bitmask for feature param in jtag_mode for ioctl JTAG_SIOCMODE
*/
#define JTAG_XFER_MODE 0
/*
* JTAG_CONTROL_MODE: JTAG controller mode. Used to set JTAG controller mode
* This is bitmask for feature param in jtag_mode for ioctl JTAG_SIOCMODE
*/
#define JTAG_CONTROL_MODE 1
/*
* JTAG_MASTER_OUTPUT_DISABLE: JTAG master mode output disable, it is used to
* enable other devices to own the JTAG bus.
* This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE
*/
#define JTAG_MASTER_OUTPUT_DISABLE 0
/*
* JTAG_MASTER_MODE: JTAG master mode. Used to set JTAG controller master mode
* This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE
*/
#define JTAG_MASTER_MODE 1
/*
* JTAG_XFER_HW_MODE: JTAG hardware mode. Used to set HW drived or bitbang
* mode. This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE
*/
#define JTAG_XFER_HW_MODE 1
/*
* JTAG_XFER_SW_MODE: JTAG software mode. Used to set SW drived or bitbang
* mode. This is bitmask for mode param in jtag_mode for ioctl JTAG_SIOCMODE
*/
#define JTAG_XFER_SW_MODE 0
/**
* enum jtag_tapstate:
*
* @JTAG_STATE_TLRESET: JTAG state machine Test Logic Reset state
* @JTAG_STATE_IDLE: JTAG state machine IDLE state
* @JTAG_STATE_SELECTDR: JTAG state machine SELECT_DR state
* @JTAG_STATE_CAPTUREDR: JTAG state machine CAPTURE_DR state
* @JTAG_STATE_SHIFTDR: JTAG state machine SHIFT_DR state
* @JTAG_STATE_EXIT1DR: JTAG state machine EXIT-1 DR state
* @JTAG_STATE_PAUSEDR: JTAG state machine PAUSE_DR state
* @JTAG_STATE_EXIT2DR: JTAG state machine EXIT-2 DR state
* @JTAG_STATE_UPDATEDR: JTAG state machine UPDATE DR state
* @JTAG_STATE_SELECTIR: JTAG state machine SELECT_IR state
* @JTAG_STATE_CAPTUREIR: JTAG state machine CAPTURE_IR state
* @JTAG_STATE_SHIFTIR: JTAG state machine SHIFT_IR state
* @JTAG_STATE_EXIT1IR: JTAG state machine EXIT-1 IR state
* @JTAG_STATE_PAUSEIR: JTAG state machine PAUSE_IR state
* @JTAG_STATE_EXIT2IR: JTAG state machine EXIT-2 IR state
* @JTAG_STATE_UPDATEIR: JTAG state machine UPDATE IR state
* @JTAG_STATE_CURRENT: JTAG current state, saved by driver
*/
enum jtag_tapstate {
JTAG_STATE_TLRESET,
JTAG_STATE_IDLE,
JTAG_STATE_SELECTDR,
JTAG_STATE_CAPTUREDR,
JTAG_STATE_SHIFTDR,
JTAG_STATE_EXIT1DR,
JTAG_STATE_PAUSEDR,
JTAG_STATE_EXIT2DR,
JTAG_STATE_UPDATEDR,
JTAG_STATE_SELECTIR,
JTAG_STATE_CAPTUREIR,
JTAG_STATE_SHIFTIR,
JTAG_STATE_EXIT1IR,
JTAG_STATE_PAUSEIR,
JTAG_STATE_EXIT2IR,
JTAG_STATE_UPDATEIR,
JTAG_STATE_CURRENT
};
/**
* enum jtag_reset:
*
* @JTAG_NO_RESET: JTAG run TAP from current state
* @JTAG_FORCE_RESET: JTAG force TAP to reset state
*/
enum jtag_reset {
JTAG_NO_RESET = 0,
JTAG_FORCE_RESET = 1,
};
/**
* enum jtag_xfer_type:
*
* @JTAG_SIR_XFER: SIR transfer
* @JTAG_SDR_XFER: SDR transfer
*/
enum jtag_xfer_type {
JTAG_SIR_XFER = 0,
JTAG_SDR_XFER = 1,
};
/**
* enum jtag_xfer_direction:
*
* @JTAG_READ_XFER: read transfer
* @JTAG_WRITE_XFER: write transfer
* @JTAG_READ_WRITE_XFER: read & write transfer
*/
enum jtag_xfer_direction {
JTAG_READ_XFER = 1,
JTAG_WRITE_XFER = 2,
JTAG_READ_WRITE_XFER = 3,
};
/**
* struct jtag_tap_state - forces JTAG state machine to go into a TAPC
* state
*
* @reset: 0 - run IDLE/PAUSE from current state
* 1 - go through TEST_LOGIC/RESET state before IDLE/PAUSE
* @end: completion flag
* @tck: clock counter
*
* Structure provide interface to JTAG device for JTAG set state execution.
*/
struct jtag_tap_state {
__u8 reset;
__u8 from;
__u8 endstate;
__u32 tck;
};
/**
* union pad_config - Padding Configuration:
*
* @type: transfer type
* @pre_pad_number: Number of prepadding bits bit[11:0]
* @post_pad_number: Number of prepadding bits bit[23:12]
* @pad_data : Bit value to be used by pre and post padding bit[24]
* @int_value: unsigned int packed padding configuration value bit[32:0]
*
* Structure provide pre and post padding configuration in a single __u32
*/
union pad_config {
struct {
__u32 pre_pad_number : 12;
__u32 post_pad_number : 12;
__u32 pad_data : 1;
__u32 rsvd : 7;
};
__u32 int_value;
};
/**
* struct jtag_xfer - jtag xfer:
*
* @type: transfer type
* @direction: xfer direction
* @from: xfer current state
* @endstate: xfer end state
* @padding: xfer padding
* @length: xfer bits length
* @tdio : xfer data array
*
* Structure provide interface to JTAG device for JTAG SDR/SIR xfer execution.
*/
struct jtag_xfer {
__u8 type;
__u8 direction;
__u8 from;
__u8 endstate;
__u32 padding;
__u32 length;
__u64 tdio;
};
/**
* struct bitbang_packet - jtag bitbang array packet:
*
* @data: JTAG Bitbang struct array pointer(input/output)
* @length: array size (input)
*
* Structure provide interface to JTAG device for JTAG bitbang bundle execution
*/
struct bitbang_packet {
struct tck_bitbang *data;
__u32 length;
} __attribute__((__packed__));
/**
* struct jtag_bitbang - jtag bitbang:
*
* @tms: JTAG TMS
* @tdi: JTAG TDI (input)
* @tdo: JTAG TDO (output)
*
* Structure provide interface to JTAG device for JTAG bitbang execution.
*/
struct tck_bitbang {
__u8 tms;
__u8 tdi;
__u8 tdo;
} __attribute__((__packed__));
/**
* struct jtag_mode - jtag mode:
*
* @feature: 0 - JTAG feature setting selector for JTAG controller HW/SW
* 1 - JTAG feature setting selector for controller bus master
* mode output (enable / disable).
* @mode: (0 - SW / 1 - HW) for JTAG_XFER_MODE feature(0)
* (0 - output disable / 1 - output enable) for JTAG_CONTROL_MODE
* feature(1)
*
* Structure provide configuration modes to JTAG device.
*/
struct jtag_mode {
__u32 feature;
__u32 mode;
};
/* ioctl interface */
#define __JTAG_IOCTL_MAGIC 0xb2
#define JTAG_SIOCSTATE _IOW(__JTAG_IOCTL_MAGIC, 0, struct jtag_tap_state)
#define JTAG_SIOCFREQ _IOW(__JTAG_IOCTL_MAGIC, 1, unsigned int)
#define JTAG_GIOCFREQ _IOR(__JTAG_IOCTL_MAGIC, 2, unsigned int)
#define JTAG_IOCXFER _IOWR(__JTAG_IOCTL_MAGIC, 3, struct jtag_xfer)
#define JTAG_GIOCSTATUS _IOWR(__JTAG_IOCTL_MAGIC, 4, enum jtag_tapstate)
#define JTAG_SIOCMODE _IOW(__JTAG_IOCTL_MAGIC, 5, unsigned int)
#define JTAG_IOCBITBANG _IOW(__JTAG_IOCTL_MAGIC, 6, unsigned int)
/******************************************************************************************************************/
int ast_jtag_open(char *dev);
void ast_jtag_close(void);
unsigned int ast_get_jtag_freq(void);
int ast_set_jtag_freq(unsigned int freq);
int ast_jtag_run_test_idle(unsigned char end, unsigned int tck);
int ast_jtag_xfer(unsigned char endsts, unsigned int len, unsigned int *out, unsigned int *in, enum jtag_xfer_type type);
int ast_jtag_state_reset_force(unsigned char end, unsigned int tck);
#endif /* __UAPI_LINUX_JTAG_H */
+159
View File
@@ -0,0 +1,159 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2020 Aspeed Technology Inc.
*/
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <getopt.h>
#include <string.h>
#include <termios.h>
#include <sys/mman.h>
#include "ast-jtag.h"
#include "svf.h"
#define ERROR_OK (0)
#define ERROR_NO_CONFIG_FILE (-2)
#define ERROR_BUF_TOO_SMALL (-3)
#define ERROR_FAIL (-4)
#define ERROR_WAIT (-5)
#define ERROR_TIMEOUT_REACHED (-6)
enum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };
int loglevel = LOG_WARN;
static void
usage(FILE *fp, int argc, char **argv)
{
if(0)
{
argc = argc;
}
fprintf(fp,
"Usage: %s [options]\n\n"
"Options:\n"
" -h | --help Print this message\n"
" -d | --debug Set log level, default = 3\n"
" -n | --node jtag device node\n"
" -f | --frequency frequency\n"
" -p | --play play SVF file\n"
" -s | --software software mode\n"
"",
argv[0]);
}
static const char short_options [] = "hsd:n:f:p:";
static const struct option
long_options [] = {
{ "help", no_argument, NULL, 'h' },
{ "debug", required_argument, NULL, 'd' },
{ "node", required_argument, NULL, 'n' },
{ "fequency", required_argument, NULL, 'f' },
{ "play", required_argument, NULL, 'p' },
{ "software", no_argument, NULL, 's' },
{ 0, 0, 0, 0 }
};
/*********************************************************************************/
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/*************************************************************************************/
int main(int argc, char *argv[])
{
int ret;
char option;
char svf_name[100] = "";
char dev_name[100] = "";
int svf = 0;
unsigned int freq = 0;
unsigned int jtag_freq = 0;
uint8_t sw_mode = 0;
while ((option = getopt_long(argc, argv, short_options, long_options, NULL)) != (char) -1) {
switch (option) {
case 'h':
usage(stdout, argc, argv);
exit(EXIT_SUCCESS);
break;
case 'd':
loglevel = atol(optarg);
printf("loglevel %d\n", loglevel);
break;
case 'n':
strcpy(dev_name, optarg);
if (!strcmp(dev_name, "")) {
printf("No dev file name!\n");
usage(stdout, argc, argv);
exit(EXIT_FAILURE);
}
break;
case 'f':
freq = atol(optarg);
printf("frequency %d\n", freq);
break;
case 'p':
svf = 1;
strcpy(svf_name, optarg);
if (!strcmp(svf_name, "")) {
printf("No out file name!\n");
usage(stdout, argc, argv);
exit(EXIT_FAILURE);
}
break;
case 's':
sw_mode = 1;
break;
default:
usage(stdout, argc, argv);
exit(EXIT_FAILURE);
}
}
if (!svf){
usage(stdout, argc, argv);
exit(EXIT_FAILURE);
}
#if 1
if (ast_jtag_open(dev_name))
exit(1);
ast_set_jtag_mode(sw_mode);
//show current ast jtag configuration
jtag_freq = ast_get_jtag_freq();
if (jtag_freq == 0) {
perror("Jtag freq error !! \n");
goto out;
}
if (freq) {
ast_set_jtag_freq(freq);
printf("JTAG Set Freq %d\n", freq);
} else {
printf("JTAG Freq %d\n", jtag_freq);
}
#endif
if (svf) {
printf("Playing %s \n", svf_name);
ret = handle_svf_command(svf_name);
if (ret == ERROR_OK) {
printf("Success!\n");
} else {
printf("Error: %d\n", ret);
}
}
out:
ast_jtag_close();
return 0;
}
File diff suppressed because it is too large Load Diff
+93
View File
@@ -0,0 +1,93 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2005 by Dominic Rath
* Dominic.Rath@gmx.de
*
* Copyright (C) 2007-2010 Øyvind Harboe
* oyvind.harboe@zylin.com
*/
#ifndef SVF_H
#define SVF_H
#include <stdint.h>
/*-----</Macros>-------------------------------------------------*/
/**
* Defines JTAG Test Access Port states.
*
* These definitions were gleaned from the ARM7TDMI-S Technical
* Reference Manual and validated against several other ARM core
* technical manuals.
*
* FIXME some interfaces require specific numbers be used, as they
* are handed-off directly to their hardware implementations.
* Fix those drivers to map as appropriate ... then pick some
* sane set of numbers here (where 0/uninitialized == INVALID).
*/
typedef enum tap_state {
TAP_INVALID = -1,
/* Proper ARM recommended numbers */
TAP_DREXIT2 = 0x0,
TAP_DREXIT1 = 0x1,
TAP_DRSHIFT = 0x2,
TAP_DRPAUSE = 0x3,
TAP_IRSELECT = 0x4,
TAP_DRUPDATE = 0x5,
TAP_DRCAPTURE = 0x6,
TAP_DRSELECT = 0x7,
TAP_IREXIT2 = 0x8,
TAP_IREXIT1 = 0x9,
TAP_IRSHIFT = 0xa,
TAP_IRPAUSE = 0xb,
TAP_IDLE = 0xc,
TAP_IRUPDATE = 0xd,
TAP_IRCAPTURE = 0xe,
TAP_RESET = 0x0f,
} tap_state_t;
/**
* Defines arguments for reset functions
*/
#define SRST_DEASSERT 0
#define SRST_ASSERT 1
#define TRST_DEASSERT 0
#define TRST_ASSERT 1
/**
* Function tap_state_name
* Returns a string suitable for display representing the JTAG tap_state
*/
const char *tap_state_name(tap_state_t state);
/** Provides user-friendly name lookup of TAP states. */
tap_state_t tap_state_by_name(const char *name);
/** The current TAP state of the pending JTAG command queue. */
extern tap_state_t cmd_queue_cur_state;
/**
* This structure defines a single scan field in the scan. It provides
* fields for the field's width and pointers to scan input and output
* values.
*
* In addition, this structure includes a value and mask that is used by
* jtag_add_dr_scan_check() to validate the value that was scanned out.
*/
struct scan_field {
/** The number of bits this field specifies */
int num_bits;
/** A pointer to value to be scanned into the device */
const uint8_t *out_value;
/** A pointer to a 32-bit memory location for data scanned out */
uint8_t *in_value;
/** The value used to check the data scanned out. */
uint8_t *check_value;
/** The mask to go with check_value */
uint8_t *check_mask;
};
int handle_svf_command(char *filename);
#endif /* SVF_H */
@@ -0,0 +1,4 @@
OBMC_IMAGE_EXTRA_INSTALL:append = " \
phosphor-dbus-monitor \
tzdata \
"
@@ -0,0 +1,575 @@
From 76889ebb1cdc9d5cc2e29c065d1ab0c906b88f47 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Mon, 9 Dec 2024 14:30:51 +0800
Subject: [PATCH] Add Managers SEL log service
---
include/luxshare/sel.hpp | 434 ++++++++++++++++++++++++++++++
include/luxshare/utils.hpp | 38 +++
meson.build | 1 +
meson_options.txt | 8 +
redfish-core/lib/log_services.hpp | 6 +
src/webserver_main.cpp | 6 +
6 files changed, 493 insertions(+)
create mode 100755 include/luxshare/sel.hpp
create mode 100755 include/luxshare/utils.hpp
diff --git a/include/luxshare/sel.hpp b/include/luxshare/sel.hpp
new file mode 100755
index 00000000..cbaa1cd5
--- /dev/null
+++ b/include/luxshare/sel.hpp
@@ -0,0 +1,434 @@
+#pragma once
+#include <app.hpp>
+#include <async_resp.hpp>
+#include <luxshare/utils.hpp>
+#include <error_messages.hpp>
+#include <registries/privilege_registry.hpp>
+
+namespace crow
+{
+namespace luxshare_sel_api
+{
+
+enum class SELStatus
+{
+ DEASSERTED,
+ ASSERTED,
+ UNKNOWN
+};
+
+
+
+inline std::string translateSeverityDbusToRedfish(const std::string& s)
+{
+ if ((s == "xyz.openbmc_project.Logging.Entry.Level.Critical") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Emergency") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Error"))
+ {
+ return "Critical";
+ }
+ if ((s == "xyz.openbmc_project.Logging.Entry.Level.Debug") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Informational") ||
+ (s == "xyz.openbmc_project.Logging.Entry.Level.Notice"))
+ {
+ return "OK";
+ }
+ if (s == "xyz.openbmc_project.Logging.Entry.Level.Warning")
+ {
+ return "Warning";
+ }
+ if (s == "xyz.openbmc_project.Logging.Entry.Level.Alert")
+ {
+ return "NonRecoverable";
+ }
+ return "";
+}
+
+inline void requestRoutesSelClear(App& app)
+{
+ BMCWEB_ROUTE(
+ app,
+ "/redfish/v1/Managers/bmc/LogServices/SEL/Actions/LogService.ClearLog/")
+ .privileges(redfish::privileges::privilegeSetConfigureComponents)
+ .methods(boost::beast::http::verb::post)(
+ [](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ if (!redfish::luxshare::checkPostRequestBodyEmpty(req))
+ {
+ redfish::messages::actionParameterNotSupported(
+ asyncResp->res, req.body(), "ClearLog");
+ return;
+ }
+ using IpmiDbusRspType = std::tuple<uint8_t, uint8_t, uint8_t,
+ uint8_t, std::vector<uint8_t>>;
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code &ec, IpmiDbusRspType response1) {
+ // Handle the response of the first method call
+ if (ec) {
+ BMCWEB_LOG_ERROR("Error calling execute method: {}", ec.message());
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const uint8_t& cc1 = std::get<3>(response1);
+ if (cc1 != 0) {
+ BMCWEB_LOG_ERROR("Failed to reserve sel: cc: {}", cc1);
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Extract reservation ID from the response
+ std::vector<uint8_t> reservationId = std::get<4>(response1);
+ std::vector<uint8_t> commandData = {0x43, 0x4C, 0x52, 0xAA};
+ commandData.insert(commandData.begin(), reservationId.begin(), reservationId.end());
+
+ // Execute "Clear SEL" IPMI command
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code &ec1,IpmiDbusRspType response2) {
+ // Handle the response of the clear SEL command
+ if (ec1) {
+ BMCWEB_LOG_ERROR("Error calling execute method: {}", ec1.message());
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+
+ const uint8_t& cc2 = std::get<3>(response2);
+ if (cc2 != 0) {
+ BMCWEB_LOG_ERROR("Failed to clear sel: cc: {}", cc2);
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+
+ // Success logic for clearing SEL can go here
+ BMCWEB_LOG_INFO("Successfully cleared SEL.");
+ },
+ "xyz.openbmc_project.Ipmi.Host",
+ "/xyz/openbmc_project/Ipmi",
+ "xyz.openbmc_project.Ipmi.Server", "execute",
+ uint8_t{0x0a}, uint8_t{0x00}, uint8_t{0x47}, // Command to clear SEL
+ commandData,
+ std::map<std::string, std::variant<uint8_t>>{}
+ );
+ },
+ "xyz.openbmc_project.Ipmi.Host",
+ "/xyz/openbmc_project/Ipmi",
+ "xyz.openbmc_project.Ipmi.Server", "execute",
+ uint8_t{0x0a}, uint8_t{0x00}, uint8_t{0x42}, // Command to reserve SEL
+ std::vector<uint8_t>{},
+ std::map<std::string, std::variant<uint8_t>>{});
+ });
+}
+
+inline void requestRoutesSelEntries(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/SEL/Entries/")
+ .privileges(redfish::privileges::getLogService)
+ .methods(boost::beast::http::verb::get)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+ // Get sensor info from xyz.openbmc_project.Ipmi.Host
+ auto respHandler =
+ [asyncResp](
+ const boost::system::error_code& ec,
+ const std::unordered_map<std::string, std::vector<uint8_t>>&
+ sensorInfo) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error getting SensorInfo property: {}",
+ ec.message());
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+ // Get all sel log from xyz.openbmc_project.Logging service.
+ sdbusplus::message::object_path path(
+ "/xyz/openbmc_project/logging");
+ dbus::utility::getManagedObjects(
+ "xyz.openbmc_project.Logging", path,
+ [asyncResp,
+ sensorInfo](const boost::system::error_code& errorCode,
+ const dbus::utility::ManagedObjectType& resp) {
+ if (errorCode)
+ {
+ BMCWEB_LOG_ERROR("Logging GetManagedObjects error: {}",
+ errorCode.message());
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+
+ nlohmann::json& entriesArray =
+ asyncResp->res.jsonValue["Members"];
+ entriesArray = nlohmann::json::array();
+ std::map<uint32_t, uint64_t> idToTimestamp;
+ for (const auto& objectPath : resp)
+ {
+ const uint32_t* id = nullptr;
+ const uint64_t* timestamp = nullptr;
+ const std::string* severity = nullptr;
+ const std::string* message = nullptr;
+ const std::vector<std::string>* additionalData = nullptr;
+ nlohmann::json sensorName;
+ nlohmann::json sensorValue;
+ nlohmann::json sensorNumber;
+ nlohmann::json sensorType;
+ nlohmann::json eventType;
+ std::string sensorPath;
+ SELStatus selStatus = SELStatus::UNKNOWN;
+
+ for (const auto& interfaceMap : objectPath.second)
+ {
+ if (interfaceMap.first ==
+ "xyz.openbmc_project.Logging.Entry")
+ {
+ for (const auto& propertyMap : interfaceMap.second)
+ {
+ if (propertyMap.first == "Id")
+ {
+ id = std::get_if<uint32_t>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Timestamp")
+ {
+ timestamp = std::get_if<uint64_t>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Severity")
+ {
+ severity = std::get_if<std::string>(
+ &propertyMap.second);
+ }
+ else if (propertyMap.first == "Message")
+ {
+ message = std::get_if<std::string>(
+ &propertyMap.second);
+ if (*message ==
+ "xyz.openbmc_project.Common.Error."
+ "InternalFailure")
+ {
+ // Skip this entry
+ break;
+ }
+ }
+ else if (propertyMap.first == "AdditionalData")
+ {
+ additionalData =
+ std::get_if<std::vector<std::string>>(
+ &propertyMap.second);
+ }
+ }
+ }
+ }
+
+ if (id == nullptr || message == nullptr ||
+ timestamp == nullptr || severity == nullptr ||
+ additionalData == nullptr)
+ {
+ continue;
+ }
+
+ idToTimestamp[*id] = *timestamp;
+
+ entriesArray.push_back({});
+ nlohmann::json& thisEntry = entriesArray.back();
+ thisEntry["@odata.id"] = boost::urls::format(
+ "/redfish/v1/Managers/bmc/LogServices/SEL/Entries/{}",
+ std::to_string(*id));
+ thisEntry["Id"] = *id;
+ thisEntry["Message"] = *message;
+
+ // Get the Created time from the timestamp.
+ thisEntry["Created"] =
+ redfish::time_utils::getDateTimeUintMs(*timestamp);
+ thisEntry["Severity"] =
+ translateSeverityDbusToRedfish(*severity);
+
+ for (const auto& data : *additionalData)
+ {
+ if (data.starts_with("SENSOR_PATH="))
+ {
+ sensorPath =
+ data.substr(data.find_first_of('=') + 1);
+ if (!sensorPath.empty())
+ {
+ // Get the sensor name from the last level of
+ // the path.
+ sensorName =
+ data.substr(data.find_last_of('/') + 1);
+ }
+ }
+ else if (data.starts_with("EVENT_DIR="))
+ {
+ selStatus = static_cast<SELStatus>(std::stoi(
+ data.substr(data.find_first_of('=') + 1)));
+ }
+ else if (data.starts_with("READING="))
+ {
+ sensorValue =
+ data.substr(data.find_first_of('=') + 1);
+ }
+ else if (data.starts_with("SENSOR_DATA="))
+ {
+ // The second character is the status of the
+ // discrete sensor. Convert to string format
+ // starting with 0x.
+ auto sensorValueStr =
+ data.substr(data.find_first_of('=') + 2, 1);
+
+ try
+ {
+ std::stringstream output;
+ output << "0x" << std::hex << std::setw(2)
+ << std::setfill('0')
+ << static_cast<uint16_t>(std::stoi(
+ sensorValueStr, nullptr, 16));
+
+ sensorValue = output.str();
+ }
+ catch (const std::exception&)
+ {
+ sensorValue = nlohmann::json::value_t::null;
+ }
+ }
+ }
+
+ if (selStatus == SELStatus::UNKNOWN)
+ {
+ // Match SEL status in message property.
+ std::string messageStr = *message;
+ if (messageStr.find("deassert") != std::string::npos)
+ {
+ selStatus = SELStatus::DEASSERTED;
+ }
+ else
+ {
+ selStatus = SELStatus::ASSERTED;
+ }
+ }
+
+ if (sensorValue == nlohmann::json::value_t::null)
+ {
+ // Get SEL Reading in message properties.
+ std::string messageErased(*message);
+ std::string::size_type posString = 0;
+ posString = messageErased.find("Reading ");
+ if (posString == std::string::npos)
+ {
+ posString = messageErased.find("Reading=");
+ }
+
+ if (posString != std::string::npos)
+ {
+ // Offset the length of 'Reading ' or 'Reading=' to
+ // obtain the substring before the space.
+ messageErased = messageErased.substr(posString + 8);
+ auto posSpace = messageErased.find_last_of(' ');
+ if (posSpace != std::string::npos)
+ {
+ sensorValue = messageErased.substr(0, posSpace);
+ }
+ }
+ }
+
+ auto sensorEntryInfo = sensorInfo.find(sensorPath);
+ if (sensorEntryInfo != sensorInfo.end())
+ {
+ std::stringstream output;
+ // Sensor number subscript in the vector is 6.
+ output << "0x" << std::hex << std::setw(2)
+ << std::setfill('0')
+ << static_cast<uint16_t>(
+ sensorEntryInfo->second[6]);
+ sensorNumber = output.str();
+ // Sensor type subscript in the vector is 0.
+ output.str("");
+ output << "0x" << std::hex << std::setw(2)
+ << std::setfill('0')
+ << static_cast<uint16_t>(
+ sensorEntryInfo->second[0]);
+ sensorType = output.str();
+ // Event type subscript in the vector is 1.
+ output.str("");
+ output << "0x" << std::hex << std::setw(2)
+ << std::setfill('0')
+ << static_cast<uint16_t>(
+ sensorEntryInfo->second[1]);
+ eventType = output.str();
+ }
+
+ thisEntry["SensorType"] = sensorType;
+ thisEntry["SensorName"] = sensorName;
+ thisEntry["SensorNumber"] = sensorNumber;
+ thisEntry["SensorValue"] = sensorValue;
+ thisEntry["EventType"] = eventType;
+ if (selStatus == SELStatus::DEASSERTED)
+ {
+ thisEntry["Status"] = "Deasserted";
+ }
+ else
+ {
+ thisEntry["Status"] = "Asserted";
+ }
+ }
+
+ std::sort(entriesArray.begin(), entriesArray.end(),
+ [&idToTimestamp](const nlohmann::json& left,
+ const nlohmann::json& right) {
+ return (idToTimestamp[left["Id"].get<uint32_t>()] >=
+ idToTimestamp[right["Id"].get<uint32_t>()]);
+ });
+ asyncResp->res.jsonValue["Members@odata.count"] =
+ entriesArray.size();
+ });
+ };
+
+ sdbusplus::asio::getProperty<
+ std::unordered_map<std::string, std::vector<uint8_t>>>(
+ *crow::connections::systemBus, "xyz.openbmc_project.Ipmi.Host",
+ "/xyz/openbmc_project/Ipmi/SensorInfo",
+ "xyz.openbmc_project.IPMI.SensorInfo", "SensorInfo",
+ std::move(respHandler));
+ });
+}
+
+inline void requestRoutesSel(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/LogServices/SEL/")
+ .privileges(redfish::privileges::getLogService)
+ .methods(boost::beast::http::verb::get)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ asyncResp->res.jsonValue["@odata.type"] =
+ "#LogService.v1_1_0.LogService";
+ asyncResp->res.jsonValue["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/SEL";
+ asyncResp->res.jsonValue["Name"] = "Event Log Service";
+ asyncResp->res.jsonValue["Description"] = "System Event Log Service";
+ asyncResp->res.jsonValue["Id"] = "SEL";
+ std::pair<std::string, std::string> redfishDateTimeOffset =
+ redfish::time_utils::getDateTimeOffsetNow();
+ asyncResp->res.jsonValue["DateTime"] = redfishDateTimeOffset.first;
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] =
+ redfishDateTimeOffset.second;
+
+ asyncResp->res.jsonValue["Entries"]["@odata.id"] =
+ "/redfish/v1/Managers/bmc/LogServices/SEL/Entries";
+ });
+}
+
+inline void requestRoutes(App& app)
+{
+ requestRoutesSelClear(app);
+ requestRoutesSelEntries(app);
+ requestRoutesSel(app);
+}
+
+} // namespace luxshare_sel_api
+} // namespace crow
diff --git a/include/luxshare/utils.hpp b/include/luxshare/utils.hpp
new file mode 100755
index 00000000..d1d7b97a
--- /dev/null
+++ b/include/luxshare/utils.hpp
@@ -0,0 +1,38 @@
+#pragma once
+#include <utils/json_utils.hpp>
+#include <utils/sw_utils.hpp>
+
+
+namespace redfish
+{
+namespace luxshare
+{
+
+inline bool checkPostRequestBodyEmpty(const crow::Request& req)
+{
+ if (req.body().empty())
+ {
+ return true;
+ }
+
+ nlohmann::json jsonRequest = nlohmann::json::parse(req.body(), nullptr,
+ false);
+ if (jsonRequest.is_discarded())
+ {
+ BMCWEB_LOG_DEBUG("Failed to parse json in request");
+ return false;
+ }
+
+ nlohmann::json::object_t* object =
+ jsonRequest.get_ptr<nlohmann::json::object_t*>();
+ if (object == nullptr || (!object->empty()))
+ {
+ BMCWEB_LOG_DEBUG("Json value is not object or empty");
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace luxshare
+} // namespace redfish
diff --git a/meson.build b/meson.build
index fcc0d7c4..3afb44e1 100644
--- a/meson.build
+++ b/meson.build
@@ -94,6 +94,7 @@ feature_map = {
'experimental-redfish-multi-computer-system' : '-DBMCWEB_ENABLE_MULTI_COMPUTERSYSTEM',
'vm-websocket' : '-DBMCWEB_ENABLE_VM_WEBSOCKET',
'xtoken-auth' : '-DBMCWEB_ENABLE_XTOKEN_AUTHENTICATION',
+ 'luxshare-api' : '-DBMCWEB_ENABLE_LUXSHARE_API',
#'vm-nbdproxy' : '-DBMCWEB_ENABLE_VM_NBDPROXY',
}
diff --git a/meson_options.txt b/meson_options.txt
index 017c16bd..562ac55b 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -200,6 +200,14 @@ option(
/google/v1/'''
)
+# Luxshare redfish option
+option(
+ 'luxshare-api',
+ type: 'feature',
+ value : 'enabled',
+ description: 'Enable Luxshare readfish feature'
+)
+
option(
'http-body-limit',
type: 'integer',
diff --git a/redfish-core/lib/log_services.hpp b/redfish-core/lib/log_services.hpp
index 9cb1fe05..51fe2313 100644
--- a/redfish-core/lib/log_services.hpp
+++ b/redfish-core/lib/log_services.hpp
@@ -2365,6 +2365,12 @@ inline void handleBMCLogServicesCollectionGet(
nlohmann::json& logServiceArray = asyncResp->res.jsonValue["Members"];
logServiceArray = nlohmann::json::array();
+#ifdef BMCWEB_ENABLE_LUXSHARE_API
+ nlohmann::json::object_t eventLog;
+ eventLog["@odata.id"] = "/redfish/v1/Managers/bmc/LogServices/SEL";
+ logServiceArray.emplace_back(std::move(eventLog));
+#endif
+
#ifdef BMCWEB_ENABLE_REDFISH_BMC_JOURNAL
nlohmann::json::object_t journal;
journal["@odata.id"] = "/redfish/v1/Managers/bmc/LogServices/Journal";
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index 67e2aaef..0008ad52 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -28,6 +28,8 @@
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server.hpp>
+#include <luxshare/sel.hpp>
+
#include <exception>
#include <memory>
#include <string>
@@ -116,6 +118,10 @@ static int run()
crow::google_api::requestRoutes(app);
#endif
+#ifdef BMCWEB_ENABLE_LUXSHARE_API
+ crow::luxshare_sel_api::requestRoutes(app);
+#endif
+
if (bmcwebInsecureDisableXssPrevention != 0)
{
cors_preflight::requestRoutes(app);
--
2.25.1
@@ -0,0 +1,91 @@
From f8db58ca9b57df4e97d5775a9038011019299cb3 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Thu, 14 Nov 2024 19:09:27 +0800
Subject: [PATCH] Add ReleaseDate for BMC inventory
---
redfish-core/lib/update_service.hpp | 47 +++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 3 deletions(-)
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index af2725aa..cc3d939a 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -892,6 +892,45 @@ inline static void
}
}
+inline void
+ getSoftwareReleaseDate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& service, const std::string& path,
+ const std::string& purpose)
+{
+ if (purpose == sw_util::bmcPurpose)
+ {
+ sdbusplus::asio::getProperty<std::string>(
+ *crow::connections::systemBus, service, path,
+ "xyz.openbmc_project.Software.ReleaseDate", "ReleaseDate",
+ [asyncResp, path](const boost::system::error_code& ec,
+ const std::string& relDate) {
+ if (ec)
+ {
+ if (ec.value() ==
+ boost::system::linux_error::bad_request_descriptor)
+ {
+ BMCWEB_LOG_DEBUG("Priority do not available in {} {}", path,
+ ec.message());
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR(
+ "Error getting Priority property from {}: {}", path,
+ ec.message());
+ messages::internalError(asyncResp->res);
+ }
+ return;
+ }
+
+ asyncResp->res.jsonValue["ReleaseDate"] = relDate;
+ });
+ }
+ else
+ {
+ BMCWEB_LOG_DEBUG("Unknown software purpose {}", purpose);
+ }
+}
+
inline void
getSoftwareVersion(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
const std::string& service, const std::string& path,
@@ -900,7 +939,7 @@ inline void
sdbusplus::asio::getAllProperties(
*crow::connections::systemBus, service, path,
"xyz.openbmc_project.Software.Version",
- [asyncResp,
+ [asyncResp, service, path,
swId](const boost::system::error_code& ec,
const dbus::utility::DBusPropertiesMap& propertiesList) {
if (ec)
@@ -961,7 +1000,8 @@ inline void
std::string formatDesc = swInvPurpose->substr(endDesc);
asyncResp->res.jsonValue["Description"] = formatDesc + " image";
getRelatedItems(asyncResp, *swInvPurpose);
- });
+ getSoftwareReleaseDate(asyncResp, service, path, *swInvPurpose);
+ });
}
inline void requestRoutesSoftwareInventory(App& app)
@@ -1003,7 +1043,8 @@ inline void requestRoutesSoftwareInventory(App& app)
std::string, std::vector<std::string>>>>&
obj : subtree)
{
- if (!obj.first.ends_with(*swId))
+ if (sdbusplus::message::object_path(obj.first).filename() !=
+ *swId)
{
continue;
}
--
2.25.1
@@ -0,0 +1,517 @@
From b814ff4bd75cc7ac9eac4b2b0214d1947d8d05b7 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Fri, 17 Jan 2025 10:25:19 +0800
Subject: [PATCH] Add redfish oem rsyslog api
---
include/luxshare/dump.hpp | 461 ++++++++++++++++++++++++++++++++++
redfish-core/lib/managers.hpp | 4 +
src/webserver_main.cpp | 2 +
3 files changed, 467 insertions(+)
create mode 100755 include/luxshare/dump.hpp
diff --git a/include/luxshare/dump.hpp b/include/luxshare/dump.hpp
new file mode 100755
index 00000000..060e948f
--- /dev/null
+++ b/include/luxshare/dump.hpp
@@ -0,0 +1,461 @@
+#pragma once
+#include <app.hpp>
+#include <async_resp.hpp>
+#include <boost/asio/ip/address.hpp>
+#include <error_messages.hpp>
+#include <registries/privilege_registry.hpp>
+#include <xyz/openbmc_project/Common/Progress/server.hpp>
+
+#include <filesystem>
+#include <fstream>
+
+namespace crow
+{
+namespace luxshare_dump_api
+{
+
+namespace fs = std::filesystem;
+
+static const std::map<std::string, std::string> rsyslogIndexTranslation = {
+ {"index0", "Index0"},
+ {"index1", "Index1"},
+ {"index2", "Index2"},
+ {"index3", "Index3"}};
+
+
+inline std::string getRsyslogSettingsHelper(
+ const boost::asio::yield_context& yield,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& dbusObj, const std::string& propertyName)
+{
+ boost::system::error_code ec;
+ auto response = crow::connections::systemBus
+ ->yield_method_call<std::variant<std::string>>(
+ yield, ec, "xyz.openbmc_project.Settings", dbusObj,
+ "org.freedesktop.DBus.Properties", "Get",
+ "xyz.openbmc_project.Logging.Rsyslog",
+ propertyName);
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error getting {} property from {} : {}", propertyName,
+ dbusObj, ec.message());
+ redfish::messages::internalError(asyncResp->res);
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["Status"] = 1;
+ return std::string{};
+ }
+ const std::string* propertyValue = std::get_if<std::string>(&response);
+ if (propertyValue == nullptr)
+ {
+ BMCWEB_LOG_ERROR("D-Bus response gets null property value");
+ redfish::messages::internalError(asyncResp->res);
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["Status"] = 1;
+ return std::string{};
+ }
+ return *propertyValue;
+}
+
+template <typename PropertyType>
+inline void setRsyslogSettingsHelper(
+ const boost::asio::yield_context& yield,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const std::string& dbusObj, const std::string& propertyName,
+ const PropertyType& propertyValue)
+{
+ boost::system::error_code ec;
+ crow::connections::systemBus->yield_method_call<void>(
+ yield, ec, "xyz.openbmc_project.Settings", dbusObj,
+ "org.freedesktop.DBus.Properties", "Set",
+ "xyz.openbmc_project.Logging.Rsyslog", propertyName,
+ std::variant<PropertyType>(propertyValue));
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error setting {} property from {}: {}", propertyName,
+ dbusObj, ec.message());
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+}
+
+inline bool checkAddressTypeAndAddress(const std::string& dbusAddressType,
+ const std::string& dbusAddress)
+{
+ boost::system::error_code ec;
+ boost::asio::ip::address tmpAddress =
+ boost::asio::ip::make_address(dbusAddress, ec);
+ if (dbusAddressType == "xyz.openbmc_project.Logging.Rsyslog.Type.IPv4")
+ {
+ // check multicast address, broadcast address, and 0.x.x.x address.
+ if (!ec && tmpAddress.is_v4() && !tmpAddress.is_multicast() &&
+ (dbusAddress != "255.255.255.255") &&
+ !dbusAddress.starts_with("0."))
+ {
+ return true;
+ }
+ }
+ else if (dbusAddressType == "xyz.openbmc_project.Logging.Rsyslog.Type.IPv6")
+ {
+ // check multicast address
+ if (!ec && tmpAddress.is_v6() && !tmpAddress.is_multicast())
+ {
+ return true;
+ }
+ }
+
+ BMCWEB_LOG_DEBUG(
+ "address does not match addressType, or address is invalid");
+ return false;
+}
+
+inline void requestRoutesOemLuxshareRsyslogSettings(App& app)
+{
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Oem/Luxshare/RsyslogSettings/")
+ .privileges(redfish::privileges::getLogService)
+ .methods(boost::beast::http::verb::get)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ crow::connections::systemBus->async_method_call(
+ [asyncResp](const boost::system::error_code ec,
+ const std::vector<std::string>& subTreePaths) {
+ if (ec)
+ {
+ BMCWEB_LOG_ERROR("Error calling GetSubTreePaths method: {}",
+ ec.message());
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+ for (const auto& path : subTreePaths)
+ {
+ sdbusplus::asio::getAllProperties(
+ *crow::connections::systemBus,
+ "xyz.openbmc_project.Settings", path,
+ "xyz.openbmc_project.Logging.Rsyslog",
+ [asyncResp, path](const boost::system::error_code& ec1,
+ const dbus::utility::DBusPropertiesMap&
+ propertiesList) {
+ if (ec1)
+ {
+ BMCWEB_LOG_ERROR(
+ "Error getting Rsyslog properties from {}: {}",
+ path, ec1.message());
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+ const std::string* addressType = nullptr;
+ const std::string* address = nullptr;
+ const std::string* protocolType = nullptr;
+ const uint16_t* ports = nullptr;
+ const bool* status = nullptr;
+
+ bool success = sdbusplus::unpackPropertiesNoThrow(
+ redfish::dbus_utils::UnpackErrorPrinter(),
+ propertiesList, "AddressType", addressType, "Address",
+ address, "ProtocolType", protocolType, "Port", ports,
+ "Status", status);
+ if (!success)
+ {
+ BMCWEB_LOG_ERROR("Unpack error!");
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+
+ nlohmann::json::object_t obj;
+ if (addressType != nullptr)
+ {
+ obj["AddressType"] =
+ (*addressType) ==
+ "xyz.openbmc_project.Logging.Rsyslog.Type.IPv6"
+ ? "IPv6"
+ : "IPv4";
+ }
+ if (address != nullptr)
+ {
+ obj["Address"] = *address;
+ }
+ if (protocolType != nullptr)
+ {
+ obj["ProtocolType"] =
+ (*protocolType) ==
+ "xyz.openbmc_project.Logging.Rsyslog.Protocol.UDP"
+ ? "UDP"
+ : "TCP";
+ }
+ if (ports != nullptr)
+ {
+ obj["Port"] = *ports;
+ }
+ if (status != nullptr)
+ {
+ obj["Status"] = (*status) ? "Enabled" : "Disabled";
+ }
+ sdbusplus::message::object_path objectPath(path);
+ std::string rsyslogIndex =
+ rsyslogIndexTranslation.at(objectPath.filename());
+ if (path.starts_with(
+ "/xyz/openbmc_project/logging/rsyslog/audit_log/"))
+ {
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["AuditLog"]
+ [rsyslogIndex] = obj;
+ }
+ else if (
+ path.starts_with(
+ "/xyz/openbmc_project/logging/rsyslog/sel_log/"))
+ {
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["SEL"]
+ [rsyslogIndex] = obj;
+ }
+ else if (
+ path.starts_with(
+ "/xyz/openbmc_project/logging/rsyslog/sol_log/"))
+ {
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["SOL"]
+ [rsyslogIndex] = obj;
+ }
+ else if (
+ path.starts_with(
+ "/xyz/openbmc_project/logging/rsyslog/syslog_log/"))
+ {
+ asyncResp->res.jsonValue["Oem"]["Luxshare"]["Syslog"]
+ [rsyslogIndex] = obj;
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR("Can't find bmc D-Bus object!");
+ redfish::messages::internalError(asyncResp->res);
+ return;
+ }
+ });
+ }
+ },
+ "xyz.openbmc_project.ObjectMapper",
+ "/xyz/openbmc_project/object_mapper",
+ "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths",
+ "/xyz/openbmc_project/logging/rsyslog", 0,
+ std::array<const char*, 1>{"xyz.openbmc_project.Logging.Rsyslog"});
+ });
+
+ BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Oem/Luxshare/RsyslogSettings/")
+ .privileges(redfish::privileges::privilegeSetConfigureComponents)
+ .methods(boost::beast::http::verb::patch)(
+ [&app](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+ {
+ return;
+ }
+
+ boost::asio::spawn(
+ crow::connections::systemBus->get_io_context(),
+ [asyncResp, &req](const boost::asio::yield_context& yield) {
+ std::optional<nlohmann::json> oemLuxshareObject;
+ using InputMap =
+ std::map<std::string, std::optional<nlohmann::json>>;
+ InputMap logTypeMap = {{"Syslog", std::nullopt},
+ {"SEL", std::nullopt},
+ {"AuditLog", std::nullopt},
+ {"SOL", std::nullopt}};
+ InputMap indexMap = {{"index0", std::nullopt},
+ {"index1", std::nullopt},
+ {"index2", std::nullopt},
+ {"index3", std::nullopt}};
+ std::optional<std::string> status;
+ std::optional<std::string> addressType;
+ std::optional<std::string> address;
+ std::optional<uint16_t> ports;
+ std::optional<std::string> protocolType;
+ const std::map<std::string, std::string> dbusLogType = {
+ {"Syslog", "syslog_log"},
+ {"SEL", "sel_log"},
+ {"AuditLog", "audit_log"},
+ {"SOL", "sol_log"}};
+
+ if (!redfish::json_util::readJsonPatch(
+ req, asyncResp->res, "Oem/Luxshare", oemLuxshareObject))
+ {
+ BMCWEB_LOG_ERROR("readJsonPatch error!");
+ return;
+ }
+ if (!redfish::json_util::readJson(
+ oemLuxshareObject.value(), asyncResp->res, "Syslog",
+ logTypeMap["Syslog"], "SEL", logTypeMap["SEL"], "AuditLog",
+ logTypeMap["AuditLog"], "SOL", logTypeMap["SOL"]))
+ {
+ BMCWEB_LOG_ERROR("readJsonPatch error!");
+ return;
+ }
+
+ for (auto& logType : logTypeMap)
+ {
+ if (logType.second)
+ {
+ if (!redfish::json_util::readJson(
+ logType.second.value(), asyncResp->res, "Index0",
+ indexMap["index0"], "Index1", indexMap["index1"],
+ "Index2", indexMap["index2"], "Index3",
+ indexMap["index3"]))
+ {
+ BMCWEB_LOG_ERROR("readJson error!");
+ return;
+ }
+ for (auto& index : indexMap)
+ {
+ if (index.second)
+ {
+ status.reset();
+ addressType.reset();
+ address.reset();
+ ports.reset();
+ protocolType.reset();
+
+ if (!redfish::json_util::readJson(
+ index.second.value(), asyncResp->res,
+ "Status", status, "AddressType",
+ addressType, "Address", address, "Port",
+ ports, "ProtocolType", protocolType))
+ {
+ BMCWEB_LOG_ERROR("readJson error!");
+ return;
+ }
+ std::string dbusObj =
+ "/xyz/openbmc_project/logging/rsyslog/" +
+ dbusLogType.at(logType.first) + "/" +
+ index.first;
+
+ if (status)
+ {
+ if ((*status) != "Enabled" &&
+ (*status) != "Disabled")
+ {
+ BMCWEB_LOG_ERROR("status error: {}",
+ *status);
+ redfish::messages::propertyValueNotInList(
+ asyncResp->res, *status, "Status");
+ return;
+ }
+
+ bool dbusStatus = (*status) == "Enabled";
+ setRsyslogSettingsHelper(yield, asyncResp,
+ dbusObj, "Status",
+ dbusStatus);
+ }
+ if (addressType || address)
+ {
+ std::string dbusAddressType;
+ std::string dbusAddress;
+ // get addressType
+ if (addressType)
+ {
+ if (*addressType == "IPv6")
+ {
+ dbusAddressType =
+ "xyz.openbmc_project.Logging.Rsyslog.Type.IPv6";
+ }
+ else if (*addressType == "IPv4")
+ {
+ dbusAddressType =
+ "xyz.openbmc_project.Logging.Rsyslog.Type.IPv4";
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR(
+ "addresstype error: {}",
+ *addressType);
+ redfish::messages::
+ propertyValueNotInList(
+ asyncResp->res, *addressType,
+ "AddressType");
+ return;
+ }
+ }
+ else
+ {
+ dbusAddressType = getRsyslogSettingsHelper(
+ yield, asyncResp, dbusObj,
+ "AddressType");
+ }
+ // get address
+ if (address)
+ {
+ dbusAddress = *address;
+ }
+ else
+ {
+ dbusAddress = getRsyslogSettingsHelper(
+ yield, asyncResp, dbusObj, "Address");
+ }
+ // check if addressType and address is
+ // conflicted
+ if (!checkAddressTypeAndAddress(dbusAddressType,
+ dbusAddress))
+ {
+ BMCWEB_LOG_DEBUG(
+ "AddressType and address is conflicted");
+ redfish::messages::invalidObject(
+ asyncResp->res, "Address");
+ return;
+ }
+ // set addressType
+ if (addressType)
+ {
+ setRsyslogSettingsHelper(
+ yield, asyncResp, dbusObj,
+ "AddressType", dbusAddressType);
+ }
+ // set address
+ if (address)
+ {
+ setRsyslogSettingsHelper(yield, asyncResp,
+ dbusObj, "Address",
+ *address);
+ }
+ }
+ if (ports)
+ {
+ setRsyslogSettingsHelper(
+ yield, asyncResp, dbusObj, "Port", *ports);
+ }
+ if (protocolType)
+ {
+ std::string dbusProtocolType;
+ if (*protocolType == "UDP")
+ {
+ dbusProtocolType =
+ "xyz.openbmc_project.Logging.Rsyslog.Protocol.UDP";
+ }
+ else if (*protocolType == "TCP")
+ {
+ dbusProtocolType =
+ "xyz.openbmc_project.Logging.Rsyslog.Protocol.TCP";
+ }
+ else
+ {
+ BMCWEB_LOG_ERROR("protocolType error: {}",
+ *protocolType);
+ redfish::messages::propertyValueNotInList(
+ asyncResp->res, *protocolType,
+ "ProtocolType");
+ return;
+ }
+ setRsyslogSettingsHelper(
+ yield, asyncResp, dbusObj, "ProtocolType",
+ dbusProtocolType);
+ }
+ }
+ }
+ }
+ }
+ });
+ });
+}
+
+inline void requestRoutes(App& app)
+{
+ requestRoutesOemLuxshareRsyslogSettings(app);
+}
+
+} // namespace luxshare_dump_api
+} // namespace crow
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 05b8c292..7efe0335 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -2106,6 +2106,10 @@ inline void requestRoutesManager(App& app)
sw_util::populateSoftwareInformation(asyncResp, sw_util::bmcPurpose,
"FirmwareVersion", true);
+ nlohmann::json& luxshareOemObject =
+ asyncResp->res.jsonValue["Oem"]["Luxshare"];
+ luxshareOemObject["RsyslogSettings"]["@odata.id"] =
+ "/redfish/v1/Managers/bmc/Oem/Luxshare/RsyslogSettings";
managerGetLastResetTime(asyncResp);
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index f4f43254..9edb9b78 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -30,6 +30,7 @@
#include <luxshare/sel.hpp>
#include <luxshare/firmware_update.hpp>
+#include <luxshare/dump.hpp>
#include <exception>
#include <memory>
@@ -122,6 +123,7 @@ static int run()
#ifdef BMCWEB_ENABLE_LUXSHARE_API
crow::luxshare_sel_api::requestRoutes(app);
crow::luxshare_update_firmware::requestRoutes(app);
+ crow::luxshare_dump_api::requestRoutes(app);
#endif
if (bmcwebInsecureDisableXssPrevention != 0)
--
2.25.1
@@ -0,0 +1,27 @@
From fc722c287eb1186d66dc8be949e845decf3588e3 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Tue, 12 Nov 2024 10:28:29 +0800
Subject: [PATCH] Fix webui set static ip failed issue
---
redfish-core/lib/ethernet.hpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index 8de854f7..1c288e13 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -1415,8 +1415,8 @@ inline void
if (nicIpEntry != ipv4Data.cend())
{
deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
- nicIpEntry->id, prefixLength, *gateway,
- *address, asyncResp);
+ nicIpEntry->id, prefixLength, *address,
+ *gateway, asyncResp);
nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
ipv4Data.cend());
}
--
2.25.1
@@ -0,0 +1,36 @@
From 13d1bbbba793c3fb2b81bdc2789a9bf2a3809cd9 Mon Sep 17 00:00:00 2001
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
Date: Tue, 17 Dec 2024 21:25:10 +0800
Subject: [PATCH] Modify nbd proxy path The path of nbd-proxy is modified from
/usr/sbin to /usr/bin
---
include/luxshare/sel.hpp | 0
include/luxshare/utils.hpp | 0
include/vm_websocket.hpp | 2 +-
3 files changed, 1 insertion(+), 1 deletion(-)
mode change 100755 => 100644 include/luxshare/sel.hpp
mode change 100755 => 100644 include/luxshare/utils.hpp
diff --git a/include/luxshare/sel.hpp b/include/luxshare/sel.hpp
old mode 100755
new mode 100644
diff --git a/include/luxshare/utils.hpp b/include/luxshare/utils.hpp
old mode 100755
new mode 100644
diff --git a/include/vm_websocket.hpp b/include/vm_websocket.hpp
index 1b06a93d..a8d6a149 100644
--- a/include/vm_websocket.hpp
+++ b/include/vm_websocket.hpp
@@ -56,7 +56,7 @@ class Handler : public std::enable_shared_from_this<Handler>
void connect()
{
std::error_code ec;
- proxy = boost::process::child("/usr/sbin/nbd-proxy", media,
+ proxy = boost::process::child("/usr/bin/nbd-proxy", media,
boost::process::std_out > pipeOut,
boost::process::std_in < pipeIn, ec);
if (ec)
--
2.25.1
@@ -0,0 +1,26 @@
From f2375ff9d5c343225163167d3ed52330ef1484e0 Mon Sep 17 00:00:00 2001
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
Date: Wed, 18 Dec 2024 20:14:39 +0800
Subject: [PATCH] Modify task max timeout time to 10 minutes When update bios,
the update task time may over 5 minutes, get task status will return fail
---
redfish-core/lib/update_service.hpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index cc3d939a..53b65d0d 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -240,7 +240,7 @@ static void
// if we're getting status updates it's
// still alive, update timer
- taskData->extendTimer(std::chrono::minutes(5));
+ taskData->extendTimer(std::chrono::minutes(10));
}
// as firmware update often results in a
--
2.25.1
@@ -0,0 +1,124 @@
From 7e909a983073baa858e0245adf7f7694cb13d88c Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Thu, 19 Dec 2024 19:23:12 +0800
Subject: [PATCH] Only add sensors in ipmi sensor json file to active sensor
list
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
redfish-core/lib/sensors.hpp | 84 +++++++++++++++++++++++++++++++++++-
1 file changed, 82 insertions(+), 2 deletions(-)
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index 04e48c5c..20f21a93 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -432,6 +432,81 @@ void getConnections(std::shared_ptr<SensorsAsyncResp> sensorsAsyncResp,
std::move(objectsWithConnectionCb));
}
+struct SensorInfo
+{
+ std::string sensorName;
+ uint8_t readingType;
+ uint8_t sensorType;
+};
+
+using SensorMessages = std::unordered_map<std::string, SensorInfo>;
+
+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);
+}
+
/**
* @brief Shrinks the list of sensors for processing
* @param SensorsAysncResp The class holding the Redfish response
@@ -443,7 +518,7 @@ void getConnections(std::shared_ptr<SensorsAsyncResp> sensorsAsyncResp,
*/
inline void reduceSensorList(
crow::Response& res, std::string_view chassisSubNode,
- std::span<const std::string_view> sensorTypes,
+ [[maybe_unused]] std::span<const std::string_view> sensorTypes,
const std::vector<std::string>* allSensors,
const std::shared_ptr<std::set<std::string>>& activeSensors)
{
@@ -468,8 +543,13 @@ inline void reduceSensorList(
{
if (sensor.starts_with(type))
{
- activeSensors->emplace(sensor);
+ auto sensorInfo = getSensorInfo(sensor);
+ if (sensorInfo != std::nullopt)
+ {
+ activeSensors->emplace(sensor);
+ }
}
+
}
}
}
--
2.34.1
@@ -0,0 +1,50 @@
From 15ec7caabeb6ed2bb01e8ef9e3d9bc6efd1415e0 Mon Sep 17 00:00:00 2001
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
Date: Mon, 25 Nov 2024 21:49:32 +0800
Subject: [PATCH] Remove web sensor underscores
---
redfish-core/lib/sensors.hpp | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index 5bd846d6..04e48c5c 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -744,7 +744,6 @@ inline void objectPropertiesToJson(
sensorJson["Id"] = std::move(subNodeEscaped);
std::string sensorNameEs(sensorName);
- std::replace(sensorNameEs.begin(), sensorNameEs.end(), '_', ' ');
sensorJson["Name"] = std::move(sensorNameEs);
}
else if (sensorType != "power")
@@ -753,7 +752,6 @@ inline void objectPropertiesToJson(
// PowerControl, those properties have more general values because
// multiple sensors can be stored in the same JSON object.
std::string sensorNameEs(sensorName);
- std::replace(sensorNameEs.begin(), sensorNameEs.end(), '_', ' ');
sensorJson["Name"] = std::move(sensorNameEs);
}
@@ -1074,7 +1072,6 @@ inline void populateFanRedundancy(
sensorsAsyncResp->asyncResp->res);
return;
}
- std::replace(name.begin(), name.end(), '_', ' ');
std::string health;
@@ -1103,8 +1100,7 @@ inline void populateFanRedundancy(
}
/*
todo(ed): merge patch that fixes the names
- std::replace(itemName.begin(),
- itemName.end(), '_', ' ');*/
+ */
auto schemaItem =
std::find_if(fanRedfish.begin(), fanRedfish.end(),
[itemName](const nlohmann::json& fan) {
--
2.25.1
@@ -0,0 +1,122 @@
From 2070b4aaf3eab4f4478ef30881e55a685523263f Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Fri, 8 Nov 2024 14:38:24 +0800
Subject: [PATCH] Reset static ipv4 address when turn off dhcpv4
---
redfish-core/lib/ethernet.hpp | 71 +++++++++++++++++++++++++++++------
1 file changed, 59 insertions(+), 12 deletions(-)
diff --git a/redfish-core/lib/ethernet.hpp b/redfish-core/lib/ethernet.hpp
index 57fe24c4..8de854f7 100644
--- a/redfish-core/lib/ethernet.hpp
+++ b/redfish-core/lib/ethernet.hpp
@@ -1044,10 +1044,51 @@ inline void
});
}
-inline void setDHCPEnabled(const std::string& ifaceId,
- const std::string& propertyName, const bool v4Value,
- const bool v6Value,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+inline void handleIPv4DHCPDisableKeepIp(
+ const std::string& ifaceId, const bool v4Value,
+ const std::vector<IPv4AddressData>& ipv4Data,
+ const std::optional<nlohmann::json::array_t> &
+ ipv4StaticAddresses,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+{
+ // If v4DHCP is disabled, and there is no incoming static address data,
+ // if have any existing DHCP addresses, change them to static addresses
+ if (!v4Value && !ipv4StaticAddresses)
+ {
+ auto it = std::find_if(
+ ipv4Data.begin(), ipv4Data.end(),
+ [](const IPv4AddressData& addr) { return addr.origin == "DHCP"; });
+
+ if (it == ipv4Data.end())
+ {
+ // Do nothing
+ BMCWEB_LOG_INFO("No DHCP addresses to convert to static");
+ return;
+ }
+
+ uint8_t prefixLength = 0;
+ std::string address = it->address;
+ std::string gateway = it->gateway;
+ std::string netmask = it->netmask;
+
+ if (!ip_util::ipv4VerifyIpAndGetBitcount(netmask, &prefixLength))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ createIPv4(ifaceId, prefixLength, gateway, address, asyncResp);
+ }
+}
+
+inline void setDHCPEnabled(
+ const std::string& ifaceId,
+ const std::string& propertyName,const bool v4Value,
+ const bool v6Value,
+ const std::vector<IPv4AddressData>& ipv4Data,
+ const std::optional<nlohmann::json::array_t> &
+ ipv4StaticAddresses,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
sdbusplus::asio::setProperty(
@@ -1063,6 +1104,8 @@ inline void setDHCPEnabled(const std::string& ifaceId,
}
messages::success(asyncResp->res);
});
+ handleIPv4DHCPDisableKeepIp(ifaceId, v4Value, ipv4Data, ipv4StaticAddresses,
+ asyncResp);
}
inline void setEthernetInterfaceBoolProperty(
@@ -1122,11 +1165,15 @@ inline void handleSLAACAutoConfigPatch(
});
}
-inline void handleDHCPPatch(const std::string& ifaceId,
- const EthernetInterfaceData& ethData,
- const DHCPParameters& v4dhcpParms,
- const DHCPParameters& v6dhcpParms,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+inline void handleDHCPPatch(
+ const std::string& ifaceId,
+ const EthernetInterfaceData& ethData,
+ const std::optional<nlohmann::json::array_t> &
+ ipv4StaticAddresses,
+ const std::vector<IPv4AddressData>& ipv4Data,
+ const DHCPParameters& v4dhcpParms,
+ const DHCPParameters& v6dhcpParms,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
@@ -1223,7 +1270,7 @@ inline void handleDHCPPatch(const std::string& ifaceId,
BMCWEB_LOG_DEBUG("set DHCPEnabled...");
setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
- asyncResp);
+ ipv4Data, ipv4StaticAddresses, asyncResp);
BMCWEB_LOG_DEBUG("set DNSEnabled...");
setDHCPv4Config("DNSEnabled", nextDNS, asyncResp);
BMCWEB_LOG_DEBUG("set NTPEnabled...");
@@ -2051,8 +2098,8 @@ inline void requestEthernetInterfacesRoutes(App& app)
if (dhcpv4 || dhcpv6)
{
- handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
- asyncResp);
+ handleDHCPPatch(ifaceId, ethData, ipv4StaticAddresses, ipv4Data,
+ v4dhcpParms, v6dhcpParms, asyncResp);
}
if (hostname)
--
2.25.1
@@ -0,0 +1,179 @@
From cfd7bb5a9175a2fa01aa314cace2c3fd0be85d07 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Tue, 26 Nov 2024 16:49:35 +0800
Subject: [PATCH] Support redfish set bmc timezone
---
redfish-core/include/utils/time_utils.hpp | 40 ++++++++++++-
redfish-core/lib/managers.hpp | 68 ++++++++++++++++++++++-
2 files changed, 105 insertions(+), 3 deletions(-)
diff --git a/redfish-core/include/utils/time_utils.hpp b/redfish-core/include/utils/time_utils.hpp
index 314ea85d..c69eec28 100644
--- a/redfish-core/include/utils/time_utils.hpp
+++ b/redfish-core/include/utils/time_utils.hpp
@@ -13,6 +13,7 @@
#include <ratio>
#include <string>
#include <string_view>
+#include <regex>
// IWYU pragma: no_include <stddef.h>
// IWYU pragma: no_include <stdint.h>
@@ -284,6 +285,15 @@ std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
using days = std::chrono::duration<
IntType, std::ratio_multiply<hours::period, std::ratio<24>>>;
+ time_t timep;
+ time(&timep);
+ struct tm* localTime = localtime(&timep);
+ auto validLocalTime = mktime(localTime);
+ struct tm* gmTime = gmtime(&timep);
+ auto validGmTime = mktime(gmTime);
+ auto timeEquation = validLocalTime - validGmTime;
+
+ t += std::chrono::seconds(timeEquation);
// d is days since 1970-01-01
days d = std::chrono::duration_cast<days>(t);
@@ -348,8 +358,9 @@ std::string toISO8061ExtendedStr(std::chrono::duration<IntType, Period> t)
MicroDuration subsec = duration_cast<MicroDuration>(t);
out += details::padZeros(subsec.count(), 6);
}
-
- out += "+00:00";
+ char tzstring[32] = {0};
+ std::snprintf(tzstring, sizeof(tzstring), "%+03lld:00", timeEquation/3600);
+ out += tzstring;
return out;
}
} // namespace details
@@ -445,5 +456,30 @@ inline std::optional<usSinceEpoch> dateStringToEpoch(std::string_view datetime)
return std::chrono::duration<uint64_t, std::micro>{durMicroSecs};
}
+inline bool isValidTimeOffset(const std::string& timeOffset) {
+ std::regex timeOffsetRegex(R"(^([-+][0-1][0-9]:[0-5][0-9])$)");
+
+ return std::regex_match(timeOffset, timeOffsetRegex);
+}
+
+int convertTimeOffsetToMinutes(const std::string& timeOffset) {
+
+ if (!isValidTimeOffset(timeOffset)) {
+ return -1;
+ }
+
+ int hours = std::stoi(timeOffset.substr(1, 2));
+ if(hours < -13 || hours > 12)
+ {
+ return -1;
+ }
+ int totalMinutes = hours * 60;
+
+ if (timeOffset[0] == '-') {
+ totalMinutes = -totalMinutes;
+ }
+ return totalMinutes;
+}
+
} // namespace time_utils
} // namespace redfish
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index a114d440..30395284 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -1879,6 +1879,67 @@ inline void setDateTime(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
});
}
+inline void setDateTimeLocalOffset(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
+ std::string datetimelocaloffset)
+{
+ int hrs = 0;
+ char ZoneInfoFile[128] = {0}, file[32] = {0};
+ static constexpr int16_t SEL_UTC_MAX_RANGE = 1440;
+ static constexpr int16_t SEL_UTC_MIN_RANGE = -1440;
+ static constexpr int16_t UNSPECIFIED_UTC_OFFSET = 0x7ff;
+ constexpr auto LOCALTIME = "/etc/localtime";
+ int UTCOffset = redfish::time_utils::convertTimeOffsetToMinutes(datetimelocaloffset);
+ if (((UTCOffset > SEL_UTC_MAX_RANGE ) || (UTCOffset < SEL_UTC_MIN_RANGE) || (UTCOffset % 60 != 0)) && UTCOffset != UNSPECIFIED_UTC_OFFSET)
+ {
+ messages::propertyValueOutOfRange(asyncResp->res, datetimelocaloffset,
+ "DateTimeLocalOffset");
+ return;
+ }
+
+ hrs = UTCOffset / 60;
+ if(UTCOffset == UNSPECIFIED_UTC_OFFSET)
+ {
+ hrs = 0;
+ }
+
+ if (0 > UTCOffset)
+ {
+ if (snprintf(file,sizeof(file), "GMT+%d", -hrs) >= static_cast<long int>(sizeof(file)))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+ else
+ {
+ if (snprintf(file,sizeof(file), "GMT-%d", hrs) >= static_cast<long int>(sizeof(file)))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+ }
+
+ if (snprintf (ZoneInfoFile, sizeof(ZoneInfoFile), "%s/%s", "/usr/share/zoneinfo/Etc", file) >= static_cast<long int>(sizeof(ZoneInfoFile)))
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if((0 > unlink(LOCALTIME)) && errno != ENOENT)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ if(symlink(ZoneInfoFile, LOCALTIME) < 0)
+ {
+ messages::internalError(asyncResp->res);
+ return;
+ }
+
+ asyncResp->res.jsonValue["DateTimeLocalOffset"] = datetimelocaloffset;
+}
+
inline void
checkForQuiesced(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
@@ -2189,9 +2250,10 @@ inline void requestRoutesManager(App& app)
std::optional<nlohmann::json> oem;
std::optional<nlohmann::json> links;
std::optional<std::string> datetime;
+ std::optional<std::string> datatimelocaloffset;
if (!json_util::readJsonPatch(req, asyncResp->res, "Oem", oem,
- "DateTime", datetime, "Links", links))
+ "DateTime", datetime, "Links", links, "DateTimeLocalOffset", datatimelocaloffset))
{
return;
}
@@ -2252,6 +2314,10 @@ inline void requestRoutesManager(App& app)
{
setDateTime(asyncResp, std::move(*datetime));
}
+ if (datatimelocaloffset)
+ {
+ setDateTimeLocalOffset(asyncResp, std::move(*datatimelocaloffset));
+ }
});
}
--
2.25.1
@@ -0,0 +1,62 @@
From 925563a9f9ec895ffbc0c5db39f1d02258ceb1df Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Wed, 18 Dec 2024 13:59:12 +0800
Subject: [PATCH] Support webui switch bmc boot source
---
redfish-core/lib/managers.hpp | 31 ++++++++++++++++++++++++++++++-
1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index 30395284..0680e38d 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -1739,6 +1739,8 @@ inline void
});
}
+#define MAIN_BMC_BOOT_SOURCE "/sys/devices/platform/ahb/1e620000.spi/access_primary"
+#define BACKUP_BMC_BOOT_SOURCE "/sys/devices/platform/ahb/1e620000.spi/access_backup"
/**
* @brief Set the running firmware image
*
@@ -1843,9 +1845,35 @@ inline void
messages::internalError(asyncResp->res);
return;
}
- doBMCGracefulRestart(asyncResp);
+ // doBMCGracefulRestart(asyncResp);
});
});
+
+ char cmd[256] = {0};
+ std::string currentSelector;
+ std::ifstream slotFile("/run/media/slot");
+ std::getline(slotFile, currentSelector);
+ if (currentSelector == "0")
+ {
+ memset(cmd, 0 , sizeof(cmd));
+ snprintf(cmd, sizeof(cmd), "echo 1 > %s", BACKUP_BMC_BOOT_SOURCE);
+ if(system(cmd))
+ {
+ BMCWEB_LOG_DEBUG("Set BMC boot from backup flash failed.");
+ return;
+ }
+ }
+ if (currentSelector == "1")
+ {
+ memset(cmd, 0 , sizeof(cmd));
+ snprintf(cmd, sizeof(cmd), "echo 1 > %s", MAIN_BMC_BOOT_SOURCE);
+ if(system(cmd))
+ {
+ BMCWEB_LOG_DEBUG("Set BMC boot from main flash failed.");
+ return;
+ }
+ }
+
}
inline void setDateTime(std::shared_ptr<bmcweb::AsyncResp> asyncResp,
--
2.25.1
@@ -0,0 +1,188 @@
From 6fb46035f50ab26d177747df558d961bcbe2914a Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Tue, 24 Dec 2024 16:57:11 +0800
Subject: [PATCH] Sync webui sensor status with ipmi
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
redfish-core/lib/sensors.hpp | 122 +++++++++++++++++++++++++++++++++--
1 file changed, 117 insertions(+), 5 deletions(-)
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index 20f21a93..722a111d 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -672,11 +672,12 @@ void getChassis(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
}
/**
- * @brief Returns the Redfish State value for the specified inventory item.
+ * @brief Returns the Redfish PSU State value for the specified inventory item.
* @param inventoryItem D-Bus inventory item associated with a sensor.
+ * available.
* @return State value for inventory item.
*/
-inline std::string getState(const InventoryItem* inventoryItem)
+inline std::string getPsuState(const InventoryItem* inventoryItem)
{
if ((inventoryItem != nullptr) && !(inventoryItem->isPresent))
{
@@ -686,6 +687,76 @@ inline std::string getState(const InventoryItem* inventoryItem)
return "Enabled";
}
+/**
+ * @brief Returns the Redfish State value for the specified inventory item.
+ * @param inventoryItem D-Bus inventory item associated with a sensor.
+ * @return State value for inventory item.
+ */
+inline std::string getState(const dbus::utility::DBusPropertiesMap& valuesDict,
+ nlohmann::json& sensorJson)
+{
+ std::string currentstate;
+ auto statusIt = sensorJson.find("Status");
+ if (statusIt != sensorJson.end())
+ {
+ auto stateIt = statusIt->find("State");
+ if (stateIt != statusIt->end())
+ {
+ std::string* state = stateIt->get_ptr<std::string*>();
+ if (state != nullptr)
+ {
+ currentstate = *state;
+ }
+ }
+ }
+
+ auto nameIt = sensorJson.find("Name");
+ if (nameIt != sensorJson.end())
+ {
+ std::string* name = nameIt->get_ptr<std::string*>();
+ if (name != nullptr && name->ends_with("_Supply"))
+ {
+ return currentstate;
+ }
+ }
+
+ if (currentstate == "Disabled")
+ {
+ return "Disabled";
+ }
+
+ for (const auto& [property, value] : valuesDict)
+ {
+ if (property == "Available")
+ {
+ const bool* available = std::get_if<bool>(&value);
+ if ((available != nullptr) && !(*available))
+ {
+ return "Disabled";
+ }
+ }
+ }
+
+ if (currentstate == "No Reading")
+ {
+ return "No Reading";
+ }
+
+ for (const auto& [property, value] : valuesDict)
+ {
+ if (property == "Functional")
+ {
+ const bool* functional = std::get_if<bool>(&value);
+ if ((functional != nullptr) && !(*functional))
+ {
+ return "No Reading";
+ }
+ }
+ }
+
+ return "Enabled";
+}
+
/**
* @brief Returns the Redfish Health value for the specified sensor.
* @param sensorJson Sensor JSON object.
@@ -702,9 +773,20 @@ inline std::string getHealth(nlohmann::json& sensorJson,
// objects contain multiple sensors (such as PowerSupplies). We want to set
// the overall health to be the most severe of any of the sensors.
std::string currentHealth;
+ std::string currentstate;
auto statusIt = sensorJson.find("Status");
if (statusIt != sensorJson.end())
{
+ auto stateIt = statusIt->find("State");
+ if (stateIt != statusIt->end())
+ {
+ std::string* state = stateIt->get_ptr<std::string*>();
+ if (state != nullptr)
+ {
+ currentstate = *state;
+ }
+ }
+
auto healthIt = statusIt->find("Health");
if (healthIt != statusIt->end())
{
@@ -716,6 +798,36 @@ inline std::string getHealth(nlohmann::json& sensorJson,
}
}
+ if (currentstate == "Disabled" || currentstate == "No Reading")
+ {
+ return "ns";
+ }
+
+ // If current health in JSON object is already NonRecoverable, return that.
+ // This should override the sensor health, which might be less severe.
+ if (currentHealth == "NonRecoverable")
+ {
+ return "NonRecoverable";
+ }
+
+ // Check if sensor has NonRecoverable threshold alarm
+ for (const auto& [prop, value] : valuesDict)
+ {
+ if (prop == "NonRecoverableAlarmHigh" ||
+ prop == "NonRecoverableAlarmLow")
+ {
+ const bool* asserted = std::get_if<bool>(&value);
+ if (asserted == nullptr)
+ {
+ BMCWEB_LOG_ERROR("Illegal sensor threshold");
+ }
+ else if (*asserted)
+ {
+ return "NonRecoverable";
+ }
+ }
+ }
+
// If current health in JSON object is already Critical, return that. This
// should override the sensor health, which might be less severe.
if (currentHealth == "Critical")
@@ -835,9 +947,9 @@ inline void objectPropertiesToJson(
sensorJson["Name"] = std::move(sensorNameEs);
}
- sensorJson["Status"]["State"] = getState(inventoryItem);
+ sensorJson["Status"]["State"] = getState(propertiesDict, sensorJson);
sensorJson["Status"]["Health"] = getHealth(sensorJson, propertiesDict,
- inventoryItem);
+ nullptr);
// Parameter to set to override the type we get from dbus, and force it to
// int, regardless of what is available. This is used for schemas like fan,
@@ -2294,7 +2406,7 @@ inline nlohmann::json& getPowerSupply(nlohmann::json& powerSupplyArray,
inventoryItem.powerSupplyEfficiencyPercent;
}
- powerSupply["Status"]["State"] = getState(&inventoryItem);
+ powerSupply["Status"]["State"] = getPsuState(&inventoryItem);
const char* health = inventoryItem.isFunctional ? "OK" : "Critical";
powerSupply["Status"]["Health"] = health;
--
2.34.1
@@ -0,0 +1,25 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
DEPENDS += " \
phosphor-dbus-interfaces \
"
SRC_URI:append = " \
file://0001-Reset-static-ipv4-address-when-turn-off-dhcpv4.patch \
file://0001-Fix-webui-set-static-ip-failed-issue.patch \
file://0001-Remove-web-sensor-underscores.patch \
file://0001-Support-redfish-set-bmc-timezone.patch \
file://0001-Add-Managers-SEL-log-service.patch \
file://0001-Modify-nbd-proxy-path.patch \
file://0001-Support-webui-switch-bmc-boot-source.patch \
file://0001-Modify-task-max-timeout-time-to-10-minutes.patch \
file://0001-Only-add-sensors-in-ipmi-sensor-json-file-to-active-.patch \
file://0001-Sync-webui-sensor-status-with-ipmi.patch \
file://0001-Add-ReleaseDate-for-BMC-inventory.patch \
file://0001-Add-luxshare-oem-redfish-update-interface.patch \
file://0001-Add-redfish-oem-rsyslog-api.patch \
"
EXTRA_OEMESON:append = " \
-Dhttp-body-limit=65 \
"
+41
View File
@@ -0,0 +1,41 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
LICENSE = "CLOSED"
SUMMARY = "FRU Write IPMI Command"
TARGET_CC_ARCH += "${LDFLAGS}"
SRC_URI += " \
file://ipmi-fru.cpp \
file://Makefile \
"
SRCREV = "${AUTOREV}"
PR = "r1"
SO_VERSION = "1"
S = "${WORKDIR}"
DEPENDS = " \
boost \
sdbusplus \
phosphor-ipmi-host \
phosphor-logging \
"
inherit pkgconfig
inherit obmc-phosphor-ipmiprovider-symlink
do_compile () {
oe_runmake
}
do_install() {
install -d ${D}${libdir}/ipmid-providers
install -m 0755 ${S}/libipmi-fru.so.${SO_VERSION} ${D}/${libdir}/ipmid-providers/
}
HOSTIPMI_PROVIDER_LIBRARY += "libipmi-fru.so"
FILES:${PN}:append = " ${libdir}/ipmid-providers/lib*${SOLIBS}"
FILES:${PN}:append = " ${libdir}/host-ipmid/lib*${SOLIBS}"
RDEPENDS_${PN} += " phosphor-ipmi-host"
+21
View File
@@ -0,0 +1,21 @@
SRC = ipmi-fru.cpp
SO_VERSION = 1
OUTPUT = libipmi-fru.so.$(SO_VERSION)
CFLAGS += -O3 -Wno-unused-result -std=c++20
BUILD_LIB = -shared -fPIC
BOOST_CXX_FLAG += -DBOOST_ERROR_CODE_HEADER_ONLY
BOOST_CXX_FLAG += -DBOOST_SYSTEM_NO_DEPRECATED
BOOST_CXX_FLAG += -DBOOST_ALL_NO_LIB
BOOST_CXX_FLAG += -DBOOST_NO_RTTI
BOOST_CXX_FLAG += -DBOOST_NO_TYPEID
BOOST_CXX_FLAG += -DBOOST_ASIO_DISABLE_THREADS
BOOST_CXX_FLAG += -DBOOST_COROUTINES_NO_DEPRECATION_WARNING
LIBS += -lsdbusplus -lsystemd -lipmid
all: $(SRC)
$(CXX) $(BUILD_LIB) $(SRC) -o $(OUTPUT) $(CFLAGS) $(LIBS) $(BOOST_CXX_FLAG)
clean:
-rm -rf $(OUTPUT)
@@ -0,0 +1,180 @@
#include <boost/algorithm/string.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/process.hpp>
#include <filesystem>
#include <functional>
#include <iostream>
#include <fstream>
#include <ipmid/api.hpp>
#include <ipmid/message.hpp>
#include <ipmid/types.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/message/types.hpp>
#include <sdbusplus/timer.hpp>
#include <stdexcept>
#include <string_view>
namespace ipmi {
namespace storage {
std::map<uint8_t, std::string> __attribute__((init_priority(101)))
fruIDMap = {{0, "/sys/bus/i2c/devices/i2c-14/14-0053/eeprom"}};
std::map<uint8_t, std::vector<uint8_t>> fruCache
__attribute__((init_priority(101)));
constexpr uint16_t FRUMAXSIZE = 0x8000;
void register_netfn_storage_functions() __attribute__((constructor));
void cacheFruData() {
for (auto fruInfo : fruIDMap) {
std::ifstream fruFile(fruInfo.second, std::ios::binary);
if (!fruFile) {
continue;
}
fruFile.seekg(0, std::ios::end);
std::streampos fileSize = fruFile.tellg();
fruFile.seekg(0, std::ios::beg);
fruCache[fruInfo.first].resize(fileSize);
fruFile.read(reinterpret_cast<char *>(fruCache[fruInfo.first].data()),
fileSize);
fruCache[fruInfo.first].resize(FRUMAXSIZE);
}
}
/** @brief implements the write FRU data command
* @param fruDeviceId - FRU Device ID
* @param fruInventoryOffset - FRU Inventory Offset to write
* @param dataToWrite - Data to write
*
* @returns ipmi completion code plus response data
* - countWritten - Count written
*/
ipmi::RspType<uint8_t>
ipmiStorageWriteFruData(ipmi::Context::ptr ctx, uint8_t fruDeviceId,
uint16_t fruInventoryOffset,
std::vector<uint8_t> &dataToWrite) {
constexpr uint8_t fruHeaderMutiRecOffset = 5;
constexpr uint8_t fruHeaderCheckSumOffset = 7;
uint8_t countWritten = 0;
if (fruIDMap.find(fruDeviceId) == fruIDMap.end() || fruDeviceId == 0xFF ||
fruCache.find(fruDeviceId) == fruCache.end()) {
return ipmi::responseInvalidFieldRequest();
}
// Not Support MutiRecord, set to disabled
if (fruInventoryOffset == 0) {
dataToWrite[fruHeaderMutiRecOffset] = 0;
int zsum = 0;
for (uint8_t index = 0; index < 5; index++)
zsum += dataToWrite[index];
dataToWrite[fruHeaderCheckSumOffset] = -(zsum % 256);
}
if ((fruInventoryOffset + dataToWrite.size()) > FRUMAXSIZE) {
return ipmi::responseParmOutOfRange();
}
std::copy(dataToWrite.begin(), dataToWrite.end(),
fruCache[fruDeviceId].begin() + fruInventoryOffset);
std::ofstream fruFile(fruIDMap[fruDeviceId],
std::ios::binary | std::ios::out);
if (!fruFile) {
return ipmi::responseUnspecifiedError();
}
fruFile.seekp(fruInventoryOffset);
std::copy(dataToWrite.begin(), dataToWrite.end(),
std::ostreambuf_iterator<char>(fruFile));
countWritten = std::min(dataToWrite.size(), static_cast<size_t>(0xFF));
return ipmi::responseSuccess(countWritten);
}
/**@brief implements the Read FRU Data command
* @param fruDeviceId - FRU device ID. FFh = reserved
* @param offset - FRU inventory offset to read
* @param readCount - count to read
*
* @return IPMI completion code plus response data
* - returnCount - response data count.
* - data - response data
*/
ipmi::RspType<uint8_t, // count returned
std::vector<uint8_t>> // FRU data
ipmiStorageReadFruData(uint8_t fruDeviceId, uint16_t offset,
uint8_t readCount) {
if (fruDeviceId == 0xFF) {
return ipmi::responseInvalidFieldRequest();
}
auto iter = fruIDMap.find(fruDeviceId);
if (iter == fruIDMap.end()) {
return ipmi::responseSensorInvalid();
}
if (fruCache.find(fruDeviceId) == fruCache.end()) {
return ipmi::responseSensorInvalid();
}
uint8_t returnCount;
if ((offset + readCount) <= FRUMAXSIZE) {
returnCount = readCount;
} else {
returnCount = FRUMAXSIZE - offset;
}
std::vector<uint8_t> fruData(
(fruCache[fruDeviceId].begin() + offset),
(fruCache[fruDeviceId].begin() + offset + returnCount));
return ipmi::responseSuccess(returnCount, fruData);
}
/** @brief implements the get FRU Inventory Area Info command
*
* @returns IPMI completion code plus response data
* - FRU Inventory area size in bytes,
* - access bit
**/
ipmi::RspType<uint16_t, // FRU Inventory area size in bytes,
uint8_t // access size (bytes / words)
>
ipmiStorageGetFruInvAreaInfo(uint8_t fruID) {
auto iter = fruIDMap.find(fruID);
if (iter == fruIDMap.end()) {
return ipmi::responseSensorInvalid();
}
if (!std::filesystem::exists(iter->second)) {
return ipmi::responseSensorInvalid();
}
return ipmi::responseSuccess(static_cast<uint16_t>(FRUMAXSIZE),
static_cast<uint8_t>(0));
}
void register_netfn_storage_functions() {
cacheFruData();
// <WRITE FRU Data>
ipmi::registerHandler(ipmi::prioMax, ipmi::netFnStorage,
ipmi::storage::cmdWriteFruData,
ipmi::Privilege::Operator, ipmiStorageWriteFruData);
// <READ FRU Data>
ipmi::registerHandler(ipmi::prioMax, ipmi::netFnStorage,
ipmi::storage::cmdReadFruData,
ipmi::Privilege::Operator, ipmiStorageReadFruData);
// <Get FRU Inventory Area Info>
ipmi::registerHandler(ipmi::prioMax, ipmi::netFnStorage,
ipmi::storage::cmdGetFruInventoryAreaInfo,
ipmi::Privilege::User, ipmiStorageGetFruInvAreaInfo);
}
} // namespace storage
} // namespace ipmi
@@ -0,0 +1,866 @@
From c5fdb031d5b352a32dce058b8326637b82b79fe7 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Thu, 12 Dec 2024 11:17:57 +0800
Subject: [PATCH] change ipmitool to shared objects
---
include/ipmitool/Makefile.am | 6 +-
include/ipmitool/ipmi_sel_desc.h | 797 +++++++++++++++++++++++++++++++
lib/Makefile.am | 2 +-
src/plugins/Makefile.am | 2 +-
4 files changed, 803 insertions(+), 4 deletions(-)
create mode 100755 include/ipmitool/ipmi_sel_desc.h
diff --git a/include/ipmitool/Makefile.am b/include/ipmitool/Makefile.am
index 8bc584a..fb4d72f 100644
--- a/include/ipmitool/Makefile.am
+++ b/include/ipmitool/Makefile.am
@@ -30,7 +30,8 @@
MAINTAINERCLEANFILES = Makefile.in
-noinst_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \
+pkgincludedir = $(includedir)/ipmitool
+pkginclude_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \
ipmi_chassis.h ipmi_entity.h ipmi_fru.h ipmi_hpmfwupg.h ipmi_lanp.h \
ipmi_sdr.h ipmi_sel.h ipmi_sol.h ipmi_mc.h ipmi_raw.h \
ipmi_channel.h ipmi_sensor.h ipmi_event.h ipmi_session.h \
@@ -39,4 +40,5 @@ noinst_HEADERS = log.h bswap.h hpm2.h helper.h ipmi.h ipmi_cc.h ipmi_intf.h \
ipmi_fwum.h ipmi_main.h ipmi_tsol.h ipmi_firewall.h \
ipmi_kontronoem.h ipmi_ekanalyzer.h ipmi_gendev.h ipmi_ime.h \
ipmi_delloem.h ipmi_dcmi.h ipmi_vita.h ipmi_sel_supermicro.h \
- ipmi_cfgp.h ipmi_lanp6.h ipmi_quantaoem.h
+ ipmi_cfgp.h ipmi_lanp6.h ipmi_quantaoem.h ipmi_time.h ipmi_sel_desc.h
+
diff --git a/include/ipmitool/ipmi_sel_desc.h b/include/ipmitool/ipmi_sel_desc.h
new file mode 100755
index 0000000..942857c
--- /dev/null
+++ b/include/ipmitool/ipmi_sel_desc.h
@@ -0,0 +1,797 @@
+#ifndef IPMI_SEL_DESC_H
+#define IPMI_SEL_DESC_H
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#define SEL_OEM_TS_DATA_LEN 6
+#define SEL_OEM_NOTS_DATA_LEN 13
+#define HDD_NVME_STATUS_EVT2 0x3
+#define EXPANDER_ERR_EVT2 0x4
+#define EXPANDER_ERR_EVT3 0x5
+#define POWER_FAULT_EVT2 0x6
+#define BMC_BOOT_EVT2 0x7
+#define BMC_BOOT_EVT3 0x8
+#define LEAKAGE_EVT2 0x0A
+#define FW_UPDATE_EVT2 0x0B
+#define FW_UPDATE_EVT3 0x0C
+#define RETIMER_ERR_EVT2 0x0D
+
+#define SENSOR_TYPE_MAX 0x2C
+
+// Definition for PowerFault sensor
+#define SIZE_OF_POWER_FAULT 10 /* Max Size of the length of the power_fault array */
+#define MAX_EVENT_STR 128 /* Max Size of each event string */
+
+static const char sensor_power_fault[SIZE_OF_POWER_FAULT][MAX_EVENT_STR] = {
+ "PSU",
+ "MAINBOARD",
+ "FAN",
+ "NVME",
+ "OCP",
+ "RISER",
+ "CPU",
+ "DIMM",
+ "OTHER",
+ "ACCELERATOR"};
+
+/* sensor type codes (IPMI v1.5 table 36.3)
+ / Updated to v2.0 Table 42-3, Sensor Type Codes */
+static const char *sensor_type_desc[] = {
+ "reserved",
+ "Temperature",
+ "Voltage",
+ "Current",
+ "Fan",
+ "Physical Security",
+ "Platform Security",
+ "Processor",
+ "Power Supply",
+ "Power Unit",
+ "Cooling Device",
+ "Other",
+ "Memory",
+ "Drive Slot / Bay",
+ "POST Memory Resize",
+ "System Firmwares",
+ "Event Logging Disabled",
+ "Watchdog1",
+ "System Event",
+ "Critical Interrupt",
+ "Button",
+ "Module / Board",
+ "Microcontroller",
+ "Add-in Card",
+ "Chassis",
+ "Chip Set",
+ "Other FRU",
+ "Cable / Interconnect",
+ "Terminator",
+ "System Boot Initiated",
+ "Boot Error",
+ "OS Boot",
+ "OS Critical Stop",
+ "Slot / Connector",
+ "System ACPI Power State",
+ "Watchdog2",
+ "Platform Alert",
+ "Entity Presence",
+ "Monitor ASIC",
+ "LAN",
+ "Management Subsys Health",
+ "Battery",
+ "Session Audit",
+ "Version Change",
+ "FRU State"};
+
+/* IPMI 2.0 Table 43-15, Sensor Unit Type Codes */
+#define UNIT_TYPE_MAX 92 /* This is the ID of "grams" */
+#define UNIT_TYPE_LONGEST_NAME 19 /* This is the length of "color temp deg K" */
+static const char *unit_desc[] = {
+ "unspecified",
+ "degrees C",
+ "degrees F",
+ "degrees K",
+ "Volts",
+ "Amps",
+ "Watts",
+ "Joules",
+ "Coulombs",
+ "VA",
+ "Nits",
+ "lumen",
+ "lux",
+ "Candela",
+ "kPa",
+ "PSI",
+ "Newton",
+ "CFM",
+ "RPM",
+ "Hz",
+ "microsecond",
+ "millisecond",
+ "second",
+ "minute",
+ "hour",
+ "day",
+ "week",
+ "mil",
+ "inches",
+ "feet",
+ "cu in",
+ "cu feet",
+ "mm",
+ "cm",
+ "m",
+ "cu cm",
+ "cu m",
+ "liters",
+ "fluid ounce",
+ "radians",
+ "steradians",
+ "revolutions",
+ "cycles",
+ "gravities",
+ "ounce",
+ "pound",
+ "ft-lb",
+ "oz-in",
+ "gauss",
+ "gilberts",
+ "henry",
+ "millihenry",
+ "farad",
+ "microfarad",
+ "ohms",
+ "siemens",
+ "mole",
+ "becquerel",
+ "PPM",
+ "reserved",
+ "Decibels",
+ "DbA",
+ "DbC",
+ "gray",
+ "sievert",
+ "color temp deg K",
+ "bit",
+ "kilobit",
+ "megabit",
+ "gigabit",
+ "byte",
+ "kilobyte",
+ "megabyte",
+ "gigabyte",
+ "word",
+ "dword",
+ "qword",
+ "line",
+ "hit",
+ "miss",
+ "retry",
+ "reset",
+ "overflow",
+ "underrun",
+ "collision",
+ "packets",
+ "messages",
+ "characters",
+ "error",
+ "correctable error",
+ "uncorrectable error",
+ "fatal error",
+ "grams"
+};
+
+struct ipmi_event_data_types
+{
+ uint8_t flag;
+ uint8_t data;
+ char desc[256];
+};
+
+static struct ipmi_event_data_types HDD_NVME_Status_evt2[] = {
+ {HDD_NVME_STATUS_EVT2, 0x00, ""},
+};
+
+static struct ipmi_event_data_types Expander_Err_evt2[] = {
+ {EXPANDER_ERR_EVT2, 0x00, ""},
+};
+
+static struct ipmi_event_data_types Expander_Err_evt3[] = {
+ {EXPANDER_ERR_EVT3, 0x00, ""},
+};
+
+static struct ipmi_event_data_types Retimer_Err_evt2[] = {
+ {RETIMER_ERR_EVT2, 0x00, ""},
+};
+
+static struct ipmi_event_data_types power_fault_evt2[] = {
+ {POWER_FAULT_EVT2, 0x00, "Fault event of PSU"},
+ {POWER_FAULT_EVT2, 0x01, "main board 12V inlet eFuse overcurrent protection event"},
+ {POWER_FAULT_EVT2, 0x02, "Fault or PG events related to fan board power supply"},
+ {POWER_FAULT_EVT2, 0x03, "NVMe backplane power supply Fault or PG event"},
+ {POWER_FAULT_EVT2, 0x04, "Fault or PG event related to OCP card power supply"},
+ {POWER_FAULT_EVT2, 0x05, "Fault or PG event related to Riser board power supply"},
+ {POWER_FAULT_EVT2, 0x06, "CPU power supply related Fault or PG events"},
+ {POWER_FAULT_EVT2, 0x07, "DIMM related power supply Fault/PG events"},
+ {POWER_FAULT_EVT2, 0x08, "Other system module power supply Fault/PG event"},
+ {POWER_FAULT_EVT2, 0xff, "Other kinds of power on timeout events"},
+};
+
+static struct ipmi_event_data_types BMC_BOOT_evt2[] = {
+ {BMC_BOOT_EVT2, 0xaa, ""},
+};
+
+static struct ipmi_event_data_types BMC_BOOT_evt3[] = {
+ {BMC_BOOT_EVT3, 0x00, ", AC power on"},
+ {BMC_BOOT_EVT3, 0x01, ", ExtReset Pin reset"},
+ {BMC_BOOT_EVT3, 0x02, ", Bmc startup FMT_WDT2 timeout"},
+ {BMC_BOOT_EVT3, 0x03, ", Bmc runtime watchdog timeout"},
+ {BMC_BOOT_EVT3, 0x04, ", Bmc cold reset "},
+ {BMC_BOOT_EVT3, 0x05, ", Bmc warm reset"},
+ {BMC_BOOT_EVT3, 0x06, ", Execute reboot command in shell"},
+ {BMC_BOOT_EVT3, 0x08, ", Upgrade and restart"},
+ {BMC_BOOT_EVT3, 0x0f, ", The main process restarts only"}};
+
+static struct ipmi_event_data_types Leakage_evt2[] = {
+ {LEAKAGE_EVT2, 0x00, ", Leakage Point default"},
+ {LEAKAGE_EVT2, 0x01, ", Leakage Point A"},
+ {LEAKAGE_EVT2, 0x02, ", Leakage Point B"},
+ {LEAKAGE_EVT2, 0x03, ", Leakage Point C"},
+ {LEAKAGE_EVT2, 0x04, ", Leakage Point D"},
+ {LEAKAGE_EVT2, 0x05, ", Leakage Point E"},
+};
+
+static struct ipmi_event_data_types FW_Update_evt2[] = {
+ {FW_UPDATE_EVT2, 0x01, ""},
+ {FW_UPDATE_EVT2, 0x02, ""},
+ {FW_UPDATE_EVT2, 0x03, ""},
+};
+static struct ipmi_event_data_types FW_Update_evt3[] = {
+ {FW_UPDATE_EVT3, 0x01, ", image-1(BMC)"},
+ {FW_UPDATE_EVT3, 0x02, ", image-2(BMC)"},
+ {FW_UPDATE_EVT3, 0xFF, ", BIOS"},
+};
+
+struct ipmi_event_sensor_types
+{
+ uint8_t code;
+ uint8_t offset;
+#define ALL_OFFSETS_SPECIFIED 0xff
+ uint8_t data;
+ const char *desc;
+ struct ipmi_event_data_types *evt2;
+ struct ipmi_event_data_types *evt3;
+};
+
+struct ipmi_oem_event_sensor_types
+{
+ uint8_t code0;
+ uint8_t code1;
+ uint8_t code2;
+ uint8_t code3;
+ const char *desc;
+};
+
+struct ipmi_oem_specific_sensor_types
+{
+ uint8_t flag;
+ uint8_t code;
+ const char *desc;
+};
+
+static struct ipmi_event_sensor_types generic_event_types[] = {
+ /* Threshold Based States */
+ {0x01, 0x00, 0xff, "Lower Non-critical going low"},
+ {0x01, 0x01, 0xff, "Lower Non-critical going high"},
+ {0x01, 0x02, 0xff, "Lower Critical going low"},
+ {0x01, 0x03, 0xff, "Lower Critical going high"},
+ {0x01, 0x04, 0xff, "Lower Non-recoverable going low"},
+ {0x01, 0x05, 0xff, "Lower Non-recoverable going high"},
+ {0x01, 0x06, 0xff, "Upper Non-critical going low"},
+ {0x01, 0x07, 0xff, "Upper Non-critical going high"},
+ {0x01, 0x08, 0xff, "Upper Critical going low"},
+ {0x01, 0x09, 0xff, "Upper Critical going high"},
+ {0x01, 0x0a, 0xff, "Upper Non-recoverable going low"},
+ {0x01, 0x0b, 0xff, "Upper Non-recoverable going high"},
+ /* DMI-based "usage state" States */
+ {0x02, 0x00, 0xff, "Transition to Idle"},
+ {0x02, 0x01, 0xff, "Transition to Active"},
+ {0x02, 0x02, 0xff, "Transition to Busy"},
+ /* Digital-Discrete Event States */
+ {0x03, 0x00, 0xff, "State Deasserted", power_fault_evt2},
+ {0x03, 0x01, 0xff, "State Asserted", power_fault_evt2},
+ {0x04, 0x00, 0xff, "Predictive Failure Deasserted"},
+ {0x04, 0x01, 0xff, "Predictive Failure Asserted"},
+ {0x05, 0x00, 0xff, "Limit Not Exceeded"},
+ {0x05, 0x01, 0xff, "Limit Exceeded"},
+ {0x06, 0x00, 0xff, "Performance Met"},
+ {0x06, 0x01, 0xff, "Performance Lags"},
+ /* Severity Event States */
+ {0x07, 0x00, 0xff, "Transition to OK", Leakage_evt2},
+ {0x07, 0x01, 0xff, "Transition to Non-critical from OK", Leakage_evt2},
+ {0x07, 0x02, 0xff, "Transition to Critical from less severe"},
+ {0x07, 0x03, 0xff, "Transition to Non-recoverable from less severe"},
+ {0x07, 0x04, 0xff, "Transition to Non-critical from more severe"},
+ {0x07, 0x05, 0xff, "Transition to Critical from Non-recoverable"},
+ {0x07, 0x06, 0xff, "Transition to Non-recoverable"},
+ {0x07, 0x07, 0xff, "Monitor"},
+ {0x07, 0x08, 0xff, "Informational"},
+ /* Availability Status States */
+ {0x08, 0x00, 0xff, "Device Absent"},
+ {0x08, 0x01, 0xff, "Device Present"},
+ {0x09, 0x00, 0xff, "Device Disabled"},
+ {0x09, 0x01, 0xff, "Device Enabled"},
+ {0x0a, 0x00, 0xff, "Transition to Running"},
+ {0x0a, 0x01, 0xff, "Transition to In Test"},
+ {0x0a, 0x02, 0xff, "Transition to Power Off"},
+ {0x0a, 0x03, 0xff, "Transition to On Line"},
+ {0x0a, 0x04, 0xff, "Transition to Off Line"},
+ {0x0a, 0x05, 0xff, "Transition to Off Duty"},
+ {0x0a, 0x06, 0xff, "Transition to Degraded"},
+ {0x0a, 0x07, 0xff, "Transition to Power Save"},
+ {0x0a, 0x08, 0xff, "Install Error"},
+ /* Redundancy States */
+ {0x0b, 0x00, 0xff, "Fully Redundant"},
+ {0x0b, 0x01, 0xff, "Redundancy Lost"},
+ {0x0b, 0x02, 0xff, "Redundancy Degraded"},
+ {0x0b, 0x03, 0xff, "Non-Redundant: Sufficient from Redundant"},
+ {0x0b, 0x04, 0xff, "Non-Redundant: Sufficient from Insufficient"},
+ {0x0b, 0x05, 0xff, "Non-Redundant: Insufficient Resources"},
+ {0x0b, 0x06, 0xff, "Redundancy Degraded from Fully Redundant"},
+ {0x0b, 0x07, 0xff, "Redundancy Degraded from Non-Redundant"},
+ /* ACPI Device Power States */
+ {0x0c, 0x00, 0xff, "D0 Power State"},
+ {0x0c, 0x01, 0xff, "D1 Power State"},
+ {0x0c, 0x02, 0xff, "D2 Power State"},
+ {0x0c, 0x03, 0xff, "D3 Power State"},
+ /* END */
+ {0x00, 0x00, 0xff, NULL},
+};
+
+static struct ipmi_event_sensor_types sensor_retimer_event_types[] = {
+ /* Digital-Discrete Event States */
+ {0x03, 0x00, 0xff, "State Deasserted"},
+ {0x03, 0x01, 0xff, "State Asserted", Retimer_Err_evt2},
+ /* END */
+ {0x00, 0x00, 0xff, NULL},
+};
+
+static struct ipmi_event_sensor_types sensor_specific_event_types[] = {
+ /* Physical Security */
+ {0x05, 0x00, 0xff, "General Chassis intrusion"},
+ {0x05, 0x01, 0xff, "Drive Bay intrusion"},
+ {0x05, 0x02, 0xff, "I/O Card area intrusion"},
+ {0x05, 0x03, 0xff, "Processor area intrusion"},
+ {0x05, 0x04, 0xff, "System unplugged from LAN"},
+ {0x05, 0x05, 0xff, "Unauthorized dock"},
+ {0x05, 0x06, 0xff, "FAN area intrusion"},
+ /* Platform Security */
+ {0x06, 0x00, 0xff, "Front Panel Lockout violation attempted"},
+ {0x06, 0x01, 0xff, "Pre-boot password violation - user password"},
+ {0x06, 0x02, 0xff, "Pre-boot password violation - setup password"},
+ {0x06, 0x03, 0xff, "Pre-boot password violation - network boot password"},
+ {0x06, 0x04, 0xff, "Other pre-boot password violation"},
+ {0x06, 0x05, 0xff, "Out-of-band access password violation"},
+ /* Processor */
+ {0x07, 0x00, 0xff, "IERR"},
+ {0x07, 0x01, 0xff, "Thermal Trip"},
+ {0x07, 0x02, 0xff, "FRB1/BIST failure"},
+ {0x07, 0x03, 0xff, "FRB2/Hang in POST failure"},
+ {0x07, 0x04, 0xff, "FRB3/Processor startup/init failure"},
+ {0x07, 0x05, 0xff, "Configuration Error"},
+ {0x07, 0x06, 0xff, "SM BIOS Uncorrectable CPU-complex Error"},
+ {0x07, 0x07, 0xff, "Presence detected"},
+ {0x07, 0x08, 0xff, "Disabled"},
+ {0x07, 0x09, 0xff, "Terminator presence detected"},
+ {0x07, 0x0a, 0xff, "Throttled"},
+ {0x07, 0x0b, 0xff, "Uncorrectable machine check exception"},
+ {0x07, 0x0c, 0xff, "Correctable machine check error"},
+ /* Power Supply */
+ {0x08, 0x00, 0xff, "Presence detected"},
+ {0x08, 0x01, 0xff, "Failure detected"},
+ {0x08, 0x02, 0xff, "Predictive failure"},
+ {0x08, 0x03, 0xff, "Power Supply AC lost"},
+ {0x08, 0x04, 0xff, "AC lost or out-of-range"},
+ {0x08, 0x05, 0xff, "AC out-of-range, but present"},
+ {0x08, 0x06, 0x00, "Config Error: Vendor Mismatch"},
+ {0x08, 0x06, 0x01, "Config Error: Revision Mismatch"},
+ {0x08, 0x06, 0x02, "Config Error: Processor Missing"},
+ {0x08, 0x06, 0x03, "Config Error: Power Supply Rating Mismatch"},
+ {0x08, 0x06, 0x04, "Config Error: Voltage Rating Mismatch"},
+ {0x08, 0x06, 0xff, "Config Error"},
+ {0x08, 0x07, 0xff, "Power Supply Inactive"},
+ /* Power Unit */
+ {0x09, 0x00, 0xff, "Power off/down"},
+ {0x09, 0x01, 0xff, "Power cycle"},
+ {0x09, 0x02, 0xff, "240VA power down"},
+ {0x09, 0x03, 0xff, "Interlock power down"},
+ {0x09, 0x04, 0xff, "AC lost"},
+ {0x09, 0x05, 0xff, "Soft-power control failure"},
+ {0x09, 0x06, 0xff, "Failure detected"},
+ {0x09, 0x07, 0xff, "Predictive failure"},
+ /* Memory */
+ {0x0c, 0x00, 0xff, "Correctable ECC"},
+ {0x0c, 0x01, 0xff, "Uncorrectable ECC"},
+ {0x0c, 0x02, 0xff, "Parity"},
+ {0x0c, 0x03, 0xff, "Memory Scrub Failed"},
+ {0x0c, 0x04, 0xff, "Memory Device Disabled"},
+ {0x0c, 0x05, 0xff, "Correctable ECC logging limit reached"},
+ {0x0c, 0x06, 0xff, "Presence Detected"},
+ {0x0c, 0x07, 0xff, "Configuration Error"},
+ {0x0c, 0x08, 0xff, "Spare"},
+ {0x0c, 0x09, 0xff, "Throttled"},
+ {0x0c, 0x0a, 0xff, "Critical Overtemperature"},
+ /* Drive Slot */
+ {0x0d, 0x00, 0xff, "Drive Present", HDD_NVME_Status_evt2},
+ {0x0d, 0x01, 0xff, "Drive Fault", HDD_NVME_Status_evt2},
+ {0x0d, 0x02, 0xff, "Predictive Failure"},
+ {0x0d, 0x03, 0xff, "Hot Spare"},
+ {0x0d, 0x04, 0xff, "Parity Check In Progress"},
+ {0x0d, 0x05, 0xff, "In Critical Array"},
+ {0x0d, 0x06, 0xff, "In Failed Array"},
+ {0x0d, 0x07, 0xff, "Rebuild In Progress"},
+ {0x0d, 0x08, 0xff, "Rebuild Aborted"},
+ /* System Firmware Error */
+ {0x0f, 0x00, 0x00, "Unspecified"},
+ {0x0f, 0x00, 0x01, "No system memory installed"},
+ {0x0f, 0x00, 0x02, "No usable system memory"},
+ {0x0f, 0x00, 0x03, "Unrecoverable IDE device failure"},
+ {0x0f, 0x00, 0x04, "Unrecoverable system-board failure"},
+ {0x0f, 0x00, 0x05, "Unrecoverable diskette failure"},
+ {0x0f, 0x00, 0x06, "Unrecoverable hard-disk controller failure"},
+ {0x0f, 0x00, 0x07, "Unrecoverable PS/2 or USB keyboard failure"},
+ {0x0f, 0x00, 0x08, "Removable boot media not found"},
+ {0x0f, 0x00, 0x09, "Unrecoverable video controller failure"},
+ {0x0f, 0x00, 0x0a, "No video device selected"},
+ {0x0f, 0x00, 0x0b, "BIOS corruption detected"},
+ {0x0f, 0x00, 0x0c, "CPU voltage mismatch"},
+ {0x0f, 0x00, 0x0d, "CPU speed mismatch failure"},
+ {0x0f, 0x00, 0xff, "Unknown Error"},
+ /* System Firmware Hang */
+ {0x0f, 0x01, 0x00, "Unspecified"},
+ {0x0f, 0x01, 0x01, "Memory initialization"},
+ {0x0f, 0x01, 0x02, "Hard-disk initialization"},
+ {0x0f, 0x01, 0x03, "Secondary CPU Initialization"},
+ {0x0f, 0x01, 0x04, "User authentication"},
+ {0x0f, 0x01, 0x05, "User-initiated system setup"},
+ {0x0f, 0x01, 0x06, "USB resource configuration"},
+ {0x0f, 0x01, 0x07, "PCI resource configuration"},
+ {0x0f, 0x01, 0x08, "Option ROM initialization"},
+ {0x0f, 0x01, 0x09, "Video initialization"},
+ {0x0f, 0x01, 0x0a, "Cache initialization"},
+ {0x0f, 0x01, 0x0b, "SMBus initialization"},
+ {0x0f, 0x01, 0x0c, "Keyboard controller initialization"},
+ {0x0f, 0x01, 0x0d, "Management controller initialization"},
+ {0x0f, 0x01, 0x0e, "Docking station attachment"},
+ {0x0f, 0x01, 0x0f, "Enabling docking station"},
+ {0x0f, 0x01, 0x10, "Docking station ejection"},
+ {0x0f, 0x01, 0x11, "Disabling docking station"},
+ {0x0f, 0x01, 0x12, "Calling operating system wake-up vector"},
+ {0x0f, 0x01, 0x13, "System boot initiated"},
+ {0x0f, 0x01, 0x14, "Motherboard initialization"},
+ {0x0f, 0x01, 0x15, "reserved"},
+ {0x0f, 0x01, 0x16, "Floppy initialization"},
+ {0x0f, 0x01, 0x17, "Keyboard test"},
+ {0x0f, 0x01, 0x18, "Pointing device test"},
+ {0x0f, 0x01, 0x19, "Primary CPU initialization"},
+ {0x0f, 0x01, 0xff, "Unknown Hang"},
+ /* System Firmware Progress */
+ {0x0f, 0x02, 0x00, "Unspecified"},
+ {0x0f, 0x02, 0x01, "Memory initialization"},
+ {0x0f, 0x02, 0x02, "Hard-disk initialization"},
+ {0x0f, 0x02, 0x03, "Secondary CPU Initialization"},
+ {0x0f, 0x02, 0x04, "User authentication"},
+ {0x0f, 0x02, 0x05, "User-initiated system setup"},
+ {0x0f, 0x02, 0x06, "USB resource configuration"},
+ {0x0f, 0x02, 0x07, "PCI resource configuration"},
+ {0x0f, 0x02, 0x08, "Option ROM initialization"},
+ {0x0f, 0x02, 0x09, "Video initialization"},
+ {0x0f, 0x02, 0x0a, "Cache initialization"},
+ {0x0f, 0x02, 0x0b, "SMBus initialization"},
+ {0x0f, 0x02, 0x0c, "Keyboard controller initialization"},
+ {0x0f, 0x02, 0x0d, "Management controller initialization"},
+ {0x0f, 0x02, 0x0e, "Docking station attachment"},
+ {0x0f, 0x02, 0x0f, "Enabling docking station"},
+ {0x0f, 0x02, 0x10, "Docking station ejection"},
+ {0x0f, 0x02, 0x11, "Disabling docking station"},
+ {0x0f, 0x02, 0x12, "Calling operating system wake-up vector"},
+ {0x0f, 0x02, 0x13, "System boot initiated"},
+ {0x0f, 0x02, 0x14, "Motherboard initialization"},
+ {0x0f, 0x02, 0x15, "reserved"},
+ {0x0f, 0x02, 0x16, "Floppy initialization"},
+ {0x0f, 0x02, 0x17, "Keyboard test"},
+ {0x0f, 0x02, 0x18, "Pointing device test"},
+ {0x0f, 0x02, 0x19, "Primary CPU initialization"},
+ {0x0f, 0x02, 0xff, "Unknown Progress"},
+ /* Event Logging Disabled */
+ {0x10, 0x00, 0xff, "Correctable memory error logging disabled"},
+ {0x10, 0x01, 0xff, "Event logging disabled"},
+ {0x10, 0x02, 0xff, "Log area reset/cleared"},
+ {0x10, 0x03, 0xff, "All event logging disabled"},
+ {0x10, 0x04, 0xff, "Log full"},
+ {0x10, 0x05, 0xff, "Log almost full"},
+ /* Watchdog 1 */
+ {0x11, 0x00, 0xff, "BIOS Reset"},
+ {0x11, 0x01, 0xff, "OS Reset"},
+ {0x11, 0x02, 0xff, "OS Shut Down"},
+ {0x11, 0x03, 0xff, "OS Power Down"},
+ {0x11, 0x04, 0xff, "OS Power Cycle"},
+ {0x11, 0x05, 0xff, "OS NMI/Diag Interrupt"},
+ {0x11, 0x06, 0xff, "OS Expired"},
+ {0x11, 0x07, 0xff, "OS pre-timeout Interrupt"},
+ /* System Event */
+ {0x12, 0x00, 0xff, "System Reconfigured"},
+ {0x12, 0x01, 0xff, "OEM System boot event"},
+ {0x12, 0x02, 0xff, "Undetermined system hardware failure"},
+ {0x12, 0x03, 0xff, "Entry added to auxiliary log"},
+ {0x12, 0x04, 0xff, "PEF Action"},
+ {0x12, 0x05, 0xff, "Timestamp Clock Sync"},
+ /* Critical Interrupt */
+ {0x13, 0x00, 0xff, "NMI/Diag Interrupt"},
+ {0x13, 0x01, 0xff, "Bus Timeout"},
+ {0x13, 0x02, 0xff, "I/O Channel check NMI"},
+ {0x13, 0x03, 0xff, "Software NMI"},
+ {0x13, 0x04, 0xff, "PCI PERR", Expander_Err_evt2, Expander_Err_evt3},
+ {0x13, 0x05, 0xff, "PCI SERR", Expander_Err_evt2, Expander_Err_evt3},
+ {0x13, 0x06, 0xff, "EISA failsafe timeout"},
+ {0x13, 0x07, 0xff, "Bus Correctable error", Expander_Err_evt2, Expander_Err_evt3},
+ {0x13, 0x08, 0xff, "Bus Uncorrectable error", Expander_Err_evt2, Expander_Err_evt3},
+ {0x13, 0x09, 0xff, "Fatal NMI"},
+ {0x13, 0x0a, 0xff, "Bus Fatal Error", Expander_Err_evt2, Expander_Err_evt3},
+ {0x13, 0x0b, 0xff, "Bus Degraded", Expander_Err_evt2, Expander_Err_evt3},
+ /* Button */
+ {0x14, 0x00, 0xff, "Power Button pressed"},
+ {0x14, 0x01, 0xff, "Sleep Button pressed"},
+ {0x14, 0x02, 0xff, "Reset Button pressed"},
+ {0x14, 0x03, 0xff, "FRU Latch"},
+ {0x14, 0x04, 0xff, "FRU Service"},
+ /* Chip Set */
+ {0x19, 0x00, 0xff, "Soft Power Control Failure"},
+ {0x19, 0x01, 0xff, "Thermal Trip"},
+ /* Cable/Interconnect */
+ {0x1b, 0x00, 0xff, "Connected"},
+ {0x1b, 0x01, 0xff, "Config Error"},
+ /* System Boot Initiated */
+ {0x1d, 0x00, 0xff, "Initiated by power up", BMC_BOOT_evt2, BMC_BOOT_evt3},
+ {0x1d, 0x01, 0xff, "Initiated by hard reset"},
+ {0x1d, 0x02, 0xff, "Initiated by warm reset"},
+ {0x1d, 0x03, 0xff, "User requested PXE boot"},
+ {0x1d, 0x04, 0xff, "Automatic boot to diagnostic"},
+ {0x1d, 0x05, 0xff, "OS initiated hard reset"},
+ {0x1d, 0x06, 0xff, "OS initiated warm reset"},
+ {0x1d, 0x07, 0xff, "System Restart"},
+ /* Boot Error */
+ {0x1e, 0x00, 0xff, "No bootable media"},
+ {0x1e, 0x01, 0xff, "Non-bootable disk in drive"},
+ {0x1e, 0x02, 0xff, "PXE server not found"},
+ {0x1e, 0x03, 0xff, "Invalid boot sector"},
+ {0x1e, 0x04, 0xff, "Timeout waiting for selection"},
+ /* OS Boot */
+ {0x1f, 0x00, 0xff, "A: boot completed"},
+ {0x1f, 0x01, 0xff, "C: boot completed"},
+ {0x1f, 0x02, 0xff, "PXE boot completed"},
+ {0x1f, 0x03, 0xff, "Diagnostic boot completed"},
+ {0x1f, 0x04, 0xff, "CD-ROM boot completed"},
+ {0x1f, 0x05, 0xff, "ROM boot completed"},
+ {0x1f, 0x06, 0xff, "boot completed - device not specified"},
+ {0x1f, 0x07, 0xff, "Installation started"},
+ {0x1f, 0x08, 0xff, "Installation completed"},
+ {0x1f, 0x09, 0xff, "Installation aborted"},
+ {0x1f, 0x0a, 0xff, "Installation failed"},
+ /* OS Stop/Shutdown */
+ {0x20, 0x00, 0xff, "Error during system startup"},
+ {0x20, 0x01, 0xff, "Run-time critical stop"},
+ {0x20, 0x02, 0xff, "OS graceful stop"},
+ {0x20, 0x03, 0xff, "OS graceful shutdown"},
+ {0x20, 0x04, 0xff, "PEF initiated soft shutdown"},
+ {0x20, 0x05, 0xff, "Agent not responding"},
+ /* Slot/Connector */
+ {0x21, 0x00, 0xff, "Fault Status"},
+ {0x21, 0x01, 0xff, "Identify Status"},
+ {0x21, 0x02, 0xff, "Device Installed"},
+ {0x21, 0x03, 0xff, "Ready for Device Installation"},
+ {0x21, 0x04, 0xff, "Ready for Device Removal"},
+ {0x21, 0x05, 0xff, "Slot Power is Off"},
+ {0x21, 0x06, 0xff, "Device Removal Request"},
+ {0x21, 0x07, 0xff, "Interlock"},
+ {0x21, 0x08, 0xff, "Slot is Disabled"},
+ {0x21, 0x09, 0xff, "Spare Device"},
+ /* System ACPI Power State */
+ {0x22, 0x00, 0xff, "S0/G0: working"},
+ {0x22, 0x01, 0xff, "S1: sleeping with system hw & processor context maintained"},
+ {0x22, 0x02, 0xff, "S2: sleeping, processor context lost"},
+ {0x22, 0x03, 0xff, "S3: sleeping, processor & hw context lost, memory retained"},
+ {0x22, 0x04, 0xff, "S4: non-volatile sleep/suspend-to-disk"},
+ {0x22, 0x05, 0xff, "S5/G2: soft-off"},
+ {0x22, 0x06, 0xff, "S4/S5: soft-off"},
+ {0x22, 0x07, 0xff, "G3: mechanical off"},
+ {0x22, 0x08, 0xff, "Sleeping in S1/S2/S3 state"},
+ {0x22, 0x09, 0xff, "G1: sleeping"},
+ {0x22, 0x0a, 0xff, "S5: entered by override"},
+ {0x22, 0x0b, 0xff, "Legacy ON state"},
+ {0x22, 0x0c, 0xff, "Legacy OFF state"},
+ {0x22, 0x0e, 0xff, "Unknown"},
+ /* Watchdog 2 */
+ {0x23, 0x00, 0xff, "Timer expired"},
+ {0x23, 0x01, 0xff, "Hard reset"},
+ {0x23, 0x02, 0xff, "Power down"},
+ {0x23, 0x03, 0xff, "Power cycle"},
+ {0x23, 0x04, 0xff, "reserved"},
+ {0x23, 0x05, 0xff, "reserved"},
+ {0x23, 0x06, 0xff, "reserved"},
+ {0x23, 0x07, 0xff, "reserved"},
+ {0x23, 0x08, 0xff, "Timer interrupt"},
+ /* Platform Alert */
+ {0x24, 0x00, 0xff, "Platform generated page"},
+ {0x24, 0x01, 0xff, "Platform generated LAN alert"},
+ {0x24, 0x02, 0xff, "Platform Event Trap generated"},
+ {0x24, 0x03, 0xff, "Platform generated SNMP trap, OEM format"},
+ /* Entity Presence */
+ {0x25, 0x00, 0xff, "Present"},
+ {0x25, 0x01, 0xff, "Absent"},
+ {0x25, 0x02, 0xff, "Disabled"},
+ /* LAN */
+ {0x27, 0x00, 0xff, "Heartbeat Lost"},
+ {0x27, 0x01, 0xff, "Heartbeat"},
+ /* Management Subsystem Health */
+ {0x28, 0x00, 0xff, "Sensor access degraded or unavailable"},
+ {0x28, 0x01, 0xff, "Controller access degraded or unavailable"},
+ {0x28, 0x02, 0xff, "Management controller off-line"},
+ {0x28, 0x03, 0xff, "Management controller unavailable"},
+ {0x28, 0x04, 0xff, "Sensor failure"},
+ {0x28, 0x05, 0xff, "FRU failure"},
+ /* Battery */
+ {0x29, 0x00, 0xff, "Low"},
+ {0x29, 0x01, 0xff, "Failed"},
+ {0x29, 0x02, 0xff, "Presence Detected"},
+ /* Version Change */
+ {0x2b, 0x00, 0xff, "Hardware change detected"},
+ {0x2b, 0x01, 0x00, "Firmware or software change detected"},
+ {0x2b, 0x01, 0x01, "Firmware or software change detected, Mngmt Ctrl Dev Id"},
+ {0x2b, 0x01, 0x02, "Firmware or software change detected, Mngmt Ctrl Firm Rev"},
+ {0x2b, 0x01, 0x03, "Firmware or software change detected, Mngmt Ctrl Dev Rev"},
+ {0x2b, 0x01, 0x04, "Firmware or software change detected, Mngmt Ctrl Manuf Id"},
+ {0x2b, 0x01, 0x05, "Firmware or software change detected, Mngmt Ctrl IPMI Vers"},
+ {0x2b, 0x01, 0x06, "Firmware or software change detected, Mngmt Ctrl Aux Firm Id"},
+ {0x2b, 0x01, 0x07, "Firmware or software change detected, Mngmt Ctrl Firm Boot Block"},
+ {0x2b, 0x01, 0x08, "Firmware or software change detected, Mngmt Ctrl Other"},
+ {0x2b, 0x01, 0x09, "Firmware or software change detected, BIOS/EFI change"},
+ {0x2b, 0x01, 0x0A, "Firmware or software change detected, SMBIOS change"},
+ {0x2b, 0x01, 0x0B, "Firmware or software change detected, O/S change"},
+ {0x2b, 0x01, 0x0C, "Firmware or software change detected, O/S loader change"},
+ {0x2b, 0x01, 0x0D, "Firmware or software change detected, Service Diag change"},
+ {0x2b, 0x01, 0x0E, "Firmware or software change detected, Mngmt SW agent change"},
+ {0x2b, 0x01, 0x0F, "Firmware or software change detected, Mngmt SW App change"},
+ {0x2b, 0x01, 0x10, "Firmware or software change detected, Mngmt SW Middle"},
+ {0x2b, 0x01, 0x11, "Firmware or software change detected, Prog HW Change (FPGA)"},
+ {0x2b, 0x01, 0x12, "Firmware or software change detected, board/FRU module change"},
+ {0x2b, 0x01, 0x13, "Firmware or software change detected, board/FRU component change"},
+ {0x2b, 0x01, 0x14, "Firmware or software change detected, board/FRU replace equ ver"},
+ {0x2b, 0x01, 0x15, "Firmware or software change detected, board/FRU replace new ver"},
+ {0x2b, 0x01, 0x16, "Firmware or software change detected, board/FRU replace old ver"},
+ {0x2b, 0x01, 0x17, "Firmware or software change detected, board/FRU HW conf change"},
+ {0x2b, 0x02, 0xff, "Hardware incompatibility detected"},
+ {0x2b, 0x03, 0xff, "Firmware or software incompatibility detected"},
+ {0x2b, 0x04, 0xff, "Invalid or unsupported hardware version"},
+ {0x2b, 0x05, 0xff, "Invalid or unsupported firmware or software version"},
+ {0x2b, 0x06, 0xff, "Hardware change success"},
+ {0x2b, 0x07, 0x00, "Firmware or software change success"},
+ {0x2b, 0x07, 0x01, "Firmware or software change success, Mngmt Ctrl Dev Id"},
+ {0x2b, 0x07, 0x02, "Firmware or software change success, Mngmt Ctrl Firm Rev", FW_Update_evt2, FW_Update_evt3},
+ {0x2b, 0x07, 0x03, "Firmware or software change success, Mngmt Ctrl Dev Rev"},
+ {0x2b, 0x07, 0x04, "Firmware or software change success, Mngmt Ctrl Manuf Id"},
+ {0x2b, 0x07, 0x05, "Firmware or software change success, Mngmt Ctrl IPMI Vers"},
+ {0x2b, 0x07, 0x06, "Firmware or software change success, Mngmt Ctrl Aux Firm Id"},
+ {0x2b, 0x07, 0x07, "Firmware or software change success, Mngmt Ctrl Firm Boot Block"},
+ {0x2b, 0x07, 0x08, "Firmware or software change success, Mngmt Ctrl Other"},
+ {0x2b, 0x07, 0x09, "Firmware or software change success, BIOS/EFI change"},
+ {0x2b, 0x07, 0x0A, "Firmware or software change success, SMBIOS change"},
+ {0x2b, 0x07, 0x0B, "Firmware or software change success, O/S change"},
+ {0x2b, 0x07, 0x0C, "Firmware or software change success, O/S loader change"},
+ {0x2b, 0x07, 0x0D, "Firmware or software change success, Service Diag change"},
+ {0x2b, 0x07, 0x0E, "Firmware or software change success, Mngmt SW agent change"},
+ {0x2b, 0x07, 0x0F, "Firmware or software change success, Mngmt SW App change"},
+ {0x2b, 0x07, 0x10, "Firmware or software change success, Mngmt SW Middle"},
+ {0x2b, 0x07, 0x11, "Firmware or software change success, Prog HW Change (FPGA)"},
+ {0x2b, 0x07, 0x12, "Firmware or software change success, board/FRU module change"},
+ {0x2b, 0x07, 0x13, "Firmware or software change success, board/FRU component change"},
+ {0x2b, 0x07, 0x14, "Firmware or software change success, board/FRU replace equ ver"},
+ {0x2b, 0x07, 0x15, "Firmware or software change success, board/FRU replace new ver"},
+ {0x2b, 0x07, 0x16, "Firmware or software change success, board/FRU replace old ver"},
+ {0x2b, 0x07, 0x17, "Firmware or software change success, board/FRU HW conf change"},
+ /* FRU State */
+ {0x2c, 0x00, 0xff, "Not Installed"},
+ {0x2c, 0x01, 0xff, "Inactive"},
+ {0x2c, 0x02, 0xff, "Activation Requested"},
+ {0x2c, 0x03, 0xff, "Activation in Progress"},
+ {0x2c, 0x04, 0xff, "Active"},
+ {0x2c, 0x05, 0xff, "Deactivation Requested"},
+ {0x2c, 0x06, 0xff, "Deactivation in Progress"},
+ {0x2c, 0x07, 0xff, "Communication lost"},
+ /* PICMG FRU Hot Swap */
+ {0xF0, 0x00, 0xFF, "Transition to M0"},
+ {0xF0, 0x01, 0xFF, "Transition to M1"},
+ {0xF0, 0x02, 0xFF, "Transition to M2"},
+ {0xF0, 0x03, 0xFF, "Transition to M3"},
+ {0xF0, 0x04, 0xFF, "Transition to M4"},
+ {0xF0, 0x05, 0xFF, "Transition to M5"},
+ {0xF0, 0x06, 0xFF, "Transition to M6"},
+ {0xF0, 0x07, 0xFF, "Transition to M7"},
+ /* PICMG IPMB Physical Link */
+ {0xF1, 0x00, 0xff, "IPMB-A disabled, IPMB-B disabled"},
+ {0xF1, 0x01, 0xff, "IPMB-A enabled, IPMB-B disabled"},
+ {0xF1, 0x02, 0xff, "IPMB-A disabled, IPMB-B enabled"},
+ {0xF1, 0x03, 0xff, "IPMB-A enabled, IPMB-B enabled"},
+ /* PICMG Module Hot Swap */
+ {0xF2, 0x00, 0xff, "Module Handle Closed"},
+ {0xF2, 0x01, 0xff, "Module Handle Opened"},
+ {0xF2, 0x02, 0xff, "Quiesced"},
+ {0x00, 0x00, 0xff, NULL},
+};
+
+static struct ipmi_oem_event_sensor_types sensor_oem_event_types[] = {
+ {0xba, 0xcb, 0x01, 0xff, "Kernel Panic"},
+ {0xba, 0xcb, 0x02, 0x00, "Power Button pressed accidentally under S0"},
+ {0xba, 0xcc, 0x01, 0x00, "Switch to golden flash"},
+ {0xba, 0xcc, 0x01, 0x01,
+ "Switch to golden flash forced by security module due to primary flash verification failure"},
+ {0xba, 0xcc, 0x02, 0x01, "PCIe topology does not match any suite"},
+ {0xba, 0xcc, 0x02, 0x02, "EEPROM CRC result is incorrect"},
+ {0xba, 0xcc, 0x02, 0x03, "Current PCIe devices do not match PCIe topology"},
+ {0xba, 0xcc, 0x03, 0x00, "Abnormal leakage line detected"},
+ {0xba, 0xcc, 0x03, 0x01, "Abnormal leakage line detected at point A"},
+ {0xba, 0xcc, 0x03, 0x02, "Abnormal leakage line detected at point B"},
+ {0xba, 0xcc, 0x03, 0x03, "Abnormal leakage line detected at point C"},
+ {0xba, 0xcc, 0x03, 0x04, "Abnormal leakage line detected at point D"},
+ {0xba, 0xcc, 0x03, 0x05, "Abnormal leakage line detected at point E"},
+ {0xba, 0xcc, 0x04, 0x00, "Leakage line is absent"},
+ {0xba, 0xcc, 0x05, 0x01, "Security module verify BMC primary flash failed"},
+ {0xba, 0xcc, 0x05, 0x02, "Security module verify BMC golden flash failed"},
+ {0xba, 0xcc, 0x05, 0x03, "Security module verify BMC primary and golden flash failed"},
+ {0xba, 0xcc, 0x05, 0x04, "Security module verify BIOS flash failed"},
+ {0xba, 0xcc, 0x05, 0x05, "Security module verify BMC primary flash and BIOS flash failed"},
+ {0xba, 0xcc, 0x05, 0x06, "Security module verify BMC golden flash and BIOS flash failed"},
+ {0xba, 0xcc, 0x05, 0x07, "Security module verify BMC primary and golden flash and BIOS flash failed"},
+ {0xba, 0xcc, 0x05, 0x08, "Security module firmware update failed"},
+ {0xba, 0xcc, 0x06, 0x01, "BMC Recovery occurred"},
+ {0xba, 0xcc, 0x06, 0x02, "BIOS Recovery occurred"},
+ {0xba, 0xcc, 0x06, 0x03, "PFR Recovery occurred"},
+ {0xba, 0xcc, 0x07, 0x01, "Insufficient Bus Number resources"},
+ {0xba, 0xcc, 0x07, 0x02, "Insufficient IO Size resources"},
+ {0xba, 0xcc, 0x07, 0x03, "Insufficient MEM32 Size resources"},
+ {0xba, 0xcc, 0x07, 0x04, "Insufficient MEM32 PREF Size resources"},
+ {0xba, 0xcc, 0x07, 0x05, "Insufficient MEM64 PREF Size resources"},
+ {0xba, 0xcc, 0x08, 0x00,
+ "Failed to synchronize user information between HOST and BOX BMC"},
+ {0xba, 0xcc, 0x09, 0x01, "Failed to power on HOST through BMC"},
+ {0xba, 0xcc, 0x09, 0x02, "Failed to power off HOST through BMC"},
+ {0x00, 0x00, 0x00, 0x00, NULL},
+};
+
+static struct ipmi_oem_specific_sensor_types sensor_oem_ppr_types[] = {
+ {1, 0x01, "hPPR repair "},
+ {1, 0x02, "sPPR repair "},
+ {1, 0x03, "runtime hPPR repair "},
+ {1, 0x04, "runtime sPPR repair "},
+ {5, 0x01, "success"},
+ {5, 0x02, "fail"},
+ {0, 0x00, NULL},
+};
+
+static struct ipmi_oem_specific_sensor_types sensor_oem_bacd_types[] = {
+ {3, 0, "Fatal(CATERR/MSMI)"},
+ {3, 1, "UCE-R(CATERR/MSMI_16BCLK)"},
+ {3, 2, "CE(reserve for ERR 0)"},
+ {3, 3, "FW(Data from FW/BIOS)"},
+ {3, 4, "Reserved"},
+ {3, 5, "Reserved"},
+ {3, 6, "Reserved"},
+ {3, 7, "Reserved"},
+ {2, 0x00, "Dump succeeded"},
+ {2, 0x01, "Dump failed"},
+ {0, 0x00, NULL},
+};
+
+#endif /* IPMI_SEL_DESC_H */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 258aa1c..edfd80f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -32,7 +32,7 @@ AUTOMAKE_OPTIONS = subdir-objects
AM_CPPFLAGS = -I$(top_srcdir)/include
MAINTAINERCLEANFILES = Makefile.in
-noinst_LTLIBRARIES = libipmitool.la
+lib_LTLIBRARIES = libipmitool.la
libipmitool_la_SOURCES = helper.c ipmi_sdr.c ipmi_sel.c ipmi_sol.c ipmi_pef.c \
ipmi_lanp.c ipmi_fru.c ipmi_chassis.c ipmi_mc.c log.c \
dimm_spd.c ipmi_sensor.c ipmi_channel.c ipmi_event.c \
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 14acbcf..0829e84 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -35,7 +35,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
SUBDIRS = @INTF_LAN@ @INTF_LANPLUS@ @INTF_OPEN@ @INTF_LIPMI@ @INTF_IMB@ @INTF_BMC@ @INTF_FREE@ @INTF_SERIAL@ @INTF_DUMMY@ @INTF_USB@ @INTF_DBUS@
DIST_SUBDIRS = lan lanplus open lipmi imb bmc free serial dummy usb dbus
-noinst_LTLIBRARIES = libintf.la
+lib_LTLIBRARIES = libintf.la
libintf_la_SOURCES = ipmi_intf.c
libintf_la_CFLAGS = -DDEFAULT_INTF='"@DEFAULT_INTF@"'
libintf_la_LDFLAGS = -export-dynamic
--
2.25.1
+6
View File
@@ -0,0 +1,6 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append = " \
file://0001-change-ipmitool-to-shared-objects.patch \
"
@@ -0,0 +1,48 @@
From dcfe25ff7fe8874933107ff5dcfaa447722de5d1 Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Thu, 26 Dec 2024 10:38:18 +0800
Subject: [PATCH] Add multiplierM offsetB bExp rExp items in
sensor_data_record.json
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
scripts/sensor_data_record_gen.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/scripts/sensor_data_record_gen.py b/scripts/sensor_data_record_gen.py
index 2ef58b7..fdcf691 100755
--- a/scripts/sensor_data_record_gen.py
+++ b/scripts/sensor_data_record_gen.py
@@ -12,10 +12,18 @@ def getSensorParams(sensor, sensor_params):
sensorName = sensor.get("sensorName", path[path.rfind("/") + 1 :])
sensorReadingType = sensor.get("sensorReadingType", 0)
sensorType = sensor.get("sensorType", 0)
+ multiplierM = sensor.get("multiplierM", 0)
+ offsetB = sensor.get("offsetB", 0)
+ bExp = sensor.get("bExp", 0)
+ rExp = sensor.get("rExp", 0)
sensor_params[path] = {
"sensorName": sensorName,
"sensorReadingType": sensorReadingType,
"sensorType": sensorType,
+ "multiplierM": multiplierM,
+ "offsetB": offsetB,
+ "bExp": bExp,
+ "rExp": rExp,
}
overridePaths = sensor.get("overridePaths", [])
@@ -25,6 +33,10 @@ def getSensorParams(sensor, sensor_params):
"sensorName": sensorName,
"sensorReadingType": sensorReadingType,
"sensorType": sensorType,
+ "multiplierM": multiplierM,
+ "offsetB": offsetB,
+ "bExp": bExp,
+ "rExp": rExp,
}
return sensor_params
--
2.34.1
@@ -0,0 +1,263 @@
From 57dc7fbdd1dceb8c82512dae754bf4a8370a4010 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Fri, 7 Feb 2025 14:42:30 +0800
Subject: [PATCH] Add power cycle trigger async firmware update
---
chassishandler.cpp | 216 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 216 insertions(+)
diff --git a/chassishandler.cpp b/chassishandler.cpp
index 89d3e00..8e68ac5 100644
--- a/chassishandler.cpp
+++ b/chassishandler.cpp
@@ -8,6 +8,7 @@
#include <mapper.h>
#include <netinet/in.h>
+#include <boost/asio.hpp>
#include <ipmid/api.hpp>
#include <ipmid/types.hpp>
#include <ipmid/utils.hpp>
@@ -813,6 +814,196 @@ ipmi::RspType<> ipmiSetChassisCap(bool intrusion, bool fpLockout,
return ipmi::responseSuccess();
}
+//------------------------------------------------
+// Is power on (check power state before async update)
+//------------------------------------------------
+bool isPowerOn()
+{
+ std::variant<std::string> msg;
+ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+ try
+ {
+ auto method = bus.new_method_call("xyz.openbmc_project.State.Chassis",
+ "/xyz/openbmc_project/state/chassis0",
+ "org.freedesktop.DBus.Properties",
+ "Get");
+ method.append("xyz.openbmc_project.State.Chassis");
+ method.append("CurrentPowerState");
+ auto reply = bus.call(method);
+ reply.read(msg);
+ return std::get<std::string>(msg).find("Off") != std::string::npos
+ ? false
+ : true;
+ }
+ catch (const std::exception& /*ex*/)
+ {
+ log<level::ERR>("Can not get power status");
+ return true;
+ }
+}
+
+//------------------------------------------------
+// Async update start (return status or no value))
+//------------------------------------------------
+std::string asyncUpdateStart()
+{
+ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+ std::string asyncStatus{};
+ auto method = bus.new_method_call(
+ "xyz.openbmc_project.Software.AsyncUpdate",
+ "/xyz/openbmc_project/Software/AsyncUpdate",
+ "xyz.openbmc_project.Software.AsyncUpdate", "Start");
+ try
+ {
+ auto reply = bus.call(method);
+ reply.read(asyncStatus);
+ return asyncStatus;
+ }
+ catch (const sdbusplus::exception::SdBusError& /*ex*/)
+ {
+ log<level::ERR>("Error in starting async update");
+ return "";
+ }
+}
+
+//------------------------------------------------
+// Get async update status (return status or no value)
+//------------------------------------------------
+std::string asyncUpdateStatus()
+{
+ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+ try
+ {
+ auto status = ipmi::getDbusProperty(
+ bus, "xyz.openbmc_project.Software.AsyncUpdate",
+ "/xyz/openbmc_project/Software/AsyncUpdate",
+ "xyz.openbmc_project.Software.AsyncUpdate", "AsyncUpdateStatus");
+ return std::get<std::string>(status);
+ }
+ catch (const sdbusplus::exception::SdBusError& /*ex*/)
+ {
+ log<level::ERR>("Can not get async update status");
+ return "";
+ }
+}
+
+int initiateHostStateTransition(ipmi::Context::ptr& ctx,
+ State::Host::Transition transition);
+int initiateChassisStateTransition(ipmi::Context::ptr& ctx,
+ State::Chassis::Transition transition);
+//---------------------------------------------------------------------------
+// if power cycle wait for power on
+//---------------------------------------------------------------------------
+void waitForUpdateDone()
+{
+ static boost::asio::steady_timer timer(*getIoContext());
+ timer.expires_after(boost::asio::chrono::seconds(15));
+ timer.async_wait([&](const boost::system::error_code& ec) {
+ if (ec)
+ {
+ return;
+ }
+ if (asyncUpdateStatus() != "Idle")
+ {
+ waitForUpdateDone();
+ return;
+ }
+ sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+ try
+ {
+ auto method =
+ bus.new_method_call("xyz.openbmc_project.State.Host",
+ "/xyz/openbmc_project/state/host0",
+ "org.freedesktop.DBus.Properties", "Set");
+
+ method.append("xyz.openbmc_project.State.Host");
+ method.append("RequestedHostTransition");
+ method.append(std::variant<std::string>{
+ "xyz.openbmc_project.State.Host.Transition.On"});
+ bus.call_noreply(method);
+ }
+ catch (const sdbusplus::exception::SdBusError& /*ex*/)
+ {
+ log<level::ERR>("Can not power On after async update");
+ }
+ });
+}
+//---------------------------------------------------------------------------
+// wait for power off to start update
+//---------------------------------------------------------------------------
+void waitForStartUpdate(bool doPowerOn)
+{
+ static boost::asio::steady_timer timer(*getIoContext());
+ timer.expires_after(boost::asio::chrono::seconds(15));
+ timer.async_wait(
+ [doPowerOn](const boost::system::error_code& ec) {
+ if (ec)
+ {
+ return;
+ }
+ if (isPowerOn()) // power status is not "off"
+ {
+ waitForStartUpdate(doPowerOn);
+ return;
+ }
+ try
+ {
+ asyncUpdateStart();
+ if (doPowerOn)
+ {
+ waitForUpdateDone();
+ }
+ }
+ catch (const sdbusplus::exception::SdBusError& /*ex*/)
+ {
+ log<level::ERR>("Can not start update");
+ }
+ });
+}
+
+enum class PowerControlAsyncStatus
+{
+ active,
+ running,
+ idle
+};
+
+//---------------------------------------------------------------------------
+// hook host power control to trigger async update
+// return true if async-update is not in progress
+//---------------------------------------------------------------------------
+PowerControlAsyncStatus
+ processPowerControlHost(ipmi::Context::ptr& ctx,
+ State::Host::Transition transition)
+{
+ std::string asyncStatus = asyncUpdateStatus();
+ auto doPowerOn = isPowerOn();
+ switch (transition)
+ {
+ case State::Host::Transition::Reboot:
+ if (asyncStatus == "Waiting")
+ {
+ initiateChassisStateTransition(ctx,
+ State::Chassis::Transition::Off);
+ waitForStartUpdate(doPowerOn);
+ return PowerControlAsyncStatus::active;
+ }
+ else if (asyncStatus == "Running")
+ {
+ return PowerControlAsyncStatus::running;
+ }
+ break;
+ case State::Host::Transition::On:
+ if (asyncStatus == "Running")
+ {
+ return PowerControlAsyncStatus::running;
+ }
+ break;
+ default:
+ break;
+ }
+ return PowerControlAsyncStatus::idle;
+}
//------------------------------------------
// Calls into Host State Manager Dbus object
//------------------------------------------
@@ -1363,9 +1554,18 @@ ipmi::RspType<> ipmiChassisControl(ipmi::Context::ptr& ctx,
uint8_t chassisControl)
{
int rc = 0;
+ PowerControlAsyncStatus asyncUpdateStatus = PowerControlAsyncStatus::idle;
switch (chassisControl)
{
case CMD_POWER_ON:
+ asyncUpdateStatus =
+ processPowerControlHost(ctx, State::Host::Transition::On);
+ if (asyncUpdateStatus != PowerControlAsyncStatus::idle)
+ {
+ log<level::ERR>(
+ "Power-on opertion is not allowed during the upgrade process");
+ return ipmi::responseCommandNotAvailable();
+ }
rc = initiateHostStateTransition(ctx, State::Host::Transition::On);
break;
case CMD_POWER_OFF:
@@ -1377,6 +1577,22 @@ ipmi::RspType<> ipmiChassisControl(ipmi::Context::ptr& ctx,
ctx, State::Host::Transition::ForceWarmReboot);
break;
case CMD_POWER_CYCLE:
+ asyncUpdateStatus =
+ processPowerControlHost(ctx, State::Host::Transition::Reboot);
+ if (asyncUpdateStatus == PowerControlAsyncStatus::active)
+ {
+ log<level::INFO>(
+ "Power-cycle operation will activate the async-update, let the async-update flow to do the power-cycle");
+ rc = ipmi::ccSuccess;
+ break;
+ }
+ else if (asyncUpdateStatus == PowerControlAsyncStatus::running)
+ {
+ log<level::INFO>(
+ "Power-cycle operation is not allowed during the upgrade");
+ rc = ipmi::ccCommandNotAvailable;
+ break;
+ }
rc = initiateHostStateTransition(ctx,
State::Host::Transition::Reboot);
break;
--
2.25.1
@@ -0,0 +1,31 @@
From a16e5220657aeca72ad01c2408fefed38fa3c256 Mon Sep 17 00:00:00 2001
From: wangjue <jue.wang2@luxshare-ict.com>
Date: Fri, 13 Dec 2024 11:07:55 +0800
Subject: [PATCH] Fix incorrect thresholdLevelsStates response for Get Sensor
Reading command
Signed-off-by: wangjue <jue.wang2@luxshare-ict.com>
---
sensordatahandler.hpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/sensordatahandler.hpp b/sensordatahandler.hpp
index 6c3a8e5..2867cd5 100644
--- a/sensordatahandler.hpp
+++ b/sensordatahandler.hpp
@@ -327,9 +327,9 @@ GetSensorResponse readingData(const Info& sensorInfo)
warningAlarmLow = false;
}
response.thresholdLevelsStates =
- (static_cast<uint8_t>(critAlarmHigh) << 3) |
- (static_cast<uint8_t>(critAlarmLow) << 2) |
- (static_cast<uint8_t>(warningAlarmHigh) << 1) |
+ (static_cast<uint8_t>(critAlarmHigh) << 4) |
+ (static_cast<uint8_t>(warningAlarmHigh) << 3) |
+ (static_cast<uint8_t>(critAlarmLow) << 1) |
(static_cast<uint8_t>(warningAlarmLow));
return response;
--
2.34.1
@@ -0,0 +1,160 @@
From 3079d7621187cb966f19726f2f31fb03f0080eed Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Wed, 11 Dec 2024 17:08:44 +0800
Subject: [PATCH] add sensor config file
---
scripts/meson.build | 19 +++++-
scripts/sensor_data_record_gen.py | 104 ++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+), 3 deletions(-)
create mode 100755 scripts/sensor_data_record_gen.py
diff --git a/scripts/meson.build b/scripts/meson.build
index b739e6f..ae5358c 100644
--- a/scripts/meson.build
+++ b/scripts/meson.build
@@ -3,11 +3,11 @@ python_exe = find_program('python3', 'python')
sensor_gen = custom_target('sensor-gen',
output: 'sensor-gen.cpp',
- input: [ 'sensor_gen.py', get_option('sensor-yaml-gen')],
+ input: files(get_option('sensor-yaml-gen')),
command: [
python_exe,
- '@INPUT0@',
- '-i', '@INPUT1@',
+ files('sensor_gen.py'),
+ '-i', '@INPUT@',
'-o', meson.current_build_dir(),
'generate-cpp',
],
@@ -39,3 +39,16 @@ fru_gen = custom_target('fru-gen',
],
)
generated_src += fru_gen
+
+sensor_data_gen = custom_target('sensor-json-gen',
+ output: 'sensor-data-record.json',
+ input: files(get_option('sensor-yaml-gen')),
+ command: [
+ files('sensor_data_record_gen.py'),
+ '-i', '@INPUT@',
+ '-o', meson.current_build_dir(),
+ ],
+ install: true,
+ install_dir: get_option('datadir') / 'ipmi-providers',
+)
+generated_src += sensor_data_gen
diff --git a/scripts/sensor_data_record_gen.py b/scripts/sensor_data_record_gen.py
new file mode 100755
index 0000000..2ef58b7
--- /dev/null
+++ b/scripts/sensor_data_record_gen.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python3
+
+import argparse
+import json
+import os
+
+import yaml
+
+
+def getSensorParams(sensor, sensor_params):
+ path = sensor["path"]
+ sensorName = sensor.get("sensorName", path[path.rfind("/") + 1 :])
+ sensorReadingType = sensor.get("sensorReadingType", 0)
+ sensorType = sensor.get("sensorType", 0)
+ sensor_params[path] = {
+ "sensorName": sensorName,
+ "sensorReadingType": sensorReadingType,
+ "sensorType": sensorType,
+ }
+
+ overridePaths = sensor.get("overridePaths", [])
+ for item in overridePaths:
+ sensorName = item[item.rfind("/") + 1 :]
+ sensor_params[item] = {
+ "sensorName": sensorName,
+ "sensorReadingType": sensorReadingType,
+ "sensorType": sensorType,
+ }
+ return sensor_params
+
+
+def main():
+ app_description = "Convert sensor yaml to json."
+
+ parser = argparse.ArgumentParser(
+ description=app_description,
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ )
+ parser.add_argument(
+ "-i",
+ "--sensor_yaml",
+ dest="sensor_yaml",
+ nargs="*",
+ type=str,
+ default=[],
+ help="input sensor yaml file list to parse",
+ )
+ parser.add_argument(
+ "-o",
+ "--output-dir",
+ dest="outputdir",
+ help="The directory of json file",
+ )
+ parser.add_argument(
+ "-f",
+ "--override-flag",
+ dest="override",
+ default="",
+ help="override flag",
+ )
+ args = parser.parse_args()
+
+ if not args.override and len(args.sensor_yaml) > 1:
+ raise RuntimeError(
+ "Not support multi machine, but there are multi sensor yamls"
+ )
+ total_sensor_params = {}
+
+ for yaml_file in args.sensor_yaml:
+ with open(yaml_file, "r") as y:
+ sensors = yaml.safe_load(y)
+ sensors = [i for i in sensors.values()]
+ sensor_params = {}
+ for s in sensors:
+ sensor_params = getSensorParams(s, sensor_params)
+ for sensor_param in sensor_params:
+ # if the sensor is already in the total_sensor_params, check the value is must same
+ if sensor_param in total_sensor_params:
+ if (
+ total_sensor_params[sensor_param]
+ != sensor_params[sensor_param]
+ ):
+ raise RuntimeError(
+ "The sensor is already in the total_sensor_params, but the value is different"
+ )
+ else:
+ total_sensor_params[sensor_param] = sensor_params[
+ sensor_param
+ ]
+ output_json = os.path.join(args.outputdir, "sensor-data-record.json")
+ with open(output_json, "w") as j:
+ j.write(
+ json.dumps(
+ total_sensor_params,
+ indent=4,
+ sort_keys=True,
+ separators=(",", ": "),
+ )
+ )
+ j.write("\n")
+
+
+if __name__ == "__main__":
+ main()
--
2.25.1
@@ -0,0 +1,93 @@
From fdcfa9e7ff6eb31fe77cd4032d202bb8f1a50f37 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Thu, 21 Nov 2024 18:23:00 +0800
Subject: [PATCH] ipmi cmd support set sel time utc offset
---
storagehandler.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/storagehandler.cpp b/storagehandler.cpp
index 4fef019..67d76ea 100644
--- a/storagehandler.cpp
+++ b/storagehandler.cpp
@@ -696,6 +696,63 @@ ipmi::RspType<int16_t> ipmiStorageGetSelTimeUtcOffset()
return ipmi::responseSuccess(timeEquation);
}
+/** @brief implements the Set SEL timezone command
+ * @returns IPMI completion code plus response data
+ * -current timezone
+ */
+ipmi::RspType<> ipmiStorageSetSelTimeUtcOffset(int16_t UTCOffset)
+{
+ int hrs = 0;
+ char ZoneInfoFile[128] = {0}, file[32] = {0};
+ static constexpr int16_t SEL_UTC_MAX_RANGE = 1440;
+ static constexpr int16_t SEL_UTC_MIN_RANGE = -1440;
+ static constexpr int16_t UNSPECIFIED_UTC_OFFSET = 0x7ff;
+ constexpr auto LOCALTIME = "/etc/localtime";
+
+ if (((UTCOffset > SEL_UTC_MAX_RANGE ) || (UTCOffset < SEL_UTC_MIN_RANGE) || (UTCOffset % 60 != 0)) && UTCOffset != UNSPECIFIED_UTC_OFFSET)
+ {
+ return ipmi::responseParmOutOfRange();
+ }
+
+ hrs = UTCOffset / 60;
+ if(UTCOffset == UNSPECIFIED_UTC_OFFSET)
+ {
+ hrs = 0;
+ }
+
+ if (0 > UTCOffset)
+ {
+ if (snprintf(file,sizeof(file), "GMT+%d", -hrs) >= (long int)sizeof(file))
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+ }
+ else
+ {
+ if (snprintf(file,sizeof(file), "GMT-%d", hrs) >= (long int)sizeof(file))
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+ }
+
+ if (snprintf (ZoneInfoFile, sizeof(ZoneInfoFile), "%s/%s", "/usr/share/zoneinfo/Etc", file) >= (long int)sizeof(ZoneInfoFile))
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+
+ if((0 > unlink(LOCALTIME)) && errno != ENOENT)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+
+ if(symlink(ZoneInfoFile, LOCALTIME) < 0)
+ {
+ return ipmi::responseUnspecifiedError();
+ }
+
+ return ipmi::responseSuccess();
+}
+
/** @brief implements the reserve SEL command
* @returns IPMI completion code plus response data
* - SEL reservation ID.
@@ -952,6 +1009,12 @@ void register_netfn_storage_functions()
ipmi::Privilege::User,
ipmiStorageGetSelTimeUtcOffset);
+ // <Set SEL Timezone>
+ ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnStorage,
+ ipmi::storage::cmdSetSelTimeUtcOffset,
+ ipmi::Privilege::Operator,
+ ipmiStorageSetSelTimeUtcOffset);
+
// <Get SEL Entry>
ipmi_register_callback(NETFUN_STORAGE, IPMI_CMD_GET_SEL_ENTRY, NULL,
getSELEntry, PRIVILEGE_USER);
--
2.25.1
@@ -0,0 +1,141 @@
From cfb5e13388531e1317eeb3ccf0f8eef0c6eeca60 Mon Sep 17 00:00:00 2001
From: Ren Yu <yux.ren@intel.com>
Date: Tue, 28 May 2019 17:11:17 +0800
Subject: [PATCH] Save the pre-timeout interrupt in dbus property
Get the watchdog pre-timeout interrupt value from ipmi watchdog set command,
and store it into dbus property.
Tested:
Config IPMI watchdog: BIOS FRB2 Power Cycle after 1 seconds:
ipmitool raw 0x06 0x24 0x01 0x13 0x0 0x2 0xa 0x00
Start watchdog:
Ipmitool mc watchdog reset
Check the watchdog pre-timeout interrupt in below:
https://BMCIP/redfish/v1/Systems/system/LogServices/EventLog/Entries
Signed-off-by: Ren Yu <yux.ren@intel.com>
Upstream-Status: Pending
---
app/watchdog.cpp | 47 ++++++++++++++++++++++++++++++++++++++++
app/watchdog_service.cpp | 6 +++++
app/watchdog_service.hpp | 9 ++++++++
3 files changed, 62 insertions(+)
diff --git a/app/watchdog.cpp b/app/watchdog.cpp
index 03c373e..cb0b1fd 100644
--- a/app/watchdog.cpp
+++ b/app/watchdog.cpp
@@ -80,6 +80,7 @@ ipmi::RspType<> ipmiAppResetWatchdogTimer()
static constexpr uint8_t wd_dont_stop = 0x1 << 6;
static constexpr uint8_t wd_timeout_action_mask = 0x3;
+static constexpr uint8_t wdPreTimeoutInterruptMask = 0x3;
static constexpr uint8_t wdTimerUseResTimer1 = 0x0;
static constexpr uint8_t wdTimerUseResTimer2 = 0x6;
@@ -127,6 +128,45 @@ WatchdogService::Action ipmiActionToWdAction(IpmiAction ipmi_action)
}
}
+enum class IpmiPreTimeoutInterrupt : uint8_t
+{
+ None = 0x0,
+ SMI = 0x1,
+ NMI = 0x2,
+ MI = 0x3,
+};
+/** @brief Converts an IPMI Watchdog PreTimeoutInterrupt to DBUS defined action
+ * @param[in] ipmi_action The IPMI Watchdog PreTimeoutInterrupt
+ * @return The Watchdog PreTimeoutInterrupt that the ipmi_action maps to
+ */
+WatchdogService::PreTimeoutInterruptAction ipmiPreTimeoutInterruptToWdAction(
+ IpmiPreTimeoutInterrupt ipmiPreTimeOutInterrupt)
+{
+ switch (ipmiPreTimeOutInterrupt)
+ {
+ case IpmiPreTimeoutInterrupt::None:
+ {
+ return WatchdogService::PreTimeoutInterruptAction::None;
+ }
+ case IpmiPreTimeoutInterrupt::SMI:
+ {
+ return WatchdogService::PreTimeoutInterruptAction::SMI;
+ }
+ case IpmiPreTimeoutInterrupt::NMI:
+ {
+ return WatchdogService::PreTimeoutInterruptAction::NMI;
+ }
+ case IpmiPreTimeoutInterrupt::MI:
+ {
+ return WatchdogService::PreTimeoutInterruptAction::MI;
+ }
+ default:
+ {
+ throw std::domain_error("IPMI PreTimeoutInterrupt is invalid");
+ }
+ }
+}
+
enum class IpmiTimerUse : uint8_t
{
Reserved = 0x0,
@@ -250,6 +290,13 @@ ipmi::RspType<>
// Mark as initialized so that future resets behave correctly
wd_service.setInitialized(true);
+ // pretimeOutAction
+ const auto ipmiPreTimeoutInterrupt =
+ static_cast<IpmiPreTimeoutInterrupt>(wdPreTimeoutInterruptMask &
+ (static_cast<uint8_t>(preTimeoutInterrupt)));
+ wd_service.setPreTimeoutInterrupt(
+ ipmiPreTimeoutInterruptToWdAction(ipmiPreTimeoutInterrupt));
+
lastCallSuccessful = true;
return ipmi::responseSuccess();
}
diff --git a/app/watchdog_service.cpp b/app/watchdog_service.cpp
index 3534e89..4df1ab6 100644
--- a/app/watchdog_service.cpp
+++ b/app/watchdog_service.cpp
@@ -198,3 +198,9 @@ void WatchdogService::setInterval(uint64_t interval)
{
setProperty("Interval", interval);
}
+
+void WatchdogService::setPreTimeoutInterrupt(
+ PreTimeoutInterruptAction preTimeoutInterrupt)
+{
+ setProperty("PreTimeoutInterrupt", convertForMessage(preTimeoutInterrupt));
+}
\ No newline at end of file
diff --git a/app/watchdog_service.hpp b/app/watchdog_service.hpp
index 141bdb7..32b7461 100644
--- a/app/watchdog_service.hpp
+++ b/app/watchdog_service.hpp
@@ -15,6 +15,8 @@ class WatchdogService
using Action =
sdbusplus::xyz::openbmc_project::State::server::Watchdog::Action;
+ using PreTimeoutInterruptAction = sdbusplus::xyz::openbmc_project::State::
+ server::Watchdog::PreTimeoutInterruptAction;
using TimerUse =
sdbusplus::xyz::openbmc_project::State::server::Watchdog::TimerUse;
@@ -92,6 +94,13 @@ class WatchdogService
*/
void setInterval(uint64_t interval);
+ /** @brief Sets the value of the PreTimeoutInterrupt property on the host
+ * watchdog
+ *
+ * @param[in] PreTimeoutInterrupt - The new PreTimeoutInterrupt value
+ */
+ void setPreTimeoutInterrupt(PreTimeoutInterruptAction preTimeoutInterrupt);
+
private:
/** @brief sdbusplus handle */
sdbusplus::bus_t bus;
--
2.17.1
@@ -0,0 +1,21 @@
[Unit]
Description=Phosphor Inband IPMI
Wants=clear-once.service
Wants=xyz.openbmc_project.Settings.service
After=xyz.openbmc_project.Settings.service
After=clear-once.service
After=org.openbmc.HostIpmi.service
[Service]
Restart=always
ExecStart=/usr/bin/env ipmid
SyslogIdentifier=ipmid
RuntimeDirectory = ipmi
RuntimeDirectoryPreserve = yes
StateDirectory = ipmi
Type=dbus
BusName=xyz.openbmc_project.Control.Host
[Install]
WantedBy=basic.target
Alias=xyz.openbmc_project.Control.Host.service
@@ -0,0 +1,3 @@
[Unit]
Wants=mapper-wait@-xyz-openbmc_project-inventory-system-board-Lux_Baseboard-BMC_Boot.service
After=mapper-wait@-xyz-openbmc_project-inventory-system-board-Lux_Baseboard-BMC_Boot.service
@@ -0,0 +1,40 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
PROJECT_SRC_DIR := "${THISDIR}/${PN}"
# The URI is required for the autobump script but keep it commented
# to not override the upstream value
# SRC_URI += "git://github.com/openbmc/phosphor-host-ipmid;branch=master;protocol=https"
SRC_URI += "file://phosphor-ipmi-host.service \
file://0063-Save-the-pre-timeout-interrupt-in-dbus-property.patch \
file://sensor-wait-sel.conf \
file://0001-ipmi-cmd-support-set-sel-time-utc-offset.patch \
file://0001-add-sensor-config-file.patch \
file://0001-Fix-incorrect-thresholdLevelsStates-response-for-Get.patch \
file://0001-Add-multiplierM-offsetB-bExp-rExp-items-in-sensor_da.patch \
file://0001-Add-power-cycle-trigger-async-firmware-update.patch \
"
FILES:${PN} += "${datadir}/ipmi-providers"
PACKAGECONFIG:remove = "allowlist"
PACKAGECONFIG:remove = "i2c-allowlist"
PACKAGECONFIG:remove = "boot-flag-safe-mode"
RDEPENDS:${PN}:remove = "clear-once"
# remove the softpoweroff service since we do not need it
SYSTEMD_SERVICE:${PN}:remove = " \
xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service"
SYSTEMD_LINK:${PN}:remove = " \
../xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service:obmc-host-shutdown@0.target.requires/xyz.openbmc_project.Ipmi.Internal.SoftPowerOff.service \
"
# remove dependencies from main recipe since we control it with local service file
unset IPMI_HOST_NEEDED_SERVICES
do_install:append(){
rm -f ${D}/${bindir}/phosphor-softpoweroff
install -d ${D}${systemd_unitdir}/system/phosphor-ipmi-host.service.d/
install -m 0644 ${WORKDIR}/sensor-wait-sel.conf ${D}${systemd_unitdir}/system/phosphor-ipmi-host.service.d/
}
@@ -0,0 +1,2 @@
KERNEL=="ipmi-kcs3", SYMLINK+="ipmi_kcs3"
KERNEL=="ipmi-kcs4", SYMLINK+="ipmi_kcs4"
@@ -0,0 +1,23 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
#SYSTEMD_SUBSTITUTIONS_remove = "KCS_DEVICE:${KCS_DEVICE}:${DBUS_SERVICE_${PN}}"
# Default kcs device is ipmi-kcs3; this is SMS.
# Add SMM kcs device instance
# Replace the '-' to '_', since Dbus object/interface names do not allow '-'.
KCS_DEVICE = "ipmi_kcs3"
SMM_DEVICE = "ipmi_kcs4"
SYSTEMD_SERVICE:${PN}:append = " ${PN}@${SMM_DEVICE}.service "
# The URI is required for the autobump script but keep it commented
# to not override the upstream value
# SRC_URI = "git://github.com/openbmc/kcsbridge.git;branch=master;protocol=https"
SRCREV = "43c83c56507cd35982537e5a646ee716f8335b6c"
SRC_URI += "file://99-ipmi-kcs.rules"
do_install:append() {
install -d ${D}${base_libdir}/udev/rules.d
install -m 0644 ${WORKDIR}/99-ipmi-kcs.rules ${D}${base_libdir}/udev/rules.d/
}
@@ -0,0 +1,42 @@
From 5e41098712ad65cb508560b01e38a9c9bf481a0c Mon Sep 17 00:00:00 2001
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
Date: Wed, 14 Aug 2024 19:48:15 +0800
Subject: [PATCH] Support HMAC-SHA1 Authentication/Integrity for RMCP+ lan
session
---
auth_algo.hpp | 3 ++-
integrity_algo.hpp | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/auth_algo.hpp b/auth_algo.hpp
index f940370..c218acf 100644
--- a/auth_algo.hpp
+++ b/auth_algo.hpp
@@ -106,7 +106,8 @@ class Interface
*/
static bool isAlgorithmSupported(Algorithms algo)
{
- if (algo == Algorithms::RAKP_HMAC_SHA256)
+ if (algo == Algorithms::RAKP_HMAC_SHA1 ||
+ algo == Algorithms::RAKP_HMAC_SHA256)
{
return true;
}
diff --git a/integrity_algo.hpp b/integrity_algo.hpp
index 6ba6340..6347357 100644
--- a/integrity_algo.hpp
+++ b/integrity_algo.hpp
@@ -94,7 +94,8 @@ class Interface
*/
static bool isAlgorithmSupported(Algorithms algo)
{
- if (algo == Algorithms::HMAC_SHA256_128)
+ if (algo == Algorithms::HMAC_SHA1_96 ||
+ algo == Algorithms::HMAC_SHA256_128)
{
return true;
}
--
2.25.1
@@ -0,0 +1,4 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += " \
file://0001-Support-HMAC-SHA1-Authentication-Integrity-for-RMCP.patch \
"
@@ -0,0 +1,142 @@
From e1dd95b374504a2a25c18291b640745a12957ace Mon Sep 17 00:00:00 2001
From: "Wang.Bin" <Bin-B.Wang@luxshare-ict.com>
Date: Mon, 6 Jan 2025 15:06:13 +0800
Subject: [PATCH 2/2] Remove-realErrors-and-infoErrors
---
log_manager.cpp | 57 +++++--------------------------------------------
log_manager.hpp | 16 --------------
2 files changed, 5 insertions(+), 68 deletions(-)
diff --git a/log_manager.cpp b/log_manager.cpp
index 2bfab30..15be9cb 100644
--- a/log_manager.cpp
+++ b/log_manager.cpp
@@ -55,15 +55,7 @@ inline auto getLevel(const std::string& errMsg)
return reqLevel;
}
-int Manager::getRealErrSize()
-{
- return realErrors.size();
-}
-int Manager::getInfoErrSize()
-{
- return infoErrors.size();
-}
uint32_t Manager::commit(uint64_t transactionId, std::string errMsg)
{
@@ -200,31 +192,16 @@ void Manager::createEntry(std::string errMsg, Entry::Level errLvl,
{
if (!Extensions::disableDefaultLogCaps())
{
- if (errLvl < Entry::sevLowerLimit)
- {
- if (realErrors.size() >= ERROR_CAP)
- {
- erase(realErrors.front());
- }
- }
- else
+ std::cout << "entries size" << static_cast<int>(entries.size()) <<std::endl;
+ if (entries.size() >= ERROR_INFO_CAP)
{
- if (infoErrors.size() >= ERROR_INFO_CAP)
- {
- erase(infoErrors.front());
- }
+ erase(entries.begin()->first);
}
}
+ std::cout << "entryId" << static_cast<int>(entryId)<< std::endl;
entryId++;
- if (errLvl >= Entry::sevLowerLimit)
- {
- infoErrors.push_back(entryId);
- }
- else
- {
- realErrors.push_back(entryId);
- }
+
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
@@ -529,21 +506,6 @@ void Manager::erase(uint32_t entryId)
errorPath /= std::to_string(entryId);
fs::remove(errorPath);
- auto removeId = [](std::list<uint32_t>& ids, uint32_t id) {
- auto it = std::find(ids.begin(), ids.end(), id);
- if (it != ids.end())
- {
- ids.erase(it);
- }
- };
- if (entryFound->second->severity() >= Entry::sevLowerLimit)
- {
- removeId(infoErrors, entryId);
- }
- else
- {
- removeId(realErrors, entryId);
- }
entries.erase(entryFound);
checkAndRemoveBlockingError(entryId);
@@ -592,15 +554,6 @@ void Manager::restore()
if (sanity(static_cast<uint32_t>(idNum), e->id()))
{
e->path(file.path(), true);
- if (e->severity() >= Entry::sevLowerLimit)
- {
- infoErrors.push_back(idNum);
- }
- else
- {
- realErrors.push_back(idNum);
- }
-
entries.insert(std::make_pair(idNum, std::move(e)));
}
else
diff --git a/log_manager.hpp b/log_manager.hpp
index 0b9056f..80866a7 100644
--- a/log_manager.hpp
+++ b/log_manager.hpp
@@ -124,17 +124,6 @@ class Manager : public details::ServerObject<details::ManagerIface>
entryId = 0;
}
- /** @brief Returns the count of high severity errors
- *
- * @return int - count of real errors
- */
- int getRealErrSize();
-
- /** @brief Returns the count of Info errors
- *
- * @return int - count of info errors
- */
- int getInfoErrSize();
/** @brief Returns the number of blocking errors
*
@@ -325,11 +314,6 @@ class Manager : public details::ServerObject<details::ManagerIface>
/** @brief Persistent sdbusplus DBus bus connection. */
sdbusplus::bus_t& busLog;
- /** @brief List of error ids for high severity errors */
- std::list<uint32_t> realErrors;
-
- /** @brief List of error ids for Info(and below) severity */
- std::list<uint32_t> infoErrors;
/** @brief Id of last error log entry */
uint32_t entryId;
--
2.25.1
@@ -0,0 +1,11 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += " \
file://0001-parse-message-when-sel-is-created.patch \
file://0002-Remove-realErrors-and-infoErrors.patch \
"
DEPENDS += "nlohmann-json"
DEPENDS += "ipmitool"
EXTRA_OEMESON:append = " -Derror_info_cap=1000"
@@ -0,0 +1,3 @@
SRC_URI = "file://luxshare-eeprom.tar.gz"
S = "${WORKDIR}"
@@ -0,0 +1,20 @@
[
{
"bus": 1,
"address": 84,
"path": "/com/luxshare/eeprom/baseboard",
"interface": "com.luxshare.eeprom",
"properties": [
{
"name": "Eth0MAC",
"offset": 512,
"size": 8
},
{
"name": "Eth1MAC",
"offset": 520,
"size": 8
}
]
}
]
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
import argparse
import json
import sys
def parse_config(path):
eeproms = {}
with open(path, 'r') as f:
config = json.load(f)
for eeprom in config:
eeproms[eeprom['path']] = eeprom['properties']
return eeproms
'''
[
{
"bus": 1,
"address": 84,
"path": "/com/luxshare/eeprom/1",
"interface": "com.luxshare.eeprom",
"properties": [
{
"name": "ETH0MAC",
"offset": 0,
"size": 6
},
{
"name": "ETH1MAC",
"offset": 8,
"size": 6
}
]
}
]
'''
def check_overlap(properties):
# sort by offset
properties.sort(key=lambda x: x['offset'])
for i in range(len(properties) - 1):
if properties[i]['offset'] + properties[i]['size'] > properties[i + 1]['offset']:
print('overlap found: {} {} {} {} {} {}'.format(
properties[i]['name'],
properties[i]['offset'],
properties[i]['size'],
properties[i + 1]['name'],
properties[i + 1]['offset'],
properties[i + 1]['size'],
))
sys.exit(1)
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Check if eeprom properties overlap')
parser.add_argument('path', help='path to json config')
args = parser.parse_args()
path = args.path
eeproms = parse_config(path)
for path, properties in eeproms.items():
print(properties)
check_overlap(properties)
@@ -0,0 +1,35 @@
LICENSE = "CLOSED"
SUMMARY = "Luxshare eeprom"
inherit meson systemd pkgconfig
require ${BPN}.inc
SRC_URI += " \
file://overlap.py \
file://eeprom.json \
"
DEPENDS = " \
sdbusplus \
nlohmann-json \
${PYTHON_PN}-native \
"
RDEPENDS:${PN} += "bash"
SYSTEMD_SERVICE:${PN} = "eeprom-manager.service"
do_install:append() {
install -d ${D}/usr/share/luxshare-eeprom
install -m 0644 ${WORKDIR}/eeprom.json ${D}/usr/share/luxshare-eeprom
}
# add a new task to check if the eeprom is valid
# after do_install
do_check_eeprom() {
python3 ${WORKDIR}/overlap.py ${D}/usr/share/luxshare-eeprom/eeprom.json
}
addtask check_eeprom after do_install before do_package
@@ -0,0 +1,20 @@
SUMMARY = "Read GUID from eeprom"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit allarch
inherit obmc-phosphor-systemd
RDEPENDS:${PN} += "bash"
S = "${WORKDIR}"
SRC_URI += "file://read-guid-from-eeprom.sh"
do_install() {
install -d ${D}${bindir}
install -m 0755 ${S}/read-guid-from-eeprom.sh ${D}${bindir}/read-guid-from-eeprom.sh
}
SYSTEMD_SERVICE:${PN} += "read-guid-from-eeprom.service"
@@ -0,0 +1,12 @@
[Unit]
Description=Read GUID from eeprom
After=xyz.openbmc_project.Settings.service
After=com.luxshare.eeprom.service
[Service]
Type=oneshot
ExecStart=/usr/bin/read-guid-from-eeprom.sh
ExecStartPost=touch /run/initramfs/read-guid-from-eeprom.done
[Install]
WantedBy=multi-user.target
@@ -0,0 +1,60 @@
#!/bin/bash
set -e
SETTINGS_SERVICE="xyz.openbmc_project.Settings"
GUID_OBJPATH="/xyz/openbmc_project/inventory/item/bmc"
GUID_INTERFACE="xyz.openbmc_project.Common.UUID"
BMC_INTERFACE="xyz.openbmc_project.Inventory.Item.Bmc"
SYSTEM_GUID_PROPERTY="UUID"
DEVICE_GUID_PROPERTY="DeviceGUID"
EEPROM_SERVICE="com.luxshare.eeprom"
EEPROM_OBJPATH="/com/luxshare/eeprom/baseboard"
EEPROM_INTERFACE="com.luxshare.eeprom"
EEPROM_SYSTEM_GUID_PROPERTY="SystemGUID"
EEPROM_DEVICE_GUID_PROPERTY="DeviceGUID"
echo "generate device&system guid from machine-id"
guid_str=$(systemd-id128 machine-id --app-specific=e0e17376646147daa50cd0cc64124578)
system_data_raw=$(busctl get-property ${EEPROM_SERVICE} ${EEPROM_OBJPATH} ${EEPROM_INTERFACE} ${EEPROM_SYSTEM_GUID_PROPERTY})
#remove ay 16
system_GUID=$(echo $system_data_raw | sed 's/ay [0-9]\+ //')
read -a data <<< "$system_GUID"
hex_data=()
#dec==>hex
for decimal_value in "${data[@]}"; do
hex_value=$(printf "%02x" "$decimal_value")
hex_data+=("$hex_value")
done
echo "Read system GUID from eeprom service : ${system_GUID}"
if [[ "$system_GUID" == "255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255" ]];then
busctl set-property "${SETTINGS_SERVICE}" "${GUID_OBJPATH}" "${GUID_INTERFACE}" "${SYSTEM_GUID_PROPERTY}" s "${guid_str:0:8}"-"${guid_str:8:4}"-"${guid_str:12:4}"-"${guid_str:16:4}"-"${guid_str:20:12}"
else
busctl set-property "${SETTINGS_SERVICE}" "${GUID_OBJPATH}" "${GUID_INTERFACE}" "${SYSTEM_GUID_PROPERTY}" s "${hex_data[0]}""${hex_data[1]}""${hex_data[2]}""${hex_data[3]}"-"${hex_data[4]}""${hex_data[5]}"-"${hex_data[6]}""${hex_data[7]}"-"${hex_data[8]}""${hex_data[9]}"-"${hex_data[10]}""${hex_data[11]}""${hex_data[12]}""${hex_data[13]}""${hex_data[14]}""${hex_data[15]}"
fi
device_data_raw=$(busctl get-property ${EEPROM_SERVICE} ${EEPROM_OBJPATH} ${EEPROM_INTERFACE} ${EEPROM_DEVICE_GUID_PROPERTY})
device_GUID=$(echo $device_data_raw | sed 's/ay [0-9]\+ //')
read -a data <<< "$device_GUID"
hex_data=()
#dec==>hex
for decimal_value in "${data[@]}"; do
hex_value=$(printf "%02x" "$decimal_value")
hex_data+=("$hex_value")
done
echo "Read device GUID from eeprom : ${device_GUID}"
if [[ "$device_GUID" == "255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255" ]];then
busctl set-property "${SETTINGS_SERVICE}" "${GUID_OBJPATH}" "${BMC_INTERFACE}" "${DEVICE_GUID_PROPERTY}" s "${guid_str:0:8}"-"${guid_str:8:4}"-"${guid_str:12:4}"-"${guid_str:16:4}"-"${guid_str:20:12}"
else
busctl set-property "${SETTINGS_SERVICE}" "${GUID_OBJPATH}" "${BMC_INTERFACE}" "${DEVICE_GUID_PROPERTY}" s "${hex_data[0]}""${hex_data[1]}""${hex_data[2]}""${hex_data[3]}"-"${hex_data[4]}""${hex_data[5]}"-"${hex_data[6]}""${hex_data[7]}"-"${hex_data[8]}""${hex_data[9]}"-"${hex_data[10]}""${hex_data[11]}""${hex_data[12]}""${hex_data[13]}""${hex_data[14]}""${hex_data[15]}"
fi
@@ -0,0 +1,20 @@
UMMARY = "Write GUID to eeprom"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit allarch
inherit obmc-phosphor-systemd
RDEPENDS:${PN} += "bash"
S = "${WORKDIR}"
SRC_URI += "file://write-guid-to-eeprom.sh"
do_install() {
install -d ${D}${bindir}
install -m 0755 ${S}/write-guid-to-eeprom.sh ${D}${bindir}/write-guid-to-eeprom.sh
}
SYSTEMD_SERVICE:${PN} += "write-guid-to-eeprom.service"
@@ -0,0 +1,10 @@
[Unit]
Description=Write GUID to eeprom
After=xyz.openbmc_project.Settings.service
After=com.luxshare.eeprom.service
Wants=xyz.openbmc_project.Settings.service
ConditionPathExists=/run/initramfs/read-guid-from-eeprom.done
[Service]
Type=oneshot
ExecStart=/usr/bin/write-guid-to-eeprom.sh
@@ -0,0 +1,55 @@
#!/bin/bash
set -e
SETTINGS_SERVICE="xyz.openbmc_project.Settings"
GUID_OBJPATH="/xyz/openbmc_project/inventory/item/bmc"
GUID_INTERFACE="xyz.openbmc_project.Common.UUID"
BMC_INTERFACE="xyz.openbmc_project.Inventory.Item.Bmc"
SYSTEM_GUID_PROPERTY="UUID"
DEVICE_GUID_PROPERTY="DeviceGUID"
EEPROM_SERVICE="com.luxshare.eeprom"
EEPROM_OBJPATH="/com/luxshare/eeprom/baseboard"
EEPROM_INTERFACE="com.luxshare.eeprom"
EEPROM_SYSTEM_GUID_PROPERTY="SystemGUID"
EEPROM_DEVICE_GUID_PROPERTY="DeviceGUID"
creat_GUID_str()
{
GUID=$1
for((i=0;i<4;i++));
do
data[i]=${GUID:i*2+1:2}
done
for((i=4;i<6;i++));
do
data[i]=${GUID:i*2+2:2}
done
for((i=6;i<8;i++));
do
data[i]=${GUID:i*2+3:2}
done
for((i=8;i<10;i++));
do
data[i]=${GUID:i*2+4:2}
done
for((i=10;i<16;i++));
do
data[i]=${GUID:i*2+5:2}
done
}
system_GUID=$(busctl get-property ${SETTINGS_SERVICE} ${GUID_OBJPATH} ${GUID_INTERFACE} ${SYSTEM_GUID_PROPERTY} | awk '{print $2}')
creat_GUID_str "${system_GUID}"
echo "Write system GUID to eeprom : ${system_GUID}"
busctl set-property ${EEPROM_SERVICE} ${EEPROM_OBJPATH} ${EEPROM_INTERFACE} ${EEPROM_SYSTEM_GUID_PROPERTY} ay 16 0x"${data[0]}" 0x"${data[1]}" 0x"${data[2]}" 0x"${data[3]}" 0x"${data[4]}" 0x"${data[5]}" 0x"${data[6]}" 0x"${data[7]}" 0x"${data[8]}" 0x"${data[9]}" 0x"${data[10]}" 0x"${data[11]}" 0x"${data[12]}" 0x"${data[13]}" 0x"${data[14]}" 0x"${data[15]}"
device_GUID=$(busctl get-property ${SETTINGS_SERVICE} ${GUID_OBJPATH} ${BMC_INTERFACE} ${DEVICE_GUID_PROPERTY} | awk '{print $2}')
creat_GUID_str "${device_GUID}"
echo "Write device GUID to eeprom : ${device_GUID}"
busctl set-property ${EEPROM_SERVICE} ${EEPROM_OBJPATH} ${EEPROM_INTERFACE} ${EEPROM_DEVICE_GUID_PROPERTY} ay 16 0x"${data[0]}" 0x"${data[1]}" 0x"${data[2]}" 0x"${data[3]}" 0x"${data[4]}" 0x"${data[5]}" 0x"${data[6]}" 0x"${data[7]}" 0x"${data[8]}" 0x"${data[9]}" 0x"${data[10]}" 0x"${data[11]}" 0x"${data[12]}" 0x"${data[13]}" 0x"${data[14]}" 0x"${data[15]}"
@@ -0,0 +1,78 @@
From 8095b90a438aebeba61721b30f0f7bd5f865c666 Mon Sep 17 00:00:00 2001
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
Date: Tue, 26 Aug 2025 11:01:18 +0800
Subject: [PATCH] Fix ipv4 and ipv6 ip issue Openbmc use dbus property to
control ipv4/ipv6 ip mode: .DHCP4
property b true emits-change
writable .DHCP6 property b
true emits-change writable .DHCPEnabled
property s
"xyz.openbmc_project.Network.Ethernet... emits-change writable
DHCP4=true, DHCP6=true, set DHCPEnabled to xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both
DHCP4=true, DHCP6=false, set DHCPEnabled to xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4
DHCP4=false, DHCP6=true, set DHCPEnabled to xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6
DHCP4=false, DHCP6=false, set DHCPEnabled to xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none
re-write the EthernetInterface::dhcp4 and EthernetInterface::dhcp6 function to get current value and set value
---
src/ethernet_interface.cpp | 24 ++++++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 31c6145..43a68a8 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -388,8 +388,10 @@ bool EthernetInterface::ipv6AcceptRA(bool value)
bool EthernetInterface::dhcp4(bool value)
{
- if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
+ bool oldValue = dhcp4(); // get current value
+ if (value != oldValue) // compare current value and set value
{
+ EthernetInterfaceIntf::dhcp4(value); //set new value
writeConfigurationFile();
manager.get().reloadConfigs();
}
@@ -398,8 +400,10 @@ bool EthernetInterface::dhcp4(bool value)
bool EthernetInterface::dhcp6(bool value)
{
- if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
+ bool oldValue = dhcp6(); // get current value
+ if (value != oldValue) // compare current value and set value
{
+ EthernetInterfaceIntf::dhcp6(value); //set new value
writeConfigurationFile();
manager.get().reloadConfigs();
}
@@ -684,11 +688,23 @@ void EthernetInterface::writeConfigurationFile()
auto& network = config.map["Network"].emplace_back();
auto& lla = network["LinkLocalAddressing"];
#ifdef LINK_LOCAL_AUTOCONFIGURATION
- lla.emplace_back("yes");
+ if (dhcp4() && dhcp6())
+ {
+ lla.emplace_back("yes");
+ }
+ else if (dhcp4())
+ {
+ lla.emplace_back("ipv4");
+ }
+ else if (dhcp6())
+ {
+ lla.emplace_back("ipv6");
+ }
#else
lla.emplace_back("no");
#endif
- network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
+ network["IPv6AcceptRA"].emplace_back(
+ (ipv6AcceptRA() && dhcp6()) ? "true" : "false");
network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
: (dhcp6() ? "ipv6" : "false"));
{
--
2.25.1
@@ -0,0 +1,73 @@
From dc27450fcd8cd509d540afccb06974e92a117cd6 Mon Sep 17 00:00:00 2001
From: roly <Rolyli.Li@luxshare-ict.com>
Date: Fri, 8 Nov 2024 14:31:08 +0800
Subject: [PATCH] Fix static ip still exist after enable dhcp
---
src/ethernet_interface.cpp | 19 ++++++++++++++++++-
src/ethernet_interface.hpp | 12 ++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 2851a1b..126255c 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -266,6 +266,22 @@ ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
Argument::ARGUMENT_VALUE(ipaddress.c_str()));
}
std::optional<stdplus::SubnetAny> ifaddr;
+
+ if (dhcpIsEnabled(protType))
+ {
+ log<level::INFO>("DHCP enabled on the interface, disabling");
+ switch (protType)
+ {
+ case IP::Protocol::IPv4:
+ dhcp4(false);
+ break;
+ case IP::Protocol::IPv6:
+ dhcp6(false);
+ ipv6AcceptRA(false);
+ break;
+ }
+ }
+
try
{
if (prefixLength == 0)
@@ -702,7 +718,8 @@ void EthernetInterface::writeConfigurationFile()
auto& address = network["Address"];
for (const auto& addr : addrs)
{
- if (originIsManuallyAssigned(addr.second->origin()))
+ if (originIsManuallyAssigned(addr.second->origin()) &&
+ !dhcpIsEnabled(addr.second->type()))
{
address.emplace_back(stdplus::toStr(addr.first));
}
diff --git a/src/ethernet_interface.hpp b/src/ethernet_interface.hpp
index 0e9c536..b927e69 100644
--- a/src/ethernet_interface.hpp
+++ b/src/ethernet_interface.hpp
@@ -129,6 +129,18 @@ class EthernetInterface : public Ifaces
using EthernetInterfaceIntf::dhcp6;
bool dhcp6(bool value) override;
+ inline bool dhcpIsEnabled(IP::Protocol family) const
+ {
+ switch (family)
+ {
+ case IP::Protocol::IPv6:
+ return dhcp6();
+ case IP::Protocol::IPv4:
+ return dhcp4();
+ }
+ throw std::logic_error("Unreachable");
+ }
+
inline bool dhcpIsEnabled(stdplus::In4Addr) const
{
return dhcp4();
--
2.25.1
@@ -0,0 +1,25 @@
From c9ad304d3e9a40cf58e6d054a3b030cac4ca07d6 Mon Sep 17 00:00:00 2001
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
Date: Fri, 9 May 2025 09:40:16 +0800
Subject: [PATCH] Fix the issue where the gateway configuration is not taking
effect
---
src/ethernet_interface.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 126255c..82e70a2 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -891,6 +891,7 @@ std::string EthernetInterface::defaultGateway(std::string gateway)
if (gateway != defaultGateway())
{
gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
+ writeConfigurationFile();
manager.get().reloadConfigs();
}
return gateway;
--
2.25.1
@@ -0,0 +1,26 @@
From 9caa64de9ce05305682e97057962fced2b5d7be7 Mon Sep 17 00:00:00 2001
From: Patrick Rudolph <patrick.rudolph@9elements.com>
Date: Mon, 4 Sep 2023 11:22:31 +0200
Subject: [PATCH] ethernet_interface: Fix configuration
Include config.h to satisfy #ifdefs used in code.
Fixes config 'persist-mac' and 'uboot-env' having no effect.
Change-Id: I27a4984dc069871dc757388494fcf145069a6143
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
src/ethernet_interface.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/ethernet_interface.cpp b/src/ethernet_interface.cpp
index 2851a1b..0427363 100644
--- a/src/ethernet_interface.cpp
+++ b/src/ethernet_interface.cpp
@@ -1,3 +1,4 @@
+#include "config.h"
#include "ethernet_interface.hpp"
--
2.34.1
@@ -0,0 +1,8 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += " \
file://0001-Fix-static-ip-still-exist-after-enable-dhcp.patch \
file://0001-Fix-the-issue-where-the-gateway-configuration-is-not.patch \
file://0001-ethernet_interface-Fix-configuration.patch \
file://0001-Fix-ipv4-and-ipv6-ip-issue.patch \
"
@@ -0,0 +1,46 @@
SUMMARY = "OpenBMC for Luxshare Applications"
PR = "r1"
inherit packagegroup
PROVIDES = "${PACKAGES}"
PACKAGES = " \
${PN}-chassis \
${PN}-fans \
${PN}-flash \
${PN}-system \
"
PROVIDES += "virtual/obmc-chassis-mgmt"
PROVIDES += "virtual/obmc-fan-mgmt"
PROVIDES += "virtual/obmc-flash-mgmt"
PROVIDES += "virtual/obmc-system-mgmt"
RPROVIDES:${PN}-chassis += "virtual-obmc-chassis-mgmt"
RPROVIDES:${PN}-fans += "virtual-obmc-fan-mgmt"
RPROVIDES:${PN}-flash += "virtual-obmc-flash-mgmt"
RPROVIDES:${PN}-system += "virtual-obmc-system-mgmt"
VIRTUAL-RUNTIME_obmc-inventory-manager = "entity-manager"
VIRTUAL-RUNTIME_obmc-host-state-manager = "x86-power-control"
VIRTUAL-RUNTIME_obmc-chassis-state-manager = "x86-power-control"
VIRTUAL-RUNTIME_obmc-discover-system-state = "x86-power-control"
PREFERRED_PROVIDER_virtual/obmc-inventory-data = "entity-manager"
SUMMARY:${PN}-chassis = "Luxshare Chassis"
RDEPENDS:${PN}-chassis = " \
x86-power-control \
phosphor-sel-logger \
ipmitool \
phosphor-post-code-manager \
phosphor-host-postd \
host-misc-comm-manager \
svf \
"
SUMMARY:${PN}-flash = "Luxshare Flash"
RDEPENDS:${PN}-flash = " \
phosphor-software-manager \
"
RDEPENDS:${PN}-fans = " phosphor-pid-control "
RDEPENDS:${PN}-system = " dbus-sensors "
@@ -0,0 +1,14 @@
RDEPENDS:${PN}-extras:append = " \
phosphor-misc-usb-ctrl \
srvcfg-manager \
phosphor-misc-http-redirect-awk \
ethtool \
gawk \
net-tools \
host-misc-comm-manager \
"
RDEPENDS:${PN}-software:append = " \
phosphor-software-manager-sync \
curl \
"
@@ -0,0 +1,5 @@
RDEPENDS:${PN}:append = "\
lsof \
gdb \
gdbserver \
"
@@ -0,0 +1,209 @@
---
/xyz/openbmc_project/logging/rsyslog/audit_log/index0:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv6
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/audit_log/index1:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv6
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/audit_log/index2:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv4
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/audit_log/index3:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv4
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/sel_log/index0:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv6
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/sel_log/index1:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv6
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/sel_log/index2:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv4
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/sel_log/index3:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv4
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/syslog_log/index0:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv6
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/syslog_log/index1:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv6
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/syslog_log/index2:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv4
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/syslog_log/index3:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv4
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/sol_log/index0:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv6
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/sol_log/index1:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv6
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/sol_log/index2:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv4
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
/xyz/openbmc_project/logging/rsyslog/sol_log/index3:
- Interface: xyz.openbmc_project.Logging.Rsyslog
Properties:
Status:
Default: 'false'
AddressType:
Default: Rsyslog::Type::IPv4
Address:
Default: '""'
Port:
Default: 0
ProtocolType:
Default: Rsyslog::Protocol::UDP
@@ -0,0 +1,5 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI:append = " \
file://Rsyslog.override.yml \
"
@@ -0,0 +1,25 @@
From 3862ecd0e0d99c9591b036e6e53d84113eb24752 Mon Sep 17 00:00:00 2001
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
Date: Wed, 11 Dec 2024 17:42:00 +0800
Subject: [PATCH] Do not remove user home dir when delete user
---
user_mgr.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/user_mgr.cpp b/user_mgr.cpp
index 873ee1d..257fbe9 100644
--- a/user_mgr.cpp
+++ b/user_mgr.cpp
@@ -1617,7 +1617,7 @@ void UserMgr::executeUserAdd(const char* userName, const char* groups,
void UserMgr::executeUserDelete(const char* userName)
{
- executeCmd("/usr/sbin/userdel", userName, "-r");
+ executeCmd("/usr/sbin/userdel", userName);
}
void UserMgr::executeUserClearFailRecords(const char* userName)
--
2.25.1
@@ -0,0 +1,64 @@
From b814451f0d9301d3ad9210154512cbee4eaaac9b Mon Sep 17 00:00:00 2001
From: "Chen.Zhao" <zhao.chen@luxshare-ict.com>
Date: Tue, 10 Dec 2024 15:30:10 +0800
Subject: [PATCH] Move user home to tmp instead
When creat new user or modify user name, because the user HOME is default in /home, BMC can't move
/home/xxx to another folder. So move user HOME to /tmp to fix this issue.
Tested:
D:\Software\ipmitool_win_18>ipmitool -I lanplus -H 10.67.13.44 -U test -P Admin@9000 user set name 2 testtest
D:\Software\ipmitool_win_18>ipmitool -I lanplus -H 10.67.13.44 -U test -P Admin@9000 user list 1
ID Name Callin Link Auth IPMI Msg Channel Priv Limit
1 root false true true ADMINISTRATOR
2 testtest false true true ADMINISTRATOR
3 test false true true ADMINISTRATOR
4 true false false NO ACCESS
5 true false false NO ACCESS
6 true false false NO ACCESS
7 true false false NO ACCESS
8 true false false NO ACCESS
9 true false false NO ACCESS
10 true false false NO ACCESS
11 true false false NO ACCESS
12 true false false NO ACCESS
13 true false false NO ACCESS
14 true false false NO ACCESS
15 true false false NO ACCESS
---
user_mgr.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/user_mgr.cpp b/user_mgr.cpp
index 5bb1509..873ee1d 100644
--- a/user_mgr.cpp
+++ b/user_mgr.cpp
@@ -1609,9 +1609,10 @@ void UserMgr::executeUserAdd(const char* userName, const char* groups,
{
// set EXPIRE_DATE to 0 to disable user, PAM takes 0 as expire on
// 1970-01-01, that's an implementation-defined behavior
- executeCmd("/usr/sbin/useradd", userName, "-G", groups, "-m", "-N", "-s",
- (sshRequested ? "/bin/sh" : "/sbin/nologin"), "-e",
- (enabled ? "" : "1970-01-01"));
+ executeCmd("/usr/sbin/useradd", userName, "-G", groups, "-M", "-d", "/tmp",
+ "-N", "-s", (sshRequested ? "/bin/sh" : "/sbin/nologin"), "-e",
+ (enabled ? "" : "1970-01-01"));
+
}
void UserMgr::executeUserDelete(const char* userName)
@@ -1628,8 +1629,9 @@ void UserMgr::executeUserRename(const char* userName, const char* newUserName)
{
std::string newHomeDir = "/home/";
newHomeDir += newUserName;
- executeCmd("/usr/sbin/usermod", "-l", newUserName, userName, "-d",
- newHomeDir.c_str(), "-m");
+ // Do not create new home, and re-use /tmp as home for the user
+ executeCmd("/usr/sbin/usermod", "-l", newUserName, userName, "-d", "/tmp");
+
}
void UserMgr::executeUserModify(const char* userName, const char* newGroups,
--
2.25.1
@@ -0,0 +1,6 @@
FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"
SRC_URI += " \
file://0001-Move-user-home-to-tmp-instead.patch \
file://0001-Do-not-remove-user-home-dir-when-delete-user.patch \
"
+22
View File
@@ -0,0 +1,22 @@
SUMMARY = "Disable the watchdog used to monitor BMC ready"
PR = "r1"
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
inherit allarch
inherit obmc-phosphor-systemd
RDEPENDS:${PN} += "bash"
S = "${WORKDIR}"
SRC_URI += "file://disable-wdt"
do_install() {
install -d ${D}${bindir}
install -m 0755 ${S}/disable-wdt ${D}${bindir}/disable-wdt
}
SYSTEMD_SERVICE:${PN} += "disable-wdt.service"
@@ -0,0 +1,14 @@
#!/bin/bash
set -e
ACCESS_PRIMARY="/sys/devices/platform/ahb/1e620000.spi/access_primary"
ACCESS_BACKUP="/sys/devices/platform/ahb/1e620000.spi/access_backup"
if [ -f "${ACCESS_PRIMARY}" ]; then
echo 0 > ${ACCESS_PRIMARY}
echo "Disable watchdog by access_primary."
elif [ -f "${ACCESS_BACKUP}" ]; then
echo 0 > ${ACCESS_BACKUP}
echo "Disable watchdog by access_backup."
fi
@@ -0,0 +1,10 @@
[Unit]
Description=Disable the watchdog
[Service]
Type=oneshot
ExecStart=/usr/bin/disable-wdt
ExecStart=bash -c "echo -1 > /proc/sys/kernel/panic"
[Install]
WantedBy=multi-user.target
+12
View File
@@ -0,0 +1,12 @@
SUMMARY = "System watchdog"
DESCRIPTION = "BMC hardware watchdog service that is used to reset BMC \
when unrecoverable events occurs"
inherit allarch
inherit obmc-phosphor-systemd
LICENSE = "Apache-2.0"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
SYSTEMD_SERVICE:${PN} += "system-watchdog.service"
SYSTEMD_ENVIRONMENT_FILE:${PN} += "obmc/system-watchdog/system-watchdog.conf"
@@ -0,0 +1,3 @@
TIMEOUT=180
INTERVAL=10
DEVICE=/dev/watchdog1
@@ -0,0 +1,11 @@
[Unit]
Description=BMC Hardware Watchdog Daemon
[Service]
EnvironmentFile=/etc/default/obmc/system-watchdog/system-watchdog.conf
ExecStart=/sbin/watchdog -T ${{TIMEOUT}} -t ${{INTERVAL}} -F ${{DEVICE}}
KillSignal=SIGABRT
[Install]
WantedBy=basic.target