Hardware/Mainboard/SMBIOS.cs
author moel.mich
Sun, 08 Aug 2010 13:57:26 +0000
changeset 165 813d8bc3192f
parent 154 9257814ba151
child 167 b7cc9d09aefe
permissions -rw-r--r--
Refactored the hardware monitoring code into a library (Issue 101).
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     5   The contents of this file are subject to the Mozilla Public License Version
     6   1.1 (the "License"); you may not use this file except in compliance with
     7   the License. You may obtain a copy of the License at
     8  
     9   http://www.mozilla.org/MPL/
    10 
    11   Software distributed under the License is distributed on an "AS IS" basis,
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13   for the specific language governing rights and limitations under the License.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    17   The Initial Developer of the Original Code is 
    18   Michael Möller <m.moeller@gmx.ch>.
    19   Portions created by the Initial Developer are Copyright (C) 2009-2010
    20   the Initial Developer. All Rights Reserved.
    21 
    22   Contributor(s):
    23 
    24   Alternatively, the contents of this file may be used under the terms of
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    27   in which case the provisions of the GPL or the LGPL are applicable instead
    28   of those above. If you wish to allow use of your version of this file only
    29   under the terms of either the GPL or the LGPL, and not to allow others to
    30   use your version of this file under the terms of the MPL, indicate your
    31   decision by deleting the provisions above and replace them with the notice
    32   and other provisions required by the GPL or the LGPL. If you do not delete
    33   the provisions above, a recipient may use your version of this file under
    34   the terms of any one of the MPL, the GPL or the LGPL.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.IO;
    41 using System.Management;
    42 using System.Text;
    43 
    44 namespace OpenHardwareMonitor.Hardware.Mainboard {
    45 
    46   internal class SMBIOS {
    47 
    48     private byte[] raw;
    49     private Structure[] table;
    50 
    51     private BIOSInformation biosInformation = null;
    52     private BaseBoardInformation baseBoardInformation = null;
    53 
    54     private string ReadSysFS(string path) {
    55       try {
    56         if (File.Exists(path)) {
    57           using (StreamReader reader = new StreamReader(path)) 
    58             return reader.ReadLine();
    59         } else {
    60           return null;
    61         }
    62       } catch {
    63         return null;
    64       }
    65     }
    66     
    67     public SMBIOS() {
    68       int p = (int)System.Environment.OSVersion.Platform;
    69       if ((p == 4) || (p == 128)) {
    70         this.raw = null;
    71         this.table = null;
    72         
    73         string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
    74         string boardName = ReadSysFS("/sys/class/dmi/id/board_name");        
    75         string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");        
    76         this.baseBoardInformation = new BaseBoardInformation(
    77           boardVendor, boardName, boardVersion, null);
    78         
    79         string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
    80         string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
    81         this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
    82         
    83       } else {              
    84         List<Structure> structureList = new List<Structure>();
    85 
    86         raw = null;
    87         try {
    88           ManagementObjectCollection collection = 
    89             new ManagementObjectSearcher("root\\WMI", 
    90               "SELECT SMBiosData FROM MSSMBios_RawSMBiosTables").Get();
    91          
    92           foreach (ManagementObject mo in collection) {
    93             raw = (byte[])mo["SMBiosData"];
    94             break;
    95           }
    96         } catch { }
    97   
    98         if (raw != null && raw.Length > 0) {
    99           int offset = 0;
   100           byte type = raw[offset];
   101           while (offset + 4 < raw.Length && type != 127) {
   102   
   103             type = raw[offset];
   104             int length = raw[offset + 1];
   105             ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
   106   
   107             if (offset + length > raw.Length)
   108               break;
   109             byte[] data = new byte[length];
   110             Array.Copy(raw, offset, data, 0, length);
   111             offset += length;
   112   
   113             List<string> stringsList = new List<string>();
   114             if (offset < raw.Length && raw[offset] == 0)
   115               offset++;
   116   
   117             while (offset < raw.Length && raw[offset] != 0) {
   118               StringBuilder sb = new StringBuilder();
   119               while (offset < raw.Length && raw[offset] != 0) {
   120                 sb.Append((char)raw[offset]); offset++;
   121               }
   122               offset++;
   123               stringsList.Add(sb.ToString());
   124             }
   125             offset++;
   126             switch (type) {
   127               case 0x00:
   128                 this.biosInformation = new BIOSInformation(
   129                   type, handle, data, stringsList.ToArray());
   130                 structureList.Add(this.biosInformation); break;
   131               case 0x02: this.baseBoardInformation = new BaseBoardInformation(
   132                   type, handle, data, stringsList.ToArray());
   133                 structureList.Add(this.baseBoardInformation); break;
   134               default: structureList.Add(new Structure(
   135                 type, handle, data, stringsList.ToArray())); break;
   136             }
   137           }
   138         }
   139               
   140         table = structureList.ToArray();
   141       }
   142     }
   143 
   144     public string GetReport() {
   145       StringBuilder r = new StringBuilder();
   146 
   147       if (biosInformation != null) {
   148         r.Append("BIOS Vendor: "); r.AppendLine(biosInformation.Vendor);
   149         r.Append("BIOS Version: "); r.AppendLine(biosInformation.Version);
   150         r.AppendLine();
   151       }
   152 
   153       if (baseBoardInformation != null) {
   154         r.Append("Mainboard Manufacturer: ");
   155         r.AppendLine(baseBoardInformation.ManufacturerName);
   156         r.Append("Mainboard Name: ");
   157         r.AppendLine(baseBoardInformation.ProductName);
   158         r.AppendLine();
   159       }
   160 
   161       if (raw != null) {
   162         string base64 = Convert.ToBase64String(raw);
   163         r.AppendLine("SMBIOS Table");
   164         r.AppendLine();
   165 
   166         for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
   167           r.Append(" ");
   168           for (int j = 0; j < 0x40; j++) {
   169             int index = (i << 6) | j;
   170             if (index < base64.Length) {              
   171               r.Append(base64[index]);
   172             }
   173           }
   174           r.AppendLine();
   175         }
   176         r.AppendLine();
   177       }
   178 
   179       return r.ToString();
   180     }
   181 
   182     public BIOSInformation BIOS {
   183       get { return biosInformation; }
   184     }
   185 
   186     public BaseBoardInformation Board {
   187       get { return baseBoardInformation; }
   188     }
   189 
   190     public class Structure {
   191       private byte type;
   192       private ushort handle;
   193 
   194       private byte[] data;
   195       private string[] strings;
   196 
   197       protected string GetString(int offset) {
   198         if (offset < data.Length && data[offset] > 0 &&
   199          data[offset] <= strings.Length)
   200           return strings[data[offset] - 1];
   201         else
   202           return "";
   203       }
   204 
   205       public Structure(byte type, ushort handle, byte[] data, string[] strings) 
   206       {
   207         this.type = type;
   208         this.handle = handle;
   209         this.data = data;
   210         this.strings = strings;
   211       }
   212 
   213       public byte Type { get { return type; } }
   214 
   215       public ushort Handle { get { return handle; } }
   216     }
   217       
   218     public class BIOSInformation : Structure {
   219 
   220       private string vendor;
   221       private string version;
   222       
   223       public BIOSInformation(string vendor, string version) 
   224         : base (0x00, 0, null, null) 
   225       {
   226         this.vendor = vendor;
   227         this.version = version;
   228       }
   229       
   230       public BIOSInformation(byte type, ushort handle, byte[] data,
   231         string[] strings)
   232         : base(type, handle, data, strings) 
   233       {
   234         this.vendor = GetString(0x04);
   235         this.version = GetString(0x05);
   236       }
   237 
   238       public string Vendor { get { return vendor; } }
   239 
   240       public string Version { get { return version; } }
   241     }
   242 
   243     public class BaseBoardInformation : Structure {
   244 
   245       private string manufacturerName;
   246       private string productName;
   247       private string version;
   248       private string serialNumber;
   249       private Manufacturer manufacturer;
   250       private Model model;
   251 
   252       private void SetManufacturerName(string manufacturerName) {
   253         this.manufacturerName = manufacturerName;
   254         
   255         switch (manufacturerName) {
   256           case "ASRock":
   257             manufacturer = Manufacturer.ASRock; break;
   258           case "ASUSTeK Computer INC.":
   259             manufacturer = Manufacturer.ASUS; break;
   260           case "Dell Inc.":
   261             manufacturer = Manufacturer.Dell; break;
   262           case "DFI":
   263           case "DFI Inc.":            
   264             manufacturer = Manufacturer.DFI; break;
   265           case "EPoX COMPUTER CO., LTD":
   266             manufacturer = Manufacturer.EPoX; break;
   267           case "EVGA":
   268             manufacturer = Manufacturer.EVGA; break;
   269           case "First International Computer, Inc.":
   270             manufacturer = Manufacturer.FIC; break;
   271           case "Gigabyte Technology Co., Ltd.":
   272             manufacturer = Manufacturer.Gigabyte; break;
   273           case "Hewlett-Packard":
   274             manufacturer = Manufacturer.HP; break;
   275           case "IBM":
   276             manufacturer = Manufacturer.IBM; break;
   277           case "MICRO-STAR INTERNATIONAL CO., LTD":
   278           case "MICRO-STAR INTERNATIONAL CO.,LTD":
   279             manufacturer = Manufacturer.MSI; break;
   280           case "XFX":
   281             manufacturer = Manufacturer.XFX; break;
   282           case "To be filled by O.E.M.":
   283             manufacturer = Manufacturer.Unknown; break;
   284           default:
   285             manufacturer = Manufacturer.Unknown; break;
   286         }
   287       }
   288       
   289       private void SetProductName(string productName) {
   290         this.productName = productName;
   291         
   292         switch (productName) {
   293           case "880GMH/USB3":
   294             model = Model._880GMH_USB3; break;
   295           case "Crosshair III Formula":
   296             model = Model.Crosshair_III_Formula; break;
   297           case "M2N-SLI DELUXE":
   298             model = Model.M2N_SLI_DELUXE; break;
   299           case "M4A79XTD EVO":
   300             model = Model.M4A79XTD_EVO; break;
   301           case "P5W DH Deluxe":
   302             model = Model.P5W_DH_Deluxe; break;
   303           case "P6X58D-E":
   304             model = Model.P6X58D_E; break;
   305           case "LP BI P45-T2RS Elite":
   306             model = Model.LP_BI_P45_T2RS_Elite; break;
   307           case "LP DK P55-T3eH9":
   308             model = Model.LP_DK_P55_T3eH9; break;
   309           case "X58 SLI Classified":
   310             model = Model.X58_SLI_Classified; break;
   311           case "965P-S3":
   312             model = Model._965P_S3; break;
   313           case "EP45-DS3R":
   314             model = Model.EP45_DS3R; break;
   315           case "EP45-UD3R":
   316             model = Model.EP45_UD3R; break;
   317           case "EX58-EXTREME":
   318             model = Model.EX58_EXTREME; break;
   319           case "GA-MA770T-UD3":
   320             model = Model.GA_MA770T_UD3; break;
   321           case "GA-MA785GMT-UD2H":
   322             model = Model.GA_MA785GMT_UD2H; break;
   323           case "P35-DS3":
   324             model = Model.P35_DS3; break;
   325           case "P35-DS3L":
   326             model = Model.P35_DS3L; break;
   327           case "P55-UD4":
   328             model = Model.P55_UD4; break;
   329           case "X38-DS5":
   330             model = Model.X38_DS5; break;
   331           case "X58A-UD3R":
   332             model = Model.X58A_UD3R; break;
   333           case "To be filled by O.E.M.":
   334             model = Model.Unknown; break;
   335           default:
   336             model = Model.Unknown; break;
   337         }
   338       }
   339       
   340       public BaseBoardInformation(string manufacturerName, string productName, 
   341         string version, string serialNumber) 
   342         : base(0x02, 0, null, null) 
   343       {        
   344         SetManufacturerName(manufacturerName);
   345         SetProductName(productName);
   346         this.version = version;
   347         this.serialNumber = serialNumber;
   348       }
   349       
   350       public BaseBoardInformation(byte type, ushort handle, byte[] data,
   351         string[] strings)
   352         : base(type, handle, data, strings) {
   353 
   354         SetManufacturerName(GetString(0x04).Trim());
   355         SetProductName(GetString(0x05).Trim());
   356         this.version = GetString(0x06).Trim();
   357         this.serialNumber = GetString(0x07).Trim();               
   358       }
   359       
   360       public string ManufacturerName { get { return manufacturerName; } }
   361 
   362       public string ProductName { get { return productName; } }
   363 
   364       public string Version { get { return version; } }
   365 
   366       public string SerialNumber { get { return serialNumber; } }
   367 
   368       public Manufacturer Manufacturer { get { return manufacturer; } }
   369 
   370       public Model Model { get { return model; } }
   371 
   372     }
   373   }
   374 }