Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package lsvpd for openSUSE:Factory checked 
in at 2026-01-08 15:26:34
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lsvpd (Old)
 and      /work/SRC/openSUSE:Factory/.lsvpd.new.1928 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "lsvpd"

Thu Jan  8 15:26:34 2026 rev:66 rq:1325832 version:1.7.17

Changes:
--------
--- /work/SRC/openSUSE:Factory/lsvpd/lsvpd.changes      2023-10-05 
20:03:55.832398164 +0200
+++ /work/SRC/openSUSE:Factory/.lsvpd.new.1928/lsvpd.changes    2026-01-08 
15:28:05.198706406 +0100
@@ -1,0 +2,17 @@
+Wed Jan  7 17:31:58 UTC 2026 - Michal Suchanek <[email protected]>
+
+- Update to version 1.7.17 (jsc#PED-14567, jsc#PED-14550)
+  * Add NVME-MI support for VPD data collection from NVMe devices.
+  * Enhance tools to display custom VPD for Nvidia-specific adapters.
+  * Enhance tools to display FC, CCIN VPD information for Spyre cards.
+  * Enhance lscfg verbose output to include Feature Code field display.
+  * Resolve critical race conditions that could cause SQLite logic errors
+    under concurrent access.
+- Update to version 1.7.16
+  * Add support for Spyre device VPD data collection and retention
+  * Enhance lsvpd to use IPS output for serial numbers and machine type/model
+  * Add systemd service support for vpdupdate
+  * Improve SCSI page code detection and fix comparison logic
+  * Add device information display in tuple format
+
+-------------------------------------------------------------------

Old:
----
  lsvpd-1.7.15.tar.gz

New:
----
  lsvpd-1.7.17.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ lsvpd.spec ++++++
--- /var/tmp/diff_new_pack.yoJL7W/_old  2026-01-08 15:28:05.946737446 +0100
+++ /var/tmp/diff_new_pack.yoJL7W/_new  2026-01-08 15:28:05.946737446 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package lsvpd
 #
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           lsvpd
-Version:        1.7.15
+Version:        1.7.17
 Release:        0
 Summary:        VPD Hardware Inventory Utilities for Linux
 License:        GPL-2.0-or-later
@@ -30,6 +30,7 @@
 BuildRequires:  libtool
 BuildRequires:  libvpd-devel
 BuildRequires:  sg3_utils-devel
+BuildRequires:  systemd-rpm-macros
 BuildRequires:  zlib-devel
 Requires:       /bin/sed
 Recommends:     hwdata
@@ -46,8 +47,7 @@
 levels.
 
 %prep
-%setup -q
-%autopatch -p1
+%autosetup -p1
 
 %build
 export CFLAGS="%{optflags} -UPCI_IDS 
-DPCI_IDS='\"%{_datadir}/hwdata/pci.ids\"' -UUSB_IDS 
-DUSB_IDS='\"%{_datadir}/hwdata/usb.ids\"'"
@@ -76,12 +76,21 @@
        rm %{_sysconfdir}/udev/rules.d/99-lsvpd.disabled
 fi
 
+%pre
+%service_add_pre vpdupdate.service
+
 %post
 if [ -d %{_localstatedir}/lib/lsvpd ] ; then
   rm -rf %{_localstatedir}/lib/lsvpd
 fi
 %{_sbindir}/vpdupdate
-exit 0
+%service_add_post vpdupdate.service
+
+%preun
+%service_del_preun vpdupdate.service
+
+%postun
+%service_del_postun vpdupdate.service
 
 %files
 %license COPYING
@@ -93,4 +102,5 @@
 %endif
 %attr (755,root,root) %{_sbindir}/*
 %{_mandir}/*/*
+%{_unitdir}/vpdupdate.service
 

++++++ lsvpd-1.7.15.tar.gz -> lsvpd-1.7.17.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/.travis.yml new/lsvpd-1.7.17/.travis.yml
--- old/lsvpd-1.7.15/.travis.yml        2023-09-28 16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/.travis.yml        2025-12-02 08:20:31.000000000 +0100
@@ -8,7 +8,7 @@
 env:
     matrix:
     - RUN_ON_CONTAINER=fedora-37
-    - RUN_ON_CONTAINER=ubuntu-23.04
+    - RUN_ON_CONTAINER=ubuntu-24.04
 
 install:
     - docker build --pull -t ${RUN_ON_CONTAINER} -f 
lsvpd-ci/Dockerfile-${RUN_ON_CONTAINER} .
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/ChangeLog new/lsvpd-1.7.17/ChangeLog
--- old/lsvpd-1.7.15/ChangeLog  2023-09-28 16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/ChangeLog  2025-12-02 08:20:31.000000000 +0100
@@ -1,3 +1,19 @@
+1.7.17: Sathvika Vasireddy <[email protected]> - Tue Dec 2 2025
+- Add NVME-MI support for VPD data collection from NVMe devices.
+- Enhance tools to display custom VPD for Nvidia-specific adapters.
+- Enhance tools to display FC, CCIN VPD information for Spyre cards.
+- Enhance lscfg verbose output to include Feature Code field display.
+- Resolve critical race conditions that could cause SQLite logic errors
+under concurrent access.
+
+1.7.16: Mahesh Salgaonkar <[email protected]> - Fri Jul 11 2025
+- Add support for Spyre device VPD data collection and retention
+- Enhance lsvpd to use IPS output for serial numbers and machine type/model
+- Add systemd service support for vpdupdate
+- Improve SCSI page code detection and fix comparison logic
+- Add device information display in tuple format
+- Update CI infrastructure (Ubuntu 24.04, fix Fedora 37 builds)
+
 1.7.15: Mahesh Salgaonkar <[email protected]> - Mon Sep 25 2023
 - Display additional VPD information for NVMe devices
 - Report correct microcode information for I/O devices
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/Makefile.am new/lsvpd-1.7.17/Makefile.am
--- old/lsvpd-1.7.15/Makefile.am        2023-09-28 16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/Makefile.am        2025-12-02 08:20:31.000000000 +0100
@@ -60,6 +60,10 @@
        man/lsvpd.8 \
        man/vpdupdate.8
 
+# Systemd service file
+systemdunitdir = $(prefix)/lib/systemd/system
+systemdunit_DATA = vpdupdate.service
+
 vpdupdate_LDADD = -lz -lstdc++ -lvpd_cxx
 if SGUTIL1
 vpdupdate_LDADD += -lsgutils
@@ -90,4 +94,4 @@
                ${DESTDIR}/etc/lsvpd/cpu_mod_conv.conf
 
 EXTRA_DIST = $(man8_MANS) bootstrap.sh scsi_templates.conf cpu_mod_conv.conf \
-            nvme_templates.conf
+            nvme_templates.conf vpdupdate.service.in
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/configure.ac 
new/lsvpd-1.7.17/configure.ac
--- old/lsvpd-1.7.15/configure.ac       2023-09-28 16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/configure.ac       2025-12-02 08:20:31.000000000 +0100
@@ -3,7 +3,7 @@
 AC_PREREQ([2.69])
 
 #base
-AC_INIT([lsvpd],[1.7.15],[[email protected],[email protected]])
+AC_INIT([lsvpd],[1.7.17],[[email protected],[email protected]])
 AC_CONFIG_HEADER([config/config.h])
 AC_SUBST(DATE, [`date`])
 AC_CONFIG_MACRO_DIR([m4])
@@ -70,5 +70,5 @@
 AC_CHECK_FUNCS([memmove memset mkdir socket strdup strerror strtol uname 
strchr strndup])
 
 #finished
-AC_CONFIG_FILES([Makefile lsvpd.spec])
+AC_CONFIG_FILES([Makefile lsvpd.spec vpdupdate.service])
 AC_OUTPUT
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/lsvpd-ci/Dockerfile-fedora-37 
new/lsvpd-1.7.17/lsvpd-ci/Dockerfile-fedora-37
--- old/lsvpd-1.7.15/lsvpd-ci/Dockerfile-fedora-37      2023-09-28 
16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/lsvpd-ci/Dockerfile-fedora-37      2025-12-02 
08:20:31.000000000 +0100
@@ -1,6 +1,6 @@
 FROM fedora:37
 
 RUN dnf -y install gcc-g++ make sg3_utils-devel zlib-devel iprutils
-RUN dnf -y install libvpd-devel librtas-devel libtool automake rpm-build git
+RUN dnf -y install libvpd-devel librtas-devel libtool automake rpm-build git 
systemd-rpm-macros
 COPY . /build/
 WORKDIR /build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/lsvpd-ci/Dockerfile-ubuntu-23.04 
new/lsvpd-1.7.17/lsvpd-ci/Dockerfile-ubuntu-23.04
--- old/lsvpd-1.7.15/lsvpd-ci/Dockerfile-ubuntu-23.04   2023-09-28 
16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/lsvpd-ci/Dockerfile-ubuntu-23.04   1970-01-01 
01:00:00.000000000 +0100
@@ -1,8 +0,0 @@
-FROM ubuntu:23.04
-ENV DEBIAN_FRONTEND    noninteractive
-RUN apt-get update -qq
-RUN apt-get update -qq && apt-get install -y automake libtool git make g++ 
libstdc++-10-dev pkg-config
-RUN apt-get update -qq && apt-get install -y libsqlite3-dev zlib1g-dev 
iprutils libsgutils2-dev
-RUN apt-get update -qq && apt-get install -y librtas-dev librtasevent-dev 
libvpd-dev
-COPY . /build/
-WORKDIR /build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/lsvpd-ci/Dockerfile-ubuntu-24.04 
new/lsvpd-1.7.17/lsvpd-ci/Dockerfile-ubuntu-24.04
--- old/lsvpd-1.7.15/lsvpd-ci/Dockerfile-ubuntu-24.04   1970-01-01 
01:00:00.000000000 +0100
+++ new/lsvpd-1.7.17/lsvpd-ci/Dockerfile-ubuntu-24.04   2025-12-02 
08:20:31.000000000 +0100
@@ -0,0 +1,8 @@
+FROM ubuntu:24.04
+ENV DEBIAN_FRONTEND    noninteractive
+RUN apt-get update -qq
+RUN apt-get update -qq && apt-get install -y automake libtool git make g++ 
libstdc++-10-dev pkg-config
+RUN apt-get update -qq && apt-get install -y libsqlite3-dev zlib1g-dev 
iprutils libsgutils2-dev
+RUN apt-get update -qq && apt-get install -y librtas-dev librtasevent-dev 
libvpd-dev
+COPY . /build/
+WORKDIR /build
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/lsvpd-ci/build-ubuntu-23.04.sh 
new/lsvpd-1.7.17/lsvpd-ci/build-ubuntu-23.04.sh
--- old/lsvpd-1.7.15/lsvpd-ci/build-ubuntu-23.04.sh     2023-09-28 
16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/lsvpd-ci/build-ubuntu-23.04.sh     1970-01-01 
01:00:00.000000000 +0100
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-set -uo pipefail
-set -e
-set -vx
-MAKE_J=$(grep -c processor /proc/cpuinfo)
-
-./bootstrap.sh
-./configure
-make -j $MAKE_J
-make -j $MAKE_J check
-make dist-gzip
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/lsvpd-ci/build-ubuntu-24.04.sh 
new/lsvpd-1.7.17/lsvpd-ci/build-ubuntu-24.04.sh
--- old/lsvpd-1.7.15/lsvpd-ci/build-ubuntu-24.04.sh     1970-01-01 
01:00:00.000000000 +0100
+++ new/lsvpd-1.7.17/lsvpd-ci/build-ubuntu-24.04.sh     2025-12-02 
08:20:31.000000000 +0100
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+set -uo pipefail
+set -e
+set -vx
+MAKE_J=$(grep -c processor /proc/cpuinfo)
+
+./bootstrap.sh
+./configure
+make -j $MAKE_J
+make -j $MAKE_J check
+make dist-gzip
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/lsvpd.spec.in 
new/lsvpd-1.7.17/lsvpd.spec.in
--- old/lsvpd-1.7.15/lsvpd.spec.in      2023-09-28 16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/lsvpd.spec.in      2025-12-02 08:20:31.000000000 +0100
@@ -26,6 +26,8 @@
 BuildRequires: sg3_utils-devel
 BuildRequires: automake
 BuildRequires: libtool
+BuildRequires:  systemd-rpm-macros
+Requires:       systemd
 
 Recommends:     hwdata
 
@@ -55,10 +57,20 @@
 %{__make} install DESTDIR=$RPM_BUILD_ROOT
 
 %post
+# Post-install script for vpdupdate
+# Always enable the service
+systemctl -q enable vpdupdate.service >/dev/null 2>&1 || :
+systemctl daemon-reload >/dev/null 2>&1 || :
+
 %{_sbindir}/vpdupdate &
 # Ignore the vpdupdate failures and enforce a success
 exit 0
 
+%preun
+# Pre-uninstall script for vpdupdate
+systemctl -q disable vpdupdate.service >/dev/null 2>&1 || :
+systemctl daemon-reload >/dev/null 2>&1 || :
+
 %files
 %defattr(-,root,root,-)
 %doc COPYING README
@@ -76,9 +88,26 @@
 %config %{_sysconfdir}/lsvpd/nvme_templates.conf
 %config %{_sysconfdir}/lsvpd/cpu_mod_conv.conf
 %dir %{_sysconfdir}/lsvpd
+%{_unitdir}/vpdupdate.service
 
 
 %changelog
+* Tue Dec 2 2025 - Sathvika Vasireddy <[email protected]> - 1.7.17
+- Add NVME-MI support for VPD data collection from NVMe devices.
+- Enhance tools to display custom VPD for Nvidia-specific adapters.
+- Enhance tools to display FC, CCIN VPD information for Spyre cards.
+- Enhance lscfg verbose output to include Feature Code field display.
+- Resolve critical race conditions that could cause SQLite logic errors
+  under concurrent access.
+
+* Fri Jul 11 2025 - Mahesh Salgaonkar <[email protected]> - 1.7.16
+- Add support for Spyre device VPD data collection and retention
+- Enhance lsvpd to use IPS output for serial numbers and machine type/model
+- Add systemd service support for vpdupdate
+- Improve SCSI page code detection and fix comparison logic
+- Add device information display in tuple format
+- Update CI infrastructure (Ubuntu 24.04, fix Fedora 37 builds)
+
 * Mon Sep 25 2023 - Mahesh Salgaonkar <[email protected]> - 1.7.15
 - Display additional VPD information for NVMe devices
 - Report correct microcode information for I/O devices
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/src/include/sysfstreecollector.hpp 
new/lsvpd-1.7.17/src/include/sysfstreecollector.hpp
--- old/lsvpd-1.7.15/src/include/sysfstreecollector.hpp 2023-09-28 
16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/src/include/sysfstreecollector.hpp 2025-12-02 
08:20:31.000000000 +0100
@@ -67,6 +67,10 @@
        /* NVME f1h log page VPD size */
        #define NVME_VPD_INFO_SIZE              1024
 
+       /* NVMe-MI Receive Opcode */
+       #define NVME_MI_CMD_RECEIVE     0x1E
+       #define NVME_MI_VPD_DATA_LEN    256
+
        /**
         * SysFSTreeCollector contains the logic for device discovery and VPD
         * retrieval from /sys and sg_utils.
@@ -125,6 +129,7 @@
                        // nvme specific
                        int load_nvme_templates(const string& filename);
                        int interpretNVMEf1hLogPage(Component *fillMe, char 
*data);
+                       int interpretNVMEMiLog(Component *fillMe, char *data);
 
                        // scsi specific
                        int load_scsi_templates(const string&);
@@ -139,6 +144,8 @@
                        void process_template(Component *fillMe, string 
*deviceType,
                                                                        char 
*data, int dataSize, string *format,
                                                                        int 
pageCode);
+                       void fillSpyreVpd(Component* fillMe);
+                       string read11S(unsigned char* bar0_ptr);
                        int collectNvmeVpd(Component *fillMe, int device_fd);
 
                        int collectVpd(Component *fillMe, int device_fd, bool 
limitSCSISize);
@@ -204,6 +211,17 @@
                         */
                        void fillPCIDev( Component* fillMe, const string& 
sysDir );
 
+                       /** Set custom VPD fields for specific devices based on
+                        * device/vendor IDs.
+                        * @param fillMe: Component to populate with custom VPD 
data
+                        * @param vendorId: PCI vendor ID
+                        * @param deviceId: PCI device ID
+                        * @param subVendorId: PCI subsystem vendor ID
+                        * @param subDeviceId: PCI subsystem device ID
+                        */
+                       void setCustomVPDFields(Component* fillMe, int 
vendorId, int deviceId,
+                                       int subVendorId, int subDeviceId);
+
                        /**
                         * Fill the Manufacturer name and Product description 
if the
                         * vendor and product ids are available under /sys.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lsvpd-1.7.15/src/internal/sys_interface/devicetreecollector.cpp 
new/lsvpd-1.7.17/src/internal/sys_interface/devicetreecollector.cpp
--- old/lsvpd-1.7.15/src/internal/sys_interface/devicetreecollector.cpp 
2023-09-28 16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/src/internal/sys_interface/devicetreecollector.cpp 
2025-12-02 08:20:31.000000000 +0100
@@ -1411,26 +1411,51 @@
                if( val != "" )
                        sys->mArch.setValue( val, 100, __FILE__, __LINE__ );
 
-               val = getAttrValue( "/proc/device-tree", "model" );
+               val = getAttrValue( "/proc/device-tree", "ibm,vendor-model" );
                if( val != "" )
                {
                        sys->mMachineType.setValue( val, 80, __FILE__, __LINE__ 
);
-                       if ( !val.compare (0, 4, "IBM,") )
+                       if ( !val.compare (0, 4, "IPS,") )
                                sys->mMachineModel.setValue( val.substr( 4 ), 
80, __FILE__, __LINE__ );
                        else
                                sys->mMachineModel.setValue( val, 80, __FILE__, 
__LINE__ );
                }
+               else
+               {
+                       val = getAttrValue( "/proc/device-tree", "model" );
+                       if( val != "")
+                       {
+                               sys->mMachineType.setValue( val, 80, __FILE__, 
__LINE__ );
+                               if ( !val.compare (0, 4, "IBM,") )
+                                       sys->mMachineModel.setValue( 
val.substr( 4 ), 80, __FILE__, __LINE__ );
+                               else
+                                       sys->mMachineModel.setValue( val, 80, 
__FILE__, __LINE__ );
+                       }
+               }
 
-               val = getAttrValue("/proc/device-tree", "system-id" );
+               val = getAttrValue("/proc/device-tree", "ibm,vendor-system-id" 
);
                if( val != "" )
                {
                        sys->mSerialNum1.setValue( val, 80, __FILE__, __LINE__ 
);
                        sys->mProcessorID.setValue( val, 80, __FILE__, __LINE__ 
);
-                       if( !val.compare(0, 4, "IBM,") )
+                       if( !val.compare(0, 4, "IPS,") )
                                sys->mSerialNum2.setValue( val.substr( 6 ), 80, 
__FILE__, __LINE__ );
                        else
                                sys->mSerialNum2.setValue( val, 80 , __FILE__, 
__LINE__ );
                }
+               else
+               {
+                       val = getAttrValue("/proc/device-tree", "system-id" );
+                       if( val != "")
+                       {
+                               sys->mSerialNum1.setValue( val, 80, __FILE__, 
__LINE__ );
+                               sys->mProcessorID.setValue( val, 80, __FILE__, 
__LINE__ );
+                               if( !val.compare(0, 4, "IBM,") )
+                                       sys->mSerialNum2.setValue( val.substr( 
6 ), 80, __FILE__, __LINE__ );
+                               else
+                                       sys->mSerialNum2.setValue( val, 80 , 
__FILE__, __LINE__ );
+                       }
+               }
 
                val = getAttrValue("/proc/device-tree", "ibm,partition-uuid" );
                if( val != "" )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lsvpd-1.7.15/src/internal/sys_interface/sysfs_SCSI_Fill.cpp 
new/lsvpd-1.7.17/src/internal/sys_interface/sysfs_SCSI_Fill.cpp
--- old/lsvpd-1.7.15/src/internal/sys_interface/sysfs_SCSI_Fill.cpp     
2023-09-28 16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/src/internal/sys_interface/sysfs_SCSI_Fill.cpp     
2025-12-02 08:20:31.000000000 +0100
@@ -70,6 +70,9 @@
 #include <cstring>
 #include <limits.h>
 
+#include <vector>
+#include <algorithm>
+
 extern "C"
 {
 #include <scsi/sg_cmds.h>
@@ -1102,6 +1105,100 @@
                return 0;
        }
 
+
+int SysFSTreeCollector::interpretNVMEMiLog(Component *fillMe, char *data)
+{
+       string val;
+       val = strdupTrim(data + 4, 40);
+       if (val.length() > 0)
+               setVPDField(fillMe, "ID", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 44, 12);
+       if (val.length() > 0)
+               setVPDField(fillMe, "PN", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 56, 10);
+       if (val.length() > 0)
+               setVPDField(fillMe, "EC", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 66, 12);
+       if (val.length() > 0)
+               setVPDField(fillMe, "FN", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 78, 12);
+       if (val.length() > 0)
+               setVPDField(fillMe, "AN", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 90, 4);
+       if (val.length() > 0)
+               setVPDField(fillMe, "FC", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 94, 4);
+       if (val.length() > 0)
+               setVPDField(fillMe, "CC", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 98, 8);
+       if (val.length() > 0)
+               setVPDField(fillMe, "SN", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 106, 8);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z0", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 114, 4);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z1", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 118, 10);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z2", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 128, 12);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z3", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 140, 1);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z4", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 141, 2);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z5", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 143, 8);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z6", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 151, 3);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z7", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 154, 5);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z8", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 159, 2);
+       if (val.length() > 0)
+               setVPDField(fillMe, "Z9", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 161, 4);
+       if (val.length() > 0)
+               setVPDField(fillMe, "ZA", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 165, 4);
+       if (val.length() > 0)
+               setVPDField(fillMe, "ZB", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 169, 2);
+       if (val.length() > 0)
+               setVPDField(fillMe, "ZC", val, __FILE__, __LINE__);
+
+       val = strdupTrim(data + 171, 20);
+       if (val.length() > 0)
+               setVPDField(fillMe, "MN", val, __FILE__, __LINE__);
+       return 0;
+}
+
         int SysFSTreeCollector::interpretNVMEf1hLogPage(Component *fillMe, 
char *data)
        {
                int eof[50]; // version 0001 has 24 ',' separated fields, more 
for future
@@ -1190,6 +1287,27 @@
        }
 
 
+int nvme_read_mi_vpd(int device_fd, void *buf)
+{
+       struct nvme_admin_cmd cmd = {0};
+
+       cmd.opcode = NVME_MI_CMD_RECEIVE;
+       cmd.nsid = 0;
+       cmd.addr = (__u64)(uintptr_t) buf;
+       cmd.data_len = NVME_MI_VPD_DATA_LEN;
+
+       cmd.cdw10 = 0x804;
+       cmd.cdw11 = 0x5;
+       cmd.cdw13 = NVME_MI_VPD_DATA_LEN;
+
+       int rc = ioctl(device_fd, NVME_IOCTL_ADMIN_CMD, &cmd);
+
+       if (rc == 0)
+               return 0;
+
+       return -1;
+}
+
         int nvme_read_vpd(int device_fd, void *buf)
        {
                int rc, ret = -1;
@@ -1229,14 +1347,19 @@
        {
                int rc;
                char data[NVME_VPD_INFO_SIZE];
+               char mi_data[NVME_MI_VPD_DATA_LEN];
 
                rc = nvme_read_vpd(device_fd, data);
-               if (rc)
+               if (rc == 0) {
+                       rc = interpretNVMEf1hLogPage(fillMe, data);
                        return rc;
+               }
 
-               rc = interpretNVMEf1hLogPage(fillMe, data);
-               if (rc)
+               rc = nvme_read_mi_vpd(device_fd, mi_data);
+               if (rc == 0) {
+                       rc = interpretNVMEMiLog(fillMe, mi_data);
                        return rc;
+               }
 
                return 0;
        }
@@ -1275,6 +1398,7 @@
                int pageCodeInt;
                int rc;
                char vendor[32], model[32], firmware[32];
+               std::vector<int> byteValues;
 
                if ((fillMe->devBus.getValue()).empty()) {
                        if ((fillMe->getDevClass() == "nvme")) {
@@ -1367,6 +1491,19 @@
 
                }
 
+               /* Check supported page codes using page code 0
+                * evpd set
+                */
+
+               memset(buffer, '\0', MAXBUFSIZE);
+               len = doSGQuery(device_fd, buffer, MAXBUFSIZE, 1, 0, 0);
+               if (len > 0) {
+                       for (int i = 4; i < len; ++i) {
+                               int byteValue = (int)buffer[i];
+                               byteValues.push_back(byteValue);
+                       }
+               }
+
                /* SG Utils Inquiry
                 * Can device be quieried?  Initial Query
                 */
@@ -1413,7 +1550,7 @@
                                pageTemp = 
retrievePageTemplate(devTemplate->format_str, i);
                                retrievePageCode(pageTemp, pageCode, 
pageFormat);
 
-                               if( pageCode == "0xDIAG" )
+                               if( pageCode == "DIAG" )
                                {
                                        /*
                                         * Special case to retrieve Physical 
locations using
@@ -1428,8 +1565,9 @@
                                                evpd = 0;
                                        else evpd = 1;
 
-                                       len = doSGQuery( device_fd, buffer, 
MAXBUFSIZE, evpd,
-                                                        pageCodeInt, 
RECEIVE_DIAGNOSTIC );
+                                       if (std::find(byteValues.begin(), 
byteValues.end(), pageCodeInt) != byteValues.end())
+                                               len = doSGQuery( device_fd, 
buffer, MAXBUFSIZE, evpd,
+                                                                pageCodeInt, 
RECEIVE_DIAGNOSTIC );
                                }
                                else
                                {
@@ -1447,7 +1585,8 @@
                                        // Query this page
                                        memset(buffer, '\0', MAXBUFSIZE);
                                        //                                      
coutd << "Attempting query, evpd = " << evpd << ", pageCodeInt = " << 
pageCodeInt <<endl;
-                                       len = doSGQuery(device_fd, buffer, 
MAXBUFSIZE, evpd, pageCodeInt, 0);
+                                       if (std::find(byteValues.begin(), 
byteValues.end(), pageCodeInt) != byteValues.end())
+                                               len = doSGQuery(device_fd, 
buffer, MAXBUFSIZE, evpd, pageCodeInt, 0);
                                }
 
                                if (len < 0) {
@@ -1468,9 +1607,10 @@
                                 printf("%d:%c  ", s, buffer[s]);
                                 printf("\n");*/
 
-                               //Interpret this page
-                               interpretPage(fillMe, buffer, len, pageCodeInt, 
&pageFormat,
-                                             subtype, &subtypeDS);
+                               //Interpret only the pages that are supported
+                               if (std::find(byteValues.begin(), 
byteValues.end(), pageCodeInt) != byteValues.end())
+                                       interpretPage(fillMe, buffer, len, 
pageCodeInt, &pageFormat,
+                                                     subtype, &subtypeDS);
                        }
                }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/lsvpd-1.7.15/src/internal/sys_interface/sysfstreecollector.cpp 
