Fixed Issue 651.
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/.
7 Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Collections.Generic;
14 using System.Management;
17 namespace OpenHardwareMonitor.Hardware {
19 internal class SMBIOS {
21 private readonly byte[] raw;
22 private readonly Structure[] table;
24 private readonly Version version;
25 private readonly BIOSInformation biosInformation;
26 private readonly SystemInformation systemInformation;
27 private readonly BaseBoardInformation baseBoardInformation;
28 private readonly ProcessorInformation processorInformation;
29 private readonly MemoryDevice[] memoryDevices;
31 private static string ReadSysFS(string path) {
33 if (File.Exists(path)) {
34 using (StreamReader reader = new StreamReader(path))
35 return reader.ReadLine();
45 int p = (int)Environment.OSVersion.Platform;
46 if ((p == 4) || (p == 128)) {
50 string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
51 string boardName = ReadSysFS("/sys/class/dmi/id/board_name");
52 string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");
53 this.baseBoardInformation = new BaseBoardInformation(
54 boardVendor, boardName, boardVersion, null);
56 string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor");
57 string productName = ReadSysFS("/sys/class/dmi/id/product_name");
58 string productVersion = ReadSysFS("/sys/class/dmi/id/product_version");
59 this.systemInformation = new SystemInformation(systemVendor,
60 productName, productVersion, null, null);
62 string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
63 string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
64 this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
66 this.memoryDevices = new MemoryDevice[0];
68 List<Structure> structureList = new List<Structure>();
69 List<MemoryDevice> memoryDeviceList = new List<MemoryDevice>();
72 byte majorVersion = 0;
73 byte minorVersion = 0;
75 ManagementObjectCollection collection;
76 using (ManagementObjectSearcher searcher =
77 new ManagementObjectSearcher("root\\WMI",
78 "SELECT * FROM MSSMBios_RawSMBiosTables")) {
79 collection = searcher.Get();
82 foreach (ManagementObject mo in collection) {
83 raw = (byte[])mo["SMBiosData"];
84 majorVersion = (byte)mo["SmbiosMajorVersion"];
85 minorVersion = (byte)mo["SmbiosMinorVersion"];
90 if (majorVersion > 0 || minorVersion > 0)
91 version = new Version(majorVersion, minorVersion);
93 if (raw != null && raw.Length > 0) {
95 byte type = raw[offset];
96 while (offset + 4 < raw.Length && type != 127) {
99 int length = raw[offset + 1];
100 ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
102 if (offset + length > raw.Length)
104 byte[] data = new byte[length];
105 Array.Copy(raw, offset, data, 0, length);
108 List<string> stringsList = new List<string>();
109 if (offset < raw.Length && raw[offset] == 0)
112 while (offset < raw.Length && raw[offset] != 0) {
113 StringBuilder sb = new StringBuilder();
114 while (offset < raw.Length && raw[offset] != 0) {
115 sb.Append((char)raw[offset]); offset++;
118 stringsList.Add(sb.ToString());
123 this.biosInformation = new BIOSInformation(
124 type, handle, data, stringsList.ToArray());
125 structureList.Add(this.biosInformation); break;
127 this.systemInformation = new SystemInformation(
128 type, handle, data, stringsList.ToArray());
129 structureList.Add(this.systemInformation); break;
130 case 0x02: this.baseBoardInformation = new BaseBoardInformation(
131 type, handle, data, stringsList.ToArray());
132 structureList.Add(this.baseBoardInformation); break;
133 case 0x04: this.processorInformation = new ProcessorInformation(
134 type, handle, data, stringsList.ToArray());
135 structureList.Add(this.processorInformation); break;
136 case 0x11: MemoryDevice m = new MemoryDevice(
137 type, handle, data, stringsList.ToArray());
138 memoryDeviceList.Add(m);
139 structureList.Add(m); break;
140 default: structureList.Add(new Structure(
141 type, handle, data, stringsList.ToArray())); break;
146 memoryDevices = memoryDeviceList.ToArray();
147 table = structureList.ToArray();
151 public string GetReport() {
152 StringBuilder r = new StringBuilder();
154 if (version != null) {
155 r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2));
160 r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor);
161 r.Append("BIOS Version: "); r.AppendLine(BIOS.Version);
165 if (System != null) {
166 r.Append("System Manufacturer: ");
167 r.AppendLine(System.ManufacturerName);
168 r.Append("System Name: ");
169 r.AppendLine(System.ProductName);
170 r.Append("System Version: ");
171 r.AppendLine(System.Version);
176 r.Append("Mainboard Manufacturer: ");
177 r.AppendLine(Board.ManufacturerName);
178 r.Append("Mainboard Name: ");
179 r.AppendLine(Board.ProductName);
180 r.Append("Mainboard Version: ");
181 r.AppendLine(Board.Version);
185 if (Processor != null) {
186 r.Append("Processor Manufacturer: ");
187 r.AppendLine(Processor.ManufacturerName);
188 r.Append("Processor Version: ");
189 r.AppendLine(Processor.Version);
190 r.Append("Processor Core Count: ");
191 r.AppendLine(Processor.CoreCount.ToString());
192 r.Append("Processor Core Enabled: ");
193 r.AppendLine(Processor.CoreEnabled.ToString());
194 r.Append("Processor Thread Count: ");
195 r.AppendLine(Processor.ThreadCount.ToString());
196 r.Append("Processor External Clock: ");
197 r.Append(Processor.ExternalClock);
198 r.AppendLine(" Mhz");
202 for (int i = 0; i < MemoryDevices.Length; i++) {
203 r.Append("Memory Device [" + i + "] Manufacturer: ");
204 r.AppendLine(MemoryDevices[i].ManufacturerName);
205 r.Append("Memory Device [" + i + "] Part Number: ");
206 r.AppendLine(MemoryDevices[i].PartNumber);
207 r.Append("Memory Device [" + i + "] Device Locator: ");
208 r.AppendLine(MemoryDevices[i].DeviceLocator);
209 r.Append("Memory Device [" + i + "] Bank Locator: ");
210 r.AppendLine(MemoryDevices[i].BankLocator);
211 r.Append("Memory Device [" + i + "] Speed: ");
212 r.Append(MemoryDevices[i].Speed);
213 r.AppendLine(" MHz");
218 string base64 = Convert.ToBase64String(raw);
219 r.AppendLine("SMBIOS Table");
222 for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
224 for (int j = 0; j < 0x40; j++) {
225 int index = (i << 6) | j;
226 if (index < base64.Length) {
227 r.Append(base64[index]);
238 public BIOSInformation BIOS {
239 get { return biosInformation; }
242 public SystemInformation System {
243 get { return systemInformation; }
246 public BaseBoardInformation Board {
247 get { return baseBoardInformation; }
251 public ProcessorInformation Processor {
252 get { return processorInformation; }
255 public MemoryDevice[] MemoryDevices {
256 get { return memoryDevices; }
259 public class Structure {
260 private readonly byte type;
261 private readonly ushort handle;
263 private readonly byte[] data;
264 private readonly string[] strings;
266 protected int GetByte(int offset) {
267 if (offset < data.Length && offset >= 0)
273 protected int GetWord(int offset) {
274 if (offset + 1 < data.Length && offset >= 0)
275 return (data[offset + 1] << 8) | data[offset];
280 protected string GetString(int offset) {
281 if (offset < data.Length && data[offset] > 0 &&
282 data[offset] <= strings.Length)
283 return strings[data[offset] - 1];
288 public Structure(byte type, ushort handle, byte[] data, string[] strings)
291 this.handle = handle;
293 this.strings = strings;
296 public byte Type { get { return type; } }
298 public ushort Handle { get { return handle; } }
301 public class BIOSInformation : Structure {
303 private readonly string vendor;
304 private readonly string version;
306 public BIOSInformation(string vendor, string version)
307 : base (0x00, 0, null, null)
309 this.vendor = vendor;
310 this.version = version;
313 public BIOSInformation(byte type, ushort handle, byte[] data,
315 : base(type, handle, data, strings)
317 this.vendor = GetString(0x04);
318 this.version = GetString(0x05);
321 public string Vendor { get { return vendor; } }
323 public string Version { get { return version; } }
326 public class SystemInformation : Structure {
328 private readonly string manufacturerName;
329 private readonly string productName;
330 private readonly string version;
331 private readonly string serialNumber;
332 private readonly string family;
334 public SystemInformation(string manufacturerName, string productName,
335 string version, string serialNumber, string family)
336 : base (0x01, 0, null, null)
338 this.manufacturerName = manufacturerName;
339 this.productName = productName;
340 this.version = version;
341 this.serialNumber = serialNumber;
342 this.family = family;
345 public SystemInformation(byte type, ushort handle, byte[] data,
347 : base(type, handle, data, strings)
349 this.manufacturerName = GetString(0x04);
350 this.productName = GetString(0x05);
351 this.version = GetString(0x06);
352 this.serialNumber = GetString(0x07);
353 this.family = GetString(0x1A);
356 public string ManufacturerName { get { return manufacturerName; } }
358 public string ProductName { get { return productName; } }
360 public string Version { get { return version; } }
362 public string SerialNumber { get { return serialNumber; } }
364 public string Family { get { return family; } }
368 public class BaseBoardInformation : Structure {
370 private readonly string manufacturerName;
371 private readonly string productName;
372 private readonly string version;
373 private readonly string serialNumber;
375 public BaseBoardInformation(string manufacturerName, string productName,
376 string version, string serialNumber)
377 : base(0x02, 0, null, null)
379 this.manufacturerName = manufacturerName;
380 this.productName = productName;
381 this.version = version;
382 this.serialNumber = serialNumber;
385 public BaseBoardInformation(byte type, ushort handle, byte[] data,
387 : base(type, handle, data, strings) {
389 this.manufacturerName = GetString(0x04).Trim();
390 this.productName = GetString(0x05).Trim();
391 this.version = GetString(0x06).Trim();
392 this.serialNumber = GetString(0x07).Trim();
395 public string ManufacturerName { get { return manufacturerName; } }
397 public string ProductName { get { return productName; } }
399 public string Version { get { return version; } }
401 public string SerialNumber { get { return serialNumber; } }
405 public class ProcessorInformation : Structure {
407 public ProcessorInformation(byte type, ushort handle, byte[] data,
409 : base(type, handle, data, strings)
411 this.ManufacturerName = GetString(0x07).Trim();
412 this.Version = GetString(0x10).Trim();
413 this.CoreCount = GetByte(0x23);
414 this.CoreEnabled = GetByte(0x24);
415 this.ThreadCount = GetByte(0x25);
416 this.ExternalClock = GetWord(0x12);
419 public string ManufacturerName { get; private set; }
421 public string Version { get; private set; }
423 public int CoreCount { get; private set; }
425 public int CoreEnabled { get; private set; }
427 public int ThreadCount { get; private set; }
429 public int ExternalClock { get; private set; }
432 public class MemoryDevice : Structure {
434 private readonly string deviceLocator;
435 private readonly string bankLocator;
436 private readonly string manufacturerName;
437 private readonly string serialNumber;
438 private readonly string partNumber;
439 private readonly int speed;
441 public MemoryDevice(byte type, ushort handle, byte[] data,
443 : base(type, handle, data, strings)
445 this.deviceLocator = GetString(0x10).Trim();
446 this.bankLocator = GetString(0x11).Trim();
447 this.manufacturerName = GetString(0x17).Trim();
448 this.serialNumber = GetString(0x18).Trim();
449 this.partNumber = GetString(0x1A).Trim();
450 this.speed = GetWord(0x15);
453 public string DeviceLocator { get { return deviceLocator; } }
455 public string BankLocator { get { return bankLocator; } }
457 public string ManufacturerName { get { return manufacturerName; } }
459 public string SerialNumber { get { return serialNumber; } }
461 public string PartNumber { get { return partNumber; } }
463 public int Speed { get { return speed; } }