Hardware/Mainboard/SMBIOS.cs
author moel.mich
Sun, 08 Jul 2012 15:24:44 +0000
changeset 358 7962499f9cd6
parent 344 3145aadca3d2
child 359 30bb76a1da24
permissions -rw-r--r--
Added support for SSDs with a controller from Micron.
     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.Mainboard {
    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 
    29     private static string ReadSysFS(string path) {
    30       try {
    31         if (File.Exists(path)) {
    32           using (StreamReader reader = new StreamReader(path)) 
    33             return reader.ReadLine();
    34         } else {
    35           return null;
    36         }
    37       } catch {
    38         return null;
    39       }
    40     }
    41     
    42     public SMBIOS() {
    43       int p = (int)Environment.OSVersion.Platform;
    44       if ((p == 4) || (p == 128)) {
    45         this.raw = null;
    46         this.table = null;
    47         
    48         string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
    49         string boardName = ReadSysFS("/sys/class/dmi/id/board_name");        
    50         string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");        
    51         this.baseBoardInformation = new BaseBoardInformation(
    52           boardVendor, boardName, boardVersion, null);
    53 
    54         string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor");
    55         string productName = ReadSysFS("/sys/class/dmi/id/product_name");
    56         string productVersion = ReadSysFS("/sys/class/dmi/id/product_version");    
    57         this.systemInformation = new SystemInformation(systemVendor, 
    58           productName, productVersion, null, null);
    59 
    60         string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
    61         string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
    62         this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
    63         
    64       } else {              
    65         List<Structure> structureList = new List<Structure>();
    66 
    67         raw = null;
    68         byte majorVersion = 0;
    69         byte minorVersion = 0;
    70         try {
    71           ManagementObjectCollection collection;
    72           using (ManagementObjectSearcher searcher = 
    73             new ManagementObjectSearcher("root\\WMI", 
    74               "SELECT * FROM MSSMBios_RawSMBiosTables")) {
    75             collection = searcher.Get();
    76           }
    77          
    78           foreach (ManagementObject mo in collection) {
    79             raw = (byte[])mo["SMBiosData"];
    80             majorVersion = (byte)mo["SmbiosMajorVersion"];
    81             minorVersion = (byte)mo["SmbiosMinorVersion"];            
    82             break;
    83           }
    84         } catch { }
    85 
    86         if (majorVersion > 0 || minorVersion > 0)
    87           version = new Version(majorVersion, minorVersion);
    88   
    89         if (raw != null && raw.Length > 0) {
    90           int offset = 0;
    91           byte type = raw[offset];
    92           while (offset + 4 < raw.Length && type != 127) {
    93   
    94             type = raw[offset];
    95             int length = raw[offset + 1];
    96             ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
    97   
    98             if (offset + length > raw.Length)
    99               break;
   100             byte[] data = new byte[length];
   101             Array.Copy(raw, offset, data, 0, length);
   102             offset += length;
   103   
   104             List<string> stringsList = new List<string>();
   105             if (offset < raw.Length && raw[offset] == 0)
   106               offset++;
   107   
   108             while (offset < raw.Length && raw[offset] != 0) {
   109               StringBuilder sb = new StringBuilder();
   110               while (offset < raw.Length && raw[offset] != 0) {
   111                 sb.Append((char)raw[offset]); offset++;
   112               }
   113               offset++;
   114               stringsList.Add(sb.ToString());
   115             }
   116             offset++;
   117             switch (type) {
   118               case 0x00:
   119                 this.biosInformation = new BIOSInformation(
   120                   type, handle, data, stringsList.ToArray());
   121                 structureList.Add(this.biosInformation); break;
   122               case 0x01:
   123                 this.systemInformation = new SystemInformation(
   124                   type, handle, data, stringsList.ToArray());
   125                 structureList.Add(this.systemInformation); break;
   126               case 0x02: this.baseBoardInformation = new BaseBoardInformation(
   127                   type, handle, data, stringsList.ToArray());
   128                 structureList.Add(this.baseBoardInformation); break;
   129               default: structureList.Add(new Structure(
   130                 type, handle, data, stringsList.ToArray())); break;
   131             }
   132           }
   133         }
   134               
   135         table = structureList.ToArray();
   136       }
   137     }
   138 
   139     public string GetReport() {
   140       StringBuilder r = new StringBuilder();
   141 
   142       if (version != null) {
   143         r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2));
   144         r.AppendLine();
   145       }
   146 
   147       if (BIOS != null) {
   148         r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor);
   149         r.Append("BIOS Version: "); r.AppendLine(BIOS.Version);
   150         r.AppendLine();
   151       }
   152 
   153       if (System != null) {
   154         r.Append("System Manufacturer: ");
   155         r.AppendLine(System.ManufacturerName);
   156         r.Append("System Name: ");
   157         r.AppendLine(System.ProductName);
   158         r.Append("System Version: ");
   159         r.AppendLine(System.Version);
   160         r.AppendLine();
   161       }
   162 
   163       if (Board != null) {
   164         r.Append("Mainboard Manufacturer: ");
   165         r.AppendLine(Board.ManufacturerName);
   166         r.Append("Mainboard Name: ");
   167         r.AppendLine(Board.ProductName);
   168         r.Append("Mainboard Version: ");
   169         r.AppendLine(Board.Version);
   170         r.AppendLine();
   171       }
   172 
   173       if (raw != null) {
   174         string base64 = Convert.ToBase64String(raw);
   175         r.AppendLine("SMBIOS Table");
   176         r.AppendLine();
   177 
   178         for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
   179           r.Append(" ");
   180           for (int j = 0; j < 0x40; j++) {
   181             int index = (i << 6) | j;
   182             if (index < base64.Length) {              
   183               r.Append(base64[index]);
   184             }
   185           }
   186           r.AppendLine();
   187         }
   188         r.AppendLine();
   189       }
   190 
   191       return r.ToString();
   192     }
   193 
   194     public BIOSInformation BIOS {
   195       get { return biosInformation; }
   196     }
   197 
   198     public SystemInformation System {
   199       get { return systemInformation; }
   200     }
   201 
   202     public BaseBoardInformation Board {
   203       get { return baseBoardInformation; }
   204     }
   205 
   206     public class Structure {
   207       private readonly byte type;
   208       private readonly ushort handle;
   209 
   210       private readonly byte[] data;
   211       private readonly string[] strings;
   212 
   213       protected string GetString(int offset) {
   214         if (offset < data.Length && data[offset] > 0 &&
   215          data[offset] <= strings.Length)
   216           return strings[data[offset] - 1];
   217         else
   218           return "";
   219       }
   220 
   221       public Structure(byte type, ushort handle, byte[] data, string[] strings) 
   222       {
   223         this.type = type;
   224         this.handle = handle;
   225         this.data = data;
   226         this.strings = strings;
   227       }
   228 
   229       public byte Type { get { return type; } }
   230 
   231       public ushort Handle { get { return handle; } }
   232     }
   233       
   234     public class BIOSInformation : Structure {
   235 
   236       private readonly string vendor;
   237       private readonly string version;
   238       
   239       public BIOSInformation(string vendor, string version) 
   240         : base (0x00, 0, null, null) 
   241       {
   242         this.vendor = vendor;
   243         this.version = version;
   244       }
   245       
   246       public BIOSInformation(byte type, ushort handle, byte[] data,
   247         string[] strings)
   248         : base(type, handle, data, strings) 
   249       {
   250         this.vendor = GetString(0x04);
   251         this.version = GetString(0x05);
   252       }
   253 
   254       public string Vendor { get { return vendor; } }
   255 
   256       public string Version { get { return version; } }
   257     }
   258 
   259     public class SystemInformation : Structure {
   260 
   261       private readonly string manufacturerName;
   262       private readonly string productName;
   263       private readonly string version;
   264       private readonly string serialNumber;
   265       private readonly string family;
   266 
   267       public SystemInformation(string manufacturerName, string productName, 
   268         string version, string serialNumber, string family) 
   269         : base (0x01, 0, null, null) 
   270       {
   271         this.manufacturerName = manufacturerName;
   272         this.productName = productName;
   273         this.version = version;
   274         this.serialNumber = serialNumber;
   275         this.family = family;
   276       }
   277 
   278       public SystemInformation(byte type, ushort handle, byte[] data,
   279         string[] strings)
   280         : base(type, handle, data, strings) 
   281       {
   282         this.manufacturerName = GetString(0x04);
   283         this.productName = GetString(0x05);
   284         this.version = GetString(0x06);
   285         this.serialNumber = GetString(0x07);
   286         this.family = GetString(0x1A);
   287       }
   288 
   289       public string ManufacturerName { get { return manufacturerName; } }
   290 
   291       public string ProductName { get { return productName; } }
   292 
   293       public string Version { get { return version; } }
   294 
   295       public string SerialNumber { get { return serialNumber; } }
   296 
   297       public string Family { get { return family; } }
   298 
   299     }
   300 
   301     public class BaseBoardInformation : Structure {
   302 
   303       private readonly string manufacturerName;
   304       private readonly string productName;
   305       private readonly string version;
   306       private readonly string serialNumber;
   307       private readonly Manufacturer manufacturer;
   308       private readonly Model model;
   309 
   310       private static Manufacturer GetManufacturer(string name) {               
   311         switch (name) {
   312           case "Alienware":
   313             return Manufacturer.Alienware;
   314           case "Apple Inc.":
   315             return Manufacturer.Apple;
   316           case "ASRock":
   317             return Manufacturer.ASRock;
   318           case "ASUSTeK Computer INC.":
   319           case "ASUSTeK COMPUTER INC.":
   320             return Manufacturer.ASUS;
   321           case "Dell Inc.":
   322             return Manufacturer.Dell;
   323           case "DFI":
   324           case "DFI Inc.":            
   325             return Manufacturer.DFI;
   326           case "ECS":
   327             return Manufacturer.ECS;
   328           case "EPoX COMPUTER CO., LTD":
   329             return Manufacturer.EPoX;
   330           case "EVGA":
   331             return Manufacturer.EVGA;
   332           case "First International Computer, Inc.":
   333             return Manufacturer.FIC;
   334           case "FUJITSU":
   335           case "FUJITSU SIEMENS":
   336             return Manufacturer.Fujitsu;
   337           case "Gigabyte Technology Co., Ltd.":
   338             return Manufacturer.Gigabyte;
   339           case "Hewlett-Packard":
   340             return Manufacturer.HP;
   341           case "IBM":
   342             return Manufacturer.IBM;
   343           case "Intel":
   344           case "Intel Corp.":
   345           case "Intel Corporation":
   346           case "INTEL Corporation":
   347             return Manufacturer.Intel;   
   348           case "Lenovo":
   349           case "LENOVO":
   350             return Manufacturer.Lenovo;
   351           case "Micro-Star International":
   352           case "MICRO-STAR INTERNATIONAL CO., LTD":
   353           case "MICRO-STAR INTERNATIONAL CO.,LTD":
   354           case "MSI":
   355             return Manufacturer.MSI;
   356           case "Shuttle":
   357             return Manufacturer.Shuttle;
   358           case "Supermicro":
   359             return Manufacturer.Supermicro;
   360           case "TOSHIBA":
   361             return Manufacturer.Toshiba;
   362           case "XFX":
   363             return  Manufacturer.XFX;
   364           case "To be filled by O.E.M.":
   365             return  Manufacturer.Unknown;
   366           default:
   367             return  Manufacturer.Unknown;
   368         }
   369       }
   370 
   371       private static Model GetModel(string name) {
   372         switch (name) {
   373           case "880GMH/USB3":
   374             return Model._880GMH_USB3;
   375           case "ASRock AOD790GX/128M":
   376             return Model.AOD790GX_128M;
   377           case "P55 Deluxe":
   378             return Model.P55_Deluxe;
   379           case "Crosshair III Formula":
   380             return Model.Crosshair_III_Formula;
   381           case "M2N-SLI DELUXE":
   382             return Model.M2N_SLI_DELUXE;
   383           case "M4A79XTD EVO":
   384             return Model.M4A79XTD_EVO;
   385           case "P5W DH Deluxe":
   386             return Model.P5W_DH_Deluxe;
   387           case "P6T":
   388             return Model.P6T;
   389           case "P6X58D-E":
   390             return Model.P6X58D_E;
   391           case "P8P67":
   392             return Model.P8P67;
   393           case "P8P67 EVO":
   394             return Model.P8P67_EVO;
   395           case "P8P67 PRO":
   396             return Model.P8P67_PRO;
   397           case "P8P67-M PRO":
   398             return Model.P8P67_M_PRO;
   399           case "P9X79":
   400             return Model.P9X79;
   401           case "Rampage Extreme":
   402             return Model.Rampage_Extreme;
   403           case "Rampage II GENE":
   404             return Model.Rampage_II_GENE;
   405           case "LP BI P45-T2RS Elite":
   406             return Model.LP_BI_P45_T2RS_Elite;
   407           case "LP DK P55-T3eH9":
   408             return Model.LP_DK_P55_T3eH9;
   409           case "A890GXM-A":
   410             return Model.A890GXM_A;
   411           case "X58 SLI Classified":
   412             return Model.X58_SLI_Classified;
   413           case "965P-S3":
   414             return Model._965P_S3;
   415           case "EP45-DS3R":
   416             return Model.EP45_DS3R;
   417           case "EP45-UD3R":
   418             return Model.EP45_UD3R;
   419           case "EX58-EXTREME":
   420             return Model.EX58_EXTREME;
   421           case "EX58-UD3R":
   422             return Model.EX58_UD3R;
   423           case "G41M-Combo":
   424             return Model.G41M_Combo;
   425           case "G41MT-S2":
   426             return Model.G41MT_S2;
   427           case "G41MT-S2P":
   428             return Model.G41MT_S2P;
   429           case "GA-MA770T-UD3":
   430             return Model.GA_MA770T_UD3;
   431           case "GA-MA770T-UD3P":
   432             return Model.GA_MA770T_UD3P;
   433           case "GA-MA785GM-US2H":
   434             return Model.GA_MA785GM_US2H;
   435           case "GA-MA785GMT-UD2H":
   436             return Model.GA_MA785GMT_UD2H;
   437           case "GA-MA78LM-S2H":
   438             return Model.GA_MA78LM_S2H;
   439           case "GA-MA790X-UD3P":
   440             return Model.GA_MA790X_UD3P;
   441           case "H55-USB3":
   442             return Model.H55_USB3;
   443           case "H55N-USB3":
   444             return Model.H55N_USB3;
   445           case "H61M-DS2 REV 1.2":
   446             return Model.H61M_DS2_REV_1_2;
   447           case "H61M-USB3-B3 REV 2.0":
   448             return Model.H61M_USB3_B3_REV_2_0;
   449           case "H67A-UD3H-B3":
   450             return Model.H67A_UD3H_B3;
   451           case "H67A-USB3-B3":
   452             return Model.H67A_USB3_B3;
   453           case "P35-DS3":
   454             return Model.P35_DS3;
   455           case "P35-DS3L":
   456             return Model.P35_DS3L;
   457           case "P55-UD4":
   458             return Model.P55_UD4;
   459           case "P55A-UD3":
   460             return Model.P55A_UD3;
   461           case "P55M-UD4":
   462             return Model.P55M_UD4;
   463           case "P67A-UD3-B3":
   464             return Model.P67A_UD3_B3;
   465           case "P67A-UD3R-B3":
   466             return Model.P67A_UD3R_B3;
   467           case "P67A-UD4-B3":
   468             return Model.P67A_UD4_B3;
   469           case "P8Z68-V PRO":
   470             return Model.P8Z68_V_PRO;
   471           case "X38-DS5":
   472             return Model.X38_DS5;
   473           case "X58A-UD3R":
   474             return Model.X58A_UD3R;
   475           case "Z68A-D3H-B3":
   476             return Model.Z68A_D3H_B3;
   477           case "Z68AP-D3":
   478             return Model.Z68AP_D3;
   479           case "Z68X-UD3H-B3":
   480             return Model.Z68X_UD3H_B3;
   481           case "Z68X-UD7-B3":
   482             return Model.Z68X_UD7_B3;
   483           case "FH67":
   484             return Model.FH67;
   485           case "Base Board Product Name":
   486           case "To be filled by O.E.M.":
   487             return Model.Unknown;
   488           default:
   489             return Model.Unknown;
   490         }
   491       }
   492       
   493       public BaseBoardInformation(string manufacturerName, string productName, 
   494         string version, string serialNumber) 
   495         : base(0x02, 0, null, null) 
   496       {
   497         this.manufacturerName = manufacturerName;
   498         this.manufacturer = GetManufacturer(manufacturerName);
   499         this.productName = productName;
   500         this.model = GetModel(productName);
   501         this.version = version;
   502         this.serialNumber = serialNumber;
   503       }
   504       
   505       public BaseBoardInformation(byte type, ushort handle, byte[] data,
   506         string[] strings)
   507         : base(type, handle, data, strings) {
   508 
   509         this.manufacturerName = GetString(0x04).Trim();
   510         this.manufacturer = GetManufacturer(this.manufacturerName);
   511         this.productName = GetString(0x05).Trim();
   512         this.model = GetModel(this.productName);
   513         this.version = GetString(0x06).Trim();
   514         this.serialNumber = GetString(0x07).Trim();               
   515       }
   516       
   517       public string ManufacturerName { get { return manufacturerName; } }
   518 
   519       public string ProductName { get { return productName; } }
   520 
   521       public string Version { get { return version; } }
   522 
   523       public string SerialNumber { get { return serialNumber; } }
   524 
   525       public Manufacturer Manufacturer { get { return manufacturer; } }
   526 
   527       public Model Model { get { return model; } }
   528 
   529     }
   530   }
   531 }