Пример #1
0
def idt(argv):
    if (2 == len(argv)):
        logger().log( "[CHIPSEC] Dumping IDT of %d CPU threads" % chipsec_util._cs.msr.get_cpu_thread_count() )
        chipsec_util._cs.msr.IDT_all( 4 )
    elif (3 == len(argv)):
        tid = int(argv[2],16)
        chipsec_util._cs.msr.IDT( tid, 4 )
Пример #2
0
    def write_byte( self, target_address, offset, value ):
        # clear status bits
        self.cs.write_register( self.smb_reg_status, 0xFF )

        # SMBus txn RW direction = Write, SMBus slave address = target_address
        hst_sa = 0x0
        hst_sa = self.cs.set_register_field( self.smb_reg_address, hst_sa, 'RW', SMBUS_COMMAND_WRITE )
        hst_sa = self.cs.set_register_field( self.smb_reg_address, hst_sa, 'Address', target_address, True )
        self.cs.write_register( self.smb_reg_address, hst_sa )
        # command data = byte offset (bus txn address)
        self.cs.write_register_field( self.smb_reg_command, 'DataOffset', offset )
        # write the data
        self.cs.write_register_field( self.smb_reg_data0, 'Data', value )
        # command = Byte Data
        #if self.cs.register_has_field( self.smb_reg_control, 'SMB_CMD' ):
        self.cs.write_register_field( self.smb_reg_control, 'SMB_CMD', SMBUS_COMMAND_BYTE_DATA )
        # send SMBus txn
        self.cs.write_register_field( self.smb_reg_control, 'START', 1 )

        # wait for cycle to complete
        if not self._wait_for_cycle(): return False
        # clear status bits
        self.cs.write_register( self.smb_reg_status, 0xFF )
        # clear address/offset registers
        #chipsec.chipset.write_register( self.cs, self.smb_reg_address, 0x0 )
        #chipsec.chipset.write_register( self.cs, self.smb_reg_command, 0x0 )
        if logger().HAL: logger().log( "[smbus] write to device %X off %X = %X" % (target_address, offset, value) )
        return True
Пример #3
0
 def delete_EFI_variable( self, name, guid, attrs=None ):
     if logger().UTIL_TRACE or logger().VERBOSE:
        logger().log( '[uefi] Deleting EFI variable:' )
        logger().log( 'Name: %s' % name )
        logger().log( 'GUID: %s' % guid )
        if attrs is not None: logger().log( 'Attributes: %s' % attrs )
     return self.helper.set_EFI_variable( name, guid, None, attrs )
Пример #4
0
 def va2pa( self, va ):
     (pa, error_code) = self.helper.va2pa( va )
     if logger().HAL: logger().log( '[mem] VA (0x%016X) -> PA (0x%016X)' % (va, pa) )
     if error_code:
         logger().log( '[mem] Looks like VA (0x%016X) not mapped' % (va) )
         return 
     return pa
Пример #5
0
 def loadHelpers(self):
     if logger().VERBOSE:
         logger().log("======== Load Helper for %s ===========" % platform.system().lower())
     if chipsec.file.main_is_frozen():
         self.loadHelpersFromEXE()
     else:
         self.loadHelpersFromFileSystem()
Пример #6
0
 def get_table_list_from_SDT(self, sdt, is_xsdt):
     logger().log( 'Getting table list from entries in %s' % ('XSDT' if is_xsdt else 'RSDT') )
     for a in sdt.Entries:
         _sig = self.cs.mem.read_physical_mem( a, ACPI_TABLE_SIG_SIZE )
         if _sig not in ACPI_TABLES.keys():
             logger().warn( 'Unknown ACPI table signature: %s' % _sig )
         self.tableList[ _sig ].append(a)
Пример #7
0
    def main(self, argv):
        global _cs
        #import traceback
        if self.CHIPSEC_LOADED_AS_EXE:
            import zipfile
            myzip = zipfile.ZipFile("library.zip")
            cmds = map( self.map_modname_zip, filter(self.f_mod_zip, myzip.namelist()) )
        else:
            #traceback.print_stack()
            mydir = os.path.dirname(__file__)
            cmds_dir = os.path.join(mydir,os.path.join("chipsec","utilcmd"))
            cmds = map( self.map_modname, filter(self.f_mod, os.listdir(cmds_dir)) )

        #print "[CHIPSEC] Loaded command-line extensions:"
        #print '   %s' % cmds
        #print ' '
        exit_code = 0
        module = None
        for cmd in cmds:
            try:
                #exec 'from chipsec.utilcmd.' + cmd + ' import *'
                cmd_path = 'chipsec.utilcmd.' + cmd
                module = importlib.import_module( cmd_path )
                cu = getattr(module, 'chipsec_util')
                self.commands.update(cu.commands)
            except ImportError, msg:
                logger().error( "Couldn't import util command extension '%s'" % cmd )
                raise ImportError, msg
Пример #8
0
 def compress_EFI_binary( self, uncompressed_name, compressed_name, compression_type ):
     if logger().HAL: logger().log( "[uefi] compressing EFI binary (type = 0x%X)\n       %s ->\n       %s" % (compression_type,uncompressed_name,compressed_name) )
     if compression_type in COMPRESSION_TYPES:
         return self.cs.helper.compress_file( uncompressed_name, compressed_name, compression_type )
     else: 
         logger().error( 'Unknown EFI compression type 0x%X' % compression_type )
         return None
Пример #9
0
def gdt(argv):
    if (2 == len(argv)):
       logger().log( "[CHIPSEC] Dumping GDT of %d CPU threads" % _cs.msr.get_cpu_thread_count() )
       _cs.msr.GDT_all( 4 )
    elif (3 == len(argv)):
       tid = int(argv[2],16)
       _cs.msr.GDT( tid, 4 )
Пример #10
0
def mmio(argv):

    t = time.time()

    if 3 > len(argv):
        print usage
        return

    op = argv[2]
    t = time.time()

    if "list" == op:
        list_MMIO_BARs(chipsec_util._cs)
    elif "dump" == op:
        bar = argv[3].upper()
        logger().log("[CHIPSEC] Dumping %s MMIO space.." % bar)
        dump_MMIO_BAR(chipsec_util._cs, bar)
    elif "read" == op:
        bar = argv[3].upper()
        off = int(argv[4], 16)
        reg = read_MMIO_BAR_reg(chipsec_util._cs, bar, off)
        logger().log("[CHIPSEC] Read %s + 0x%X: 0x%08X" % (bar, off, reg))
    elif "write" == op:
        bar = argv[3].upper()
        off = int(argv[4], 16)
        reg = int(argv[5], 16)
        logger().log("[CHIPSEC] Write %s + 0x%X: 0x%08X" % (bar, off, reg))
        write_MMIO_BAR_reg(chipsec_util._cs, bar, off, reg)
    else:
        logger().error("unknown command-line option '%.32s'" % ucode_op)
        print usage
        return

    logger().log("[CHIPSEC] (mmio) time elapsed %.3f" % (time.time() - t))
Пример #11
0
    def read_byte( self, target_address, offset ):
        # clear status bits
        chipsec.chipset.write_register( self.cs, self.smb_reg_status, 0xFF )

        # SMBus txn RW direction = Read, SMBus slave address = target_address
        hst_sa = 0x0
        hst_sa = chipsec.chipset.set_register_field( self.cs, self.smb_reg_address, hst_sa, 'RW', SMBUS_COMMAND_READ )
        hst_sa = chipsec.chipset.set_register_field( self.cs, self.smb_reg_address, hst_sa, 'Address', target_address, True )
        chipsec.chipset.write_register( self.cs, self.smb_reg_address, hst_sa )
        # command data = byte offset (bus txn address)
        chipsec.chipset.write_register_field( self.cs, self.smb_reg_command, 'DataOffset', offset )
        # command = Byte Data
        #if chipsec.chipset.register_has_field( self.cs, self.smb_reg_control, 'SMB_CMD' ):
        chipsec.chipset.write_register_field( self.cs, self.smb_reg_control, 'SMB_CMD', SMBUS_COMMAND_BYTE_DATA )
        # send SMBus txn
        chipsec.chipset.write_register_field( self.cs, self.smb_reg_control, 'START', 1 )

        # wait for cycle to complete
        if not self._wait_for_cycle(): return 0xFF
        # read the data
        value = chipsec.chipset.read_register_field( self.cs, self.smb_reg_data0, 'Data' )
        # clear status bits
        chipsec.chipset.write_register( self.cs, self.smb_reg_status, 0xFF )
        # clear address/offset registers
        #chipsec.chipset.write_register( self.cs, self.smb_reg_address, 0x0 )
        #chipsec.chipset.write_register( self.cs, self.smb_reg_command, 0x0 )
        if logger().VERBOSE: logger().log( "[smbus] read device %X off %X = %X" % (target_address, offset, value) )
        return value
Пример #12
0
 def is_SMBus_supported( self ):
     (did,vid) = self.cs.get_DeviceVendorID( 'SMBUS' )
     if logger().HAL: logger().log( "[smbus] SMBus Controller (DID,VID) = (0x%04X,0x%04X)" % (did,vid) )
     if (0x8086 == vid): return True
     else:
         logger().error( "Unknown SMBus Controller (DID,VID) = (0x%04X,0x%04X)" % (did,vid) )
         return False
