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, ®) < 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
