Blob Blame History Raw
From 17aa0a1e48bf9dd596c7678b93bd5aaaad94aeb8 Mon Sep 17 00:00:00 2001
From: Lyonel Vincent <lyonel@ezix.org>
Date: Tue, 20 Jun 2017 20:49:30 +0200
Subject: [PATCH] merge Petr Oros' pull request

cf. https://github.com/lyonel/lshw/pull/29

 * Proper detect vendor_id/device_id for virtual functions
 * Sync SMBIOS with latest specification
---
 src/core/dmi.cc   | 323 +++++++++++++++++++++++++++++++++---------------------
 src/core/pci.cc   |  13 ++-
 src/core/sysfs.cc |  10 ++
 src/core/sysfs.h  |   2 +
 4 files changed, 221 insertions(+), 127 deletions(-)

diff --git a/src/core/dmi.cc b/src/core/dmi.cc
index 250f485..d1b0b07 100644
--- a/src/core/dmi.cc
+++ b/src/core/dmi.cc
@@ -408,6 +408,13 @@ static unsigned long dmi_cache_size(u16 n)
     return (n & 0x7FFF) * 1024;                   // value is in 1K blocks
 }
 
+static unsigned long long dmi_cache_size_long(u32 n)
+{
+  if (n & (1 << 31))
+    return (n & 0x7FFFFFFF) * 64 * 1024;              // value is in 64K blocks
+  else
+    return (n & 0x7FFFFFFF) * 1024;                   // value is in 1K blocks
+}
 
 static void dmi_cache_sramtype(u16 c,
 hwNode & n)
@@ -657,9 +664,13 @@ void dmi_chassis(u8 code, hwNode & n)
     "tablet", N_("Tablet"), NULL,
     "convertible", N_("Convertible"), NULL,
     "detachable", N_("Detachable"), NULL,               /* 0x20 */
+    "iot-gateway", N_("IoT Gateway"), NULL,
+    "embedded", N_("Embedded PC"), NULL,
+    "mini", N_("Mini PC"), NULL,
+    "stick", N_("Stick PC"), NULL,               /* 0x24 */
   };
 
-  if(code <= 0x20)
+  if(code <= 0x24)
   {
     if(n.getDescription()=="") n.setDescription(_(chassis_type[1+3*code]));
 
@@ -720,9 +731,9 @@ static const char *dmi_processor_family(uint16_t code)
     "Core Solo mobile",
     "Atom",
     "Core M",
-    "",
-    "",
-    "",
+    "Core M3",
+    "Core M5",
+    "Core M7",
     "Alpha",                                      /* 0x30 */
     "Alpha 21064",
     "Alpha 21066",
@@ -780,9 +791,9 @@ static const char *dmi_processor_family(uint16_t code)
     "Athlon X4",                                  /* 0x66 */
     "Opteron X1000",
     "Opteron X2000 APU",
-    "",
-    "",
-    "",
+    "Opteron A",
+    "Opteron X3000 APU",
+    "Zen",
     "",
     "",
     "",
@@ -938,6 +949,8 @@ static const char *dmi_processor_family(uint16_t code)
 
   switch (code)
   {
+    case 0x100: return "ARMv7";
+    case 0x101: return "ARMv8";
     case 0x104: return "SH-3";
     case 0x105: return "SH-4";
     case 0x118: return "ARM";
@@ -966,7 +979,8 @@ static void dmi_table(const u8 *buf,
 int len,
 hwNode & node,
 int dmiversionmaj,
-int dmiversionmin)
+int dmiversionmin,
+int dmiversionrev)
 {
   struct dmi_header *dm;
   hwNode *hardwarenode = NULL;
@@ -1008,24 +1022,34 @@ int dmiversionmin)
 // BIOS Information Block
         {
           string release(dmi_string(dm,
-            data[8]));
+            data[0x08]));
           hwNode newnode("firmware",
             hw::memory,
             dmi_string(dm,
-            data[4]));
+            data[0x04]));
           newnode.setVersion(dmi_string(dm, data[5]));
-          newnode.setCapacity(64 * data[9] * 1024);
-          newnode.setSize(16 * (0x10000 - (data[7] << 8 | data[6])));
-//newnode.setPhysId(16 * (data[7] << 8 | data[6]));
+          if (data[0x09] != 0xFF)
+            newnode.setCapacity(64 * (data[0x09] + 1) * 1024);
+          else
+          {
+            if (dm->length < 0x1A)
+              newnode.setCapacity(16 * 1024 * 1024);
+            else
+            {
+              unsigned int unit = (data[0x19] << 8 | data[0x18]) & 0x4000 ? 1024 : 1024 * 1024;
+              newnode.setCapacity(((data[0x19] << 8 | data[0x18]) & 0x3FFF) * unit);
+            }
+          }
+          newnode.setSize(16 * (0x10000 - (data[0x07] << 8 | data[0x06])));
           newnode.setPhysId(dm->handle);
           newnode.setDescription(_("BIOS"));
           newnode.addHint("icon", string("chip"));
           newnode.claim();
 
