From 68a4d47bdfbe4ebcc048e9f08862e2639bbec2e7 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Date: Thu, 21 Sep 2017 18:34:20 +0530 Subject: [PATCH 3/3] lsmcode: Support firmware info on BMC based Power9 system P9 system supports various service processor stack like FSP based system, SMC system, AMI with OpenBMC stack etc. Some of these systems supports full ipmi stack and few other systems doesn't (at least for now). lsmcode uses ipmi interface (ipmitool fru) to get firmware information. It fails on some of the P9 system where we donot have full ipmi support. Recently we added support in OPAL to export firmware information via device tree for P9 BMC systems (/ibm,firmware-versions node). Even recent hostboot firmware on P8 BMC system exports these information via mini device tree. This patch enables lsmcode to collect firmware information via device tree. Sample output on Power9 system after applying this patch: ./lsmcode Version of System Firmware : Product Name : OpenPOWER Firmware Product Version : open-power-firestone-v1.17-101-g1c57f18-dirty Product Extra : occ-site_local-akshay-28f2cec-dirty Product Extra : skiboot-5.6.0-158-ga1e0a047b2a0 Product Extra : buildroot-2017.02.2-7-g23118ce Product Extra : capp-ucode-9c73e9f Product Extra : petitboot-v1.4.3-pa6836f6 Product Extra : hostboot-binaries-711147e Product Extra : machine-xml-2494a43 Product Extra : hostboot-695bd89 Product Extra : linux-4.11.6-openpower1-p1e59f24 root@fir02:/home/ankit/lsvpd# ./lsmcode --All sys0!system: open-power-firestone-v1.17-101-g1c57f18-dirty sg0 0:0:0:0 sda !ST1000NX0313.BE33 Sample output on Power8 system after applying this patch: ./lsmcode Version of System Firmware : Product Name : OpenPOWER Firmware Product Version : open-power-firestone-v1.17-101-g1c57f18-dirty Product Extra : buildroot-2017.02.2-7-g23118ce Product Extra : skiboot-5.6.0-158-ga1e0a047b2a0 Product Extra : hostboot-695bd89 Product Extra : linux-4.11.6-openpower1-p1e59f24 Product Extra : petitboot-v1.4.3-pa6836f6 Product Extra : machine-xml-2494a43 Product Extra : occ-site_local-28f2cec-dirty root@fir:lsvpd# ./lsmcode --All sys0!system: open-power-firestone-v1.17-101-g1c57f18-dirty sg0 0:0:0:0 sda !ST1000NX0313.BE33 Signed-off-by: Ankit Kumar [Updated description, Changed "product version" property name - Vasant] Signed-off-by: Vasant Hegde --- src/output/lsmcode.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 129 insertions(+), 6 deletions(-) diff --git a/src/output/lsmcode.cpp b/src/output/lsmcode.cpp index a8d9f11..c96a176 100644 --- a/src/output/lsmcode.cpp +++ b/src/output/lsmcode.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ #define _GNU_SOURCE // for getopt_long #endif +#include #include #include #include @@ -50,6 +52,9 @@ #include #include +/* Firmware information device tree node on PowerNV system */ +#define FW_VERSION_DT_NODE DEVTREEPATH"/ibm,firmware-versions/" + /* IPMI tool */ #define CMD_IPMITOOL "ipmitool" @@ -152,6 +157,117 @@ parse_err: return string(); } +static string read_dt_property(const string& path, const string& attrName) +{ + struct stat info; + string fullPath; + string ret = ""; + + ostringstream os; + os << path << "/" << attrName; + fullPath = os.str( ); + + if (stat(fullPath.c_str( ), &info) != 0) { + ostringstream os; + if (errno != ENOENT) { + os << "Error statting " << fullPath << ", errno: " << errno; + Logger().log( os.str( ), LOG_ERR ); + } + return ret; + } + + ifstream attrIn; + attrIn.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); + try { + attrIn.open( fullPath.c_str( ) ); + } + catch (std::ifstream::failure e) { + ostringstream os; + os << "Error opening " << fullPath; + Logger().log(os.str( ), LOG_WARNING); + return ret; + } + + if (attrIn) { + char * strBuf; + try + { + strBuf = new char [ info.st_size + 1 ]; + } + catch (exception& e) + { + return ret; + } + memset( strBuf, '\0', info.st_size + 1 ); + attrIn.read( strBuf, info.st_size ); + ret = strBuf; + attrIn.close( ); + delete [] strBuf; + } + return ret; +} + +/* Get system firmware information on BMC based system via device tree */ +static string bmc_get_fw_dt_info(void) +{ + string fwdata, tag, val, prod_ver = "", prod_extra = ""; + struct dirent *ent; + DIR * pDBdir = NULL; + /* Properties to ignore from DT/ibm,firmware-versions node */ + const char *ignore_dt[] = {"phandle", "name"}; + int i; + bool ignore_dt_flag = false; + + pDBdir = opendir(FW_VERSION_DT_NODE); + if (pDBdir == NULL) { + stringstream os; + os << "Error opening directory " << FW_VERSION_DT_NODE << endl; + Logger().log(os.str( ), LOG_ERR); + return string(""); + } + + fwdata = string("\n Product Name : OpenPOWER Firmware\n"); + while ((ent = readdir( pDBdir )) != NULL) { + string fname = ent->d_name; + for (i = 0; i < (int)(sizeof(ignore_dt)/sizeof(char *)); i++) { + if (fname.compare(string(ignore_dt[i])) == 0) { + ignore_dt_flag = true; + break; + } + } + + if (ignore_dt_flag == true) { + ignore_dt_flag = false; + continue; + } + + /* + * Looks like some system has open-power property and some + * other has "IBM" property. Lets use one of these property + * for Product Version. + */ + if (fname.compare("IBM") == 0 || fname.compare("open-power") == 0) { + if (prod_ver == string("")) { + tag = string(" Product Version : "); + prod_ver = read_dt_property(string(FW_VERSION_DT_NODE), fname); + if (prod_ver == string("")) + continue; + prod_ver = tag + fname + string("-") + prod_ver + string("\n"); + continue; + } + } + + tag = string(" Product Extra : \t"); + val = read_dt_property(string(FW_VERSION_DT_NODE), fname); + if (val == string("")) + continue; + prod_extra = prod_extra + tag + fname + string("-") + val + string("\n"); + } + + fwdata = fwdata + prod_ver + prod_extra; + return fwdata; +} + /* Get production version */ static string bmc_get_product_version(string fwData) { @@ -181,13 +297,20 @@ bool printSystem( const vector& leaves ) * based system. Hence we don't store this information in VPD db. */ if (PlatformCollector::isBMCBasedSystem()) { - string ipmitool = get_ipmitool_path(); - if (ipmitool.empty()) - return false; + string fwData; + if (!access(FW_VERSION_DT_NODE, F_OK | R_OK)) { + fwData = bmc_get_fw_dt_info(); + if (fwData.empty()) + return false; + } else { + string ipmitool = get_ipmitool_path(); + if (ipmitool.empty()) + return false; - string fwData = bmc_get_fw_fru_info(ipmitool); - if (fwData.empty()) - return false; + fwData = bmc_get_fw_fru_info(ipmitool); + if (fwData.empty()) + return false; + } if ( all ) { string pVersion = bmc_get_product_version(fwData); -- 2.14.3