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