Пример #13
0
 def read_EFI_variables( self, efi_var_store, authvars ):
     if ( efi_var_store is None ):
         logger().error( 'efi_var_store is None' )
         return None
     variables = EFI_VAR_DICT[ self._FWType ]['func_getefivariables']( efi_var_store )
     if logger().UTIL_TRACE: print_sorted_EFI_variables( variables )
     return variables
Пример #14
0
def parse_script( script, log_script=False ):
    off                    = 0
    entry_type             = 0
    s3_boot_script_entries = []
    len_s                  = len(script)

    if log_script: logger().log( '[uefi] +++ S3 Resume Boot-Script +++\n' )
    script_type,script_header_length = id_s3bootscript_type( script, log_script )
    off += script_header_length

    while (off < len_s) and (entry_type != S3BootScriptOpcode.EFI_BOOT_SCRIPT_TERMINATE_OPCODE):
        entry_type,s3script_entry = parse_s3bootscript_entry( script_type, script, off, log_script )
        # couldn't parse the next entry - return what has been parsed so far
        if s3script_entry is None: return s3_boot_script_entries
        s3_boot_script_entries.append( s3script_entry )
        off += s3script_entry.length

    if log_script: logger().log( '[uefi] +++ End of S3 Resume Boot-Script +++' )

    if logger().HAL: logger().log( '[uefi] S3 Resume Boot-Script size: 0x%X' % off )
    if logger().VERBOSE: 
        logger().log( '\n[uefi] [++++++++++ S3 Resume Boot-Script Buffer ++++++++++]' )
        print_buffer( script[ : off ] )

    return s3_boot_script_entries
Пример #15
0
def parse_uefi_section( _uefi, data, Size, offset, polarity, parent_offset, parent_path, decode_log_path ):
    sec_offset, next_sec_offset, SecName, SecType, SecBody, SecHeaderSize = NextFwFileSection(data, Size, offset, polarity)
    secn = 0
    ui_string = None
    efi_file = None
    while next_sec_offset != None:
        if (SecName != None):
            save_section_info( parent_offset + sec_offset, SecName, SecType, decode_log_path )
            sec_fs_name = "%02d_%s" % (secn, SecName)
            section_path = os.path.join(parent_path, sec_fs_name)
            if (SecType in (EFI_SECTION_PE32, EFI_SECTION_TE, EFI_SECTION_PIC, EFI_SECTION_COMPATIBILITY16)):
                type2ext = {EFI_SECTION_PE32: 'pe32', EFI_SECTION_TE: 'te', EFI_SECTION_PIC: 'pic', EFI_SECTION_COMPATIBILITY16: 'c16'}
                sec_fs_name = "%02d_%s.%s.efi" % (secn, SecName, type2ext[SecType])
                if ui_string != None:
                    sec_fs_name = ui_string
                    ui_string = None
                efi_file = sec_fs_name
                section_path = os.path.join(parent_path, sec_fs_name)
                write_file( section_path, SecBody[SecHeaderSize:] )
            else:
                write_file( section_path, SecBody[SecHeaderSize:] )
                if (SecType == EFI_SECTION_USER_INTERFACE):
                    ui_string = unicode(SecBody[SecHeaderSize:], "utf-16-le")[:-1]
                    if (ui_string[-4:] != '.efi'): ui_string = "%s.efi" % ui_string
                    #print ui_string
                    if efi_file != None:
                        os.rename(os.path.join(parent_path, efi_file), os.path.join(parent_path, ui_string))
                        efi_file = None
            if (SecType in (EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED, EFI_SECTION_FIRMWARE_VOLUME_IMAGE)):
                section_dir_path = "%s.dir" % section_path
                os.makedirs( section_dir_path )
                if   (SecType == EFI_SECTION_COMPRESSION):
                    UncompressedLength, CompressionType = struct.unpack(EFI_COMPRESSION_SECTION, SecBody[SecHeaderSize:SecHeaderSize+EFI_COMPRESSION_SECTION_size])
                    decompressed = decompress_section_data(_uefi, section_dir_path, sec_fs_name, SecBody[SecHeaderSize+EFI_COMPRESSION_SECTION_size:], CompressionType)
                    if decompressed:
                        parse_uefi_section(_uefi, decompressed, len(decompressed), 0, polarity, 0, section_dir_path, decode_log_path)
                        pass
                elif (SecType == EFI_SECTION_GUID_DEFINED):
                    # TODO: decode section based on its GUID
                    # Only CRC32 guided sectioni can be decoded for now
                    guid0, guid1, guid2, guid3, DataOffset, Attributes = struct.unpack(EFI_GUID_DEFINED_SECTION, SecBody[SecHeaderSize:SecHeaderSize+EFI_GUID_DEFINED_SECTION_size])
                    sguid = guid_str(guid0, guid1, guid2, guid3)
                    logger().log("\t\t\tDefinition guid: %s\n" % sguid +\
                                 "\t\t\tData offset    : 0x%04X\n" % DataOffset +\
                                 "\t\t\tAttributes     : 0x%04X\n" % Attributes \
                                 )
                    if (sguid == EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID):
                        parse_uefi_section(_uefi, SecBody[DataOffset:], Size - DataOffset, 0, polarity, 0, section_dir_path, decode_log_path)
                    elif (sguid == LZMA_CUSTOM_DECOMPRESS_GUID):
                        decompressed = decompress_section_data(_uefi, section_dir_path, sec_fs_name, SecBody[DataOffset:], 2)
                        if decompressed:
                            parse_uefi_section(_uefi, decompressed, len(decompressed), 0, polarity, 0, section_dir_path, decode_log_path)
                    #else:
                    #   write_file( os.path.join(section_dir_path, "%s-%04X" % (sguid, Attributes)), SecBody[DataOffset:] )
                    pass
                elif (SecType == EFI_SECTION_FIRMWARE_VOLUME_IMAGE):
                    parse_uefi_region(_uefi, SecBody[SecHeaderSize:], section_dir_path)
        sec_offset, next_sec_offset, SecName, SecType, SecBody, SecHeaderSize = NextFwFileSection(data, Size, next_sec_offset, polarity)
        secn = secn + 1
Пример #16
0
 def write_range( self, start_offset, buffer ):
     size = len(buffer)
     for i in range(size):
         self.write_memory( start_offset + i, ord(buffer[i]) )
     if logger().HAL:
         logger().log( "[ec] write EC memory to offset %X size %X:" % (start_offset, size) )
         print_buffer( buffer )
     return True
Пример #17
0
 def read_range( self, target_address, start_offset, size ):
     buffer = [chr(0xFF)]*size
     for i in range (size):
         buffer[i] = chr( self.read_byte( target_address, start_offset + i ) )
     if logger().HAL:
         logger().log( "[smbus] reading %u bytes from device 0x%X at offset %X" % (size, target_address, start_offset) )
         #print_buffer( buffer )
     return buffer
Пример #18
0
 def write_range( self, target_address, start_offset, buffer ):
     size = len(buffer)
     for i in range(size):
         self.write_byte( target_address, start_offset + i, ord(buffer[i]) )
     if logger().HAL:
         logger().log( "[smbus] writing %u bytes to device 0x%X at offset %X" % (size, target_address, start_offset) )
         #print_buffer( buffer )
     return True
Пример #19
0
 def detect( self ):
     _dimms = []
     for d in SPD_DIMMS:
         if self.isSPDPresent( d ): _dimms.append( d )
     if logger().HAL: 
         logger().log( "Detected the following SPD devices:" )
         for _dimm in _dimms: logger().log( "%s: 0x%02X" % (SPD_DIMMS[_dimm],_dimm) )
     return _dimms 
Пример #20
0
 def stop( self, start_driver ):
     if not self.filecmds is None:
         self.filecmds.Save()
     if not self.helper.stop( start_driver ):
         logger().warn("failed to stop OS helper") 
     else:
         if not self.helper.delete( start_driver ):
             logger().warn("failed to delete OS helper")
Пример #21
0
 def set_EFI_variable( self, name, guid, var, attrs=None ):
     if logger().UTIL_TRACE or logger().VERBOSE:
        logger().log( '[uefi] Writing EFI variable:' )
        logger().log( 'Name: %s' % name )
        logger().log( 'GUID: %s' % guid )
        if attrs is not None: logger().log( 'Attributes: %s' % attrs )
        #print_buffer( var )
     return self.helper.set_EFI_variable( name, guid, var, attrs )
Пример #22
0
def platform(argv):

    try:
        print_supported_chipsets()
        logger().log("")
        chipsec_util._cs.print_chipset()
    except UnknownChipsetError, msg:
        logger().error( msg )
Пример #23
0
 def display_SPI_Protected_Ranges( self ):
     logger().log( "SPI Protected Ranges" )
     logger().log( "------------------------------------------------------------" )
     logger().log( "PRx (offset) | Value    | Base     | Limit    | WP? | RP?" )
     logger().log( "------------------------------------------------------------" )
     for j in range(5):
        (base,limit,wpe,rpe,pr_reg_off,pr_reg_value) = self.get_SPI_Protected_Range( j )
        logger().log( "PR%d (%02X)     | %08X | %08X | %08X | %d   | %d " % (j,pr_reg_off,pr_reg_value,base,limit,wpe,rpe) )
Пример #24
0
 def get_EFI_variable( self, name, guid, filename=None ):
     var = self.helper.get_EFI_variable( name, guid )
     if var:
         if filename: write_file( filename, var )
         if logger().UTIL_TRACE or logger().VERBOSE:
             logger().log( '[uefi] EFI variable %s:%s :' % (guid, name) )
             print_buffer( var )
     return var
