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