-          dmi_bios_features(data[13] << 24 | data[12] << 16 | data[11] << 8 |
-            data[10],
-            data[17] << 24 | data[16] << 16 | data[15] << 8 |
-            data[14], newnode);
+          dmi_bios_features(data[0x0D] << 24 | data[0x0C] << 16 | data[0x0B] << 8 |
+            data[0x0A],
+            data[0x11] << 24 | data[0x10] << 16 | data[0x0F] << 8 |
+            data[0x0E], newnode);
 
           if (dm->length > 0x12)
             dmi_bios_features_ext(&data[0x12], dm->length - 0x12, newnode);
@@ -1039,12 +1063,12 @@ int dmiversionmin)
       case 1:
 // System Information Block
         node.setHandle(handle);
-        node.setVendor(dmi_string(dm, data[4]));
-        node.setProduct(dmi_string(dm, data[5]));
-        node.setVersion(dmi_string(dm, data[6]));
-        node.setSerial(dmi_string(dm, data[7]));
+        node.setVendor(dmi_string(dm, data[0x04]));
+        node.setProduct(dmi_string(dm, data[0x05]));
+        node.setVersion(dmi_string(dm, data[0x06]));
+        node.setSerial(dmi_string(dm, data[0x07]));
         if (dm->length >= 0x19)
-          node.setConfig("uuid", dmi_uuid(data + 8));
+          node.setConfig("uuid", dmi_uuid(data + 0x08));
         if (dm->length >= 0x1B)
         {
           node.setConfig("sku", dmi_string(dm, data[0x19]));
@@ -1057,15 +1081,14 @@ int dmiversionmin)
       case 2:
 // Board Information Block
         {
-
-                                                  // we are the only system board on the computer so connect everything to us
+          // we are the only system board on the computer so connect everything to us
           if ((dm->length <= 0x0E) || (data[0x0E] == 0))
           {
-            hardwarenode->setVendor(dmi_string(dm, data[4]));
-            hardwarenode->setProduct(dmi_string(dm, data[5]));
-            hardwarenode->setVersion(dmi_string(dm, data[6]));
-            hardwarenode->setSerial(dmi_string(dm, data[7]));
-            if(dm->length >= 0x0a)
+            hardwarenode->setVendor(dmi_string(dm, data[0x04]));
+            hardwarenode->setProduct(dmi_string(dm, data[0x05]));
+            hardwarenode->setVersion(dmi_string(dm, data[0x06]));
+            hardwarenode->setSerial(dmi_string(dm, data[0x07]));
+            if(dm->length >= 0x0A)
               hardwarenode->setSlot(dmi_string(dm, data[0x0A]));
             hardwarenode->setHandle(handle);
             hardwarenode->setDescription(_("Motherboard"));
@@ -1083,10 +1106,10 @@ int dmiversionmin)
                   (data[0x0F + 2 * i + 1] << 8 |
                   data[0x0F + 2 * i]));
 
-            newnode.setVendor(dmi_string(dm, data[4]));
-            newnode.setProduct(dmi_string(dm, data[5]));
-            newnode.setVersion(dmi_string(dm, data[6]));
-            newnode.setSerial(dmi_string(dm, data[7]));
+            newnode.setVendor(dmi_string(dm, data[0x04]));
+            newnode.setProduct(dmi_string(dm, data[0x05]));
+            newnode.setVersion(dmi_string(dm, data[0x06]));
+            newnode.setSerial(dmi_string(dm, data[0x07]));
             newnode.setSlot(dmi_string(dm, data[0x0A]));
             newnode.setHandle(handle);
             newnode.setPhysId(dm->handle);
@@ -1102,14 +1125,14 @@ int dmiversionmin)
 // special case: if the system characteristics are still unknown,
 // use values from the chassis
         if (node.getVendor() == "")
-          node.setVendor(dmi_string(dm, data[4]));
+          node.setVendor(dmi_string(dm, data[0x04]));
         if (node.getProduct() == "")
-          node.setProduct(dmi_string(dm, data[5]));
+          node.setProduct(dmi_string(dm, data[0x05]));
         if (node.getVersion() == "")