Пример #25
0
def read_ucode_file( ucode_filename ):
    ucode_buf = read_file( ucode_filename )
    if (ucode_filename.endswith('.pdb')):
        if logger().VERBOSE:
            logger().log( "[ucode] PDB file '%.256s' has ucode update header (size = 0x%X)" % (ucode_filename, UCODE_HEADER_SIZE) )
        dump_ucode_update_header( ucode_buf )
        return ucode_buf[UCODE_HEADER_SIZE:]
    else:
        return ucode_buf
Пример #26
0
def helper():
    global _helper
    if _helper == None:
        try:
            _helper  = OsHelper()
        except BaseException, msg:
            logger().error( str(msg) )
            if logger().VERBOSE: logger().log_bad(traceback.format_exc())
            raise
Пример #27
0
 def read_phys_mem_byte_64(self, phys_address_hi, phys_address_lo ):
     out_buf = self.read_phys_mem_64( phys_address_hi, phys_address_lo, 1 )
     try:
         value = struct.unpack( 'B', out_buf.raw )[0]
     except:
         raise MemoryAccessError, "read_phys_mem did not return 1 Byte"
     if logger().VERBOSE:
         logger().log( '[mem] byte at PA = 0x%08X_%08X: 0x%02X' % (phys_address_hi, phys_address_lo, value) )
     return value
Пример #28
0
 def read_phys_mem_word_64(self, phys_address_hi, phys_address_lo ):
     out_buf = self.read_phys_mem_64( phys_address_hi, phys_address_lo, 2 )
     try:
         value = struct.unpack( 'H', out_buf.raw )[0]
     except:
         raise MemoryAccessError, "read_phys_mem did not return hex word"
     if logger().VERBOSE:
         logger().log( '[mem] word at PA = 0x%08X_%08X: 0x%04X' % (phys_address_hi, phys_address_lo, value) )
     return value
Пример #29
0
 def update_ucode_all_cpus(self, ucode_file ):
     if not ( os.path.exists(ucode_file) and os.path.isfile(ucode_file) ):
         logger().error( "Ucode file not found: '%.256s'" % ucode_file )
         return False
     ucode_buf = read_ucode_file( ucode_file )
     if (ucode_buf is not None) and (len(ucode_buf) > 0):
         for tid in range(self.get_cpu_thread_count()):
             self.load_ucode_update( tid, ucode_buf )
     return True
Пример #30
0
 def write_range( self, target_address, start_offset, buffer ):
     size = len(buffer)
     smbus_io_base = self.get_SMBus_Base_Address()
     for i in range(size):
         self._write_byte( smbus_io_base, target_address, start_offset + i, ord(buffer[i]) )
     if logger().VERBOSE:
         logger().log( "[smbus] write device %X to offset %X size %X:" % (target_address, start_offset, size) )
         print_buffer( buffer )
     return True
Пример #31
0
def decode_s3bs_opcode(data):
    opcode = None
    size = None
    width = None
    count = None
    value = None
    mask = None

    op = None
    opcode, = struct.unpack('<B', data[:1])
    try:
        if logger().VERBOSE: logger().log(script_opcodes[opcode])
    except:
        pass
    if S3BootScriptOpcode.EFI_BOOT_SCRIPT_IO_WRITE_OPCODE == opcode:
        frmt = '<BBHIQ'
        size = struct.calcsize(frmt)
        opcode, width, address, alignment, count = struct.unpack(
            frmt, data[:size])
        op = op_io_pci_mem(opcode, size, width, address, count, data[size:],
                           value, mask)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE == opcode:
        frmt = '<BBHIQQ'
        size = struct.calcsize(frmt)
        opcode, width, address, alignment, value, mask = struct.unpack(
            frmt, data[:size])
        op = op_io_pci_mem(opcode, size, width, address, count, None, value,
                           mask)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE == opcode:
        frmt = '<BBHIQQ'
        size = struct.calcsize(frmt)
        opcode, width, alignment1, alignment2, address, count = struct.unpack(
            frmt, data[:size])
        op = op_io_pci_mem(opcode, size, width, address, count, data[size:],
                           value, mask)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE == opcode:
        frmt = '<BBHIQQQ'
        size = struct.calcsize(frmt)
        opcode, width, alignment1, alignment2, address, value, mask = struct.unpack(
            frmt, data[:size])
        op = op_io_pci_mem(opcode, size, width, address, count, None, value,
                           mask)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE == opcode:
        frmt = '<BBHIQQ'
        size = struct.calcsize(frmt)
        opcode, width, alignment1, alignment2, address, count = struct.unpack(
            frmt, data[:size])
        op = op_io_pci_mem(opcode, size, width, address, count, data[size:],
                           value, mask)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE == opcode:
        frmt = '<BBHIQQQ'
        size = struct.calcsize(frmt)
        opcode, width, alignment1, alignment2, address, value, mask = struct.unpack(
            frmt, data[:size])
        op = op_io_pci_mem(opcode, size, width, address, count, None, value,
                           mask)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE == opcode:
        frmt = '<BBQBB'
        size = struct.calcsize(frmt)
        opcode, slave_address, command, operation, peccheck = struct.unpack(
            frmt, data[:size])
        op = op_smbus_execute(opcode, size, width, address, count, data[size:],
                              value, mask)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_STALL_OPCODE == opcode:
        frmt = '<BBQ'
        size = struct.calcsize(frmt)
        opcode, dummy, duration = struct.unpack(frmt, data[:size])
        op = op_stall(opcode, size, duration)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_DISPATCH_OPCODE == opcode:
        frmt = '<BBHIQ'
        size = struct.calcsize(frmt)
        opcode, dummy1, dummy2, dummy3, entrypoint = struct.unpack(
            frmt, data[:size])
        op = op_dispatch(opcode, size, entrypoint)
    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_TERMINATE_OPCODE == opcode:
        frmt = '<B'
        size = struct.calcsize(frmt)
        opcode, = struct.unpack(frmt, data[:size])
        op = op_terminate(opcode, size)
    else:
        op = op_unknown(opcode, 1)
        if logger().VERBOSE: logger().warn('Unrecognized opcode %X' % opcode)

    return op
