1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/Hardware/SMBIOS.cs Mon Jul 23 21:54:35 2012 +0000
1.3 @@ -0,0 +1,388 @@
1.4 +/*
1.5 +
1.6 + This Source Code Form is subject to the terms of the Mozilla Public
1.7 + License, v. 2.0. If a copy of the MPL was not distributed with this
1.8 + file, You can obtain one at http://mozilla.org/MPL/2.0/.
1.9 +
1.10 + Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
1.11 +
1.12 +*/
1.13 +
1.14 +using System;
1.15 +using System.Collections.Generic;
1.16 +using System.IO;
1.17 +using System.Management;
1.18 +using System.Text;
1.19 +
1.20 +namespace OpenHardwareMonitor.Hardware {
1.21 +
1.22 + internal class SMBIOS {
1.23 +
1.24 + private readonly byte[] raw;
1.25 + private readonly Structure[] table;
1.26 +
1.27 + private readonly Version version;
1.28 + private readonly BIOSInformation biosInformation;
1.29 + private readonly SystemInformation systemInformation;
1.30 + private readonly BaseBoardInformation baseBoardInformation;
1.31 + private readonly MemoryDevice[] memoryDevices;
1.32 +
1.33 + private static string ReadSysFS(string path) {
1.34 + try {
1.35 + if (File.Exists(path)) {
1.36 + using (StreamReader reader = new StreamReader(path))
1.37 + return reader.ReadLine();
1.38 + } else {
1.39 + return null;
1.40 + }
1.41 + } catch {
1.42 + return null;
1.43 + }
1.44 + }
1.45 +
1.46 + public SMBIOS() {
1.47 + int p = (int)Environment.OSVersion.Platform;
1.48 + if ((p == 4) || (p == 128)) {
1.49 + this.raw = null;
1.50 + this.table = null;
1.51 +
1.52 + string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
1.53 + string boardName = ReadSysFS("/sys/class/dmi/id/board_name");
1.54 + string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");
1.55 + this.baseBoardInformation = new BaseBoardInformation(
1.56 + boardVendor, boardName, boardVersion, null);
1.57 +
1.58 + string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor");
1.59 + string productName = ReadSysFS("/sys/class/dmi/id/product_name");
1.60 + string productVersion = ReadSysFS("/sys/class/dmi/id/product_version");
1.61 + this.systemInformation = new SystemInformation(systemVendor,
1.62 + productName, productVersion, null, null);
1.63 +
1.64 + string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
1.65 + string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
1.66 + this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
1.67 +
1.68 + this.memoryDevices = new MemoryDevice[0];
1.69 + } else {
1.70 + List<Structure> structureList = new List<Structure>();
1.71 + List<MemoryDevice> memoryDeviceList = new List<MemoryDevice>();
1.72 +
1.73 + raw = null;
1.74 + byte majorVersion = 0;
1.75 + byte minorVersion = 0;
1.76 + try {
1.77 + ManagementObjectCollection collection;
1.78 + using (ManagementObjectSearcher searcher =
1.79 + new ManagementObjectSearcher("root\\WMI",
1.80 + "SELECT * FROM MSSMBios_RawSMBiosTables")) {
1.81 + collection = searcher.Get();
1.82 + }
1.83 +
1.84 + foreach (ManagementObject mo in collection) {
1.85 + raw = (byte[])mo["SMBiosData"];
1.86 + majorVersion = (byte)mo["SmbiosMajorVersion"];
1.87 + minorVersion = (byte)mo["SmbiosMinorVersion"];
1.88 + break;
1.89 + }
1.90 + } catch { }
1.91 +
1.92 + if (majorVersion > 0 || minorVersion > 0)
1.93 + version = new Version(majorVersion, minorVersion);
1.94 +
1.95 + if (raw != null && raw.Length > 0) {
1.96 + int offset = 0;
1.97 + byte type = raw[offset];
1.98 + while (offset + 4 < raw.Length && type != 127) {
1.99 +
1.100 + type = raw[offset];
1.101 + int length = raw[offset + 1];
1.102 + ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
1.103 +
1.104 + if (offset + length > raw.Length)
1.105 + break;
1.106 + byte[] data = new byte[length];
1.107 + Array.Copy(raw, offset, data, 0, length);
1.108 + offset += length;
1.109 +
1.110 + List<string> stringsList = new List<string>();
1.111 + if (offset < raw.Length && raw[offset] == 0)
1.112 + offset++;
1.113 +
1.114 + while (offset < raw.Length && raw[offset] != 0) {
1.115 + StringBuilder sb = new StringBuilder();
1.116 + while (offset < raw.Length && raw[offset] != 0) {
1.117 + sb.Append((char)raw[offset]); offset++;
1.118 + }
1.119 + offset++;
1.120 + stringsList.Add(sb.ToString());
1.121 + }
1.122 + offset++;
1.123 + switch (type) {
1.124 + case 0x00:
1.125 + this.biosInformation = new BIOSInformation(
1.126 + type, handle, data, stringsList.ToArray());
1.127 + structureList.Add(this.biosInformation); break;
1.128 + case 0x01:
1.129 + this.systemInformation = new SystemInformation(
1.130 + type, handle, data, stringsList.ToArray());
1.131 + structureList.Add(this.systemInformation); break;
1.132 + case 0x02: this.baseBoardInformation = new BaseBoardInformation(
1.133 + type, handle, data, stringsList.ToArray());
1.134 + structureList.Add(this.baseBoardInformation); break;
1.135 + case 0x11: MemoryDevice m = new MemoryDevice(
1.136 + type, handle, data, stringsList.ToArray());
1.137 + memoryDeviceList.Add(m);
1.138 + structureList.Add(m); break;
1.139 + default: structureList.Add(new Structure(
1.140 + type, handle, data, stringsList.ToArray())); break;
1.141 + }
1.142 + }
1.143 + }
1.144 +
1.145 + memoryDevices = memoryDeviceList.ToArray();
1.146 + table = structureList.ToArray();
1.147 + }
1.148 + }
1.149 +
1.150 + public string GetReport() {
1.151 + StringBuilder r = new StringBuilder();
1.152 +
1.153 + if (version != null) {
1.154 + r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2));
1.155 + r.AppendLine();
1.156 + }
1.157 +
1.158 + if (BIOS != null) {
1.159 + r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor);
1.160 + r.Append("BIOS Version: "); r.AppendLine(BIOS.Version);
1.161 + r.AppendLine();
1.162 + }
1.163 +
1.164 + if (System != null) {
1.165 + r.Append("System Manufacturer: ");
1.166 + r.AppendLine(System.ManufacturerName);
1.167 + r.Append("System Name: ");
1.168 + r.AppendLine(System.ProductName);
1.169 + r.Append("System Version: ");
1.170 + r.AppendLine(System.Version);
1.171 + r.AppendLine();
1.172 + }
1.173 +
1.174 + if (Board != null) {
1.175 + r.Append("Mainboard Manufacturer: ");
1.176 + r.AppendLine(Board.ManufacturerName);
1.177 + r.Append("Mainboard Name: ");
1.178 + r.AppendLine(Board.ProductName);
1.179 + r.Append("Mainboard Version: ");
1.180 + r.AppendLine(Board.Version);
1.181 + r.AppendLine();
1.182 + }
1.183 +
1.184 + for (int i = 0; i < MemoryDevices.Length; i++) {
1.185 + r.Append("Memory Device [" + i + "] Manufacturer: ");
1.186 + r.AppendLine(MemoryDevices[i].ManufacturerName);
1.187 + r.Append("Memory Device [" + i + "] Part Number: ");
1.188 + r.AppendLine(MemoryDevices[i].PartNumber);
1.189 + r.AppendLine();
1.190 + }
1.191 +
1.192 + if (raw != null) {
1.193 + string base64 = Convert.ToBase64String(raw);
1.194 + r.AppendLine("SMBIOS Table");
1.195 + r.AppendLine();
1.196 +
1.197 + for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
1.198 + r.Append(" ");
1.199 + for (int j = 0; j < 0x40; j++) {
1.200 + int index = (i << 6) | j;
1.201 + if (index < base64.Length) {
1.202 + r.Append(base64[index]);
1.203 + }
1.204 + }
1.205 + r.AppendLine();
1.206 + }
1.207 + r.AppendLine();
1.208 + }
1.209 +
1.210 + return r.ToString();
1.211 + }
1.212 +
1.213 + public BIOSInformation BIOS {
1.214 + get { return biosInformation; }
1.215 + }
1.216 +
1.217 + public SystemInformation System {
1.218 + get { return systemInformation; }
1.219 + }
1.220 +
1.221 + public BaseBoardInformation Board {
1.222 + get { return baseBoardInformation; }
1.223 + }
1.224 +
1.225 + public MemoryDevice[] MemoryDevices {
1.226 + get { return memoryDevices; }
1.227 + }
1.228 +
1.229 + public class Structure {
1.230 + private readonly byte type;
1.231 + private readonly ushort handle;
1.232 +
1.233 + private readonly byte[] data;
1.234 + private readonly string[] strings;
1.235 +
1.236 + protected string GetString(int offset) {
1.237 + if (offset < data.Length && data[offset] > 0 &&
1.238 + data[offset] <= strings.Length)
1.239 + return strings[data[offset] - 1];
1.240 + else
1.241 + return "";
1.242 + }
1.243 +
1.244 + public Structure(byte type, ushort handle, byte[] data, string[] strings)
1.245 + {
1.246 + this.type = type;
1.247 + this.handle = handle;
1.248 + this.data = data;
1.249 + this.strings = strings;
1.250 + }
1.251 +
1.252 + public byte Type { get { return type; } }
1.253 +
1.254 + public ushort Handle { get { return handle; } }
1.255 + }
1.256 +
1.257 + public class BIOSInformation : Structure {
1.258 +
1.259 + private readonly string vendor;
1.260 + private readonly string version;
1.261 +
1.262 + public BIOSInformation(string vendor, string version)
1.263 + : base (0x00, 0, null, null)
1.264 + {
1.265 + this.vendor = vendor;
1.266 + this.version = version;
1.267 + }
1.268 +
1.269 + public BIOSInformation(byte type, ushort handle, byte[] data,
1.270 + string[] strings)
1.271 + : base(type, handle, data, strings)
1.272 + {
1.273 + this.vendor = GetString(0x04);
1.274 + this.version = GetString(0x05);
1.275 + }
1.276 +
1.277 + public string Vendor { get { return vendor; } }
1.278 +
1.279 + public string Version { get { return version; } }
1.280 + }
1.281 +
1.282 + public class SystemInformation : Structure {
1.283 +
1.284 + private readonly string manufacturerName;
1.285 + private readonly string productName;
1.286 + private readonly string version;
1.287 + private readonly string serialNumber;
1.288 + private readonly string family;
1.289 +
1.290 + public SystemInformation(string manufacturerName, string productName,
1.291 + string version, string serialNumber, string family)
1.292 + : base (0x01, 0, null, null)
1.293 + {
1.294 + this.manufacturerName = manufacturerName;
1.295 + this.productName = productName;
1.296 + this.version = version;
1.297 + this.serialNumber = serialNumber;
1.298 + this.family = family;
1.299 + }
1.300 +
1.301 + public SystemInformation(byte type, ushort handle, byte[] data,
1.302 + string[] strings)
1.303 + : base(type, handle, data, strings)
1.304 + {
1.305 + this.manufacturerName = GetString(0x04);
1.306 + this.productName = GetString(0x05);
1.307 + this.version = GetString(0x06);
1.308 + this.serialNumber = GetString(0x07);
1.309 + this.family = GetString(0x1A);
1.310 + }
1.311 +
1.312 + public string ManufacturerName { get { return manufacturerName; } }
1.313 +
1.314 + public string ProductName { get { return productName; } }
1.315 +
1.316 + public string Version { get { return version; } }
1.317 +
1.318 + public string SerialNumber { get { return serialNumber; } }
1.319 +
1.320 + public string Family { get { return family; } }
1.321 +
1.322 + }
1.323 +
1.324 + public class BaseBoardInformation : Structure {
1.325 +
1.326 + private readonly string manufacturerName;
1.327 + private readonly string productName;
1.328 + private readonly string version;
1.329 + private readonly string serialNumber;
1.330 +
1.331 + public BaseBoardInformation(string manufacturerName, string productName,
1.332 + string version, string serialNumber)
1.333 + : base(0x02, 0, null, null)
1.334 + {
1.335 + this.manufacturerName = manufacturerName;
1.336 + this.productName = productName;
1.337 + this.version = version;
1.338 + this.serialNumber = serialNumber;
1.339 + }
1.340 +
1.341 + public BaseBoardInformation(byte type, ushort handle, byte[] data,
1.342 + string[] strings)
1.343 + : base(type, handle, data, strings) {
1.344 +
1.345 + this.manufacturerName = GetString(0x04).Trim();
1.346 + this.productName = GetString(0x05).Trim();
1.347 + this.version = GetString(0x06).Trim();
1.348 + this.serialNumber = GetString(0x07).Trim();
1.349 + }
1.350 +
1.351 + public string ManufacturerName { get { return manufacturerName; } }
1.352 +
1.353 + public string ProductName { get { return productName; } }
1.354 +
1.355 + public string Version { get { return version; } }
1.356 +
1.357 + public string SerialNumber { get { return serialNumber; } }
1.358 +
1.359 + }
1.360 +
1.361 + public class MemoryDevice : Structure {
1.362 +
1.363 + private readonly string manufacturerName;
1.364 + private readonly string serialNumber;
1.365 + private readonly string partNumber;
1.366 +
1.367 + public MemoryDevice(string manufacturerName, string serialNumber,
1.368 + string partNumber)
1.369 + : base(0x11, 0, null, null) {
1.370 + this.manufacturerName = manufacturerName;
1.371 + this.serialNumber = serialNumber;
1.372 + this.partNumber = partNumber;
1.373 + }
1.374 +
1.375 + public MemoryDevice(byte type, ushort handle, byte[] data,
1.376 + string[] strings)
1.377 + : base(type, handle, data, strings) {
1.378 + this.manufacturerName = GetString(0x17).Trim();
1.379 + this.serialNumber = GetString(0x18).Trim();
1.380 + this.partNumber = GetString(0x1A).Trim();
1.381 + }
1.382 +
1.383 + public string ManufacturerName { get { return manufacturerName; } }
1.384 +
1.385 + public string SerialNumber { get { return serialNumber; } }
1.386 +
1.387 + public string PartNumber { get { return partNumber; } }
1.388 +
1.389 + }
1.390 + }
1.391 +}