-          node.setVersion(dmi_string(dm, data[6]));
+          node.setVersion(dmi_string(dm, data[0x06]));
         if (node.getSerial() == "")
-          node.setSerial(dmi_string(dm, data[7]));
-        dmi_chassis(data[5] & 0x7F, node);
+          node.setSerial(dmi_string(dm, data[0x07]));
+        dmi_chassis(data[0x05] & 0x7F, node);
         break;
 
       case 4:
@@ -1120,16 +1143,16 @@ int dmiversionmin)
 
           newnode.claim();
           newnode.setBusInfo(cpubusinfo(currentcpu++));
-          newnode.setSlot(dmi_string(dm, data[4]));
+          newnode.setSlot(dmi_string(dm, data[0x04]));
           newnode.setDescription(_("CPU"));
           newnode.addHint("icon", string("cpu"));
           if (dm->length >= 0x2A)
             newnode.setProduct(dmi_processor_family(
                 (((uint16_t) data[0x29]) << 8) + data[0x28]));
           else
-            newnode.setProduct(dmi_processor_family(data[6]));
+            newnode.setProduct(dmi_processor_family(data[0x06]));
           newnode.setVersion(dmi_string(dm, data[0x10]));
-          newnode.setVendor(dmi_string(dm, data[7]));
+          newnode.setVendor(dmi_string(dm, data[0x07]));
           newnode.setPhysId(dm->handle);
           if (dm->length > 0x1A)
           {
@@ -1177,15 +1200,30 @@ int dmiversionmin)
           }
 
           if (dm->length >= 0x28)
-          { 
+          {
             if (data[0x23] != 0)
-		newnode.setConfig("cores", data[0x23]);
+            {
+              if (data[0x23] == 0xFF)
+                newnode.setConfig("cores", data[0x2B] << 8 | data[0x2A]);
+              else
+                newnode.setConfig("cores", data[0x23]);
+            }
             if (data[0x24] != 0)
-		newnode.setConfig("enabledcores", data[0x24]);
+            {
+              if (data[0x24] == 0xFF)
+                newnode.setConfig("enabledcores", data[0x2D] << 8 | data[0x2C]);
+              else
+                newnode.setConfig("enabledcores", data[0x24]);
+            }
             if (data[0x25] != 0)
-		newnode.setConfig("threads", data[0x25]);
+            {
+              if (data[0x25] == 0xFF)
+                newnode.setConfig("threads", data[0x2F] << 8 | data[0x2E]);
+              else
+                newnode.setConfig("threads", data[0x25]);
+            }
             if (data[0x26] & 0x4)
-		newnode.addCapability("lm", _("64-bit capable"));
+              newnode.addCapability("lm", _("64-bit capable"));
           }
 
           newnode.setHandle(handle);
@@ -1207,7 +1245,7 @@ int dmiversionmin)
           newnode.setHandle(handle);
           newnode.setPhysId(dm->handle);
 
-          size = data[0x0E] * (1 << data[8]) * 1024 * 1024;
+          size = data[0x0E] * (1 << data[0x08]) * 1024 * 1024;
           newnode.setCapacity(size);
 
 // loop through the controller's slots and link them to us
@@ -1237,44 +1275,44 @@ int dmiversionmin)
           unsigned long long size = 0;
 
           newnode.setDescription(_("empty memory bank"));
-          newnode.setSlot(dmi_string(dm, data[4]).c_str());
+          newnode.setSlot(dmi_string(dm, data[0x04]).c_str());
           if (data[6])
-            clock = 1000000000 / data[6];         // convert value from ns to Hz
+            clock = 1000000000 / data[0x06];         // convert value from ns to Hz
           newnode.setClock(clock);
-          newnode.setDescription(dmi_decode_ram(data[8] << 8 | data[7]));
+          newnode.setDescription(dmi_decode_ram(data[0x08] << 8 | data[0x07]));
           newnode.addHint("icon", string("memory"));
 // installed size
-          switch (data[9] & 0x7F)
+          switch (data[0x09] & 0x7F)
           {
             case 0x7D:
             case 0x7E:
             case 0x7F:
               break;
             default:
-              size = (1 << (data[9] & 0x7F)) << 20;
+              size = (1 << (data[0x09] & 0x7F)) << 20;
           }
-          if (data[9] & 0x80)
+          if (data[0x09] & 0x80)
             size *= 2;
 // enabled size
-          switch (data[10] & 0x7F)
+          switch (data[0x0A] & 0x7F)
           {
             case 0x7D:
             case 0x7E:
             case 0x7F:
               break;
             default:
-              capacity = (1 << (data[10] & 0x7F)) << 20;
+              capacity = (1 << (data[0x0A] & 0x7F)) << 20;
           }
