Use Device Locator as DIMM Object Path if Enabled
Setting feature to use deviceLocator (ServiceLabel) as the DIMM
object path creates by SMBIOS.
Tested:
busctl introspect shows all DIMMs match their deviceLocator aka LocationCode
Google-Bug-Id: 324938090
Change-Id: Ifd1e9acc9086f700d791de5e4425eba3257d839f
Signed-off-by: Edward Lee <edwarddl@google.com>
(cherry picked from commit ba7d303981c38488b8cebd69056cef9aef92ba5c)
diff --git a/recipes-phosphor/smbios/smbios-mdr/0001-Use-Device-Locator-as-DIMM-Object-Path-if-Enabled.patch b/recipes-phosphor/smbios/smbios-mdr/0001-Use-Device-Locator-as-DIMM-Object-Path-if-Enabled.patch
new file mode 100644
index 0000000..1e393fb
--- /dev/null
+++ b/recipes-phosphor/smbios/smbios-mdr/0001-Use-Device-Locator-as-DIMM-Object-Path-if-Enabled.patch
@@ -0,0 +1,191 @@
+From 90b2b1588f0794199ae99239eb3952ead16a3df4 Mon Sep 17 00:00:00 2001
+From: Edward Lee <edwarddl@google.com>
+Date: Tue, 13 Feb 2024 22:39:04 +0000
+Subject: [PATCH] Use Device Locator as DIMM Object Path if Enabled
+
+Adding new feature which uses deviceLocator property as the index for
+DIMM DBus object.
+
+This is to create a stable mapping from dimmId and ServiceLabel for bmcweb.
+
+Tested:
+busctl introspect shows all dimms match their deviceLocator aka LocationCode
+
+Patch Tracking Bug: b/325114650
+Upstream info / review: https://gerrit.openbmc.org/c/openbmc/smbios-mdr/+/69384
+Upstream-Status: Submitted
+Justification:
+Waiting for Review
+
+Signed-off-by: Edward Lee <edwarddl@google.com>
+---
+ include/mdrv2.hpp | 3 ++
+ include/smbios_mdrv2.hpp | 2 ++
+ meson.options | 7 ++++
+ src/mdrv2.cpp | 72 ++++++++++++++++++++++++++++++++++++++++
+ src/meson.build | 4 +++
+ 5 files changed, 88 insertions(+)
+
+diff --git a/include/mdrv2.hpp b/include/mdrv2.hpp
+index 818b0ab..5ccbb49 100644
+--- a/include/mdrv2.hpp
++++ b/include/mdrv2.hpp
+@@ -170,6 +170,9 @@ class MDRV2 :
+ std::vector<boost::container::flat_map<std::string, RecordVariant>>
+ getRecordType(size_t type);
+
++ std::optional<std::string>
++ getDeviceLocatorFromIndex(uint8_t* smbiosTableStorage, int dimmNum);
++
+ private:
+ boost::asio::steady_timer timer;
+
+diff --git a/include/smbios_mdrv2.hpp b/include/smbios_mdrv2.hpp
+index 37e4648..e3f5562 100644
+--- a/include/smbios_mdrv2.hpp
++++ b/include/smbios_mdrv2.hpp
+@@ -172,6 +172,8 @@ struct CpuLinkInfo
+ } __attribute__((packed));
+ #endif
+
++static constexpr const char* motherboardSuffix = "/chassis/motherboard/";
++
+ static constexpr const char* cpuSuffix = "/chassis/motherboard/cpu";
+
+ static constexpr const char* dimmSuffix = "/chassis/motherboard/dimm";
+diff --git a/meson.options b/meson.options
+index 0fc5c2d..ff1baa6 100644
+--- a/meson.options
++++ b/meson.options
+@@ -60,3 +60,10 @@ option(
+ value: '',
+ description: 'Optional suffix for generated D-Bus Inventory object paths'
+ )
++
++option(
++ 'use-device-locator-as-dimm-object-path',
++ type: 'feature',
++ value: 'disabled',
++ description: 'SMBIOS creates DIMM Dbus objects as filepath dimmX. If this feature is enabled, then the deviceLocator index will be the X. If the feature is disabled, the order of dimm in SMBIOS table will be the X.'
++)
+diff --git a/src/mdrv2.cpp b/src/mdrv2.cpp
+index 24337e2..f2d2d5a 100644
+--- a/src/mdrv2.cpp
++++ b/src/mdrv2.cpp
+@@ -20,6 +20,7 @@
+
+ #include <sys/mman.h>
+
++#include <boost/algorithm/string.hpp>
+ #include <phosphor-logging/elog-errors.hpp>
+ #include <sdbusplus/exception.hpp>
+ #include <xyz/openbmc_project/Smbios/MDR_V2/error.hpp>
+@@ -621,6 +622,46 @@ void MDRV2::systemInfoUpdate()
+ dimms.resize(*num);
+ }
+
++#ifdef USE_DEVICE_LOCATOR_AS_DIMM_OBJECT_PATH
++ // Use sorted map to map deviceLocator to index
++ std::map<std::string, unsigned int> deviceLocatorToIndex;
++
++ for (unsigned int index = 0; index < *num; index++)
++ {
++ std::optional<std::string> deviceLocator = getDeviceLocatorFromIndex(
++ smbiosDir.dir[smbiosDirIndex].dataStorage, index);
++
++ if (!deviceLocator)
++ {
++ continue;
++ }
++
++ deviceLocatorToIndex[boost::algorithm::to_lower_copy(*deviceLocator)] =
++ index;
++ }
++
++ unsigned int dimmsIndex = 0;
++
++ for (const auto& [deviceLocator, index] : deviceLocatorToIndex)
++ {
++ std::string path = smbiosInventoryPath + motherboardSuffix +
++ deviceLocator;
++
++ if (dimmsIndex + 1 > dimms.size())
++ {
++ dimms.emplace_back(std::make_unique<phosphor::smbios::Dimm>(
++ *bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage,
++ motherboardPath));
++ }
++ else
++ {
++ dimms[index]->memoryInfoUpdate(
++ smbiosDir.dir[smbiosDirIndex].dataStorage, motherboardPath);
++ }
++
++ ++dimmsIndex;
++ }
++#else
+ for (unsigned int index = 0; index < *num; index++)
+ {
+ std::string path = smbiosInventoryPath + dimmSuffix +
+@@ -637,6 +678,7 @@ void MDRV2::systemInfoUpdate()
+ smbiosDir.dir[smbiosDirIndex].dataStorage, motherboardPath);
+ }
+ }
++#endif
+
+ #endif
+
+@@ -1033,5 +1075,35 @@ std::vector<boost::container::flat_map<std::string, RecordVariant>>
+ return ret;
+ }
+
++std::optional<std::string>
++ MDRV2::getDeviceLocatorFromIndex(uint8_t* smbiosTableStorage, int dimmNum)
++{
++ uint8_t* dataIn = smbiosTableStorage;
++
++ dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
++
++ if (dataIn == nullptr)
++ {
++ return std::nullopt;
++ }
++ for (uint8_t index = 0; index < dimmNum; index++)
++ {
++ dataIn = smbiosNextPtr(dataIn);
++ if (dataIn == nullptr)
++ {
++ return std::nullopt;
++ }
++ dataIn = getSMBIOSTypePtr(dataIn, memoryDeviceType);
++ if (dataIn == nullptr)
++ {
++ return std::nullopt;
++ }
++ }
++
++ auto memoryInfo = reinterpret_cast<struct MemoryInfo*>(dataIn);
++ return positionToString(memoryInfo->deviceLocator, memoryInfo->length,
++ dataIn);
++}
++
+ } // namespace smbios
+ } // namespace phosphor
+diff --git a/src/meson.build b/src/meson.build
+index 4c7fa48..cdbd5d6 100644
+--- a/src/meson.build
++++ b/src/meson.build
+@@ -11,6 +11,10 @@ if get_option('dimm-only-locator').allowed()
+ cpp_args_smbios += ['-DDIMM_ONLY_LOCATOR']
+ endif
+
++if get_option('use-device-locator-as-dimm-object-path').allowed()
++ cpp_args_smbios += ['-DUSE_DEVICE_LOCATOR_AS_DIMM_OBJECT_PATH']
++endif
++
+ grpc_blobs_dep = []
+
+ if get_option('smbios-grpc-blob').allowed()
+--
+2.44.0.rc0.258.g7320e95886-goog
+
diff --git a/recipes-phosphor/smbios/smbios-mdr_%.bbappend b/recipes-phosphor/smbios/smbios-mdr_%.bbappend
index a3eb984..e56d356 100644
--- a/recipes-phosphor/smbios/smbios-mdr_%.bbappend
+++ b/recipes-phosphor/smbios/smbios-mdr_%.bbappend
@@ -13,6 +13,7 @@
file://0001-Add-support-for-google-oem-cpu-link-structure.patch\
file://0001-Add-assoc-trim-path-option-and-Board-match.patch\
file://0001-Clean-up-some-buffer-allocations.patch\
+ file://0001-Use-Device-Locator-as-DIMM-Object-Path-if-Enabled.patch\
"
EXTRA_OEMESON:append:gbmc = " -Ddimm-only-locator=enabled"