Hardware/SMBIOS.cs
author StephaneLenclud
Thu, 18 Apr 2013 23:25:10 +0200
branchMiniDisplay
changeset 444 9b09e2ee0968
parent 373 3b8443edb0e6
permissions -rw-r--r--
Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
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@378
    28
    private readonly ProcessorInformation processorInformation;
moel@370
    29
    private readonly MemoryDevice[] memoryDevices;
moel@370
    30
moel@370
    31
    private static string ReadSysFS(string path) {
moel@370
    32
      try {
moel@370
    33
        if (File.Exists(path)) {
moel@370
    34
          using (StreamReader reader = new StreamReader(path)) 
moel@370
    35
            return reader.ReadLine();
moel@370
    36
        } else {
moel@370
    37
          return null;
moel@370
    38
        }
moel@370
    39
      } catch {
moel@370
    40
        return null;
moel@370
    41
      }
moel@370
    42
    }
moel@370
    43
    
moel@370
    44
    public SMBIOS() {
moel@370
    45
      int p = (int)Environment.OSVersion.Platform;
moel@370
    46
      if ((p == 4) || (p == 128)) {
moel@370
    47
        this.raw = null;
moel@370
    48
        this.table = null;
moel@370
    49
        
moel@370
    50
        string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
moel@370
    51
        string boardName = ReadSysFS("/sys/class/dmi/id/board_name");        
moel@370
    52
        string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");        
moel@370
    53
        this.baseBoardInformation = new BaseBoardInformation(
moel@370
    54
          boardVendor, boardName, boardVersion, null);
moel@370
    55
moel@370
    56
        string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor");
moel@370
    57
        string productName = ReadSysFS("/sys/class/dmi/id/product_name");
moel@370
    58
        string productVersion = ReadSysFS("/sys/class/dmi/id/product_version");    
moel@370
    59
        this.systemInformation = new SystemInformation(systemVendor, 
moel@370
    60
          productName, productVersion, null, null);
moel@370
    61
moel@370
    62
        string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
moel@370
    63
        string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
moel@370
    64
        this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
moel@370
    65
moel@370
    66
        this.memoryDevices = new MemoryDevice[0];
moel@370
    67
      } else {              
moel@370
    68
        List<Structure> structureList = new List<Structure>();
moel@370
    69
        List<MemoryDevice> memoryDeviceList = new List<MemoryDevice>();
moel@370
    70
moel@370
    71
        raw = null;
moel@370
    72
        byte majorVersion = 0;
moel@370
    73
        byte minorVersion = 0;
moel@370
    74
        try {
moel@370
    75
          ManagementObjectCollection collection;
moel@370
    76
          using (ManagementObjectSearcher searcher = 
moel@370
    77
            new ManagementObjectSearcher("root\\WMI", 
moel@370
    78
              "SELECT * FROM MSSMBios_RawSMBiosTables")) {
moel@370
    79
            collection = searcher.Get();
moel@370
    80
          }
moel@370
    81
         
moel@370
    82
          foreach (ManagementObject mo in collection) {
moel@370
    83
            raw = (byte[])mo["SMBiosData"];
moel@370
    84
            majorVersion = (byte)mo["SmbiosMajorVersion"];
moel@370
    85
            minorVersion = (byte)mo["SmbiosMinorVersion"];            
moel@370
    86
            break;
moel@370
    87
          }
moel@378
    88
        } catch { }      
moel@370
    89
moel@370
    90
        if (majorVersion > 0 || minorVersion > 0)
moel@370
    91
          version = new Version(majorVersion, minorVersion);
moel@370
    92
  
moel@370
    93
        if (raw != null && raw.Length > 0) {
moel@370
    94
          int offset = 0;
moel@370
    95
          byte type = raw[offset];
moel@370
    96
          while (offset + 4 < raw.Length && type != 127) {
moel@370
    97
  
moel@370
    98
            type = raw[offset];
moel@370
    99
            int length = raw[offset + 1];
moel@370
   100
            ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
moel@370
   101
  
moel@370
   102
            if (offset + length > raw.Length)
moel@370
   103
              break;
moel@370
   104
            byte[] data = new byte[length];
moel@370
   105
            Array.Copy(raw, offset, data, 0, length);
moel@370
   106
            offset += length;
moel@370
   107
  
moel@370
   108
            List<string> stringsList = new List<string>();
moel@370
   109
            if (offset < raw.Length && raw[offset] == 0)
moel@370
   110
              offset++;
moel@370
   111
  
moel@370
   112
            while (offset < raw.Length && raw[offset] != 0) {
moel@370
   113
              StringBuilder sb = new StringBuilder();
moel@370
   114
              while (offset < raw.Length && raw[offset] != 0) {
moel@370
   115
                sb.Append((char)raw[offset]); offset++;
moel@370
   116
              }
moel@370
   117
              offset++;
moel@370
   118
              stringsList.Add(sb.ToString());
moel@370
   119
            }
moel@370
   120
            offset++;
moel@370
   121
            switch (type) {
moel@370
   122
              case 0x00:
moel@370
   123
                this.biosInformation = new BIOSInformation(
moel@370
   124
                  type, handle, data, stringsList.ToArray());
moel@370
   125
                structureList.Add(this.biosInformation); break;
moel@370
   126
              case 0x01:
moel@370
   127
                this.systemInformation = new SystemInformation(
moel@370
   128
                  type, handle, data, stringsList.ToArray());
moel@370
   129
                structureList.Add(this.systemInformation); break;
moel@370
   130
              case 0x02: this.baseBoardInformation = new BaseBoardInformation(
moel@370
   131
                  type, handle, data, stringsList.ToArray());
moel@370
   132
                structureList.Add(this.baseBoardInformation); break;
moel@378
   133
              case 0x04: this.processorInformation = new ProcessorInformation(
moel@378
   134
                  type, handle, data, stringsList.ToArray());
moel@378
   135
                structureList.Add(this.processorInformation); break;
moel@370
   136
              case 0x11: MemoryDevice m = new MemoryDevice(
moel@370
   137
                  type, handle, data, stringsList.ToArray());
moel@370
   138
                memoryDeviceList.Add(m);
moel@370
   139
                structureList.Add(m); break;
moel@370
   140
              default: structureList.Add(new Structure(
moel@370
   141
                type, handle, data, stringsList.ToArray())); break;
moel@370
   142
            }
moel@370
   143
          }
moel@370
   144
        }
moel@370
   145
moel@370
   146
        memoryDevices = memoryDeviceList.ToArray();
moel@370
   147
        table = structureList.ToArray();
moel@370
   148
      }
moel@370
   149
    }