Пример #32
0
def parse_spi_flash_descriptor(cs, rom):
    if not (type(rom) == str):
        logger().error('Invalid fd object type %s' % type(rom))
        return

    pos = rom.find(SPI_FLASH_DESCRIPTOR_SIGNATURE)
    if (-1 == pos or pos < 0x10):
        logger().error(
            'Valid SPI flash descriptor is not found (should have signature %08X)'
            % struct.unpack('=I', SPI_FLASH_DESCRIPTOR_SIGNATURE))
        return None

    fd_off = pos - 0x10
    logger().log('[spi_fd] Valid SPI flash descriptor found at offset 0x%08X' %
                 fd_off)

    logger().log('')
    logger().log('########################################################')
    logger().log('# SPI FLASH DESCRIPTOR')
    logger().log('########################################################')
    logger().log('')

    fd = rom[fd_off:fd_off + SPI_FLASH_DESCRIPTOR_SIZE]
    fd_sig = struct.unpack_from('=I', fd[0x10:0x14])

    logger().log('+ 0x0000 Reserved : %016s' %
                 fd[0x0:0xF].encode('hex').upper())
    logger().log('+ 0x0010 Signature: 0x%08X' % fd_sig)

    #
    # Flash Descriptor Map Section
    #
    flmap0 = struct.unpack_from('=I', fd[0x14:0x18])[0]
    flmap1 = struct.unpack_from('=I', fd[0x18:0x1C])[0]
    flmap2 = struct.unpack_from('=I', fd[0x1C:0x20])[0]
    cs.print_register('FLMAP0', flmap0)
    cs.print_register('FLMAP1', flmap1)
    cs.print_register('FLMAP2', flmap2)

    fcba = cs.get_register_field('FLMAP0', flmap0, 'FCBA')
    nc = cs.get_register_field('FLMAP0', flmap0, 'NC')
    frba = cs.get_register_field('FLMAP0', flmap0, 'FRBA')
    fcba = fcba << 4
    frba = frba << 4
    nc += 1
    logger().log('')
    logger().log('+ 0x0014 Flash Descriptor Map:')
    logger().log('========================================================')
    logger().log('  Flash Component Base Address: 0x%08X' % fcba)
    logger().log('  Flash Region Base Address   : 0x%08X' % frba)
    logger().log('  Number of Flash Components  : %d' % nc)

    nr = spi.SPI_REGION_NUMBER_IN_FD
    if cs.register_has_field('FLMAP0', 'NR'):
        nr = cs.get_register_field('FLMAP0', flmap0, 'NR')
        if nr == 0:
            logger().warn(
                'only 1 region (FD) is found. Looks like flash descriptor binary is from Skylake platform or later. Try with option --platform'
            )
        nr += 1
        logger().log('  Number of Regions           : %d' % nr)

    fmba = cs.get_register_field('FLMAP1', flmap1, 'FMBA')
    nm = cs.get_register_field('FLMAP1', flmap1, 'NM')
    fpsba = cs.get_register_field('FLMAP1', flmap1, 'FPSBA')
    psl = cs.get_register_field('FLMAP1', flmap1, 'PSL')
    fmba = fmba << 4
    fpsba = fpsba << 4
    logger().log('  Flash Master Base Address   : 0x%08X' % fmba)
    logger().log('  Number of Masters           : %d' % nm)
    logger().log('  Flash PCH Strap Base Address: 0x%08X' % fpsba)
    logger().log('  PCH Strap Length            : 0x%X' % psl)

    fcpusba = cs.get_register_field('FLMAP2', flmap2, 'FCPUSBA')
    cpusl = cs.get_register_field('FLMAP2', flmap2, 'CPUSL')
    logger().log('  Flash CPU Strap Base Address: 0x%08X' % fcpusba)
    logger().log('  CPU Strap Length            : 0x%X' % cpusl)

    #
    # Flash Descriptor Component Section
    #
    logger().log('')
    logger().log('+ 0x%04X Component Section:' % fcba)
    logger().log('========================================================')

    flcomp = struct.unpack_from('=I', fd[fcba + 0x0:fcba + 0x4])[0]
    logger().log('+ 0x%04X FLCOMP   : 0x%08X' % (fcba, flcomp))
    flil = struct.unpack_from('=I', fd[fcba + 0x4:fcba + 0x8])[0]
    logger().log('+ 0x%04X FLIL     : 0x%08X' % (fcba + 0x4, flil))
    flpb = struct.unpack_from('=I', fd[fcba + 0x8:fcba + 0xC])[0]
    logger().log('+ 0x%04X FLPB     : 0x%08X' % (fcba + 0x8, flpb))

    #
    # Flash Descriptor Region Section
    #
    logger().log('')
    logger().log('+ 0x%04X Region Section:' % frba)
    logger().log('========================================================')

    flregs = [None] * nr
    for r in range(nr):
        flreg_off = frba + r * 4
        flreg = struct.unpack_from('=I', fd[flreg_off:flreg_off + 0x4])[0]
        if not cs.is_register_defined('FLREG%d' % r): continue
        base = cs.get_register_field(
            ('FLREG%d' % r), flreg, 'RB') << spi.SPI_FLA_SHIFT
        limit = cs.get_register_field(
            ('FLREG%d' % r), flreg, 'RL') << spi.SPI_FLA_SHIFT
        notused = '(not used)' if base > limit or flreg == 0xFFFFFFFF else ''
        flregs[r] = (flreg, base, limit, notused)
        logger().log('+ 0x%04X FLREG%d   : 0x%08X %s' %
                     (flreg_off, r, flreg, notused))
        #cs.print_register(('FLREG%d' % r), flreg)

    logger().log('')
    logger().log('Flash Regions')
    logger().log('--------------------------------------------------------')
    logger().log(' Region                | FLREGx    | Base     | Limit   ')
    logger().log('--------------------------------------------------------')
    for r in range(nr):
        if flregs[r]:
            logger().log('%d %-020s | %08X  | %08X | %08X %s' %
                         (r, spi.SPI_REGION_NAMES[r], flregs[r][0],
                          flregs[r][1], flregs[r][2], flregs[r][3]))

    #
    # Flash Descriptor Master Section
    #
    logger().log('')
    logger().log('+ 0x%04X Master Section:' % fmba)
    logger().log('========================================================')

    flmstrs = [None] * nm  #spi.SPI_MASTER_NUMBER_IN_FD
    for m in range(nm):
        flmstr_off = fmba + m * 4
        flmstr = struct.unpack_from('=I', fd[flmstr_off:flmstr_off + 0x4])[0]
        master_region_ra = cs.get_register_field('FLMSTR1', flmstr, 'MRRA')
        master_region_wa = cs.get_register_field('FLMSTR1', flmstr, 'MRWA')
        flmstrs[m] = (master_region_ra, master_region_wa)
        logger().log('+ 0x%04X FLMSTR%d   : 0x%08X' % (flmstr_off, m, flmstr))

    logger().log('')
    logger().log('Master Read/Write Access to Flash Regions')
    logger().log('--------------------------------------------------------')
    s = ' Region                '
    for m in range(nm):
        s = s + '| ' + ('%-6s' % spi.SPI_MASTER_NAMES[m])
    logger().log(s)
    logger().log('--------------------------------------------------------')
    for r in range(nr):
        s = '%d %-020s ' % (r, spi.SPI_REGION_NAMES[r])
        for m in range(nm):
            access_s = ''
            mask = (0x1 << r) & 0xFF
            if (flmstrs[m][0] & mask): access_s += 'R'
            if (flmstrs[m][1] & mask): access_s += 'W'
            s = s + '| ' + ('%-6s' % access_s)
        logger().log(s)

    #
    # Flash Descriptor Upper Map Section
    #
    logger().log('')
    logger().log('+ 0x%04X Flash Descriptor Upper Map:' % 0xEFC)
    logger().log('========================================================')

    flumap1 = struct.unpack_from('=I', fd[0xEFC:0xF00])[0]
    logger().log('+ 0x%04X FLUMAP1   : 0x%08X' % (0xEFC, flumap1))

    vtba = ((flumap1 & 0x000000FF) << 4)
    vtl = (((flumap1 & 0x0000FF00) >> 8) & 0xFF)
    logger().log('  VSCC Table Base Address    = 0x%08X' % vtba)
    logger().log('  VSCC Table Length          = 0x%02X' % vtl)

    #
    # OEM Section
    #
    logger().log('')
    logger().log('+ 0x%04X OEM Section:' % 0xF00)
    logger().log('========================================================')
    print_buffer(fd[0xF00:])

    logger().log('')
    logger().log('########################################################')
    logger().log('# END OF SPI FLASH DESCRIPTOR')
    logger().log('########################################################')
Пример #33
0
            except SpiRuntimeError, msg:
                print("ERROR: SPI initialization error" % str(msg))
                raise

            (bios_base, bios_limit, freg) = _spi.get_SPI_region(BIOS)
            bios_size = bios_limit - bios_base + 1
            logger().log(
                "[CHIPSEC] Reading BIOS: base = 0x%08X, limit = 0x%08X, size = 0x%08X"
                % (bios_base, bios_limit, bios_size))
            rom = _spi.read_spi(bios_base, bios_size)
            chipsec_util._cs.stop(True)
            del _spi
        elif (5 == len(argv)):
            romfilename = argv[4]
            logger().log(
                "[CHIPSEC] Extracting EFI Variables from ROM file '%s'" %
                romfilename)
            rom = read_file(romfilename)

        _orig_logname = logger().LOG_FILE_NAME
        logger().set_log_file((romfilename + '.nv.lst'))
        _uefi.parse_EFI_variables(romfilename, rom, authvars, efi_nvram_format)
        logger().set_log_file(_orig_logname)

    elif ('decode' == op):

        if (4 < len(argv)):
            filename = argv[3]
            fwtype = argv[4]
        else:
            print uefi.__doc__
Пример #34
0
def print_efi_variable( offset, efi_var_buf, EFI_var_header, efi_var_name, efi_var_data, efi_var_guid, efi_var_attributes ):
    logger().log( '\n--------------------------------' )
    logger().log( 'EFI Variable (offset = 0x{:X}):'.format(offset) )
    logger().log( '--------------------------------' )

    # Print Variable Name
    logger().log( u'Name      : {}'.format(efi_var_name) )
    # Print Variable GUID
    logger().log( 'Guid      : {}'.format(efi_var_guid) )

    # Print Variable State
    if EFI_var_header:
        if 'State' in EFI_var_header._fields:
            state = getattr(EFI_var_header, 'State')
            state_str = 'State     :'
            if uefi_platform.IS_VARIABLE_STATE( state, uefi_platform.VAR_IN_DELETED_TRANSITION ):
                state_str = state_str + ' IN_DELETED_TRANSITION +'
            if uefi_platform.IS_VARIABLE_STATE( state, uefi_platform.VAR_DELETED ):
                state_str = state_str + ' DELETED +'
            if uefi_platform.IS_VARIABLE_STATE( state, uefi_platform.VAR_ADDED ):
                state_str = state_str + ' ADDED +'
            logger().log( state_str )

        # Print Variable Complete Header
        if logger().VERBOSE:
            if EFI_var_header.__str__:
                logger().log( EFI_var_header )
            else:
                logger().log( 'Decoded Header ({}):'.format(uefi_platform.EFI_VAR_DICT[ uefi_platform.FWType.EFI_FW_TYPE_UEFI ]['name']) )
                for attr in EFI_var_header._fields:
                    logger().log( '{} = {:X}'.format('{0:<16}'.format(attr), getattr(EFI_var_header, attr)) )

    attr_str = ('Attributes: 0x{:X} ( {} )'.format(efi_var_attributes, get_attr_string( efi_var_attributes )))
    logger().log( attr_str )

    # Print Variable Data
    logger().log( 'Data:' )
    print_buffer( bytestostring(efi_var_data) )

    # Print Variable Full Contents
    if logger().VERBOSE:
        logger().log( 'Full Contents:' )
        if not efi_var_buf is None:
            print_buffer( bytestostring(efi_var_buf) )
Пример #35
0
 def delete_EFI_variable( self, name, guid ):
     if logger().HAL: logger().log( '[uefi] deleting EFI variable {}:{}'.format(guid, name) )
     return self.helper.delete_EFI_variable( name, guid )
Пример #36
0
import re
import os
import sys
import time

from chipsec.logger import *
from chipsec.file import *
from chipsec.helper.oshelper import helper

from chipsec.chipset import cs, UnknownChipsetError
_cs = cs()

#
# If you want to turn verbose logging change this line to True
#
logger().VERBOSE = False
logger().UTIL_TRACE = True

