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