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 )
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
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 )
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
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()
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)
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
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
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 )
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))
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
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
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
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
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
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
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
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
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
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")
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 )
def platform(argv): try: print_supported_chipsets() logger().log("") chipsec_util._cs.print_chipset() except UnknownChipsetError, msg: logger().error( msg )
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) )
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
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
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
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
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
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
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
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
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('########################################################')
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__
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) )
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 )
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 = {}
def ldt(argv): logger().error("[CHIPSEC] ldt not implemented")
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)
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)
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
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
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)
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' ]
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 )
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 )
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
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
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 ) )
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 ):
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 )
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 )
def getEFIvariables_UEFI(nvram_buf): logger().error('Well, implement getEFIvariables_UEFI finally, would you??') return 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 ) )
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)
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
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 )
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)
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)
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")
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