global_usage = "CHIPSEC UTILITIES\n\n" + \
               "All numeric values are in hex\n" + \
               "<width> is in {1, byte, 2, word, 4, dword}\n\n"


def help(argv):
    print "\n[CHIPSEC] chipsec_util command-line extensions should be one of the following:"
    for cmd in chipsec_util_commands.keys():
        print cmd
    print global_usage


chipsec_util_commands = {}
Пример #37
0
def ldt(argv):
    logger().error("[CHIPSEC] ldt not implemented")
Пример #38
0
 def send_NMI(self):
     if logger().HAL:
         logger().log("[intr] sending NMI# through TCO1_CTL[NMI_NOW]")
     tcobase = self.get_TCOBASE()
     return self.cs.io.write_port_byte(tcobase + NMI_TCO1_CTL + 1, NMI_NOW)
Пример #39
0
 def send_SW_SMI(self, thread_id, SMI_code_port_value, SMI_data_port_value,
                 _rax, _rbx, _rcx, _rdx, _rsi, _rdi):
     SMI_code_data = (SMI_data_port_value << 8 | SMI_code_port_value)
     if logger().HAL:
         logger().log(
             "[intr] sending SW SMI: code port 0x%02X <- 0x%02X, data port 0x%02X <- 0x%02X (0x%04X)"
             % (SMI_APMC_PORT, SMI_code_port_value, SMI_APMC_PORT + 1,
                SMI_data_port_value, SMI_code_data))
         logger().log(
             "       RAX = 0x%016X (AX will be overwridden with values of SW SMI ports B2/B3)"
             % _rax)
         logger().log("       RBX = 0x%016X" % _rbx)
         logger().log("       RCX = 0x%016X" % _rcx)
         logger().log(
             "       RDX = 0x%016X (DX will be overwridden with 0x00B2)" %
             _rdx)
         logger().log("       RSI = 0x%016X" % _rsi)
         logger().log("       RDI = 0x%016X" % _rdi)
     return self.cs.helper.send_sw_smi(thread_id, SMI_code_data, _rax, _rbx,
                                       _rcx, _rdx, _rsi, _rdi)
Пример #40
0
def modify_uefi_region(data, command, guid, uefi_file=''):
    RgLengthChange = 0
    FvOffset, FsGuid, FvLength, FvAttributes, FvHeaderLength, FvChecksum, ExtHeaderOffset, FvImage, CalcSum = NextFwVolume(
        data)
    while FvOffset is not None:
        FvLengthChange = 0
        polarity = bit_set(FvAttributes, EFI_FVB2_ERASE_POLARITY)
        if ((FsGuid == EFI_FIRMWARE_FILE_SYSTEM2_GUID)
                or (FsGuid == EFI_FIRMWARE_FILE_SYSTEM_GUID)):
            cur_offset, next_offset, Name, Type, Attributes, State, Checksum, Size, FileImage, HeaderSize, UD, fCalcSum = NextFwFile(
                FvImage, FvLength, FvHeaderLength, polarity)
            while next_offset is not None:
                if (Name == guid):
                    uefi_file_size = (len(uefi_file) + 7) & 0xFFFFFFF8
                    CurFileOffset = FvOffset + cur_offset + FvLengthChange
                    NxtFileOffset = FvOffset + next_offset + FvLengthChange
                    if command == CMD_UEFI_FILE_REMOVE:
                        FvLengthChange -= (next_offset - cur_offset)
                        logger().log(
                            "Removing UEFI file with GUID=%s at offset=%08X, size change: %d bytes"
                            % (Name, CurFileOffset, FvLengthChange))
                        data = data[:CurFileOffset] + data[NxtFileOffset:]
                    elif command == CMD_UEFI_FILE_INSERT_BEFORE:
                        FvLengthChange += uefi_file_size
                        logger().log(
                            "Inserting UEFI file before file with GUID=%s at offset=%08X, size change: %d bytes"
                            % (Name, CurFileOffset, FvLengthChange))
                        data = data[:CurFileOffset] + uefi_file.ljust(
                            uefi_file_size, '\xFF') + data[CurFileOffset:]
                    elif command == CMD_UEFI_FILE_INSERT_AFTER:
                        FvLengthChange += uefi_file_size
                        logger().log(
                            "Inserting UEFI file after file with GUID=%s at offset=%08X, size change: %d bytes"
                            % (Name, CurFileOffset, FvLengthChange))
                        data = data[:NxtFileOffset] + uefi_file.ljust(
                            uefi_file_size, '\xFF') + data[NxtFileOffset:]
                    elif command == CMD_UEFI_FILE_REPLACE:
                        FvLengthChange += uefi_file_size - (next_offset -
                                                            cur_offset)
                        logger().log(
                            "Replacing UEFI file with GUID=%s at offset=%08X, new size: %d, old size: %d, size change: %d bytes"
                            % (Name, CurFileOffset, len(uefi_file), Size,
                               FvLengthChange))
                        data = data[:CurFileOffset] + uefi_file.ljust(
                            uefi_file_size, '\xFF') + data[NxtFileOffset:]
                    else:
                        raise Exception('Invalid command')

                if next_offset - cur_offset >= 24:
                    FvEndOffset = FvOffset + next_offset + FvLengthChange

                cur_offset, next_offset, Name, Type, Attributes, State, Checksum, Size, FileImage, HeaderSize, UD, fCalcSum = NextFwFile(
                    FvImage, FvLength, next_offset, polarity)

            if FvLengthChange >= 0:
                data = data[:FvEndOffset] + data[FvEndOffset + FvLengthChange:]
            else:
                data = data[:FvEndOffset] + (abs(FvLengthChange) *
                                             '\xFF') + data[FvEndOffset:]

            FvLengthChange = 0

            #if FvLengthChange != 0:
            #    logger().log( "Rebuilding Firmware Volume with GUID=%s at offset=%08X" % (FsGuid, FvOffset) )
            #    FvHeader = data[FvOffset: FvOffset + FvHeaderLength]
            #    FvHeader = FvHeader[:0x20] + struct.pack('<Q', FvLength) + FvHeader[0x28:]
            #    NewChecksum = FvChecksum16(FvHeader[:0x32] + '\x00\x00' + FvHeader[0x34:])
            #    FvHeader = FvHeader[:0x32] + struct.pack('<H', NewChecksum) + FvHeader[0x34:]
            #    data = data[:FvOffset] + FvHeader + data[FvOffset + FvHeaderLength:]

        FvOffset, FsGuid, FvLength, FvAttributes, FvHeaderLength, FvChecksum, ExtHeaderOffset, FvImage, CalcSum = NextFwVolume(
            data, FvOffset + FvLength)
    return data
Пример #41
0
def decode_s3bs_opcode_AA(data):
    opcode = None
    width = None
    count = None
    value = None
    mask = None

    op = None
    #opcode, = struct.unpack( '<B', data[ : 1 ] )
    #if not (S3BootScriptOpcode.EFI_BOOT_SCRIPT_TERMINATE_OPCODE == opcode):

    hdr_frmt = '<BBB'
    header_size = struct.calcsize(hdr_frmt)
    opcode, dummy, size = struct.unpack(hdr_frmt, data[:header_size])
    opcode_data = data[header_size:]
    try:
        if logger().VERBOSE: logger().log(script_opcodes[opcode])
    except:
        pass

    if   S3BootScriptOpcode.EFI_BOOT_SCRIPT_IO_WRITE_OPCODE                == opcode or \
         S3BootScriptOpcode.EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE        == opcode or \
         S3BootScriptOpcode.EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE               == opcode:

        frmt = '<IIQ'
        op_size = struct.calcsize(frmt)
        width, count, address = struct.unpack(frmt, opcode_data[:op_size])
        op = op_io_pci_mem(opcode, size, width, address, count,
                           opcode_data[op_size:], value, mask)

    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE         == opcode or \
         S3BootScriptOpcode.EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE == opcode or \
         S3BootScriptOpcode.EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE        == opcode:
        frmt = '<IQ'
        sz = struct.calcsize(frmt)
        width, address = struct.unpack(frmt, opcode_data[:sz])
        frmt = 2 * script_width_formats[width]
        op_size = sz + struct.calcsize(frmt)
        value, mask = struct.unpack(frmt, opcode_data[sz:op_size])
        op = op_io_pci_mem(opcode, size, width, address, count, None, value,
                           mask)

    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE == opcode:
        if logger().UTIL_TRACE or logger().VERBOSE:
            logger().warn('Cannot parse opcode %X yet' % opcode)

    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_STALL_OPCODE == opcode:
        frmt = '<Q'
        op_size = struct.calcsize(frmt)
        duration, = struct.unpack(frmt, opcode_data[:op_size])
        op = op_stall(opcode, size, duration)

    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_DISPATCH_OPCODE == opcode:
        frmt = '<Q'
        op_size = struct.calcsize(frmt)
        entrypoint, = struct.unpack(frmt, opcode_data[:op_size])
        op = op_dispatch(opcode, size, entrypoint)

    elif S3BootScriptOpcode.EFI_BOOT_SCRIPT_TERMINATE_OPCODE == opcode:
        op = op_terminate(opcode, size)

    else:
        op = op_unknown(opcode, size)
        if logger().VERBOSE: logger().warn('Unrecognized opcode %X' % opcode)

    return op
