moel@64: /* moel@64: moel@64: Version: MPL 1.1/GPL 2.0/LGPL 2.1 moel@64: moel@64: The contents of this file are subject to the Mozilla Public License Version moel@64: 1.1 (the "License"); you may not use this file except in compliance with moel@64: the License. You may obtain a copy of the License at moel@64: moel@64: http://www.mozilla.org/MPL/ moel@64: moel@64: Software distributed under the License is distributed on an "AS IS" basis, moel@64: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License moel@64: for the specific language governing rights and limitations under the License. moel@64: moel@64: The Original Code is the Open Hardware Monitor code. moel@64: moel@64: The Initial Developer of the Original Code is moel@64: Michael Möller . moel@332: Portions created by the Initial Developer are Copyright (C) 2009-2012 moel@64: the Initial Developer. All Rights Reserved. moel@64: moel@64: Contributor(s): moel@64: moel@64: Alternatively, the contents of this file may be used under the terms of moel@64: either the GNU General Public License Version 2 or later (the "GPL"), or moel@64: the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), moel@64: in which case the provisions of the GPL or the LGPL are applicable instead moel@64: of those above. If you wish to allow use of your version of this file only moel@64: under the terms of either the GPL or the LGPL, and not to allow others to moel@64: use your version of this file under the terms of the MPL, indicate your moel@64: decision by deleting the provisions above and replace them with the notice moel@64: and other provisions required by the GPL or the LGPL. If you do not delete moel@64: the provisions above, a recipient may use your version of this file under moel@64: the terms of any one of the MPL, the GPL or the LGPL. moel@64: moel@64: */ moel@64: moel@64: using System; moel@64: using System.Collections.Generic; moel@136: using System.IO; moel@64: using System.Management; moel@64: using System.Text; moel@64: moel@64: namespace OpenHardwareMonitor.Hardware.Mainboard { moel@64: moel@165: internal class SMBIOS { moel@64: moel@195: private readonly byte[] raw; moel@195: private readonly Structure[] table; moel@64: moel@242: private readonly Version version; moel@195: private readonly BIOSInformation biosInformation; moel@320: private readonly SystemInformation systemInformation; moel@195: private readonly BaseBoardInformation baseBoardInformation; moel@64: moel@167: private static string ReadSysFS(string path) { moel@136: try { moel@136: if (File.Exists(path)) { moel@136: using (StreamReader reader = new StreamReader(path)) moel@136: return reader.ReadLine(); moel@136: } else { moel@136: return null; moel@136: } moel@136: } catch { moel@136: return null; moel@136: } moel@136: } moel@136: moel@64: public SMBIOS() { moel@195: int p = (int)Environment.OSVersion.Platform; moel@136: if ((p == 4) || (p == 128)) { moel@136: this.raw = null; moel@136: this.table = null; moel@136: moel@136: string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor"); moel@136: string boardName = ReadSysFS("/sys/class/dmi/id/board_name"); moel@136: string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version"); moel@136: this.baseBoardInformation = new BaseBoardInformation( moel@136: boardVendor, boardName, boardVersion, null); moel@320: moel@320: string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor"); moel@320: string productName = ReadSysFS("/sys/class/dmi/id/product_name"); moel@320: string productVersion = ReadSysFS("/sys/class/dmi/id/product_version"); moel@320: this.systemInformation = new SystemInformation(systemVendor, moel@320: productName, productVersion, null, null); moel@320: moel@136: string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor"); moel@136: string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version"); moel@136: this.biosInformation = new BIOSInformation(biosVendor, biosVersion); moel@136: moel@136: } else { moel@136: List structureList = new List(); moel@64: moel@136: raw = null; moel@242: byte majorVersion = 0; moel@242: byte minorVersion = 0; moel@136: try { moel@167: ManagementObjectCollection collection; moel@167: using (ManagementObjectSearcher searcher = moel@136: new ManagementObjectSearcher("root\\WMI", moel@242: "SELECT * FROM MSSMBios_RawSMBiosTables")) { moel@167: collection = searcher.Get(); moel@167: } moel@136: moel@136: foreach (ManagementObject mo in collection) { moel@136: raw = (byte[])mo["SMBiosData"]; moel@242: majorVersion = (byte)mo["SmbiosMajorVersion"]; moel@242: minorVersion = (byte)mo["SmbiosMinorVersion"]; moel@89: break; moel@136: } moel@136: } catch { } moel@242: moel@242: if (majorVersion > 0 || minorVersion > 0) moel@242: version = new Version(majorVersion, minorVersion); moel@136: moel@136: if (raw != null && raw.Length > 0) { moel@136: int offset = 0; moel@136: byte type = raw[offset]; moel@136: while (offset + 4 < raw.Length && type != 127) { moel@136: moel@136: type = raw[offset]; moel@136: int length = raw[offset + 1]; moel@136: ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]); moel@136: moel@136: if (offset + length > raw.Length) moel@136: break; moel@136: byte[] data = new byte[length]; moel@136: Array.Copy(raw, offset, data, 0, length); moel@136: offset += length; moel@136: moel@136: List stringsList = new List(); moel@136: if (offset < raw.Length && raw[offset] == 0) moel@136: offset++; moel@136: moel@89: while (offset < raw.Length && raw[offset] != 0) { moel@136: StringBuilder sb = new StringBuilder(); moel@136: while (offset < raw.Length && raw[offset] != 0) { moel@136: sb.Append((char)raw[offset]); offset++; moel@136: } moel@136: offset++; moel@136: stringsList.Add(sb.ToString()); moel@64: } moel@64: offset++; moel@136: switch (type) { moel@136: case 0x00: moel@136: this.biosInformation = new BIOSInformation( moel@136: type, handle, data, stringsList.ToArray()); moel@136: structureList.Add(this.biosInformation); break; moel@320: case 0x01: moel@320: this.systemInformation = new SystemInformation( moel@320: type, handle, data, stringsList.ToArray()); moel@320: structureList.Add(this.systemInformation); break; moel@136: case 0x02: this.baseBoardInformation = new BaseBoardInformation( moel@136: type, handle, data, stringsList.ToArray()); moel@136: structureList.Add(this.baseBoardInformation); break; moel@136: default: structureList.Add(new Structure( moel@136: type, handle, data, stringsList.ToArray())); break; moel@136: } moel@64: } moel@64: } moel@136: moel@136: table = structureList.ToArray(); moel@89: } moel@64: } moel@64: moel@64: public string GetReport() { moel@136: StringBuilder r = new StringBuilder(); moel@64: moel@242: if (version != null) { moel@242: r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2)); moel@242: r.AppendLine(); moel@242: } moel@242: moel@167: if (BIOS != null) { moel@167: r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor); moel@167: r.Append("BIOS Version: "); r.AppendLine(BIOS.Version); moel@64: r.AppendLine(); moel@64: } moel@64: moel@320: if (System != null) { moel@320: r.Append("System Manufacturer: "); moel@320: r.AppendLine(System.ManufacturerName); moel@320: r.Append("System Name: "); moel@320: r.AppendLine(System.ProductName); moel@320: r.Append("System Version: "); moel@320: r.AppendLine(System.Version); moel@320: r.AppendLine(); moel@320: } moel@320: moel@167: if (Board != null) { moel@136: r.Append("Mainboard Manufacturer: "); moel@167: r.AppendLine(Board.ManufacturerName); moel@136: r.Append("Mainboard Name: "); moel@167: r.AppendLine(Board.ProductName); moel@167: r.Append("Mainboard Version: "); moel@167: r.AppendLine(Board.Version); moel@64: r.AppendLine(); moel@64: } moel@136: moel@136: if (raw != null) { moel@136: string base64 = Convert.ToBase64String(raw); moel@136: r.AppendLine("SMBIOS Table"); moel@136: r.AppendLine(); moel@136: moel@136: for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) { moel@136: r.Append(" "); moel@136: for (int j = 0; j < 0x40; j++) { moel@136: int index = (i << 6) | j; moel@136: if (index < base64.Length) { moel@136: r.Append(base64[index]); moel@136: } moel@136: } moel@136: r.AppendLine(); moel@136: } moel@136: r.AppendLine(); moel@136: } moel@136: moel@64: return r.ToString(); moel@64: } moel@64: moel@64: public BIOSInformation BIOS { moel@64: get { return biosInformation; } moel@64: } moel@64: moel@320: public SystemInformation System { moel@320: get { return systemInformation; } moel@320: } moel@320: moel@64: public BaseBoardInformation Board { moel@64: get { return baseBoardInformation; } moel@64: } moel@64: moel@64: public class Structure { moel@195: private readonly byte type; moel@195: private readonly ushort handle; moel@64: moel@195: private readonly byte[] data; moel@195: private readonly string[] strings; moel@64: moel@64: protected string GetString(int offset) { moel@64: if (offset < data.Length && data[offset] > 0 && moel@64: data[offset] <= strings.Length) moel@64: return strings[data[offset] - 1]; moel@64: else moel@64: return ""; moel@64: } moel@64: moel@64: public Structure(byte type, ushort handle, byte[] data, string[] strings) moel@64: { moel@64: this.type = type; moel@64: this.handle = handle; moel@64: this.data = data; moel@64: this.strings = strings; moel@64: } moel@64: moel@64: public byte Type { get { return type; } } moel@64: moel@64: public ushort Handle { get { return handle; } } moel@64: } moel@136: moel@64: public class BIOSInformation : Structure { moel@64: moel@195: private readonly string vendor; moel@195: private readonly string version; moel@136: moel@136: public BIOSInformation(string vendor, string version) moel@136: : base (0x00, 0, null, null) moel@136: { moel@136: this.vendor = vendor; moel@136: this.version = version; moel@136: } moel@136: moel@64: public BIOSInformation(byte type, ushort handle, byte[] data, moel@64: string[] strings) moel@136: : base(type, handle, data, strings) moel@136: { moel@64: this.vendor = GetString(0x04); moel@64: this.version = GetString(0x05); moel@64: } moel@64: moel@64: public string Vendor { get { return vendor; } } moel@64: moel@64: public string Version { get { return version; } } moel@64: } moel@64: moel@320: public class SystemInformation : Structure { moel@320: moel@320: private readonly string manufacturerName; moel@320: private readonly string productName; moel@320: private readonly string version; moel@320: private readonly string serialNumber; moel@320: private readonly string family; moel@320: moel@320: public SystemInformation(string manufacturerName, string productName, moel@320: string version, string serialNumber, string family) moel@320: : base (0x01, 0, null, null) moel@320: { moel@320: this.manufacturerName = manufacturerName; moel@320: this.productName = productName; moel@320: this.version = version; moel@320: this.serialNumber = serialNumber; moel@320: this.family = family; moel@320: } moel@320: moel@320: public SystemInformation(byte type, ushort handle, byte[] data, moel@320: string[] strings) moel@320: : base(type, handle, data, strings) moel@320: { moel@320: this.manufacturerName = GetString(0x04); moel@320: this.productName = GetString(0x05); moel@320: this.version = GetString(0x06); moel@320: this.serialNumber = GetString(0x07); moel@320: this.family = GetString(0x1A); moel@320: } moel@320: moel@320: public string ManufacturerName { get { return manufacturerName; } } moel@320: moel@320: public string ProductName { get { return productName; } } moel@320: moel@320: public string Version { get { return version; } } moel@320: moel@320: public string SerialNumber { get { return serialNumber; } } moel@320: moel@320: public string Family { get { return family; } } moel@320: moel@320: } moel@320: moel@64: public class BaseBoardInformation : Structure { moel@64: moel@195: private readonly string manufacturerName; moel@195: private readonly string productName; moel@195: private readonly string version; moel@195: private readonly string serialNumber; moel@195: private readonly Manufacturer manufacturer; moel@195: private readonly Model model; moel@64: moel@195: private static Manufacturer GetManufacturer(string name) { moel@167: switch (name) { moel@296: case "Alienware": moel@296: return Manufacturer.Alienware; moel@296: case "Apple Inc.": moel@296: return Manufacturer.Apple; moel@153: case "ASRock": moel@195: return Manufacturer.ASRock; moel@64: case "ASUSTeK Computer INC.": moel@332: case "ASUSTeK COMPUTER INC.": moel@195: return Manufacturer.ASUS; moel@152: case "Dell Inc.": moel@195: return Manufacturer.Dell; moel@64: case "DFI": moel@72: case "DFI Inc.": moel@195: return Manufacturer.DFI; moel@177: case "ECS": moel@195: return Manufacturer.ECS; moel@64: case "EPoX COMPUTER CO., LTD": moel@195: return Manufacturer.EPoX; moel@132: case "EVGA": moel@195: return Manufacturer.EVGA; moel@152: case "First International Computer, Inc.": moel@195: return Manufacturer.FIC; moel@296: case "FUJITSU": moel@296: case "FUJITSU SIEMENS": moel@296: return Manufacturer.Fujitsu; moel@64: case "Gigabyte Technology Co., Ltd.": moel@195: return Manufacturer.Gigabyte; moel@152: case "Hewlett-Packard": moel@195: return Manufacturer.HP; moel@72: case "IBM": moel@195: return Manufacturer.IBM; moel@296: case "Intel": moel@296: case "Intel Corp.": moel@296: case "Intel Corporation": moel@296: case "INTEL Corporation": moel@296: return Manufacturer.Intel; moel@296: case "Lenovo": moel@296: case "LENOVO": moel@296: return Manufacturer.Lenovo; moel@296: case "Micro-Star International": moel@64: case "MICRO-STAR INTERNATIONAL CO., LTD": moel@72: case "MICRO-STAR INTERNATIONAL CO.,LTD": moel@296: case "MSI": moel@319: return Manufacturer.MSI; moel@319: case "Shuttle": moel@319: return Manufacturer.Shuttle; moel@296: case "Supermicro": moel@296: return Manufacturer.Supermicro; moel@296: case "TOSHIBA": moel@296: return Manufacturer.Toshiba; moel@152: case "XFX": moel@195: return Manufacturer.XFX; moel@152: case "To be filled by O.E.M.": moel@195: return Manufacturer.Unknown; moel@64: default: moel@195: return Manufacturer.Unknown; moel@126: } moel@136: } moel@195: moel@195: private static Model GetModel(string name) { moel@167: switch (name) { moel@153: case "880GMH/USB3": moel@195: return Model._880GMH_USB3; moel@220: case "ASRock AOD790GX/128M": moel@220: return Model.AOD790GX_128M; moel@221: case "P55 Deluxe": moel@221: return Model.P55_Deluxe; moel@133: case "Crosshair III Formula": moel@195: return Model.Crosshair_III_Formula; moel@133: case "M2N-SLI DELUXE": moel@195: return Model.M2N_SLI_DELUXE; moel@144: case "M4A79XTD EVO": moel@195: return Model.M4A79XTD_EVO; moel@130: case "P5W DH Deluxe": moel@195: return Model.P5W_DH_Deluxe; moel@336: case "P6T": moel@336: return Model.P6T; moel@152: case "P6X58D-E": moel@195: return Model.P6X58D_E; moel@312: case "P8P67": moel@312: return Model.P8P67; moel@311: case "P8P67 EVO": moel@311: return Model.P8P67_EVO; moel@265: case "P8P67 PRO": moel@265: return Model.P8P67_PRO; moel@276: case "P8P67-M PRO": moel@276: return Model.P8P67_M_PRO; moel@332: case "P9X79": moel@332: return Model.P9X79; moel@174: case "Rampage Extreme": moel@195: return Model.Rampage_Extreme; moel@174: case "Rampage II GENE": moel@195: return Model.Rampage_II_GENE; moel@126: case "LP BI P45-T2RS Elite": moel@195: return Model.LP_BI_P45_T2RS_Elite; moel@126: case "LP DK P55-T3eH9": moel@195: return Model.LP_DK_P55_T3eH9; moel@177: case "A890GXM-A": moel@195: return Model.A890GXM_A; moel@132: case "X58 SLI Classified": moel@195: return Model.X58_SLI_Classified; moel@130: case "965P-S3": moel@195: return Model._965P_S3; moel@126: case "EP45-DS3R": moel@195: return Model.EP45_DS3R; moel@130: case "EP45-UD3R": moel@195: return Model.EP45_UD3R; moel@133: case "EX58-EXTREME": moel@195: return Model.EX58_EXTREME; moel@154: case "GA-MA770T-UD3": moel@195: return Model.GA_MA770T_UD3; moel@126: case "GA-MA785GMT-UD2H": moel@195: return Model.GA_MA785GMT_UD2H; moel@290: case "H67A-UD3H-B3": moel@290: return Model.H67A_UD3H_B3; moel@126: case "P35-DS3": moel@195: return Model.P35_DS3; moel@133: case "P35-DS3L": moel@195: return Model.P35_DS3L; moel@148: case "P55-UD4": moel@195: return Model.P55_UD4; moel@168: case "P55M-UD4": moel@195: return Model.P55M_UD4; moel@278: case "P67A-UD4-B3": moel@278: return Model.P67A_UD4_B3; moel@337: case "P8Z68-V PRO": moel@337: return Model.P8Z68_V_PRO; moel@130: case "X38-DS5": moel@195: return Model.X38_DS5; moel@138: case "X58A-UD3R": moel@195: return Model.X58A_UD3R; moel@305: case "Z68X-UD7-B3": moel@305: return Model.Z68X_UD7_B3; moel@320: case "FH67": moel@320: return Model.FH67; moel@296: case "Base Board Product Name": moel@152: case "To be filled by O.E.M.": moel@195: return Model.Unknown; moel@126: default: moel@195: return Model.Unknown; moel@64: } moel@64: } moel@136: moel@136: public BaseBoardInformation(string manufacturerName, string productName, moel@136: string version, string serialNumber) moel@136: : base(0x02, 0, null, null) moel@195: { moel@195: this.manufacturerName = manufacturerName; moel@195: this.manufacturer = GetManufacturer(manufacturerName); moel@195: this.productName = productName; moel@195: this.model = GetModel(productName); moel@136: this.version = version; moel@136: this.serialNumber = serialNumber; moel@136: } moel@136: moel@136: public BaseBoardInformation(byte type, ushort handle, byte[] data, moel@136: string[] strings) moel@136: : base(type, handle, data, strings) { moel@64: moel@195: this.manufacturerName = GetString(0x04).Trim(); moel@195: this.manufacturer = GetManufacturer(this.manufacturerName); moel@195: this.productName = GetString(0x05).Trim(); moel@195: this.model = GetModel(this.productName); moel@136: this.version = GetString(0x06).Trim(); moel@136: this.serialNumber = GetString(0x07).Trim(); moel@136: } moel@136: moel@64: public string ManufacturerName { get { return manufacturerName; } } moel@64: moel@64: public string ProductName { get { return productName; } } moel@64: moel@89: public string Version { get { return version; } } moel@89: moel@89: public string SerialNumber { get { return serialNumber; } } moel@89: moel@64: public Manufacturer Manufacturer { get { return manufacturer; } } moel@89: moel@126: public Model Model { get { return model; } } moel@126: moel@64: } moel@64: } moel@64: }