-          if (data[10] & 0x80)
+          if (data[0x0A] & 0x80)
             capacity *= 2;
 
           newnode.setCapacity(capacity);
           newnode.setSize(size);
           if(newnode.getSize()==0)
             newnode.setDescription(newnode.getDescription() + " " + _("[empty]"));
-          if ((data[11] & 4) == 0)
+          if ((data[0x0B] & 4) == 0)
           {
-            if (data[11] & (1 << 0))
+            if (data[0x0B] & (1 << 0))
 // bank has uncorrectable errors (BIOS disabled)
               newnode.disable();
           }
@@ -1291,8 +1329,8 @@ int dmiversionmin)
             hw::memory);
 	  int level;
 
-          newnode.setSlot(dmi_string(dm, data[4]));
-          u = data[6] << 8 | data[5];
+          newnode.setSlot(dmi_string(dm, data[0x04]));
+          u = data[0x06] << 8 | data[0x05];
           level = 1 + (u & 7);
 
           if (dm->length > 0x11)
@@ -1305,11 +1343,19 @@ int dmiversionmin)
             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 ((data[0x08] << 8 | data[0x07]) == 0xFFFF)
+            newnode.setCapacity(dmi_cache_size_long(data[0x16] << 24 | data[0x15] << 16 | data[0x14] << 8 | data[0x13]));
+          else
+            newnode.setCapacity(dmi_cache_size(data[0x08] << 8 | data[0x07]));
+
+          if ((data[0x0A] << 8 | data[0x09]) == 0xFFFF)
+            newnode.setSize(dmi_cache_size_long(data[0x1A] << 24 | data[0x19] << 16 | data[0x18] << 8 | data[0x17]));
+          else
+            newnode.setSize(dmi_cache_size(data[0x0A] << 8 | data[0x09]));
+
           if ((dm->length > 0x0F) && (data[0x0F] != 0))
           {
-                                                  // convert from ns to Hz
+            // convert from ns to Hz
             newnode.setClock(1000000000 / data[0x0F]);
           }
 
@@ -1338,16 +1384,16 @@ int dmiversionmin)
           hwNode newnode("cardslot",
             hw::bus);
           newnode.setHandle(handle);
-          newnode.setSlot(dmi_string(dm, data[4]));
+          newnode.setSlot(dmi_string(dm, data[0x04]));
           printf("\t\tType: %s%s%s\n",
-            dmi_bus_width(data[6]),
-            dmi_card_size(data[8]), dmi_bus_name(data[5]));
-          if (data[7] == 3)
+            dmi_bus_width(data[0x06]),
+            dmi_card_size(data[0x08]), dmi_bus_name(data[0x05]));
+          if (data[0x07] == 3)
             printf("\t\tStatus: Available.\n");
-          if (data[7] == 4)
+          if (data[0x07] == 4)
             printf("\t\tStatus: In use.\n");
-          if (data[11] & 0xFE)
-            dmi_card_props(data[11]);
+          if (data[0x0B] & 0xFE)
+            dmi_card_props(data[0x0B]);
 //hardwarenode->addChild(newnode);
         }
 #endif
@@ -1374,13 +1420,13 @@ int dmiversionmin)
       case 13:
 #if 0
         printf("\tBIOS Language Information\n");
-        printf("\t\tInstallable Languages: %u\n", data[4]);
-        for (u = 1; u <= data[4]; u++)
+        printf("\t\tInstallable Languages: %u\n", data[0x04]);
+        for (u = 1; u <= data[0x04]; u++)
         {
           printf("\t\t\t%s\n", dmi_string(dm, u).c_str());
         }
         printf("\t\tCurrently Installed Language: %s\n",
-          dmi_string(dm, data[21]).c_str());
+          dmi_string(dm, data[0x15]).c_str());
 #endif
         break;
       case 14:
@@ -1395,7 +1441,7 @@ int dmiversionmin)
           string id = "memory";
           string description = "";
           bool claim = false, memory_icon = false;
-          switch (data[5])
+          switch (data[0x05])
           {
             case 0x03:
               description = _("System Memory");
@@ -1433,12 +1433,12 @@ int dmiversionrev)
           newnode.setHandle(handle);
           newnode.setPhysId(dm->handle);
           newnode.setDescription(description);
-          newnode.setSlot(dmi_memory_array_location(data[4]));
+          newnode.setSlot(dmi_memory_array_location(data[0x04]));
           if (memory_icon)
             newnode.addHint("icon", string("memory"));
           if (claim)
             newnode.claim();
