Fixed an error where loading config files from previous versions would crash the application.
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 MemoryDevice[] memoryDevices;
30 private static string ReadSysFS(string path) {
32 if (File.Exists(path)) {
33 using (StreamReader reader = new StreamReader(path))
34 return reader.ReadLine();
44 int p = (int)Environment.OSVersion.Platform;
45 if ((p == 4) || (p == 128)) {
49 string boardVendor = ReadSysFS("/sys/class/dmi/id/board_vendor");
50 string boardName = ReadSysFS("/sys/class/dmi/id/board_name");
51 string boardVersion = ReadSysFS("/sys/class/dmi/id/board_version");
52 this.baseBoardInformation = new BaseBoardInformation(
53 boardVendor, boardName, boardVersion, null);
55 string systemVendor = ReadSysFS("/sys/class/dmi/id/sys_vendor");
56 string productName = ReadSysFS("/sys/class/dmi/id/product_name");
57 string productVersion = ReadSysFS("/sys/class/dmi/id/product_version");
58 this.systemInformation = new SystemInformation(systemVendor,
59 productName, productVersion, null, null);
61 string biosVendor = ReadSysFS("/sys/class/dmi/id/bios_vendor");
62 string biosVersion = ReadSysFS("/sys/class/dmi/id/bios_version");
63 this.biosInformation = new BIOSInformation(biosVendor, biosVersion);
65 this.memoryDevices = new MemoryDevice[0];
67 List<Structure> structureList = new List<Structure>();
68 List<MemoryDevice> memoryDeviceList = new List<MemoryDevice>();
71 byte majorVersion = 0;
72 byte minorVersion = 0;
74 ManagementObjectCollection collection;
75 using (ManagementObjectSearcher searcher =
76 new ManagementObjectSearcher("root\\WMI",
77 "SELECT * FROM MSSMBios_RawSMBiosTables")) {
78 collection = searcher.Get();
81 foreach (ManagementObject mo in collection) {
82 raw = (byte[])mo["SMBiosData"];
83 majorVersion = (byte)mo["SmbiosMajorVersion"];
84 minorVersion = (byte)mo["SmbiosMinorVersion"];
89 if (majorVersion > 0 || minorVersion > 0)
90 version = new Version(majorVersion, minorVersion);
92 if (raw != null && raw.Length > 0) {
94 byte type = raw[offset];
95 while (offset + 4 < raw.Length && type != 127) {
98 int length = raw[offset + 1];
99 ushort handle = (ushort)((raw[offset + 2] << 8) | raw[offset + 3]);
101 if (offset + length > raw.Length)
103 byte[] data = new byte[length];
104 Array.Copy(raw, offset, data, 0, length);
107 List<string> stringsList = new List<string>();
108 if (offset < raw.Length && raw[offset] == 0)
111 while (offset < raw.Length && raw[offset] != 0) {
112 StringBuilder sb = new StringBuilder();
113 while (offset < raw.Length && raw[offset] != 0) {
114 sb.Append((char)raw[offset]); offset++;
117 stringsList.Add(sb.ToString());
122 this.biosInformation = new BIOSInformation(
123 type, handle, data, stringsList.ToArray());
124 structureList.Add(this.biosInformation); break;
126 this.systemInformation = new SystemInformation(
127 type, handle, data, stringsList.ToArray());
128 structureList.Add(this.systemInformation); break;
129 case 0x02: this.baseBoardInformation = new BaseBoardInformation(
130 type, handle, data, stringsList.ToArray());
131 structureList.Add(this.baseBoardInformation); break;
132 case 0x11: MemoryDevice m = new MemoryDevice(
133 type, handle, data, stringsList.ToArray());
134 memoryDeviceList.Add(m);
135 structureList.Add(m); break;
136 default: structureList.Add(new Structure(
137 type, handle, data, stringsList.ToArray())); break;
142 memoryDevices = memoryDeviceList.ToArray();
143 table = structureList.ToArray();
147 public string GetReport() {
148 StringBuilder r = new StringBuilder();
150 if (version != null) {
151 r.Append("SMBIOS Version: "); r.AppendLine(version.ToString(2));
156 r.Append("BIOS Vendor: "); r.AppendLine(BIOS.Vendor);
157 r.Append("BIOS Version: "); r.AppendLine(BIOS.Version);
161 if (System != null) {
162 r.Append("System Manufacturer: ");
163 r.AppendLine(System.ManufacturerName);
164 r.Append("System Name: ");
165 r.AppendLine(System.ProductName);
166 r.Append("System Version: ");
167 r.AppendLine(System.Version);
172 r.Append("Mainboard Manufacturer: ");
173 r.AppendLine(Board.ManufacturerName);
174 r.Append("Mainboard Name: ");
175 r.AppendLine(Board.ProductName);
176 r.Append("Mainboard Version: ");
177 r.AppendLine(Board.Version);
181 for (int i = 0; i < MemoryDevices.Length; i++) {
182 r.Append("Memory Device [" + i + "] Manufacturer: ");
183 r.AppendLine(MemoryDevices[i].ManufacturerName);
184 r.Append("Memory Device [" + i + "] Part Number: ");
185 r.AppendLine(MemoryDevices[i].PartNumber);
186 r.Append("Memory Device [" + i + "] Device Locator: ");
187 r.AppendLine(MemoryDevices[i].DeviceLocator);
188 r.Append("Memory Device [" + i + "] Bank Locator: ");
189 r.AppendLine(MemoryDevices[i].BankLocator);
194 string base64 = Convert.ToBase64String(raw);
195 r.AppendLine("SMBIOS Table");
198 for (int i = 0; i < Math.Ceiling(base64.Length / 64.0); i++) {
200 for (int j = 0; j < 0x40; j++) {
201 int index = (i << 6) | j;
202 if (index < base64.Length) {
203 r.Append(base64[index]);
214 public BIOSInformation BIOS {
215 get { return biosInformation; }
218 public SystemInformation System {
219 get { return systemInformation; }
222 public BaseBoardInformation Board {
223 get { return baseBoardInformation; }
226 public MemoryDevice[] MemoryDevices {
227 get { return memoryDevices; }
230 public class Structure {
231 private readonly byte type;
232 private readonly ushort handle;
234 private readonly byte[] data;
235 private readonly string[] strings;
237 protected string GetString(int offset) {
238 if (offset < data.Length && data[offset] > 0 &&
239 data[offset] <= strings.Length)
240 return strings[data[offset] - 1];
245 public Structure(byte type, ushort handle, byte[] data, string[] strings)
248 this.handle = handle;
250 this.strings = strings;
253 public byte Type { get { return type; } }
255 public ushort Handle { get { return handle; } }
258 public class BIOSInformation : Structure {
260 private readonly string vendor;
261 private readonly string version;
263 public BIOSInformation(string vendor, string version)
264 : base (0x00, 0, null, null)
266 this.vendor = vendor;
267 this.version = version;
270 public BIOSInformation(byte type, ushort handle, byte[] data,
272 : base(type, handle, data, strings)
274 this.vendor = GetString(0x04);
275 this.version = GetString(0x05);
278 public string Vendor { get { return vendor; } }
280 public string Version { get { return version; } }
283 public class SystemInformation : Structure {
285 private readonly string manufacturerName;
286 private readonly string productName;
287 private readonly string version;
288 private readonly string serialNumber;
289 private readonly string family;
291 public SystemInformation(string manufacturerName, string productName,
292 string version, string serialNumber, string family)
293 : base (0x01, 0, null, null)
295 this.manufacturerName = manufacturerName;
296 this.productName = productName;
297 this.version = version;
298 this.serialNumber = serialNumber;
299 this.family = family;
302 public SystemInformation(byte type, ushort handle, byte[] data,
304 : base(type, handle, data, strings)
306 this.manufacturerName = GetString(0x04);
307 this.productName = GetString(0x05);
308 this.version = GetString(0x06);
309 this.serialNumber = GetString(0x07);
310 this.family = GetString(0x1A);
313 public string ManufacturerName { get { return manufacturerName; } }
315 public string ProductName { get { return productName; } }
317 public string Version { get { return version; } }
319 public string SerialNumber { get { return serialNumber; } }
321 public string Family { get { return family; } }
325 public class BaseBoardInformation : Structure {
327 private readonly string manufacturerName;
328 private readonly string productName;
329 private readonly string version;
330 private readonly string serialNumber;
332 public BaseBoardInformation(string manufacturerName, string productName,
333 string version, string serialNumber)
334 : base(0x02, 0, null, null)
336 this.manufacturerName = manufacturerName;
337 this.productName = productName;
338 this.version = version;
339 this.serialNumber = serialNumber;
342 public BaseBoardInformation(byte type, ushort handle, byte[] data,
344 : base(type, handle, data, strings) {
346 this.manufacturerName = GetString(0x04).Trim();
347 this.productName = GetString(0x05).Trim();
348 this.version = GetString(0x06).Trim();
349 this.serialNumber = GetString(0x07).Trim();
352 public string ManufacturerName { get { return manufacturerName; } }
354 public string ProductName { get { return productName; } }
356 public string Version { get { return version; } }
358 public string SerialNumber { get { return serialNumber; } }
362 public class MemoryDevice : Structure {
364 private readonly string deviceLocator;
365 private readonly string bankLocator;
366 private readonly string manufacturerName;
367 private readonly string serialNumber;
368 private readonly string partNumber;
370 public MemoryDevice(byte type, ushort handle, byte[] data,
372 : base(type, handle, data, strings)
374 this.deviceLocator = GetString(0x10).Trim();
375 this.bankLocator = GetString(0x11).Trim();
376 this.manufacturerName = GetString(0x17).Trim();
377 this.serialNumber = GetString(0x18).Trim();
378 this.partNumber = GetString(0x1A).Trim();
381 public string DeviceLocator { get { return deviceLocator; } }
383 public string BankLocator { get { return bankLocator; } }
385 public string ManufacturerName { get { return manufacturerName; } }
387 public string SerialNumber { get { return serialNumber; } }
389 public string PartNumber { get { return partNumber; } }