@@ -, +, @@ 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 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 --- src/output/lsmcode.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 129 insertions(+), 6 deletions(-) --- a/src/output/lsmcode.cpp +++ a/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); --