diff --git a/SOURCES/0001-Add-missing-sysfs-entry-string_attr.patch b/SOURCES/0001-Add-missing-sysfs-entry-string_attr.patch new file mode 100644 index 0000000..3804a55 --- /dev/null +++ b/SOURCES/0001-Add-missing-sysfs-entry-string_attr.patch @@ -0,0 +1,52 @@ +From 73707308d0c17fffdad2086686135c9cfd179a60 Mon Sep 17 00:00:00 2001 +From: Dan Callaghan +Date: Tue, 30 Jun 2015 16:08:22 +1000 +Subject: [PATCH] Add missing sysfs::entry::string_attr + Partial patch 73707308d0c17fffdad2086686135c9cfd179a60 + +--- + src/core/sysfs.cc | 14 ++++++++++++++ + src/core/sysfs.h | 2 ++ + 2 files changed, 16 insertions(+) + +diff --git a/src/core/sysfs.cc b/src/core/sysfs.cc +index acc9d00..ed2c600 100644 +--- a/src/core/sysfs.cc ++++ b/src/core/sysfs.cc +@@ -302,6 +302,20 @@ entry entry::parent() const + } + + ++string entry::string_attr(const string & name, const string & def) const ++{ ++ return hw::strip(get_string(This->devpath + "/" + name, def)); ++} ++ ++ ++vector < string > entry::multiline_attr(const string & name) const ++{ ++ vector < string > lines; ++ loadfile(This->devpath + "/" + name, lines); ++ return lines; ++} ++ ++ + vector < entry > sysfs::entries_by_bus(const string & busname) + { + vector < entry > result; +diff --git a/src/core/sysfs.h b/src/core/sysfs.h +index a9dc573..7ceb395 100644 +--- a/src/core/sysfs.h ++++ b/src/core/sysfs.h +@@ -26,6 +26,8 @@ namespace sysfs + string driver() const; + entry parent() const; + string name_in_class(const string &) const; ++ string string_attr(const string & name, const string & def = "") const; ++ vector < string > multiline_attr(const string & name) const; + + struct entry_i * This; + +-- +2.7.3 + diff --git a/SOURCES/0001-Add-pseries-guest-information-711.patch b/SOURCES/0001-Add-pseries-guest-information-711.patch new file mode 100644 index 0000000..20615ff --- /dev/null +++ b/SOURCES/0001-Add-pseries-guest-information-711.patch @@ -0,0 +1,61 @@ +From d15668eb9569fd7d8259c3b5ca669781081d81c7 Mon Sep 17 00:00:00 2001 +From: Lyonel Vincent +Date: Fri, 22 Apr 2016 17:09:50 +0200 +Subject: [PATCH] Add pseries-guest information (#711) + + * host information (serial# and model) + * guest information (UUID and hypervisor) +--- + src/core/device-tree.cc | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/src/core/device-tree.cc b/src/core/device-tree.cc +index 2d1e52b..2823233 100644 +--- a/src/core/device-tree.cc ++++ b/src/core/device-tree.cc +@@ -623,6 +623,42 @@ bool scan_device_tree(hwNode & n) + n.addCapability("opal", "OPAL firmware"); + } + } ++ else if(matches(get_string(DEVICETREE "/compatible"), "qemu,pseries")) ++ { ++ string product; ++ ++ if ( exists(DEVICETREE "/host-serial") ) ++ n.setSerial(get_string(DEVICETREE "/host-serial")); ++ ++ if ( exists( DEVICETREE "/vm,uuid") ) ++ n.setConfig("uuid", get_string(DEVICETREE "/vm,uuid")); ++ ++ n.setVendor(get_string(DEVICETREE "/vendor", "IBM")); ++ ++ if ( exists(DEVICETREE "/hypervisor/compatible") ) { ++ product = get_string(DEVICETREE "/hypervisor/compatible"); ++ product = product.substr(0, product.size()-1); ++ } ++ ++ if ( exists(DEVICETREE "/host-model") ) { ++ product += " Model# "; ++ product += get_string(DEVICETREE "/host-model"); ++ } ++ ++ if (product != "") ++ n.setProduct(product); ++ ++ n.setDescription("pSeries Guest"); ++ ++ if (core) ++ { ++ core->addHint("icon", string("board")); ++ scan_devtree_root(*core); ++ scan_devtree_cpu(*core); ++ core->addCapability("qemu", "QEMU virtualization"); ++ core->addCapability("guest", "Virtualization guest"); ++ } ++ } + else + { + n.setVendor(get_string(DEVICETREE "/copyright", n.getVendor())); +-- +1.8.3.1 + diff --git a/SOURCES/0001-Retrieving-CPU-Information-on-IBM-s390x-and-ARM-syst.patch b/SOURCES/0001-Retrieving-CPU-Information-on-IBM-s390x-and-ARM-syst.patch new file mode 100644 index 0000000..730af00 --- /dev/null +++ b/SOURCES/0001-Retrieving-CPU-Information-on-IBM-s390x-and-ARM-syst.patch @@ -0,0 +1,238 @@ +From beb89de5a3c10449fe73f1c77b2486d868e5bc9a Mon Sep 17 00:00:00 2001 +From: Lyonel Vincent +Date: Sat, 20 Sep 2014 16:55:19 +0000 +Subject: [PATCH] Retrieving CPU Information on IBM/s390x and ARM systems + +cf. https://github.com/lyonel/lshw/pull/2 + + +git-svn-id: http://ezix.org/source/packages/lshw/development@2546 811e2811-9fd9-0310-a116-b6e8ac943c8b +--- + src/core/cpuinfo.cc | 180 ++++++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 155 insertions(+), 25 deletions(-) + +diff --git a/src/core/cpuinfo.cc b/src/core/cpuinfo.cc +index f16c2b5..821f455 100644 +--- a/src/core/cpuinfo.cc ++++ b/src/core/cpuinfo.cc +@@ -78,47 +78,169 @@ string value) + #endif + + #ifdef __s390x__ +- +-static void cpuinfo_s390(hwNode & node, ++static vector s390x_features; ++static string s390x_vendor; ++static void cpuinfo_s390x(hwNode & node, + string id, + string value) + { ++ if (id == "features") ++ { ++ while (value.length() > 0) ++ { ++ size_t pos = value.find(' '); ++ string capability = (pos==string::npos)?value:value.substr(0, pos); ++ s390x_features.push_back(capability); ++ if (pos == string::npos) ++ value = ""; ++ else ++ value = hw::strip(value.substr(pos)); ++ } ++ } ++ ++ if (id == "vendor_id") ++ s390x_vendor = value; ++ ++ if (cpu) ++ { ++ cpu->addHint("logo", string("s390x")); ++ cpu->claim(true); ++ cpu->setVendor(s390x_vendor); ++ ++ for(int i=0; i < s390x_features.size(); i++) ++ cpu->addCapability(s390x_features[i]); ++ /* many thanks to Martin Schwidefsky for communicating the descriptions ++ of the feature flags ++ */ ++ cpu->describeCapability("esan3", "ESA new instructions 3 (N3)"); ++ cpu->describeCapability("zarch", "x/Architecture (64-bit) mode)"); ++ cpu->describeCapability("stfle", "store facility list extended instruction"); ++ cpu->describeCapability("msa", "message security assist facility"); ++ cpu->describeCapability("ldisp", "long displacement facility"); ++ cpu->describeCapability("eimm", "extended immediate facility"); ++ cpu->describeCapability("dfp", "decimal floating point facility"); ++ cpu->describeCapability("edat", "enhanced DAT facility"); ++ cpu->describeCapability("etf3eh", "ETF3 enhancement facility"); ++ cpu->describeCapability("highgprs", "support for 64-bit registers for 31-bit programs"); ++ cpu->describeCapability("te", "transactional/constraint transactional execution facilities"); ++ } ++} ++#endif ++ ++#ifdef __arm__ ++static void cpuinfo_arm(hwNode & node, ++ string id, ++ string value) ++{ ++ + if (id.substr(0, string("processor").size())=="processor") + currentcpu++; + + hwNode *cpu = getcpu(node, currentcpu); +- + if (cpu) +- { +- cpu->addHint("logo", string("s390")); +- cpu->claim(true); +- if (id == "vendor_id") + { +- if (value == "IBM/S390") +- value = "IBM"; +- cpu->setVendor(value); ++ cpu->addHint("logo", string("arm")); ++ if (id == "model name" && node.getDescription() == "") ++ node.setDescription(value); ++ cpu->claim(true); ++ if (id == "Features") ++ { ++ while (value.length() > 0) ++ { ++ size_t pos = value.find(' '); ++ string capability = (pos==string::npos)?value:value.substr(0, pos); ++ cpu->addCapability(capability); ++ if (pos == string::npos) ++ value = ""; ++ else ++ value = hw::strip(value.substr(pos)); ++ } ++ } ++ /* With help from: ++ http://infocenter.arm.com/help/index.jsp ++ http://unix.stackexchange.com/questions/43539/what-do-the-flags-in-proc-cpuinfo-mean ++ http://en.wikipedia.org/wiki/ARM_architecture ++ */ ++ cpu->describeCapability("swp", "Swap instruction"); ++ cpu->describeCapability("swpb", "Swap Byte instruction"); ++ cpu->describeCapability("half", "Unknown"); ++ cpu->describeCapability("thumb", "Thumb instruction set"); ++ cpu->describeCapability("26bit", "26-bit Model"); ++ cpu->describeCapability("fastmult", "Fast Multiplication"); ++ cpu->describeCapability("fpa", "Floating point accelerator"); ++ cpu->describeCapability("vfp", "VFP (vector floating point instructions)"); ++ cpu->describeCapability("vfpv3", "VFP version 3"); ++ cpu->describeCapability("vfpv3d16", "VFP version 3 with 16 64-bit FPU registers"); ++ cpu->describeCapability("vfpv4", "VFP version 4"); ++ cpu->describeCapability("vfpd32", "Unknown"); ++ cpu->describeCapability("edsp", "DSP extensions"); ++ cpu->describeCapability("java", "Jazelle (Java bytecode accelerator)"); ++ cpu->describeCapability("thumbee", "Thumb Execution Environment"); ++ cpu->describeCapability("neon", "NEON aka MPE - Media Processing Engine"); ++ cpu->describeCapability("tls", "TLS register"); ++ cpu->describeCapability("iwmmxt", "SIMD instructions"); ++ cpu->describeCapability("crunch", "MaverickCrunch coprocessor"); ++ cpu->describeCapability("idiva", "SDIV and UDIV hardware division in ARM mode"); ++ cpu->describeCapability("idivt", "SDIV and UDIV hardware division in Thumb mode"); ++ cpu->describeCapability("lpae", "Large Physical Address Extension architecture"); ++ cpu->describeCapability("evtstrm", "Unknown"); + } ++} ++#endif + +- if (id == "features") +- while (value.length() > 0) +- { +- size_t pos = value.find(' '); +- string capability = (pos==string::npos)?value:value.substr(0, pos); ++#ifdef __aarch64__ ++static vector aarch64_features; ++static string aarch64_processor_name; ++static void cpuinfo_aarch64(hwNode & node, ++ string id, ++ string value) ++{ + +- cpu->addCapability(capability); ++ if (id.substr(0, string("processor").size())=="processor") ++ currentcpu++; + +- if (pos == string::npos) +- value = ""; +- else +- value = hw::strip(value.substr(pos)); +- } ++ if (id.substr(0, string("Processor").size())=="Processor") ++ aarch64_processor_name = value; + +- /* TODO: description for the capabilities*/ +- } ++ if (id == "Features") ++ { ++ while (value.length() > 0) ++ { ++ size_t pos = value.find(' '); ++ string capability = (pos==string::npos)?value:value.substr(0, pos); ++ aarch64_features.push_back(capability); ++ if (pos == string::npos) ++ value = ""; ++ else ++ value = hw::strip(value.substr(pos)); ++ } ++ for(int i=0; i<=currentcpu; i++) ++ { ++ hwNode *cpu = getcpu(node, i); ++ if (cpu) ++ { ++ cpu->addHint("logo", string("aarch64")); ++ if (node.getDescription() == "") ++ node.setDescription(aarch64_processor_name); ++ cpu->claim(true); ++ for(int i=0; i < aarch64_features.size(); i++) ++ { ++ cpu->addCapability(aarch64_features[i]); ++ cpu->describeCapability("fp", "Floating point instructions"); ++ cpu->describeCapability("asimd", "Advanced SIMD"); ++ cpu->describeCapability("evtstrm", "Event stream"); ++ cpu->describeCapability("aes", "AES instructions"); ++ cpu->describeCapability("pmull", "PMULL instruction"); ++ cpu->describeCapability("sha1", "SHA1 instructions"); ++ cpu->describeCapability("sha2", "SHA2 instructions"); ++ cpu->describeCapability("crc32", "CRC extension"); ++ } ++ } ++ } ++ } + } + #endif + +- + #ifdef __ia64__ + static void cpuinfo_ia64(hwNode & node, + string id, +@@ -467,7 +589,7 @@ bool scan_cpuinfo(hwNode & n) + cpuinfo_ppc(n, id, value); + #endif + #ifdef __s390x__ +- cpuinfo_s390(n, id, value); ++ cpuinfo_s390x(n, id, value); + #endif + #ifdef __hppa__ + cpuinfo_hppa(n, id, value); +@@ -478,6 +600,14 @@ bool scan_cpuinfo(hwNode & n) + #ifdef __ia64__ + cpuinfo_ia64(n, id, value); + #endif ++ ++#ifdef __arm__ ++ cpuinfo_arm(n, id, value); ++#endif ++#ifdef __aarch64__ ++ cpuinfo_aarch64(n, id, value); ++#endif ++ + } + } + } +-- +2.7.3 + diff --git a/SOURCES/0001-Revert-better-handling-of-whole-disk-volumes.patch b/SOURCES/0001-Revert-better-handling-of-whole-disk-volumes.patch new file mode 100644 index 0000000..b1620d8 --- /dev/null +++ b/SOURCES/0001-Revert-better-handling-of-whole-disk-volumes.patch @@ -0,0 +1,27 @@ +From 1265859914d022b2afb939ea9490bcb162f8730f Mon Sep 17 00:00:00 2001 +From: Petr Oros +Date: Mon, 8 Aug 2016 10:33:17 +0200 +Subject: [PATCH] Revert: "better" handling of whole-disk volumes + +Signed-off-by: Petr Oros +--- + src/core/partitions.cc | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/core/partitions.cc b/src/core/partitions.cc +index 634a8c0..7a90952 100644 +--- a/src/core/partitions.cc ++++ b/src/core/partitions.cc +@@ -1391,8 +1391,7 @@ bool scan_partitions(hwNode & n) + + if(!medium->isCapable("partitioned")) + { +- if(scan_volume(*medium, s)) // whole disk volume? +- medium->setClass(hw::volume); ++ scan_lvm(*medium, s); + } + + close(fd); +-- +2.7.3 + diff --git a/SOURCES/0001-add-S-390-specific-CPU-info.patch b/SOURCES/0001-add-S-390-specific-CPU-info.patch new file mode 100644 index 0000000..7438d5e --- /dev/null +++ b/SOURCES/0001-add-S-390-specific-CPU-info.patch @@ -0,0 +1,76 @@ +From 42c2acf867ae0fbfdd7f3e9c943b04715569c4a3 Mon Sep 17 00:00:00 2001 +From: Lyonel Vincent +Date: Wed, 16 Jul 2014 22:19:16 +0000 +Subject: [PATCH 1/1] add S/390-specific CPU info + +git-svn-id: http://ezix.org/source/packages/lshw/development@2536 811e2811-9fd9-0310-a116-b6e8ac943c8b +--- + src/core/cpuinfo.cc | 45 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/src/core/cpuinfo.cc b/src/core/cpuinfo.cc +index 85213f4..f16c2b5 100644 +--- a/src/core/cpuinfo.cc ++++ b/src/core/cpuinfo.cc +@@ -77,6 +77,48 @@ string value) + } + #endif + ++#ifdef __s390x__ ++ ++static void cpuinfo_s390(hwNode & node, ++string id, ++string value) ++{ ++ if (id.substr(0, string("processor").size())=="processor") ++ currentcpu++; ++ ++ hwNode *cpu = getcpu(node, currentcpu); ++ ++ if (cpu) ++ { ++ cpu->addHint("logo", string("s390")); ++ cpu->claim(true); ++ if (id == "vendor_id") ++ { ++ if (value == "IBM/S390") ++ value = "IBM"; ++ cpu->setVendor(value); ++ } ++ ++ if (id == "features") ++ while (value.length() > 0) ++ { ++ size_t pos = value.find(' '); ++ string capability = (pos==string::npos)?value:value.substr(0, pos); ++ ++ cpu->addCapability(capability); ++ ++ if (pos == string::npos) ++ value = ""; ++ else ++ value = hw::strip(value.substr(pos)); ++ } ++ ++ /* TODO: description for the capabilities*/ ++ } ++} ++#endif ++ ++ + #ifdef __ia64__ + static void cpuinfo_ia64(hwNode & node, + string id, +@@ -424,6 +466,9 @@ bool scan_cpuinfo(hwNode & n) + #ifdef __powerpc__ + cpuinfo_ppc(n, id, value); + #endif ++#ifdef __s390x__ ++ cpuinfo_s390(n, id, value); ++#endif + #ifdef __hppa__ + cpuinfo_hppa(n, id, value); + #endif +-- +2.7.3 + diff --git a/SOURCES/0001-add-missing-PCI-storage-subclasses-688.patch b/SOURCES/0001-add-missing-PCI-storage-subclasses-688.patch new file mode 100644 index 0000000..5f9480a --- /dev/null +++ b/SOURCES/0001-add-missing-PCI-storage-subclasses-688.patch @@ -0,0 +1,38 @@ +From f965cd50d9005353d4b8879f609d04df3c881da2 Mon Sep 17 00:00:00 2001 +From: Dan Callaghan +Date: Mon, 29 Jun 2015 10:30:58 +1000 +Subject: [PATCH 1/4] add missing PCI storage subclasses (#688) + +--- + src/core/pci.cc | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/core/pci.cc b/src/core/pci.cc +index 7c09eb8..fbfd143 100644 +--- a/src/core/pci.cc ++++ b/src/core/pci.cc +@@ -100,6 +100,8 @@ __ID("@(#) $Id$"); + #define PCI_CLASS_STORAGE_FLOPPY 0x0102 + #define PCI_CLASS_STORAGE_IPI 0x0103 + #define PCI_CLASS_STORAGE_RAID 0x0104 ++#define PCI_CLASS_STORAGE_SATA 0x0106 ++#define PCI_CLASS_STORAGE_SAS 0x0107 + #define PCI_CLASS_STORAGE_OTHER 0x0180 + + #define PCI_BASE_CLASS_NETWORK 0x02 +@@ -329,6 +331,12 @@ static const char *get_class_name(unsigned int c) + return "scsi"; + case PCI_CLASS_STORAGE_IDE: + return "ide"; ++ case PCI_CLASS_STORAGE_RAID: ++ return "raid"; ++ case PCI_CLASS_STORAGE_SATA: ++ return "sata"; ++ case PCI_CLASS_STORAGE_SAS: ++ return "sas"; + case PCI_CLASS_BRIDGE_HOST: + return "host"; + case PCI_CLASS_BRIDGE_ISA: +-- +2.7.3 + diff --git a/SOURCES/0001-assume-we-have-an-SMP-capable-systems-whenever-sever.patch b/SOURCES/0001-assume-we-have-an-SMP-capable-systems-whenever-sever.patch new file mode 100644 index 0000000..4cb1915 --- /dev/null +++ b/SOURCES/0001-assume-we-have-an-SMP-capable-systems-whenever-sever.patch @@ -0,0 +1,29 @@ +From 7f2b9eb87609a2a58396ae0e5bbd40de953028bd Mon Sep 17 00:00:00 2001 +From: Lyonel Vincent +Date: Sun, 21 Sep 2014 15:05:09 +0000 +Subject: [PATCH] assume we have an SMP-capable systems whenever several + processors are online + +git-svn-id: http://ezix.org/source/packages/lshw/development@2548 811e2811-9fd9-0310-a116-b6e8ac943c8b +--- + src/core/smp.cc | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/core/smp.cc b/src/core/smp.cc +index d069f52..9bd3631 100644 +--- a/src/core/smp.cc ++++ b/src/core/smp.cc +@@ -398,7 +398,9 @@ bool issmp(hwNode & n) + + bool issmp(hwNode & n) + { +- return false; ++ string onlinecpus = get_string("/sys/devices/system/cpu/online", "0"); ++ ++ return matches(onlinecpus, "^[0-9]+-[0-9]+") || matches(onlinecpus, "^[0-9]+,[0-9]+"); + } + + #endif +-- +2.7.3 + diff --git a/SOURCES/0001-fix-S-390-compilation.patch b/SOURCES/0001-fix-S-390-compilation.patch new file mode 100644 index 0000000..3938f7f --- /dev/null +++ b/SOURCES/0001-fix-S-390-compilation.patch @@ -0,0 +1,28 @@ +From 34f82be2768c14bc9d76f2f6845690b99e94d88a Mon Sep 17 00:00:00 2001 +From: Lyonel Vincent +Date: Tue, 23 Sep 2014 19:28:06 +0000 +Subject: [PATCH] fix S/390 compilation + +git-svn-id: http://ezix.org/source/packages/lshw/development@2549 811e2811-9fd9-0310-a116-b6e8ac943c8b +--- + src/core/cpuinfo.cc | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/core/cpuinfo.cc b/src/core/cpuinfo.cc +index 821f455..e451247 100644 +--- a/src/core/cpuinfo.cc ++++ b/src/core/cpuinfo.cc +@@ -101,6 +101,10 @@ string value) + if (id == "vendor_id") + s390x_vendor = value; + ++ if (matches(id, "^processor")) ++ currentcpu++; ++ ++ hwNode *cpu = getcpu(node, currentcpu); + if (cpu) + { + cpu->addHint("logo", string("s390x")); +-- +2.7.3 + diff --git a/SOURCES/0001-lshw-Parse-OPAL-firmware-properties-from-the-device-.patch b/SOURCES/0001-lshw-Parse-OPAL-firmware-properties-from-the-device-.patch new file mode 100644 index 0000000..b714f7b --- /dev/null +++ b/SOURCES/0001-lshw-Parse-OPAL-firmware-properties-from-the-device-.patch @@ -0,0 +1,103 @@ +From 2c38e1c6a9dd4e35685be5ba7f64e51fd0e31c1a Mon Sep 17 00:00:00 2001 +From: Jeremy Kerr +Date: Mon, 8 Jun 2015 12:35:00 +0800 +Subject: [PATCH] lshw: Parse OPAL firmware properties from the device tree + +OPAL-firmware-based Power machines expose a firmware device tree node in +/ibm,opal, containing version information and available interfaces. + +This change adds a function to parse information about OPAL firmware and +add it to lshw's machine information. With a current OpenPower machine, +we get something like this: + + *-firmware + product: OPAL firmware + physical id: 1 + version: skiboot-5.0.2 + capabilities: opal-v2 opal-v3 prd ipmi + +Signed-off-by: Jeremy Kerr +--- + src/core/device-tree.cc | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 59 insertions(+) + +diff --git a/src/core/device-tree.cc b/src/core/device-tree.cc +index 8908fd1..73a98a9 100644 +--- a/src/core/device-tree.cc ++++ b/src/core/device-tree.cc +@@ -162,6 +162,64 @@ static void scan_devtree_bootrom(hwNode & core) + } + } + ++static void scan_devtree_opal_firmware(hwNode & core) ++{ ++ vector < string >::iterator it; ++ vector < string > compat; ++ struct dirent **namelist; ++ int i, n; ++ ++ if (!exists(DEVICETREE "/ibm,opal")) ++ return; ++ ++ hwNode opal("firmware", hw::memory); ++ ++ opal.setProduct("OPAL firmware"); ++ if (exists(DEVICETREE "/ibm,opal/firmware/version")) ++ opal.setVersion(get_string(DEVICETREE "/ibm,opal/firmware/version")); ++ ++ compat = get_strings(DEVICETREE "/ibm,opal/compatible"); ++ ++ for (it = compat.begin(); it != compat.end(); ++it) { ++ if (matches(*it, "^ibm,opal-v2")) ++ opal.addCapability("opal-v2"); ++ if (matches(*it, "^ibm,opal-v3")) ++ opal.addCapability("opal-v3"); ++ } ++ ++ /* collect compatible strings from firmware sub-nodes */ ++ compat.clear(); ++ pushd(DEVICETREE "/ibm,opal"); ++ n = scandir(".", &namelist, selectdir, alphasort); ++ popd(); ++ for (i = 0; i < n; i++) { ++ string path = string(DEVICETREE "/ibm,opal/") ++ + string(namelist[i]->d_name) ++ + string("/compatible"); ++ ++ vector < string > tmp = get_strings(path); ++ compat.insert(compat.end(), tmp.begin(), tmp.end()); ++ ++ free(namelist[i]); ++ } ++ ++ if (n >= 0) ++ free(namelist); ++ ++ /* check our collected compatible strings for known capabilities */ ++ for (it = compat.begin(); it != compat.end(); ++it) { ++ ++ if (*it == "ibm,opal-prd") ++ opal.addCapability("prd"); ++ ++ if (*it == "ibm,opal-ipmi") ++ opal.addCapability("ipmi"); ++ } ++ ++ opal.claim(); ++ core.addChild(opal); ++} ++ + + static string cpubusinfo(int cpu) + { +@@ -619,6 +677,7 @@ bool scan_device_tree(hwNode & n) + scan_devtree_root(*core); + scan_devtree_memory_powernv(*core); + scan_devtree_cpu(*core); ++ scan_devtree_opal_firmware(*core); + n.addCapability("powernv", "Non-virtualized"); + n.addCapability("opal", "OPAL firmware"); + } +-- +1.9.1 + diff --git a/SOURCES/0001-scan-vio-devices-in-sysfs-692.patch b/SOURCES/0001-scan-vio-devices-in-sysfs-692.patch new file mode 100644 index 0000000..9184ce2 --- /dev/null +++ b/SOURCES/0001-scan-vio-devices-in-sysfs-692.patch @@ -0,0 +1,152 @@ +From 4ab4314e39f41045ef0e60d0a4500b204e26b313 Mon Sep 17 00:00:00 2001 +From: Dan Callaghan +Date: Fri, 10 Jul 2015 12:37:55 +1000 +Subject: [PATCH 1/2] scan vio devices in sysfs (#692) + +--- + src/core/Makefile | 5 +++-- + src/core/main.cc | 4 ++++ + src/core/sysfs.cc | 3 +++ + src/core/vio.cc | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ + src/core/vio.h | 8 ++++++++ + 5 files changed, 69 insertions(+), 2 deletions(-) + create mode 100644 src/core/vio.cc + create mode 100644 src/core/vio.h + +diff --git a/src/core/Makefile b/src/core/Makefile +index da34a55..643067b 100644 +--- a/src/core/Makefile ++++ b/src/core/Makefile +@@ -8,7 +8,7 @@ LDFLAGS= + LDSTATIC= + LIBS= + +-OBJS = hw.o main.o print.o mem.o dmi.o device-tree.o cpuinfo.o osutils.o pci.o version.o cpuid.o ide.o cdrom.o pcmcia-legacy.o scsi.o disk.o spd.o network.o isapnp.o pnp.o fb.o options.o usb.o sysfs.o display.o heuristics.o parisc.o cpufreq.o partitions.o blockio.o lvm.o ideraid.o pcmcia.o volumes.o mounts.o smp.o abi.o jedec.o dump.o fat.o virtio.o ++OBJS = hw.o main.o print.o mem.o dmi.o device-tree.o cpuinfo.o osutils.o pci.o version.o cpuid.o ide.o cdrom.o pcmcia-legacy.o scsi.o disk.o spd.o network.o isapnp.o pnp.o fb.o options.o usb.o sysfs.o display.o heuristics.o parisc.o cpufreq.o partitions.o blockio.o lvm.o ideraid.o pcmcia.o volumes.o mounts.o smp.o abi.o jedec.o dump.o fat.o virtio.o vio.o + ifeq ($(SQLITE), 1) + OBJS+= db.o + endif +@@ -37,7 +37,7 @@ hw.o: hw.h osutils.h version.h config.h options.h heuristics.h + main.o: hw.h print.h version.h options.h mem.h dmi.h cpuinfo.h cpuid.h + main.o: device-tree.h pci.h pcmcia.h pcmcia-legacy.h ide.h scsi.h spd.h + main.o: network.h isapnp.h fb.h usb.h sysfs.h display.h parisc.h cpufreq.h +-main.o: ideraid.h mounts.h smp.h abi.h virtio.h ++main.o: ideraid.h mounts.h smp.h abi.h virtio.h vio.h + print.o: print.h hw.h options.h version.h osutils.h config.h + mem.o: version.h config.h mem.h hw.h + dmi.o: version.h config.h dmi.h hw.h osutils.h +@@ -76,3 +76,4 @@ abi.o: version.h abi.h hw.h osutils.h + abi.o: version.h abi.h hw.h osutils.h + jedec.o: jedec.h + virtio.o: version.h hw.h sysfs.h disk.h virtio.h ++vio.o: version.h hw.h sysfs.h vio.h +diff --git a/src/core/main.cc b/src/core/main.cc +index 7008933..3c88f4c 100644 +--- a/src/core/main.cc ++++ b/src/core/main.cc +@@ -41,6 +41,7 @@ + #include "ideraid.h" + #include "mounts.h" + #include "virtio.h" ++#include "vio.h" + #include "smp.h" + #include "abi.h" + +@@ -109,6 +115,9 @@ bool scan_system(hwNode & system) + status("Virtual I/O (VIRTIO) devices"); + if (enabled("virtio")) + scan_virtio(computer); ++ status("IBM Virtual I/O (VIO)"); ++ if (enabled("vio")) ++ scan_vio(computer); + status("kernel device tree (sysfs)"); + if (enabled("sysfs")) + scan_sysfs(computer); +diff --git a/src/core/sysfs.cc b/src/core/sysfs.cc +index ed2c600..a2eca6c 100644 +--- a/src/core/sysfs.cc ++++ b/src/core/sysfs.cc +@@ -146,6 +146,9 @@ static string sysfstobusinfo(const string & path) + return "virtio@" + name; + } + ++ if (bustype == "vio") ++ return string("vio@") + basename(path.c_str()); ++ + return ""; + } + +diff --git a/src/core/vio.cc b/src/core/vio.cc +new file mode 100644 +index 0000000..e70640f +--- /dev/null ++++ b/src/core/vio.cc +@@ -0,0 +1,51 @@ ++#include "version.h" ++#include "hw.h" ++#include "sysfs.h" ++#include "vio.h" ++ ++#include ++ ++__ID("@(#) $Id$"); ++ ++using namespace std; ++ ++ ++bool scan_vio(hwNode & n) ++{ ++ vector < sysfs::entry > entries = sysfs::entries_by_bus("vio"); ++ ++ if (entries.empty()) ++ return false; ++ ++ for (vector < sysfs::entry >::iterator it = entries.begin(); ++ it != entries.end(); ++it) ++ { ++ const sysfs::entry & e = *it; ++ ++ if (e.name() == "vio") ++ continue; // skip root device ++ ++ string name = e.string_attr("name"); ++ if (name.empty()) ++ name = e.name(); ++ ++ hwNode device(name); ++ device.setDescription("Virtual I/O device (" + name + ")"); ++ ++ string businfo = e.businfo(); ++ if (!businfo.empty()) ++ device.setBusInfo(businfo); ++ ++ string driver = e.driver(); ++ if (!driver.empty()) ++ device.setConfig("driver", driver); ++ ++ string devicetree_node = e.string_attr("devspec"); ++ if (!devicetree_node.empty() && devicetree_node[0] == '/') ++ device.setLogicalName("/proc/device-tree" + devicetree_node); ++ ++ n.addChild(device); ++ } ++ ++ return true; ++} +diff --git a/src/core/vio.h b/src/core/vio.h +new file mode 100644 +index 0000000..d220f19 +--- /dev/null ++++ b/src/core/vio.h +@@ -0,0 +1,8 @@ ++#ifndef _VIO_H_ ++#define _VIO_H_ ++ ++#include "hw.h" ++ ++bool scan_vio(hwNode &); ++ ++#endif +-- +2.7.3 + diff --git a/SOURCES/0001-use-sysfs-for-DMI-info-when-available-696-666-664.patch b/SOURCES/0001-use-sysfs-for-DMI-info-when-available-696-666-664.patch new file mode 100644 index 0000000..72158a8 --- /dev/null +++ b/SOURCES/0001-use-sysfs-for-DMI-info-when-available-696-666-664.patch @@ -0,0 +1,303 @@ +From 65ce2362e59d8818fb23effb21d96d79334e77f8 Mon Sep 17 00:00:00 2001 +From: Jeffrey Bastian +Date: Thu, 10 Sep 2015 16:24:10 -0500 +Subject: [PATCH] use sysfs for DMI info when available (#696, #666, #664) + +backport from upstream commit 8237f8ebb92e (or r2579 from subversion) +fixes BZ 1261570: lshw triggers kernel "Oops - bad mode: 0 [#1] SMP" on AMD Seattle +--- + src/core/dmi.cc | 183 +++++++++++++++++++++++++++++++++++--------------------- + 1 file changed, 114 insertions(+), 69 deletions(-) + +diff --git a/src/core/dmi.cc b/src/core/dmi.cc +index ec1e25a2d644..14b1bd3c07e3 100644 +--- a/src/core/dmi.cc ++++ b/src/core/dmi.cc +@@ -82,7 +82,9 @@ + + #include + #include ++#include + ++#include + #include + #include + #include +@@ -92,11 +94,13 @@ + + __ID("@(#) $Id: dmi.cc 2520 2013-05-08 13:32:48Z lyonel $"); + ++#define SYSFSDMI "/sys/firmware/dmi/tables" ++ + static int currentcpu = 0; + +-typedef unsigned char u8; +-typedef unsigned short u16; +-typedef unsigned int u32; ++typedef uint8_t u8; ++typedef uint16_t u16; ++typedef uint32_t u32; + + struct dmi_header + { +@@ -174,7 +178,7 @@ static string cpubusinfo(int cpu) + } + + +-static string dmi_uuid(u8 * p) ++static string dmi_uuid(const u8 * p) + { + unsigned int i = 0; + bool valid = false; +@@ -357,7 +361,7 @@ hwNode & bios) + } + + +-static void dmi_bios_features_ext(u8 * data, ++static void dmi_bios_features_ext(const u8 * data, + int len, + hwNode & bios) + { +@@ -932,43 +936,22 @@ static string dmi_handle(u16 handle) + } + + +-static void dmi_table(int fd, +-u32 base, ++static void dmi_table(const u8 *buf, + int len, +-int num, + hwNode & node, + int dmiversionmaj, + int dmiversionmin) + { +- unsigned char *buf = (unsigned char *) malloc(len); + struct dmi_header *dm; + hwNode *hardwarenode = NULL; +- u8 *data; ++ const u8 *data; + int i = 0; + string handle; +- u32 mmoffset = 0; +- void *mmp = NULL; + + if (len == 0) + // no data + return; + +- if (buf == NULL) +-// memory exhausted +- return; +- +- mmoffset = base % getpagesize(); +- +- mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset); +- if (mmp == MAP_FAILED) +- { +- free(buf); +- return; +- } +- memcpy(buf, (u8 *) mmp + mmoffset, len); +- +- munmap(mmp, mmoffset + len); +- + data = buf; + while (data + sizeof(struct dmi_header) <= (u8 *) buf + len) + { +@@ -1276,7 +1259,7 @@ int dmiversionmin) + { + hwNode newnode("cache", + hw::memory); +- int level; ++ int level; + + newnode.setSlot(dmi_string(dm, data[4])); + u = data[6] << 8 | data[5]; +@@ -1291,6 +1274,7 @@ int dmiversionmin) + if (!(u & (1 << 7))) + newnode.disable(); + ++ newnode.setConfig("level", level); + newnode.setSize(dmi_cache_size(data[9] | data[10] << 8)); + newnode.setCapacity(dmi_cache_size(data[7] | (data[8] << 8))); + if ((dm->length > 0x0F) && (data[0x0F] != 0)) +@@ -1713,10 +1697,76 @@ int dmiversionmin) + data += 2; + i++; + } +- free(buf); + } + + ++static bool smbios_entry_point(const u8 *buf, size_t len, ++ hwNode & n, u16 & dmimaj, u16 & dmimin, ++ u16 & table_len, u32 & table_base) ++{ ++ if (len < 31 || memcmp(buf, "_SM_", 4) != 0) ++ return false; ++ ++ u8 smmajver = buf[6]; ++ u8 smminver = buf[7]; ++ ++ buf += 16; ++ if (smmajver && (memcmp(buf, "_DMI_", 5) == 0) && checksum(buf, 0x0F)) ++ { ++ table_len = buf[7] << 8 | buf[6]; ++ table_base = buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8]; ++ dmimaj = buf[14] ? buf[14] >> 4 : smmajver; ++ dmimin = buf[14] ? buf[14] & 0x0F : smminver; ++ ++ char buffer[20]; ++ snprintf(buffer, sizeof(buffer), "%d.%d", smmajver, smminver); ++ n.addCapability("smbios-"+string(buffer), "SMBIOS version "+string(buffer)); ++ snprintf(buffer, sizeof(buffer), "%d.%d", dmimaj, dmimin); ++ n.addCapability("dmi-"+string(buffer), "DMI version "+string(buffer)); ++ ++ return true; ++ } ++ ++ return false; ++} ++ ++ ++static bool scan_dmi_sysfs(hwNode & n) ++{ ++ if (!exists(SYSFSDMI "/smbios_entry_point") || !exists(SYSFSDMI "/DMI")) ++ return false; ++ ++ u16 table_len = 0; ++ u32 table_base = 0; ++ u16 dmimaj = 0, dmimin = 0; ++ ++ ifstream ep_stream(SYSFSDMI "/smbios_entry_point", ++ ifstream::in | ifstream::binary | ifstream::ate); ++ ifstream::pos_type ep_len = ep_stream.tellg(); ++ vector < u8 > ep_buf(ep_len); ++ ep_stream.seekg(0, ifstream::beg); ++ ep_stream.read((char *)ep_buf.data(), ep_len); ++ if (!ep_stream) ++ return false; ++ if (!smbios_entry_point(ep_buf.data(), ep_len, n, ++ dmimaj, dmimin, table_len, table_base)) ++ return false; ++ ++ ifstream dmi_stream(SYSFSDMI "/DMI", ++ ifstream::in | ifstream::binary | ifstream::ate); ++ ifstream::pos_type dmi_len = dmi_stream.tellg(); ++ vector < u8 > dmi_buf(dmi_len); ++ dmi_stream.seekg(0, ifstream::beg); ++ dmi_stream.read((char *)dmi_buf.data(), dmi_len); ++ if (!dmi_stream) ++ return false; ++ dmi_table(dmi_buf.data(), dmi_len, n, dmimaj, dmimin); ++ ++ return true; ++} ++ ++ ++#if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) + long get_efi_systab_smbios() + { + long result = 0; +@@ -1739,26 +1789,17 @@ long get_efi_systab_smbios() + } + + +-bool scan_dmi(hwNode & n) ++static bool scan_dmi_devmem(hwNode & n) + { +- unsigned char buf[20]; ++ unsigned char buf[31]; + int fd = open("/dev/mem", + O_RDONLY); + long fp = get_efi_systab_smbios(); + u32 mmoffset = 0; + void *mmp = NULL; + bool efi = true; +- u8 smmajver = 0, smminver = 0; + u16 dmimaj = 0, dmimin = 0; +- currentcpu = 0; +- +-#if defined(__arm__) || defined (__hppa__) || defined (__s390x__) || defined (__powerpc__) +- return false; // SMBIOS not supported on PA-RISC, S/390, ARM and PowerPC machines +-#endif + +- if (sizeof(u8) != 1 || sizeof(u16) != 2 || sizeof(u32) != 4) +-// compiler incompatibility +- return false; + if (fd == -1) + return false; + +@@ -1785,38 +1826,42 @@ bool scan_dmi(hwNode & n) + close(fd); + return false; + } +- else if (memcmp(buf, "_SM_", 4) == 0) ++ u16 len; ++ u32 base; ++ if (smbios_entry_point(buf, sizeof(buf), n, dmimaj, dmimin, len, base)) + { +-// SMBIOS +- smmajver = buf[6]; +- smminver = buf[7]; +- } +- else if (smmajver && (memcmp(buf, "_DMI_", 5) == 0) && checksum(buf, 0x0F)) +- { +- u16 num = buf[13] << 8 | buf[12]; +- u16 len = buf[7] << 8 | buf[6]; +- u32 base = buf[11] << 24 | buf[10] << 16 | buf[9] << 8 | buf[8]; +- dmimaj = buf[14] ? buf[14] >> 4 : smmajver; +- dmimin = buf[14] ? buf[14] & 0x0F : smminver; +- dmi_table(fd, base, len, num, n, dmimaj, dmimin); +- +- if (efi) +- break; // we don't need to search the memory for EFI systems ++ u8 *dmi_buf = (u8 *)malloc(len); ++ mmoffset = base % getpagesize(); ++ mmp = mmap(0, mmoffset + len, PROT_READ, MAP_SHARED, fd, base - mmoffset); ++ if (mmp == MAP_FAILED) ++ { ++ free(dmi_buf); ++ return false; ++ } ++ memcpy(dmi_buf, (u8 *) mmp + mmoffset, len); ++ munmap(mmp, mmoffset + len); ++ dmi_table(dmi_buf, len, n, dmimaj, dmimin); ++ free(dmi_buf); ++ break; + } ++ ++ if (efi) ++ break; // we don't need to search the memory for EFI systems + } + close(fd); +- if (smmajver != 0) +- { +- char buffer[20]; +- snprintf(buffer, sizeof(buffer), "%d.%d", smmajver, smminver); +- n.addCapability("smbios-"+string(buffer), "SMBIOS version "+string(buffer)); +- } +- if (dmimaj != 0) +- { +- char buffer[20]; +- snprintf(buffer, sizeof(buffer), "%d.%d", dmimaj, dmimin); +- n.addCapability("dmi-"+string(buffer), "DMI version "+string(buffer)); +- } + + return true; + } ++#endif // defined(__i386__) || defined(__x86_64__) || defined(__ia64__) ++ ++ ++bool scan_dmi(hwNode & n) ++{ ++ if (scan_dmi_sysfs(n)) ++ return true; ++#if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) ++ if (scan_dmi_devmem(n)) ++ return true; ++#endif ++ return false; ++} +-- +1.8.3.1 diff --git a/SOURCES/0002-expose-hints-in-XML-output-688.patch b/SOURCES/0002-expose-hints-in-XML-output-688.patch new file mode 100644 index 0000000..a470411 --- /dev/null +++ b/SOURCES/0002-expose-hints-in-XML-output-688.patch @@ -0,0 +1,36 @@ +From 235e46c6adfcb0cb5feaec8073cacd0db0bc98e7 Mon Sep 17 00:00:00 2001 +From: Amit Saha +Date: Tue, 2 Jun 2015 14:11:32 +1000 +Subject: [PATCH 2/4] expose hints in XML output (#688) + +--- + src/core/hw.cc | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/src/core/hw.cc b/src/core/hw.cc +index 44e2bd8..963f4ba 100644 +--- a/src/core/hw.cc ++++ b/src/core/hw.cc +@@ -1943,6 +1943,19 @@ string hwNode::asXML(unsigned level) + out << "" << endl; + } + resources.clear(); ++ ++ vector < string > hints = getHints(); ++ if (hints.size() > 0) { ++ out << spaces(2*level+1); ++ out << "" << endl; ++ for(unsigned int i=0; i"; ++ out << endl; ++ } ++ out << spaces(2*level+1); ++ out << "" << endl; ++ } + } + + for (unsigned int i = 0; i < countChildren(); i++) +-- +2.7.3 + diff --git a/SOURCES/0002-use-sysfs-to-find-businfo-for-SCSI-adapters-692.patch b/SOURCES/0002-use-sysfs-to-find-businfo-for-SCSI-adapters-692.patch new file mode 100644 index 0000000..2dddc69 --- /dev/null +++ b/SOURCES/0002-use-sysfs-to-find-businfo-for-SCSI-adapters-692.patch @@ -0,0 +1,70 @@ +From 079afcfb3f9568a031ae6149438d0289e745c42b Mon Sep 17 00:00:00 2001 +From: Dan Callaghan +Date: Fri, 10 Jul 2015 16:33:57 +1000 +Subject: [PATCH 2/2] use sysfs to find businfo for SCSI adapters (#692) + +In spite of its name, the SCSI_IOCTL_GET_PCI ioctl will actually return +the kernel name for the underlying SCSI adapter no matter whether it's +on the PCI bus or not. For example an IBM VIO SCSI adapter on the vio +bus might return 30000002 for this ioctl. + +Since this doesn't look like a PCI bus address, the guessBusInfo() +function would then make a bad guess, returning businfo as +parisc@30000002 which is not right. + +We can figure out the right businfo without guessing by looking in sysfs +instead. +--- + src/core/scsi.cc | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/src/core/scsi.cc b/src/core/scsi.cc +index 4aaec81..229d3a2 100644 +--- a/src/core/scsi.cc ++++ b/src/core/scsi.cc +@@ -658,9 +658,9 @@ static void scan_sg(hwNode & n) + int sg; + int fd = -1; + My_sg_scsi_id m_id; +- char slot_name[64]; // should be 16 but some 2.6 kernels require 32 bytes + string host = ""; + string businfo = ""; ++ string adapter_businfo = ""; + hwNode *parent = NULL; + int emulated = 0; + bool ghostdeventry = false; +@@ -695,6 +695,9 @@ static void scan_sg(hwNode & n) + + host = host_logicalname(m_id.host_no); + businfo = scsi_businfo(m_id.host_no); ++ adapter_businfo = ++ sysfs::entry::byClass("scsi_host", host_kname(m_id.host_no)) ++ .parent().businfo(); + + hwNode device = hwNode("generic"); + +@@ -751,10 +754,9 @@ static void scan_sg(hwNode & n) + if ((m_id.scsi_type == 0) || (m_id.scsi_type == 7) || (m_id.scsi_type == 14)) + scan_disk(device); + +- memset(slot_name, 0, sizeof(slot_name)); +- if (ioctl(fd, SCSI_IOCTL_GET_PCI, slot_name) >= 0) ++ if (!adapter_businfo.empty()) + { +- parent = n.findChildByBusInfo(guessBusInfo(hw::strip(slot_name))); ++ parent = n.findChildByBusInfo(adapter_businfo); + } + + if (!parent) +@@ -784,7 +786,7 @@ static void scan_sg(hwNode & n) + { + + if(parent->getBusInfo() == "") +- parent->setBusInfo(guessBusInfo(hw::strip(slot_name))); ++ parent->setBusInfo(adapter_businfo); + parent->setLogicalName(host); + parent->claim(); + +-- +2.7.3 + diff --git a/SOURCES/0003-refactored-sysfs-entry-to-always-store-resolved-devi.patch b/SOURCES/0003-refactored-sysfs-entry-to-always-store-resolved-devi.patch new file mode 100644 index 0000000..4ea6e98 --- /dev/null +++ b/SOURCES/0003-refactored-sysfs-entry-to-always-store-resolved-devi.patch @@ -0,0 +1,289 @@ +From e1ddfbef8bb460dec235628bd106e9e1b3aa483a Mon Sep 17 00:00:00 2001 +From: Dan Callaghan +Date: Wed, 8 Jul 2015 21:00:55 +1000 +Subject: [PATCH 3/4] refactored sysfs::entry to always store resolved device + path + +The sysfs::entry will always be pointing at the fully resolved path +under /sys/devices, which makes other sysfs operations like finding the +parent device and checking attributes simpler. +--- + src/core/network.cc | 2 +- + src/core/osutils.cc | 13 +++++++ + src/core/osutils.h | 1 + + src/core/scsi.cc | 2 +- + src/core/sysfs.cc | 98 +++++++++++++++-------------------------------------- + src/core/sysfs.h | 7 ++-- + 6 files changed, 49 insertions(+), 74 deletions(-) + +diff --git a/src/core/network.cc b/src/core/network.cc +index c636514..230edf2 100644 +--- a/src/core/network.cc ++++ b/src/core/network.cc +@@ -321,7 +321,7 @@ bool scan_network(hwNode & n) + interface.claim(); + interface.addHint("icon", string("network")); + +- string businfo = sysfs_getbusinfo(sysfs::entry::byClass("net", interface.getLogicalName())); ++ string businfo = sysfs::entry::byClass("net", interface.getLogicalName()).businfo(); + interface.setBusInfo(businfo); + + //scan_mii(fd, interface); +diff --git a/src/core/osutils.cc b/src/core/osutils.cc +index c9543b9..504fffd 100644 +--- a/src/core/osutils.cc ++++ b/src/core/osutils.cc +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -413,6 +414,18 @@ string realpath(const string & path) + } + + ++string dirname(const string & path) ++{ ++ size_t len = path.length(); ++ char *buffer = new char[len + 1]; ++ path.copy(buffer, len); ++ buffer[len] = '\0'; ++ string result = dirname(buffer); ++ delete buffer; ++ return result; ++} ++ ++ + string spaces(unsigned int count, const string & space) + { + string result = ""; +diff --git a/src/core/osutils.h b/src/core/osutils.h +index 1eb59c0..549258e 100644 +--- a/src/core/osutils.h ++++ b/src/core/osutils.h +@@ -14,6 +14,7 @@ bool exists(const std::string & path); + bool samefile(const std::string & path1, const std::string & path2); + std::string readlink(const std::string & path); + std::string realpath(const std::string & path); ++std::string dirname(const std::string & path); + bool loadfile(const std::string & file, std::vector < std::string > &lines); + + size_t splitlines(const std::string & s, +diff --git a/src/core/scsi.cc b/src/core/scsi.cc +index d85fcc8..4aaec81 100644 +--- a/src/core/scsi.cc ++++ b/src/core/scsi.cc +@@ -841,7 +841,7 @@ static bool scan_hosts(hwNode & node) + + if (!controller) + { +- string parentbusinfo = sysfs_getbusinfo(sysfs::entry::byClass("scsi_host", host_kname(number))); ++ string parentbusinfo = sysfs::entry::byClass("scsi_host", host_kname(number)).businfo(); + + controller = node.findChildByBusInfo(parentbusinfo); + } +diff --git a/src/core/sysfs.cc b/src/core/sysfs.cc +index 0c14a51..79c664e 100644 +--- a/src/core/sysfs.cc ++++ b/src/core/sysfs.cc +@@ -13,7 +13,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -24,9 +23,7 @@ using namespace sysfs; + + struct sysfs::entry_i + { +- string devclass; +- string devbus; +- string devname; ++ string devpath; + }; + + struct sysfs_t +@@ -102,7 +99,7 @@ static string sysfs_getbustype(const string & path) + { + devname = + string(fs.path + "/bus/") + string(namelist[i]->d_name) + +- "/devices/" + basename((char *) path.c_str()); ++ "/devices/" + basename(path.c_str()); + + if (samefile(devname, path)) + return string(namelist[i]->d_name); +@@ -144,48 +141,15 @@ static string sysfstobusinfo(const string & path) + } + + +-static string sysfs_getbusinfo_byclass(const string & devclass, const string & devname) ++string entry::businfo() const + { +- string device = +- fs.path + string("/class/") + devclass + string("/") + devname + "/device"; +- string result = ""; +- int i = 0; +- +- while((result == "") && (i<2)) // device may point to /businfo or /businfo/devname +- { +- if(!exists(device)) return ""; +- result = sysfstobusinfo(realpath(device)); +- device += "/../" + devname + "/.."; +- i++; +- } +- ++ string result = sysfstobusinfo(This->devpath); ++ if (result.empty()) ++ result = sysfstobusinfo(dirname(This->devpath)); + return result; + } + + +-static string sysfs_getbusinfo_bybus(const string & devbus, const string & devname) +-{ +- string device = +- fs.path + string("/bus/") + devbus + string("/devices/") + devname; +- char buffer[PATH_MAX + 1]; +- +- if (!realpath(device.c_str(), buffer)) +- return ""; +- +- return sysfstobusinfo(hw::strip(buffer)); +-} +- +- +-string sysfs_getbusinfo(const entry & e) +-{ +- if(e.This->devclass != "") +- return sysfs_getbusinfo_byclass(e.This->devclass, e.This->devname); +- if(e.This->devbus != "") +- return sysfs_getbusinfo_bybus(e.This->devbus, e.This->devname); +- return ""; +-} +- +- + static string finddevice(const string & name, const string & root = "") + { + struct dirent **namelist; +@@ -229,47 +193,33 @@ string sysfs_finddevice(const string & name) + } + + +-string sysfs_getdriver(const string & devclass, +-const string & devname) ++string entry::driver() const + { +- string driverpath = +- fs.path + string("/class/") + devclass + string("/") + devname + "/"; +- string driver = driverpath + "/driver"; +- char buffer[PATH_MAX + 1]; +- int namelen = 0; +- +- if ((namelen = readlink(driver.c_str(), buffer, sizeof(buffer))) < 0) ++ string driverlink = This->devpath + "/driver"; ++ if (!exists(driverlink)) + return ""; +- +- return string(basename(buffer)); ++ return basename(readlink(driverlink).c_str()); + } + + + entry entry::byBus(string devbus, string devname) + { +- entry e; +- +- e.This->devbus = devbus; +- e.This->devname = devname; +- ++ entry e(fs.path + "/bus/" + devbus + "/devices/" + devname); + return e; + } + + + entry entry::byClass(string devclass, string devname) + { +- entry e; +- +- e.This->devclass = devclass; +- e.This->devname = devname; +- ++ entry e(fs.path + "/class/" + devclass + "/" + devname + "/device"); + return e; + } + + +-entry::entry() ++entry::entry(const string & devpath) + { + This = new entry_i; ++ This->devpath = realpath(devpath); + } + + +@@ -296,15 +246,23 @@ entry::~entry() + + bool entry::hassubdir(const string & s) + { +- if(This->devclass != "") +- return exists(fs.path + string("/class/") + This->devclass + string("/") + This->devname + "/" + s); +- +- if(This->devbus != "") +- return exists(fs.path + string("/bus/") + This->devbus + string("/devices/") + This->devname + string("/") + s); ++ return exists(This->devpath + "/" + s); ++} + +- return false; ++ ++string entry::name() const ++{ ++ return basename(This->devpath.c_str()); ++} ++ ++ ++entry entry::parent() const ++{ ++ entry e(dirname(This->devpath)); ++ return e; + } + ++ + bool scan_sysfs(hwNode & n) + { + return false; +diff --git a/src/core/sysfs.h b/src/core/sysfs.h +index 08d2bc3..31946a2 100644 +--- a/src/core/sysfs.h ++++ b/src/core/sysfs.h +@@ -21,11 +21,15 @@ namespace sysfs + ~entry(); + + bool hassubdir(const string &); ++ string name() const; ++ string businfo() const; ++ string driver() const; ++ entry parent() const; + + struct entry_i * This; + + private: +- entry(); ++ entry(const string &); + + }; + +@@ -34,6 +38,5 @@ namespace sysfs + + bool scan_sysfs(hwNode & n); + +-std::string sysfs_getbusinfo(const sysfs::entry &); + std::string sysfs_finddevice(const string &name); + #endif +-- +2.7.3 + diff --git a/SOURCES/0004-scan-virtio-devices-in-sysfs-562.patch b/SOURCES/0004-scan-virtio-devices-in-sysfs-562.patch new file mode 100644 index 0000000..2e36a1b --- /dev/null +++ b/SOURCES/0004-scan-virtio-devices-in-sysfs-562.patch @@ -0,0 +1,262 @@ +From 1d411a25389dae9d928112c800bc08d15c4612be Mon Sep 17 00:00:00 2001 +From: Dan Callaghan +Date: Thu, 9 Jul 2015 12:27:30 +1000 +Subject: [PATCH 4/4] scan virtio devices in sysfs (#562) + +--- + src/core/Makefile | 5 ++-- + src/core/main.cc | 4 +++ + src/core/sysfs.cc | 55 ++++++++++++++++++++++++++++++++++++++++ + src/core/sysfs.h | 3 +++ + src/core/virtio.cc | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + src/core/virtio.h | 8 ++++++ + 6 files changed, 146 insertions(+), 2 deletions(-) + create mode 100644 src/core/virtio.cc + create mode 100644 src/core/virtio.h + +diff --git a/src/core/Makefile b/src/core/Makefile +index e069f00..5bf5a69 100644 +--- a/src/core/Makefile ++++ b/src/core/Makefile +@@ -8,7 +8,7 @@ LDFLAGS= + LDSTATIC= + LIBS= + +-OBJS = hw.o main.o print.o mem.o dmi.o device-tree.o cpuinfo.o osutils.o pci.o version.o cpuid.o ide.o cdrom.o pcmcia-legacy.o scsi.o disk.o spd.o network.o isapnp.o pnp.o fb.o options.o usb.o sysfs.o display.o heuristics.o parisc.o cpufreq.o partitions.o blockio.o lvm.o ideraid.o pcmcia.o volumes.o mounts.o smp.o abi.o jedec.o dump.o fat.o ++OBJS = hw.o main.o print.o mem.o dmi.o device-tree.o cpuinfo.o osutils.o pci.o version.o cpuid.o ide.o cdrom.o pcmcia-legacy.o scsi.o disk.o spd.o network.o isapnp.o pnp.o fb.o options.o usb.o sysfs.o display.o heuristics.o parisc.o cpufreq.o partitions.o blockio.o lvm.o ideraid.o pcmcia.o volumes.o mounts.o smp.o abi.o jedec.o dump.o fat.o virtio.o + ifeq ($(SQLITE), 1) + OBJS+= db.o + endif +@@ -37,7 +37,7 @@ hw.o: hw.h osutils.h version.h config.h options.h heuristics.h + main.o: hw.h print.h version.h options.h mem.h dmi.h cpuinfo.h cpuid.h + main.o: device-tree.h pci.h pcmcia.h pcmcia-legacy.h ide.h scsi.h spd.h + main.o: network.h isapnp.h fb.h usb.h sysfs.h display.h parisc.h cpufreq.h +-main.o: ideraid.h mounts.h smp.h abi.h ++main.o: ideraid.h mounts.h smp.h abi.h virtio.h + print.o: print.h hw.h options.h version.h osutils.h config.h + mem.o: version.h config.h mem.h hw.h + dmi.o: version.h config.h dmi.h hw.h osutils.h +@@ -75,3 +75,4 @@ smp.o: version.h smp.h hw.h osutils.h + smp.o: version.h smp.h hw.h osutils.h + abi.o: version.h abi.h hw.h osutils.h + jedec.o: jedec.h ++virtio.o: version.h hw.h sysfs.h disk.h virtio.h +diff --git a/src/core/main.cc b/src/core/main.cc +index d98b8d8..03848da 100644 +--- a/src/core/main.cc ++++ b/src/core/main.cc +@@ -40,6 +40,7 @@ + #include "cpufreq.h" + #include "ideraid.h" + #include "mounts.h" ++#include "virtio.h" + #include "smp.h" + #include "abi.h" + +@@ -105,6 +107,9 @@ bool scan_system(hwNode & system) + status("PCMCIA"); + if (enabled("pcmcia-legacy")) + scan_pcmcialegacy(computer); ++ status("Virtual I/O (VIRTIO) devices"); ++ if (enabled("virtio")) ++ scan_virtio(computer); + status("kernel device tree (sysfs)"); + if (enabled("sysfs")) + scan_sysfs(computer); +diff --git a/src/core/sysfs.cc b/src/core/sysfs.cc +index 79c664e..acc9d00 100644 +--- a/src/core/sysfs.cc ++++ b/src/core/sysfs.cc +@@ -137,6 +137,15 @@ static string sysfstobusinfo(const string & path) + if (bustype == "ide") + return sysfstoide(path); + ++ if (bustype == "virtio") ++ { ++ string name = basename(path.c_str()); ++ if (name.compare(0, 6, "virtio") == 0) ++ return "virtio@" + name.substr(6); ++ else ++ return "virtio@" + name; ++ } ++ + return ""; + } + +@@ -250,6 +259,33 @@ bool entry::hassubdir(const string & s) + } + + ++string entry::name_in_class(const string & classname) const ++{ ++ string result = ""; ++ ++ string classdir = This->devpath + "/" + classname; ++ if (!pushd(classdir)) ++ return result; ++ ++ struct dirent **namelist = NULL; ++ int count = scandir(".", &namelist, selectdir, alphasort); ++ popd(); ++ ++ if (count < 0) ++ return result; ++ ++ // there should be at most one ++ for (int i = 0; i < count; i++) ++ { ++ result = namelist[i]->d_name; ++ free(namelist[i]); ++ } ++ free(namelist); ++ ++ return result; ++} ++ ++ + string entry::name() const + { + return basename(This->devpath.c_str()); +@@ -263,6 +299,25 @@ entry entry::parent() const + } + + ++vector < entry > sysfs::entries_by_bus(const string & busname) ++{ ++ vector < entry > result; ++ ++ if (!pushd(fs.path + "/bus/" + busname + "/devices")) ++ return result; ++ ++ struct dirent **namelist; ++ int count; ++ count = scandir(".", &namelist, selectlink, alphasort); ++ for (int i = 0; i < count; i ++) ++ { ++ entry e = sysfs::entry::byBus(busname, namelist[i]->d_name); ++ result.push_back(e); ++ } ++ return result; ++} ++ ++ + bool scan_sysfs(hwNode & n) + { + return false; +diff --git a/src/core/sysfs.h b/src/core/sysfs.h +index 31946a2..a9dc573 100644 +--- a/src/core/sysfs.h ++++ b/src/core/sysfs.h +@@ -25,6 +25,7 @@ namespace sysfs + string businfo() const; + string driver() const; + entry parent() const; ++ string name_in_class(const string &) const; + + struct entry_i * This; + +@@ -33,6 +34,8 @@ namespace sysfs + + }; + ++ vector < entry > entries_by_bus(const string & busname); ++ + } // namespace sysfs + + +diff --git a/src/core/virtio.cc b/src/core/virtio.cc +new file mode 100644 +index 0000000..91d1196 +--- /dev/null ++++ b/src/core/virtio.cc +@@ -0,0 +1,73 @@ ++#include "version.h" ++#include "hw.h" ++#include "sysfs.h" ++#include "disk.h" ++#include "virtio.h" ++ ++#include ++ ++__ID("@(#) $Id$"); ++ ++using namespace std; ++ ++// driver seems like the only way to guess the class ++static hw::hwClass virtio_class(const string & driver) ++{ ++ if (driver == "virtio_net") ++ return hw::network; ++ if (driver == "virtio_blk") ++ return hw::disk; ++ return hw::generic; ++} ++ ++static void scan_virtio_block(hwNode & device, const sysfs::entry & entry) ++{ ++ string devname = entry.name_in_class("block"); ++ if (devname.empty()) ++ return; ++ device.setLogicalName(devname); ++ scan_disk(device); ++ device.claim(); ++} ++ ++bool scan_virtio(hwNode & n) ++{ ++ vector < sysfs::entry > entries = sysfs::entries_by_bus("virtio"); ++ ++ if (entries.empty()) ++ return false; ++ ++ for (vector < sysfs::entry >::iterator it = entries.begin(); ++ it != entries.end(); ++it) ++ { ++ const sysfs::entry & e = *it; ++ ++ hwNode device(e.name()); ++ device.setDescription("Virtual I/O device"); ++ ++ string businfo = e.businfo(); ++ if (!businfo.empty()) ++ device.setBusInfo(businfo); ++ ++ string driver = e.driver(); ++ device.setClass(virtio_class(driver)); ++ if (!driver.empty()) ++ device.setConfig("driver", driver); ++ ++ // virtio_net devices will be claimed during network interface scanning, ++ // but we handle virtio_blk devices here because nothing else will ++ scan_virtio_block(device, e); ++ ++ hwNode *parent = NULL; ++ string parent_businfo = e.parent().businfo(); ++ if (!parent_businfo.empty()) ++ parent = n.findChildByBusInfo(parent_businfo); ++ if (!parent) ++ parent = n.getChild("core"); ++ if (!parent) ++ parent = n.addChild(hwNode("core", hw::bus)); ++ parent->addChild(device); ++ } ++ ++ return true; ++} +diff --git a/src/core/virtio.h b/src/core/virtio.h +new file mode 100644 +index 0000000..0442215 +--- /dev/null ++++ b/src/core/virtio.h +@@ -0,0 +1,8 @@ ++#ifndef _VIRTIO_H_ ++#define _VIRTIO_H_ ++ ++#include "hw.h" ++ ++bool scan_virtio(hwNode &); ++ ++#endif +-- +2.7.3 + diff --git a/SOURCES/0dff3470.patch b/SOURCES/0dff3470.patch new file mode 100644 index 0000000..bb6755c --- /dev/null +++ b/SOURCES/0dff3470.patch @@ -0,0 +1,120 @@ +From 0dff3470926f813cd36d03bc79216972399e65e5 Mon Sep 17 00:00:00 2001 +From: Amit Saha +Date: Thu, 23 Apr 2015 14:52:02 +1000 +Subject: [PATCH] Add a new element "vendor_id" element which preserves the original vendor ID (#405) + +Bug: 1212284 +--- + +diff --git a/docs/lshw.xsd b/docs/lshw.xsd +index b46a33e..95d5e38 100644 +--- a/docs/lshw.xsd ++++ b/docs/lshw.xsd +@@ -13,6 +13,7 @@ + + + ++ + + + +diff --git a/src/core/cpuinfo.cc b/src/core/cpuinfo.cc +index ac2ff1b..ee96424 100644 +--- a/src/core/cpuinfo.cc ++++ b/src/core/cpuinfo.cc +@@ -263,6 +263,7 @@ + cpu->claim(true); + if (id == "vendor_id") + { ++ cpu->setVendorId(value); + if (value == "AuthenticAMD") + value = "Advanced Micro Devices [AMD]"; + if (value == "GenuineIntel") +diff --git a/src/core/hw.cc b/src/core/hw.cc +index 44e2bd8..bad65d3 100644 +--- a/src/core/hw.cc ++++ b/src/core/hw.cc +@@ -27,7 +27,7 @@ + struct hwNode_i + { + hwClass deviceclass; +- string id, vendor, product, version, date, serial, slot, handle, description, ++ string id, vendor, vendor_id, product, version, date, serial, slot, handle, description, + businfo, physid, dev; + bool enabled; + bool claimed; +@@ -395,6 +395,19 @@ + This->vendor = strip(vendor); + } + ++string hwNode::getVendorId() const ++{ ++ if (This) ++ return This->vendor_id; ++ else ++ return ""; ++} ++ ++void hwNode::setVendorId(const string & vendor_id) ++{ ++ if (This) ++ This->vendor_id = strip(vendor_id); ++} + + string hwNode::getProduct() const + { +@@ -1700,6 +1713,16 @@ + out << endl; + } + ++ if (getVendorId() != "") ++ { ++ out << spaces(2*level+1); ++ out << ""; ++ out << escape(getVendorId()); ++ out << ""; ++ out << endl; ++ } ++ ++ + if (getPhysId() != "") + { + out << spaces(2*level+1); +diff --git a/src/core/hw.h b/src/core/hw.h +index d61bb98..2f21cd0 100644 +--- a/src/core/hw.h ++++ b/src/core/hw.h +@@ -123,6 +123,8 @@ + + string getVendor() const; + void setVendor(const string & vendor); ++ string getVendorId() const; ++ void setVendorId(const string & vendor); + + string getProduct() const; + void setProduct(const string & product); +diff --git a/src/core/print.cc b/src/core/print.cc +index 5df078e..ec8dfc9 100644 +--- a/src/core/print.cc ++++ b/src/core/print.cc +@@ -209,6 +209,20 @@ + cout << endl; + } + ++ if (node.getVendorId() != "") ++ { ++ tab(level + 1, false); ++ if (html) ++ cout << ""; ++ cout << _("vendor_id") << ": "; ++ if (html) ++ cout << ""; ++ cout << node.getVendorId(); ++ if (html) ++ cout << ""; ++ cout << endl; ++ } ++ + if (node.getPhysId() != "") + { + tab(level + 1, false); diff --git a/SPECS/lshw.spec b/SPECS/lshw.spec index 7ac96b4..62a8758 100644 --- a/SPECS/lshw.spec +++ b/SPECS/lshw.spec @@ -1,7 +1,7 @@ Summary: Hardware lister Name: lshw Version: B.02.17 -Release: 5%{?dist} +Release: 12%{?dist} License: GPLv2 Group: Applications/System URL: http://ezix.org/project/wiki/HardwareLiSter @@ -15,6 +15,23 @@ Patch2: 0001-IBM-PowerNV.patch Patch3: 0002-IBM-PowerNV.patch Patch4: 0003-IBM-PowerNV.patch Patch5: 0004-IBM-PowerNV.patch +Patch6: 0001-use-sysfs-for-DMI-info-when-available-696-666-664.patch +Patch7: 0dff3470.patch +Patch8: 0001-Add-pseries-guest-information-711.patch +Patch9: 0001-lshw-Parse-OPAL-firmware-properties-from-the-device-.patch +Patch10: 0001-add-S-390-specific-CPU-info.patch +Patch11: 0001-Retrieving-CPU-Information-on-IBM-s390x-and-ARM-syst.patch +Patch12: 0001-assume-we-have-an-SMP-capable-systems-whenever-sever.patch +Patch13: 0001-fix-S-390-compilation.patch +Patch14: 0001-add-missing-PCI-storage-subclasses-688.patch +Patch15: 0002-expose-hints-in-XML-output-688.patch +Patch16: 0003-refactored-sysfs-entry-to-always-store-resolved-devi.patch +Patch17: 0004-scan-virtio-devices-in-sysfs-562.patch +Patch18: 0001-scan-vio-devices-in-sysfs-692.patch +Patch19: 0002-use-sysfs-to-find-businfo-for-SCSI-adapters-692.patch +Patch20: 0001-Add-missing-sysfs-entry-string_attr.patch +Patch21: 0001-Revert-better-handling-of-whole-disk-volumes.patch + BuildRequires: sqlite-devel Requires: hwdata @@ -48,6 +65,22 @@ plain, XML or HTML format. %patch3 -p1 %patch4 -p1 %patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 %build %{__make} %{?_smp_mflags} SBINDIR="%{_sbindir}" RPM_OPT_FLAGS="%{optflags}" SQLITE=1 gui @@ -117,6 +150,33 @@ rm -rf %{buildroot}%{_datadir}/locale/fr/ %{_datadir}/polkit-1/actions/org.ezix.lshw.gui.policy %changelog +* Mon Aug 8 2016 Petr Oros - B.02.17-12 +- Revert: "better" handling of whole-disk volumes +- Resolves: #1358748 + +* Mon Aug 1 2016 Petr Oros - B.02.17-11 +- Resolves: #1360662 + +* Tue Jul 26 2016 Petr Oros - B.02.17-10 +- Add support for reporting virtio devices +- Resolves: #1360662 + +* Mon Jul 25 2016 Petr Oros - B.02.17-9 +- Add support for proper report cpuinfo on s390x arch +- Resolves: #1208276 + +* Tue Jun 7 2016 Petr Oros - B.02.17-8 +- Add pseries-guest information and PowerNV-firmware information +- Resolves: #1334603 + +* Fri Apr 29 2016 Petr Oros - B.02.17-7 +- Report the vendor_id field for x86 cpu's +- Resolves: #1215245 + +* Mon Jan 25 2016 Petr Oros - B.02.17-6 +- Use sysfs for DMI info when available +- Resolves: #1261570 + * Mon Sep 14 2015 Petr Oros - B.02.17-5 - Resolves: #1221933 - Remove Trailing newline in 0004-IBM-PowerNV.patch