moel@370
   150
moel@370
   151
    public string GetReport() {
moel@370
   152
      StringBuilder r = new StringBuilder();
moel@370
   153
moel@370
   154
      if (version != null) {
moel@370
   155
        r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2));
moel@370
   156
        r.AppendLine();
moel@370
   157
      }
moel@370
   158
moel@370
   159
      if (BIOS != null) {
moel@370
   160
        r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor);
moel@370
   161
        r.Append("BIOS Version: "); r.AppendLine(BIOS.Version);
moel@370
   162
        r.AppendLine();
moel@370
   163
      }
moel@370
   164
moel@370
   165
      if (System != null) {
moel@370
   166
        r.Append("System Manufacturer: ");
moel@370
   167
        r.AppendLine(System.ManufacturerName);
moel@370
   168
        r.Append("System Name: ");
moel@370
   169
        r.AppendLine(System.ProductName);
moel@370
   170
        r.Append("System Version: ");
moel@370
   171
        r.AppendLine(System.Version);
moel@370
   172
        r.AppendLine();
moel@370
   173
      }
moel@370
   174
moel@370
   175
      if (Board != null) {
moel@370
   176
        r.Append("Mainboard Manufacturer: ");
moel@370
   177
        r.AppendLine(Board.ManufacturerName);
moel@370
   178
        r.Append("Mainboard Name: ");
moel@370
   179
        r.AppendLine(Board.ProductName);
moel@370
   180
        r.Append("Mainboard Version: ");
moel@370
   181
        r.AppendLine(Board.Version);
moel@370
   182
        r.AppendLine();
moel@370
   183
      }
moel@370
   184
