Hardware/SMBIOS.cs
author moel.mich
Thu, 26 Jul 2012 06:50:56 +0000
changeset 376 df64b56ece65
parent 370 8e4dedc41924
child 378 64d3ddf8d73b
permissions -rw-r--r--
Fixed an error where loading config files from previous versions would crash the application.
     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 MemoryDevice[] memoryDevices;
    29 
    30     private static string ReadSysFS(string path) {
    31       try {
    32         if (File.Exists(path)) {
    33           using (StreamReader reader = new StreamReader(path)) 
    34             return reader.ReadLine();
    35         } else {
    36           return null;
    37         }
    38       } catch {
    39         return null;
    40       }
    41     }
    42     
    43     public SMBIOS() {
    44       int p = (int)Environment.OSVersion.Platform;
    45       if ((p == 4) || (p == 128)) {
    46         this.raw = null;
    47         this.table = null;
    48         
    49         string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
    50         string boardName = ReadSysFS("/sys/class/dmi/id/board_name");        
    51         string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");        
    52         this.baseBoardInformation = new BaseBoardInformation(
    53           boardVendor, boardName, boardVersion, null);
    54 
    55         string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor");
    56         string productName = ReadSysFS("/sys/class/dmi/id/product_name");
    57         string productVersion = ReadSysFS("/sys/class/dmi/id/product_version");    
    58         this.systemInformation = new SystemInformation(systemVendor, 
    59           productName, productVersion, null, null);
    60 
    61         string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
    62         string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
    63         this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
    64 
    65         this.memoryDevices = new MemoryDevice[0];
    66       } else {              
    67         List<Structure> structureList = new List<Structure>();
    68         List<MemoryDevice> memoryDeviceList = new List<MemoryDevice>();
    69 
    70         raw = null;
    71         byte majorVersion = 0;
    72         byte minorVersion = 0;
    73         try {
    74           ManagementObjectCollection collection;
    75           using (ManagementObjectSearcher searcher = 
    76             new ManagementObjectSearcher("root\\WMI", 
    77               "SELECT * FROM MSSMBios_RawSMBiosTables")) {
    78             collection = searcher.Get();
    79           }
    80          
    81           foreach (ManagementObject mo in collection) {
    82             raw = (byte[])mo["SMBiosData"];
    83             majorVersion = (byte)mo["SmbiosMajorVersion"];
    84             minorVersion = (byte)mo["SmbiosMinorVersion"];            
    85             break;
    86           }
    87         } catch { }
    88 
    89         if (majorVersion > 0 || minorVersion > 0)
    90           version = new Version(majorVersion, minorVersion);
    91   
    92         if (raw != null && raw.Length > 0) {
    93           int offset = 0;
    94           byte type = raw[offset];
    95           while (offset + 4 < raw.Length && type != 127) {
    96   
    97             type = raw[offset];
    98             int length = raw[offset + 1];
    99             ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
   100   
   101             if (offset + length > raw.Length)
   102               break;
   103             byte[] data = new byte[length];
   104             Array.Copy(raw, offset, data, 0, length);
   105             offset += length;
   106   
   107             List<string> stringsList = new List<string>();
   108             if (offset < raw.Length && raw[offset] == 0)
   109               offset++;
   110   
   111             while (offset < raw.Length && raw[offset] != 0) {
   112               StringBuilder sb = new StringBuilder();
   113               while (offset < raw.Length && raw[offset] != 0) {
   114                 sb.Append((char)raw[offset]); offset++;
   115               }
   116               offset++;
   117               stringsList.Add(sb.ToString());
   118             }
   119             offset++;
   120             switch (type) {
   121               case 0x00:
   122                 this.biosInformation = new BIOSInformation(
   123                   type, handle, data, stringsList.ToArray());
   124                 structureList.Add(this.biosInformation); break;
   125               case 0x01:
   126                 this.systemInformation = new SystemInformation(
   127                   type, handle, data, stringsList.ToArray());
   128                 structureList.Add(this.systemInformation); break;
   129               case 0x02: this.baseBoardInformation = new BaseBoardInformation(
   130                   type, handle, data, stringsList.ToArray());
   131                 structureList.Add(this.baseBoardInformation); break;
   132               case 0x11: MemoryDevice m = new MemoryDevice(
   133                   type, handle, data, stringsList.ToArray());
   134                 memoryDeviceList.Add(m);
   135                 structureList.Add(m); break;
   136               default: structureList.Add(new Structure(
   137                 type, handle, data, stringsList.ToArray())); break;
   138             }
   139           }
   140         }
   141 
   142         memoryDevices = memoryDeviceList.ToArray();
   143         table = structureList.ToArray();
   144       }
   145     }
   146 
   147     public string GetReport() {
   148       StringBuilder r = new StringBuilder();
   149 
   150       if (version != null) {
   151         r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2));
   152         r.AppendLine();
   153       }
   154 
   155       if (BIOS != null) {
   156         r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor);
   157         r.Append("BIOS Version: "); r.AppendLine(BIOS.Version);
   158         r.AppendLine();
   159       }
   160 
   161       if (System != null) {
   162         r.Append("System Manufacturer: ");
   163         r.AppendLine(System.ManufacturerName);
   164         r.Append("System Name: ");
   165         r.AppendLine(System.ProductName);
   166         r.Append("System Version: ");
   167         r.AppendLine(System.Version);
   168         r.AppendLine();
   169       }
   170 
   171       if (Board != null) {
   172         r.Append("Mainboard Manufacturer: ");
   173         r.AppendLine(Board.ManufacturerName);
   174         r.Append("Mainboard Name: ");
   175         r.AppendLine(Board.ProductName);
   176         r.Append("Mainboard Version: ");
   177         r.AppendLine(Board.Version);
   178         r.AppendLine();
   179       }
   180 
   181       for (int i = 0; i < MemoryDevices.Length; i++) {        
   182         r.Append("Memory Device [" + i + "] Manufacturer: ");
   183         r.AppendLine(MemoryDevices[i].ManufacturerName);
   184         r.Append("Memory Device [" + i + "] Part Number: ");
   185         r.AppendLine(MemoryDevices[i].PartNumber);
   186         r.Append("Memory Device [" + i + "] Device Locator: ");
   187         r.AppendLine(MemoryDevices[i].DeviceLocator);
   188         r.Append("Memory Device [" + i + "] Bank Locator: ");
   189         r.AppendLine(MemoryDevices[i].BankLocator);
   190         r.AppendLine();
   191       }
   192 
   193       if (raw != null) {
   194         string base64 = Convert.ToBase64String(raw);
   195         r.AppendLine("SMBIOS Table");
   196         r.AppendLine();
   197 
   198         for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
   199           r.Append(" ");
   200           for (int j = 0; j < 0x40; j++) {
   201             int index = (i << 6) | j;
   202             if (index < base64.Length) {              
   203               r.Append(base64[index]);
   204             }
   205           }
   206           r.AppendLine();
   207         }
   208         r.AppendLine();
   209       }
   210 
   211       return r.ToString();
   212     }
   213 
   214     public BIOSInformation BIOS {
   215       get { return biosInformation; }
   216     }
   217 
   218     public SystemInformation System {
   219       get { return systemInformation; }
   220     }
   221 
   222     public BaseBoardInformation Board {
   223       get { return baseBoardInformation; }
   224     }
   225 
   226     public MemoryDevice[] MemoryDevices {
   227       get { return memoryDevices; }
   228     }
   229 
   230     public class Structure {
   231       private readonly byte type;
   232       private readonly ushort handle;
   233 
   234       private readonly byte[] data;
   235       private readonly string[] strings;
   236 
   237       protected string GetString(int offset) {
   238         if (offset < data.Length && data[offset] > 0 &&
   239          data[offset] <= strings.Length)
   240           return strings[data[offset] - 1];
   241         else
   242           return "";
   243       }
   244 
   245       public Structure(byte type, ushort handle, byte[] data, string[] strings) 
   246       {
   247         this.type = type;
   248         this.handle = handle;
   249         this.data = data;
   250         this.strings = strings;
   251       }
   252 
   253       public byte Type { get { return type; } }
   254 
   255       public ushort Handle { get { return handle; } }
   256     }
   257       
   258     public class BIOSInformation : Structure {
   259 
   260       private readonly string vendor;
   261       private readonly string version;
   262       
   263       public BIOSInformation(string vendor, string version) 
   264         : base (0x00, 0, null, null) 
   265       {
   266         this.vendor = vendor;
   267         this.version = version;
   268       }
   269       
   270       public BIOSInformation(byte type, ushort handle, byte[] data,
   271         string[] strings)
   272         : base(type, handle, data, strings) 
   273       {
   274         this.vendor = GetString(0x04);
   275         this.version = GetString(0x05);
   276       }
   277 
   278       public string Vendor { get { return vendor; } }
   279 
   280       public string Version { get { return version; } }
   281     }
   282 
   283     public class SystemInformation : Structure {
   284 
   285       private readonly string manufacturerName;
   286       private readonly string productName;
   287       private readonly string version;
   288       private readonly string serialNumber;
   289       private readonly string family;
   290 
   291       public SystemInformation(string manufacturerName, string productName, 
   292         string version, string serialNumber, string family) 
   293         : base (0x01, 0, null, null) 
   294       {
   295         this.manufacturerName = manufacturerName;
   296         this.productName = productName;
   297         this.version = version;
   298         this.serialNumber = serialNumber;
   299         this.family = family;
   300       }
   301 
   302       public SystemInformation(byte type, ushort handle, byte[] data,
   303         string[] strings)
   304         : base(type, handle, data, strings) 
   305       {
   306         this.manufacturerName = GetString(0x04);
   307         this.productName = GetString(0x05);
   308         this.version = GetString(0x06);
   309         this.serialNumber = GetString(0x07);
   310         this.family = GetString(0x1A);
   311       }
   312 
   313       public string ManufacturerName { get { return manufacturerName; } }
   314 
   315       public string ProductName { get { return productName; } }
   316 
   317       public string Version { get { return version; } }
   318 
   319       public string SerialNumber { get { return serialNumber; } }
   320 
   321       public string Family { get { return family; } }
   322 
   323     }
   324 
   325     public class BaseBoardInformation : Structure {
   326 
   327       private readonly string manufacturerName;
   328       private readonly string productName;
   329       private readonly string version;
   330       private readonly string serialNumber;
   331       
   332       public BaseBoardInformation(string manufacturerName, string productName, 
   333         string version, string serialNumber) 
   334         : base(0x02, 0, null, null) 
   335       {
   336         this.manufacturerName = manufacturerName;
   337         this.productName = productName;
   338         this.version = version;
   339         this.serialNumber = serialNumber;
   340       }
   341       
   342       public BaseBoardInformation(byte type, ushort handle, byte[] data,
   343         string[] strings)
   344         : base(type, handle, data, strings) {
   345 
   346         this.manufacturerName = GetString(0x04).Trim();
   347         this.productName = GetString(0x05).Trim();
   348         this.version = GetString(0x06).Trim();
   349         this.serialNumber = GetString(0x07).Trim();               
   350       }
   351       
   352       public string ManufacturerName { get { return manufacturerName; } }
   353 
   354       public string ProductName { get { return productName; } }
   355 
   356       public string Version { get { return version; } }
   357 
   358       public string SerialNumber { get { return serialNumber; } }
   359 
   360     }
   361 
   362     public class MemoryDevice : Structure {
   363 
   364       private readonly string deviceLocator;
   365       private readonly string bankLocator;
   366       private readonly string manufacturerName;
   367       private readonly string serialNumber;
   368       private readonly string partNumber;      
   369 
   370       public MemoryDevice(byte type, ushort handle, byte[] data,
   371         string[] strings)
   372         : base(type, handle, data, strings) 
   373       {
   374         this.deviceLocator = GetString(0x10).Trim();
   375         this.bankLocator = GetString(0x11).Trim();
   376         this.manufacturerName = GetString(0x17).Trim();
   377         this.serialNumber = GetString(0x18).Trim();
   378         this.partNumber = GetString(0x1A).Trim();
   379       }
   380 
   381       public string DeviceLocator { get { return deviceLocator; } }
   382 
   383       public string BankLocator { get { return bankLocator; } }
   384 
   385       public string ManufacturerName { get { return manufacturerName; } }
   386 
   387       public string SerialNumber { get { return serialNumber; } }
   388 
   389       public string PartNumber { get { return partNumber; } }
   390 
   391        
   392 
   393     }
   394   }
   395 }