new/lsvpd-1.7.17/src/internal/sys_interface/sysfstreecollector.cpp
--- old/lsvpd-1.7.15/src/internal/sys_interface/sysfstreecollector.cpp  
2023-09-28 16:02:21.000000000 +0200
+++ new/lsvpd-1.7.17/src/internal/sys_interface/sysfstreecollector.cpp  
2025-12-02 08:20:31.000000000 +0100
@@ -35,7 +35,10 @@
 #include <libvpd-2/debug.hpp>
 #include <libvpd-2/logger.hpp>
 #include <libvpd-2/lsvpd.hpp>
+#include <libvpd-2/vpddbenv.hpp>
 
+#include <linux/vfio.h>
+#include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
@@ -61,10 +64,20 @@
 #include <fstream>
 #include <sstream>
 #include <iomanip>
+#include <algorithm>
+
+#define MNIMI_INST 0x080280
+#define ECID1 0x080588
+#define MNIMI_DATA 0x0802C0
+
+std::map<std::string, bool> g_deviceAccessible;
 
 extern int errno;
 
 using namespace std;
+using namespace lsvpd;
+
+extern VpdDbEnv *spyreDb;
 
 namespace lsvpd
 {
@@ -1407,6 +1420,290 @@
                return 0;
        }
 
+       void SysFSTreeCollector::fillSpyreVpd(Component* fillMe)
+       {
+               string path;
+               Logger l;
+               char device_id[16] = {0};
+               int container_fd = -1, group_fd = -1, device_fd = -1;
+               int iommu_type = -1;
+               char path_buf[256] = {0}, group_path[256] = {0};
+               char* group_name = nullptr;
+               ssize_t len = 0;
+               uint64_t eeprom_data = 0;
+               struct vfio_region_info reg = {0};
+               void* bar0_mem = nullptr;
+               unsigned char* bar0_ptr = nullptr;
+               ostringstream ss;
+               uint8_t eeprom_res_manu = 0;
+               uint8_t boot_version = 0;
+               string boot_version_str;
+               string partNumber;
+
+               /* Read device ID */
+               path = fillMe->getID() + "/device";
+               ifstream device_stream(path.c_str());
+               if (!device_stream)
+                       return;
+
+               device_stream.getline(device_id, sizeof(device_id));
+               device_stream.close();
+
+               /* Check if the device is Spyre (device ID 0x06a7 or 0x06a8) */
+               if (strcmp(device_id, "0x06a7") != 0 && strcmp(device_id, 
"0x06a8") != 0)
+                       return;
+
+               l.log("Confirmed Spyre device " + fillMe->getID() + " with ID: 
" + string(device_id), LOG_INFO);
+
+               /* Open VFIO container */
+               container_fd = open("/dev/vfio/vfio", O_RDWR);
+               if (container_fd < 0) {
+                       l.log("Failed to open VFIO container /dev/vfio/vfio for 
" + fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_ERR);
+                       return;
+               }
+               l.log("Successfully opened VFIO container for " + 
fillMe->getID(), LOG_DEBUG);
+
+               /* Check for IOMMU Support */
+               if (ioctl(container_fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_IOMMU) 
== 1) {
+                       iommu_type = VFIO_TYPE1_IOMMU;
+                       l.log("Using VFIO_TYPE1_IOMMU for " + fillMe->getID(), 
LOG_DEBUG);
+               } else if (ioctl(container_fd, VFIO_CHECK_EXTENSION, 
VFIO_SPAPR_TCE_IOMMU) == 1) {
+                       iommu_type = VFIO_SPAPR_TCE_IOMMU;
+                       l.log("Using VFIO_SPAPR_TCE_IOMMU for " + 
fillMe->getID(), LOG_DEBUG);
+               }
+               else {
+                       l.log("No supported IOMMU type found for " + 
fillMe->getID(), LOG_ERR);
+                       close(container_fd);
+                       return;
+               }
+
+               /* Get IOMMU group */
+               snprintf(path_buf, sizeof(path_buf), "%s/iommu_group", 
fillMe->getID().c_str());
+               len = readlink(path_buf, group_path, sizeof(group_path) - 1);
+               if (len < 0) {
+                       l.log("Failed to read IOMMU group symlink " + 
string(path_buf) + " for " + fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_ERR);
+                       close(container_fd);
+                       return;
+               }
+
+               group_path[len] = '\0';
+               group_name = strrchr(group_path, '/');
+               if (!group_name) {
+                       l.log("Failed to extract group name from path: " + 
string(group_path) + " for " + fillMe->getID(), LOG_ERR);
+                       close(container_fd);
+                       return;
+               }
+               group_name++;
+
+               l.log("Found IOMMU group: " + string(group_name) + " for " + 
fillMe->getID(), LOG_DEBUG);
+
+               /* Open the VFIO Group */
+               snprintf(path_buf, sizeof(path_buf), "/dev/vfio/%s", 
group_name);
+               group_fd = open(path_buf, O_RDWR);
+
+               g_deviceAccessible[fillMe->getID()] = true;
+               if (group_fd < 0) {
+
+                       Logger l;
+                       l.log("Failed to open VFIO group " + string(path_buf) + 
" for " + fillMe->getID(), LOG_ERR);
+                       g_deviceAccessible[fillMe->getID()] = false;
+
+                       if (spyreDb != nullptr) {
+                               l.log("Attempting to use cached data from 
spyreDb for " + fillMe->getID(), LOG_INFO);
+
+                               Component* spyreComp = 
spyreDb->fetch(fillMe->getID());
+                               if (spyreComp != nullptr) {
+                                       l.log("Found cached component data for 
" + fillMe->getID(), LOG_DEBUG);
+
+                                       if 
(!spyreComp->mManufacturer.dataValue.empty()) {
+                                               
fillMe->mManufacturer.setValue(spyreComp->mManufacturer.getValue(), 80, 
__FILE__, __LINE__);
+                                       }
+                                       if 
(!spyreComp->mModel.dataValue.empty()) {
+                                               
fillMe->mModel.setValue(spyreComp->mModel.getValue(), 80, __FILE__, __LINE__);
+                                       }
+                                       if 
(!spyreComp->mEngChangeLevel.dataValue.empty()) {
+                                               
fillMe->mEngChangeLevel.setValue(spyreComp->mEngChangeLevel.getValue(), 80, 
__FILE__, __LINE__);
+                                       }
+                                       if 
(!spyreComp->mSerialNumber.dataValue.empty()) {
+                                               
fillMe->mSerialNumber.setValue(spyreComp->mSerialNumber.getValue(), 80, 
__FILE__, __LINE__);
+                                       }
+                                       if 
(!spyreComp->mPartNumber.dataValue.empty()) {
+                                               
fillMe->mPartNumber.setValue(spyreComp->mPartNumber.getValue(), 80, __FILE__, 
__LINE__);
+                                       }
+                                       if 
(!spyreComp->mPhysicalLocation.dataValue.empty()) {
+                                               
fillMe->mPhysicalLocation.setValue(spyreComp->mPhysicalLocation.getValue(), 80, 
__FILE__, __LINE__);
+                                       }
+                                       if 
(!spyreComp->mDescription.dataValue.empty()) {
+                                               
fillMe->mDescription.setValue(spyreComp->mDescription.getValue(), 80, __FILE__, 
__LINE__);
+                                       }
+                                       if 
(!spyreComp->mCDField.dataValue.empty()) {
+                                               
fillMe->mCDField.setValue(spyreComp->mCDField.getValue(), 80, __FILE__, 
__LINE__);
+                                       }
+                                       if 
(!spyreComp->mFirmwareLevel.dataValue.empty()) {
+                                               
fillMe->mFirmwareLevel.setValue(spyreComp->mFirmwareLevel.getValue(), 80, 
__FILE__, __LINE__);
+                                       }
+
+                               delete spyreComp;
+                               l.log("Successfully populated component data 
from cache for " + fillMe->getID(), LOG_INFO);
+                               } else {
+                                       l.log("No cached component data found 
in spyreDb for " + fillMe->getID(), LOG_WARNING);
+                               }
+                       }
+
+                       close(group_fd);
+                       close(container_fd);
+                       return;
+               }
+
+               /* Check group status */
+               struct vfio_group_status group_status = {.argsz = 
sizeof(group_status)};
+               if (ioctl(group_fd, VFIO_GROUP_GET_STATUS, &group_status) < 0 ||
+                               !(group_status.flags & 
VFIO_GROUP_FLAGS_VIABLE)) {
+                       l.log("Failed to get VFIO group status for " + 
fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_ERR);
+                       close(group_fd);
+                       close(container_fd);
+                       return;
+               }
+
+               /* Add group to container */
+               if (ioctl(group_fd, VFIO_GROUP_SET_CONTAINER, &container_fd) < 
0) {
+                       l.log("Failed to add VFIO group to container for " + 
fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_ERR);
+                       close(group_fd);
+                       close(container_fd);
+                       return;
+               }
+               l.log("Successfully added VFIO group to container for " + 
fillMe->getID(), LOG_DEBUG);
+
+               /* Set IOMMU type */
+               if (iommu_type != -1 && ioctl(container_fd, VFIO_SET_IOMMU, 
iommu_type) < 0) {
+                       l.log("Failed to set IOMMU type " + 
to_string(iommu_type) + " for " + fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_ERR);
+                       close(group_fd);
+                       close(container_fd);
+                       return;
+               }
+
+               l.log("Successfully set IOMMU type for " + fillMe->getID(), 
LOG_DEBUG);
+
+               device_fd = ioctl(group_fd, VFIO_GROUP_GET_DEVICE_FD,
+                               
fillMe->getID().substr(fillMe->getID().rfind("/") + 1).c_str());
+
+               if (device_fd < 0) {
+                       l.log("Failed to get device FD for " + fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_ERR);
+                       close(group_fd);
+                       close(container_fd);
+                       return;
+               }
+
+               l.log("Successfully obtained device FD for " + fillMe->getID(), 
LOG_DEBUG);
+
+               /* Configure BAR0 region info */
+               reg.argsz = sizeof(reg);
+               reg.index = VFIO_PCI_BAR0_REGION_INDEX;
+
+               /* Get BAR0 Info */
+               if (ioctl(device_fd, VFIO_DEVICE_GET_REGION_INFO, &reg) < 0) {
+                       l.log("Failed to get BAR0 region info for " + 
fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_ERR);
+                       close(device_fd);
+                       close(group_fd);
+                       close(container_fd);
+                       return;
+               }
+
+               /* Map BAR0 */
+               bar0_mem = mmap(NULL, reg.size, PROT_READ | PROT_WRITE, 
MAP_SHARED, device_fd, reg.offset);
+               if (bar0_mem == MAP_FAILED) {
+                       l.log("Failed to map BAR0 memory for " + 
fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_ERR);
+                       close(device_fd);
+                       close(group_fd);
+                       close(container_fd);
+                       return;
+               }
+
+               l.log("Successfully mapped BAR0 memory for " + fillMe->getID(), 
LOG_DEBUG);
+
+               /* Read data from mapped memory */
+               bar0_ptr = (unsigned char*)bar0_mem;
+
+               *((uint64_t*)(bar0_ptr + MNIMI_INST)) = 0xa101f801200b1467;
+               usleep(50000);
+
+               eeprom_data = *((uint64_t*)(bar0_ptr + MNIMI_DATA));
+
+               /* Set Manufacturer based on EEPROM data */
+               eeprom_res_manu = eeprom_data & 0xFF;
+               if (eeprom_res_manu == 0xff || eeprom_res_manu == 0x0) {
+                       fillMe->mManufacturer.setValue("Samsung", 80, __FILE__, 
__LINE__);
+               } else if (eeprom_res_manu == 0x1) {
+                       fillMe->mManufacturer.setValue("Micron", 80, __FILE__, 
__LINE__);
+               }
+
+               /* Set Firmware Level */
+               boot_version = (eeprom_data >> 56) & 0xFF;
+               fillMe->mFirmwareLevel.setValue(to_string(boot_version), 80, 
__FILE__, __LINE__);
+
+               string eeprom11s_sn = read11S(bar0_ptr);
+               if (eeprom11s_sn.length() >= 7) {
+                       partNumber = eeprom11s_sn.substr(0, 7);
+                       fillMe->mPartNumber.setValue(partNumber, 100, __FILE__, 
__LINE__);
+               }
+
+               fillMe->mEngChangeLevel.setValue(eeprom11s_sn.substr(10, 1), 
100, __FILE__, __LINE__);
+               fillMe->mSerialNumber.setValue(eeprom11s_sn.substr(7), 100, 
__FILE__, __LINE__);
+
+                /* Clean up memory mapping */
+                if (munmap(bar0_mem, reg.size) < 0) {
+                       l.log("Warning: Failed to unmap BAR0 memory for " + 
fillMe->getID() +
+                                       ", errno: " + to_string(errno) + " (" + 
strerror(errno) + ")", LOG_WARNING);
+               } else {
+                       l.log("Successfully unmapped BAR0 memory for " + 
fillMe->getID(), LOG_DEBUG);
+               }
+
+               /* Clean up file descriptors */
+               close(device_fd);
+               close(group_fd);
+               close(container_fd);
+
+               l.log("Successfully completed fillSpyreVpd for " + 
fillMe->getID(), LOG_INFO);
+       }
+
+       string SysFSTreeCollector::read11S(unsigned char* bar0_ptr)
+       {
+               string result;
+               char buffer[8];
+
+               *((uint64_t*)(bar0_ptr + MNIMI_INST)) = 0xa101e001200b1467;
+               usleep(50000);
+               uint64_t eeprom11s_0 = *((uint64_t*)(bar0_ptr + MNIMI_DATA));
+
+               *((uint64_t*)(bar0_ptr + MNIMI_INST)) = 0xa101e801200b1467;
+               usleep(50000);
+               uint64_t eeprom11s_1 = *((uint64_t*)(bar0_ptr + MNIMI_DATA));
+
+               *((uint64_t*)(bar0_ptr + MNIMI_INST)) = 0xa101f001200b1467;
+               usleep(50000);
+               uint64_t eeprom11s_2 = *((uint64_t*)(bar0_ptr + MNIMI_DATA)) & 
0xFFFFFF0000000000;
+
+               uint64_t values[3] = {eeprom11s_0, eeprom11s_1, eeprom11s_2};
+
+               for (int val_idx = 0; val_idx < 3; val_idx++) {
+                       for (int byte_idx = 0; byte_idx < 8; byte_idx++) {
+                               buffer[byte_idx] = (values[val_idx] >> (56 - 
byte_idx * 8)) & 0xFF;
+                       }
+                       result.append(buffer, 8);
+               }
+
+               result.erase(remove(result.begin(), result.end(), '\0'), 
result.end());
+               return result;
+       }
+
        void SysFSTreeCollector::fillPciNvmeVpd( Component* fillMe )
        {
                int device_fd;
@@ -1423,6 +1720,76 @@
                return;
        }
 
+       void SysFSTreeCollector::setCustomVPDFields(Component* fillMe,
+                       int vendorId, int deviceId,
+                       int subVendorId, int subDeviceId)
+       {
+               int sysPciId = (vendorId << 16) | deviceId;
+               int subSysPciId = (subVendorId << 16) | subDeviceId;
+
+               switch(sysPciId) {
+                       case 0x101406A7:
+                       case 0x101406A8:
+                               fillMe->mFeatureCode.setValue("ECSE", 95, 
__FILE__, __LINE__);
+                               fillMe->addDeviceSpecific( "CC", "Customer Card 
ID Number", "2E1F", 95);
+                               break;
+                       case 0x15b31021: // Nvidia ConnectX-7 PF
+                               switch (subSysPciId) {
+                                       case 0x15b30030:  // CX7 Fractal PF
+                                               
fillMe->mPartNumber.setValue("03JP126", 95, __FILE__, __LINE__);
+                                               
fillMe->mEngChangeLevel.setValue("P45996", 95, __FILE__, __LINE__);
+                                               
fillMe->mFRU.setValue("03JP128", 95, __FILE__, __LINE__);
+                                               
fillMe->mFeatureCode.setValue("EAPC / EAPD", 95, __FILE__, __LINE__);
+                                               fillMe->addDeviceSpecific("CE", 
"CCIN Extension", "EC26", 95);
+                        
fillMe->mDescription.setValue(fillMe->mDescription.getValue() +
+                            " PCIe4 4-Port 25Gb/10Gb RoCE SFP28 Adapter", 95, 
__FILE__, __LINE__);
+                                               break;
+
+                                       case 0x15b30022:  // CX7 Onion Creek PF
+                                               
fillMe->mPartNumber.setValue("03JP134", 95, __FILE__, __LINE__);
+                                               
fillMe->mEngChangeLevel.setValue("P45997", 95, __FILE__, __LINE__);
+                                               
fillMe->mFRU.setValue("03JP136", 95, __FILE__, __LINE__);
+                                               
fillMe->mFeatureCode.setValue("EAPE / EAPF", 95, __FILE__, __LINE__);
+                                               fillMe->addDeviceSpecific("CE", 
"CCIN Extension", "EC2E", 95);
+                        
fillMe->mDescription.setValue(fillMe->mDescription.getValue() +
+                            " PCIe5 2-Port 100GbE RoCE QSFP56 Adapter", 95, 
__FILE__, __LINE__);
+                                               break;
+
+                                       default:
+                                               break;
+                               }
+                               break;
+
+                       case 0x15b3101e:  // NVIDIA ConnectX-7 SR-IOV (Vendor: 
15b3, Device: 101e)
+                               switch (subSysPciId) {
+                                       case 0x15b30030:  // CX7 Fractal SR-IOV
+                                               
fillMe->mPartNumber.setValue("03JP126", 95, __FILE__, __LINE__);
+                                               
fillMe->mEngChangeLevel.setValue("P45996", 95, __FILE__, __LINE__);
+                                               
fillMe->mFRU.setValue("03JP128", 95, __FILE__, __LINE__);
+                                               
fillMe->mFeatureCode.setValue("EAPC / EAPD", 95, __FILE__, __LINE__);
+                                               fillMe->addDeviceSpecific("CE", 
"CCIN Extension", "EC26", 95);
+                        
fillMe->mDescription.setValue(fillMe->mDescription.getValue() +
+                            " PCIe4 4-Port 25Gb/10Gb RoCE SFP28 Adapter", 95, 
__FILE__, __LINE__);
+                                               break;
+
+                                       case 0x15b30022:  // CX7 Onion Creek 
SR-IOV
+                                               
fillMe->mPartNumber.setValue("03JP134", 95, __FILE__, __LINE__);
+                                               
fillMe->mEngChangeLevel.setValue("P45997", 95, __FILE__, __LINE__);
+                                               
fillMe->mFRU.setValue("03JP136", 95, __FILE__, __LINE__);
+                                               
fillMe->mFeatureCode.setValue("EAPE / EAPF", 95, __FILE__, __LINE__);
+                                               fillMe->addDeviceSpecific("CE", 
"CCIN Extension", "EC2E", 95);
+                        
fillMe->mDescription.setValue(fillMe->mDescription.getValue() +
+                            " PCIe5 2-Port 100GbE RoCE QSFP56 Adapter", 95, 
__FILE__, __LINE__);
+                                               break;
+
+                                       default:
+                                               break;
+                               }
+                               break;
+                       }
+       }
+
+
        /* Parse VPD file */
        void SysFSTreeCollector::fillPciDevVpd( Component* fillMe )
        {
@@ -1490,7 +1857,6 @@
                                                fillMe->mManufacturer.setValue( 
val,
                                                        50, __FILE__, __LINE__ 
);
 
-                                       os << hex << setw( 4 ) << setfill( '0' 
) << manID;
                                }
                        }
                        else
@@ -1500,7 +1866,6 @@
                                        fillMe->mManufacturer.setValue( val, 50,
                                                        __FILE__, __LINE__ );
 
-                               os << hex << setw( 4 ) << setfill( '0' ) << 
subMan;
                        }
 
                        // Fill Device Model
@@ -1509,7 +1874,6 @@
                        {
                                if( manID != UNKNOWN_ID )
                                {
-                                       os << hex << setw( 4 ) << setfill( '0' 
)<< devID;
                                        val = mPciTable->getName( manID, devID 
);
                                        if( val != "" )
                                                fillMe->mModel.setValue( val, 
80,
@@ -1518,7 +1882,6 @@
                        }
                        else
                        {
-                               os << hex << setw( 4 ) << setfill( '0' )<< 
subID;
                                val = mPciTable->getName( manID, devID, subID );
                                if( val != "" )
                                        fillMe->mModel.setValue( val, 80, 
__FILE__, __LINE__ );
@@ -1527,7 +1890,12 @@
                                        fillMe->mDescription.setValue( val, 80, 
__FILE__, __LINE__ );
                        }
 
-                       if( os.str( ) != "ffffffff" )
+                       os << "(" << hex << setw(4) << setfill('0') << manID << 
","
+                               << hex << setw(4) << setfill('0') << devID << 
"), ("
+                               << hex << setw(4) << setfill('0') << subMan << 
","
+                               << hex << setw(4) << setfill('0') << subID << 
")";
+
+                       if( os.str( ) != "(ffff,ffff), (ffff,ffff)" )
                                fillMe->mCDField.setValue( os.str( ), 100, 
__FILE__, __LINE__ );
                }
 
@@ -1536,9 +1904,15 @@
                /* Fill PCI device VPD info */
                fillPciDevVpd(fillMe);
 
+               /* Set custom VPD fields for specific devices */
+               setCustomVPDFields(fillMe, manID, devID, subMan, subID);
+
                /* Fill NVME device VPD info using f1h log page */
                fillPciNvmeVpd(fillMe);
 
+               /* Fill Spyre information */
+               fillSpyreVpd(fillMe);
+
                // Read the pci config file for Device Specific (YC)
                os.str( "" );
                os << fillMe->sysFsNode.dataValue << "/config";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/src/internal/updater.cpp 
new/lsvpd-1.7.17/src/internal/updater.cpp
--- old/lsvpd-1.7.15/src/internal/updater.cpp   2023-09-28 16:02:21.000000000 
+0200
+++ new/lsvpd-1.7.17/src/internal/updater.cpp   2025-12-02 08:20:31.000000000 
+0100
@@ -25,6 +25,7 @@
 #include <string>
 #include <iostream>
 #include <sstream>
+#include <map>
 
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE // for getopt_long
@@ -43,6 +44,7 @@
 #include <fcntl.h>
 #include <zlib.h>
 #include <cstdlib>
+#include <syslog.h>
 
 #include <libvpd-2/component.hpp>
 #include <libvpd-2/system.hpp>
@@ -72,12 +74,99 @@
 const string DB_FILENAME( "vpd.db" );
 const string BASE( "/sys/bus" );
 
+/* Global variables for spyre.db access */
+const string SPYRE_DB_FILENAME("spyre.db");
+VpdDbEnv *spyreDb = nullptr;
+VpdDbEnv::UpdateLock *spyreDbLock = nullptr;
+
 bool isRoot(void);
 VpdDbEnv *db;
 VpdDbEnv::UpdateLock *dblock;
 
 string env = DB_DIR, file = DB_FILENAME;
 
+extern std::map<std::string, bool> g_deviceAccessible;
+
+/**
+ * @brief Cleans up resources allocated by __spyreDbInit()
+ */
+void __spyreDbFini()
+{
+       if (spyreDb != NULL) {
+               try {
+                       delete spyreDb;
+                       spyreDbLock = NULL;
+               } catch (VpdException & ve) {  }
+       } /* if */
+       spyreDb = NULL;
+}
+
+/**
+ * @brief Cleanup Spyre-related files
+ */
+void cleanupSpyreFiles(const string& env)
+{
+
+        string spyreDbPath = env + "/" + SPYRE_DB_FILENAME;
+        if (access(spyreDbPath.c_str(), F_OK) == 0) {
+                unlink(spyreDbPath.c_str());
+        }
+
+        __spyreDbFini();
+
+        string spyreLockPath = env + "/" + SPYRE_DB_FILENAME + "-updatelock";
+        if (access(spyreLockPath.c_str(), F_OK) == 0) {
+                unlink(spyreLockPath.c_str());
+        }
+}
+
+/**
+ * @brief Print process hierarchy
+ */
+void logProcessHierarchy() {
+
+       pid_t current_pid = getpid();
+       string proc_path, process_name;
+       vector<string> hierarchy;
+       string hierarchy_str;
+
+       while (true) {
+               proc_path = "/proc/" + to_string(current_pid) + "/status";
+               ifstream status_file(proc_path);
+               string line, process_name;
+               pid_t parent_pid = -1;
+
+               if (status_file.is_open()) {
+                       while (getline(status_file, line)) {
+                               if (line.rfind("Name:", 0) == 0)
+                                       process_name = line.substr(6);
+                               else if (line.rfind("PPid:", 0) == 0) {
+                                       parent_pid = stoi(line.substr(5));
+                                       break;
+                               }
+                       }
+                       status_file.close();
+               }
+
+               hierarchy.push_back(process_name);
+
+               if (parent_pid <= 0 || parent_pid == current_pid)
+                       break;
+
+               current_pid = parent_pid;
+       }
+
+       for (auto it = hierarchy.rbegin(); it != hierarchy.rend(); ++it) {
+               if (!hierarchy_str.empty()) {
+                       hierarchy_str += " -> ";
+               }
+               hierarchy_str += *it;
+       }
+
+       syslog(LOG_INFO, "Process Hierarchy: %s", hierarchy_str.c_str());
+
+}
+
 int main( int argc, char** argv )
 {
        char opts [] = "vahsp:";
@@ -154,9 +243,11 @@
        Logger l;
 
        l.log( "vpdupdate: Constructing full devices database", LOG_NOTICE );
+       logProcessHierarchy();
        rc = initializeDB( limitSCSISize );
 
        __lsvpdFini();
+       cleanupSpyreFiles(env);
        return rc;
 }
 
@@ -320,9 +411,89 @@
 }
 
 /**
+ * @brief Check if a component is a Spyre device
+ */
+bool isSpyreDevice(Component* comp)
+{
+       if (!comp)
+               return false;
+
+       string id = comp->getID();
+       string deviceFile = id + "/device";
+       ifstream deviceStream(deviceFile.c_str());
+       if (deviceStream) {
+               string deviceId;
+               getline(deviceStream, deviceId);
+               deviceStream.close();
+
+               if (deviceId == "0x06a7" || deviceId == "0x06a8") {
+                       Logger l;
+                       l.log("Found Spyre device at: " + id, LOG_NOTICE);
+                       return true;
+               }
+       }
+       return false;
+}
+
+/**
+ * @brief Extract spyre device data from existing vpd.db
+ */
+void extractSpyreData()
+{
+       if (spyreDb == NULL) {
+               return;
+       }
+
+       string vpdDbPath = env + "/" + file;
+       if (access(vpdDbPath.c_str(), F_OK) != 0) {
+               return;
+       }
+
+       VpdDbEnv::UpdateLock* mainLock = new VpdDbEnv::UpdateLock(env, file, 
true);
+       VpdDbEnv mainDb(*mainLock);
+
+       vector<string> allKeys = mainDb.getKeys();
+       for (const string& key : allKeys) {
+               if (key.empty() || key == "/sys/bus") {
+                       continue;
+               }
+
+               Component* comp = mainDb.fetch(key);
+               if (comp) {
+                       if (isSpyreDevice(comp)) {
+                               spyreDb->store(comp);
+                       }
+                       delete comp;
+               }
+       }
+}
+
+/**
+ * @brief Initializes spyre database access.
+ * @return 0 on success, -1 on failure
+ */
+int __spyreDbInit()
+{
+       string spyreFullPath = env + "/" + SPYRE_DB_FILENAME;
+       __spyreDbFini();
+
+       spyreDbLock = new VpdDbEnv::UpdateLock(env, SPYRE_DB_FILENAME, false);
+
+       if (access(spyreFullPath.c_str(), F_OK) == 0) {
+               unlink(spyreFullPath.c_str());
+       }
+
+       spyreDb = new VpdDbEnv(*spyreDbLock);
+       if (spyreDb == NULL)
+               return -1;
+       else
+               return 0;
+}
+
+/**
  * Method does the initial population of the vpd db, this should only
  * be done once at boot time or any time that a user wishes to start with
- * a new db.
+ * a new db. And, handles spyre.db population with spyre devices.
  */
 int initializeDB( bool limitSCSI )
 {
@@ -334,6 +505,19 @@
                return -1;
 
        string fullPath = env + "/" + file;
+       string spyreFullPath = env + "/" + SPYRE_DB_FILENAME;
+
+       if (__spyreDbInit() != 0) {
+               Logger l;
+               l.log("Failed to initialize spyre database.", LOG_ERR);
+               return -1;
+       }
+
+       if (access(fullPath.c_str(), F_OK) == 0) {
+               Logger l;
+               l.log("Extracting Spyre data from existing vpd.db", LOG_NOTICE);
+               extractSpyreData();
+       }
 
        lock = new VpdDbEnv::UpdateLock(env, file, false);
        removeOldArchiveDB( );
@@ -348,6 +532,7 @@
        if ( ret != 0 ) {
                Logger l;
                l.log( "Could not allocate memory for the VPD database.", 
LOG_ERR);
+               __spyreDbFini();
                return ret;
        }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/src/output/lscfg.cpp 
new/lsvpd-1.7.17/src/output/lscfg.cpp
--- old/lsvpd-1.7.15/src/output/lscfg.cpp       2023-09-28 16:02:21.000000000 
+0200
+++ new/lsvpd-1.7.17/src/output/lscfg.cpp       2025-12-02 08:20:31.000000000 
+0100
@@ -337,7 +337,7 @@
 
                        if( val != "" )
                        {
-                               os << " (" << val << ")";
+                               os << " " << val;
                        }
 
                        if(     val.length( ) + root->getDescription( ).length( 
) <= 35 )
@@ -399,6 +399,10 @@
                                        printField( root->getSerialNumberHN( ),
                                                    root->getSerialNumber( ) );
 
+                if( root->getFeatureCode( ) != "" )
+                    printField( root->getFeatureCodeHN( ),
+                            root->getFeatureCode( ) );
+
                                if( root->getFirmwareVersion( ) != "" )
                                        printField( root->getFirmwareVersionHN( 
),
                                                    root->getFirmwareVersion( ) 
);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/src/output/lsvpd.cpp 
new/lsvpd-1.7.17/src/output/lsvpd.cpp
--- old/lsvpd-1.7.15/src/output/lsvpd.cpp       2023-09-28 16:02:21.000000000 
+0200
+++ new/lsvpd-1.7.17/src/output/lsvpd.cpp       2025-12-02 08:20:31.000000000 
+0100
@@ -169,7 +169,7 @@
                                string val = string( root->getCD( ) );
 
                                if ( val != "" )
-                                       cout << " (" << val << ")";
+                                       cout << " " << val;
 
                                cout << endl;
                        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lsvpd-1.7.15/vpdupdate.service.in 
new/lsvpd-1.7.17/vpdupdate.service.in
--- old/lsvpd-1.7.15/vpdupdate.service.in       1970-01-01 01:00:00.000000000 
+0100
+++ new/lsvpd-1.7.17/vpdupdate.service.in       2025-12-02 08:20:31.000000000 
+0100
@@ -0,0 +1,21 @@
+[Unit]
+Description=Vpdupdate Service
+# Run early but after basic system is ready
+After=sysinit.target
+After=systemd-modules-load.service
+# Run before containers can start
+Before=podman.service
+Before=docker.service
+Before=rtas_errd.service
+
+[Service]
+Type=oneshot
+# Log when service is triggered
+ExecStartPre=/bin/echo "vpdupdate.service triggered."
+ExecStart=/usr/sbin/vpdupdate
+ExecStartPost=/bin/echo "vpdupdate.service completed."
+RemainAfterExit=yes
+TimeoutStartSec=60
+
+[Install]
+WantedBy=basic.target

Reply via email to