moel@378
   185
      if (Processor != null) {
moel@378
   186
        r.Append("Processor Manufacturer: ");
moel@378
   187
        r.AppendLine(Processor.ManufacturerName);
moel@378
   188
        r.Append("Processor Version: ");
moel@378
   189
        r.AppendLine(Processor.Version);
moel@378
   190
        r.Append("Processor Core Count: ");
moel@378
   191
        r.AppendLine(Processor.CoreCount.ToString());
moel@378
   192
        r.Append("Processor Core Enabled: ");
moel@378
   193
        r.AppendLine(Processor.CoreEnabled.ToString());
moel@378
   194
        r.Append("Processor Thread Count: ");
moel@378
   195
        r.AppendLine(Processor.ThreadCount.ToString());
moel@378
   196
        r.Append("Processor External Clock: ");
moel@378
   197
        r.Append(Processor.ExternalClock);
moel@378
   198
        r.AppendLine(" Mhz");
moel@378
   199
        r.AppendLine();
moel@378
   200
      }
moel@378
   201
moel@370
   202
      for (int i = 0; i < MemoryDevices.Length; i++) {        
moel@370
   203
        r.Append("Memory Device [" + i + "] Manufacturer: ");
moel@370
   204
        r.AppendLine(MemoryDevices[i].ManufacturerName);
moel@370
   205
        r.Append("Memory Device [" + i + "] Part Number: ");
moel@370
   206
        r.AppendLine(MemoryDevices[i].PartNumber);
moel@373
   207
        r.Append("Memory Device [" + i + "] Device Locator: ");
moel@373
   208
        r.AppendLine(MemoryDevices[i].DeviceLocator);
moel@373
   209
        r.Append("Memory Device [" + i + "] Bank Locator: ");
moel@373
   210
        r.AppendLine(MemoryDevices[i].BankLocator);
moel@378
   211
        r.Append("Memory Device [" + i + "] Speed: ");
moel@378
   212
        r.Append(MemoryDevices[i].Speed);
moel@378
   213
        r.AppendLine(" MHz");
moel@370
   214
        r.AppendLine();
moel@370
   215
      }
moel@370
   216
moel@370
   217
      if (raw != null) {
moel@370
   218
        string base64 = Convert.ToBase64String(raw);
moel@370
   219
        r.AppendLine("SMBIOS Table");
moel@370
   220
        r.AppendLine();
moel@370
   221
moel@370
   222
        for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
moel@370
   223
          r.Append(" ");
moel@370
   224
          for (int j = 0; j < 0x40; j++) {
moel@370
   225
            int index = (i << 6) | j;
moel@370
   226
            if (index < base64.Length) {              
moel@370
   227
              r.Append(base64[index]);
moel@370
   228
            }
moel@370
   229
          }
moel@370
   230
          r.AppendLine();
moel@370
   231
        }
moel@370
   232
        r.AppendLine();
moel@370
   233
      }
moel@370
   234
moel@370
   235
      return r.ToString();
moel@370
   236
    }
moel@370
   237
moel@370
   238
    public BIOSInformation BIOS {
moel@370
   239
      get { return biosInformation; }
moel@370
   240
    }
moel@370
   241
moel@370
   242
    public SystemInformation System {
moel@370
   243
      get { return systemInformation; }
moel@370
   244
    }
moel@370
   245
moel@370
   246
    public BaseBoardInformation Board {
moel@370
   247
      get { return baseBoardInformation; }
moel@370
   248
    }
moel@370
   249
moel@378
   250
moel@378
   251
    public ProcessorInformation Processor {
moel@378
   252
      get { return processorInformation; }
moel@378
   253
    }
moel@378
   254
moel@370
   255
    public MemoryDevice[] MemoryDevices {
moel@370
   256
      get { return memoryDevices; }
moel@370
   257
    }
moel@370
   258
moel@370
   259
    public class Structure {
moel@370
   260
      private readonly byte type;
moel@370
   261
      private readonly ushort handle;
moel@370
   262
moel@370
   263
      private readonly byte[] data;
moel@370
   264
      private readonly string[] strings;
moel@370
   265
moel@378
   266
      protected int GetByte(int offset) {
moel@378
   267
        if (offset < data.Length && offset >= 0)
moel@378
   268
          return data[offset];
moel@378
   269
        else
moel@378
   270
          return 0;
moel@378
   271
      }
moel@378
   272
moel@378
   273
      protected int GetWord(int offset) {
moel@378
   274
        if (offset + 1 < data.Length && offset >= 0)
moel@378
   275
          return (data[offset + 1] << 8) | data[offset];
moel@378
   276
        else
moel@378
   277
          return 0;
moel@378
   278
      }
moel@378
   279
moel@370
   280
      protected string GetString(int offset) {
moel@370
   281
        if (offset < data.Length && data[offset] > 0 &&
moel@370
   282
         data[offset] <= strings.Length)
moel@370
   283
          return strings[data[offset] - 1];
moel@370
   284
        else
moel@370
   285
          return "";
moel@370
   286
      }
moel@370
   287
moel@370
   288
      public Structure(byte type, ushort handle, byte[] data, string[] strings) 
moel@370
   289
      {
moel@370
   290
        this.type = type;
moel@370
   291
        this.handle = handle;
moel@370
   292
        this.data = data;
moel@370
   293
        this.strings = strings;
moel@370
   294
      }
moel@370
   295
moel@370
   296
      public byte Type { get { return type; } }
moel@370
   297
moel@370
   298
      public ushort Handle { get { return handle; } }
moel@370
   299
    }