-          switch (data[6])
+          switch (data[0x06])
           {
             case 0x04:
               newnode.addCapability("parity", _("Parity error correction"));
@@ -1457,7 +1503,7 @@ int dmiversionmin)
               newnode.setConfig("errordetection", "crc");
               break;
           }
-          u2 = data[10] << 24 | data[9] << 16 | data[8] << 8 | data[7];
+          u2 = data[0x0A] << 24 | data[0x09] << 16 | data[0x08] << 8 | data[0x07];
           if (u2 != 0x80000000)                   // magic value for "unknown"
             newnode.setCapacity(u2 * 1024);
           else if (dm->length >= 0x17)
@@ -1489,15 +1535,15 @@ int dmiversionmin)
           string arrayhandle;
           newnode.setDescription(_("empty memory bank"));
           newnode.addHint("icon", string("memory"));
-          arrayhandle = dmi_handle(data[5] << 8 | data[4]);
+          arrayhandle = dmi_handle(data[0x05] << 8 | data[0x04]);
           strcpy(bits, "");
 // total width
-          u = data[9] << 8 | data[8];
-          if (u != 0xffff)
+          u = data[0x09] << 8 | data[0x08];
+          if (u != 0xFFFF)
             width = u;
 //data width
-          u = data[11] << 8 | data[10];
-          if ((u != 0xffff) && (u != 0))
+          u = data[0x0B] << 8 | data[0x0A];
+          if ((u != 0xFFFF) && (u != 0))
           {
             if ((u == width) || (width == 0))
             {
@@ -1520,26 +1566,26 @@ int dmiversionmin)
           }
 
 // size
