# Copyright (c) 2015, Intel Corporation # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of Intel Corporation nor the names of its contributors # may be used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """SMBIOS/DMI module.""" import bits import bitfields import ctypes import redirect import struct import uuid import unpack import ttypager import sys class SMBIOS(unpack.Struct): def __new__(cls): if sys.platform == "BITS-EFI": import efi sm_ptr = efi.system_table.ConfigurationTableDict.get(efi.SMBIOS_TABLE_GUID) else: address = 0xF0000 mem = bits.memory(0xF0000, 0x10000) for offset in range(0, len(mem), 16): signature = (ctypes.c_char * 4).from_address(address + offset).value if signature == "_SM_": entry_point_length = ctypes.c_ubyte.from_address(address + offset + 5).value csum = sum(map(ord, mem[offset:offset + entry_point_length])) & 0xff if csum == 0: sm_ptr = address + offset break else: return None if not sm_ptr: return None sm = super(SMBIOS, cls).__new__(cls) sm._header_memory = bits.memory(sm_ptr, 0x1f) return sm def __init__(self): super(SMBIOS, self).__init__() u = unpack.Unpackable(self._header_memory) self.add_field('header', Header(u)) self._structure_memory = bits.memory(self.header.structure_table_address, self.header.structure_table_length) u = unpack.Unpackable(self._structure_memory) self.add_field('structures', unpack.unpack_all(u, _smbios_structures, self), unpack.format_each("\n\n{!r}")) def structure_type(self, num): '''Dumps structure of given Type if present''' try: types_present = [self.structures[x].smbios_structure_type for x in range(len(self.structures))] matrix = dict() for index in range(len(types_present)): if types_present.count(types_present[index]) == 1: matrix[types_present[index]] = self.structures[index] else: # if multiple structures of the same type, return a list of structures for the type number if matrix.has_key(types_present[index]): matrix[types_present[index]].append(self.structures[index]) else: matrix[types_present[index]] = [self.structures[index]] return matrix[num] except: print "Failure: Type {} - not found".format(num) class Header(unpack.Struct): def __new__(cls, u): return super(Header, cls).__new__(cls) def __init__(self, u): super(Header, self).__init__() self.raw_data = u.unpack_rest() u = unpack.Unpackable(self.raw_data) self.add_field('anchor_string', u.unpack_one("4s")) self.add_field('checksum', u.unpack_one("B")) self.add_field('length', u.unpack_one("B")) self.add_field('major_version', u.unpack_one("B")) self.add_field('minor_version', u.unpack_one("B")) self.add_field('max_structure_size', u.unpack_one(" len(self.strings): return "(error: string index out of range)" return self.strings[i - 1] class BIOSInformation(SmbiosBaseStructure): smbios_structure_type = 0 def __init__(self, u, sm): super(BIOSInformation, self).__init__(u, sm) u = self.u try: self.add_field('vendor', u.unpack_one("B"), self.fmtstr) self.add_field('version', u.unpack_one("B"), self.fmtstr) self.add_field('starting_address_segment', u.unpack_one("= (2,"4"): characteristic_bytes = 2 else: characteristic_bytes = self.length - 0x12 self.add_field('characteristics_extensions', [u.unpack_one("B") for b in range(characteristic_bytes)]) if (sm.header.major_version, minor_version_str) >= (2,"4"): self.add_field('major_release', u.unpack_one("B")) self.add_field('minor_release', u.unpack_one("B")) self.add_field('ec_major_release', u.unpack_one("B")) self.add_field('ec_minor_release', u.unpack_one("B")) except: self.decode_failure = True print "Error parsing BIOSInformation" import traceback traceback.print_exc() self.fini() class SystemInformation(SmbiosBaseStructure): smbios_structure_type = 1 def __init__(self, u, sm): super(SystemInformation, self).__init__(u, sm) u = self.u try: self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) self.add_field('product_name', u.unpack_one("B"), self.fmtstr) self.add_field('version', u.unpack_one("B"), self.fmtstr) self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) if self.length > 0x8: self.add_field('uuid', uuid.UUID(bytes_le=u.unpack_one("16s"))) wakeup_types = { 0: 'Reserved', 1: 'Other', 2: 'Unknown', 3: 'APM Timer', 4: 'Modem Ring', 5: 'LAN Remote', 6: 'Power Switch', 7: 'PCI PME#', 8: 'AC Power Restored' } self.add_field('wakeup_type', u.unpack_one("B"), unpack.format_table("{}", wakeup_types)) if self.length > 0x19: self.add_field('sku_number', u.unpack_one("B"), self.fmtstr) self.add_field('family', u.unpack_one("B"), self.fmtstr) except: self.decode_failure = True print "Error parsing SystemInformation" import traceback traceback.print_exc() self.fini() _board_types = { 1: 'Unknown', 2: 'Other', 3: 'Server Blade', 4: 'Connectivity Switch', 5: 'System Management Module', 6: 'Processor Module', 7: 'I/O Module', 8: 'Memory Module', 9: 'Daughter Board', 0xA: 'Motherboard', 0xB: 'Processor/Memory Module', 0xC: 'Processor/IO Module', 0xD: 'Interconnect Board' } class BaseboardInformation(SmbiosBaseStructure): smbios_structure_type = 2 def __init__(self, u, sm): super(BaseboardInformation, self).__init__(u, sm) u = self.u try: self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) self.add_field('product', u.unpack_one("B"), self.fmtstr) self.add_field('version', u.unpack_one("B"), self.fmtstr) self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) if self.length > 0x8: self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr) if self.length > 0x9: self.add_field('feature_flags', u.unpack_one("B")) self.add_field('hosting_board', bool(bitfields.getbits(self.feature_flags, 0)), "feature_flags[0]={}") self.add_field('requires_daughter_card', bool(bitfields.getbits(self.feature_flags, 1)), "feature_flags[1]={}") self.add_field('removable', bool(bitfields.getbits(self.feature_flags, 2)), "feature_flags[2]={}") self.add_field('replaceable', bool(bitfields.getbits(self.feature_flags, 3)), "feature_flags[3]={}") self.add_field('hot_swappable', bool(bitfields.getbits(self.feature_flags, 4)), "feature_flags[4]={}") if self.length > 0xA: self.add_field('location', u.unpack_one("B"), self.fmtstr) if self.length > 0xB: self.add_field('chassis_handle', u.unpack_one(" 0xD: self.add_field('board_type', u.unpack_one("B"), unpack.format_table("{}", _board_types)) if self.length > 0xE: self.add_field('handle_count', u.unpack_one("B")) if self.handle_count > 0: self.add_field('contained_object_handles', tuple(u.unpack_one(" 9: chassis_states = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Safe', 0x04: 'Warning', 0x05: 'Critical', 0x06: 'Non-recoverable', } self.add_field('bootup_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states)) self.add_field('power_supply_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states)) self.add_field('thermal_state', u.unpack_one("B"), unpack.format_table("{}", chassis_states)) security_states = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'None', 0x04: 'External interface locked out', 0x05: 'External interface enabled', } self.add_field('security_status', u.unpack_one("B"), unpack.format_table("{}", security_states)) if self.length > 0xd: self.add_field('oem_defined', u.unpack_one(" 0x11: self.add_field('height', u.unpack_one("B")) self.add_field('num_power_cords', u.unpack_one("B")) self.add_field('contained_element_count', u.unpack_one("B")) self.add_field('contained_element_length', u.unpack_one("B")) if getattr(self, 'contained_element_count', 0): self.add_field('contained_elements', tuple(SystemEnclosureContainedElement(u, self.contained_element_length) for i in range(self.contained_element_count))) if self.length > (0x15 + (getattr(self, 'contained_element_count', 0) * getattr(self, 'contained_element_length', 0))): self.add_field('sku_number', u.unpack_one("B"), self.fmtstr) except: self.decode_failure = True print "Error parsing SystemEnclosure" import traceback traceback.print_exc() self.fini() class SystemEnclosureContainedElement(unpack.Struct): def __init__(self, u, length): super(SystemEnclosureContainedElement, self).__init__() self.start_offset = u.offset self.raw_data = u.unpack_raw(length) self.u = unpack.Unpackable(self.raw_data) u = self.u self.add_field('contained_element_type', u.unpack_one("B")) type_selections = { 0: 'SMBIOS baseboard type enumeration', 1: 'SMBIOS structure type enumeration', } self.add_field('type_select', bitfields.getbits(self.contained_element_type, 7), unpack.format_table("contained_element_type[7]={}", type_selections)) self.add_field('type', bitfields.getbits(self.contained_element_type, 6, 0)) if self.type_select == 0: self.add_field('smbios_board_type', self.type, unpack.format_table("{}", _board_types)) else: self.add_field('smbios_structure_type', self.type) self.add_field('minimum', u.unpack_one("B")) self.add_field('maximum', u.unpack_one("B")) if not u.at_end(): self.add_field('data', u.unpack_rest()) del self.u class ProcessorInformation(SmbiosBaseStructure): smbios_structure_type = 4 def __init__(self, u, sm): super(ProcessorInformation, self).__init__(u, sm) u = self.u try: self.add_field('socket_designation', u.unpack_one("B"), self.fmtstr) processor_types = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Central Processor', 0x04: 'Math Processor', 0x05: 'DSP Processor', 0x06: 'Video Processor', } self.add_field('processor_type', u.unpack_one("B"), unpack.format_table("{}", processor_types)) self.add_field('processor_family', u.unpack_one("B")) self.add_field('processor_manufacturer', u.unpack_one("B"), self.fmtstr) self.add_field('processor_id', u.unpack_one(" 0x1A: self.add_field('l1_cache_handle', u.unpack_one(" 0x20: self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr) self.add_field('part_number', u.unpack_one("B"), self.fmtstr) if self.length > 0x24: self.add_field('core_count', u.unpack_one("B")) self.add_field('core_enabled', u.unpack_one("B")) self.add_field('thread_count', u.unpack_one("B")) self.add_field('processor_characteristics', u.unpack_one(" 0x28: self.add_field('processor_family_2', u.unpack_one(" 0x2A: self.add_field('core_count2', u.unpack_one(" 0x0F: self.add_field('cache_speed', u.unpack_one("B")) if self.length > 0x10: _error_correction = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'None', 0x04: 'Parity', 0x05: 'Single-bit ECC', 0x06: 'Multi-bit ECC' } self.add_field('error_correction', u.unpack_one("B"), unpack.format_table("{}", _error_correction)) if self.length > 0x10: _system_cache_type = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Instruction', 0x04: 'Data', 0x05: 'Unified' } self.add_field('system_cache_type', u.unpack_one("B"), unpack.format_table("{}", _system_cache_type)) if self.length > 0x12: _associativity = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Direct Mapped', 0x04: '2-way Set-Associative', 0x05: '4-way Set-Associative', 0x06: 'Fully Associative', 0x07: '8-way Set-Associative', 0x08: '16-way Set-Associative', 0x09: '12-way Set-Associative', 0x0A: '24-way Set-Associative', 0x0B: '32-way Set-Associative', 0x0C: '48-way Set-Associative', 0x0D: '64-way Set-Associative', 0x0E: '20-way Set-Associative' } self.add_field('associativity', u.unpack_one("B"), unpack.format_table("{}", _associativity)) except: self.decode_failure = True print "Error parsing CacheInformation" import traceback traceback.print_exc() self.fini() class PortConnectorInfo(SmbiosBaseStructure): smbios_structure_type = 8 def __init__(self, u, sm): super(PortConnectorInfo, self).__init__(u, sm) u = self.u try: self.add_field('internal_reference_designator', u.unpack_one("B"), self.fmtstr) connector_types = { 0x00: 'None', 0x01: 'Centronics', 0x02: 'Mini Centronics', 0x03: 'Proprietary', 0x04: 'DB-25 pin male', 0x05: 'DB-25 pin female', 0x06: 'DB-15 pin male', 0x07: 'DB-15 pin female', 0x08: 'DB-9 pin male', 0x09: 'DB-9 pin female', 0x0A: 'RJ-11', 0x0B: 'RJ-45', 0x0C: '50-pin MiniSCSI', 0x0D: 'Mini-DIN', 0x0E: 'Micro-DIN', 0x0F: 'PS/2', 0x10: 'Infrared', 0x11: 'HP-HIL', 0x12: 'Access Bus (USB)', 0x13: 'SSA SCSI', 0x14: 'Circular DIN-8 male', 0x15: 'Circular DIN-8 female', 0x16: 'On Board IDE', 0x17: 'On Board Floppy', 0x18: '9-pin Dual Inline (pin 10 cut)', 0x19: '25-pin Dual Inline (pin 26 cut)', 0x1A: '50-pin Dual Inline', 0x1B: '68-pin Dual Inline', 0x1C: 'On Board Sound Input from CD-ROM', 0x1D: 'Mini-Centronics Type-14', 0x1E: 'Mini-Centronics Type-26', 0x1F: 'Mini-jack (headphones)', 0x20: 'BNC', 0x21: '1394', 0x22: 'SAS/SATA Plug Receptacle', 0xA0: 'PC-98', 0xA1: 'PC-98Hireso', 0xA2: 'PC-H98', 0xA3: 'PC-98Note', 0xA4: 'PC-98Full', 0xFF: 'Other', } self.add_field('internal_connector_type', u.unpack_one("B"), unpack.format_table("{}", connector_types)) self.add_field('external_reference_designator', u.unpack_one("B"), self.fmtstr) self.add_field('external_connector_type', u.unpack_one("B"), unpack.format_table("{}", connector_types)) port_types = { 0x00: 'None', 0x01: 'Parallel Port XT/AT Compatible', 0x02: 'Parallel Port PS/2', 0x03: 'Parallel Port ECP', 0x04: 'Parallel Port EPP', 0x05: 'Parallel Port ECP/EPP', 0x06: 'Serial Port XT/AT Compatible', 0x07: 'Serial Port 16450 Compatible', 0x08: 'Serial Port 16550 Compatible', 0x09: 'Serial Port 16550A Compatible', 0x0A: 'SCSI Port', 0x0B: 'MIDI Port', 0x0C: 'Joy Stick Port', 0x0D: 'Keyboard Port', 0x0E: 'Mouse Port', 0x0F: 'SSA SCSI', 0x10: 'USB', 0x11: 'FireWire (IEEE P1394)', 0x12: 'PCMCIA Type I2', 0x13: 'PCMCIA Type II', 0x14: 'PCMCIA Type III', 0x15: 'Cardbus', 0x16: 'Access Bus Port', 0x17: 'SCSI II', 0x18: 'SCSI Wide', 0x19: 'PC-98', 0x1A: 'PC-98-Hireso', 0x1B: 'PC-H98', 0x1C: 'Video Port', 0x1D: 'Audio Port', 0x1E: 'Modem Port', 0x1F: 'Network Port', 0x20: 'SATA', 0x21: 'SAS', 0xA0: '8251 Compatible', 0xA1: '8251 FIFO Compatible', 0xFF: 'Other', } self.add_field('port_type', u.unpack_one("B"), unpack.format_table("{}", port_types)) except: self.decodeFailure = True print "Error parsing PortConnectorInfo" import traceback traceback.print_exc() self.fini() class SystemSlots(SmbiosBaseStructure): smbios_structure_type = 9 def __init__(self, u, sm): super(SystemSlots, self).__init__(u, sm) u = self.u try: self.add_field('designation', u.unpack_one("B"), self.fmtstr) _slot_types = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'ISA', 0x04: 'MCA', 0x05: 'EISA', 0x06: 'PCI', 0x07: 'PC Card (PCMCIA)', 0x08: 'VL-VESA', 0x09: 'Proprietary', 0x0A: 'Processor Card Slot', 0x0B: 'Proprietary Memory Card Slot', 0x0C: 'I/O Riser Card Slot', 0x0D: 'NuBus', 0x0E: 'PCI 66MHz Capable', 0x0F: 'AGP', 0x10: 'AGP 2X', 0x11: 'AGP 4X', 0x12: 'PCI-X', 0x13: 'AGP 8X', 0xA0: 'PC-98/C20', 0xA1: 'PC-98/C24', 0xA2: 'PC-98/E', 0xA3: 'PC-98/Local Bus', 0xA4: 'PC-98/Card', 0xA5: 'PCI Express', 0xA6: 'PCI Express x1', 0xA7: 'PCI Express x2', 0xA8: 'PCI Express x4', 0xA9: 'PCI Express x8', 0xAA: 'PCI Express x16', 0xAB: 'PCI Express Gen 2', 0xAC: 'PCI Express Gen 2 x1', 0xAD: 'PCI Express Gen 2 x2', 0xAE: 'PCI Express Gen 2 x4', 0xAF: 'PCI Express Gen 2 x8', 0xB0: 'PCI Express Gen 2 x16', 0xB1: 'PCI Express Gen 3', 0xB2: 'PCI Express Gen 3 x1', 0xB3: 'PCI Express Gen 3 x2', 0xB4: 'PCI Express Gen 3 x4', 0xB5: 'PCI Express Gen 3 x8', 0xB6: 'PCI Express Gen 3 x16', } self.add_field('slot_type', u.unpack_one("B"), unpack.format_table("{}", _slot_types)) _slot_data_bus_widths = { 0x01: 'Other', 0x02: 'Unknown', 0x03: '8 bit', 0x04: '16 bit', 0x05: '32 bit', 0x06: '64 bit', 0x07: '128 bit', 0x08: '1x or x1', 0x09: '2x or x2', 0x0A: '4x or x4', 0x0B: '8x or x8', 0x0C: '12x or x12', 0x0D: '16x or x16', 0x0E: '32x or x32', } self.add_field('slot_data_bus_width', u.unpack_one('B'), unpack.format_table("{}", _slot_data_bus_widths)) _current_usages = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Available', 0x04: 'In use', } self.add_field('current_usage', u.unpack_one('B'), unpack.format_table("{}", _current_usages)) _slot_lengths = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Short Length', 0x04: 'Long Length', } self.add_field('slot_length', u.unpack_one('B'), unpack.format_table("{}", _slot_lengths)) self.add_field('slot_id', u.unpack_one(' 0x0C: self.add_field('characteristics2', u.unpack_one('B')) self.add_field('supports_PME', bool(bitfields.getbits(self.characteristics2, 0)), "characteristics2[0]={}") self.add_field('supports_hot_plug', bool(bitfields.getbits(self.characteristics2, 1)), "characteristics2[1]={}") self.add_field('supports_smbus', bool(bitfields.getbits(self.characteristics2, 2)), "characteristics2[2]={}") if self.length > 0x0D: self.add_field('segment_group_number', u.unpack_one(' 0x05: self.add_field('flags', u.unpack_one('B')) self.add_field('abbreviated_format', bool(bitfields.getbits(self.flags, 0)), "flags[0]={}") if self.length > 0x6: u.skip(15) self.add_field('current_language', u.unpack_one('B'), self.fmtstr) except: self.decodeFailure = True print "Error parsing BIOSLanguageInformation" import traceback traceback.print_exc() self.fini() class GroupAssociations(SmbiosBaseStructure): smbios_structure_type = 14 def __init__(self, u, sm): super(GroupAssociations, self).__init__(u, sm) u = self.u try: self.add_field('group_name', u.unpack_one("B"), self.fmtstr) self.add_field('item_type', u.unpack_one('B')) self.add_field('item_handle', u.unpack_one(' 0x14: _log_header_formats = { 0: 'No header', 1: 'Type 1 log header', xrange(2, 0x7f): 'Available for future assignment', xrange(0x80, 0xff): 'BIOS vendor or OEM-specific format' } self.add_field('log_header_format', u.unpack_one("B"), unpack.format_table("{}", _log_header_formats)) if self.length > 0x15: self.add_field('num_supported_log_type_descriptors', u.unpack_one('B')) if self.length > 0x16: self.add_field('length_log_type_descriptor', u.unpack_one('B')) if self.length != (0x17 + (self.num_supported_log_type_descriptors * self.length_log_type_descriptor)): 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) print "structure length = {}".format(self.length) print "num_supported_log_type_descriptors = {}".format(self.num_supported_log_type_descriptors) print "length_log_type_descriptor = {}".format(self.length_log_type_descriptor) self.decodeFailure = True self.add_field('descriptors', tuple(EventLogDescriptor.unpack(u) for i in range(self.num_supported_log_type_descriptors)), unpack.format_each("\n{!r}")) except: self.decodeFailure = True print "Error parsing SystemEventLog" import traceback traceback.print_exc() self.fini() class EventLogDescriptor(unpack.Struct): @staticmethod def _unpack(u): _event_log_type_descriptors = { 0x00: 'Reserved', 0x01: 'Single-bit ECC memory error', 0x02: 'Multi-bit ECC memory error', 0x03: 'Parity memory error', 0x04: 'Bus time-out', 0x05: 'I/O Channel Check', 0x06: 'Software NMI', 0x07: 'POST Memory Resize', 0x08: 'POST Error', 0x09: 'PCI Parity Error', 0x0A: 'PCI System Error', 0x0B: 'CPU Failure', 0x0C: 'EISA FailSafe Timer time-out', 0x0D: 'Correctable memory log disabled', 0x0E: 'Logging disabled for a specific Event Type - too many errors of the same type received in a short amount of time', 0x0F: 'Reserved', 0x10: 'System Limit Exceeded', 0x11: 'Asynchronous hardware timer expired and issued a system reset', 0x12: 'System configuration information', 0x13: 'Hard-disk information', 0x14: 'System reconfigured', 0x15: 'Uncorrectable CPU-complex error', 0x16: 'Log Area Reset/Cleared', 0x17: 'System boot', xrange(0x18, 0x7F): 'Unused, available for assignment', xrange(0x80, 0xFE): 'Availalbe for system- and OEM-specific assignments', 0xFF: 'End of log' } yield 'log_type', u.unpack_one('B'), unpack.format_table("{}", _event_log_type_descriptors) _event_log_format = { 0x00: 'None', 0x01: 'Handle', 0x02: 'Multiple-Event', 0x03: 'Multiple-Event Handle', 0x04: 'POST Results Bitmap', 0x05: 'System Management Type', 0x06: 'Multiple-Event System Management Type', xrange(0x80, 0xFF): 'OEM assigned' } yield 'variable_data_format_type', u.unpack_one('B'), unpack.format_table("{}", _event_log_format) class PhysicalMemoryArray(SmbiosBaseStructure): smbios_structure_type = 16 def __init__(self, u, sm): super(PhysicalMemoryArray, self).__init__(u, sm) u = self.u try: if self.length > 0x4: _location_field = { 0x01: "Other", 0x02: "Unknown", 0x03: "System board or motherboard", 0x04: "ISA add-on card", 0x05: "EISA add-on card", 0x06: "PCI add-on card", 0x07: "MCA add-on card", 0x08: "PCMCIA add-on card", 0x09: "Proprietary add-on card", 0x0A: "NuBus", 0xA0: "PC-98/C20 add-on card", 0xA1: "PC-98/C24 add-on card", 0xA2: "PC-98/E add-on card", 0xA3: "PC-98/Local bus add-on card" } self.add_field('location', u.unpack_one("B"), unpack.format_table("{}", _location_field)) if self.length > 0x05: _use = { 0x01: "Other", 0x02: "Unknown", 0x03: "System memory", 0x04: "Video memory", 0x05: "Flash memory", 0x06: "Non-volatile RAM", 0x07: "Cache memory" } self.add_field('use', u.unpack_one('B'), unpack.format_table("{}", _use)) if self.length > 0x06: _error_correction = { 0x01: "Other", 0x02: "Unknown", 0x03: "None", 0x04: "Parity", 0x05: "Single-bit ECC", 0x06: "Multi-bit ECC", 0x07: "CRC" } self.add_field('memory_error_correction', u.unpack_one('B'), unpack.format_table("{}", _error_correction)) if self.length > 0x07: self.add_field('maximum_capacity', u.unpack_one(' 0x0B: self.add_field('memory_error_information_handle', u.unpack_one(' 0x0D: self.add_field('num_memory_devices', u.unpack_one(' 0x0F: self.add_field('extended_maximum_capacity', u.unpack_one(' 0x4: self.add_field('physical_memory_array_handle', u.unpack_one(" 0x6: self.add_field('memory_error_information_handle', u.unpack_one(" 0x8: self.add_field('total_width', u.unpack_one(" 0xA: self.add_field('data_width', u.unpack_one(" 0xC: self.add_field('size', u.unpack_one(" 0xE: _form_factors = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'SIMM', 0x04: 'SIP', 0x05: 'Chip', 0x06: 'DIP', 0x07: 'ZIP', 0x08: 'Proprietary Card', 0x09: 'DIMM', 0x0A: 'TSOP', 0x0B: 'Row of chips', 0x0C: 'RIMM', 0x0D: 'SODIMM', 0x0E: 'SRIMM', 0x0F: 'FB-DIMM' } self.add_field('form_factor', u.unpack_one("B"), unpack.format_table("{}", _form_factors)) if self.length > 0xF: self.add_field('device_set', u.unpack_one("B")) if self.length > 0x10: self.add_field('device_locator', u.unpack_one("B"), self.fmtstr) if self.length > 0x11: self.add_field('bank_locator', u.unpack_one("B"), self.fmtstr) if self.length > 0x12: _memory_types = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'DRAM', 0x04: 'EDRAM', 0x05: 'VRAM', 0x06: 'SRAM', 0x07: 'RAM', 0x08: 'ROM', 0x09: 'FLASH', 0x0A: 'EEPROM', 0x0B: 'FEPROM', 0x0C: 'EPROM', 0x0D: 'CDRAM', 0x0E: '3DRAM', 0x0F: 'SDRAM', 0x10: 'SGRAM', 0x11: 'RDRAM', 0x12: 'DDR', 0x13: 'DDR2', 0x14: 'DDR2 FB-DIMM', xrange(0x15, 0x17): 'Reserved', 0x18: 'DDR3', 0x19: 'FBD2' } self.add_field('memory_type', u.unpack_one("B"), unpack.format_table("{}", _memory_types)) if self.length > 0x13: self.add_field('type_detail', u.unpack_one(' 0x15: self.add_field('speed', u.unpack_one(" 0x17: self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) if self.length > 0x18: self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) if self.length > 0x19: self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr) if self.length > 0x1A: self.add_field('part_number', u.unpack_one("B"), self.fmtstr) if self.length > 0x1B: self.add_field('attributes', u.unpack_one("B")) self.add_field('rank', bitfields.getbits(self.attributes, 3, 0), "attributes[3:0]={}") if self.length > 0x1C: if self.size == 0x7FFF: self.add_field('extended_size', u.unpack_one(' 0x20: self.add_field('configured_memory_clock_speed', u.unpack_one(" 0x22: self.add_field('minimum_voltage', u.unpack_one(" 0x24: self.add_field('maximum_voltage', u.unpack_one(" 0x26: self.add_field('configured_voltage', u.unpack_one(" 0x4: _error_types = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'OK', 0x04: 'Bad read', 0x05: 'Parity error', 0x06: 'Single-bit error', 0x07: 'Double-bit error', 0x08: 'Multi-bit error', 0x09: 'Nibble error', 0x0A: 'Checksum error', 0x0B: 'CRC error', 0x0C: 'Corrected single-bit error', 0x0D: 'Corrected error', 0x0E: 'Uncorrectable error' } self.add_field('error_type', u.unpack_one("B"), unpack.format_table("{}", _error_types)) if self.length > 0x5: _error_granularity_field = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Device level', 0x04: 'Memory partition level' } self.add_field('error_granularity', u.unpack_one("B"), unpack.format_table("{}", _error_granularity_field)) if self.length > 0x6: _error_operation_field = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Read', 0x04: 'Write', 0x05: 'Partial write' } self.add_field('error_operation', u.unpack_one("B"), unpack.format_table("{}", _error_operation_field)) if self.length > 0x7: self.add_field('vendor_syndrome', u.unpack_one(" 0xB: self.add_field('memory_array_error_address', u.unpack_one(" 0xF: self.add_field('device_error_address', u.unpack_one(" 0x13: self.add_field('error_resolution', u.unpack_one(" 0x4: self.add_field('starting_address', u.unpack_one(" 0x8: self.add_field('ending_address', u.unpack_one(" 0xC: self.add_field('memory_array_handle', u.unpack_one(" 0xE: self.add_field('partition_width', u.unpack_one("B")) if self.length > 0xF: # valid if starting_address = FFFF FFFF if self.starting_address == 0xFFFFFFFF: self.add_field('extended_starting_address', u.unpack_one(" 0x17: self.add_field('extended_ending_address', u.unpack_one(" 0x4: self.add_field('starting_address', u.unpack_one(" 0x8: self.add_field('ending_address', u.unpack_one(" 0xC: self.add_field('memory_device_handle', u.unpack_one(" 0xE: self.add_field('memory_array_mapped_address_handle', u.unpack_one(" 0x10: self.add_field('partition_row_position', u.unpack_one("B")) if self.length > 0x11: self.add_field('interleave_position', u.unpack_one("B")) if self.length > 0x12: self.add_field('interleave_data_depth', u.unpack_one("B")) if self.length > 0x13: # valid if starting_address = FFFF FFFF if self.starting_address == 0xFFFFFFFF: self.add_field('extended_starting_address', u.unpack_one(" 0x1B: self.add_field('extended_ending_address', u.unpack_one(" 0x4: _pointing_device_types = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Mouse', 0x04: 'Track Ball', 0x05: 'Track Point', 0x06: 'Glide Point', 0x07: 'Touch Pad', 0x08: 'Touch Screen', 0x09: 'Optical Sensor' } self.add_field('pointing_device_type', u.unpack_one("B"), unpack.format_table("{}", _pointing_device_types)) if self.length > 0x5: _interfaces = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Serial', 0x04: 'PS/2', 0x05: 'Infared', 0x06: 'HP-HIL', 0x07: 'Bus mouse', 0x08: 'ADB (Apple Desktop Bus)', 0x09: 'Bus mouse DB-9', 0x0A: 'Bus mouse micro-DIN', 0x0B: 'USB' } self.add_field('interface', u.unpack_one("B"), unpack.format_table("{}", _interfaces)) if self.length > 0x6: self.add_field('num_buttons', u.unpack_one("B")) except: self.decodeFailure = True print "Error parsing BuiltInPointingDevice" import traceback traceback.print_exc() self.fini() class PortableBattery(SmbiosBaseStructure): smbios_structure_type = 22 def __init__(self, u, sm): super(PortableBattery, self).__init__(u, sm) u = self.u try: if self.length > 0x4: self.add_field('location', u.unpack_one("B"), self.fmtstr) if self.length > 0x5: self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) if self.length > 0x6: self.add_field('manufacturer_date', u.unpack_one("B"), self.fmtstr) if self.length > 0x7: self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) if self.length > 0x8: self.add_field('device_name', u.unpack_one("B"), self.fmtstr) if self.length > 0x9: _device_chemistry = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Lead Acid', 0x04: 'Nickel Cadmium', 0x05: 'Nickel metal hydride', 0x06: 'Lithium-ion', 0x07: 'Zinc air', 0x08: 'Lithium Polymer' } self.add_field('device_chemistry', u.unpack_one("B"), unpack.format_table("{}", _device_chemistry)) if self.length > 0xA: self.add_field('design_capacity', u.unpack_one(" 0xC: self.add_field('design_voltage', u.unpack_one(" 0xE: self.add_field('sbds_version_number', u.unpack_one("B"), self.fmtstr) if self.length > 0xF: self.add_field('max_error_battery_data', u.unpack_one("B"), self.fmtstr) if self.length > 0x10: if self.serial_number == 0: self.add_field('sbds_serial_number', u.unpack_one(" 0x12: if self.manufacturer_date == 0: self.add_field('sbds_manufacture_date', u.unpack_one(" 0x14: if self.device_chemistry == 0x02: self.add_field('sbds_device_chemistry', u.unpack_one("B"), self.fmtstr) else: u.skip(1) if self.length > 0x15: self.add_field('design_capacity_multiplier', u.unpack_one("B")) if self.length > 0x16: self.add_field('oem_specific', u.unpack_one(" 0x4: self.add_field('capabilities', u.unpack_one("B")) self.add_field('contains_watchdog_timer', bool(bitfields.getbits(self.capabilities, 5)), "capabilities[5]={}") _boot_option = { 0b00: 'Reserved, do not use', 0b01: 'Operating System', 0b10: 'System utilities', 0b11: 'Do not reboot' } self.add_field('boot_option_on_limit', bitfields.getbits(self.capabilities, 4, 3), unpack.format_table("capabilities[4:3]={}", _boot_option)) self.add_field('boot_option_after_watchdog_reset', bitfields.getbits(self.capabilities, 2, 1), unpack.format_table("capabilities[2:1]={}", _boot_option)) self.add_field('system_reset_enabled_by_user', bool(bitfields.getbits(self.capabilities, 0)), "capabilities[0]={}") if self.length > 0x5: self.add_field('reset_count', u.unpack_one(" 0x5: self.add_field('reset_limit', u.unpack_one(" 0x9: self.add_field('timer_interval', u.unpack_one(" 0xB: self.add_field('timeout', u.unpack_one(" 0x4: self.add_field('hardware_security_settings', u.unpack_one("B")) _status = { 0x00: 'Disabled', 0x01: 'Enabled', 0x02: 'Not Implemented', 0x03: 'Unknown' } self.add_field('power_on_password_status', bitfields.getbits(self.hardware_security_settings, 7, 6), unpack.format_table("hardware_security_settings[7:6]={}", _status)) self.add_field('keyboard_password_status', bitfields.getbits(self.hardware_security_settings, 5, 4), unpack.format_table("hardware_security_settings[5:4]={}", _status)) self.add_field('admin_password_status', bitfields.getbits(self.hardware_security_settings, 3, 2), unpack.format_table("hardware_security_settings0[3:2]={}", _status)) self.add_field('front_panel_reset_status', bitfields.getbits(self.hardware_security_settings, 1, 0), unpack.format_table("hardware_security_settings[1:0]={}", _status)) except: self.decodeFailure = True print "Error parsing HardwareSecurity" import traceback traceback.print_exc() self.fini() class SystemPowerControls(SmbiosBaseStructure): smbios_structure_type = 25 def __init__(self, u, sm): super(SystemPowerControls, self).__init__(u, sm) u = self.u try: if self.length > 0x4: self.add_field('next_scheduled_poweron_month', u.unpack_one("B")) self.add_field('next_scheduled_poweron_day_of_month', u.unpack_one("B")) self.add_field('next_scheduled_poweron_hour', u.unpack_one("B")) self.add_field('next_scheduled_poweron_minute', u.unpack_one("B")) self.add_field('next_scheduled_poweron_second', u.unpack_one("B")) except: self.decodeFailure = True print "Error parsing SystemPowerControls" import traceback traceback.print_exc() self.fini() class VoltageProbe(SmbiosBaseStructure): smbios_structure_type = 26 def __init__(self, u, sm): super(VoltageProbe, self).__init__(u, sm) u = self.u try: if self.length > 0x4: self.add_field('description', u.unpack_one("B"), self.fmtstr) if self.length > 0x5: self.add_field('location_and_status', u.unpack_one("B")) _status = { 0b001: 'Other', 0b010: 'Unknown', 0b011: 'OK', 0b100: 'Non-critical', 0b101: 'Critical', 0b110: 'Non-recoverable' } _location = { 0b00001: 'Other', 0b00010: 'Unknown', 0b00011: 'Processor', 0b00100: 'Disk', 0b00101: 'Peripheral Bay', 0b00110: 'System Management Module', 0b00111: 'Motherboard', 0b01000: 'Memory Module', 0b01001: 'Processor Module', 0b01010: 'Power Unit', 0b01011: 'Add-in Card' } self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status)) self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location)) if self.length > 0x6: self.add_field('max_value', u.unpack_one(" 0x8: self.add_field('min_value', u.unpack_one(" 0xA: self.add_field('resolution', u.unpack_one(" 0xC: self.add_field('tolerance', u.unpack_one(" 0xE: self.add_field('accuracy', u.unpack_one(" 0x10: self.add_field('oem_defined', u.unpack_one(" 0x14: self.add_field('nominal_value', u.unpack_one(" 0x4: self.add_field('temperature_probe_handle', u.unpack_one(" 0x6: self.add_field('device_type_and_status', u.unpack_one("B")) _status = { 0b001: 'Other', 0b010: 'Unknown', 0b011: 'OK', 0b100: 'Non-critical', 0b101: 'Critical', 0b110: 'Non-recoverable' } _type = { 0b00001: 'Other', 0b00010: 'Unknown', 0b00011: 'Fan', 0b00100: 'Centrifugal Blower', 0b00101: 'Chip Fan', 0b00110: 'Cabinet Fan', 0b00111: 'Power Supply Fan', 0b01000: 'Heat Pipe', 0b01001: 'Integrated Refrigeration', 0b10000: 'Active Cooling', 0b10001: 'Passive Cooling' } self.add_field('status', bitfields.getbits(self.device_type_and_status, 7, 5), unpack.format_table("device_type_and_status[7:5]={}", _status)) self.add_field('device_type', bitfields.getbits(self.device_type_and_status, 4, 0), unpack.format_table("device_type_and_status[4:0]={}", _type)) if self.length > 0x7: self.add_field('cooling_unit_group', u.unpack_one("B")) if self.length > 0x8: self.add_field('OEM_defined', u.unpack_one(" 0xC: self.add_field('nominal_speed', u.unpack_one(" 0xE: self.add_field('description', u.unpack_one("B"), self.fmtstr) except: self.decodeFailure = True print "Error parsing CoolingDevice" import traceback traceback.print_exc() self.fini() class TemperatureProbe(SmbiosBaseStructure): smbios_structure_type = 28 def __init__(self, u, sm): super(TemperatureProbe, self).__init__(u, sm) u = self.u try: if self.length > 0x4: self.add_field('description', u.unpack_one("B"), self.fmtstr) if self.length > 0x5: self.add_field('location_and_status', u.unpack_one("B")) _status = { 0b001: 'Other', 0b010: 'Unknown', 0b011: 'OK', 0b100: 'Non-critical', 0b101: 'Critical', 0b110: 'Non-recoverable' } _location = { 0b00001: 'Other', 0b00010: 'Unknown', 0b00011: 'Processor', 0b00100: 'Disk', 0b00101: 'Peripheral Bay', 0b00110: 'System Management Module', 0b00111: 'Motherboard', 0b01000: 'Memory Module', 0b01001: 'Processor Module', 0b01010: 'Power Unit', 0b01011: 'Add-in Card', 0b01100: 'Front Panel Board', 0b01101: 'Back Panel Board', 0b01110: 'Power System Board', 0b01111: 'Drive Back Plane' } self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status)) self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location)) if self.length > 0x6: self.add_field('maximum_value', u.unpack_one(" 0x8: self.add_field('minimum_value', u.unpack_one(" 0xA: self.add_field('resolution', u.unpack_one(" 0xC: self.add_field('tolerance', u.unpack_one(" 0xE: self.add_field('accuracy', u.unpack_one(" 0x10: self.add_field('OEM_defined', u.unpack_one(" 0x14: self.add_field('nominal_value', u.unpack_one(" 0x4: self.add_field('description', u.unpack_one("B"), self.fmtstr) if self.length > 0x5: self.add_field('location_and_status', u.unpack_one("B")) _status = { 0b001: 'Other', 0b010: 'Unknown', 0b011: 'OK', 0b100: 'Non-critical', 0b101: 'Critical', 0b110: 'Non-recoverable' } _location = { 0b00001: 'Other', 0b00010: 'Unknown', 0b00011: 'Processor', 0b00100: 'Disk', 0b00101: 'Peripheral Bay', 0b00110: 'System Management Module', 0b00111: 'Motherboard', 0b01000: 'Memory Module', 0b01001: 'Processor Module', 0b01010: 'Power Unit', 0b01011: 'Add-in Card', 0b01100: 'Front Panel Board', 0b01101: 'Back Panel Board', 0b01110: 'Power System Board', 0b01111: 'Drive Back Plane' } self.add_field('status', bitfields.getbits(self.location_and_status, 7, 5), unpack.format_table("location_and_status[7:5]={}", _status)) self.add_field('location', bitfields.getbits(self.location_and_status, 4, 0), unpack.format_table("location_and_status[4:0]={}", _location)) if self.length > 0x6: self.add_field('maximum_value', u.unpack_one(" 0x8: self.add_field('minimum_value', u.unpack_one(" 0xA: self.add_field('resolution', u.unpack_one(" 0xC: self.add_field('tolerance', u.unpack_one(" 0xE: self.add_field('accuracy', u.unpack_one(" 0x10: self.add_field('OEM_defined', u.unpack_one(" 0x14: self.add_field('nominal_value', u.unpack_one(" 0x4: self.add_field('manufacturer_name', u.unpack_one("B"), self.fmtstr) if self.length > 0x5: self.add_field('connections', u.unpack_one("B")) self.add_field('outbound_connection_enabled', bool(bitfields.getbits(self.connections, 1)), "connections[1]={}") self.add_field('inbound_connection_enabled', bool(bitfields.getbits(self.connections, 0)), "connections[0]={}") except: self.decodeFailure = True print "Error parsing OutOfBandRemoteAccess" import traceback traceback.print_exc() self.fini() class BootIntegrityServicesEntryPoint(SmbiosBaseStructure): smbios_structure_type = 31 class SystemBootInformation(SmbiosBaseStructure): smbios_structure_type = 32 def __init__(self, u, sm): super(SystemBootInformation, self).__init__(u, sm) u = self.u try: if self.length > 0xA: u.skip(6) _boot_status = { 0: 'No errors detected', 1: 'No bootable media', 2: '"normal" operating system failed to load', 3: 'Firmware-detected hardware failure, including "unknown" failure types', 4: 'Operating system-detected hardware failure', 5: 'User-requested boot, usually through a keystroke', 6: 'System security violation', 7: 'Previously-requested image', 8: 'System watchdog timer expired, causing the system to reboot', xrange(9,127): 'Reserved for future assignment', xrange(128, 191): 'Vendor/OEM-specific implementations', xrange(192, 255): 'Product-specific implementations' } self.add_field('boot_status', u.unpack_one("B"), unpack.format_table("{}", _boot_status)) except: self.decodeFailure = True print "Error parsing SystemBootInformation" import traceback traceback.print_exc() self.fini() class MemoryErrorInfo64Bit(SmbiosBaseStructure): smbios_structure_type = 33 def __init__(self, u, sm): super(MemoryErrorInfo64Bit, self).__init__(u, sm) u = self.u try: if self.length > 0x4: _error_types = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'OK', 0x04: 'Bad read', 0x05: 'Parity error', 0x06: 'Single-bit error', 0x07: 'Double-bit error', 0x08: 'Multi-bit error', 0x09: 'Nibble error', 0x0A: 'Checksum error', 0x0B: 'CRC error', 0x0C: 'Corrected single-bit error', 0x0D: 'Corrected error', 0x0E: 'Uncorrectable error' } self.add_field('error_type', u.unpack_one("B"), unpack.format_table("{}", _error_types)) if self.length > 0x5: _error_granularity_field = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Device level', 0x04: 'Memory partition level' } self.add_field('error_granularity', u.unpack_one("B"), unpack.format_table("{}", _error_granularity_field)) if self.length > 0x6: _error_operation_field = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Read', 0x04: 'Write', 0x05: 'Partial write' } self.add_field('error_operation', u.unpack_one("B"), unpack.format_table("{}", _error_operation_field)) if self.length > 0x7: self.add_field('vendor_syndrome', u.unpack_one(" 0xB: self.add_field('memory_array_error_address', u.unpack_one(" 0xF: self.add_field('device_error_address', u.unpack_one(" 0x13: self.add_field('error_resolution', u.unpack_one(" 0x4: self.add_field('description', u.unpack_one("B"), self.fmtstr) if self.length > 0x5: _type = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'National Semiconductor LM75', 0x04: 'National Semiconductor LM78', 0x05: 'National Semiconductor LM79', 0x06: 'National Semiconductor LM80', 0x07: 'National Semiconductor LM81', 0x08: 'Analog Devices ADM9240', 0x09: 'Dallas Semiconductor DS1780', 0x0A: 'Maxim 1617', 0x0B: 'Genesys GL518SM', 0x0C: 'Winbond W83781D', 0x0D: 'Holtek HT82H791' } self.add_field('device_type', u.unpack_one("B"), unpack.format_table("{}", _type)) if self.length > 0x6: self.add_field('address', u.unpack_one(" 0xA: _address_type = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'I/O Port', 0x04: 'Memory', 0x05: 'SM Bus' } self.add_field('address_type', u.unpack_one("B"), unpack.format_table("{}", _address_type)) except: self.decodeFailure = True print "Error parsing ManagementDevice" import traceback traceback.print_exc() self.fini() class ManagementDeviceComponent(SmbiosBaseStructure): smbios_structure_type = 35 def __init__(self, u, sm): super(ManagementDeviceComponent, self).__init__(u, sm) u = self.u try: if self.length > 0x4: self.add_field('description', u.unpack_one("B"), self.fmtstr) if self.length > 0x5: self.add_field('management_device_handle', u.unpack_one(" 0x7: self.add_field('component_handle', u.unpack_one(" 0x9: self.add_field('threshold_handle', u.unpack_one(" 0x4: self.add_field('lower_threshold_noncritical', u.unpack_one(" 0x6: self.add_field('upper_threshold_noncritical', u.unpack_one(" 0x8: self.add_field('lower_threshold_critical', u.unpack_one(" 0xA: self.add_field('upper_threshold_critical', u.unpack_one(" 0xC: self.add_field('lower_threshold_nonrecoverable', u.unpack_one(" 0xE: self.add_field('upper_threshold_nonrecoverable', u.unpack_one(" 0x4: _channel_type = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'RamBus', 0x04: 'SyncLink' } self.add_field('channel_type', u.unpack_one("B"), unpack.format_table("{}", _channel_type)) if self.length > 0x6: self.add_field('max_channel_load', u.unpack_one("B")) if self.length > 0x8: self.add_field('memory_device_count', u.unpack_one("B")) if self.length > 0xA: self.add_field('memory_device_load', u.unpack_one("B")) if self.length > 0xC: self.add_field('memory_device_handle', u.unpack_one(" 0x4: self.add_field('power_unit_group', u.unpack_one("B")) if self.length > 0x5: self.add_field('location', u.unpack_one("B"), self.fmtstr) if self.length > 0x6: self.add_field('device_name', u.unpack_one("B"), self.fmtstr) if self.length > 0x7: self.add_field('manufacturer', u.unpack_one("B"), self.fmtstr) if self.length > 0x8: self.add_field('serial_number', u.unpack_one("B"), self.fmtstr) if self.length > 0x9: self.add_field('asset_tag', u.unpack_one("B"), self.fmtstr) if self.length > 0xA: self.add_field('model_part_number', u.unpack_one("B"), self.fmtstr) if self.length > 0xB: self.add_field('revision_level', u.unpack_one("B"), self.fmtstr) if self.length > 0xC: self.add_field('max_power_capacity', u.unpack_one(" 0xE: self.add_field('power_supply_characteristics', u.unpack_one(" 0x10: self.add_field('input_voltage_probe_handle', u.unpack_one(" 0x12: self.add_field('cooling_device_handle', u.unpack_one(" 0x14: self.add_field('input_current_probe_handle', u.unpack_one(" 0x4: self.add_field('num_additional_information_entries', u.unpack_one("B")) if self.length > 0x5: self.add_field('additional_information_entry_length', u.unpack_one("B")) self.add_field('referenced_handle', u.unpack_one(" 0x4: self.add_field('reference_designation', u.unpack_one("B"), self.fmtstr) if self.length > 0x5: self.add_field('device_type', u.unpack_one("B")) self.add_field('device_enabled', bool(bitfields.getbits(self.device_type, 7)), "device_type[7]={}") _device_types = { 0x01: 'Other', 0x02: 'Unknown', 0x03: 'Video', 0x04: 'SCSI Controller', 0x05: 'Ethernet', 0x06: 'Token Ring', 0x07: 'Sound', 0x08: 'PATA Controller', 0x09: 'SATA Controller', 0x0A: 'SAS Controller' } self.add_field('type_of_device', bitfields.getbits(self.device_type, 6, 0), unpack.format_table("device_type[6:0]={}", _device_types)) if self.length > 0x6: self.add_field('device_type_instance', u.unpack_one("B")) if self.length > 0x7: self.add_field('segment_group_number', u.unpack_one(" 0x9: self.add_field('bus_number', u.unpack_one("B"), self.fmtstr) if self.length > 0xA: self.add_field('device_and_function_number', u.unpack_one("B")) self.add_field('device_number', bitfields.getbits(self.device_type, 7, 3), "device_and_function_number[7:3]={}") self.add_field('function_number', bitfields.getbits(self.device_type, 2, 0), "device_and_function_number[2:0]={}") except: self.decodeFailure = True print "Error parsing OnboardDevicesExtendedInformation" import traceback traceback.print_exc() self.fini() class ManagementControllerHostInterface(SmbiosBaseStructure): smbios_structure_type = 42 def __init__(self, u, sm): super(ManagementControllerHostInterface, self).__init__(u, sm) u = self.u try: if self.length > 0x4: _interface_types = { 0x00: 'Reserved', 0x01: 'Reserved', 0x02: 'KCS: Keyboard Controller Style', 0x03: '8250 UART Register Compatible', 0x04: '16450 UART Register Compatible', 0x05: '16550/16550A UART Register Compatible', 0x06: '16650/16650A UART Register Compatible', 0x07: '16750/16750A UART Register Compatible', 0x08: '16850/16850A UART Register Compatible', 0xF0: 'OEM' } self.add_field('interface_type', u.unpack_one("B"), unpack.format_table("{}", _interface_types)) if self.length > 0x5: self.add_field('mc_host_interface_data', u.unpack_rest(), self.fmtstr) except: self.decodeFailure = True print "Error parsing ManagementControllerHostInterface" import traceback traceback.print_exc() self.fini() class Inactive(SmbiosBaseStructure): smbios_structure_type = 126 def __init__(self, u, sm): super(Inactive, self).__init__(u, sm) self.fini() class EndOfTable(SmbiosBaseStructure): smbios_structure_type = 127 def __init__(self, u, sm): super(EndOfTable, self).__init__(u, sm) self.fini() class SmbiosStructureUnknown(SmbiosBaseStructure): smbios_structure_type = None def __init__(self, u, sm): super(SmbiosStructureUnknown, self).__init__(u, sm) self.fini() _smbios_structures = [ BIOSInformation, SystemInformation, BaseboardInformation, SystemEnclosure, ProcessorInformation, MemoryControllerInformation, MemoryModuleInformation, CacheInformation, PortConnectorInfo, SystemSlots, OnBoardDevicesInformation, OEMStrings, SystemConfigOptions, BIOSLanguageInformation, GroupAssociations, SystemEventLog, PhysicalMemoryArray, MemoryDevice, MemoryErrorInfo32Bit, MemoryArrayMappedAddress, MemoryDeviceMappedAddress, BuiltInPointingDevice, PortableBattery, SystemReset, HardwareSecurity, SystemPowerControls, VoltageProbe, CoolingDevice, TemperatureProbe, ElectricalCurrentProbe, OutOfBandRemoteAccess, BootIntegrityServicesEntryPoint, SystemBootInformation, MemoryErrorInfo64Bit, ManagementDevice, ManagementDeviceComponent, ManagementDeviceThresholdData, MemoryChannel, IPMIDeviceInformation, SystemPowerSupply, AdditionalInformation, OnboardDevicesExtendedInformation, ManagementControllerHostInterface, Inactive, EndOfTable, SmbiosStructureUnknown, # Must always come last ] def log_smbios_info(): with redirect.logonly(): try: sm = SMBIOS() print if sm is None: print "No SMBIOS structures found" return output = {} known_types = (0, 1) for sm_struct in sm.structures: if sm_struct.type in known_types: output.setdefault(sm_struct.type, []).append(sm_struct) if len(output) == len(known_types): break print "SMBIOS information:" for key in sorted(known_types): for s in output.get(key, ["No structure of type {} found".format(key)]): print ttypager._wrap("{}: {}".format(key, s)) except: print "Error parsing SMBIOS information:" import traceback traceback.print_exc() def dump_raw(): try: sm = SMBIOS() if sm: s = "SMBIOS -- Raw bytes and structure decode.\n\n" s += str(sm.header) + '\n' s += bits.dumpmem(sm._header_memory) + '\n' s += "Raw bytes for the SMBIOS structures\n" s += bits.dumpmem(sm._structure_memory) + '\n' for sm_struct in sm.structures: s += str(sm_struct) + '\n' s += bits.dumpmem(sm_struct.raw_data) s += "Strings:\n" for n in range(1, len(getattr(sm_struct, "strings", [])) + 1): s += str(sm_struct.fmtstr(n)) + '\n' s += bits.dumpmem(sm_struct.raw_strings) + '\n' else: s = "No SMBIOS structures found" ttypager.ttypager_wrap(s, indent=False) except: print "Error parsing SMBIOS information:" import traceback traceback.print_exc() def dump(): try: sm = SMBIOS() if sm: s = str(sm) else: s = "No SMBIOS structures found" ttypager.ttypager_wrap(s, indent=False) except: print "Error parsing SMBIOS information:" import traceback traceback.print_exc() def annex_a_conformance(): try: sm = SMBIOS() # check: 1. The table anchor string "_SM_" is present in the address range 0xF0000 to 0xFFFFF on a 16-byte bound def table_entry_point_verification(): ''' Verify table entry-point''' if (sm.header.length < 0x1F): print "Failure: Table entry-point - The entry-point Length must be at least 0x1F" if sm.header.checksum != 0: print "Failure: Table entry-point - The entry-point checksum must evaluate to 0" if ((sm.header.major_version < 2) and (sm.header.minor_version < 4)): print "Failure: Table entry-point - SMBIOS version must be at least 2.4" if (sm.header.intermediate_anchor_string == '_DMI_'): print "Failure: Table entry-point - The Intermediate Anchor String must be '_DMI_'" if (sm.header.intermediate_checksum != 0): print "Failure: Table entry-point - The Intermediate checksum must evaluate to 0" #check: 3. The structure-table is traversable and conforms to the entry-point specifications: def req_structures(): '''Checks for required structures and corresponding data''' types_present = [sm.structures[x].smbios_structure_type for x in range(len(sm.structures))] required = [0, 1, 4, 7, 9, 16, 17, 19, 31, 32] for s in required: if s not in set(types_present): print "Failure: Type {} required but not found".format(s) else: if s == 0: if types_present.count(s) > 1: print "Failure: Type {} - One and only one structure of this type must be present.".format(s) if sm.structure_type(s).length < 0x18: print "Failure: Type {} - The structure Length field must be at least 0x18".format(s) if sm.structure_type(s).version is None: print "Failure: Type {} - BIOS Version string must be present and non-null.".format(s) if sm.structure_type(s).release_date is None: print "Failure: Type {} - BIOS Release Date string must be present, non-null, and include a 4-digit year".format(s) if bitfields.getbits(sm.structure_type(s).characteristics, 3, 0) != 0 or bitfields.getbits(sm.structure_type(s).characteristics, 31, 4) == 0: 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) elif s == 1: if types_present.count(s) > 1: print "Failure: Type {} - One and only one structure of this type must be present.".format(s) if sm.structure_type(s).length < 0x1B: print "Failure: Type {} - The structure Length field must be at least 0x1B".format(s) if sm.structure_type(s).manufacturer == None: print "Failure: Type {} - Manufacturer string must be present and non-null.".format(s) if sm.structure_type(s).product_name == None: print "Failure: Type {} - Product Name string must be present and non-null".format(s) if sm.structure_type(s).uuid == '00000000 00000000' and sm.structure_type(s).uuid == 'FFFFFFFF FFFFFFFF': print "Failure: Type {} - UUID field must be neither 00000000 00000000 nor FFFFFFFF FFFFFFFF.".format(s) if sm.structure_type(s).wakeup_type == 00 and sm.structure_type(s).wakeup_type == 0x02: print "Failure: Type {} - Wake-up Type field must be neither 00h (Reserved) nor 02h (Unknown).".format(s) # continue for remaining required types # check remaining conformance guidelines table_entry_point_verification() req_structures() except: print "Error checking ANNEX A conformance guidelines" import traceback traceback.print_exc()