phosphor: dbus-sensors: Migrate patches to meta-gbmc-staging
These patches were residing in an internal repository. We do not
need to be hide them. We need to share them with external
partners.
Tested:
Verified that the patches are applied correctly.
Verified that the content delivered by the patches
is present on the machine.
Change-Id: Ia309d85fa453983eabd5a2607512223f48de8214
Signed-off-by: Claire Liao <claireliao@google.com>
diff --git a/recipes-phosphor/sensors/dbus-sensors/0010-dbus-sensors-Creating-association-between-inventory-.patch b/recipes-phosphor/sensors/dbus-sensors/0010-dbus-sensors-Creating-association-between-inventory-.patch
new file mode 100644
index 0000000..8347433
--- /dev/null
+++ b/recipes-phosphor/sensors/dbus-sensors/0010-dbus-sensors-Creating-association-between-inventory-.patch
@@ -0,0 +1,366 @@
+From 136784e24eddedac053949883247ff6933fcb9e6 Mon Sep 17 00:00:00 2001
+From: Michael Shen <gpgpgp@google.com>
+Date: Tue, 3 Jan 2023 08:38:40 +0000
+Subject: [PATCH 1/3] dbus-sensors: Creating association between inventory and
+ sensor
+
+This change is based on the https://gerrit.openbmc.org/c/openbmc/dbus-sensors/+/53789
+It sets up additional "inventory" association between hwmon sensor and
+its corresponding inventory.
+For example `SBTSI` is the CPU sensor for AMD CPU so we can associate
+all the `SBTSI` sensor to CPU inventory.
+This is used to add the CPU resource to RelatedItems in bmcweb.
+
+Tested:
+```
+$ busctl call --verbose xyz.openbmc_project.ObjectMapper /xyz/openbmc_project/object_mapper xyz.openbmc_project.ObjectMapper GetSubTree sias /xyz/openbmc_project/sensors/temperature/CPU0_T 0 0
+MESSAGE "a{sa{sas}}" {
+ ARRAY "{sa{sas}}" {
+ DICT_ENTRY "sa{sas}" {
+ STRING "/xyz/openbmc_project/sensors/temperature/CPU0_T/chassis";
+ ARRAY "{sas}" {
+ DICT_ENTRY "sas" {
+ STRING "xyz.openbmc_project.ObjectMapper";
+ ARRAY "s" {
+ STRING "xyz.openbmc_project.Association";
+ };
+ };
+ };
+ };
+ DICT_ENTRY "sa{sas}" {
+ STRING "/xyz/openbmc_project/sensors/temperature/CPU0_T/inventory";
+ ARRAY "{sas}" {
+ DICT_ENTRY "sas" {
+ STRING "xyz.openbmc_project.ObjectMapper";
+ ARRAY "s" {
+ STRING "xyz.openbmc_project.Association";
+ };
+ };
+ };
+ };
+ };
+};
+
+$ busctl get-property xyz.openbmc_project.ObjectMapper /xyz/openbmc_project/sensors/temperature/CPU0_T/inventory xyz.openbmc_project.Association endpoints
+as 1 "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0"
+```
+
+Patch Tracking Bug: b/264604501
+Upstream info / review: go/obmcl/60031
+Upstream-Status: Submitted
+Justification: Pending upstream review
+
+Change-Id: I66d5fc880f79bb504dcceb56aee1c6f3d9df73f5
+Signed-off-by: Michael Shen <gpgpgp@google.com>
+Signed-off-by: Willy Tu <wltu@google.com>
+
+%% original patch: 0010-dbus-sensors-Creating-association-between-inventory-.patch
+---
+ src/HwmonTempMain.cpp | 136 +++++++++++++++++++++++++++++++++++++++-
+ src/HwmonTempSensor.cpp | 31 +++++++--
+ src/HwmonTempSensor.hpp | 3 +-
+ src/Utils.cpp | 13 ++++
+ src/Utils.hpp | 2 +
+ 5 files changed, 176 insertions(+), 9 deletions(-)
+
+diff --git a/src/HwmonTempMain.cpp b/src/HwmonTempMain.cpp
+index 340bf11..642902f 100644
+--- a/src/HwmonTempMain.cpp
++++ b/src/HwmonTempMain.cpp
+@@ -23,6 +23,7 @@
+ #include <boost/container/flat_set.hpp>
+ #include <sdbusplus/asio/connection.hpp>
+ #include <sdbusplus/asio/object_server.hpp>
++#include <sdbusplus/asio/property.hpp>
+ #include <sdbusplus/bus/match.hpp>
+
+ #include <array>
+@@ -50,6 +51,7 @@ static constexpr double maxValueTemperature = 127; // DegreesC
+ static constexpr double minValueTemperature = -128; // DegreesC
+
+ namespace fs = std::filesystem;
++namespace rules = sdbusplus::bus::match::rules;
+
+ static const I2CDeviceTypeMap sensorTypes{
+ {"DPS310", I2CDeviceType{"dps310", false}},
+@@ -77,6 +79,14 @@ static const I2CDeviceTypeMap sensorTypes{
+ {"W83773G", I2CDeviceType{"w83773g", true}},
+ };
+
++boost::container::flat_map<std::string, std::string> inventoryMap;
++
++static const boost::container::flat_map<std::string, std::vector<std::string>,
++ std::less<>>
++ sensorTargetMap = {
++ {"SBTSI", {"xyz.openbmc_project.Inventory.Item.Cpu"}},
++};
++
+ static struct SensorParams
+ getSensorParameters(const std::filesystem::path& path)
+ {
+@@ -320,6 +330,109 @@ boost::container::flat_map<std::string,
+ return devices;
+ }
+
++void updateLocation(
++ const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
++ std::string_view service, std::string_view path)
++{
++ sdbusplus::message_t getLocation = systemBus->new_method_call(
++ service.data(), path.data(), "org.freedesktop.DBus.Properties", "Get");
++ getLocation.append("xyz.openbmc_project.Inventory.Decorator.LocationCode");
++ getLocation.append("LocationCode");
++ std::variant<std::string> location;
++ try
++ {
++ systemBus->call(getLocation).read(location);
++ }
++ catch (const sdbusplus::exception_t&)
++ {
++ std::cerr << "Failed to get property" << std::endl;
++ return;
++ }
++ inventoryMap[std::get<std::string>(location)] = path;
++}
++
++void getInventory(const std::shared_ptr<sdbusplus::asio::connection>& systemBus,
++ const std::vector<std::string>& interfaces)
++{
++ static boost::container::flat_map<
++ std::string, std::unique_ptr<sdbusplus::bus::match::match>>
++ matchers;
++
++ static auto handler =
++ [&systemBus, &interfaces](sdbusplus::message::message&) {
++ getInventory(systemBus, interfaces);
++ };
++
++ for (const auto& interface : interfaces)
++ {
++ if (matchers.contains(interface))
++ {
++ continue;
++ }
++
++ matchers[interface] = std::make_unique<sdbusplus::bus::match::match>(
++ *systemBus,
++ rules::interfacesAdded() + rules::interface(interface) +
++ rules::path_namespace(inventoryPath),
++ handler);
++ }
++
++ sdbusplus::message_t getSubTree = systemBus->new_method_call(
++ mapper::busName, mapper::path, mapper::interface, mapper::subtree);
++ getSubTree.append(inventoryPath);
++ getSubTree.append(0);
++ getSubTree.append(interfaces);
++ GetSubTreeType subtree;
++ try
++ {
++ systemBus->call(getSubTree).read(subtree);
++ }
++ catch (const sdbusplus::exception_t&)
++ {
++ std::cerr << "Failed to get subtree\n";
++ return;
++ }
++
++ for (const auto& [path, services] : subtree)
++ {
++ for (const auto& [service, interfaces] : services)
++ {
++ if (std::find(
++ interfaces.begin(), interfaces.end(),
++ "xyz.openbmc_project.Inventory.Decorator.LocationCode") ==
++ interfaces.end())
++ {
++ continue;
++ }
++ updateLocation(systemBus, service, path);
++ }
++ }
++}
++
++// This function assumes that `LocationCode` is always a substring of its
++// corresponding `sensorName`. For example if the `LocationCode` of a cpu sensor
++// is `CPU1`. Then "Die_CPU1", "CPU1", "CPU1_T", "this_is_cpu1_sensor" are all
++// valid `sensorName`.
++std::string findInventoryPath(const std::string& sensorName)
++{
++ auto findInventoryPath =
++ std::find_if(inventoryMap.begin(), inventoryMap.end(),
++ [&sensorName](const auto& e) {
++ // ex: e.first(LocationCode)="CPU1" => search="(CPU1$|CPU1[^0-9].*$)"
++ // This will avoid "CPU11", "CPU12" ... to be matched
++ std::regex locationReg("(" + e.first + "$|" + e.first + "[^0-9].*$)",
++ std::regex::icase);
++ return std::regex_match(sensorName, locationReg);
++ });
++
++ if (findInventoryPath == inventoryMap.end())
++ {
++ std::cerr << "Inventory not found for " << sensorName << "\n";
++ return "";
++ }
++ return findInventoryPath->second;
++}
++
+ void createSensors(
+ boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
+ boost::container::flat_map<std::string, std::shared_ptr<HwmonTempSensor>>&
+@@ -501,11 +614,20 @@ void createSensors(
+ }
+ else
+ {
++ std::string inventoryPath{};
++ const auto& foundIfaces =
++ sensorTargetMap.find(getLastNameFromIface(sensorType));
++ if (foundIfaces != sensorTargetMap.end())
++ {
++ getInventory(dbusConnection, foundIfaces->second);
++ inventoryPath = findInventoryPath(sensorName);
++ }
++
+ sensor = std::make_shared<HwmonTempSensor>(
+ *hwmonFile, sensorType, objectServer, dbusConnection,
+ io, sensorName, std::move(sensorThresholds),
+ thisSensorParameters, pollRate, interfacePath,
+- readState, i2cDev);
++ readState, i2cDev, inventoryPath);
+ sensor->setupRead();
+ }
+ }
+@@ -560,11 +682,21 @@ void createSensors(
+ }
+ else
+ {
++ std::string inventoryPath{};
++ const auto& foundIfaces = sensorTargetMap.find(
++ getLastNameFromIface(sensorType));
++ if (foundIfaces != sensorTargetMap.end())
++ {
++ getInventory(dbusConnection, foundIfaces->second);
++ inventoryPath = findInventoryPath(sensorName);
++ }
++
+ sensor = std::make_shared<HwmonTempSensor>(
+ *hwmonFile, sensorType, objectServer,
+ dbusConnection, io, sensorName,
+ std::move(thresholds), thisSensorParameters,
+- pollRate, interfacePath, readState, i2cDev);
++ pollRate, interfacePath, readState, i2cDev,
++ inventoryPath);
+ sensor->setupRead();
+ }
+ }
+diff --git a/src/HwmonTempSensor.cpp b/src/HwmonTempSensor.cpp
+index 180c0c8..f92b8ab 100644
+--- a/src/HwmonTempSensor.cpp
++++ b/src/HwmonTempSensor.cpp
+@@ -23,6 +23,7 @@
+ #include <sdbusplus/asio/object_server.hpp>
+
+ #include <charconv>
++#include <filesystem>
+ #include <iostream>
+ #include <istream>
+ #include <limits>
+@@ -31,6 +32,8 @@
+ #include <utility>
+ #include <vector>
+
++namespace fs = std::filesystem;
++
+ // Temperatures are read in milli degrees Celsius, we need degrees Celsius.
+ // Pressures are read in kilopascal, we need Pascals. On D-Bus for Open BMC
+ // we use the International System of Units without prefixes.
+@@ -48,7 +51,8 @@ HwmonTempSensor::HwmonTempSensor(
+ std::vector<thresholds::Threshold>&& thresholdsIn,
+ const struct SensorParams& thisSensorParameters, const float pollRate,
+ const std::string& sensorConfiguration, const PowerState powerState,
+- const std::shared_ptr<I2CDevice>& i2cDevice) :
++ const std::shared_ptr<I2CDevice>& i2cDevice,
++ const std::string& inventoryPath) :
+ Sensor(boost::replace_all_copy(sensorName, " ", "_"),
+ std::move(thresholdsIn), sensorConfiguration, objectType, false,
+ false, thisSensorParameters.maxValue, thisSensorParameters.minValue,
+@@ -73,11 +77,26 @@ HwmonTempSensor::HwmonTempSensor(
+ name,
+ interface);
+ }
+- association = objectServer.add_interface("/xyz/openbmc_project/sensors/" +
+- thisSensorParameters.typeName +
+- "/" + name,
+- association::interface);
+- setInitialProperties(thisSensorParameters.units);
++
++ if (inventoryPath.empty())
++ {
++ association = objectServer.add_interface(
++ "/xyz/openbmc_project/sensors/" + thisSensorParameters.typeName +
++ "/" + name,
++ association::interface);
++ setInitialProperties(thisSensorParameters.units);
++ }
++ else
++ {
++ setInitialProperties(thisSensorParameters.units);
++ association = objectServer.add_interface(
++ "/xyz/openbmc_project/sensors/" + thisSensorParameters.typeName +
++ "/" + name,
++ association::interface);
++ std::string chassisPath(
++ fs::path(sensorConfiguration).parent_path().string());
++ setInventoryAssociation(association, inventoryPath, chassisPath);
++ }
+ }
+
+ bool HwmonTempSensor::isActive()
+diff --git a/src/HwmonTempSensor.hpp b/src/HwmonTempSensor.hpp
+index d45dafd..f3937f4 100644
+--- a/src/HwmonTempSensor.hpp
++++ b/src/HwmonTempSensor.hpp
+@@ -33,7 +33,8 @@ class HwmonTempSensor :
+ const struct SensorParams& thisSensorParameters,
+ float pollRate, const std::string& sensorConfiguration,
+ PowerState powerState,
+- const std::shared_ptr<I2CDevice>& i2cDevice);
++ const std::shared_ptr<I2CDevice>& i2cDevice,
++ const std::string& inventoryPath);
+ ~HwmonTempSensor() override;
+ void setupRead(void);
+ void activate(const std::string& newPath,
+diff --git a/src/Utils.cpp b/src/Utils.cpp
+index d659d37..1a92add 100644
+--- a/src/Utils.cpp
++++ b/src/Utils.cpp
+@@ -850,3 +850,16 @@ std::vector<std::unique_ptr<sdbusplus::bus::match_t>>
+ }
+ return setupPropertiesChangedMatches(bus, {types}, handler);
+ }
++
++std::string getLastNameFromIface(const std::string& iface)
++{
++ std::regex itemIfaceReg("^(.*?\\.)*(.*?)$");
++ std::smatch match;
++
++ if (std::regex_search(iface, match, itemIfaceReg))
++ {
++ return match[match.size() - 1];
++ }
++
++ return "";
++}
+diff --git a/src/Utils.hpp b/src/Utils.hpp
+index d7a08db..714c108 100644
+--- a/src/Utils.hpp
++++ b/src/Utils.hpp
+@@ -391,3 +391,5 @@ std::vector<std::unique_ptr<sdbusplus::bus::match_t>>
+ setupPropertiesChangedMatches(
+ sdbusplus::asio::connection& bus, std::span<const char* const> types,
+ const std::function<void(sdbusplus::message_t&)>& handler);
++
++std::string getLastNameFromIface(const std::string& iface);
+--
+2.35.1
+
diff --git a/recipes-phosphor/sensors/dbus-sensors_%.bbappend b/recipes-phosphor/sensors/dbus-sensors_%.bbappend
index ae21eae..9c91791 100644
--- a/recipes-phosphor/sensors/dbus-sensors_%.bbappend
+++ b/recipes-phosphor/sensors/dbus-sensors_%.bbappend
@@ -10,6 +10,7 @@
file://0102-RedfishSensor-Network-error-handling-teardown.patch \
file://0103-RedfishSensor-Intentionally-drop-reported-stale.patch \
file://0104-RedfishSensor-Port-feature-and-other-cleanups.patch \
+ file://0010-dbus-sensors-Creating-association-between-inventory-.patch \
"
# gBMC NVMe-MI support begins