dbus-sdr: Initial Dynamic Sensor Stack
Migrate intel-ipmi-oem dynamic sensor stack into
phosphor-host-ipmid for more general use.
The files are copied from
https://gerrit.openbmc-project.xyz/c/openbmc/intel-ipmi-oem/+/39743
https://gerrit.openbmc-project.xyz/plugins/gitiles/openbmc/intel-ipmi-oem/+/b910987a7d832e38e9342f0946aeb555a48f9cb0
Created `libdynamiccmds` to enable dynamic sensor stack.
Minor changes in the migration include:
1, Removing the use of `commandutils.hpp` in all files since it is only used
for
```
static constexpr bool debug = false;
```
It is added to `sdrutils.hpp` instead.
2, Update lastWriteAddr to size_t to match the vector.size() type
during comparison.
3, Renamed the sensorcommand unit test to sensorcommands_unitest.cpp
4, Removed unused variables.
- sensorcommands
```
constexpr uint8_t thresholdMask = 0xFF;
```
- sensorcommands_unitest
```
double yError = std::abs(y - yRoundtrip);
```
5, Removed Intel Specific Changes
- Redfish logs
- node manager/ME
- BIOS to SEL event
6, Removed externing a global variable for sensorTree.
- Replaced it with a method that returns a singleton
- auto& sensorTree = getSensorTree(); for access
7, Replaced intel_oem namespace with dynamic_sensors
8, Removed types.hpp and use `ipmid/types.hpp` directly
- Updated the types to match ipmid/types
- Added Association and std::vector<Association>> under Value.
9, Add cpp files for sdrutils and sensorutils.
10, link libipmid as it is required for getManagedObjects needed
by sensorcommands.cpp
Signed-off-by: Willy Tu <wltu@google.com>
Change-Id: If944620c895ecf4c9f4c3efe72479f4de276f4fb
Signed-off-by: Vijay Khemka <vijaykhemkalinux@gmail.com>
diff --git a/include/Makefile.am b/include/Makefile.am
index 08824c4..7c90f70 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -17,7 +17,11 @@
ipmid/utility.hpp \
ipmid/utils.hpp \
ipmid-host/cmd.hpp \
- ipmid-host/cmd-utils.hpp
+ ipmid-host/cmd-utils.hpp \
+ dbus-sdr/sdrutils.hpp \
+ dbus-sdr/sensorcommands.hpp \
+ dbus-sdr/sensorutils.hpp \
+ dbus-sdr/storagecommands.hpp
# Eventually we will split <ipmid/*> and <host-ipmid/*> headers
# For now they will be the same during migration
diff --git a/include/dbus-sdr/sdrutils.hpp b/include/dbus-sdr/sdrutils.hpp
new file mode 100644
index 0000000..8d27c02
--- /dev/null
+++ b/include/dbus-sdr/sdrutils.hpp
@@ -0,0 +1,118 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#include <boost/algorithm/string.hpp>
+#include <boost/bimap.hpp>
+#include <boost/container/flat_map.hpp>
+#include <cstdio>
+#include <cstring>
+#include <exception>
+#include <filesystem>
+#include <ipmid/api.hpp>
+#include <ipmid/types.hpp>
+#include <map>
+#include <phosphor-logging/log.hpp>
+#include <sdbusplus/bus/match.hpp>
+#include <string>
+#include <vector>
+
+#pragma once
+
+static constexpr bool debug = false;
+
+struct CmpStrVersion
+{
+ bool operator()(std::string a, std::string b) const
+ {
+ return strverscmp(a.c_str(), b.c_str()) < 0;
+ }
+};
+
+using SensorSubTree = boost::container::flat_map<
+ std::string,
+ boost::container::flat_map<std::string, std::vector<std::string>>,
+ CmpStrVersion>;
+
+using SensorNumMap = boost::bimap<int, std::string>;
+
+static constexpr uint16_t maxSensorsPerLUN = 255;
+static constexpr uint16_t maxIPMISensors = (maxSensorsPerLUN * 3);
+static constexpr uint16_t lun1Sensor0 = 0x100;
+static constexpr uint16_t lun3Sensor0 = 0x300;
+static constexpr uint16_t invalidSensorNumber = 0xFFFF;
+static constexpr uint8_t reservedSensorNumber = 0xFF;
+
+namespace details
+{
+bool getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree);
+
+bool getSensorNumMap(std::shared_ptr<SensorNumMap>& sensorNumMap);
+} // namespace details
+
+bool getSensorSubtree(SensorSubTree& subtree);
+
+struct CmpStr
+{
+ bool operator()(const char* a, const char* b) const
+ {
+ return std::strcmp(a, b) < 0;
+ }
+};
+
+enum class SensorTypeCodes : uint8_t
+{
+ reserved = 0x0,
+ temperature = 0x1,
+ voltage = 0x2,
+ current = 0x3,
+ fan = 0x4,
+ other = 0xB,
+};
+
+const static boost::container::flat_map<const char*, SensorTypeCodes, CmpStr>
+ sensorTypes{{{"temperature", SensorTypeCodes::temperature},
+ {"voltage", SensorTypeCodes::voltage},
+ {"current", SensorTypeCodes::current},
+ {"fan_tach", SensorTypeCodes::fan},
+ {"fan_pwm", SensorTypeCodes::fan},
+ {"power", SensorTypeCodes::other}}};
+
+std::string getSensorTypeStringFromPath(const std::string& path);
+
+uint8_t getSensorTypeFromPath(const std::string& path);
+
+uint16_t getSensorNumberFromPath(const std::string& path);
+
+uint8_t getSensorEventTypeFromPath(const std::string& path);
+
+std::string getPathFromSensorNumber(uint16_t sensorNum);
+
+namespace ipmi
+{
+std::map<std::string, std::vector<std::string>>
+ getObjectInterfaces(const char* path);
+
+std::map<std::string, Value> getEntityManagerProperties(const char* path,
+ const char* interface);
+
+const std::string* getSensorConfigurationInterface(
+ const std::map<std::string, std::vector<std::string>>&
+ sensorInterfacesResponse);
+
+void updateIpmiFromAssociation(const std::string& path,
+ const DbusInterfaceMap& sensorMap,
+ uint8_t& entityId, uint8_t& entityInstance);
+} // namespace ipmi
diff --git a/include/dbus-sdr/sensorcommands.hpp b/include/dbus-sdr/sensorcommands.hpp
new file mode 100644
index 0000000..b9c845f
--- /dev/null
+++ b/include/dbus-sdr/sensorcommands.hpp
@@ -0,0 +1,168 @@
+/*
+// Copyright (c) 2017 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <cstdint>
+#include <dbus-sdr/sdrutils.hpp>
+
+#pragma pack(push, 1)
+
+struct SensorThresholdResp
+{
+ uint8_t readable;
+ uint8_t lowernc;
+ uint8_t lowercritical;
+ uint8_t lowernonrecoverable;
+ uint8_t uppernc;
+ uint8_t uppercritical;
+ uint8_t uppernonrecoverable;
+};
+
+#pragma pack(pop)
+
+enum class IPMIThresholdRespBits
+{
+ lowerNonCritical,
+ lowerCritical,
+ lowerNonRecoverable,
+ upperNonCritical,
+ upperCritical,
+ upperNonRecoverable
+};
+
+enum class IPMISensorReadingByte2 : uint8_t
+{
+ eventMessagesEnable = (1 << 7),
+ sensorScanningEnable = (1 << 6),
+ readingStateUnavailable = (1 << 5),
+};
+
+enum class IPMISensorReadingByte3 : uint8_t
+{
+ upperNonRecoverable = (1 << 5),
+ upperCritical = (1 << 4),
+ upperNonCritical = (1 << 3),
+ lowerNonRecoverable = (1 << 2),
+ lowerCritical = (1 << 1),
+ lowerNonCritical = (1 << 0),
+};
+
+enum class IPMISensorEventEnableByte2 : uint8_t
+{
+ eventMessagesEnable = (1 << 7),
+ sensorScanningEnable = (1 << 6),
+};
+
+enum class IPMISensorEventEnableThresholds : uint8_t
+{
+ nonRecoverableThreshold = (1 << 6),
+ criticalThreshold = (1 << 5),
+ nonCriticalThreshold = (1 << 4),
+ upperNonRecoverableGoingHigh = (1 << 3),
+ upperNonRecoverableGoingLow = (1 << 2),
+ upperCriticalGoingHigh = (1 << 1),
+ upperCriticalGoingLow = (1 << 0),
+ upperNonCriticalGoingHigh = (1 << 7),
+ upperNonCriticalGoingLow = (1 << 6),
+ lowerNonRecoverableGoingHigh = (1 << 5),
+ lowerNonRecoverableGoingLow = (1 << 4),
+ lowerCriticalGoingHigh = (1 << 3),
+ lowerCriticalGoingLow = (1 << 2),
+ lowerNonCriticalGoingHigh = (1 << 1),
+ lowerNonCriticalGoingLow = (1 << 0),
+};
+
+enum class IPMIGetSensorEventEnableThresholds : uint8_t
+{
+ lowerNonCriticalGoingLow = 0,
+ lowerNonCriticalGoingHigh = 1,
+ lowerCriticalGoingLow = 2,
+ lowerCriticalGoingHigh = 3,
+ lowerNonRecoverableGoingLow = 4,
+ lowerNonRecoverableGoingHigh = 5,
+ upperNonCriticalGoingLow = 6,
+ upperNonCriticalGoingHigh = 7,
+ upperCriticalGoingLow = 8,
+ upperCriticalGoingHigh = 9,
+ upperNonRecoverableGoingLow = 10,
+ upperNonRecoverableGoingHigh = 11,
+};
+
+enum class IPMINetfnSensorCmds : ipmi_cmd_t
+{
+ ipmiCmdGetDeviceSDRInfo = 0x20,
+ ipmiCmdGetDeviceSDR = 0x21,
+ ipmiCmdReserveDeviceSDRRepo = 0x22,
+ ipmiCmdSetSensorThreshold = 0x26,
+ ipmiCmdGetSensorThreshold = 0x27,
+ ipmiCmdGetSensorEventEnable = 0x29,
+ ipmiCmdGetSensorEventStatus = 0x2B,
+ ipmiCmdGetSensorReading = 0x2D,
+ ipmiCmdGetSensorType = 0x2F,
+ ipmiCmdSetSensorReadingAndEventStatus = 0x30,
+};
+
+namespace ipmi
+{
+
+SensorSubTree& getSensorTree()
+{
+ static SensorSubTree sensorTree;
+ return sensorTree;
+}
+
+static ipmi_ret_t getSensorConnection(ipmi::Context::ptr ctx, uint8_t sensnum,
+ std::string& connection,
+ std::string& path)
+{
+ auto& sensorTree = getSensorTree();
+ if (sensorTree.empty() && !getSensorSubtree(sensorTree))
+ {
+ return IPMI_CC_RESPONSE_ERROR;
+ }
+
+ if (ctx == nullptr)
+ {
+ return IPMI_CC_RESPONSE_ERROR;
+ }
+
+ path = getPathFromSensorNumber((ctx->lun << 8) | sensnum);
+ if (path.empty())
+ {
+ return IPMI_CC_INVALID_FIELD_REQUEST;
+ }
+
+ for (const auto& sensor : sensorTree)
+ {
+ if (path == sensor.first)
+ {
+ connection = sensor.second.begin()->first;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+struct IPMIThresholds
+{
+ std::optional<uint8_t> warningLow;
+ std::optional<uint8_t> warningHigh;
+ std::optional<uint8_t> criticalLow;
+ std::optional<uint8_t> criticalHigh;
+};
+
+} // namespace ipmi
diff --git a/include/dbus-sdr/sensorutils.hpp b/include/dbus-sdr/sensorutils.hpp
new file mode 100644
index 0000000..c68a449
--- /dev/null
+++ b/include/dbus-sdr/sensorutils.hpp
@@ -0,0 +1,39 @@
+/*
+// Copyright (c) 2017 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <algorithm>
+#include <cmath>
+#include <iostream>
+
+namespace ipmi
+{
+static constexpr int16_t maxInt10 = 0x1FF;
+static constexpr int16_t minInt10 = -0x200;
+static constexpr int8_t maxInt4 = 7;
+static constexpr int8_t minInt4 = -8;
+
+bool getSensorAttributes(const double max, const double min, int16_t& mValue,
+ int8_t& rExp, int16_t& bValue, int8_t& bExp,
+ bool& bSigned);
+
+uint8_t scaleIPMIValueFromDouble(const double value, const int16_t mValue,
+ const int8_t rExp, const int16_t bValue,
+ const int8_t bExp, const bool bSigned);
+
+uint8_t getScaledIPMIValue(const double value, const double max,
+ const double min);
+} // namespace ipmi
diff --git a/include/dbus-sdr/storagecommands.hpp b/include/dbus-sdr/storagecommands.hpp
new file mode 100644
index 0000000..d0fa110
--- /dev/null
+++ b/include/dbus-sdr/storagecommands.hpp
@@ -0,0 +1,113 @@
+/*
+// Copyright (c) 2017 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include "sensorhandler.hpp"
+
+#include <cstdint>
+
+#define USING_ENTITY_MANAGER_DECORATORS
+
+static constexpr uint8_t ipmiSdrVersion = 0x51;
+
+namespace dynamic_sensors::ipmi::sel
+{
+static constexpr uint8_t selOperationSupport = 0x02;
+static constexpr uint8_t systemEvent = 0x02;
+static constexpr size_t systemEventSize = 3;
+static constexpr uint8_t oemTsEventFirst = 0xC0;
+static constexpr uint8_t oemTsEventLast = 0xDF;
+static constexpr size_t oemTsEventSize = 9;
+static constexpr uint8_t oemEventFirst = 0xE0;
+static constexpr uint8_t oemEventLast = 0xFF;
+static constexpr size_t oemEventSize = 13;
+static constexpr uint8_t eventMsgRev = 0x04;
+} // namespace dynamic_sensors::ipmi::sel
+
+enum class SdrRepositoryInfoOps : uint8_t
+{
+ allocCommandSupported = 0x1,
+ reserveSDRRepositoryCommandSupported = 0x2,
+ partialAddSDRSupported = 0x4,
+ deleteSDRSupported = 0x8,
+ reserved = 0x10,
+ modalLSB = 0x20,
+ modalMSB = 0x40,
+ overflow = 0x80
+};
+
+enum class GetFRUAreaAccessType : uint8_t
+{
+ byte = 0x0,
+ words = 0x1
+};
+
+enum class SensorUnits : uint8_t
+{
+ unspecified = 0x0,
+ degreesC = 0x1,
+ volts = 0x4,
+ amps = 0x5,
+ watts = 0x6,
+ rpm = 0x12,
+};
+
+#pragma pack(push, 1)
+struct FRUHeader
+{
+ uint8_t commonHeaderFormat;
+ uint8_t internalOffset;
+ uint8_t chassisOffset;
+ uint8_t boardOffset;
+ uint8_t productOffset;
+ uint8_t multiRecordOffset;
+ uint8_t pad;
+ uint8_t checksum;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 1)
+struct Type12Record
+{
+ get_sdr::SensorDataRecordHeader header;
+ uint8_t slaveAddress;
+ uint8_t channelNumber;
+ uint8_t powerStateNotification;
+ uint8_t deviceCapabilities;
+ uint24_t reserved;
+ uint8_t entityID;
+ uint8_t entityInstance;
+ uint8_t oem;
+ uint8_t typeLengthCode;
+ char name[16];
+};
+#pragma pack(pop)
+
+namespace ipmi
+{
+namespace storage
+{
+
+constexpr const size_t type12Count = 2;
+ipmi_ret_t getFruSdrs(ipmi::Context::ptr ctx, size_t index,
+ get_sdr::SensorDataFruRecord& resp);
+
+ipmi_ret_t getFruSdrCount(ipmi::Context::ptr ctx, size_t& count);
+
+std::vector<uint8_t> getType12SDRs(uint16_t index, uint16_t recordId);
+std::vector<uint8_t> getNMDiscoverySDR(uint16_t index, uint16_t recordId);
+} // namespace storage
+} // namespace ipmi
diff --git a/include/ipmid/types.hpp b/include/ipmid/types.hpp
index fa4d58c..e62c819 100644
--- a/include/ipmid/types.hpp
+++ b/include/ipmid/types.hpp
@@ -16,8 +16,11 @@
using DbusObjectInfo = std::pair<DbusObjectPath, DbusService>;
using DbusProperty = std::string;
-using Value = std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
- int64_t, uint64_t, double, std::string>;
+using Association = std::tuple<std::string, std::string, std::string>;
+
+using Value =
+ std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t,
+ uint64_t, double, std::string, std::vector<Association>>;
using PropertyMap = std::map<DbusProperty, Value>;