Пример #42
0
def decode_uefi_region(_uefi, pth, fname, fwtype):

    bios_pth = os.path.join(pth, fname + '.dir')
    if not os.path.exists(bios_pth):
        os.makedirs(bios_pth)
    fv_pth = os.path.join(bios_pth, 'FV')
    if not os.path.exists(fv_pth):
        os.makedirs(fv_pth)

    # Decoding UEFI Firmware Volumes
    if logger().HAL:
        logger().log("[spi_uefi] decoding UEFI firmware volumes...")
    parse_uefi_region_from_file(_uefi, fname, fwtype, fv_pth)

    # Decoding EFI Variables NVRAM
    if logger().HAL: logger().log("[spi_uefi] decoding UEFI NVRAM...")
    region_data = read_file(fname)
    if fwtype is None:
        fwtype = identify_EFI_NVRAM(region_data)
        if fwtype is None: return
    elif fwtype not in fw_types:
        if logger().HAL: logger().error("unrecognized NVRAM type %s" % fwtype)
        return
    nvram_fname = os.path.join(bios_pth, ('nvram_%s' % fwtype))
    logger().set_log_file((nvram_fname + '.nvram.lst'))
    _uefi.parse_EFI_variables(nvram_fname, region_data, False, fwtype)
Пример #43
0
import sys
import time
import importlib
import imp

from chipsec.logger import *
from chipsec.file import *
from chipsec.helper.oshelper import helper

from chipsec.chipset import cs, UnknownChipsetError
_cs = cs()

#
# If you want to turn verbose logging change this line to True
#
logger().UTIL_TRACE = True
logger().VERBOSE = False
logger().HAL = False
logger().DEBUG = False

# If you want to specify a different platform change this line to a string from chipset.py
# _Platform = 'SNB'
_Platform = None


class ExitCode:
    OK = 0
    EXCEPTION = 32


#CMD_OPTS_WIDTH = [ 'byte', 'word', 'dword', 'qword' ]
Пример #44
0
 def set_EFI_variable_from_file( self, name, guid, filename, attrs=None ):
     if filename is None:
        logger().error( 'File with EFI variable is not specified' )
        return False
     var = read_file( filename )
     return self.set_EFI_variable( name, guid, var, attrs )
Пример #45
0
 def set_EFI_variable( self, name, guid, var, datasize=None, attrs=None ):
     if logger().HAL:
         logger().log( '[uefi] writing EFI variable {}:{} {}'.format(guid, name, '' if attrs is None else ('(attributes = {})'.format(attrs))) )
         #print_buffer( var )
     return self.helper.set_EFI_variable( name, guid, var, datasize, attrs )
Пример #46
0
    def find_EFI_variable_store( self, rom_buffer ):
        if ( rom_buffer is None ):
            logger().error( 'rom_buffer is None' )
            return None
        # Meh..
        rom = "".join( rom_buffer )
        offset       = 0
        size         = len(rom_buffer)
        nvram_header = None

        if EFI_VAR_DICT[ self._FWType ]['func_getnvstore']:
           (offset, size, nvram_header) = EFI_VAR_DICT[ self._FWType ]['func_getnvstore']( rom )
           if (-1 == offset):
              logger().error( "'func_getnvstore' is defined but could not find EFI NVRAM. Exiting.." )
              return None
        else:
           logger().log( "[uefi] 'func_getnvstore' is not defined in EFI_VAR_DICT. Assuming start offset 0.." )

        if -1 == size: size = len(rom_buffer)
        nvram_buf = rom[ offset : offset + size ]

        if logger().UTIL_TRACE:
            logger().log( '[uefi] Found EFI NVRAM at offset 0x%08X' % offset )
            logger().log( """
==================================================================
NVRAM: EFI Variable Store
==================================================================""")
            if nvram_header: logger().log( nvram_header )
        return nvram_buf
Пример #47
0
def uefi(argv):
    """
    >>> chipsec_util uefi var-list
    >>> chipsec_util uefi var-find <name>|<GUID>
    >>> chipsec_util uefi var-read|var-write|var-delete <name> <GUID> <efi_variable_file>
    >>> chipsec_util uefi nvram[-auth] <fw_type> [rom_file]
    >>> chipsec_util uefi tables
    >>> chipsec_util uefi s3bootscript [script_address]
    >>> chipsec_util uefi assemble <GUID> freeform none|lzma|tiano <raw_file> <uefi_file>
    >>> chipsec_util uefi insert_before|insert_after|replace|remove <GUID> <bios_rom> <modified_bios_rom> <uefi_file>

    For a list of fw types run:

    >>> chipsec_util uefi types
    
    Examples:

    >>> chipsec_util uefi var-list
    >>> chipsec_util uefi var-find PK
    >>> chipsec_util uefi var-read db D719B2CB-3D3A-4596-A3BC-DAD00E67656F db.bin
    >>> chipsec_util uefi var-write db D719B2CB-3D3A-4596-A3BC-DAD00E67656F db.bin
    >>> chipsec_util uefi var-delete db D719B2CB-3D3A-4596-A3BC-DAD00E67656F
    >>> chipsec_util uefi nvram fwtype bios.rom
    >>> chipsec_util uefi nvram-auth fwtype bios.rom
    >>> chipsec_util uefi decode uefi.bin fwtype
    >>> chipsec_util uefi keys db.bin
    >>> chipsec_util uefi tables
    >>> chipsec_util uefi s3bootscript
    >>> chipsec_util uefi assemble AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE freeform lzma uefi_file.raw uefi_file.bin
    >>> chipsec_util uefi replace  AAAAAAAA-BBBB-CCCC-DDDD-EEEEEEEEEEEE bios.bin modified_bios.bin uefi_file.bin
    """

    if 3 > len(argv):
        print uefi.__doc__
        return

    if argv[2] == "types":
        print "\n<fw_type> should be in [ %s ]\n" % (" | ".join( ["%s" % t for t in fw_types])) + \
        "chipsec_util uefi keys <keyvar_file>\n" + \
        "                  <keyvar_file> should be one of the following EFI variables\n" + \
        "                  [ %s ]\n" % (" | ".join( ["%s" % var for var in SECURE_BOOT_KEY_VARIABLES]))
        return

    op = argv[2]
    t = time.time()

    filename = None
    if ('var-read' == op):
        if (4 < len(argv)):
            name = argv[3]
            guid = argv[4]
        if (5 < len(argv)):
            filename = argv[5]
        logger().log(
            "[CHIPSEC] Reading EFI variable Name='%s' GUID={%s} to '%s' via Variable API.."
            % (name, guid, filename))
        var = _uefi.get_EFI_variable(name, guid, filename)

    elif ('var-write' == op):

        if (5 < len(argv)):
            name = argv[3]
            guid = argv[4]
            filename = argv[5]
        else:
            print uefi.__doc__
            return
        logger().log(
            "[CHIPSEC] writing EFI variable Name='%s' GUID={%s} from '%s' via Variable API.."
            % (name, guid, filename))
        status = _uefi.set_EFI_variable_from_file(name, guid, filename)
        logger().log("[CHIPSEC] status: %s" %
                     chipsec.hal.uefi_common.EFI_STATUS_DICT[status])
        if status == 0:
            logger().log("[CHIPSEC] set_EFI_variable return SUCCESS status")
        else:
            logger().error("set_EFI_variable wasn't able to modify variable")

    elif ('var-delete' == op):

        if (4 < len(argv)):
            name = argv[3]
            guid = argv[4]
        else:
            print uefi.__doc__
            return
        logger().log(
            "[CHIPSEC] Deleting EFI variable Name='%s' GUID={%s} via Variable API.."
            % (name, guid))
        status = _uefi.delete_EFI_variable(name, guid)
        logger().log("Returned %s" %
                     chipsec.hal.uefi_common.EFI_STATUS_DICT[status])
        if status == 0:
            logger().log("[CHIPSEC] delete_EFI_variable return SUCCESS status")
        else:
            logger().error(
                "delete_EFI_variable wasn't able to delete variable")

    elif ('var-list' == op):

        #infcls = 2
        #if (3 < len(argv)): filename = argv[3]
        #if (4 < len(argv)): infcls = int(argv[4],16)
        logger().log(
            "[CHIPSEC] Enumerating all EFI variables via OS specific EFI Variable API.."
        )
        efi_vars = _uefi.list_EFI_variables()
        if efi_vars is None:
            logger().log(
                "[CHIPSEC] Could not enumerate EFI Variables (Legacy OS?). Exit.."
            )
            return

        logger().log("[CHIPSEC] Decoding EFI Variables..")
        _orig_logname = logger().LOG_FILE_NAME
        logger().set_log_file('efi_variables.lst')
        #print_sorted_EFI_variables( efi_vars )
        nvram_pth = 'efi_variables.dir'
        if not os.path.exists(nvram_pth): os.makedirs(nvram_pth)
        decode_EFI_variables(efi_vars, nvram_pth)
        logger().set_log_file(_orig_logname)

        #efi_vars = _uefi.list_EFI_variables( infcls, filename )
        #_orig_logname = logger().LOG_FILE_NAME
        #logger().set_log_file( (filename + '.nv.lst') )
        #_uefi.parse_EFI_variables( filename, efi_vars, False, FWType.EFI_FW_TYPE_WIN )
        #logger().set_log_file( _orig_logname )

        logger().log(
            "[CHIPSEC] Variables are in efi_variables.lst log and efi_variables.dir directory"
        )

    elif ('var-find' == op):

        _vars = _uefi.list_EFI_variables()
        if _vars is None:
            logger().log_warning(
                'Could not enumerate UEFI variables (non-UEFI OS?)')
            return

        _input_var = argv[3]
        if ('-' in _input_var):
            logger().log("[*] Searching for UEFI variable with GUID {%s}.." %
                         _input_var)
            for name in _vars:
                n = 0
                for (off, buf, hdr, data, guid, attrs) in _vars[name]:
                    if _input_var == guid:
                        var_fname = '%s_%s_%s_%d.bin' % (
                            name, guid, get_attr_string(attrs).strip(), n)
                        logger().log_good(
                            "Found UEFI variable %s:%s. Dumped to '%s'" %
                            (guid, name, var_fname))
                        write_file(var_fname, data)
                    n += 1
        else:
            logger().log("[*] Searching for UEFI variable with name %s.." %
                         _input_var)
            for name, _v in _vars.iteritems():
                n = 0
                for (off, buf, hdr, data, guid, attrs) in _v:
                    if _input_var == name:
                        var_fname = '%s_%s_%s_%d.bin' % (
                            name, guid, get_attr_string(attrs).strip(), n)
                        logger().log_good(
                            "Found UEFI variable %s:%s. Dumped to '%s'" %
                            (guid, name, var_fname))
                        write_file(var_fname, data)
                    n += 1

    elif ('nvram' == op or 'nvram-auth' == op):

        authvars = ('nvram-auth' == op)
        efi_nvram_format = argv[3]
        if (4 == len(argv)):
            logger().log(
                "[CHIPSEC] Extracting EFI Variables directly in SPI ROM..")
            try:
                chipsec_util._cs.init(True)
                _spi = SPI(chipsec_util._cs)
            except UnknownChipsetError, msg:
                print("ERROR: Unknown chipset vendor (%s)" % str(msg))
                raise
            except SpiRuntimeError, msg:
                print("ERROR: SPI initialization error" % str(msg))
                raise

            (bios_base, bios_limit, freg) = _spi.get_SPI_region(BIOS)
            bios_size = bios_limit - bios_base + 1
            logger().log(
                "[CHIPSEC] Reading BIOS: base = 0x%08X, limit = 0x%08X, size = 0x%08X"
                % (bios_base, bios_limit, bios_size))
            rom = _spi.read_spi(bios_base, bios_size)
            chipsec_util._cs.stop(True)
            del _spi
