diff --git a/chipsec/hal/cpu.py b/chipsec/hal/cpu.py index 8eb13cdf..851d8612 100644 --- a/chipsec/hal/cpu.py +++ b/chipsec/hal/cpu.py @@ -43,6 +43,12 @@ from collections import namedtuple from chipsec.hal import acpi, hal_base from chipsec.logger import logger +VMM_NONE = 0 +VMM_XEN = 0x1 +VMM_HYPER_V = 0x2 +VMM_VMWARE = 0x3 +VMM_KVM = 0x4 + class CPURuntimeError (RuntimeError): pass @@ -74,6 +80,22 @@ class CPU(hal_base.HALBase): if logger().VERBOSE: logger().log( "[cpu] CPUID out: EAX=0x%08X, EBX=0x%08X, ECX=0x%08X, EDX=0x%08X" % (eax, ebx, ecx, edx) ) return (eax, ebx, ecx, edx) + # Using cpuid check if running under vmm control + def check_vmm(self): + # check Hypervisor Present + (eax, ebx, ecx, edx) = self.cpuid( 0x01, 0 ) + if (ecx & 0x80000000): + (eax, ebx, ecx, edx) = self.cpuid( 0x40000000, 0 ) + is_xen = ((ebx == 0x566e6558) and (ecx == 0x65584d4d) and (edx == 0x4d4d566e)) + if is_xen: return VMM_XEN + is_hyperv = ((ebx == 0x7263694D) and (ecx == 0x666F736F) and (edx == 0x76482074)) + if is_hyperv: return VMM_HYPER_V + is_vmware = ((ebx == 0x61774d56) and (ecx == 0x4d566572) and (edx == 0x65726177)) + if is_vmware: return VMM_VMWARE + is_kvm = ((ebx == 0x4b4d564b) and (ecx == 0x564b4d56) and (edx == 0x0000004d)) + if is_kvm: return VMM_KVM + return VMM_NONE + # Using CPUID we can determine if Hyper-Threading is enabled in the CPU def is_HT_active(self): logical_processor_per_core=self.get_number_logical_processor_per_core() @@ -157,7 +179,8 @@ class CPU(hal_base.HALBase): smram_limit = None smram_size = 0 try: - (smram_base, smram_limit, smram_size) = self.get_SMRR_SMRAM() + if (self.check_SMRR_supported()): + (smram_base, smram_limit, smram_size) = self.get_SMRR_SMRAM() except: pass @@ -172,6 +195,9 @@ class CPU(hal_base.HALBase): # Check that SMRR is supported by CPU in IA32_MTRRCAP_MSR[SMRR] # def check_SMRR_supported( self ): + # MS HyperV workaround. HyperV reports SMRR support but throws and exception on access to SMRR msrs. + # Not a problem for chipsec driver but crashes RwDrv. + if self.check_vmm() == VMM_HYPER_V: return False mtrrcap_msr_reg = self.cs.read_register( 'MTRRCAP' ) if logger().VERBOSE: self.cs.print_register( 'MTRRCAP', mtrrcap_msr_reg ) smrr = self.cs.get_register_field( 'MTRRCAP', mtrrcap_msr_reg, 'SMRR' ) diff --git a/chipsec/helper/helpers.py b/chipsec/helper/helpers.py index 66b82621..78edbe1a 100644 --- a/chipsec/helper/helpers.py +++ b/chipsec/helper/helpers.py @@ -22,5 +22,6 @@ from chipsec.helper.efi import * from chipsec.helper.linux import * from chipsec.helper.osx import * +#from chipsec.helper.rwe import * from chipsec.helper.win import * diff --git a/chipsec/helper/rwe/__init__.py b/chipsec/helper/rwe/__init__.py new file mode 100644 index 00000000..f7c48c62 --- /dev/null +++ b/chipsec/helper/rwe/__init__.py @@ -0,0 +1,26 @@ +#!/usr/bin/python +#CHIPSEC: Platform Security Assessment Framework +#Copyright (c) 2010-2017, Intel Corporation +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; Version 2. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +#Contact information: +#chipsec@intel.com +# + +import platform, os +if "windows" == platform.system().lower() and os.environ.has_key("USERWE"): + __all__ = [ "rwehelper" ] +else: + __all__ = [ ] diff --git a/chipsec/helper/rwe/rwehelper.py b/chipsec/helper/rwe/rwehelper.py new file mode 100644 index 00000000..dc5adbb5 --- /dev/null +++ b/chipsec/helper/rwe/rwehelper.py @@ -0,0 +1,948 @@ +#CHIPSEC: Platform Security Assessment Framework +#Copyright (c) 2010-2017, Intel Corporation +# +#This program is free software; you can redistribute it and/or +#modify it under the terms of the GNU General Public License +#as published by the Free Software Foundation; Version 2. +# +#This program is distributed in the hope that it will be useful, +#but WITHOUT ANY WARRANTY; without even the implied warranty of +#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#GNU General Public License for more details. +# +#You should have received a copy of the GNU General Public License +#along with this program; if not, write to the Free Software +#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +#Contact information: +#chipsec@intel.com +# + +# ------------------------------------------------------------------------------- +# +# CHIPSEC: Platform Hardware Security Assessment Framework +# (c) 2010-2012 Intel Corporation +# +# ------------------------------------------------------------------------------- + +""" +Management and communication with Windows kernel mode driver which provides access to hardware resources + +.. note:: + On Windows you need to install pywin32 Python extension corresponding to your Python version: + http://sourceforge.net/projects/pywin32/ +""" + +__version__ = '1.0' + +import os.path +import struct +import sys +import platform +import re +import errno +import traceback +import time +from threading import Lock +from collections import namedtuple +from ctypes import * + +import pywintypes +import win32service #win32serviceutil, win32api, win32con +import winerror +from win32file import FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, FILE_FLAG_OVERLAPPED, INVALID_HANDLE_VALUE +import win32api, win32process, win32security, win32file, win32serviceutil + +from chipsec.helper.oshelper import Helper, OsHelperError, HWAccessViolationError, UnimplementedAPIError, UnimplementedNativeAPIError, get_tools_path +from chipsec.logger import logger, print_buffer +import chipsec.file +import chipsec.defines + + +class PCI_BDF(Structure): + _fields_ = [("BUS", c_ushort, 16), # Bus + ("DEV", c_ushort, 16), # Device + ("FUNC", c_ushort, 16), # Function + ("OFF", c_ushort, 16)] # Offset + + def cfg_address(self): + addr = (self.BUS << 16) | (self.DEV << 11) | (self.FUNC << 8) | (self.OFF & 0xFC) | 0x80000000 + return addr + +kernel32 = windll.kernel32 + + +drv_hndl_error_msg = "Cannot open rwe driver handle. Make sure rwe driver is installed and started if you are using option -e (see README)" + +DRIVER_FILE_NAME = "RwDrv.sys" +DEVICE_FILE = "\\\\.\\RwDrv" +SERVICE_NAME = "RwDrv" +DISPLAY_NAME = "RwDrv" + +CHIPSEC_INSTALL_PATH = os.path.join(sys.prefix, "Lib\site-packages\chipsec") + +# Status Codes +STATUS_PRIVILEGED_INSTRUCTION = 0xC0000096 + +# Defines for Win32 API Calls +GENERIC_READ = 0x80000000 +GENERIC_WRITE = 0x40000000 +OPEN_EXISTING = 0x3 + +FILE_DEVICE_UNKNOWN = 0x00000022 + +METHOD_BUFFERED = 0 +METHOD_IN_DIRECT = 1 +METHOD_OUT_DIRECT = 2 +METHOD_NEITHER = 3 + +FILE_ANY_ACCESS = 0 +FILE_SPECIAL_ACCESS = (FILE_ANY_ACCESS) +FILE_READ_ACCESS = ( 0x0001 ) +FILE_WRITE_ACCESS = ( 0x0002 ) + +def CTL_CODE( DeviceType, Function, Method, Access ): + return ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) + +# +# chipsec driver IOCTL codes +# +CHIPSEC_CTL_ACCESS = (FILE_ANY_ACCESS) + +#CLOSE_DRIVER = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +READ_PCI_CFG_REGISTER = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +WRITE_PCI_CFG_REGISTER = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_READ_PHYSMEM = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa02, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_WRITE_PHYSMEM = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa03, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +#IOCTL_LOAD_UCODE_PATCH = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80b, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_WRMSR = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa13, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_RDMSR = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa12, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_READ_IO_PORT_BYTE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa04, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_READ_IO_PORT_WORD = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa06, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_READ_IO_PORT_DWORD = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa08, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_WRITE_IO_PORT_BYTE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa05, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_WRITE_IO_PORT_WORD = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa07, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_WRITE_IO_PORT_DWORD = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa09, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +#IOCTL_GET_CPU_DESCRIPTOR_TABLE = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +#IOCTL_SWSMI = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x811, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) + + +IOCTL_ALLOC_PHYSMEM = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa20, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_FREE_PHYSMEM = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa21, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_RDCR = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa1b, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) +IOCTL_WRCR = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa1c, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) + +IOCTL_CPUID = CTL_CODE(FILE_DEVICE_UNKNOWN, 0xa14, METHOD_BUFFERED, CHIPSEC_CTL_ACCESS) + + +# +# NT Errors +# +# Defined in WinDDK\7600.16385.1\inc\api\ntstatus.h +# + +# +# UEFI constants +# +# Default buffer size for EFI variables +#EFI_VAR_MAX_BUFFER_SIZE = 128*1024 +EFI_VAR_MAX_BUFFER_SIZE = 1024*1024 + +attributes = { + "EFI_VARIABLE_NON_VOLATILE" : 0x00000001, + "EFI_VARIABLE_BOOTSERVICE_ACCESS" : 0x00000002, + "EFI_VARIABLE_RUNTIME_ACCESS" : 0x00000004, + "EFI_VARIABLE_HARDWARE_ERROR_RECORD" : 0x00000008, + "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS" : 0x00000010, + "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS" : 0x00000020, + "EFI_VARIABLE_APPEND_WRITE" : 0x00000040 +} + +PyLong_AsByteArray = pythonapi._PyLong_AsByteArray +PyLong_AsByteArray.argtypes = [py_object, + c_char_p, + c_size_t, + c_int, + c_int] + +def packl_ctypes( lnum, bitlength ): + length = (bitlength + 7)/8 + a = create_string_buffer( length ) + PyLong_AsByteArray(lnum, a, len(a), 1, 1) # 4th param is for endianness 0 - big, non 0 - little + return a.raw + +# +# Firmware Table Provider Signatures +# +FirmwareTableProviderSignature_ACPI = 0x41435049 # 'ACPI' - The ACPI firmware table provider +FirmwareTableProviderSignature_FIRM = 0x4649524D # 'FIRM' - The raw firmware table provider +FirmwareTableProviderSignature_RSMB = 0x52534D42 # 'RSMB' - The raw SMBIOS firmware table provider + +FirmwareTableID_RSDT = 0x54445352 +FirmwareTableID_XSDT = 0x54445358 + +# +# Windows 8 NtEnumerateSystemEnvironmentValuesEx (infcls = 2) +# +def guid_str(guid0, guid1, guid2, guid3): + return ( "%08X-%04X-%04X-%04s-%06s" % (guid0, guid1, guid2, guid3[:2].encode('hex').upper(), guid3[-6::].encode('hex').upper()) ) + +class EFI_HDR_WIN( namedtuple('EFI_HDR_WIN', 'Size DataOffset DataSize Attributes guid0 guid1 guid2 guid3') ): + __slots__ = () + def __str__(self): + return """ +Header (Windows) +---------------- +VendorGuid= {%08X-%04X-%04X-%04s-%06s} +Size = 0x%08X +DataOffset= 0x%08X +DataSize = 0x%08X +Attributes= 0x%08X +""" % ( self.guid0, self.guid1, self.guid2, self.guid3[:2].encode('hex').upper(), self.guid3[-6::].encode('hex').upper(), self.Size, self.DataOffset, self.DataSize, self.Attributes ) + +def getEFIvariables_NtEnumerateSystemEnvironmentValuesEx2( nvram_buf ): + start = 0 + buffer = nvram_buf + bsize = len(buffer) + header_fmt = ">32)&0xFFFFFFFF, phys_address&0xFFFFFFFF, size ) + if size == 8: + value = struct.unpack( '=Q', out_buf )[0] + elif size == 4: + value = struct.unpack( '=I', out_buf )[0] + elif size == 2: + value = struct.unpack( '=H', out_buf )[0] + elif size == 1: + value = struct.unpack( '=B', out_buf )[0] + else: value = 0 + return value + def write_mmio_reg( self, phys_address, size, value ): + #raise UnimplementedNativeAPIError( "write_mmio_reg" ) + if size == 8: buf = struct.pack( '=Q', value ) + elif size == 4: buf = struct.pack( '=I', value&0xFFFFFFFF ) + elif size == 2: buf = struct.pack( '=H', value&0xFFFF ) + elif size == 1: buf = struct.pack( '=B', value&0xFF ) + else: return False + return self.write_phys_mem( ((phys_address>>32)&0xFFFFFFFF), (phys_address&0xFFFFFFFF), size, buf ) + + def alloc_phys_mem( self, length, max_pa ): + #raise UnimplementedNativeAPIError( "alloc_phys_mem" ) + (va, pa) = (0,0) + out_length = 16 + out_buf = (c_char * out_length)() + in_buf = struct.pack( ' GetFirmwareEnvironmentVariable( name='%s', GUID='%s' ).." % (name, "{%s}" % guid) ) + length = self.GetFirmwareEnvironmentVariable( name, "{%s}" % guid, efi_var, EFI_VAR_MAX_BUFFER_SIZE ) + else: + if self.GetFirmwareEnvironmentVariableEx is not None: + pattrs = c_int(attrs) + if logger().HAL: logger().log( "[helper] -> GetFirmwareEnvironmentVariableEx( name='%s', GUID='%s', attrs = 0x%X ).." % (name, "{%s}" % guid, attrs) ) + length = self.GetFirmwareEnvironmentVariableEx( name, "{%s}" % guid, efi_var, EFI_VAR_MAX_BUFFER_SIZE, pattrs ) + if (0 == length) or (efi_var is None): + status = kernel32.GetLastError() + logger().error( 'GetFirmwareEnvironmentVariable[Ex] returned error: %s' % WinError() ) + efi_var_data = None + #raise WinError(errno.EIO,"Unable to get EFI variable") + else: + efi_var_data = efi_var[:length] + + return (status, efi_var_data, attrs) + + def get_EFI_variable( self, name, guid, attrs=None ): + (status, data, attributes) = self.get_EFI_variable_full( name, guid, attrs ) + return data + + def set_EFI_variable( self, name, guid, data, datasize, attrs ): + var = bytes(0) if data is None else data + var_len = len(var) if datasize is None else datasize + + if attrs is None: + if self.SetFirmwareEnvironmentVariable is not None: + if logger().HAL: logger().log( "[helper] -> SetFirmwareEnvironmentVariable( name='%s', GUID='%s', length=0x%X ).." % (name, "{%s}" % guid, var_len) ) + ntsts = self.SetFirmwareEnvironmentVariable( name, "{%s}" % guid, var, var_len ) + else: + if self.SetFirmwareEnvironmentVariableEx is not None: + if logger().HAL: logger().log( "[helper] -> SetFirmwareEnvironmentVariableEx( name='%s', GUID='%s', length=0x%X, length=0x%X ).." % (name, "{%s}" % guid, var_len, attrs) ) + ntsts = self.SetFirmwareEnvironmentVariableEx( name, "{%s}" % guid, var, var_len, attrs ) + if 0 != ntsts: + status = 0 # EFI_SUCCESS + else: + status = kernel32.GetLastError() + logger().error( 'SetFirmwareEnvironmentVariable[Ex] returned error: %s' % WinError() ) + #raise WinError(errno.EIO, "Unable to set EFI variable") + return status + + def delete_EFI_variable(self, name, guid): + return self.set_EFI_variable( name, guid, None, datasize=0, attrs=None ) + + def list_EFI_variables( self, infcls=2 ): + if logger().VERBOSE: logger().log( '[helper] -> NtEnumerateSystemEnvironmentValuesEx( infcls=%d )..' % infcls ) + efi_vars = create_string_buffer( EFI_VAR_MAX_BUFFER_SIZE ) + length = packl_ctypes( long(EFI_VAR_MAX_BUFFER_SIZE), 32 ) + status = self.NtEnumerateSystemEnvironmentValuesEx( infcls, efi_vars, length ) + status = ( ((1 << 32) - 1) & status) + if (0xC0000023 == status): + retlength, = struct.unpack(" table_size: + table_size = retVal + tBuffer = create_string_buffer( table_size ) + retVal = self.GetSystemFirmwareTbl( FirmwareTableProviderSignature_ACPI, tbl, tBuffer, table_size ) + return tBuffer[:retVal] + + # ACPI access is implemented through ACPI HAL rather than through kernel module + def get_ACPI_table( self ): + raise UnimplementedAPIError( "get_ACPI_table" ) + + + + # + # IOSF Message Bus access + # + + def msgbus_send_read_message( self, mcr, mcrx ): + logger().error( "[helper] Message Bus is not supported yet" ) + return None + + def msgbus_send_write_message( self, mcr, mcrx, mdr ): + logger().error( "[helper] Message Bus is not supported yet" ) + return None + + def msgbus_send_message( self, mcr, mcrx, mdr=None ): + logger().error( "[helper] Message Bus is not supported yet" ) + return None + + # + # File system + # + def get_tool_info( self, tool_type ): + tool_name = _tools[ tool_type ] if tool_type in _tools else None + tool_path = os.path.join( get_tools_path(), self.os_system.lower() ) + return tool_name,tool_path + +# +# Get instance of this OS helper +# +def get_helper(): + return RweHelper( ) diff --git a/chipsec/modules/common/smrr.py b/chipsec/modules/common/smrr.py index e116676e..3a171af5 100644 --- a/chipsec/modules/common/smrr.py +++ b/chipsec/modules/common/smrr.py @@ -42,11 +42,11 @@ class smrr(BaseModule): # # Check that SMRR are supported by CPU in IA32_MTRRCAP_MSR[SMRR] # - def check_SMRR_supported(self): - mtrrcap_msr_reg = self.cs.read_register( 'MTRRCAP' ) - if self.logger.VERBOSE: self.cs.print_register( 'MTRRCAP', mtrrcap_msr_reg ) - smrr = self.cs.get_register_field( 'MTRRCAP', mtrrcap_msr_reg, 'SMRR' ) - return (1 == smrr) + #def check_SMRR_supported(self): + #mtrrcap_msr_reg = self.cs.read_register( 'MTRRCAP' ) + #if self.logger.VERBOSE: self.cs.print_register( 'MTRRCAP', mtrrcap_msr_reg ) + #smrr = self.cs.get_register_field( 'MTRRCAP', mtrrcap_msr_reg, 'SMRR' ) + #return (1 == smrr) def check_SMRR(self, do_modify): if not self.cs.is_register_defined( 'MTRRCAP' ) or \ @@ -55,7 +55,7 @@ class smrr(BaseModule): self.logger.error( "Couldn't find definition of required configuration registers" ) return ModuleResult.ERROR - if self.check_SMRR_supported(): + if self.cs.cpu.check_SMRR_supported(): self.logger.log_good( "OK. SMRR range protection is supported" ) else: self.logger.log_important( "CPU does not support SMRR range protection of SMRAM" ) diff --git a/chipsec/modules/smm_dma.py b/chipsec/modules/smm_dma.py index 36f8791a..fe3427e5 100644 --- a/chipsec/modules/smm_dma.py +++ b/chipsec/modules/smm_dma.py @@ -61,15 +61,19 @@ class smm_dma(BaseModule): def check_tseg_config(self): res = ModuleResult.FAILED (tseg_base, tseg_limit, tseg_size ) = self.cs.cpu.get_TSEG() - (smram_base, smram_limit, smram_size) = self.cs.cpu.get_SMRR_SMRAM() self.logger.log("[*] TSEG : 0x%016X - 0x%016X (size = 0x%08X)" % (tseg_base, tseg_limit, tseg_size )) - self.logger.log("[*] SMRR range: 0x%016X - 0x%016X (size = 0x%08X)\n" % (smram_base, smram_limit, smram_size)) + if (self.cs.cpu.check_SMRR_supported()): + (smram_base, smram_limit, smram_size) = self.cs.cpu.get_SMRR_SMRAM() + self.logger.log("[*] SMRR range: 0x%016X - 0x%016X (size = 0x%08X)\n" % (smram_base, smram_limit, smram_size)) + else: + smram_base = 0 + smram_limit = 0 + self.logger.log("[*] SMRR is not supported\n") self.logger.log( "[*] checking TSEG range configuration.." ) if (0 == smram_base) and (0 == smram_limit): res = ModuleResult.WARNING self.logger.log_warn_check( "TSEG is properly configured but can't determine if it covers entire SMRAM" ) - else: if (tseg_base <= smram_base) and (smram_limit <= tseg_limit): #if (tseg_base == smram_base) and (tseg_size == smram_size):