moel@370
   300
      
moel@370
   301
    public class BIOSInformation : Structure {
moel@370
   302
moel@370
   303
      private readonly string vendor;
moel@370
   304
      private readonly string version;
moel@370
   305
      
moel@370
   306
      public BIOSInformation(string vendor, string version) 
moel@370
   307
        : base (0x00, 0, null, null) 
moel@370
   308
      {
moel@370
   309
        this.vendor = vendor;
moel@370
   310
        this.version = version;
moel@370
   311
      }
moel@370
   312
      
moel@370
   313
      public BIOSInformation(byte type, ushort handle, byte[] data,
moel@370
   314
        string[] strings)
moel@370
   315
        : base(type, handle, data, strings) 
moel@370
   316
      {
moel@370
   317
        this.vendor = GetString(0x04);
moel@370
   318
        this.version = GetString(0x05);
moel@370
   319
      }
moel@370
   320
moel@370
   321
      public string Vendor { get { return vendor; } }
moel@370
   322
moel@370
   323
      public string Version { get { return version; } }
moel@370
   324
    }
moel@370
   325
moel@370
   326
    public class SystemInformation : Structure {
moel@370
   327
moel@370
   328
      private readonly string manufacturerName;
moel@370
   329
      private readonly string productName;
moel@370
   330
      private readonly string version;
moel@370
   331
      private readonly string serialNumber;
moel@370
   332
      private readonly string family;
moel@370
   333
moel@370
   334
      public SystemInformation(string manufacturerName, string productName, 
moel@370
   335
        string version, string serialNumber, string family) 
moel@370
   336
        : base (0x01, 0, null, null) 
moel@370
   337
      {
moel@370
   338
        this.manufacturerName = manufacturerName;
moel@370
   339
        this.productName = productName;
moel@370
   340
        this.version = version;
moel@370
   341
        this.serialNumber = serialNumber;
moel@370
   342
        this.family = family;
moel@370
   343
      }
moel@370
   344
moel@370
   345
      public SystemInformation(byte type, ushort handle, byte[] data,
moel@370
   346
        string[] strings)
moel@370
   347
        : base(type, handle, data, strings) 
moel@370
   348
      {
moel@370
   349
        this.manufacturerName = GetString(0x04);
moel@370
   350
        this.productName = GetString(0x05);
moel@370
   351
        this.version = GetString(0x06);
moel@370
   352
        this.serialNumber = GetString(0x07);
moel@370
   353
        this.family = GetString(0x1A);
moel@370
   354
      }
moel@370
   355
moel@370
   356
      public string ManufacturerName { get { return manufacturerName; } }
moel@370
   357
moel@370
   358
      public string ProductName { get { return productName; } }
moel@370
   359
moel@370
   360
      public string Version { get { return version; } }
moel@370
   361
moel@370
   362
      public string SerialNumber { get { return serialNumber; } }
moel@370
   363
moel@370
   364
      public string Family { get { return family; } }
moel@370
   365
moel@370
   366
    }
moel@370
   367
