467 lines
15 KiB
C#
Raw Permalink Normal View History

/*
2010-01-26 22:37:48 +00:00
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
2010-01-26 22:37:48 +00:00
Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
2010-01-26 22:37:48 +00:00
*/
using System;
using System.Collections.Generic;
using System.IO;
2010-01-26 22:37:48 +00:00
using System.Management;
using System.Text;
namespace OpenHardwareMonitor.Hardware {
2010-01-26 22:37:48 +00:00
internal class SMBIOS {
2010-01-26 22:37:48 +00:00
private readonly byte[] raw;
private readonly Structure[] table;
2010-01-26 22:37:48 +00:00
2010-11-13 20:20:03 +00:00
private readonly Version version;
private readonly BIOSInformation biosInformation;
private readonly SystemInformation systemInformation;
private readonly BaseBoardInformation baseBoardInformation;
private readonly ProcessorInformation processorInformation;
private readonly MemoryDevice[] memoryDevices;
2010-01-26 22:37:48 +00:00
2010-08-15 14:46:58 +00:00
private static string ReadSysFS(string path) {
try {
if (File.Exists(path)) {
using (StreamReader reader = new StreamReader(path))
return reader.ReadLine();
} else {
return null;
}
} catch {
return null;
}
}
public SMBIOS() {
if (OperatingSystem.IsUnix) {
this.raw = null;
this.table = null;
string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
string boardName = ReadSysFS("/sys/class/dmi/id/board_name");
string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");
this.baseBoardInformation = new BaseBoardInformation(
boardVendor, boardName, boardVersion, null);
string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor");
string productName = ReadSysFS("/sys/class/dmi/id/product_name");
string productVersion = ReadSysFS("/sys/class/dmi/id/product_version");
this.systemInformation = new SystemInformation(systemVendor,
productName, productVersion, null, null);
string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
this.memoryDevices = new MemoryDevice[0];
} else {
List<Structure> structureList = new List<Structure>();
List<MemoryDevice> memoryDeviceList = new List<MemoryDevice>();
raw = null;
2010-11-13 20:20:03 +00:00
byte majorVersion = 0;
byte minorVersion = 0;
try {
2010-08-15 14:46:58 +00:00
ManagementObjectCollection collection;
using (ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\WMI",
2010-11-13 20:20:03 +00:00
"SELECT * FROM MSSMBios_RawSMBiosTables")) {
2010-08-15 14:46:58 +00:00
collection = searcher.Get();
}
foreach (ManagementObject mo in collection) {
raw = (byte[])mo["SMBiosData"];
2010-11-13 20:20:03 +00:00
majorVersion = (byte)mo["SmbiosMajorVersion"];
minorVersion = (byte)mo["SmbiosMinorVersion"];
2010-04-05 21:31:21 +00:00
break;
}
} catch { }
2010-11-13 20:20:03 +00:00
if (majorVersion > 0 || minorVersion > 0)
version = new Version(majorVersion, minorVersion);
if (raw != null && raw.Length > 0) {
int offset = 0;
byte type = raw[offset];
while (offset + 4 < raw.Length && type != 127) {
type = raw[offset];
int length = raw[offset + 1];
ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
if (offset + length > raw.Length)
break;
byte[] data = new byte[length];
Array.Copy(raw, offset, data, 0, length);
offset += length;
List<string> stringsList = new List<string>();
if (offset < raw.Length && raw[offset] == 0)
offset++;
2010-04-05 21:31:21 +00:00
while (offset < raw.Length && raw[offset] != 0) {
StringBuilder sb = new StringBuilder();
while (offset < raw.Length && raw[offset] != 0) {
sb.Append((char)raw[offset]); offset++;
}
offset++;
stringsList.Add(sb.ToString());
}
2010-04-05 21:31:21 +00:00
offset++;
switch (type) {
case 0x00:
this.biosInformation = new BIOSInformation(
type, handle, data, stringsList.ToArray());
structureList.Add(this.biosInformation); break;
case 0x01:
this.systemInformation = new SystemInformation(
type, handle, data, stringsList.ToArray());
structureList.Add(this.systemInformation); break;
case 0x02: this.baseBoardInformation = new BaseBoardInformation(
type, handle, data, stringsList.ToArray());
structureList.Add(this.baseBoardInformation); break;
case 0x04: this.processorInformation = new ProcessorInformation(
type, handle, data, stringsList.ToArray());
structureList.Add(this.processorInformation); break;
case 0x11: MemoryDevice m = new MemoryDevice(
type, handle, data, stringsList.ToArray());
memoryDeviceList.Add(m);
structureList.Add(m); break;
default: structureList.Add(new Structure(
type, handle, data, stringsList.ToArray())); break;
}
2010-01-26 22:37:48 +00:00
}
}
memoryDevices = memoryDeviceList.ToArray();
table = structureList.ToArray();
2010-04-05 21:31:21 +00:00
}
2010-01-26 22:37:48 +00:00
}
public string GetReport() {
StringBuilder r = new StringBuilder();
2010-01-26 22:37:48 +00:00
2010-11-13 20:20:03 +00:00
if (version != null) {
r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2));
r.AppendLine();
}
2010-08-15 14:46:58 +00:00
if (BIOS != null) {
r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor);
r.Append("BIOS Version: "); r.AppendLine(BIOS.Version);
2010-01-26 22:37:48 +00:00
r.AppendLine();
}
if (System != null) {
r.Append("System Manufacturer: ");
r.AppendLine(System.ManufacturerName);
r.Append("System Name: ");
r.AppendLine(System.ProductName);
r.Append("System Version: ");
r.AppendLine(System.Version);
r.AppendLine();
}
2010-08-15 14:46:58 +00:00
if (Board != null) {
r.Append("Mainboard Manufacturer: ");
2010-08-15 14:46:58 +00:00
r.AppendLine(Board.ManufacturerName);
r.Append("Mainboard Name: ");
2010-08-15 14:46:58 +00:00
r.AppendLine(Board.ProductName);
r.Append("Mainboard Version: ");
r.AppendLine(Board.Version);
2010-01-26 22:37:48 +00:00
r.AppendLine();
}
if (Processor != null) {
r.Append("Processor Manufacturer: ");
r.AppendLine(Processor.ManufacturerName);
r.Append("Processor Version: ");
r.AppendLine(Processor.Version);
r.Append("Processor Core Count: ");
r.AppendLine(Processor.CoreCount.ToString());
r.Append("Processor Core Enabled: ");
r.AppendLine(Processor.CoreEnabled.ToString());
r.Append("Processor Thread Count: ");
r.AppendLine(Processor.ThreadCount.ToString());
r.Append("Processor External Clock: ");
r.Append(Processor.ExternalClock);
r.AppendLine(" Mhz");
r.AppendLine();
}
for (int i = 0; i < MemoryDevices.Length; i++) {
r.Append("Memory Device [" + i + "] Manufacturer: ");
r.AppendLine(MemoryDevices[i].ManufacturerName);
r.Append("Memory Device [" + i + "] Part Number: ");
r.AppendLine(MemoryDevices[i].PartNumber);
2012-07-25 15:33:16 +00:00
r.Append("Memory Device [" + i + "] Device Locator: ");
r.AppendLine(MemoryDevices[i].DeviceLocator);
r.Append("Memory Device [" + i + "] Bank Locator: ");
r.AppendLine(MemoryDevices[i].BankLocator);
r.Append("Memory Device [" + i + "] Speed: ");
r.Append(MemoryDevices[i].Speed);
r.AppendLine(" MHz");
r.AppendLine();
}
if (raw != null) {
string base64 = Convert.ToBase64String(raw);
r.AppendLine("SMBIOS Table");
r.AppendLine();
for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
r.Append(" ");
for (int j = 0; j < 0x40; j++) {
int index = (i << 6) | j;
if (index < base64.Length) {
r.Append(base64[index]);
}
}
r.AppendLine();
}
r.AppendLine();
}
2010-01-26 22:37:48 +00:00
return r.ToString();
}
public BIOSInformation BIOS {
get { return biosInformation; }
}
public SystemInformation System {
get { return systemInformation; }
}
public BaseBoardInformation Board {
get { return baseBoardInformation; }
}
2010-01-26 22:37:48 +00:00
public ProcessorInformation Processor {
get { return processorInformation; }
}
public MemoryDevice[] MemoryDevices {
get { return memoryDevices; }
}
2010-01-26 22:37:48 +00:00
public class Structure {
private readonly byte type;
private readonly ushort handle;
2010-01-26 22:37:48 +00:00
private readonly byte[] data;
private readonly string[] strings;
2010-01-26 22:37:48 +00:00
protected int GetByte(int offset) {
if (offset < data.Length && offset >= 0)
return data[offset];
else
return 0;
}
protected int GetWord(int offset) {
if (offset + 1 < data.Length && offset >= 0)
return (data[offset + 1] << 8) | data[offset];
else
return 0;
}
protected string GetString(int offset) {
if (offset < data.Length && data[offset] > 0 &&
data[offset] <= strings.Length)
return strings[data[offset] - 1];
else
return "";
}
2010-01-26 22:37:48 +00:00
public Structure(byte type, ushort handle, byte[] data, string[] strings)
{
this.type = type;
this.handle = handle;
this.data = data;
this.strings = strings;
}
public byte Type { get { return type; } }
public ushort Handle { get { return handle; } }
}
2010-01-26 22:37:48 +00:00
public class BIOSInformation : Structure {
private readonly string vendor;
private readonly string version;
public BIOSInformation(string vendor, string version)
: base (0x00, 0, null, null)
{
this.vendor = vendor;
this.version = version;
}
2010-01-26 22:37:48 +00:00
public BIOSInformation(byte type, ushort handle, byte[] data,
string[] strings)
: base(type, handle, data, strings)
{
this.vendor = GetString(0x04);
this.version = GetString(0x05);
2010-01-26 22:37:48 +00:00
}
public string Vendor { get { return vendor; } }
public string Version { get { return version; } }
}
public class SystemInformation : Structure {
private readonly string manufacturerName;
private readonly string productName;
private readonly string version;
private readonly string serialNumber;
private readonly string family;
public SystemInformation(string manufacturerName, string productName,
string version, string serialNumber, string family)
: base (0x01, 0, null, null)
{
this.manufacturerName = manufacturerName;
this.productName = productName;
this.version = version;
this.serialNumber = serialNumber;
this.family = family;
}
public SystemInformation(byte type, ushort handle, byte[] data,
string[] strings)
: base(type, handle, data, strings)
{
this.manufacturerName = GetString(0x04);
this.productName = GetString(0x05);
this.version = GetString(0x06);
this.serialNumber = GetString(0x07);
this.family = GetString(0x1A);
}
public string ManufacturerName { get { return manufacturerName; } }
public string ProductName { get { return productName; } }
public string Version { get { return version; } }
public string SerialNumber { get { return serialNumber; } }
public string Family { get { return family; } }
}
2010-01-26 22:37:48 +00:00
public class BaseBoardInformation : Structure {
private readonly string manufacturerName;
private readonly string productName;
private readonly string version;
private readonly string serialNumber;
public BaseBoardInformation(string manufacturerName, string productName,
string version, string serialNumber)
: base(0x02, 0, null, null)
{
this.manufacturerName = manufacturerName;
this.productName = productName;
this.version = version;
this.serialNumber = serialNumber;
}
public BaseBoardInformation(byte type, ushort handle, byte[] data,
string[] strings)
: base(type, handle, data, strings) {
2010-01-26 22:37:48 +00:00
this.manufacturerName = GetString(0x04).Trim();
this.productName = GetString(0x05).Trim();
this.version = GetString(0x06).Trim();
this.serialNumber = GetString(0x07).Trim();
}
public string ManufacturerName { get { return manufacturerName; } }
2010-01-26 22:37:48 +00:00
public string ProductName { get { return productName; } }
2010-04-05 21:31:21 +00:00
public string Version { get { return version; } }
public string SerialNumber { get { return serialNumber; } }
}
public class ProcessorInformation : Structure {
public ProcessorInformation(byte type, ushort handle, byte[] data,
string[] strings)
: base(type, handle, data, strings)
{
this.ManufacturerName = GetString(0x07).Trim();
this.Version = GetString(0x10).Trim();
this.CoreCount = GetByte(0x23);
this.CoreEnabled = GetByte(0x24);
this.ThreadCount = GetByte(0x25);
this.ExternalClock = GetWord(0x12);
}
public string ManufacturerName { get; private set; }
public string Version { get; private set; }
public int CoreCount { get; private set; }
public int CoreEnabled { get; private set; }
public int ThreadCount { get; private set; }
public int ExternalClock { get; private set; }
}
public class MemoryDevice : Structure {
2012-07-25 15:33:16 +00:00
private readonly string deviceLocator;
private readonly string bankLocator;
private readonly string manufacturerName;
private readonly string serialNumber;
private readonly string partNumber;
private readonly int speed;
public MemoryDevice(byte type, ushort handle, byte[] data,
string[] strings)
2012-07-25 15:33:16 +00:00
: base(type, handle, data, strings)
{
this.deviceLocator = GetString(0x10).Trim();
this.bankLocator = GetString(0x11).Trim();
this.manufacturerName = GetString(0x17).Trim();
this.serialNumber = GetString(0x18).Trim();
this.partNumber = GetString(0x1A).Trim();
this.speed = GetWord(0x15);
}
2012-07-25 15:33:16 +00:00
public string DeviceLocator { get { return deviceLocator; } }
public string BankLocator { get { return bankLocator; } }
public string ManufacturerName { get { return manufacturerName; } }
public string SerialNumber { get { return serialNumber; } }
2010-04-05 21:31:21 +00:00
public string PartNumber { get { return partNumber; } }
public int Speed { get { return speed; } }
2012-07-25 15:33:16 +00:00
2010-01-26 22:37:48 +00:00
}
}
}