-          u = data[13] << 8 | data[12];
-          if(u == 0x7fff) {
-             unsigned long long extendsize = (data[0x1f] << 24) | (data[0x1e] << 16) | (data[0x1d] << 8) | data[0x1c];
-             extendsize &= 0x7fffffffUL;
+          u = data[0x0D] << 8 | data[0x0C];
+          if(u == 0x7FFF) {
+             unsigned long long extendsize = (data[0x1F] << 24) | (data[0x1E] << 16) | (data[0x1D] << 8) | data[0x1C];
+             extendsize &= 0x7FFFFFFFUL;
              size = extendsize * 1024ULL * 1024ULL;
           }
 	  else
-          if (u != 0xffff)
-            size = (1024ULL * (u & 0x7fff) * ((u & 0x8000) ? 1 : 1024ULL));
-          description += string(dmi_memory_device_form_factor(data[14]));
-          slot = dmi_string(dm, data[16]);
-//printf("\t\tBank Locator: %s\n", dmi_string(dm, data[17]));
-          description += string(dmi_memory_device_type(data[18]));
-          u = data[20] << 8 | data[19];
-          if (u & 0x1ffe)
+          if (u != 0xFFFF)
+            size = (1024ULL * (u & 0x7FFF) * ((u & 0x8000) ? 1 : 1024ULL));
+          description += string(dmi_memory_device_form_factor(data[0x0E]));
+          slot = dmi_string(dm, data[0x10]);
+//printf("\t\tBank Locator: %s\n", dmi_string(dm, data[0x11]));
+          description += string(dmi_memory_device_type(data[0x12]));
+          u = data[0x14] << 8 | data[0x13];
+          if (u & 0x1FFE)
             description += dmi_memory_device_detail(u);
-          if (dm->length > 21)
+          if (dm->length > 0x15)
           {
             char buffer[80];
-            u = data[22] << 8 | data[21];
+            u = data[0x16] << 8 | data[0x15];
 // speed
             clock = u * 1000000;                  // u is a frequency in MHz
             if (u == 0)
@@ -1553,12 +1599,12 @@ int dmiversionmin)
           newnode.setHandle(handle);
 //newnode.setPhysId(dm->handle);
           newnode.setSlot(slot);
-          if (dm->length > 23)
-            newnode.setVendor(dmi_string(dm, data[23]));
-          if (dm->length > 24)
-            newnode.setSerial(dmi_string(dm, data[24]));
-          if (dm->length > 26)
-            newnode.setProduct(dmi_string(dm, data[26]));
+          if (dm->length > 0x17)
+            newnode.setVendor(dmi_string(dm, data[0x17]));
+          if (dm->length > 0x18)
+            newnode.setSerial(dmi_string(dm, data[0x18]));
+          if (dm->length > 0x1A)
+            newnode.setProduct(dmi_string(dm, data[0x1A]));
           newnode.setDescription(description);
           newnode.setSize(size);
           if(newnode.getSize()==0)
@@ -1586,10 +1632,20 @@ int dmiversionmin)
         {
           hwNode newnode("range",
             hw::address);
-          unsigned long start, end;
+          uint64_t start = 0, end = 0;
           string arrayhandle = dmi_handle(data[0x0D] << 8 | data[0x0C]);
-          start = ((data[4] | data[5] << 8) | (data[6] | data[7] << 8) << 16);
-          end = ((data[8] | data[9] << 8) | (data[10] | data[11] << 8) << 16);
+          start = data[0x07] << 24 | data[0x06] << 16 | data[0x05] << 8 | data[0x04];
+          if (start == 0xFFFFFFFF)
+            start = uint64_t(data[0x16]) << 56 | uint64_t(data[0x15]) << 48 |
+                    uint64_t(data[0x14]) << 40 | uint64_t(data[0x13]) << 32 |
+                    uint64_t(data[0x12]) << 24 | uint64_t(data[0x11]) << 16 |
+                    uint64_t(data[0x10]) << 8 | uint64_t(data[0x0F]);
+          end = data[0x0B] << 24 | data[0x0A] << 16 | data[0x09] << 8 | data[0x08];
+          if (end == 0xFFFFFFFF)
+            end = uint64_t(data[0x1E]) << 56 | uint64_t(data[0x1D]) << 48 |
+                    uint64_t(data[0x1C]) << 40 | uint64_t(data[0x1B]) << 32 |
+                    uint64_t(data[0x1A]) << 24 | uint64_t(data[0x19]) << 16 |
+                    uint64_t(data[0x18]) << 8 | uint64_t(data[0x17]);
           if (end - start < 512)                  // memory range is smaller thant 512KB
           {
 // consider that values were expressed in megagytes
@@ -1614,10 +1670,20 @@ int dmiversionmin)
         {
           hwNode newnode("range",
             hw::address);
-          unsigned long start, end;
+          unsigned long long start = 0, end = 0;
           string devicehandle = dmi_handle(data[0x0D] << 8 | data[0x0C]);
-          start = ((data[4] | data[5] << 8) | (data[6] | data[7] << 8) << 16);
-          end = ((data[8] | data[9] << 8) | (data[10] | data[11] << 8) << 16);
+          start = data[0x07] << 24 | data[0x06] << 16 | data[0x05] << 8 | data[0x04];
+          if (start == 0xFFFFFFFF)
+            start = uint64_t(data[0x16]) << 56 | uint64_t(data[0x15]) << 48 |
+                    uint64_t(data[0x14]) << 40 | uint64_t(data[0x13]) << 32 |
+                    uint64_t(data[0x12]) << 24 | uint64_t(data[0x11]) << 16 |
+                    uint64_t(data[0x10]) << 8 | uint64_t(data[0x0F]);
+          end = data[0x0B] << 24 | data[0x0A] << 16 | data[0x09] << 8 | data[0x08];
+          if (end == 0xFFFFFFFF)
+            end = uint64_t(data[0x1E]) << 56 | uint64_t(data[0x1D]) << 48 |
+                    uint64_t(data[0x1C]) << 40 | uint64_t(data[0x1B]) << 32 |
+                    uint64_t(data[0x1A]) << 24 | uint64_t(data[0x19]) << 16 |
+                    uint64_t(data[0x18]) << 8 | uint64_t(data[0x17]);
           if (end - start < 512)                  // memory range is smaller than 512KB
           {
 // consider that values were expressed in megagytes
@@ -1661,11 +1727,11 @@ int dmiversionmin)
             batt.setVersion(dmi_string(dm, data[0x06]));
           if(data[0x07] || dm->length<0x1A)
             batt.setSerial(dmi_string(dm, data[0x07]));
-          batt.setConfig("voltage", dmi_battery_voltage(data[0x0c] + 256*data[0x0d]));
+          batt.setConfig("voltage", dmi_battery_voltage(data[0x0C] + 256*data[0x0D]));
           if(dm->length<0x1A)
-            batt.setCapacity(dmi_battery_capacity(data[0x0a] + 256*data[0x0b], 1));
+            batt.setCapacity(dmi_battery_capacity(data[0x0A] + 256*data[0x0B], 1));
           else
-            batt.setCapacity(dmi_battery_capacity(data[0x0a] + 256*data[0x0b], data[0x15]));
+            batt.setCapacity(dmi_battery_capacity(data[0x0A] + 256*data[0x0B], data[0x15]));
           if(data[0x09]!=0x02 || dm->length<0x1A)
             batt.setDescription(hw::strip(string(dmi_battery_chemistry(data[0x09])) + " Battery"));
 
@@ -1724,7 +1790,7 @@ int dmiversionmin)
 // System Boot Information
         if (dm->length < 0x0B)
           break;
-        node.setConfig("boot", dmi_bootinfo(data[0x0a]));
+        node.setConfig("boot", dmi_bootinfo(data[0x0A]));
         break;
       case 33:
 // 64-bit Memory Error Information
@@ -1755,9 +1821,9 @@ int dmiversionmin)
           power.setDescription(dmi_string(dm, data[0x06]));
           power.setVendor(dmi_string(dm, data[0x07]));
           power.setSerial(dmi_string(dm, data[0x08]));
