qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

smbios.py2 (110610B)


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