Hardware/SMBIOS.cs
author moel.mich
Tue, 30 Dec 2014 21:04:54 +0000
changeset 430 6b24e39f1b84
parent 373 3b8443edb0e6
permissions -rw-r--r--
Fixed Issue 651.
     1 /*
     2  
     3   This Source Code Form is subject to the terms of the Mozilla Public
     4   License, v. 2.0. If a copy of the MPL was not distributed with this
     5   file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6  
     7   Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
     8 	
     9 */
    10 
    11 using System;
    12 using System.Collections.Generic;
    13 using System.IO;
    14 using System.Management;
    15 using System.Text;
    16 
    17 namespace OpenHardwareMonitor.Hardware {
    18 
    19   internal class SMBIOS {
    20 
    21     private readonly byte[] raw;
    22     private readonly Structure[] table;
    23 
    24     private readonly Version version;
    25     private readonly BIOSInformation biosInformation;
    26     private readonly SystemInformation systemInformation;
    27     private readonly BaseBoardInformation baseBoardInformation;
    28     private readonly ProcessorInformation processorInformation;
    29     private readonly MemoryDevice[] memoryDevices;
    30 
    31     private static string ReadSysFS(string path) {
    32       try {
    33         if (File.Exists(path)) {
    34           using (StreamReader reader = new StreamReader(path)) 
    35             return reader.ReadLine();
    36         } else {
    37           return null;
    38         }
    39       } catch {
    40         return null;
    41       }
    42     }
    43     
    44     public SMBIOS() {
    45       int p = (int)Environment.OSVersion.Platform;
    46       if ((p == 4) || (p == 128)) {
    47         this.raw = null;
    48         this.table = null;
    49         
    50         string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
    51         string boardName = ReadSysFS("/sys/class/dmi/id/board_name");        
    52         string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");        
    53         this.baseBoardInformation = new BaseBoardInformation(
    54           boardVendor, boardName, boardVersion, null);
    55 
    56         string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor");
    57         string productName = ReadSysFS("/sys/class/dmi/id/product_name");
    58         string productVersion = ReadSysFS("/sys/class/dmi/id/product_version");    
    59         this.systemInformation = new SystemInformation(systemVendor, 
    60           productName, productVersion, null, null);
    61 
    62         string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
    63         string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
    64         this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
    65 
    66         this.memoryDevices = new MemoryDevice[0];
    67       } else {              
    68         List<Structure> structureList = new List<Structure>();
    69         List<MemoryDevice> memoryDeviceList = new List<MemoryDevice>();
    70 
    71         raw = null;
    72         byte majorVersion = 0;
    73         byte minorVersion = 0;
    74         try {
    75           ManagementObjectCollection collection;
    76           using (ManagementObjectSearcher searcher = 
    77             new ManagementObjectSearcher("root\\WMI", 
    78               "SELECT * FROM MSSMBios_RawSMBiosTables")) {
    79             collection = searcher.Get();
    80           }
    81          
    82           foreach (ManagementObject mo in collection) {
    83             raw = (byte[])mo["SMBiosData"];
    84             majorVersion = (byte)mo["SmbiosMajorVersion"];
    85             minorVersion = (byte)mo["SmbiosMinorVersion"];            
    86             break;
    87           }
    88         } catch { }      
    89 
    90         if (majorVersion > 0 || minorVersion > 0)
    91           version = new Version(majorVersion, minorVersion);
    92   
    93         if (raw != null && raw.Length > 0) {
    94           int offset = 0;
    95           byte type = raw[offset];
    96           while (offset + 4 < raw.Length && type != 127) {
    97   
    98             type = raw[offset];
    99             int length = raw[offset + 1];
   100             ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
   101   
   102             if (offset + length > raw.Length)
   103               break;
   104             byte[] data = new byte[length];
   105             Array.Copy(raw, offset, data, 0, length);
   106             offset += length;
   107   
   108             List<string> stringsList = new List<string>();
   109             if (offset < raw.Length && raw[offset] == 0)
   110               offset++;
   111   
   112             while (offset < raw.Length && raw[offset] != 0) {
   113               StringBuilder sb = new StringBuilder();
   114               while (offset < raw.Length && raw[offset] != 0) {
   115                 sb.Append((char)raw[offset]); offset++;
   116               }
   117               offset++;
   118               stringsList.Add(sb.ToString());
   119             }
   120             offset++;
   121             switch (type) {
   122               case 0x00:
   123                 this.biosInformation = new BIOSInformation(
   124                   type, handle, data, stringsList.ToArray());
   125                 structureList.Add(this.biosInformation); break;
   126               case 0x01:
   127                 this.systemInformation = new SystemInformation(
   128                   type, handle, data, stringsList.ToArray());
   129                 structureList.Add(this.systemInformation); break;
   130               case 0x02: this.baseBoardInformation = new BaseBoardInformation(
   131                   type, handle, data, stringsList.ToArray());
   132                 structureList.Add(this.baseBoardInformation); break;
   133               case 0x04: this.processorInformation = new ProcessorInformation(
   134                   type, handle, data, stringsList.ToArray());
   135                 structureList.Add(this.processorInformation); break;
   136               case 0x11: MemoryDevice m = new MemoryDevice(
   137                   type, handle, data, stringsList.ToArray());
   138                 memoryDeviceList.Add(m);
   139                 structureList.Add(m); break;
   140               default: structureList.Add(new Structure(
   141                 type, handle, data, stringsList.ToArray())); break;
   142             }
   143           }
   144         }
   145 
   146         memoryDevices = memoryDeviceList.ToArray();
   147         table = structureList.ToArray();
   148       }
   149     }
   150 
   151     public string GetReport() {
   152       StringBuilder r = new StringBuilder();
   153 
   154       if (version != null) {
   155         r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2));
   156         r.AppendLine();
   157       }
   158 
   159       if (BIOS != null) {
   160         r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor);
   161         r.Append("BIOS Version: "); r.AppendLine(BIOS.Version);
   162         r.AppendLine();
   163       }
   164 
   165       if (System != null) {
   166         r.Append("System Manufacturer: ");
   167         r.AppendLine(System.ManufacturerName);
   168         r.Append("System Name: ");
   169         r.AppendLine(System.ProductName);
   170         r.Append("System Version: ");
   171         r.AppendLine(System.Version);
   172         r.AppendLine();
   173       }
   174 
   175       if (Board != null) {
   176         r.Append("Mainboard Manufacturer: ");
   177         r.AppendLine(Board.ManufacturerName);
   178         r.Append("Mainboard Name: ");
   179         r.AppendLine(Board.ProductName);
   180         r.Append("Mainboard Version: ");
   181         r.AppendLine(Board.Version);
   182         r.AppendLine();
   183       }
   184 
   185       if (Processor != null) {
   186         r.Append("Processor Manufacturer: ");
   187         r.AppendLine(Processor.ManufacturerName);
   188         r.Append("Processor Version: ");
   189         r.AppendLine(Processor.Version);
   190         r.Append("Processor Core Count: ");
   191         r.AppendLine(Processor.CoreCount.ToString());
   192         r.Append("Processor Core Enabled: ");
   193         r.AppendLine(Processor.CoreEnabled.ToString());
   194         r.Append("Processor Thread Count: ");
   195         r.AppendLine(Processor.ThreadCount.ToString());
   196         r.Append("Processor External Clock: ");
   197         r.Append(Processor.ExternalClock);
   198         r.AppendLine(" Mhz");
   199         r.AppendLine();
   200       }
   201 
   202       for (int i = 0; i < MemoryDevices.Length; i++) {        
   203         r.Append("Memory Device [" + i + "] Manufacturer: ");
   204         r.AppendLine(MemoryDevices[i].ManufacturerName);
   205         r.Append("Memory Device [" + i + "] Part Number: ");
   206         r.AppendLine(MemoryDevices[i].PartNumber);
   207         r.Append("Memory Device [" + i + "] Device Locator: ");
   208         r.AppendLine(MemoryDevices[i].DeviceLocator);
   209         r.Append("Memory Device [" + i + "] Bank Locator: ");
   210         r.AppendLine(MemoryDevices[i].BankLocator);
   211         r.Append("Memory Device [" + i + "] Speed: ");
   212         r.Append(MemoryDevices[i].Speed);
   213         r.AppendLine(" MHz");
   214         r.AppendLine();
   215       }
   216 
   217       if (raw != null) {
   218         string base64 = Convert.ToBase64String(raw);
   219         r.AppendLine("SMBIOS Table");
   220         r.AppendLine();
   221 
   222         for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
   223           r.Append(" ");
   224           for (int j = 0; j < 0x40; j++) {
   225             int index = (i << 6) | j;
   226             if (index < base64.Length) {              
   227               r.Append(base64[index]);
   228             }
   229           }
   230           r.AppendLine();
   231         }
   232         r.AppendLine();
   233       }
   234 
   235       return r.ToString();
   236     }
   237 
   238     public BIOSInformation BIOS {
   239       get { return biosInformation; }
   240     }
   241 
   242     public SystemInformation System {
   243       get { return systemInformation; }
   244     }
   245 
   246     public BaseBoardInformation Board {
   247       get { return baseBoardInformation; }
   248     }
   249 
   250 
   251     public ProcessorInformation Processor {
   252       get { return processorInformation; }
   253     }
   254 
   255     public MemoryDevice[] MemoryDevices {
   256       get { return memoryDevices; }
   257     }
   258 
   259     public class Structure {
   260       private readonly byte type;
   261       private readonly ushort handle;
   262 
   263       private readonly byte[] data;
   264       private readonly string[] strings;
   265 
   266       protected int GetByte(int offset) {
   267         if (offset < data.Length && offset >= 0)
   268           return data[offset];
   269         else
   270           return 0;
   271       }
   272 
   273       protected int GetWord(int offset) {
   274         if (offset + 1 < data.Length && offset >= 0)
   275           return (data[offset + 1] << 8) | data[offset];
   276         else
   277           return 0;
   278       }
   279 
   280       protected string GetString(int offset) {
   281         if (offset < data.Length && data[offset] > 0 &&
   282          data[offset] <= strings.Length)
   283           return strings[data[offset] - 1];
   284         else
   285           return "";
   286       }
   287 
   288       public Structure(byte type, ushort handle, byte[] data, string[] strings) 
   289       {
   290         this.type = type;
   291         this.handle = handle;
   292         this.data = data;
   293         this.strings = strings;
   294       }
   295 
   296       public byte Type { get { return type; } }
   297 
   298       public ushort Handle { get { return handle; } }
   299     }
   300       
   301     public class BIOSInformation : Structure {
   302 
   303       private readonly string vendor;
   304       private readonly string version;
   305       
   306       public BIOSInformation(string vendor, string version) 
   307         : base (0x00, 0, null, null) 
   308       {
   309         this.vendor = vendor;
   310         this.version = version;
   311       }
   312       
   313       public BIOSInformation(byte type, ushort handle, byte[] data,
   314         string[] strings)
   315         : base(type, handle, data, strings) 
   316       {
   317         this.vendor = GetString(0x04);
   318         this.version = GetString(0x05);
   319       }
   320 
   321       public string Vendor { get { return vendor; } }
   322 
   323       public string Version { get { return version; } }
   324     }
   325 
   326     public class SystemInformation : Structure {
   327 
   328       private readonly string manufacturerName;
   329       private readonly string productName;
   330       private readonly string version;
   331       private readonly string serialNumber;
   332       private readonly string family;
   333 
   334       public SystemInformation(string manufacturerName, string productName, 
   335         string version, string serialNumber, string family) 
   336         : base (0x01, 0, null, null) 
   337       {
   338         this.manufacturerName = manufacturerName;
   339         this.productName = productName;
   340         this.version = version;
   341         this.serialNumber = serialNumber;
   342         this.family = family;
   343       }
   344 
   345       public SystemInformation(byte type, ushort handle, byte[] data,
   346         string[] strings)
   347         : base(type, handle, data, strings) 
   348       {
   349         this.manufacturerName = GetString(0x04);
   350         this.productName = GetString(0x05);
   351         this.version = GetString(0x06);
   352         this.serialNumber = GetString(0x07);
   353         this.family = GetString(0x1A);
   354       }
   355 
   356       public string ManufacturerName { get { return manufacturerName; } }
   357 
   358       public string ProductName { get { return productName; } }
   359 
   360       public string Version { get { return version; } }
   361 
   362       public string SerialNumber { get { return serialNumber; } }
   363 
   364       public string Family { get { return family; } }
   365 
   366     }
   367 
   368     public class BaseBoardInformation : Structure {
   369 
   370       private readonly string manufacturerName;
   371       private readonly string productName;
   372       private readonly string version;
   373       private readonly string serialNumber;
   374       
   375       public BaseBoardInformation(string manufacturerName, string productName, 
   376         string version, string serialNumber) 
   377         : base(0x02, 0, null, null) 
   378       {
   379         this.manufacturerName = manufacturerName;
   380         this.productName = productName;
   381         this.version = version;
   382         this.serialNumber = serialNumber;
   383       }
   384       
   385       public BaseBoardInformation(byte type, ushort handle, byte[] data,
   386         string[] strings)
   387         : base(type, handle, data, strings) {
   388 
   389         this.manufacturerName = GetString(0x04).Trim();
   390         this.productName = GetString(0x05).Trim();
   391         this.version = GetString(0x06).Trim();
   392         this.serialNumber = GetString(0x07).Trim();               
   393       }
   394       
   395       public string ManufacturerName { get { return manufacturerName; } }
   396 
   397       public string ProductName { get { return productName; } }
   398 
   399       public string Version { get { return version; } }
   400 
   401       public string SerialNumber { get { return serialNumber; } }
   402 
   403     }
   404 
   405     public class ProcessorInformation : Structure {
   406 
   407       public ProcessorInformation(byte type, ushort handle, byte[] data,
   408         string[] strings)
   409         : base(type, handle, data, strings) 
   410       {
   411         this.ManufacturerName = GetString(0x07).Trim();
   412         this.Version = GetString(0x10).Trim();
   413         this.CoreCount = GetByte(0x23);
   414         this.CoreEnabled = GetByte(0x24);
   415         this.ThreadCount = GetByte(0x25);
   416         this.ExternalClock = GetWord(0x12);
   417       }
   418 
   419       public string ManufacturerName { get; private set; }
   420 
   421       public string Version { get; private set; }
   422 
   423       public int CoreCount { get; private set; }
   424 
   425       public int CoreEnabled { get; private set; }
   426 
   427       public int ThreadCount { get; private set; }
   428      
   429       public int ExternalClock { get; private set; }
   430     }
   431 
   432     public class MemoryDevice : Structure {
   433 
   434       private readonly string deviceLocator;
   435       private readonly string bankLocator;
   436       private readonly string manufacturerName;
   437       private readonly string serialNumber;
   438       private readonly string partNumber;
   439       private readonly int speed;
   440 
   441       public MemoryDevice(byte type, ushort handle, byte[] data,
   442         string[] strings)
   443         : base(type, handle, data, strings) 
   444       {
   445         this.deviceLocator = GetString(0x10).Trim();
   446         this.bankLocator = GetString(0x11).Trim();
   447         this.manufacturerName = GetString(0x17).Trim();
   448         this.serialNumber = GetString(0x18).Trim();
   449         this.partNumber = GetString(0x1A).Trim();
   450         this.speed = GetWord(0x15);
   451       }
   452 
   453       public string DeviceLocator { get { return deviceLocator; } }
   454 
   455       public string BankLocator { get { return bankLocator; } }
   456 
   457       public string ManufacturerName { get { return manufacturerName; } }
   458 
   459       public string SerialNumber { get { return serialNumber; } }
   460 
   461       public string PartNumber { get { return partNumber; } }
   462 
   463       public int Speed { get { return speed; } }
   464 
   465     }
   466   }
   467 }