commit 50e2fa22298de13fd731488306d2cbd0081730d8 Author: Sathvika Vasireddy Date: Fri Feb 10 14:55:41 2023 +0530 lsvpd: Fill firmware information by recursively looking for firmware specific files within sysfs ID Currently, fillFirmware() is filling firmware information based on the classNode value of a given component. It then looks for firmware specific sysfs files (fw_version, fwrev, firmware_rev), within the classNode path, to set firmware fields accordingly. For components that do not have a classNode value, fillFirmware() does not look for firmware information within the sysfs firmware files, and hence does not set firmware fields. This patch recursively looks for sysfs firmware files within the ID path of a component, and sets the firmware fields accordingly, if not already set. Reported-by: Borislav Stoymirski Signed-off-by: Sathvika Vasireddy Signed-off-by: Mahesh Salgaonkar Tested-by: Borislav Stoymirski diff --git a/src/include/icollector.hpp b/src/include/icollector.hpp index 894dd99..392632f 100644 --- a/src/include/icollector.hpp +++ b/src/include/icollector.hpp @@ -116,6 +116,25 @@ namespace lsvpd virtual ~ICollector( ){} protected: + /** Recursively search for attrName within a given path. + * + * @param path + * Directory path to search for filename. + * + * @param attrName + * Filename to search for. + * + * @return + * Path in which attrName file exists. + * + * If attrName is fwrev, and is found at + * /sys/devices/pci0020:01/0020:01:00.1/host4/scsi_host/host4/fwrev, + * searchFile() will return + * /sys/devices/pci0020:01/0020:01:00.1/host4/scsi_host/host4. + */ + string searchFile( const string& path, + const string& attrName ); + string getAttrValue( const string& path, const string& attrName ); diff --git a/src/internal/sys_interface/icollector.cpp b/src/internal/sys_interface/icollector.cpp index 5c4dccc..7586fe8 100644 --- a/src/internal/sys_interface/icollector.cpp +++ b/src/internal/sys_interface/icollector.cpp @@ -32,11 +32,46 @@ #include #include #include +#include +#include +#include using namespace std; namespace lsvpd { + + string ICollector::searchFile( const string& path, const string& attrName ) + { + DIR *dir; + struct dirent *entry; + + if ((dir = opendir(path.c_str())) == NULL) + return ""; + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_type == DT_DIR) { + // Found a directory, but ignore . and .. + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + string newPath = path + "/" + entry->d_name; + string result = searchFile(newPath, attrName); + if (result != "") { + closedir(dir); + return result; + } + } + else { + if (entry->d_name == attrName) { + closedir(dir); + return path; + } + } + } + closedir(dir); + return ""; + } + /** * Read a device attribute, given dev path and attribute name * @var path Full path to device in sysfs diff --git a/src/internal/sys_interface/sysfstreecollector.cpp b/src/internal/sys_interface/sysfstreecollector.cpp index c5eb71d..03eb7da 100644 --- a/src/internal/sys_interface/sysfstreecollector.cpp +++ b/src/internal/sys_interface/sysfstreecollector.cpp @@ -1837,6 +1837,10 @@ ERROR: void SysFSTreeCollector::fillFirmware( Component* fillMe ) { + string result = ""; + string path = fillMe->getID(); + const string firmwareAttributes[] = {"fw_version", "firmware_rev"}; + const size_t firmwareAttributesSize = sizeof(firmwareAttributes) / sizeof(firmwareAttributes[0]); string classNode = fillMe->getClassNode(); if (classNode.length() > 0) { fillMe->mFirmwareVersion.setValue( getAttrValue( classNode, @@ -1848,6 +1852,23 @@ ERROR: fillMe->mFirmwareVersion.setValue( getAttrValue( classNode, "firmware_rev" ), 30, __FILE__, __LINE__ ); } + + if (fillMe->mFirmwareLevel.dataValue.empty()) { + result = searchFile(path, "fwrev"); + if (!result.empty()) { + fillMe->mFirmwareLevel.setValue( getAttrValue( result, + "fwrev" ), 30, __FILE__, __LINE__ ); + } + } + + for (size_t i = 0; i < firmwareAttributesSize && fillMe->mFirmwareVersion.dataValue.empty(); i++) { + result = searchFile(path, firmwareAttributes[i]); + if (!result.empty()) { + fillMe->mFirmwareVersion.setValue( getAttrValue( result, + firmwareAttributes[i]), 30, __FILE__, __LINE__ ); + break; + } + } } string SysFSTreeCollector::resolveClassPath( const string& path )