moel@370
   368
    public class BaseBoardInformation : Structure {
moel@370
   369
moel@370
   370
      private readonly string manufacturerName;
moel@370
   371
      private readonly string productName;
moel@370
   372
      private readonly string version;
moel@370
   373
      private readonly string serialNumber;
moel@370
   374
      
moel@370
   375
      public BaseBoardInformation(string manufacturerName, string productName, 
moel@370
   376
        string version, string serialNumber) 
moel@370
   377
        : base(0x02, 0, null, null) 
moel@370
   378
      {
moel@370
   379
        this.manufacturerName = manufacturerName;
moel@370
   380
        this.productName = productName;
moel@370
   381
        this.version = version;
moel@370
   382
        this.serialNumber = serialNumber;
moel@370
   383
      }
moel@370
   384
      
moel@370
   385
      public BaseBoardInformation(byte type, ushort handle, byte[] data,
moel@370
   386
        string[] strings)
moel@370
   387
        : base(type, handle, data, strings) {
moel@370
   388
moel@370
   389
        this.manufacturerName = GetString(0x04).Trim();
moel@370
   390
        this.productName = GetString(0x05).Trim();
moel@370
   391
        this.version = GetString(0x06).Trim();
moel@370
   392
        this.serialNumber = GetString(0x07).Trim();               
moel@370
   393
      }
moel@370
   394
      
moel@370
   395
      public string ManufacturerName { get { return manufacturerName; } }
moel@370
   396
moel@370
   397
      public string ProductName { get { return productName; } }
moel@370
   398
moel@370
   399
      public string Version { get { return version; } }
moel@370
   400
moel@370
   401
      public string SerialNumber { get { return serialNumber; } }
moel@370
   402
moel@370
   403
    }
moel@370
   404
moel@378
   405
    public class ProcessorInformation : Structure {
moel@378
   406
moel@378
   407
      public ProcessorInformation(byte type, ushort handle, byte[] data,
moel@378
   408
        string[] strings)
moel@378
   409
        : base(type, handle, data, strings) 
moel@378
   410
      {
moel@378
   411
        this.ManufacturerName = GetString(0x07).Trim();
moel@378
   412
        this.Version = GetString(0x10).Trim();
moel@378
   413
        this.CoreCount = GetByte(0x23);
moel@378
   414
        this.CoreEnabled = GetByte(0x24);
moel@378
   415
        this.ThreadCount = GetByte(0x25);
moel@378
   416
        this.ExternalClock = GetWord(0x12);
moel@378
   417
      }
moel@378
   418
moel@378
   419
      public string ManufacturerName { get; private set; }
moel@378
   420
moel@378
   421
      public string Version { get; private set; }
moel@378
   422
moel@378
   423
      public int CoreCount { get; private set; }
moel@378
   424
moel@378
   425
      public int CoreEnabled { get; private set; }
moel@378
   426
moel@378
   427
      public int ThreadCount { get; private set; }
moel@378
   428
     
moel@378
   429
      public int ExternalClock { get; private set; }
moel@378
   430
    }
moel@378
   431
moel@370
   432
    public class MemoryDevice : Structure {
moel@370
   433
moel@373
   434
      private readonly string deviceLocator;
moel@373
   435
      private readonly string bankLocator;
moel@370
   436
      private readonly string manufacturerName;
moel@370
   437
      private readonly string serialNumber;
moel@378
   438
      private readonly string partNumber;
moel@378
   439
      private readonly int speed;
moel@370
   440
moel@370
   441
      public MemoryDevice(byte type, ushort handle, byte[] data,
moel@370
   442
        string[] strings)
moel@373
   443
        : base(type, handle, data, strings) 
moel@373
   444
      {
moel@373
   445
        this.deviceLocator = GetString(0x10).Trim();
moel@373
   446
        this.bankLocator = GetString(0x11).Trim();
moel@370
   447
        this.manufacturerName = GetString(0x17).Trim();
moel@370
   448
        this.serialNumber = GetString(0x18).Trim();
moel@370
   449
        this.partNumber = GetString(0x1A).Trim();
moel@378
   450
        this.speed = GetWord(0x15);
moel@370
   451
      }
moel@370
   452
moel@373
   453
      public string DeviceLocator { get { return deviceLocator; } }
moel@373
   454
moel@373
   455
      public string BankLocator { get { return bankLocator; } }
moel@373
   456
moel@370
   457
      public string ManufacturerName { get { return manufacturerName; } }
moel@370
   458
moel@370
   459
      public string SerialNumber { get { return serialNumber; } }
moel@370
   460
moel@370
   461
      public string PartNumber { get { return partNumber; } }
moel@370
   462
moel@378
   463
      public int Speed { get { return speed; } }
moel@373
   464
moel@370
   465
    }
moel@370
   466
  }
moel@370
   467
}