Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / tests / avocado / acpi-bits / bits-tests / smbios.py2
blobfc623de072a7ffb8c4a7068e6ab107dc5535cd81
1 # Copyright (c) 2015, Intel Corporation
2 # All rights reserved.
4 # SPDX-License-Identifier: BSD-3-Clause
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions are met:
9 #     * Redistributions of source code must retain the above copyright notice,
10 #       this list of conditions and the following disclaimer.
11 #     * Redistributions in binary form must reproduce the above copyright notice,
12 #       this list of conditions and the following disclaimer in the documentation
13 #       and/or other materials provided with the distribution.
14 #     * Neither the name of Intel Corporation nor the names of its contributors
15 #       may be used to endorse or promote products derived from this software
16 #       without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 # This script runs only from the biosbits VM.
31 """SMBIOS/DMI module."""
33 import bits
34 import bitfields
35 import ctypes
36 import redirect
37 import struct
38 import uuid
39 import unpack
40 import ttypager
41 import sys
43 class SMBIOS(unpack.Struct):
44     def __new__(cls):
45         if sys.platform == "BITS-EFI":
46             import efi
47             sm_ptr = efi.system_table.ConfigurationTableDict.get(efi.SMBIOS_TABLE_GUID)
48         else:
49             address = 0xF0000
50             mem = bits.memory(0xF0000, 0x10000)
51             for offset in range(0, len(mem), 16):
52                 signature = (ctypes.c_char * 4).from_address(address + offset).value
53                 if signature == "_SM_":
54                     entry_point_length = ctypes.c_ubyte.from_address(address + offset + 5).value
55                     csum = sum(map(ord, mem[offset:offset + entry_point_length])) & 0xff
56                     if csum == 0:
57                         sm_ptr = address + offset
58                         break
59             else:
60                 return None
62         if not sm_ptr:
63             return None
65         sm = super(SMBIOS, cls).__new__(cls)
66         sm._header_memory = bits.memory(sm_ptr, 0x1f)
67         return sm
69     def __init__(self):
70         super(SMBIOS, self).__init__()
71         u = unpack.Unpackable(self._header_memory)
72         self.add_field('header', Header(u))
73         self._structure_memory = bits.memory(self.header.structure_table_address, self.header.structure_table_length)
74         u = unpack.Unpackable(self._structure_memory)
75         self.add_field('structures', unpack.unpack_all(u, _smbios_structures, self), unpack.format_each("\n\n{!r}"))
77     def structure_type(self, num):
78         '''Dumps structure of given Type if present'''
79         try:
80             types_present = [self.structures[x].smbios_structure_type for x in range(len(self.structures))]
81             matrix = dict()
82             for index in range(len(types_present)):
83                 if types_present.count(types_present[index]) == 1:
84                     matrix[types_present[index]] = self.structures[index]
85                 else: # if multiple structures of the same type, return a list of structures for the type number
86                     if matrix.has_key(types_present[index]):
87                         matrix[types_present[index]].append(self.structures[index])
88                     else:
89                         matrix[types_present[index]] = [self.structures[index]]
90             return matrix[num]
91         except:
92             print "Failure: Type {} - not found".format(num)
94 class Header(unpack.Struct):
95     def __new__(cls, u):
96         return super(Header, cls).__new__(cls)
98     def __init__(self, u):
99         super(Header, self).__init__()
100         self.raw_data = u.unpack_rest()
101         u = unpack.Unpackable(self.raw_data)
102         self.add_field('anchor_string', u.unpack_one("4s"))
103         self.add_field('checksum', u.unpack_one("B"))
104         self.add_field('length', u.unpack_one("B"))
105         self.add_field('major_version', u.unpack_one("B"))
106         self.add_field('minor_version', u.unpack_one("B"))
107         self.add_field('max_structure_size', u.unpack_one("<H"))
108         self.add_field('entry_point_revision', u.unpack_one("B"))
109         self.add_field('formatted_area', u.unpack_one("5s"))
110         self.add_field('intermediate_anchor_string', u.unpack_one("5s"))
111         self.add_field('intermediate_checksum', u.unpack_one("B"))
112         self.add_field('structure_table_length', u.unpack_one("<H"))
113         self.add_field('structure_table_address', u.unpack_one("<I"))
114         self.add_field('number_structures', u.unpack_one("<H"))
115         self.add_field('bcd_revision', u.unpack_one("B"))
116         if not u.at_end():
117             self.add_field('data', u.unpack_rest())
119 class SmbiosBaseStructure(unpack.Struct):
120     def __new__(cls, u, sm):
121         t = u.unpack_peek_one("B")
122         if cls.smbios_structure_type is not None and t != cls.smbios_structure_type:
123             return None
124         return super(SmbiosBaseStructure, cls).__new__(cls)
126     def __init__(self, u, sm):
127         super(SmbiosBaseStructure, self).__init__()
128         self.start_offset = u.offset
129         length = u.unpack_peek_one("<xB")
130         self.raw_data = u.unpack_raw(length)
131         self.u = unpack.Unpackable(self.raw_data)
133         self.strings_offset = u.offset
134         def unpack_string():
135             return "".join(iter(lambda: u.unpack_one("c"), "\x00"))
136         strings = list(iter(unpack_string, ""))
137         if not strings:
138             u.skip(1)
140         self.strings_length = u.offset - self.strings_offset
141         self.raw_strings = str(bits.memory(sm.header.structure_table_address + self.strings_offset, self.strings_length))
143         if len(strings):
144             self.strings = strings
146         self.add_field('type', self.u.unpack_one("B"))
147         self.add_field('length', self.u.unpack_one("B"))
148         self.add_field('handle', self.u.unpack_one("<H"))
150     def fini(self):
151         if not self.u.at_end():
152             self.add_field('data', self.u.unpack_rest())
153         del self.u
155     def fmtstr(self, i):
156         """Format the specified index and the associated string"""
157         return "{} '{}'".format(i, self.getstr(i))
159     def getstr(self, i):
160         """Get the string associated with the given index"""
161         if i == 0:
162             return "(none)"
163         if not hasattr(self, "strings"):
164             return "(error: structure has no strings)"
165         if i > len(self.strings):
166             return "(error: string index out of range)"
167         return self.strings[i - 1]
169 class BIOSInformation(SmbiosBaseStructure):
170     smbios_structure_type = 0
172     def __init__(self, u, sm):
173         super(BIOSInformation, self).__init__(u, sm)
174         u = self.u
175         try:
176             self.add_field('vendor', u.unpack_one("B"), self.fmtstr)
177             self.add_field('version', u.unpack_one("B"), self.fmtstr)
178             self.add_field('starting_address_segment', u.unpack_one("<H"))
179             self.add_field('release_date', u.unpack_one("B"), self.fmtstr)
180             self.add_field('rom_size', u.unpack_one("B"))
181             self.add_field('characteristics', u.unpack_one("<Q"))
182             minor_version_str = str(sm.header.minor_version) # 34 is .34, 4 is .4, 41 is .41; compare ASCIIbetically to compare initial digits rather than numeric value
183             if (sm.header.major_version, minor_version_str) >= (2,"4"):
184                 characteristic_bytes = 2
185             else:
186                 characteristic_bytes = self.length - 0x12
187             self.add_field('characteristics_extensions', [u.unpack_one("B") for b in range(characteristic_bytes)])
188             if (sm.header.major_version, minor_version_str) >= (2,"4"):
189                 self.add_field('major_release', u.unpack_one("B"))
190                 self.add_field('minor_release', u.unpack_one("B"))
191                 self.add_field('ec_major_release', u.unpack_one("B"))
192                 self.add_field('ec_minor_release', u.unpack_one("B"))
193         except:
194             self.decode_failure = True
195             print "Error parsing BIOSInformation"
196             import traceback
197             traceback.print_exc()
198         self.fini()
200 class SystemInformation(SmbiosBaseStructure):
201     smbios_structure_type = 1
203     def __init__(self, u, sm):
204         super(SystemInformation, self).__init__(u, sm)
205         u = self.u
206         try:
207             self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
208             self.add_field('product_name', u.unpack_one("B"), self.fmtstr)
209             self.add_field('version', u.unpack_one("B"), self.fmtstr)
210             self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
211             if self.length > 0x8:
212                 self.add_field('uuid', uuid.UUID(bytes_le=u.unpack_one("16s")))
213                 wakeup_types = {
214                     0: 'Reserved',
215                     1: 'Other',
216                     2: 'Unknown',
217                     3: 'APM Timer',
218                     4: 'Modem Ring',
219                     5: 'LAN Remote',
220                     6: 'Power Switch',
221                     7: 'PCI PME#',
222                     8: 'AC Power Restored'
223                 }
224                 self.add_field('wakeup_type', u.unpack_one("B"), unpack.format_table("{}", wakeup_types))
225             if self.length > 0x19:
226                 self.add_field('sku_number', u.unpack_one("B"), self.fmtstr)
227                 self.add_field('family', u.unpack_one("B"), self.fmtstr)
228         except:
229             self.decode_failure = True
230             print "Error parsing SystemInformation"
231             import traceback
232             traceback.print_exc()
233         self.fini()
235 _board_types = {
236     1: 'Unknown',
237     2: 'Other',
238     3: 'Server Blade',
239     4: 'Connectivity Switch',
240     5: 'System Management Module',
241     6: 'Processor Module',
242     7: 'I/O Module',
243     8: 'Memory Module',
244     9: 'Daughter Board',
245     0xA: 'Motherboard',
246     0xB: 'Processor/Memory Module',
247     0xC: 'Processor/IO Module',
248     0xD: 'Interconnect Board'
251 class BaseboardInformation(SmbiosBaseStructure):
252     smbios_structure_type = 2
254     def __init__(self, u, sm):
255         super(BaseboardInformation, self).__init__(u, sm)
256         u = self.u
257         try:
258             self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
259             self.add_field('product', u.unpack_one("B"), self.fmtstr)
260             self.add_field('version', u.unpack_one("B"), self.fmtstr)
261             self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
263             if self.length > 0x8:
264                 self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
266             if self.length > 0x9:
267                 self.add_field('feature_flags', u.unpack_one("B"))
268                 self.add_field('hosting_board', bool(bitfields.getbits(self.feature_flags, 0)), "feature_flags[0]={}")
269                 self.add_field('requires_daughter_card', bool(bitfields.getbits(self.feature_flags, 1)), "feature_flags[1]={}")
270                 self.add_field('removable', bool(bitfields.getbits(self.feature_flags, 2)), "feature_flags[2]={}")
271                 self.add_field('replaceable', bool(bitfields.getbits(self.feature_flags, 3)), "feature_flags[3]={}")
272                 self.add_field('hot_swappable', bool(bitfields.getbits(self.feature_flags, 4)), "feature_flags[4]={}")
274             if self.length > 0xA:
275                 self.add_field('location', u.unpack_one("B"), self.fmtstr)
277             if self.length > 0xB:
278                 self.add_field('chassis_handle', u.unpack_one("<H"))
280             if self.length > 0xD:
281                 self.add_field('board_type', u.unpack_one("B"), unpack.format_table("{}", _board_types))
283             if self.length > 0xE:
284                 self.add_field('handle_count', u.unpack_one("B"))
285                 if self.handle_count > 0:
286                     self.add_field('contained_object_handles', tuple(u.unpack_one("<H") for i in range(self.handle_count)))
287         except:
288             self.decode_failure = True
289             print "Error parsing BaseboardInformation"
290             import traceback
291             traceback.print_exc()
292         self.fini()
294 class SystemEnclosure(SmbiosBaseStructure):
295     smbios_structure_type = 3
297     def __init__(self, u, sm):
298         super(SystemEnclosure, self).__init__(u, sm)
299         u = self.u
300         try:
301             self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
302             self.add_field('enumerated_type', u.unpack_one("B"))
303             self.add_field('chassis_lock_present', bool(bitfields.getbits(self.enumerated_type, 7)), "enumerated_type[7]={}")
304             board_types = {
305                 0x01: 'Other',
306                 0x02: 'Unknown',
307                 0x03: 'Desktop',
308                 0x04: 'Low Profile Desktop',
309                 0x05: 'Pizza Box',
310                 0x06: 'Mini Tower',
311                 0x07: 'Tower',
312                 0x08: 'Portable',
313                 0x09: 'Laptop',
314                 0x0A: 'Notebook',
315                 0x0B: 'Hand Held',
316                 0x0C: 'Docking Station',
317                 0x0D: 'All in One',
318                 0x0E: 'Sub Notebook',
319                 0x0F: 'Space-saving',
320                 0x10: 'Lunch Box',
321                 0x11: 'Main Server Chassis',
322                 0x12: 'Expansion Chassis',
323                 0x13: 'SubChassis',
324                 0x14: 'Bus Expansion Chassis',
325                 0x15: 'Peripheral Chassis',
326                 0x16: 'RAID Chassis',
327                 0x17: 'Rack Mount Chassis',
328                 0x18: 'Sealed-case PC',
329                 0x19: 'Multi-system chassis W',
330                 0x1A: 'Compact PCI',
331                 0x1B: 'Advanced TCA',
332                 0x1C: 'Blade',
333                 0x1D: 'Blade Enclosure',
334             }
335             self.add_field('system_enclosure_type', bitfields.getbits(self.enumerated_type, 6, 0), unpack.format_table("enumerated_type[6:0]={}", board_types))
336             self.add_field('version', u.unpack_one("B"), self.fmtstr)
337             self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
338             self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
339             minor_version_str = str(sm.header.minor_version) # 34 is .34, 4 is .4, 41 is .41; compare ASCIIbetically to compare initial digits rather than numeric value
340             if self.length > 9:
341                 chassis_states = {
342                     0x01: 'Other',
343                     0x02: 'Unknown',
344                     0x03: 'Safe',
345                     0x04: 'Warning',
346                     0x05: 'Critical',
347                     0x06: 'Non-recoverable',
348                 }
349                 self.add_field('bootup_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states))
350                 self.add_field('power_supply_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states))
351                 self.add_field('thermal_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states))
352                 security_states = {
353                     0x01: 'Other',
354                     0x02: 'Unknown',
355                     0x03: 'None',
356                     0x04: 'External interface locked out',
357                     0x05: 'External interface enabled',
358                 }
359                 self.add_field('security_status', u.unpack_one("B"), unpack.format_table("{}", security_states))
360             if self.length > 0xd:
361                 self.add_field('oem_defined', u.unpack_one("<I"))
362             if self.length > 0x11:
363                 self.add_field('height', u.unpack_one("B"))
364                 self.add_field('num_power_cords', u.unpack_one("B"))
365                 self.add_field('contained_element_count', u.unpack_one("B"))
366                 self.add_field('contained_element_length', u.unpack_one("B"))
367             if getattr(self, 'contained_element_count', 0):
368                 self.add_field('contained_elements', tuple(SystemEnclosureContainedElement(u, self.contained_element_length) for i in range(self.contained_element_count)))
369             if self.length > (0x15 + (getattr(self, 'contained_element_count', 0) * getattr(self, 'contained_element_length', 0))):
370                 self.add_field('sku_number', u.unpack_one("B"), self.fmtstr)
371         except:
372             self.decode_failure = True
373             print "Error parsing SystemEnclosure"
374             import traceback
375             traceback.print_exc()
376         self.fini()
378 class SystemEnclosureContainedElement(unpack.Struct):
379     def __init__(self, u, length):
380         super(SystemEnclosureContainedElement, self).__init__()
381         self.start_offset = u.offset
382         self.raw_data = u.unpack_raw(length)
383         self.u = unpack.Unpackable(self.raw_data)
384         u = self.u
385         self.add_field('contained_element_type', u.unpack_one("B"))
386         type_selections = {
387             0: 'SMBIOS baseboard type enumeration',
388             1: 'SMBIOS structure type enumeration',
389         }
390         self.add_field('type_select', bitfields.getbits(self.contained_element_type, 7), unpack.format_table("contained_element_type[7]={}", type_selections))
391         self.add_field('type', bitfields.getbits(self.contained_element_type, 6, 0))
392         if self.type_select == 0:
393             self.add_field('smbios_board_type', self.type, unpack.format_table("{}", _board_types))
394         else:
395             self.add_field('smbios_structure_type', self.type)
396         self.add_field('minimum', u.unpack_one("B"))
397         self.add_field('maximum', u.unpack_one("B"))
398         if not u.at_end():
399             self.add_field('data', u.unpack_rest())
400         del self.u
402 class ProcessorInformation(SmbiosBaseStructure):
403     smbios_structure_type = 4
405     def __init__(self, u, sm):
406         super(ProcessorInformation, self).__init__(u, sm)
407         u = self.u
408         try:
409             self.add_field('socket_designation', u.unpack_one("B"), self.fmtstr)
410             processor_types = {
411                 0x01: 'Other',
412                 0x02: 'Unknown',
413                 0x03: 'Central Processor',
414                 0x04: 'Math Processor',
415                 0x05: 'DSP Processor',
416                 0x06: 'Video Processor',
417             }
418             self.add_field('processor_type', u.unpack_one("B"), unpack.format_table("{}", processor_types))
419             self.add_field('processor_family', u.unpack_one("B"))
420             self.add_field('processor_manufacturer', u.unpack_one("B"), self.fmtstr)
421             self.add_field('processor_id', u.unpack_one("<Q"))
422             self.add_field('processor_version', u.unpack_one("B"), self.fmtstr)
423             self.add_field('voltage', u.unpack_one("B"))
424             self.add_field('external_clock', u.unpack_one("<H"))
425             self.add_field('max_speed', u.unpack_one("<H"))
426             self.add_field('current_speed', u.unpack_one("<H"))
427             self.add_field('status', u.unpack_one("B"))
428             processor_upgrades = {
429                 0x01: 'Other',
430                 0x02: 'Unknown',
431                 0x03: 'Daughter Board',
432                 0x04: 'ZIF Socket',
433                 0x05: 'Replaceable Piggy Back',
434                 0x06: 'None',
435                 0x07: 'LIF Socket',
436                 0x08: 'Slot 1',
437                 0x09: 'Slot 2',
438                 0x0A: '370-pin socket',
439                 0x0B: 'Slot A',
440                 0x0C: 'Slot M',
441                 0x0D: 'Socket 423',
442                 0x0E: 'Socket A (Socket 462)',
443                 0x0F: 'Socket 478',
444                 0x10: 'Socket 754',
445                 0x11: 'Socket 940',
446                 0x12: 'Socket 939',
447                 0x13: 'Socket mPGA604',
448                 0x14: 'Socket LGA771',
449                 0x15: 'Socket LGA775',
450                 0x16: 'Socket S1',
451                 0x17: 'Socket AM2',
452                 0x18: 'Socket F (1207)',
453                 0x19: 'Socket LGA1366',
454                 0x1A: 'Socket G34',
455                 0x1B: 'Socket AM3',
456                 0x1C: 'Socket C32',
457                 0x1D: 'Socket LGA1156',
458                 0x1E: 'Socket LGA1567',
459                 0x1F: 'Socket PGA988A',
460                 0x20: 'Socket BGA1288',
461                 0x21: 'Socket rPGA988B',
462                 0x22: 'Socket BGA1023',
463                 0x23: 'Socket BGA1224',
464                 0x24: 'Socket BGA1155',
465                 0x25: 'Socket LGA1356',
466                 0x26: 'Socket LGA2011',
467                 0x27: 'Socket FS1',
468                 0x28: 'Socket FS2',
469                 0x29: 'Socket FM1',
470                 0x2A: 'Socket FM2',
471             }
472             self.add_field('processor_upgrade', u.unpack_one("B"), unpack.format_table("{}", processor_upgrades))
473             if self.length > 0x1A:
474                 self.add_field('l1_cache_handle', u.unpack_one("<H"))
475                 self.add_field('l2_cache_handle', u.unpack_one("<H"))
476                 self.add_field('l3_cache_handle', u.unpack_one("<H"))
477             if self.length > 0x20:
478                 self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
479                 self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
480                 self.add_field('part_number', u.unpack_one("B"), self.fmtstr)
481             if self.length > 0x24:
482                 self.add_field('core_count', u.unpack_one("B"))
483                 self.add_field('core_enabled', u.unpack_one("B"))
484                 self.add_field('thread_count', u.unpack_one("B"))
485                 self.add_field('processor_characteristics', u.unpack_one("<H"))
486             if self.length > 0x28:
487                 self.add_field('processor_family_2', u.unpack_one("<H"))
488             if self.length > 0x2A:
489                 self.add_field('core_count2', u.unpack_one("<H"))
490                 self.add_field('core_enabled2', u.unpack_one("<H"))
491                 self.add_field('thread_count2', u.unpack_one("<H"))
492         except:
493             self.decode_failure = True
494             print "Error parsing Processor Information"
495             import traceback
496             traceback.print_exc()
497         self.fini()
499 class MemoryControllerInformation(SmbiosBaseStructure): #obsolete starting with v2.1
500     smbios_structure_type = 5
502     def __init__(self, u, sm):
503         super(MemoryControllerInformation, self).__init__(u, sm)
504         u = self.u
505         try:
506             _error_detecting_method = {
507                 0x01: 'Other',
508                 0x02: 'Unknown',
509                 0x03: 'None',
510                 0x04: '8-bit Parity',
511                 0x05: '32-bit ECC',
512                 0x06: '64-bit ECC',
513                 0x07: '128-bit ECC',
514                 0x08: 'CRC'
515                 }
516             self.add_field('error_detecting_method', u.unpack_one("B"), unpack.format_table("{}", _error_detecting_method))
517             self.add_field('error_correcting_capability', u.unpack_one("B"))
518             _interleaves = {
519                 0x01: 'Other',
520                 0x02: 'Unknown',
521                 0x03: 'One-Way Interleave',
522                 0x04: 'Two-Way Interleave',
523                 0x05: 'Four-Way Interleave',
524                 0x06: 'Eight-Way Interleave',
525                 0x07: 'Sixteen-Way Interleave'
526                 }
527             self.add_field('supported_interleave', u.unpack_one("B"), unpack.format_table("{}", _interleaves))
528             self.add_field('current_interleave', u.unpack_one("B"), unpack.format_table("{}", _interleaves))
529             self.add_field('max_memory_module_size', u.unpack_one("B"), self.fmtstr)
530             self.add_field('supported_speeds', u.unpack_one("<H"))
531             self.add_field('supported_memory_types', u.unpack_one("<H"))
532             self.add_field('memory_module_voltage', u.unpack_one("B"))
533             self.add_field('req_voltage_b2', bitfields.getbits(self.memory_module_voltage, 2), "memory_module_voltage[2]={}")
534             self.add_field('req_voltage_b1', bitfields.getbits(self.memory_module_voltage, 1), "memory_module_voltage[1]={}")
535             self.add_field('req_voltage_b0', bitfields.getbits(self.memory_module_voltage, 0), "memory_module_voltage[0]={}")
536             self.add_field('num_associated_memory_slots', u.unpack_one("B"))
537             self.add_field('memory_module_configuration_handles', u.unpack_one("<(self.num_associated_memory_slots)H"))
538             self.add_field('enabled_error_correcting_capabilities', u.unpack_one("B"))
539         except:
540             self.decode_failure = True
541             print "Error parsing MemoryControllerInformation"
542             import traceback
543             traceback.print_exc()
544         self.fini()
546 class MemoryModuleInformation(SmbiosBaseStructure): #obsolete starting with v2.1
547     smbios_structure_type = 6
549     def __init__(self, u, sm):
550         super(MemoryModuleInformation, self).__init__(u, sm)
551         u = self.u
552         try:
553             self.add_field('socket_designation', u.unpack_one("B"), self.fmtstr)
554             self.add_field('bank_connections', u.unpack_one("B"))
555             self.add_field('current_speed', u.unpack_one("B"))
556             self.add_field('current_memory_type', u.unpack_one("<H"))
557             _mem_connection = {
558                 0: 'single',
559                 1: 'double-bank'
560                 }
561             self.add_field('installed_mem', u.unpack_one("B"))
562             self.add_field('installed_size', bitfields.getbits(self.installed_mem, 6, 0), "installed_mem[6:0]={}")
563             self.add_field('installed_memory_module_connection', bitfields.getbits(self.installed_mem, 7), unpack.format_table("installed_mem[7]={}", _mem_connection))
564             self.add_field('enabled_mem', u.unpack_one("B"))
565             self.add_field('enabled_size', bitfields.getbits(self.installed_mem, 6, 0), "enabled_mem[6:0]={}")
566             self.add_field('enabled_memory_module_connection', bitfields.getbits(self.installed_mem, 7), unpack.format_table("enabled_mem[7]={}", _mem_connection))
567             self.add_field('error_status', u.unpack_one("B"))
568             self.add_field('error_status_info_obstained_from_event_log', bool(bitfields.getbits(self.error_status, 2)), unpack.format_table("error_status[2]={}", _mem_connection))
569             self.add_field('correctable_errors_received', bool(bitfields.getbits(self.error_status, 1)), unpack.format_table("error_status[1]={}", _mem_connection))
570             self.add_field('uncorrectable_errors_received', bool(bitfields.getbits(self.error_status, 0)), unpack.format_table("error_status[0]={}", _mem_connection))
571         except:
572             self.decode_failure = True
573             print "Error parsing MemoryModuleInformation"
574             import traceback
575             traceback.print_exc()
576         self.fini()
578 class CacheInformation(SmbiosBaseStructure):
579     smbios_structure_type = 7
581     def __init__(self, u, sm):
582         super(CacheInformation, self).__init__(u, sm)
583         u = self.u
584         try:
585             self.add_field('socket_designation', u.unpack_one("B"), self.fmtstr)
586             processor_types = {
587                 0x01: 'Other',
588                 0x02: 'Unknown',
589                 0x03: 'Central Processor',
590                 0x04: 'Math Processor',
591                 0x05: 'DSP Processor',
592                 0x06: 'Video Processor',
593             }
594             self.add_field('cache_configuration', u.unpack_one("<H"))
595             _operational_mode = {
596                 0b00: 'Write Through',
597                 0b01: 'Write Back',
598                 0b10: 'Varies with Memory Address',
599                 0b11: 'Unknown'
600                 }
601             self.add_field('operational_mode', bitfields.getbits(self.cache_configuration, 9, 8), unpack.format_table("cache_configuration[9:8]={}", _operational_mode))
602             self.add_field('enabled_at_boot_time', bool(bitfields.getbits(self.cache_configuration, 7)), "cache_configuration[7]={}")
603             _location = {
604                 0b00: 'Internal',
605                 0b01: 'External',
606                 0b10: 'Reserved',
607                 0b11: 'Unknown'
608                 }
609             self.add_field('location_relative_to_cpu_module', bitfields.getbits(self.cache_configuration, 6, 5), unpack.format_table("cache_configuration[6:5]={}", _location))
610             self.add_field('cache_socketed', bool(bitfields.getbits(self.cache_configuration, 3)), "cache_configuration[3]={}")
611             self.add_field('cache_level', bitfields.getbits(self.cache_configuration, 2, 0), "cache_configuration[2:0]={}")
612             self.add_field('max_cache_size', u.unpack_one("<H"))
613             _granularity = {
614                 0: '1K granularity',
615                 1: '64K granularity'
616                 }
617             self.add_field('max_granularity', bitfields.getbits(self.cache_configuration, 15), unpack.format_table("max_cache_size[15]={}", _granularity))
618             self.add_field('max_size_in_granularity', bitfields.getbits(self.cache_configuration, 14, 0), "max_cache_size[14, 0]={}")
619             self.add_field('installed_size', u.unpack_one("<H"))
620             if self.installed_size != 0:
621                 self.add_field('installed_granularity', bitfields.getbits(self.cache_configuration, 15), unpack.format_table("installed_size[15]={}", _granularity))
622                 self.add_field('installed_size_in_granularity', bitfields.getbits(self.cache_configuration, 14, 0), "installed_size[14, 0]={}")
623             self.add_field('supported_sram_type', u.unpack_one("<H"))
624             self.add_field('current_sram_type', u.unpack_one("<H"))
625             if self.length > 0x0F:
626                 self.add_field('cache_speed', u.unpack_one("B"))
627             if self.length > 0x10:
628                 _error_correction = {
629                     0x01: 'Other',
630                     0x02: 'Unknown',
631                     0x03: 'None',
632                     0x04: 'Parity',
633                     0x05: 'Single-bit ECC',
634                     0x06: 'Multi-bit ECC'
635                     }
636                 self.add_field('error_correction', u.unpack_one("B"), unpack.format_table("{}", _error_correction))
637             if self.length > 0x10:
638                 _system_cache_type = {
639                     0x01: 'Other',
640                     0x02: 'Unknown',
641                     0x03: 'Instruction',
642                     0x04: 'Data',
643                     0x05: 'Unified'
644                     }
645                 self.add_field('system_cache_type', u.unpack_one("B"), unpack.format_table("{}", _system_cache_type))
646             if self.length > 0x12:
647                 _associativity = {
648                     0x01: 'Other',
649                     0x02: 'Unknown',
650                     0x03: 'Direct Mapped',
651                     0x04: '2-way Set-Associative',
652                     0x05: '4-way Set-Associative',
653                     0x06: 'Fully Associative',
654                     0x07: '8-way Set-Associative',
655                     0x08: '16-way Set-Associative',
656                     0x09: '12-way Set-Associative',
657                     0x0A: '24-way Set-Associative',
658                     0x0B: '32-way Set-Associative',
659                     0x0C: '48-way Set-Associative',
660                     0x0D: '64-way Set-Associative',
661                     0x0E: '20-way Set-Associative'
662                     }
663                 self.add_field('associativity', u.unpack_one("B"), unpack.format_table("{}", _associativity))
665         except:
666             self.decode_failure = True
667             print "Error parsing CacheInformation"
668             import traceback
669             traceback.print_exc()
670         self.fini()
672 class PortConnectorInfo(SmbiosBaseStructure):
673     smbios_structure_type = 8
675     def __init__(self, u, sm):
676         super(PortConnectorInfo, self).__init__(u, sm)
677         u = self.u
678         try:
679             self.add_field('internal_reference_designator', u.unpack_one("B"), self.fmtstr)
680             connector_types = {
681                 0x00: 'None',
682                 0x01: 'Centronics',
683                 0x02: 'Mini Centronics',
684                 0x03: 'Proprietary',
685                 0x04: 'DB-25 pin male',
686                 0x05: 'DB-25 pin female',
687                 0x06: 'DB-15 pin male',
688                 0x07: 'DB-15 pin female',
689                 0x08: 'DB-9 pin male',
690                 0x09: 'DB-9 pin female',
691                 0x0A: 'RJ-11',
692                 0x0B: 'RJ-45',
693                 0x0C: '50-pin MiniSCSI',
694                 0x0D: 'Mini-DIN',
695                 0x0E: 'Micro-DIN',
696                 0x0F: 'PS/2',
697                 0x10: 'Infrared',
698                 0x11: 'HP-HIL',
699                 0x12: 'Access Bus (USB)',
700                 0x13: 'SSA SCSI',
701                 0x14: 'Circular DIN-8 male',
702                 0x15: 'Circular DIN-8 female',
703                 0x16: 'On Board IDE',
704                 0x17: 'On Board Floppy',
705                 0x18: '9-pin Dual Inline (pin 10 cut)',
706                 0x19: '25-pin Dual Inline (pin 26 cut)',
707                 0x1A: '50-pin Dual Inline',
708                 0x1B: '68-pin Dual Inline',
709                 0x1C: 'On Board Sound Input from CD-ROM',
710                 0x1D: 'Mini-Centronics Type-14',
711                 0x1E: 'Mini-Centronics Type-26',
712                 0x1F: 'Mini-jack (headphones)',
713                 0x20: 'BNC',
714                 0x21: '1394',
715                 0x22: 'SAS/SATA Plug Receptacle',
716                 0xA0: 'PC-98',
717                 0xA1: 'PC-98Hireso',
718                 0xA2: 'PC-H98',
719                 0xA3: 'PC-98Note',
720                 0xA4: 'PC-98Full',
721                 0xFF: 'Other',
722             }
723             self.add_field('internal_connector_type', u.unpack_one("B"), unpack.format_table("{}", connector_types))
724             self.add_field('external_reference_designator', u.unpack_one("B"), self.fmtstr)
725             self.add_field('external_connector_type', u.unpack_one("B"), unpack.format_table("{}", connector_types))
726             port_types = {
727                 0x00: 'None',
728                 0x01: 'Parallel Port XT/AT Compatible',
729                 0x02: 'Parallel Port PS/2',
730                 0x03: 'Parallel Port ECP',
731                 0x04: 'Parallel Port EPP',
732                 0x05: 'Parallel Port ECP/EPP',
733                 0x06: 'Serial Port XT/AT Compatible',
734                 0x07: 'Serial Port 16450 Compatible',
735                 0x08: 'Serial Port 16550 Compatible',
736                 0x09: 'Serial Port 16550A Compatible',
737                 0x0A: 'SCSI Port',
738                 0x0B: 'MIDI Port',
739                 0x0C: 'Joy Stick Port',
740                 0x0D: 'Keyboard Port',
741                 0x0E: 'Mouse Port',
742                 0x0F: 'SSA SCSI',
743                 0x10: 'USB',
744                 0x11: 'FireWire (IEEE P1394)',
745                 0x12: 'PCMCIA Type I2',
746                 0x13: 'PCMCIA Type II',
747                 0x14: 'PCMCIA Type III',
748                 0x15: 'Cardbus',
749                 0x16: 'Access Bus Port',
750                 0x17: 'SCSI II',
751                 0x18: 'SCSI Wide',
752                 0x19: 'PC-98',
753                 0x1A: 'PC-98-Hireso',
754                 0x1B: 'PC-H98',
755                 0x1C: 'Video Port',
756                 0x1D: 'Audio Port',
757                 0x1E: 'Modem Port',
758                 0x1F: 'Network Port',
759                 0x20: 'SATA',
760                 0x21: 'SAS',
761                 0xA0: '8251 Compatible',
762                 0xA1: '8251 FIFO Compatible',
763                 0xFF: 'Other',
764             }
765             self.add_field('port_type', u.unpack_one("B"), unpack.format_table("{}", port_types))
766         except:
767             self.decodeFailure = True
768             print "Error parsing PortConnectorInfo"
769             import traceback
770             traceback.print_exc()
771         self.fini()
773 class SystemSlots(SmbiosBaseStructure):
774     smbios_structure_type = 9
776     def __init__(self, u, sm):
777         super(SystemSlots, self).__init__(u, sm)
778         u = self.u
779         try:
780             self.add_field('designation', u.unpack_one("B"), self.fmtstr)
781             _slot_types = {
782                 0x01: 'Other',
783                 0x02: 'Unknown',
784                 0x03: 'ISA',
785                 0x04: 'MCA',
786                 0x05: 'EISA',
787                 0x06: 'PCI',
788                 0x07: 'PC Card (PCMCIA)',
789                 0x08: 'VL-VESA',
790                 0x09: 'Proprietary',
791                 0x0A: 'Processor Card Slot',
792                 0x0B: 'Proprietary Memory Card Slot',
793                 0x0C: 'I/O Riser Card Slot',
794                 0x0D: 'NuBus',
795                 0x0E: 'PCI 66MHz Capable',
796                 0x0F: 'AGP',
797                 0x10: 'AGP 2X',
798                 0x11: 'AGP 4X',
799                 0x12: 'PCI-X',
800                 0x13: 'AGP 8X',
801                 0xA0: 'PC-98/C20',
802                 0xA1: 'PC-98/C24',
803                 0xA2: 'PC-98/E',
804                 0xA3: 'PC-98/Local Bus',
805                 0xA4: 'PC-98/Card',
806                 0xA5: 'PCI Express',
807                 0xA6: 'PCI Express x1',
808                 0xA7: 'PCI Express x2',
809                 0xA8: 'PCI Express x4',
810                 0xA9: 'PCI Express x8',
811                 0xAA: 'PCI Express x16',
812                 0xAB: 'PCI Express Gen 2',
813                 0xAC: 'PCI Express Gen 2 x1',
814                 0xAD: 'PCI Express Gen 2 x2',
815                 0xAE: 'PCI Express Gen 2 x4',
816                 0xAF: 'PCI Express Gen 2 x8',
817                 0xB0: 'PCI Express Gen 2 x16',
818                 0xB1: 'PCI Express Gen 3',
819                 0xB2: 'PCI Express Gen 3 x1',
820                 0xB3: 'PCI Express Gen 3 x2',
821                 0xB4: 'PCI Express Gen 3 x4',
822                 0xB5: 'PCI Express Gen 3 x8',
823                 0xB6: 'PCI Express Gen 3 x16',
824             }
825             self.add_field('slot_type', u.unpack_one("B"), unpack.format_table("{}", _slot_types))
826             _slot_data_bus_widths = {
827                 0x01: 'Other',
828                 0x02: 'Unknown',
829                 0x03: '8 bit',
830                 0x04: '16 bit',
831                 0x05: '32 bit',
832                 0x06: '64 bit',
833                 0x07: '128 bit',
834                 0x08: '1x or x1',
835                 0x09: '2x or x2',
836                 0x0A: '4x or x4',
837                 0x0B: '8x or x8',
838                 0x0C: '12x or x12',
839                 0x0D: '16x or x16',
840                 0x0E: '32x or x32',
841             }
842             self.add_field('slot_data_bus_width', u.unpack_one('B'), unpack.format_table("{}", _slot_data_bus_widths))
843             _current_usages = {
844                 0x01: 'Other',
845                 0x02: 'Unknown',
846                 0x03: 'Available',
847                 0x04: 'In use',
848             }
849             self.add_field('current_usage', u.unpack_one('B'), unpack.format_table("{}", _current_usages))
850             _slot_lengths = {
851                 0x01: 'Other',
852                 0x02: 'Unknown',
853                 0x03: 'Short Length',
854                 0x04: 'Long Length',
855             }
856             self.add_field('slot_length', u.unpack_one('B'), unpack.format_table("{}", _slot_lengths))
857             self.add_field('slot_id', u.unpack_one('<H'))
858             self.add_field('characteristics1', u.unpack_one('B'))
859             self.add_field('characteristics_unknown', bool(bitfields.getbits(self.characteristics1, 0)), "characteristics1[0]={}")
860             self.add_field('provides_5_0_volts', bool(bitfields.getbits(self.characteristics1, 1)), "characteristics1[1]={}")
861             self.add_field('provides_3_3_volts', bool(bitfields.getbits(self.characteristics1, 2)), "characteristics1[2]={}")
862             self.add_field('shared_slot', bool(bitfields.getbits(self.characteristics1, 3)), "characteristics1[3]={}")
863             self.add_field('supports_pc_card_16', bool(bitfields.getbits(self.characteristics1, 4)), "characteristics1[4]={}")
864             self.add_field('supports_cardbus', bool(bitfields.getbits(self.characteristics1, 5)), "characteristics1[5]={}")
865             self.add_field('supports_zoom_video', bool(bitfields.getbits(self.characteristics1, 6)), "characteristics1[6]={}")
866             self.add_field('supports_modem_ring_resume', bool(bitfields.getbits(self.characteristics1, 7)), "characteristics1[7]={}")
867             if self.length > 0x0C:
868                 self.add_field('characteristics2', u.unpack_one('B'))
869                 self.add_field('supports_PME', bool(bitfields.getbits(self.characteristics2, 0)), "characteristics2[0]={}")
870                 self.add_field('supports_hot_plug', bool(bitfields.getbits(self.characteristics2, 1)), "characteristics2[1]={}")
871                 self.add_field('supports_smbus', bool(bitfields.getbits(self.characteristics2, 2)), "characteristics2[2]={}")
872             if self.length > 0x0D:
873                 self.add_field('segment_group_number', u.unpack_one('<H'))
874                 self.add_field('bus_number', u.unpack_one('B'))
875                 self.add_field('device_function_number', u.unpack_one('B'))
876                 self.add_field('device_number', bitfields.getbits(self.device_function_number, 7, 3), "device_function_number[7:3]={}")
877                 self.add_field('function_number', bitfields.getbits(self.device_function_number, 2, 0), "device_function_number[2:0]={}")
878         except:
879             self.decodeFailure = True
880             print "Error parsing SystemSlots"
881             import traceback
882             traceback.print_exc()
883         self.fini()
885 class OnBoardDevicesInformation(SmbiosBaseStructure):
886     smbios_structure_type = 10
888     def __init__(self, u, sm):
889         super(OnBoardDevicesInformation, self).__init__(u, sm)
890         u = self.u
891         try:
892             self.add_field('device_type', u.unpack_one("B"))
893             self.add_field('device_enabled', bool(bitfields.getbits(self.device_type, 7)), "device_type[7]={}")
894             _device_types = {
895                 0x01: 'Other',
896                 0x02: 'Unknown',
897                 0x03: 'Video',
898                 0x04: 'SCSI Controller',
899                 0x05: 'Ethernet',
900                 0x06: 'Token Ring',
901                 0x07: 'Sound',
902                 0x08: 'PATA Controller',
903                 0x09: 'SATA Controller',
904                 0x0A: 'SAS Controller'
905             }
906             self.add_field('type_of_device', bitfields.getbits(self.device_type, 6, 0), unpack.format_table("device_type[6:0]={}", _device_types))
907             self.add_field('description_string', u.unpack_one("B"), self.fmtstr)
908         except:
909             self.decodeFailure = True
910             print "Error parsing OnBoardDevicesInformation"
911             import traceback
912             traceback.print_exc()
913         self.fini()
915 class OEMStrings(SmbiosBaseStructure):
916     smbios_structure_type = 11
918     def __init__(self, u, sm):
919         super(OEMStrings, self).__init__(u, sm)
920         u = self.u
921         try:
922             self.add_field('count', u.unpack_one("B"))
923         except:
924             self.decodeFailure = True
925             print "Error parsing OEMStrings"
926             import traceback
927             traceback.print_exc()
928         self.fini()
930 class SystemConfigOptions(SmbiosBaseStructure):
931     smbios_structure_type = 12
933     def __init__(self, u, sm):
934         super(SystemConfigOptions, self).__init__(u, sm)
935         u = self.u
936         try:
937             self.add_field('count', u.unpack_one("B"))
938         except:
939             self.decodeFailure = True
940             print "Error parsing SystemConfigOptions"
941             import traceback
942             traceback.print_exc()
943         self.fini()
945 class BIOSLanguageInformation(SmbiosBaseStructure):
946     smbios_structure_type = 13
948     def __init__(self, u, sm):
949         super(BIOSLanguageInformation, self).__init__(u, sm)
950         u = self.u
951         try:
952             self.add_field('installable_languages', u.unpack_one("B"))
953             if self.length > 0x05:
954                 self.add_field('flags', u.unpack_one('B'))
955                 self.add_field('abbreviated_format', bool(bitfields.getbits(self.flags, 0)), "flags[0]={}")
956             if self.length > 0x6:
957                 u.skip(15)
958                 self.add_field('current_language', u.unpack_one('B'), self.fmtstr)
959         except:
960             self.decodeFailure = True
961             print "Error parsing BIOSLanguageInformation"
962             import traceback
963             traceback.print_exc()
964         self.fini()
966 class GroupAssociations(SmbiosBaseStructure):
967     smbios_structure_type = 14
969     def __init__(self, u, sm):
970         super(GroupAssociations, self).__init__(u, sm)
971         u = self.u
972         try:
973             self.add_field('group_name', u.unpack_one("B"), self.fmtstr)
974             self.add_field('item_type', u.unpack_one('B'))
975             self.add_field('item_handle', u.unpack_one('<H'))
976         except:
977             self.decodeFailure = True
978             print "Error parsing GroupAssociations"
979             import traceback
980             traceback.print_exc()
981         self.fini()
983 class SystemEventLog(SmbiosBaseStructure):
984     smbios_structure_type = 15
986     def __init__(self, u, sm):
987         super(SystemEventLog, self).__init__(u, sm)
988         u = self.u
989         try:
990             self.add_field('log_area_length', u.unpack_one("<H"))
991             self.add_field('log_header_start_offset', u.unpack_one('<H'))
992             self.add_field('log_data_start_offset', u.unpack_one('<H'))
993             _access_method = {
994                 0x00: 'Indexed I/O: 1 8-bit index port, 1 8-bit data port',
995                 0x01: 'Indexed I/O: 2 8-bit index ports, 1 8-bit data port',
996                 0x02: 'Indexed I/O: 1 16-bit index port, 1 8-bit data port',
997                 0x03: 'Memory-mapped physical 32-bit address',
998                 0x04: 'Available through General-Purpose NonVolatile Data functions',
999                 xrange(0x05, 0x07F): 'Available for future assignment',
1000                 xrange(0x80, 0xFF): 'BIOS Vendor/OEM-specific'
1001                 }
1002             self.add_field('access_method', u.unpack_one('B'), unpack.format_table("{}", _access_method))
1003             self.add_field('log_status', u.unpack_one('B'))
1004             self.add_field('log_area_full', bool(bitfields.getbits(self.log_status, 1)), "log_status[1]={}")
1005             self.add_field('log_area_valid', bool(bitfields.getbits(self.log_status, 0)), "log_status[0]={}")
1006             self.add_field('log_change_token', u.unpack_one('<I'))
1007             self.add_field('access_method_address', u.unpack_one('<I'))
1008             if self.length > 0x14:
1009                 _log_header_formats = {
1010                     0: 'No header',
1011                     1: 'Type 1 log header',
1012                     xrange(2, 0x7f): 'Available for future assignment',
1013                     xrange(0x80, 0xff): 'BIOS vendor or OEM-specific format'
1014                     }
1015                 self.add_field('log_header_format', u.unpack_one("B"), unpack.format_table("{}", _log_header_formats))
1016             if self.length > 0x15:
1017                 self.add_field('num_supported_log_type_descriptors', u.unpack_one('B'))
1018             if self.length > 0x16:
1019                 self.add_field('length_log_type_descriptor', u.unpack_one('B'))
1020             if self.length != (0x17 + (self.num_supported_log_type_descriptors * self.length_log_type_descriptor)):
1021                 print "Error: structure length ({}) != 0x17 + (num_supported_log_type_descriptors ({}) * length_log_type_descriptor({}))".format(self.length, self.num_supported_log_type_descriptors, self.length_log_type_descriptor)
1022                 print "structure length = {}".format(self.length)
1023                 print "num_supported_log_type_descriptors = {}".format(self.num_supported_log_type_descriptors)
1024                 print "length_log_type_descriptor = {}".format(self.length_log_type_descriptor)
1025                 self.decodeFailure = True
1026             self.add_field('descriptors', tuple(EventLogDescriptor.unpack(u) for i in range(self.num_supported_log_type_descriptors)), unpack.format_each("\n{!r}"))
1027         except:
1028             self.decodeFailure = True
1029             print "Error parsing SystemEventLog"
1030             import traceback
1031             traceback.print_exc()
1032         self.fini()
1034 class EventLogDescriptor(unpack.Struct):
1035     @staticmethod
1036     def _unpack(u):
1037         _event_log_type_descriptors = {
1038             0x00: 'Reserved',
1039             0x01: 'Single-bit ECC memory error',
1040             0x02: 'Multi-bit ECC memory error',
1041             0x03: 'Parity memory error',
1042             0x04: 'Bus time-out',
1043             0x05: 'I/O Channel Check',
1044             0x06: 'Software NMI',
1045             0x07: 'POST Memory Resize',
1046             0x08: 'POST Error',
1047             0x09: 'PCI Parity Error',
1048             0x0A: 'PCI System Error',
1049             0x0B: 'CPU Failure',
1050             0x0C: 'EISA FailSafe Timer time-out',
1051             0x0D: 'Correctable memory log disabled',
1052             0x0E: 'Logging disabled for a specific Event Type - too many errors of the same type received in a short amount of time',
1053             0x0F: 'Reserved',
1054             0x10: 'System Limit Exceeded',
1055             0x11: 'Asynchronous hardware timer expired and issued a system reset',
1056             0x12: 'System configuration information',
1057             0x13: 'Hard-disk information',
1058             0x14: 'System reconfigured',
1059             0x15: 'Uncorrectable CPU-complex error',
1060             0x16: 'Log Area Reset/Cleared',
1061             0x17: 'System boot',
1062             xrange(0x18, 0x7F): 'Unused, available for assignment',
1063             xrange(0x80, 0xFE): 'Availalbe for system- and OEM-specific assignments',
1064             0xFF: 'End of log'
1065         }
1066         yield 'log_type', u.unpack_one('B'), unpack.format_table("{}", _event_log_type_descriptors)
1067         _event_log_format = {
1068             0x00: 'None',
1069             0x01: 'Handle',
1070             0x02: 'Multiple-Event',
1071             0x03: 'Multiple-Event Handle',
1072             0x04: 'POST Results Bitmap',
1073             0x05: 'System Management Type',
1074             0x06: 'Multiple-Event System Management Type',
1075             xrange(0x80, 0xFF): 'OEM assigned'
1076         }
1077         yield 'variable_data_format_type', u.unpack_one('B'), unpack.format_table("{}", _event_log_format)
1079 class PhysicalMemoryArray(SmbiosBaseStructure):
1080     smbios_structure_type = 16
1082     def __init__(self, u, sm):
1083         super(PhysicalMemoryArray, self).__init__(u, sm)
1084         u = self.u
1085         try:
1086             if self.length > 0x4:
1087                 _location_field = {
1088                     0x01: "Other",
1089                     0x02: "Unknown",
1090                     0x03: "System board or motherboard",
1091                     0x04: "ISA add-on card",
1092                     0x05: "EISA add-on card",
1093                     0x06: "PCI add-on card",
1094                     0x07: "MCA add-on card",
1095                     0x08: "PCMCIA add-on card",
1096                     0x09: "Proprietary add-on card",
1097                     0x0A: "NuBus",
1098                     0xA0: "PC-98/C20 add-on card",
1099                     0xA1: "PC-98/C24 add-on card",
1100                     0xA2: "PC-98/E add-on card",
1101                     0xA3: "PC-98/Local bus add-on card"
1102                     }
1103                 self.add_field('location', u.unpack_one("B"), unpack.format_table("{}", _location_field))
1104             if self.length > 0x05:
1105                 _use = {
1106                     0x01: "Other",
1107                     0x02: "Unknown",
1108                     0x03: "System memory",
1109                     0x04: "Video memory",
1110                     0x05: "Flash memory",
1111                     0x06: "Non-volatile RAM",
1112                     0x07: "Cache memory"
1113                     }
1114                 self.add_field('use', u.unpack_one('B'), unpack.format_table("{}", _use))
1115             if self.length > 0x06:
1116                 _error_correction = {
1117                     0x01: "Other",
1118                     0x02: "Unknown",
1119                     0x03: "None",
1120                     0x04: "Parity",
1121                     0x05: "Single-bit ECC",
1122                     0x06: "Multi-bit ECC",
1123                     0x07: "CRC"
1124                     }
1125                 self.add_field('memory_error_correction', u.unpack_one('B'), unpack.format_table("{}", _error_correction))
1126             if self.length > 0x07:
1127                 self.add_field('maximum_capacity', u.unpack_one('<I'))
1128             if self.length > 0x0B:
1129                 self.add_field('memory_error_information_handle', u.unpack_one('<H'))
1130             if self.length > 0x0D:
1131                 self.add_field('num_memory_devices', u.unpack_one('<H'))
1132             if self.length > 0x0F:
1133                 self.add_field('extended_maximum_capacity', u.unpack_one('<Q'))
1134         except:
1135             self.decodeFailure = True
1136             print "Error parsing PhysicalMemoryArray"
1137             import traceback
1138             traceback.print_exc()
1139         self.fini()
1141 class MemoryDevice(SmbiosBaseStructure):
1142     smbios_structure_type = 17
1144     def __init__(self, u, sm):
1145         super(MemoryDevice, self).__init__(u, sm)
1146         u = self.u
1147         try:
1148             if self.length > 0x4:
1149                 self.add_field('physical_memory_array_handle', u.unpack_one("<H"))
1150             if self.length > 0x6:
1151                 self.add_field('memory_error_information_handle', u.unpack_one("<H"))
1152             if self.length > 0x8:
1153                 self.add_field('total_width', u.unpack_one("<H"))
1154             if self.length > 0xA:
1155                 self.add_field('data_width', u.unpack_one("<H"))
1156             if self.length > 0xC:
1157                 self.add_field('size', u.unpack_one("<H"))
1158             if self.length > 0xE:
1159                 _form_factors = {
1160                     0x01: 'Other',
1161                     0x02: 'Unknown',
1162                     0x03: 'SIMM',
1163                     0x04: 'SIP',
1164                     0x05: 'Chip',
1165                     0x06: 'DIP',
1166                     0x07: 'ZIP',
1167                     0x08: 'Proprietary Card',
1168                     0x09: 'DIMM',
1169                     0x0A: 'TSOP',
1170                     0x0B: 'Row of chips',
1171                     0x0C: 'RIMM',
1172                     0x0D: 'SODIMM',
1173                     0x0E: 'SRIMM',
1174                     0x0F: 'FB-DIMM'
1175                     }
1176                 self.add_field('form_factor', u.unpack_one("B"), unpack.format_table("{}", _form_factors))
1177             if self.length > 0xF:
1178                 self.add_field('device_set', u.unpack_one("B"))
1179             if self.length > 0x10:
1180                 self.add_field('device_locator', u.unpack_one("B"), self.fmtstr)
1181             if self.length > 0x11:
1182                 self.add_field('bank_locator', u.unpack_one("B"), self.fmtstr)
1183             if self.length > 0x12:
1184                 _memory_types = {
1185                     0x01: 'Other',
1186                     0x02: 'Unknown',
1187                     0x03: 'DRAM',
1188                     0x04: 'EDRAM',
1189                     0x05: 'VRAM',
1190                     0x06: 'SRAM',
1191                     0x07: 'RAM',
1192                     0x08: 'ROM',
1193                     0x09: 'FLASH',
1194                     0x0A: 'EEPROM',
1195                     0x0B: 'FEPROM',
1196                     0x0C: 'EPROM',
1197                     0x0D: 'CDRAM',
1198                     0x0E: '3DRAM',
1199                     0x0F: 'SDRAM',
1200                     0x10: 'SGRAM',
1201                     0x11: 'RDRAM',
1202                     0x12: 'DDR',
1203                     0x13: 'DDR2',
1204                     0x14: 'DDR2 FB-DIMM',
1205                     xrange(0x15, 0x17): 'Reserved',
1206                     0x18: 'DDR3',
1207                     0x19: 'FBD2'
1208                     }
1209                 self.add_field('memory_type', u.unpack_one("B"), unpack.format_table("{}", _memory_types))
1210             if self.length > 0x13:
1211                 self.add_field('type_detail', u.unpack_one('<H'))
1212             if self.length > 0x15:
1213                 self.add_field('speed', u.unpack_one("<H"))
1214             if self.length > 0x17:
1215                 self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
1216             if self.length > 0x18:
1217                 self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
1218             if self.length > 0x19:
1219                 self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
1220             if self.length > 0x1A:
1221                 self.add_field('part_number', u.unpack_one("B"), self.fmtstr)
1222             if self.length > 0x1B:
1223                 self.add_field('attributes', u.unpack_one("B"))
1224                 self.add_field('rank', bitfields.getbits(self.attributes, 3, 0), "attributes[3:0]={}")
1225             if self.length > 0x1C:
1226                 if self.size == 0x7FFF:
1227                     self.add_field('extended_size', u.unpack_one('<I'))
1228                     self.add_field('mem_size', bitfields.getbits(self.type_detail, 30, 0), "type_detail[30:0]={}")
1229                 else:
1230                     u.skip(4)
1231             if self.length > 0x20:
1232                 self.add_field('configured_memory_clock_speed', u.unpack_one("<H"))
1233             if self.length > 0x22:
1234                 self.add_field('minimum_voltage', u.unpack_one("<H"))
1235             if self.length > 0x24:
1236                 self.add_field('maximum_voltage', u.unpack_one("<H"))
1237             if self.length > 0x26:
1238                 self.add_field('configured_voltage', u.unpack_one("<H"))
1239         except:
1240             self.decodeFailure = True
1241             print "Error parsing MemoryDevice"
1242             import traceback
1243             traceback.print_exc()
1244         self.fini()
1246 class MemoryErrorInfo32Bit(SmbiosBaseStructure):
1247     smbios_structure_type = 18
1249     def __init__(self, u, sm):
1250         super(MemoryErrorInfo32Bit, self).__init__(u, sm)
1251         u = self.u
1252         try:
1253             if self.length > 0x4:
1254                 _error_types = {
1255                     0x01: 'Other',
1256                     0x02: 'Unknown',
1257                     0x03: 'OK',
1258                     0x04: 'Bad read',
1259                     0x05: 'Parity error',
1260                     0x06: 'Single-bit error',
1261                     0x07: 'Double-bit error',
1262                     0x08: 'Multi-bit error',
1263                     0x09: 'Nibble error',
1264                     0x0A: 'Checksum error',
1265                     0x0B: 'CRC error',
1266                     0x0C: 'Corrected single-bit error',
1267                     0x0D: 'Corrected error',
1268                     0x0E: 'Uncorrectable error'
1269                     }
1270                 self.add_field('error_type', u.unpack_one("B"), unpack.format_table("{}", _error_types))
1271             if self.length > 0x5:
1272                  _error_granularity_field = {
1273                     0x01: 'Other',
1274                     0x02: 'Unknown',
1275                     0x03: 'Device level',
1276                     0x04: 'Memory partition level'
1277                     }
1278                  self.add_field('error_granularity', u.unpack_one("B"), unpack.format_table("{}", _error_granularity_field))
1279             if self.length > 0x6:
1280                 _error_operation_field = {
1281                     0x01: 'Other',
1282                     0x02: 'Unknown',
1283                     0x03: 'Read',
1284                     0x04: 'Write',
1285                     0x05: 'Partial write'
1286                     }
1287                 self.add_field('error_operation', u.unpack_one("B"), unpack.format_table("{}", _error_operation_field))
1288             if self.length > 0x7:
1289                 self.add_field('vendor_syndrome', u.unpack_one("<I"))
1290             if self.length > 0xB:
1291                 self.add_field('memory_array_error_address', u.unpack_one("<I"))
1292             if self.length > 0xF:
1293                 self.add_field('device_error_address', u.unpack_one("<I"))
1294             if self.length > 0x13:
1295                 self.add_field('error_resolution', u.unpack_one("<I"))
1296         except:
1297             self.decodeFailure = True
1298             print "Error parsing MemoryErrorInfo32Bit"
1299             import traceback
1300             traceback.print_exc()
1301         self.fini()
1303 class MemoryArrayMappedAddress(SmbiosBaseStructure):
1304     smbios_structure_type = 19
1306     def __init__(self, u, sm):
1307         super(MemoryArrayMappedAddress, self).__init__(u, sm)
1308         u = self.u
1309         try:
1310             if self.length > 0x4:
1311                 self.add_field('starting_address', u.unpack_one("<I"))
1312                 # if FFFF FFFF: address stored in Extended Starting Address
1313             if self.length > 0x8:
1314                 self.add_field('ending_address', u.unpack_one("<I"))
1315             if self.length > 0xC:
1316                 self.add_field('memory_array_handle', u.unpack_one("<H"))
1317             if self.length > 0xE:
1318                 self.add_field('partition_width', u.unpack_one("B"))
1319             if self.length > 0xF:
1320                 # valid if starting_address = FFFF FFFF
1321                 if self.starting_address == 0xFFFFFFFF:
1322                     self.add_field('extended_starting_address', u.unpack_one("<Q"))
1323                     if self.length > 0x17:
1324                         self.add_field('extended_ending_address', u.unpack_one("<Q"))
1325                 else:
1326                     u.skip(16)
1328         except:
1329             self.decodeFailure = True
1330             print "Error parsing MemoryArrayMappedAddress"
1331             import traceback
1332             traceback.print_exc()
1333         self.fini()
1335 class MemoryDeviceMappedAddress(SmbiosBaseStructure):
1336     smbios_structure_type = 20
1338     def __init__(self, u, sm):
1339         super(MemoryDeviceMappedAddress, self).__init__(u, sm)
1340         u = self.u
1341         try:
1342             if self.length > 0x4:
1343                 self.add_field('starting_address', u.unpack_one("<I"))
1344                 # if FFFF FFFF: address stored in Extended Starting Address
1345             if self.length > 0x8:
1346                 self.add_field('ending_address', u.unpack_one("<I"))
1347             if self.length > 0xC:
1348                 self.add_field('memory_device_handle', u.unpack_one("<H"))
1349             if self.length > 0xE:
1350                 self.add_field('memory_array_mapped_address_handle', u.unpack_one("<H"))
1351             if self.length > 0x10:
1352                 self.add_field('partition_row_position', u.unpack_one("B"))
1353             if self.length > 0x11:
1354                 self.add_field('interleave_position', u.unpack_one("B"))
1355             if self.length > 0x12:
1356                 self.add_field('interleave_data_depth', u.unpack_one("B"))
1357             if self.length > 0x13:
1358                 # valid if starting_address = FFFF FFFF
1359                 if self.starting_address == 0xFFFFFFFF:
1360                     self.add_field('extended_starting_address', u.unpack_one("<Q"))
1361                     if self.length > 0x1B:
1362                         self.add_field('extended_ending_address', u.unpack_one("<Q"))
1363                 else:
1364                     u.skip(16)
1365         except:
1366             self.decodeFailure = True
1367             print "Error parsing MemoryDeviceMappedAddress"
1368             import traceback
1369             traceback.print_exc()
1370         self.fini()
1372 class BuiltInPointingDevice(SmbiosBaseStructure):
1373     smbios_structure_type = 21
1375     def __init__(self, u, sm):
1376         super(BuiltInPointingDevice, self).__init__(u, sm)
1377         u = self.u
1378         try:
1379             if self.length > 0x4:
1380                 _pointing_device_types = {
1381                     0x01: 'Other',
1382                     0x02: 'Unknown',
1383                     0x03: 'Mouse',
1384                     0x04: 'Track Ball',
1385                     0x05: 'Track Point',
1386                     0x06: 'Glide Point',
1387                     0x07: 'Touch Pad',
1388                     0x08: 'Touch Screen',
1389                     0x09: 'Optical Sensor'
1390                     }
1391                 self.add_field('pointing_device_type', u.unpack_one("B"), unpack.format_table("{}", _pointing_device_types))
1392             if self.length > 0x5:
1393                 _interfaces = {
1394                     0x01: 'Other',
1395                     0x02: 'Unknown',
1396                     0x03: 'Serial',
1397                     0x04: 'PS/2',
1398                     0x05: 'Infared',
1399                     0x06: 'HP-HIL',
1400                     0x07: 'Bus mouse',
1401                     0x08: 'ADB (Apple Desktop Bus)',
1402                     0x09: 'Bus mouse DB-9',
1403                     0x0A: 'Bus mouse micro-DIN',
1404                     0x0B: 'USB'
1405                     }
1406                 self.add_field('interface', u.unpack_one("B"), unpack.format_table("{}", _interfaces))
1407             if self.length > 0x6:
1408                 self.add_field('num_buttons', u.unpack_one("B"))
1409         except:
1410             self.decodeFailure = True
1411             print "Error parsing BuiltInPointingDevice"
1412             import traceback
1413             traceback.print_exc()
1414         self.fini()
1416 class PortableBattery(SmbiosBaseStructure):
1417     smbios_structure_type = 22
1419     def __init__(self, u, sm):
1420         super(PortableBattery, self).__init__(u, sm)
1421         u = self.u
1422         try:
1423             if self.length > 0x4:
1424                 self.add_field('location', u.unpack_one("B"), self.fmtstr)
1425             if self.length > 0x5:
1426                 self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
1427             if self.length > 0x6:
1428                 self.add_field('manufacturer_date', u.unpack_one("B"), self.fmtstr)
1429             if self.length > 0x7:
1430                 self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
1431             if self.length > 0x8:
1432                 self.add_field('device_name', u.unpack_one("B"), self.fmtstr)
1433             if self.length > 0x9:
1434                 _device_chemistry = {
1435                     0x01: 'Other',
1436                     0x02: 'Unknown',
1437                     0x03: 'Lead Acid',
1438                     0x04: 'Nickel Cadmium',
1439                     0x05: 'Nickel metal hydride',
1440                     0x06: 'Lithium-ion',
1441                     0x07: 'Zinc air',
1442                     0x08: 'Lithium Polymer'
1443                     }
1444                 self.add_field('device_chemistry', u.unpack_one("B"), unpack.format_table("{}", _device_chemistry))
1445             if self.length > 0xA:
1446                 self.add_field('design_capacity', u.unpack_one("<H"))
1447             if self.length > 0xC:
1448                 self.add_field('design_voltage', u.unpack_one("<H"))
1449             if self.length > 0xE:
1450                 self.add_field('sbds_version_number', u.unpack_one("B"), self.fmtstr)
1451             if self.length > 0xF:
1452                 self.add_field('max_error_battery_data', u.unpack_one("B"), self.fmtstr)
1453             if self.length > 0x10:
1454                 if self.serial_number == 0:
1455                     self.add_field('sbds_serial_number', u.unpack_one("<H"))
1456                 else:
1457                     u.skip(2)
1458             if self.length > 0x12:
1459                 if self.manufacturer_date == 0:
1460                     self.add_field('sbds_manufacture_date', u.unpack_one("<H"))
1461                     self.add_field('year_biased_by_1980', bitfields.getbits(self.sbds_manufacture_date, 15, 9), "sbds_manufacture_date[15:9]={}")
1462                     self.add_field('month', bitfields.getbits(self.sbds_manufacture_date, 8, 5), "sbds_manufacture_date[8:5]={}")
1463                     self.add_field('date', bitfields.getbits(self.sbds_manufacture_date, 4, 0), "sbds_manufacture_date[4:0]={}")
1464                 else:
1465                     u.skip(2)
1466             if self.length > 0x14:
1467                 if self.device_chemistry == 0x02:
1468                     self.add_field('sbds_device_chemistry', u.unpack_one("B"), self.fmtstr)
1469                 else:
1470                     u.skip(1)
1471             if self.length > 0x15:
1472                 self.add_field('design_capacity_multiplier', u.unpack_one("B"))
1473             if self.length > 0x16:
1474                 self.add_field('oem_specific', u.unpack_one("<I"))
1475         except:
1476             self.decodeFailure = True
1477             print "Error parsing PortableBattery"
1478             import traceback
1479             traceback.print_exc()
1480         self.fini()
1482 class SystemReset(SmbiosBaseStructure):
1483     smbios_structure_type = 23
1485     def __init__(self, u, sm):
1486         super(SystemReset, self).__init__(u, sm)
1487         u = self.u
1488         try:
1489             if self.length > 0x4:
1490                 self.add_field('capabilities', u.unpack_one("B"))
1491                 self.add_field('contains_watchdog_timer', bool(bitfields.getbits(self.capabilities, 5)), "capabilities[5]={}")
1492                 _boot_option = {
1493                     0b00: 'Reserved, do not use',
1494                     0b01: 'Operating System',
1495                     0b10: 'System utilities',
1496                     0b11: 'Do not reboot'
1497                     }
1498                 self.add_field('boot_option_on_limit', bitfields.getbits(self.capabilities, 4, 3), unpack.format_table("capabilities[4:3]={}", _boot_option))
1499                 self.add_field('boot_option_after_watchdog_reset', bitfields.getbits(self.capabilities, 2, 1), unpack.format_table("capabilities[2:1]={}", _boot_option))
1500                 self.add_field('system_reset_enabled_by_user', bool(bitfields.getbits(self.capabilities, 0)), "capabilities[0]={}")
1501             if self.length > 0x5:
1502                 self.add_field('reset_count', u.unpack_one("<H"))
1503             if self.length > 0x5:
1504                 self.add_field('reset_limit', u.unpack_one("<H"))
1505             if self.length > 0x9:
1506                 self.add_field('timer_interval', u.unpack_one("<H"))
1507             if self.length > 0xB:
1508                 self.add_field('timeout', u.unpack_one("<H"))
1509         except:
1510             self.decodeFailure = True
1511             print "Error parsing SystemReset"
1512             import traceback
1513             traceback.print_exc()
1514         self.fini()
1516 class HardwareSecurity(SmbiosBaseStructure):
1517     smbios_structure_type = 24
1519     def __init__(self, u, sm):
1520         super(HardwareSecurity, self).__init__(u, sm)
1521         u = self.u
1522         try:
1523             if self.length > 0x4:
1524                 self.add_field('hardware_security_settings', u.unpack_one("B"))
1525                 _status = {
1526                     0x00: 'Disabled',
1527                     0x01: 'Enabled',
1528                     0x02: 'Not Implemented',
1529                     0x03: 'Unknown'
1530                     }
1531                 self.add_field('power_on_password_status', bitfields.getbits(self.hardware_security_settings, 7, 6), unpack.format_table("hardware_security_settings[7:6]={}", _status))
1532                 self.add_field('keyboard_password_status', bitfields.getbits(self.hardware_security_settings, 5, 4), unpack.format_table("hardware_security_settings[5:4]={}", _status))
1533                 self.add_field('admin_password_status', bitfields.getbits(self.hardware_security_settings, 3, 2), unpack.format_table("hardware_security_settings0[3:2]={}", _status))
1534                 self.add_field('front_panel_reset_status', bitfields.getbits(self.hardware_security_settings, 1, 0), unpack.format_table("hardware_security_settings[1:0]={}", _status))
1535         except:
1536             self.decodeFailure = True
1537             print "Error parsing HardwareSecurity"
1538             import traceback
1539             traceback.print_exc()
1540         self.fini()
1542 class SystemPowerControls(SmbiosBaseStructure):
1543     smbios_structure_type = 25
1545     def __init__(self, u, sm):
1546         super(SystemPowerControls, self).__init__(u, sm)
1547         u = self.u
1548         try:
1549             if self.length > 0x4:
1550                 self.add_field('next_scheduled_poweron_month', u.unpack_one("B"))
1551                 self.add_field('next_scheduled_poweron_day_of_month', u.unpack_one("B"))
1552                 self.add_field('next_scheduled_poweron_hour', u.unpack_one("B"))
1553                 self.add_field('next_scheduled_poweron_minute', u.unpack_one("B"))
1554                 self.add_field('next_scheduled_poweron_second', u.unpack_one("B"))
1555         except:
1556             self.decodeFailure = True
1557             print "Error parsing SystemPowerControls"
1558             import traceback
1559             traceback.print_exc()
1560         self.fini()
1562 class VoltageProbe(SmbiosBaseStructure):
1563     smbios_structure_type = 26
1565     def __init__(self, u, sm):
1566         super(VoltageProbe, self).__init__(u, sm)
1567         u = self.u
1568         try:
1569             if self.length > 0x4:
1570                 self.add_field('description', u.unpack_one("B"), self.fmtstr)
1571             if self.length > 0x5:
1572                 self.add_field('location_and_status', u.unpack_one("B"))
1573                 _status = {
1574                     0b001: 'Other',
1575                     0b010: 'Unknown',
1576                     0b011: 'OK',
1577                     0b100: 'Non-critical',
1578                     0b101: 'Critical',
1579                     0b110: 'Non-recoverable'
1580                     }
1581                 _location = {
1582                     0b00001: 'Other',
1583                     0b00010: 'Unknown',
1584                     0b00011: 'Processor',
1585                     0b00100: 'Disk',
1586                     0b00101: 'Peripheral Bay',
1587                     0b00110: 'System Management Module',
1588                     0b00111: 'Motherboard',
1589                     0b01000: 'Memory Module',
1590                     0b01001: 'Processor Module',
1591                     0b01010: 'Power Unit',
1592                     0b01011: 'Add-in Card'
1593                     }
1594                 self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status))
1595                 self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location))
1596             if self.length > 0x6:
1597                 self.add_field('max_value', u.unpack_one("<H"))
1598             if self.length > 0x8:
1599                 self.add_field('min_value', u.unpack_one("<H"))
1600             if self.length > 0xA:
1601                 self.add_field('resolution', u.unpack_one("<H"))
1602             if self.length > 0xC:
1603                 self.add_field('tolerance', u.unpack_one("<H"))
1604             if self.length > 0xE:
1605                 self.add_field('accuracy', u.unpack_one("<H"))
1606             if self.length > 0x10:
1607                 self.add_field('oem_defined', u.unpack_one("<I"))
1608             if self.length > 0x14:
1609                 self.add_field('nominal_value', u.unpack_one("<H"))
1610         except:
1611             self.decodeFailure = True
1612             print "Error parsing VoltageProbe"
1613             import traceback
1614             traceback.print_exc()
1615         self.fini()
1617 class CoolingDevice(SmbiosBaseStructure):
1618     smbios_structure_type = 27
1620     def __init__(self, u, sm):
1621         super(CoolingDevice, self).__init__(u, sm)
1622         u = self.u
1623         try:
1624             if self.length > 0x4:
1625                 self.add_field('temperature_probe_handle', u.unpack_one("<H"))
1626             if self.length > 0x6:
1627                 self.add_field('device_type_and_status', u.unpack_one("B"))
1628                 _status = {
1629                     0b001: 'Other',
1630                     0b010: 'Unknown',
1631                     0b011: 'OK',
1632                     0b100: 'Non-critical',
1633                     0b101: 'Critical',
1634                     0b110: 'Non-recoverable'
1635                     }
1636                 _type = {
1637                     0b00001: 'Other',
1638                     0b00010: 'Unknown',
1639                     0b00011: 'Fan',
1640                     0b00100: 'Centrifugal Blower',
1641                     0b00101: 'Chip Fan',
1642                     0b00110: 'Cabinet Fan',
1643                     0b00111: 'Power Supply Fan',
1644                     0b01000: 'Heat Pipe',
1645                     0b01001: 'Integrated Refrigeration',
1646                     0b10000: 'Active Cooling',
1647                     0b10001: 'Passive Cooling'
1648                     }
1649                 self.add_field('status', bitfields.getbits(self.device_type_and_status, 7, 5), unpack.format_table("device_type_and_status[7:5]={}", _status))
1650                 self.add_field('device_type', bitfields.getbits(self.device_type_and_status, 4, 0), unpack.format_table("device_type_and_status[4:0]={}", _type))
1651             if self.length > 0x7:
1652                 self.add_field('cooling_unit_group', u.unpack_one("B"))
1653             if self.length > 0x8:
1654                 self.add_field('OEM_defined', u.unpack_one("<I"))
1655             if self.length > 0xC:
1656                 self.add_field('nominal_speed', u.unpack_one("<H"))
1657             if self.length > 0xE:
1658                self.add_field('description', u.unpack_one("B"), self.fmtstr)
1659         except:
1660             self.decodeFailure = True
1661             print "Error parsing CoolingDevice"
1662             import traceback
1663             traceback.print_exc()
1664         self.fini()
1666 class TemperatureProbe(SmbiosBaseStructure):
1667     smbios_structure_type = 28
1669     def __init__(self, u, sm):
1670         super(TemperatureProbe, self).__init__(u, sm)
1671         u = self.u
1672         try:
1673             if self.length > 0x4:
1674                 self.add_field('description', u.unpack_one("B"), self.fmtstr)
1675             if self.length > 0x5:
1676                 self.add_field('location_and_status', u.unpack_one("B"))
1677                 _status = {
1678                     0b001: 'Other',
1679                     0b010: 'Unknown',
1680                     0b011: 'OK',
1681                     0b100: 'Non-critical',
1682                     0b101: 'Critical',
1683                     0b110: 'Non-recoverable'
1684                     }
1685                 _location = {
1686                     0b00001: 'Other',
1687                     0b00010: 'Unknown',
1688                     0b00011: 'Processor',
1689                     0b00100: 'Disk',
1690                     0b00101: 'Peripheral Bay',
1691                     0b00110: 'System Management Module',
1692                     0b00111: 'Motherboard',
1693                     0b01000: 'Memory Module',
1694                     0b01001: 'Processor Module',
1695                     0b01010: 'Power Unit',
1696                     0b01011: 'Add-in Card',
1697                     0b01100: 'Front Panel Board',
1698                     0b01101: 'Back Panel Board',
1699                     0b01110: 'Power System Board',
1700                     0b01111: 'Drive Back Plane'
1701                     }
1702                 self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status))
1703                 self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location))
1704             if self.length > 0x6:
1705                 self.add_field('maximum_value', u.unpack_one("<H"))
1706             if self.length > 0x8:
1707                 self.add_field('minimum_value', u.unpack_one("<H"))
1708             if self.length > 0xA:
1709                 self.add_field('resolution', u.unpack_one("<H"))
1710             if self.length > 0xC:
1711                 self.add_field('tolerance', u.unpack_one("<H"))
1712             if self.length > 0xE:
1713                 self.add_field('accuracy', u.unpack_one("<H"))
1714             if self.length > 0x10:
1715                 self.add_field('OEM_defined', u.unpack_one("<I"))
1716             if self.length > 0x14:
1717                 self.add_field('nominal_value', u.unpack_one("<H"))
1718         except:
1719             self.decodeFailure = True
1720             print "Error parsing TemperatureProbe"
1721             import traceback
1722             traceback.print_exc()
1723         self.fini()
1725 class ElectricalCurrentProbe(SmbiosBaseStructure):
1726     smbios_structure_type = 29
1728     def __init__(self, u, sm):
1729         super(ElectricalCurrentProbe, self).__init__(u, sm)
1730         u = self.u
1731         try:
1732             if self.length > 0x4:
1733                 self.add_field('description', u.unpack_one("B"), self.fmtstr)
1734             if self.length > 0x5:
1735                 self.add_field('location_and_status', u.unpack_one("B"))
1736                 _status = {
1737                     0b001: 'Other',
1738                     0b010: 'Unknown',
1739                     0b011: 'OK',
1740                     0b100: 'Non-critical',
1741                     0b101: 'Critical',
1742                     0b110: 'Non-recoverable'
1743                     }
1744                 _location = {
1745                     0b00001: 'Other',
1746                     0b00010: 'Unknown',
1747                     0b00011: 'Processor',
1748                     0b00100: 'Disk',
1749                     0b00101: 'Peripheral Bay',
1750                     0b00110: 'System Management Module',
1751                     0b00111: 'Motherboard',
1752                     0b01000: 'Memory Module',
1753                     0b01001: 'Processor Module',
1754                     0b01010: 'Power Unit',
1755                     0b01011: 'Add-in Card',
1756                     0b01100: 'Front Panel Board',
1757                     0b01101: 'Back Panel Board',
1758                     0b01110: 'Power System Board',
1759                     0b01111: 'Drive Back Plane'
1760                     }
1761                 self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status))
1762                 self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location))
1763             if self.length > 0x6:
1764                 self.add_field('maximum_value', u.unpack_one("<H"))
1765             if self.length > 0x8:
1766                 self.add_field('minimum_value', u.unpack_one("<H"))
1767             if self.length > 0xA:
1768                 self.add_field('resolution', u.unpack_one("<H"))
1769             if self.length > 0xC:
1770                 self.add_field('tolerance', u.unpack_one("<H"))
1771             if self.length > 0xE:
1772                 self.add_field('accuracy', u.unpack_one("<H"))
1773             if self.length > 0x10:
1774                 self.add_field('OEM_defined', u.unpack_one("<I"))
1775             if self.length > 0x14:
1776                 self.add_field('nominal_value', u.unpack_one("<H"))
1777         except:
1778             self.decodeFailure = True
1779             print "Error parsing ElectricalCurrentProbe"
1780             import traceback
1781             traceback.print_exc()
1782         self.fini()
1784 class OutOfBandRemoteAccess(SmbiosBaseStructure):
1785     smbios_structure_type = 30
1787     def __init__(self, u, sm):
1788         super(OutOfBandRemoteAccess, self).__init__(u, sm)
1789         u = self.u
1790         try:
1791             if self.length > 0x4:
1792                 self.add_field('manufacturer_name', u.unpack_one("B"), self.fmtstr)
1793             if self.length > 0x5:
1794                 self.add_field('connections', u.unpack_one("B"))
1795                 self.add_field('outbound_connection_enabled', bool(bitfields.getbits(self.connections, 1)), "connections[1]={}")
1796                 self.add_field('inbound_connection_enabled', bool(bitfields.getbits(self.connections, 0)), "connections[0]={}")
1797         except:
1798             self.decodeFailure = True
1799             print "Error parsing OutOfBandRemoteAccess"
1800             import traceback
1801             traceback.print_exc()
1802         self.fini()
1804 class BootIntegrityServicesEntryPoint(SmbiosBaseStructure):
1805     smbios_structure_type = 31
1807 class SystemBootInformation(SmbiosBaseStructure):
1808     smbios_structure_type = 32
1810     def __init__(self, u, sm):
1811         super(SystemBootInformation, self).__init__(u, sm)
1812         u = self.u
1813         try:
1814             if self.length > 0xA:
1815                 u.skip(6)
1816                 _boot_status = {
1817                     0: 'No errors detected',
1818                     1: 'No bootable media',
1819                     2: '"normal" operating system failed to load',
1820                     3: 'Firmware-detected hardware failure, including "unknown" failure types',
1821                     4: 'Operating system-detected hardware failure',
1822                     5: 'User-requested boot, usually through a keystroke',
1823                     6: 'System security violation',
1824                     7: 'Previously-requested image',
1825                     8: 'System watchdog timer expired, causing the system to reboot',
1826                     xrange(9,127): 'Reserved for future assignment',
1827                     xrange(128, 191): 'Vendor/OEM-specific implementations',
1828                     xrange(192, 255): 'Product-specific implementations'
1829                     }
1830                 self.add_field('boot_status', u.unpack_one("B"), unpack.format_table("{}", _boot_status))
1831         except:
1832             self.decodeFailure = True
1833             print "Error parsing SystemBootInformation"
1834             import traceback
1835             traceback.print_exc()
1836         self.fini()
1838 class MemoryErrorInfo64Bit(SmbiosBaseStructure):
1839     smbios_structure_type = 33
1841     def __init__(self, u, sm):
1842         super(MemoryErrorInfo64Bit, self).__init__(u, sm)
1843         u = self.u
1844         try:
1845             if self.length > 0x4:
1846                 _error_types = {
1847                     0x01: 'Other',
1848                     0x02: 'Unknown',
1849                     0x03: 'OK',
1850                     0x04: 'Bad read',
1851                     0x05: 'Parity error',
1852                     0x06: 'Single-bit error',
1853                     0x07: 'Double-bit error',
1854                     0x08: 'Multi-bit error',
1855                     0x09: 'Nibble error',
1856                     0x0A: 'Checksum error',
1857                     0x0B: 'CRC error',
1858                     0x0C: 'Corrected single-bit error',
1859                     0x0D: 'Corrected error',
1860                     0x0E: 'Uncorrectable error'
1861                     }
1862                 self.add_field('error_type', u.unpack_one("B"), unpack.format_table("{}", _error_types))
1863             if self.length > 0x5:
1864                  _error_granularity_field = {
1865                     0x01: 'Other',
1866                     0x02: 'Unknown',
1867                     0x03: 'Device level',
1868                     0x04: 'Memory partition level'
1869                     }
1870                  self.add_field('error_granularity', u.unpack_one("B"), unpack.format_table("{}", _error_granularity_field))
1871             if self.length > 0x6:
1872                 _error_operation_field = {
1873                     0x01: 'Other',
1874                     0x02: 'Unknown',
1875                     0x03: 'Read',
1876                     0x04: 'Write',
1877                     0x05: 'Partial write'
1878                     }
1879                 self.add_field('error_operation', u.unpack_one("B"), unpack.format_table("{}", _error_operation_field))
1880             if self.length > 0x7:
1881                 self.add_field('vendor_syndrome', u.unpack_one("<I"))
1882             if self.length > 0xB:
1883                 self.add_field('memory_array_error_address', u.unpack_one("<Q"))
1884             if self.length > 0xF:
1885                 self.add_field('device_error_address', u.unpack_one("<Q"))
1886             if self.length > 0x13:
1887                 self.add_field('error_resolution', u.unpack_one("<Q"))
1888         except:
1889             self.decodeFailure = True
1890             print "Error parsing MemoryErrorInfo64Bit"
1891             import traceback
1892             traceback.print_exc()
1893         self.fini()
1895 class ManagementDevice(SmbiosBaseStructure):
1896     smbios_structure_type = 34
1898     def __init__(self, u, sm):
1899         super(ManagementDevice, self).__init__(u, sm)
1900         u = self.u
1901         try:
1902             if self.length > 0x4:
1903                 self.add_field('description', u.unpack_one("B"), self.fmtstr)
1904             if self.length > 0x5:
1905                 _type = {
1906                     0x01: 'Other',
1907                     0x02: 'Unknown',
1908                     0x03: 'National Semiconductor LM75',
1909                     0x04: 'National Semiconductor LM78',
1910                     0x05: 'National Semiconductor LM79',
1911                     0x06: 'National Semiconductor LM80',
1912                     0x07: 'National Semiconductor LM81',
1913                     0x08: 'Analog Devices ADM9240',
1914                     0x09: 'Dallas Semiconductor DS1780',
1915                     0x0A: 'Maxim 1617',
1916                     0x0B: 'Genesys GL518SM',
1917                     0x0C: 'Winbond W83781D',
1918                     0x0D: 'Holtek HT82H791'
1919                     }
1920                 self.add_field('device_type', u.unpack_one("B"), unpack.format_table("{}", _type))
1921             if self.length > 0x6:
1922                 self.add_field('address', u.unpack_one("<I"))
1923             if self.length > 0xA:
1924                  _address_type = {
1925                     0x01: 'Other',
1926                     0x02: 'Unknown',
1927                     0x03: 'I/O Port',
1928                     0x04: 'Memory',
1929                     0x05: 'SM Bus'
1930                     }
1931                  self.add_field('address_type', u.unpack_one("B"), unpack.format_table("{}", _address_type))
1932         except:
1933             self.decodeFailure = True
1934             print "Error parsing ManagementDevice"
1935             import traceback
1936             traceback.print_exc()
1937         self.fini()
1939 class ManagementDeviceComponent(SmbiosBaseStructure):
1940     smbios_structure_type = 35
1942     def __init__(self, u, sm):
1943         super(ManagementDeviceComponent, self).__init__(u, sm)
1944         u = self.u
1945         try:
1946             if self.length > 0x4:
1947                 self.add_field('description', u.unpack_one("B"), self.fmtstr)
1948             if self.length > 0x5:
1949                 self.add_field('management_device_handle', u.unpack_one("<H"))
1950             if self.length > 0x7:
1951                 self.add_field('component_handle', u.unpack_one("<H"))
1952             if self.length > 0x9:
1953                 self.add_field('threshold_handle', u.unpack_one("<H"))
1954         except:
1955             self.decodeFailure = True
1956             print "Error parsing ManagementDeviceComponent"
1957             import traceback
1958             traceback.print_exc()
1959         self.fini()
1961 class ManagementDeviceThresholdData(SmbiosBaseStructure):
1962     smbios_structure_type = 36
1964     def __init__(self, u, sm):
1965         super(ManagementDeviceThresholdData, self).__init__(u, sm)
1966         u = self.u
1967         try:
1968             if self.length > 0x4:
1969                 self.add_field('lower_threshold_noncritical', u.unpack_one("<H"))
1970             if self.length > 0x6:
1971                 self.add_field('upper_threshold_noncritical', u.unpack_one("<H"))
1972             if self.length > 0x8:
1973                 self.add_field('lower_threshold_critical', u.unpack_one("<H"))
1974             if self.length > 0xA:
1975                 self.add_field('upper_threshold_critical', u.unpack_one("<H"))
1976             if self.length > 0xC:
1977                 self.add_field('lower_threshold_nonrecoverable', u.unpack_one("<H"))
1978             if self.length > 0xE:
1979                 self.add_field('upper_threshold_nonrecoverable', u.unpack_one("<H"))
1980         except:
1981             self.decodeFailure = True
1982             print "Error parsing ManagementDeviceThresholdData"
1983             import traceback
1984             traceback.print_exc()
1985         self.fini()
1987 class MemoryChannel(SmbiosBaseStructure):
1988     smbios_structure_type = 37
1990     def __init__(self, u, sm):
1991         super(MemoryChannel, self).__init__(u, sm)
1992         u = self.u
1993         try:
1994             if self.length > 0x4:
1995                 _channel_type = {
1996                     0x01: 'Other',
1997                     0x02: 'Unknown',
1998                     0x03: 'RamBus',
1999                     0x04: 'SyncLink'
2000                     }
2001                 self.add_field('channel_type', u.unpack_one("B"), unpack.format_table("{}", _channel_type))
2002             if self.length > 0x6:
2003                 self.add_field('max_channel_load', u.unpack_one("B"))
2004             if self.length > 0x8:
2005                 self.add_field('memory_device_count', u.unpack_one("B"))
2006             if self.length > 0xA:
2007                 self.add_field('memory_device_load', u.unpack_one("B"))
2008             if self.length > 0xC:
2009                 self.add_field('memory_device_handle', u.unpack_one("<H"))
2010         except:
2011             self.decodeFailure = True
2012             print "Error parsing MemoryChannel"
2013             import traceback
2014             traceback.print_exc()
2015         self.fini()
2017 class IPMIDeviceInformation(SmbiosBaseStructure):
2018     smbios_structure_type = 38
2020     def __init__(self, u, sm):
2021         super(IPMIDeviceInformation, self).__init__(u, sm)
2022         u = self.u
2023         try:
2024             _interface_type = {
2025                 0x00: 'Unknown',
2026                 0x01: 'KCS: Keyboard Controller Style',
2027                 0x02: 'SMIC: Server Management Interface Chip',
2028                 0x03: 'BT: Block Transfer',
2029                 xrange(0x04, 0xFF): 'Reserved'
2030                 }
2031             self.add_field('interface_type', u.unpack_one("B"), unpack.format_table("{}", _interface_type))
2032             self.add_field('ipmi_specification_revision', u.unpack_one("B"))
2033             self.add_field('msd_revision', bitfields.getbits(self.ipmi_specification_revision, 7, 4), "ipmi_specification_revision[7:4]={}")
2034             self.add_field('lsd_revision', bitfields.getbits(self.ipmi_specification_revision, 3, 0), "ipmi_specification_revision[3:0]={}")
2036             self.add_field('i2c_slave_address', u.unpack_one("B"))
2037             self.add_field('nv_storage_device_address', u.unpack_one("B"))
2038             self.add_field('base_address', u.unpack_one("<Q"))
2039             # if lsb is 1, address is in IO space. otherwise, memory-mapped
2040             self.add_field('base_address_modifier_interrupt_info', u.unpack_one("B"))
2041             _reg_spacing = {
2042                 0b00: 'Interface registers are on successive byte boundaries',
2043                 0b01: 'Interface registers are on 32-bit boundaries',
2044                 0b10: 'Interface registers are on 16-byte boundaries',
2045                 0b11: 'Reserved'
2046                 }
2047             self.add_field('register_spacing', bitfields.getbits(self.base_address_modifier_interrupt_info, 7, 6), unpack.format_table("base_address_modifier_interrupt_info[7:6]={}", _reg_spacing))
2048             self.add_field('ls_bit_for_addresses', bitfields.getbits(self.base_address_modifier_interrupt_info, 4), "base_address_modifier_interrupt_info[4]={}")
2049             self.add_field('interrupt_info_specified', bool(bitfields.getbits(self.base_address_modifier_interrupt_info, 3)), "base_address_modifier_interrupt_info[3]={}")
2050             _polarity = {
2051                 0: 'active low',
2052                 1: 'active high'
2053                 }
2054             self.add_field('interrupt_polarity', bitfields.getbits(self.base_address_modifier_interrupt_info, 1), unpack.format_table("base_address_modifier_interrupt_info[1]={}", _polarity))
2055             _interrupt_trigger = {
2056                 0: 'edge',
2057                 1: 'level'
2058                 }
2059             self.add_field('interrupt_trigger_mode', bitfields.getbits(self.base_address_modifier_interrupt_info, 0), unpack.format_table("base_address_modifier_interrupt_info[0]={}", _interrupt_trigger))
2060             self.add_field('interrupt_number', u.unpack_one("B"))
2061         except:
2062             self.decodeFailure = True
2063             print "Error parsing IPMIDeviceInformation"
2064             import traceback
2065             traceback.print_exc()
2066         self.fini()
2068 class SystemPowerSupply(SmbiosBaseStructure):
2069     smbios_structure_type = 39
2071     def __init__(self, u, sm):
2072         super(SystemPowerSupply, self).__init__(u, sm)
2073         u = self.u
2074         try:
2075             if self.length > 0x4:
2076                 self.add_field('power_unit_group', u.unpack_one("B"))
2077             if self.length > 0x5:
2078                 self.add_field('location', u.unpack_one("B"), self.fmtstr)
2079             if self.length > 0x6:
2080                 self.add_field('device_name', u.unpack_one("B"), self.fmtstr)
2081             if self.length > 0x7:
2082                 self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr)
2083             if self.length > 0x8:
2084                 self.add_field('serial_number', u.unpack_one("B"), self.fmtstr)
2085             if self.length > 0x9:
2086                 self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr)
2087             if self.length > 0xA:
2088                 self.add_field('model_part_number', u.unpack_one("B"), self.fmtstr)
2089             if self.length > 0xB:
2090                 self.add_field('revision_level', u.unpack_one("B"), self.fmtstr)
2091             if self.length > 0xC:
2092                 self.add_field('max_power_capacity', u.unpack_one("<H"))
2093             if self.length > 0xE:
2094                 self.add_field('power_supply_characteristics', u.unpack_one("<H"))
2095                 _dmtf_power_supply_type = {
2096                     0b001: 'Other',
2097                     0b010: 'Unknown',
2098                     0b011: 'Linear',
2099                     0b100: 'Switching',
2100                     0b101: 'Battery',
2101                     0b110: 'UPS',
2102                     0b111: 'Converter',
2103                     0b1000: 'Regulator',
2104                     xrange(0b1001, 0b1111): 'Reserved'
2105                     }
2106                 self.add_field('dmtf_power_supply_type', bitfields.getbits(self.power_supply_characteristics, 13, 10), unpack.format_table("power_supply_characteristics[13:10]={}", _dmtf_power_supply_type))
2107                 _status = {
2108                     0b001: 'Other',
2109                     0b010: 'Unknown',
2110                     0b011: 'OK',
2111                     0b100: 'Non-critical',
2112                     0b101: 'Critical; power supply has failed and has been taken off-line'
2113                     }
2114                 self.add_field('status', bitfields.getbits(self.power_supply_characteristics, 9, 7), unpack.format_table("power_supply_characteristics[9:7]={}", _status))
2115                 _dmtf_input_voltage_range_switching = {
2116                     0b001: 'Other',
2117                     0b010: 'Unknown',
2118                     0b011: 'Manual',
2119                     0b100: 'Auto-switch',
2120                     0b101: 'Wide range',
2121                     0b110: 'Not applicable',
2122                     xrange(0b0111, 0b1111): 'Reserved'
2123                     }
2124                 self.add_field('dmtf_input_voltage_range_switching', bitfields.getbits(self.power_supply_characteristics, 6, 3), unpack.format_table("power_supply_characteristics[6:3]={}", _dmtf_input_voltage_range_switching))
2125                 self.add_field('power_supply_unplugged', bool(bitfields.getbits(self.power_supply_characteristics, 2)), "power_supply_characteristics[2]={}")
2126                 self.add_field('power_supply_present', bool(bitfields.getbits(self.power_supply_characteristics, 1)), "power_supply_characteristics[1]={}")
2127                 self.add_field('power_supply_hot_replaceable', bool(bitfields.getbits(self.power_supply_characteristics, 0)), "power_supply_characteristics[0]={}")
2128             if self.length > 0x10:
2129                 self.add_field('input_voltage_probe_handle', u.unpack_one("<H"))
2130             if self.length > 0x12:
2131                 self.add_field('cooling_device_handle', u.unpack_one("<H"))
2132             if self.length > 0x14:
2133                 self.add_field('input_current_probe_handle', u.unpack_one("<H"))
2134         except:
2135             self.decodeFailure = True
2136             print "Error parsing SystemPowerSupply"
2137             import traceback
2138             traceback.print_exc()
2139         self.fini()
2141 class AdditionalInformation(SmbiosBaseStructure):
2142     smbios_structure_type = 40
2144     def __init__(self, u, sm):
2145         super(AdditionalInformation, self).__init__(u, sm)
2146         u = self.u
2147         try:
2148             if self.length > 0x4:
2149                 self.add_field('num_additional_information_entries', u.unpack_one("B"))
2150             if self.length > 0x5:
2151                 self.add_field('additional_information_entry_length', u.unpack_one("B"))
2152                 self.add_field('referenced_handle', u.unpack_one("<H"))
2153                 self.add_field('referenced_offset', u.unpack_one("B"))
2154                 self.add_field('string', u.unpack_one("B"), self.fmtstr)
2155                 self.add_field('value', u.unpack_rest())
2156         except:
2157             self.decodeFailure = True
2158             print "Error parsing AdditionalInformation"
2159             import traceback
2160             traceback.print_exc()
2161         self.fini()
2163 class OnboardDevicesExtendedInformation(SmbiosBaseStructure):
2164     smbios_structure_type = 41
2166     def __init__(self, u, sm):
2167         super(OnboardDevicesExtendedInformation, self).__init__(u, sm)
2168         u = self.u
2169         try:
2170             if self.length > 0x4:
2171                 self.add_field('reference_designation', u.unpack_one("B"), self.fmtstr)
2172             if self.length > 0x5:
2173                 self.add_field('device_type', u.unpack_one("B"))
2174                 self.add_field('device_enabled', bool(bitfields.getbits(self.device_type, 7)), "device_type[7]={}")
2175                 _device_types = {
2176                     0x01: 'Other',
2177                     0x02: 'Unknown',
2178                     0x03: 'Video',
2179                     0x04: 'SCSI Controller',
2180                     0x05: 'Ethernet',
2181                     0x06: 'Token Ring',
2182                     0x07: 'Sound',
2183                     0x08: 'PATA Controller',
2184                     0x09: 'SATA Controller',
2185                     0x0A: 'SAS Controller'
2186                     }
2187                 self.add_field('type_of_device', bitfields.getbits(self.device_type, 6, 0), unpack.format_table("device_type[6:0]={}", _device_types))
2188             if self.length > 0x6:
2189                 self.add_field('device_type_instance', u.unpack_one("B"))
2190             if self.length > 0x7:
2191                 self.add_field('segment_group_number', u.unpack_one("<H"))
2192             if self.length > 0x9:
2193                 self.add_field('bus_number', u.unpack_one("B"), self.fmtstr)
2194             if self.length > 0xA:
2195                 self.add_field('device_and_function_number', u.unpack_one("B"))
2196                 self.add_field('device_number', bitfields.getbits(self.device_type, 7, 3), "device_and_function_number[7:3]={}")
2197                 self.add_field('function_number', bitfields.getbits(self.device_type, 2, 0), "device_and_function_number[2:0]={}")
2198         except:
2199             self.decodeFailure = True
2200             print "Error parsing OnboardDevicesExtendedInformation"
2201             import traceback
2202             traceback.print_exc()
2203         self.fini()
2205 class ManagementControllerHostInterface(SmbiosBaseStructure):
2206     smbios_structure_type = 42
2208     def __init__(self, u, sm):
2209         super(ManagementControllerHostInterface, self).__init__(u, sm)
2210         u = self.u
2211         try:
2212             if self.length > 0x4:
2213                 _interface_types = {
2214                     0x00: 'Reserved',
2215                     0x01: 'Reserved',
2216                     0x02: 'KCS: Keyboard Controller Style',
2217                     0x03: '8250 UART Register Compatible',
2218                     0x04: '16450 UART Register Compatible',
2219                     0x05: '16550/16550A UART Register Compatible',
2220                     0x06: '16650/16650A UART Register Compatible',
2221                     0x07: '16750/16750A UART Register Compatible',
2222                     0x08: '16850/16850A UART Register Compatible',
2223                     0xF0: 'OEM'
2224                     }
2225                 self.add_field('interface_type', u.unpack_one("B"), unpack.format_table("{}", _interface_types))
2226             if self.length > 0x5:
2227                 self.add_field('mc_host_interface_data', u.unpack_rest(), self.fmtstr)
2228         except:
2229             self.decodeFailure = True
2230             print "Error parsing ManagementControllerHostInterface"
2231             import traceback
2232             traceback.print_exc()
2233         self.fini()
2235 class Inactive(SmbiosBaseStructure):
2236     smbios_structure_type = 126
2238     def __init__(self, u, sm):
2239         super(Inactive, self).__init__(u, sm)
2240         self.fini()
2242 class EndOfTable(SmbiosBaseStructure):
2243     smbios_structure_type = 127
2245     def __init__(self, u, sm):
2246         super(EndOfTable, self).__init__(u, sm)
2247         self.fini()
2249 class SmbiosStructureUnknown(SmbiosBaseStructure):
2250     smbios_structure_type = None
2252     def __init__(self, u, sm):
2253         super(SmbiosStructureUnknown, self).__init__(u, sm)
2254         self.fini()
2256 _smbios_structures = [
2257     BIOSInformation,
2258     SystemInformation,
2259     BaseboardInformation,
2260     SystemEnclosure,
2261     ProcessorInformation,
2262     MemoryControllerInformation,
2263     MemoryModuleInformation,
2264     CacheInformation,
2265     PortConnectorInfo,
2266     SystemSlots,
2267     OnBoardDevicesInformation,
2268     OEMStrings,
2269     SystemConfigOptions,
2270     BIOSLanguageInformation,
2271     GroupAssociations,
2272     SystemEventLog,
2273     PhysicalMemoryArray,
2274     MemoryDevice,
2275     MemoryErrorInfo32Bit,
2276     MemoryArrayMappedAddress,
2277     MemoryDeviceMappedAddress,
2278     BuiltInPointingDevice,
2279     PortableBattery,
2280     SystemReset,
2281     HardwareSecurity,
2282     SystemPowerControls,
2283     VoltageProbe,
2284     CoolingDevice,
2285     TemperatureProbe,
2286     ElectricalCurrentProbe,
2287     OutOfBandRemoteAccess,
2288     BootIntegrityServicesEntryPoint,
2289     SystemBootInformation,
2290     MemoryErrorInfo64Bit,
2291     ManagementDevice,
2292     ManagementDeviceComponent,
2293     ManagementDeviceThresholdData,
2294     MemoryChannel,
2295     IPMIDeviceInformation,
2296     SystemPowerSupply,
2297     AdditionalInformation,
2298     OnboardDevicesExtendedInformation,
2299     ManagementControllerHostInterface,
2300     Inactive,
2301     EndOfTable,
2302     SmbiosStructureUnknown, # Must always come last
2305 def log_smbios_info():
2306     with redirect.logonly():
2307         try:
2308             sm = SMBIOS()
2309             print
2310             if sm is None:
2311                 print "No SMBIOS structures found"
2312                 return
2313             output = {}
2314             known_types = (0, 1)
2315             for sm_struct in sm.structures:
2316                 if sm_struct.type in known_types:
2317                     output.setdefault(sm_struct.type, []).append(sm_struct)
2318                     if len(output) == len(known_types):
2319                         break
2321             print "SMBIOS information:"
2322             for key in sorted(known_types):
2323                 for s in output.get(key, ["No structure of type {} found".format(key)]):
2324                     print ttypager._wrap("{}: {}".format(key, s))
2325         except:
2326             print "Error parsing SMBIOS information:"
2327             import traceback
2328             traceback.print_exc()
2330 def dump_raw():
2331     try:
2332         sm = SMBIOS()
2333         if sm:
2334             s = "SMBIOS -- Raw bytes and structure decode.\n\n"
2336             s += str(sm.header) + '\n'
2337             s += bits.dumpmem(sm._header_memory) + '\n'
2339             s += "Raw bytes for the SMBIOS structures\n"
2340             s += bits.dumpmem(sm._structure_memory) + '\n'
2342             for sm_struct in sm.structures:
2343                 s += str(sm_struct) + '\n'
2344                 s += bits.dumpmem(sm_struct.raw_data)
2346                 s += "Strings:\n"
2347                 for n in range(1, len(getattr(sm_struct, "strings", [])) + 1):
2348                     s += str(sm_struct.fmtstr(n)) + '\n'
2349                 s += bits.dumpmem(sm_struct.raw_strings) + '\n'
2350         else:
2351             s = "No SMBIOS structures found"
2352         ttypager.ttypager_wrap(s, indent=False)
2353     except:
2354         print "Error parsing SMBIOS information:"
2355         import traceback
2356         traceback.print_exc()
2358 def dump():
2359     try:
2360         sm = SMBIOS()
2361         if sm:
2362             s = str(sm)
2363         else:
2364             s = "No SMBIOS structures found"
2365         ttypager.ttypager_wrap(s, indent=False)
2366     except:
2367         print "Error parsing SMBIOS information:"
2368         import traceback
2369         traceback.print_exc()
2371 def annex_a_conformance():
2372     try:
2373         sm = SMBIOS()
2375         # check: 1. The table anchor string "_SM_" is present in the address range 0xF0000 to 0xFFFFF on a 16-byte bound
2377         def table_entry_point_verification():
2378             ''' Verify table entry-point'''
2379             if (sm.header.length < 0x1F):
2380                 print "Failure: Table entry-point - The entry-point Length must be at least 0x1F"
2381             if sm.header.checksum != 0:
2382                 print "Failure: Table entry-point - The entry-point checksum must evaluate to 0"
2383             if ((sm.header.major_version < 2) and (sm.header.minor_version < 4)):
2384                 print "Failure: Table entry-point - SMBIOS version must be at least 2.4"
2385             if (sm.header.intermediate_anchor_string == '_DMI_'):
2386                 print "Failure: Table entry-point - The Intermediate Anchor String must be '_DMI_'"
2387             if (sm.header.intermediate_checksum != 0):
2388                 print "Failure: Table entry-point - The Intermediate checksum must evaluate to 0"
2390         #check: 3. The structure-table is traversable and conforms to the entry-point specifications:
2392         def req_structures():
2393             '''Checks for required structures and corresponding data'''
2394             types_present = [sm.structures[x].smbios_structure_type for x in range(len(sm.structures))]
2395             required = [0, 1, 4, 7, 9, 16, 17, 19, 31, 32]
2396             for s in required:
2397                 if s not in set(types_present):
2398                     print "Failure: Type {} required but not found".format(s)
2400                 else:
2401                     if s == 0:
2402                         if types_present.count(s) > 1:
2403                             print "Failure: Type {} - One and only one structure of this type must be present.".format(s)
2404                         if sm.structure_type(s).length < 0x18:
2405                             print "Failure: Type {} - The structure Length field must be at least 0x18".format(s)
2406                         if sm.structure_type(s).version is None:
2407                             print "Failure: Type {} - BIOS Version string must be present and non-null.".format(s)
2408                         if sm.structure_type(s).release_date is None:
2409                             print "Failure: Type {} - BIOS Release Date string must be present, non-null, and include a 4-digit year".format(s)
2410                         if bitfields.getbits(sm.structure_type(s).characteristics, 3, 0) != 0 or bitfields.getbits(sm.structure_type(s).characteristics, 31, 4) == 0:
2411                             print "Failure: Type {} - BIOS Characteristics: bits 3:0 must all be 0, and at least one of bits 31:4 must be set to 1.".format(s)
2412                     elif s == 1:
2413                         if types_present.count(s) > 1:
2414                             print "Failure: Type {} - One and only one structure of this type must be present.".format(s)
2415                         if sm.structure_type(s).length < 0x1B:
2416                             print "Failure: Type {} - The structure Length field must be at least 0x1B".format(s)
2417                         if sm.structure_type(s).manufacturer == None:
2418                             print "Failure: Type {} - Manufacturer string must be present and non-null.".format(s)
2419                         if sm.structure_type(s).product_name == None:
2420                             print "Failure: Type {} - Product Name string must be present and non-null".format(s)
2421                         if sm.structure_type(s).uuid == '00000000 00000000' and sm.structure_type(s).uuid == 'FFFFFFFF FFFFFFFF':
2422                             print "Failure: Type {} - UUID field must be neither 00000000 00000000 nor FFFFFFFF FFFFFFFF.".format(s)
2423                         if sm.structure_type(s).wakeup_type == 00 and sm.structure_type(s).wakeup_type == 0x02:
2424                             print "Failure: Type {} - Wake-up Type field must be neither 00h (Reserved) nor 02h (Unknown).".format(s)
2425                     # continue for remaining required types
2427         # check remaining conformance guidelines
2429         table_entry_point_verification()
2430         req_structures()
2431     except:
2432         print "Error checking ANNEX A conformance guidelines"
2433         import traceback
2434         traceback.print_exc()