-          power.setProduct(dmi_string(dm, data[0x0a]));
-          power.setVersion(dmi_string(dm, data[0x0b]));
-          power.setCapacity(data[0x0c] + 256*data[0x0d]);
+          power.setProduct(dmi_string(dm, data[0x0A]));
+          power.setVersion(dmi_string(dm, data[0x0B]));
+          power.setCapacity(data[0x0C] + 256*data[0x0D]);
           node.addChild(power);
         }
         break;
@@ -1780,17 +1846,19 @@ int dmiversionmin)
 
 
 static bool smbios_entry_point(const u8 *buf, size_t len,
-    hwNode & n, u16 & dmimaj, u16 & dmimin,
+    hwNode & n, u16 & dmimaj, u16 & dmimin, u16 & dmirev,
     uint32_t & table_len, uint64_t & table_base)
 {
   u8 smmajver = 0;
   u8 smminver = 0;
+  u8 smdocrev = 0;
 
   if (len >= 24 && memcmp(buf, "_SM3_", 5) == 0 && checksum(buf, buf[6]))
   {
     // SMBIOS 3.0 entry point structure (64-bit)
     dmimaj = smmajver = buf[7];
     dmimin = smminver = buf[8];
+    dmirev = smdocrev = buf[9];
     table_len = (((uint32_t) buf[15]) << 24) +
                 (((uint32_t) buf[14]) << 16) +
                 (((uint32_t) buf[13]) << 8) +
@@ -1823,9 +1891,16 @@ static bool smbios_entry_point(const u8 *buf, size_t len,
   if (smmajver > 0)
   {
     char buffer[20];
-    snprintf(buffer, sizeof(buffer), "%d.%d", smmajver, smminver);
+    if (smmajver == 3)
+      snprintf(buffer, sizeof(buffer), "%d.%d.%d", smmajver, smminver, smdocrev);
+    else
+      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);
+
+    if (dmimaj == 3)
+      snprintf(buffer, sizeof(buffer), "%d.%d.%d", dmimaj, dmimin, dmirev);
+    else
+      snprintf(buffer, sizeof(buffer), "%d.%d", dmimaj, dmimin);
     n.addCapability("dmi-"+string(buffer), "DMI version "+string(buffer));
 
     return true;
@@ -1842,7 +1917,7 @@ static bool scan_dmi_sysfs(hwNode & n)
 
   uint32_t table_len = 0;
   uint64_t table_base = 0;
-  u16 dmimaj = 0, dmimin = 0;
+  u16 dmimaj = 0, dmimin = 0, dmirev = 0;
 
   ifstream ep_stream(SYSFSDMI "/smbios_entry_point",
       ifstream::in | ifstream::binary | ifstream::ate);
@@ -1853,7 +1938,7 @@ static bool scan_dmi_sysfs(hwNode & n)
   if (!ep_stream)
     return false;
   if (!smbios_entry_point(ep_buf.data(), ep_len, n,
-        dmimaj, dmimin, table_len, table_base))
+        dmimaj, dmimin, dmirev, table_len, table_base))
     return false;
 
   ifstream dmi_stream(SYSFSDMI "/DMI",
@@ -1864,7 +1939,7 @@ static bool scan_dmi_sysfs(hwNode & n)
   dmi_stream.read((char *)dmi_buf.data(), dmi_len);
   if (!dmi_stream)
     return false;
-  dmi_table(dmi_buf.data(), dmi_len, n, dmimaj, dmimin);
+  dmi_table(dmi_buf.data(), dmi_len, n, dmimaj, dmimin, dmirev);
 
   return true;
 }
@@ -1902,7 +1977,7 @@ static bool scan_dmi_devmem(hwNode & n)
   u32 mmoffset = 0;
   void *mmp = NULL;
   bool efi = true;
-  u16 dmimaj = 0, dmimin = 0;
+  u16 dmimaj = 0, dmimin = 0, dmirev = 0;
 
   if (fd == -1)
     return false;
@@ -1932,7 +2007,7 @@ static bool scan_dmi_devmem(hwNode & n)
     }
     uint32_t len;
     uint64_t base;