Пример #48
0
 def write_physical_mem_word( self, phys_address, word_value ):
     if logger().HAL: logger().log( '[mem] word to PA = 0x%016X <- 0x%04X' % (phys_address, word_value) )
     return self.write_physical_mem( phys_address, 2, struct.pack( 'H', word_value ) )
Пример #49
0
def cmos(argv):
    if 3 > len(argv):
        print usage
        return

    try:
        cmos = CMOS(  )
    except CmosRuntimeError, msg:
        print msg
        return

    op = argv[2]
    t = time.time()

    if ( 'dump' == op ):
        logger().log( "[CHIPSEC] Dumping CMOS memory.." )
        cmos.dump()
    elif ( 'readl' == op ):
        off = int(argv[3],16)
        val = cmos.read_cmos_low( off )
        logger().log( "[CHIPSEC] CMOS low byte 0x%X = 0x%X" % (off, val) )
    elif ( 'writel' == op ):
        off = int(argv[3],16)
        val = int(argv[4],16)
        logger().log( "[CHIPSEC] Writing CMOS low byte 0x%X <- 0x%X " % (off, val) )
        cmos.write_cmos_low( off, val )
    elif ( 'readh' == op ):
        off = int(argv[3],16)
        val = cmos.read_cmos_high( off )
        logger().log( "[CHIPSEC] CMOS high byte 0x%X = 0x%X" % (off, val) )
    elif ( 'writeh' == op ):
Пример #50
0
 def write_physical_mem( self, phys_address, length, buf ):
     if logger().HAL:
         logger().log( '[mem] buffer len = 0x%X to PA = 0x%016X' % (length, phys_address) )
         print_buffer( buf )
     return self.helper.write_physical_mem( phys_address, length, buf )
Пример #51
0
def print_efi_variable( offset, efi_var_buf, EFI_var_header, efi_var_name, efi_var_data, efi_var_guid, efi_var_attributes ):
        logger().log( '\n--------------------------------' )
        logger().log( 'EFI Variable (offset = 0x%x):' % offset )
        logger().log( '--------------------------------' )

        # Print Variable Name
        logger().log( 'Name      : %s' % efi_var_name )
        # Print Variable GUID
        logger().log( 'Guid      : %s' % efi_var_guid )

        # Print Variable State
        if EFI_var_header:
           if 'State' in EFI_var_header._fields:
              state = getattr(EFI_var_header, 'State')
              state_str = 'State     :'
              if IS_VARIABLE_STATE( state, VAR_IN_DELETED_TRANSITION ):
                 state_str = state_str + ' IN_DELETED_TRANSITION +'
              if IS_VARIABLE_STATE( state, VAR_DELETED ):
                 state_str = state_str + ' DELETED +'
              if IS_VARIABLE_STATE( state, VAR_ADDED ):
                 state_str = state_str + ' ADDED +'
              logger().log( state_str )
        
           # Print Variable Complete Header
           if logger().VERBOSE:
              if EFI_var_header.__str__:
                 logger().log( EFI_var_header )
              else:
                 logger().log( 'Decoded Header (%s):' % EFI_VAR_DICT[ self._FWType ]['name'] )
                 for attr in EFI_var_header._fields:
                    logger().log( '%s = %X' % ('{0:<16}'.format(attr), getattr(EFI_var_header, attr)) )
        
        attr_str = ('Attributes: 0x%X ( ' % efi_var_attributes) + get_attr_string( efi_var_attributes ) + ' )'
        logger().log( attr_str )
        
        # Print Variable Data
        logger().log( 'Data:' )
        print_buffer( efi_var_data )

        # Print Variable Full Contents
        if logger().VERBOSE:
           logger().log( 'Full Contents:' )
           print_buffer( efi_var_buf )
Пример #52
0
def getEFIvariables_UEFI(nvram_buf):
    logger().error('Well, implement getEFIvariables_UEFI finally, would you??')
    return 0
Пример #53
0
 def write_physical_mem_dword( self, phys_address, dword_value ):
     if logger().HAL: logger().log( '[mem] dword to PA = 0x%016X <- 0x%08X' % (phys_address, dword_value) )
     return self.write_physical_mem( phys_address, 4, struct.pack( 'I', dword_value ) )
Пример #54
0
    def find_s3_bootscript(self):
        found = False
        BootScript_addresses = []

        efivars = self.list_EFI_variables()
        if efivars is None:
            logger().error('Could not enumerate UEFI variables at runtime')
            return (found, BootScript_addresses)
        if logger().HAL:
            logger().log("[uefi] searching for EFI variable(s): " +
                         str(S3_BOOTSCRIPT_VARIABLES))

        for efivar_name in efivars:
            (off, buf, hdr, data, guid, attrs) = efivars[efivar_name][0]
            if efivar_name in S3_BOOTSCRIPT_VARIABLES:
                if logger().HAL:
                    logger().log("[uefi] found: '%s' {%s} %s variable" %
                                 (efivar_name, guid, get_attr_string(attrs)))
                if logger().VERBOSE:
                    logger().log('[uefi] %s variable data:' % efivar_name)
                    print_buffer(data)

                varsz = len(data)
                if 4 == varsz: AcpiGlobalAddr_fmt = '<L'
                elif 8 == varsz: AcpiGlobalAddr_fmt = '<Q'
                else:
                    logger().error(
                        "Unrecognized format of '%s' UEFI variable (data size = 0x%X)"
                        % (efivar_name, varsz))
                    break
                AcpiGlobalAddr = struct.unpack_from(AcpiGlobalAddr_fmt,
                                                    data)[0]

                if logger().HAL:
                    logger().log(
                        "[uefi] Pointer to ACPI Global Data structure: 0x%016X"
                        % (AcpiGlobalAddr))
                if logger().HAL:
                    logger().log(
                        "[uefi] Decoding ACPI Global Data structure..")
                AcpiVariableSet = self.helper.read_physical_mem(
                    AcpiGlobalAddr, ACPI_VARIABLE_SET_STRUCT_SIZE)
                if logger().VERBOSE:
                    logger().log('[uefi] AcpiVariableSet structure:')
                    print_buffer(AcpiVariableSet)
                AcpiVariableSet_fmt = '<6Q'
                #if len(AcpiVariableSet) < struct.calcsize(AcpiVariableSet_fmt):
                #    logger().error( 'Unrecognized format of AcpiVariableSet structure' )
                #    return (False,0)
                AcpiReservedMemoryBase, AcpiReservedMemorySize, S3ReservedLowMemoryBase, AcpiBootScriptTable, RuntimeScriptTableBase, AcpiFacsTable = struct.unpack_from(
                    AcpiVariableSet_fmt, AcpiVariableSet)
                if logger().HAL:
                    logger().log(
                        '[uefi] ACPI Boot-Script table base = 0x%016X' %
                        AcpiBootScriptTable)
                found = True
                BootScript_addresses.append(AcpiBootScriptTable)
                #break
        return (found, BootScript_addresses)