-    if (smbios_entry_point(buf, sizeof(buf), n, dmimaj, dmimin, len, base))
+    if (smbios_entry_point(buf, sizeof(buf), n, dmimaj, dmimin, dmirev, len, base))
     {
       u8 *dmi_buf = (u8 *)malloc(len);
       mmoffset = base % getpagesize();
@@ -1944,7 +2019,7 @@ static bool scan_dmi_devmem(hwNode & n)
       }
       memcpy(dmi_buf, (u8 *) mmp + mmoffset, len);
       munmap(mmp, mmoffset + len);
-      dmi_table(dmi_buf, len, n, dmimaj, dmimin);
+      dmi_table(dmi_buf, len, n, dmimaj, dmimin, dmirev);
       free(dmi_buf);
       break;
     }
diff --git a/src/core/pci.cc b/src/core/pci.cc
index d1625cf..fa6a1e5 100644
--- a/src/core/pci.cc
+++ b/src/core/pci.cc
@@ -774,8 +774,12 @@ static hwNode *scan_pci_dev(struct pci_dev &d, hwNode & n)
   if(!pcidb_loaded)
     pcidb_loaded = load_pcidb();
 
-      d.vendor_id = get_conf_word(d, PCI_VENDOR_ID);
-      d.device_id = get_conf_word(d, PCI_DEVICE_ID);
+      u_int16_t tmp_vendor_id = get_conf_word(d, PCI_VENDOR_ID);
+      u_int16_t tmp_device_id = get_conf_word(d, PCI_DEVICE_ID);
+      if ((tmp_vendor_id & tmp_device_id) != 0xffff) {
+        d.vendor_id = tmp_vendor_id;
+        d.device_id = tmp_device_id;
+      }
       u_int16_t dclass = get_conf_word(d, PCI_CLASS_DEVICE);
       u_int16_t cmd = get_conf_word(d, PCI_COMMAND);
       u_int16_t status = get_conf_word(d, PCI_STATUS);
@@ -1122,6 +1126,7 @@ bool scan_pci(hwNode & n)
     if(matches(devices[i]->d_name, "^[[:xdigit:]]+:[[:xdigit:]]+:[[:xdigit:]]+\\.[[:xdigit:]]+$"))
     {
       string devicepath = string(devices[i]->d_name)+"/config";
+      sysfs::entry device_entry = sysfs::entry::byBus("pci", devices[i]->d_name);
       struct pci_dev d;
       int fd = open(devicepath.c_str(), O_RDONLY);
       if (fd >= 0)
@@ -1136,6 +1141,8 @@ bool scan_pci(hwNode & n)
       }
 
       sscanf(devices[i]->d_name, "%hx:%hx:%hhx.%hhx", &d.domain, &d.bus, &d.dev, &d.func);
+      sscanf(device_entry.vendor().c_str(), "%hx", &d.vendor_id);
+      sscanf(device_entry.device().c_str(), "%hx", &d.device_id);
       hwNode *device = scan_pci_dev(d, n);
 
       if(device)
@@ -1166,7 +1173,7 @@ bool scan_pci(hwNode & n)
           device->claim();
         }
 
-	device->setModalias(sysfs::entry::byBus("pci", devices[i]->d_name).modalias());
+        device->setModalias(device_entry.modalias());
 
         if(exists(resourcename))
         {
diff --git a/src/core/sysfs.cc b/src/core/sysfs.cc
index 97dbab5..486f8ee 100644
--- a/src/core/sysfs.cc
+++ b/src/core/sysfs.cc
@@ -358,6 +358,16 @@ string entry::modalias() const
   return get_string(This->devpath+"/modalias");
 }
 
+string entry::device() const
+{
+  return get_string(This->devpath+"/device");
+}
+
+string entry::vendor() const
+{
+  return get_string(This->devpath+"/vendor");
+}
+
 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 d37e2d4..dffa4b2 100644
--- a/src/core/sysfs.h
+++ b/src/core/sysfs.h
@@ -26,6 +26,8 @@ namespace sysfs
       string businfo() const;
       string driver() const;
       string modalias() const;
+      string device() const;
+      string vendor() const;
       entry parent() const;
       string name_in_class(const string &) const;
       string string_attr(const string & name, const string & def = "") const;
-- 
2.14.0