Пример #55
0
 def read_physical_mem_byte( self, phys_address ):
     out_buf = self.read_physical_mem( phys_address, 1 )
     value = struct.unpack( '=B', out_buf )[0]
     if logger().HAL: logger().log( '[mem] byte at PA = 0x%016X: 0x%02X' % (phys_address, value) )
     return value
Пример #56
0
 def dump_EFI_tables( self ):
     (found,pa,hdr,table,table_buf) = self.find_EFI_System_Table()
     if found:
         logger().log( "[uefi] EFI System Table:" )
         print_buffer( bytestostring(table_buf) )
         logger().log( hdr )
         logger().log( table )
     (found,ect_pa,ect,ect_buf) = self.find_EFI_Configuration_Table()
     if found:
         logger().log( "\n[uefi] EFI Configuration Table:" )
         print_buffer( bytestostring(ect_buf) )
         logger().log( ect )
     (found,pa,hdr,table,table_buf) = self.find_EFI_RuntimeServices_Table()
     if found:
         logger().log( "\n[uefi] EFI Runtime Services Table:" )
         print_buffer( bytestostring(table_buf) )
         logger().log( hdr )
         logger().log( table )
     (found,pa,hdr,table,table_buf) = self.find_EFI_BootServices_Table()
     if found:
         logger().log( "\n[uefi] EFI Boot Services Table:" )
         print_buffer( bytestostring(table_buf) )
         logger().log( hdr )
         logger().log( table )
     (found,pa,hdr,table,table_buf) = self.find_EFI_DXEServices_Table()
     if found:
         logger().log( "\n[uefi] EFI DXE Services Table:" )
         print_buffer( bytestostring(table_buf) )
         logger().log( hdr )
         logger().log( table )
Пример #57
0
    def find_EFI_Configuration_Table( self ):
        ect_pa = None
        ect    = None
        ect_buf= None
        (isFound,est_pa,est_header,est,est_buf) = self.find_EFI_System_Table()
        if isFound and est is not None:
            if 0 != est.BootServices:
                if logger().HAL: logger().log( "[uefi] UEFI appears to be in Boot mode" )
                ect_pa = est.ConfigurationTable
            else:
                if logger().HAL: logger().log( "[uefi] UEFI appears to be in Runtime mode" )
                ect_pa = self.cs.mem.va2pa( est.ConfigurationTable )
                if not ect_pa:
                    # Most likely the VA in the System Table is not mapped so find the RST by signature and 
                    # then compute the address of the configuration table.  This assumes the VA mapping keeps
                    # the pages in the same relative location as in physical memory.
                    (rst_found, rst_pa, rst_header, rst, rst_buf) = self.find_EFI_RuntimeServices_Table()
                    if rst_found:
                        if logger().HAL: logger().warn("Attempting to derive configuration table address")
                        ect_pa = rst_pa + (est.ConfigurationTable - est.RuntimeServices)
                    else:
                        if logger().HAL: logger().warn( "Can't find UEFI ConfigurationTable" )
                        return (None,ect_pa,ect,ect_buf)

        if logger().HAL: logger().log( "[uefi] EFI Configuration Table ({:d} entries): VA = 0x{:016X}, PA = 0x{:016X}".format(est.NumberOfTableEntries,est.ConfigurationTable,ect_pa) )

        found = (ect_pa is not None)
        if found:
            ect_buf = self.cs.mem.read_physical_mem( ect_pa, EFI_VENDOR_TABLE_SIZE*est.NumberOfTableEntries )
            ect = EFI_CONFIGURATION_TABLE()
            for i in range(est.NumberOfTableEntries):
                vt = EFI_VENDOR_TABLE( *struct.unpack_from( EFI_VENDOR_TABLE_FORMAT, ect_buf[i*EFI_VENDOR_TABLE_SIZE:] ) )
                ect.VendorTables[ vt.VendorGuid() ] = vt.VendorTable
        return (found,ect_pa,ect,ect_buf)
Пример #58
0
 def find_EFI_Table( self, table_sig ):
     (smram_base,smram_limit,smram_size) = self.cs.cpu.get_SMRAM()
     CHUNK_SZ = 1024*1024 # 1MB
     if logger().HAL: logger().log( "[uefi] searching memory for EFI table with signature '{}' ..".format(table_sig) )
     table_pa,table_header,table,table_buf = None,None,None,None
     pa = smram_base - CHUNK_SZ
     isFound = False
     while pa > CHUNK_SZ:
         if logger().HAL: logger().log( '[uefi] reading 0x{:016X}..'.format(pa) )
         membuf = self.cs.mem.read_physical_mem( pa, CHUNK_SZ )
         pos = bytestostring(membuf).find( table_sig )
         if -1 != pos:
             table_pa = pa + pos
             if logger().HAL: logger().log( "[uefi] found signature '{}' at 0x{:016X}..".format(table_sig,table_pa) )
             if pos < (CHUNK_SZ - EFI_TABLE_HEADER_SIZE):
                 hdr = membuf[ pos : pos + EFI_TABLE_HEADER_SIZE ]
             else:
                 hdr = self.cs.mem.read_physical_mem( table_pa, EFI_TABLE_HEADER_SIZE )
             table_header = EFI_TABLE_HEADER( *struct.unpack_from( EFI_TABLE_HEADER_FMT, hdr ) )
             # do some sanity checks on the header
             if 0 != table_header.Reserved or                 \
                0 == table_header.CRC32    or                 \
                table_header.Revision not in EFI_REVISIONS or \
                table_header.HeaderSize > MAX_EFI_TABLE_SIZE:
                 if logger().HAL:
                     logger().log( "[uefi] found '{}' at 0x{:016X} but doesn't look like an actual table. keep searching..".format(table_sig,table_pa) )
                     logger().log( table_header )
             else:
                 isFound = True
                 if logger().HAL: logger().log( "[uefi] found EFI table at 0x{:016X} with signature '{}'..".format(table_pa,table_sig) )
                 table_size = struct.calcsize( EFI_TABLES[table_sig]['fmt'] )
                 if pos < (CHUNK_SZ - EFI_TABLE_HEADER_SIZE - table_size):
                     table_buf = membuf[ pos : pos + EFI_TABLE_HEADER_SIZE + table_size ]
                 else:
                     table_buf = self.cs.mem.read_physical_mem( table_pa, EFI_TABLE_HEADER_SIZE + table_size )
                 table = EFI_TABLES[table_sig]['struct']( *struct.unpack_from( EFI_TABLES[table_sig]['fmt'], table_buf[EFI_TABLE_HEADER_SIZE:] ) )
                 if logger().HAL:
                    print_buffer( bytestostring(table_buf) )
                    logger().log( '[uefi] {}:'.format(EFI_TABLES[table_sig]['name']) )
                    logger().log( table_header )
                    logger().log( table )
                 break
         pa -= CHUNK_SZ
     if (not isFound) and logger().HAL: logger().log( "[uefi] could not find EFI table with signature '{}'".format(table_sig) )
     return (isFound,table_pa,table_header,table,table_buf)
Пример #59
0
 def stop(self, start_driver):
     if not self.helper.stop(start_driver):
         logger().warn("failed to stop OS helper")
     else:
         if not self.helper.delete(start_driver):
             logger().warn("failed to delete OS helper")
Пример #60
0
def save_efi_tree(_uefi,
                  modules,
                  parent=None,
                  save_modules=True,
                  path=None,
                  save_log=True,
                  lvl=0):
    mod_dir_path = None
    modules_arr = []
    modn = 0
    for m in modules:
        md = {}
        m.indent = DEF_INDENT * lvl
        if save_log: logger().log(m)

        # extract all non-function non-None members of EFI_MODULE objects
        attrs = [
            a for a in dir(m)
            if not callable(getattr(m, a)) and not a.startswith("__") and (
                getattr(m, a) is not None)
        ]
        for a in attrs:
            md[a] = getattr(m, a)
        md["class"] = type(m).__name__
        # remove extra attributes
        for f in ["Image", "indent"]:
            del md[f]

        # save EFI module image, make sub-directory for children
        if save_modules:
            mod_path = dump_efi_module(m, parent, modn, path)
            try:
                md["file_path"] = os.path.relpath(
                    mod_path[4:] if mod_path.startswith("\\\\?\\"
                                                        ) else mod_path)
            except:
                md["file_path"] = mod_path.split(os.sep)[-1]
            if m.isNVRAM or len(m.children) > 0:
                mod_dir_path = "%s.dir" % mod_path
                if not os.path.exists(mod_dir_path): os.makedirs(mod_dir_path)
                if m.isNVRAM:
                    try:
                        if m.NVRAMType is not None:
                            # @TODO: technically, NVRAM image should be m.Image but
                            # getNVstore_xxx functions expect FV than a FW file within FV
                            # so for EFI_FILE type of module using parent's Image as NVRAM
                            nvram = parent.Image if (
                                type(m) == EFI_FILE
                                and type(parent) == EFI_FV) else m.Image
                            _uefi.parse_EFI_variables(
                                os.path.join(mod_dir_path, 'NVRAM'), nvram,
                                False, m.NVRAMType)
                        else:
                            raise
                    except:
                        logger().warn(
                            "couldn't extract NVRAM in {%s} using type '%s'" %
                            (m.Guid, m.NVRAMType))

        # save children modules
        if len(m.children) > 0:
            md["children"] = save_efi_tree(_uefi, m.children, m, save_modules,
                                           mod_dir_path, save_log, lvl + 1)
        else:
            del md["children"]

        modules_arr.append(md)
        modn += 1

    return modules_arr