Files
Daniel Schaefer ea7d64da75 Convert bytestostring before finding substring
Like in line 275 we need to convert to string before finding.
In Python3 bytes and strings are not the same and thus it would break.
2019-09-03 10:07:12 -07:00

562 lines
22 KiB
Python

#!/usr/bin/python
#CHIPSEC: Platform Security Assessment Framework
#Copyright (c) 2010-2019, 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-2018 Intel Corporation
#
# -------------------------------------------------------------------------------
"""
HAL component providing access to and decoding of ACPI tables
"""
__version__ = '0.1'
import struct
import sys
from collections import defaultdict
from collections import namedtuple
from chipsec.logger import *
from chipsec.file import *
from chipsec.defines import bytestostring
from chipsec.hal import acpi_tables, hal_base, uefi
from chipsec.helper import oshelper
class AcpiRuntimeError (RuntimeError):
pass
# ACPI Table Header Format
ACPI_TABLE_HEADER_FORMAT = '=4sIBB6s8sI4sI'
ACPI_TABLE_HEADER_SIZE = struct.calcsize(ACPI_TABLE_HEADER_FORMAT) # 36
assert( 36 == ACPI_TABLE_HEADER_SIZE )
class ACPI_TABLE_HEADER( namedtuple('ACPI_TABLE_HEADER', 'Signature Length Revision Checksum OEMID OEMTableID OEMRevision CreatorID CreatorRevision') ):
__slots__ = ()
def __str__(self):
return """ Table Header
------------------------------------------------------------------
Signature : {}
Length : 0x{:08X}
Revision : 0x{:02X}
Checksum : 0x{:02X}
OEM ID : {}
OEM Table ID : {}
OEM Revision : 0x{:08X}
Creator ID : {}
Creator Revision : 0x{:08X}
""".format( self.Signature, self.Length, self.Revision, self.Checksum, self.OEMID, self.OEMTableID, self.OEMRevision, self.CreatorID, self.CreatorRevision )
ACPI_TABLE_SIG_SIZE = 0x4
ACPI_TABLE_SIG_ROOT = 'ROOT'
ACPI_TABLE_SIG_RSDP = 'RSDP'
ACPI_TABLE_SIG_RSDT = 'RSDT'
ACPI_TABLE_SIG_XSDT = 'XSDT'
ACPI_TABLE_SIG_FACP = 'FACP'
ACPI_TABLE_SIG_FACS = 'FACS'
ACPI_TABLE_SIG_DSDT = 'DSDT'
ACPI_TABLE_SIG_SSDT = 'SSDT'
ACPI_TABLE_SIG_PSDT = 'PSDT'
ACPI_TABLE_SIG_APIC = 'APIC'
ACPI_TABLE_SIG_SBST = 'SBST'
ACPI_TABLE_SIG_ECDT = 'ECDT'
ACPI_TABLE_SIG_SRAT = 'SRAT'
ACPI_TABLE_SIG_SLIC = 'SLIC'
ACPI_TABLE_SIG_SLIT = 'SLIT'
ACPI_TABLE_SIG_BOOT = 'BOOT'
ACPI_TABLE_SIG_CPEP = 'CPEP'
ACPI_TABLE_SIG_DBGP = 'DBGP'
ACPI_TABLE_SIG_ETDT = 'ETDT'
ACPI_TABLE_SIG_HPET = 'HPET'
ACPI_TABLE_SIG_MCFG = 'MCFG'
ACPI_TABLE_SIG_SPCR = 'SPCR'
ACPI_TABLE_SIG_SPMI = 'SPMI'
ACPI_TABLE_SIG_TCPA = 'TCPA'
ACPI_TABLE_SIG_WDAT = 'WDAT'
ACPI_TABLE_SIG_WDRT = 'WDRT'
ACPI_TABLE_SIG_WSPT = 'WSPT'
ACPI_TABLE_SIG_WDDT = 'WDDT'
ACPI_TABLE_SIG_ASF = 'ASF!'
ACPI_TABLE_SIG_MSEG = 'MSEG'
ACPI_TABLE_SIG_DMAR = 'DMAR'
ACPI_TABLE_SIG_UEFI = 'UEFI'
ACPI_TABLE_SIG_FPDT = 'FPDT'
ACPI_TABLE_SIG_PCCT = 'PCCT'
ACPI_TABLE_SIG_MSDM = 'MSDM'
ACPI_TABLE_SIG_BATB = 'BATB'
ACPI_TABLE_SIG_BGRT = 'BGRT'
ACPI_TABLE_SIG_LPIT = 'LPIT'
ACPI_TABLE_SIG_ASPT = 'ASPT'
ACPI_TABLE_SIG_FIDT = 'FIDT'
ACPI_TABLE_SIG_HEST = 'HEST'
ACPI_TABLE_SIG_BERT = 'BERT'
ACPI_TABLE_SIG_ERST = 'ERST'
ACPI_TABLE_SIG_EINJ = 'EINJ'
ACPI_TABLE_SIG_TPM2 = 'TPM2'
ACPI_TABLE_SIG_WSMT = 'WSMT'
ACPI_TABLE_SIG_DBG2 = 'DBG2'
ACPI_TABLE_SIG_NHLT = 'NHLT'
ACPI_TABLE_SIG_MSCT = 'MSCT'
ACPI_TABLE_SIG_RASF = 'RASF'
ACPI_TABLE_SIG_SPMI = 'SPMI'
ACPI_TABLE_SIG_OEM1 = 'OEM1'
ACPI_TABLE_SIG_OEM2 = 'OEM2'
ACPI_TABLE_SIG_OEM3 = 'OEM3'
ACPI_TABLE_SIG_OEM4 = 'OEM4'
ACPI_TABLE_SIG_NFIT = 'NFIT'
ACPI_TABLES = {
ACPI_TABLE_SIG_ROOT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_RSDT: acpi_tables.RSDT,
ACPI_TABLE_SIG_XSDT: acpi_tables.XSDT,
ACPI_TABLE_SIG_FACP: acpi_tables.FADT,
ACPI_TABLE_SIG_FACS: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_DSDT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_SSDT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_PSDT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_APIC: acpi_tables.APIC,
ACPI_TABLE_SIG_SBST: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_ECDT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_SRAT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_SLIC: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_SLIT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_BOOT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_CPEP: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_DBGP: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_ETDT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_HPET: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_MCFG: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_SPCR: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_SPMI: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_TCPA: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_WDAT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_WDRT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_WSPT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_WDDT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_ASF : acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_MSEG: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_DMAR: acpi_tables.DMAR,
ACPI_TABLE_SIG_UEFI: acpi_tables.UEFI_TABLE,
ACPI_TABLE_SIG_FPDT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_PCCT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_MSDM: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_BATB: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_BGRT: acpi_tables.BGRT,
ACPI_TABLE_SIG_LPIT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_ASPT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_FIDT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_HEST: acpi_tables.HEST,
ACPI_TABLE_SIG_BERT: acpi_tables.BERT,
ACPI_TABLE_SIG_ERST: acpi_tables.ERST,
ACPI_TABLE_SIG_EINJ: acpi_tables.EINJ,
ACPI_TABLE_SIG_TPM2: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_WSMT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_DBG2: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_NHLT: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_MSCT: acpi_tables.MSCT,
ACPI_TABLE_SIG_RASF: acpi_tables.RASF,
ACPI_TABLE_SIG_SPMI: acpi_tables.SPMI,
ACPI_TABLE_SIG_OEM1: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_OEM2: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_OEM3: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_OEM4: acpi_tables.ACPI_TABLE,
ACPI_TABLE_SIG_NFIT: acpi_tables.NFIT
}
########################################################################################################
#
# RSDP
#
########################################################################################################
RSDP_GUID_ACPI2_0 = '8868E871-E4F1-11D3-BC22-0080C73C8881'
RSDP_GUID_ACPI1_0 = 'EB9D2D31-2D88-11D3-9A16-0090273FC14D'
ACPI_RSDP_SIG = 'RSD PTR '
# RSDP Format
ACPI_RSDP_FORMAT = '<8sB6sBI'
ACPI_RSDP_EXT_FORMAT = 'IQB3s'
ACPI_RSDP_SIZE = struct.calcsize(ACPI_RSDP_FORMAT)
ACPI_RSDP_EXT_SIZE = struct.calcsize(ACPI_RSDP_FORMAT + ACPI_RSDP_EXT_FORMAT)
assert ACPI_RSDP_EXT_SIZE == 36
class RSDP():
def __init__( self, table_content ):
if len(table_content) == ACPI_RSDP_SIZE:
(self.Signature, self.Checksum, self.OEMID,
self.Revision, self.RsdtAddress) = struct.unpack(ACPI_RSDP_FORMAT, table_content)
else:
(self.Signature, self.Checksum, self.OEMID,
self.Revision, self.RsdtAddress, self.Length,
self.XsdtAddress, self.ExtChecksum, self.Reserved) = struct.unpack(ACPI_RSDP_FORMAT + ACPI_RSDP_EXT_FORMAT, table_content)
def __str__( self ):
default = ("==================================================================\n"
" Root System Description Pointer (RSDP)\n"
"==================================================================\n"
" Signature : {}\n"
" Checksum : 0x{:02X}\n"
" OEM ID : {}\n"
" Revision : 0x{:02X}\n"
" RSDT Address : 0x{:08X}\n"
).format(self.Signature, self.Checksum, self.OEMID, self.Revision, self.RsdtAddress)
if hasattr(self, "Length"):
default += (" Length : 0x{:08X}\n"
" XSDT Address : 0x{:016X}\n"
" Extended Checksum: 0x{:02X}\n"
" Reserved : {}\n"
).format(self.Length, self.XsdtAddress, self.ExtChecksum, self.Reserved.encode("hex") if ( isinstance(self.Reserved,str) ) else self.Reserved.hex() )
return default
# some sanity checking on RSDP
def is_RSDP_valid(self ):
return (0 != self.Checksum and (0x0 == self.Revision or 0x2 == self.Revision) )
########################################################################################################
#
# ACPI HAL Component
#
########################################################################################################
class ACPI(hal_base.HALBase):
def __init__(self, cs):
super(ACPI, self).__init__(cs)
self.uefi = uefi.UEFI(self.cs)
self.tableList = defaultdict(list)
self.get_ACPI_table_list()
def read_RSDP(self, rsdp_pa):
rsdp_buf = self.cs.mem.read_physical_mem( rsdp_pa, ACPI_RSDP_SIZE)
rsdp = RSDP(rsdp_buf)
if rsdp.Revision >= 0x2:
rsdp_buf = self.cs.mem.read_physical_mem( rsdp_pa, ACPI_RSDP_EXT_SIZE)
rsdp = RSDP(rsdp_buf)
return rsdp
#
# Check RSDP in Extended BIOS Data Area
#
def _find_RSDP_in_EBDA(self):
rsdp_pa = None
rsdp = None
if logger().HAL: logger().log( "[acpi] searching RSDP in EBDA.." )
ebda_ptr_addr = 0x40E
ebda_addr = struct.unpack('<H', self.cs.mem.read_physical_mem( ebda_ptr_addr, 2 ))[0] << 4
if ebda_addr > 0x400 and ebda_addr < 0xA0000:
membuf = self.cs.mem.read_physical_mem(ebda_addr, 0xA0000 - ebda_addr)
pos = bytestostring(membuf).find( ACPI_RSDP_SIG )
if -1 != pos:
rsdp_pa = ebda_addr + pos
rsdp = self.read_RSDP(rsdp_pa)
if rsdp.is_RSDP_valid():
if logger().HAL: logger().log( "[acpi] found RSDP in EBDA at: 0x{:016X}".format(rsdp_pa) )
else:
rsdp_pa = None
return rsdp, rsdp_pa
#
# Search RSDP in legacy BIOS E/F segments (0xE0000 - 0xFFFFF)
#
def _find_RSDP_in_legacy_BIOS_segments(self):
rsdp_pa = None
rsdp = None
membuf = self.cs.mem.read_physical_mem( 0xE0000, 0x20000 )
membuf = bytestostring(membuf)
pos = bytestostring(membuf).find( ACPI_RSDP_SIG )
if -1 != pos:
rsdp_pa = 0xE0000 + pos
rsdp = self.read_RSDP(rsdp_pa)
if rsdp.is_RSDP_valid():
if logger().HAL: logger().log( "[acpi] found RSDP in BIOS E/F segments: 0x{:016X}".format(rsdp_pa) )
else:
rsdp_pa = None
return rsdp, rsdp_pa
#
# Search for RSDP in the EFI memory (EFI Configuration Table)
#
def _find_RSDP_in_EFI_config_table(self):
rsdp_pa = None
rsdp = None
if logger().HAL: logger().log( '[acpi] searching RSDP pointers in EFI Configuration Table..' )
(isFound,ect_pa,ect,ect_buf) = self.uefi.find_EFI_Configuration_Table()
if isFound:
if RSDP_GUID_ACPI2_0 in ect.VendorTables:
rsdp_pa = ect.VendorTables[ RSDP_GUID_ACPI2_0 ]
if logger().HAL: logger().log( '[acpi] ACPI 2.0+ RSDP {{{}}} in EFI Config Table: 0x{:016X}'.format(RSDP_GUID_ACPI2_0,rsdp_pa) )
elif RSDP_GUID_ACPI1_0 in ect.VendorTables:
rsdp_pa = ect.VendorTables[ RSDP_GUID_ACPI1_0 ]
if logger().HAL: logger().log( '[acpi] ACPI 1.0 RSDP {{{}}} in EFI Config Table: 0x{:016X}'.format(RSDP_GUID_ACPI1_0,rsdp_pa) )
rsdp = self.read_RSDP(rsdp_pa)
if rsdp.is_RSDP_valid():
if logger().HAL: logger().log( "[acpi] found RSDP in EFI Config Table: 0x{:016X}".format(rsdp_pa) )
else:
rsdp_pa = None
return rsdp, rsdp_pa
#
# Search for RSDP in all EFI memory
#
def _find_RSDP_in_EFI(self):
rsdp_pa = None
rsdp = None
if logger().HAL: logger().log( "[acpi] searching all EFI memory for RSDP (this may take a minute).." )
CHUNK_SZ = 1024*1024 # 1MB
(smram_base, smram_limit, smram_size) = self.cs.cpu.get_SMRAM()
pa = smram_base - CHUNK_SZ
while pa > CHUNK_SZ:
membuf = self.cs.mem.read_physical_mem( pa, CHUNK_SZ )
pos = bytestostring(membuf).find( ACPI_RSDP_SIG )
if -1 != pos:
rsdp_pa = pa + pos
if logger().HAL: logger().log( "[acpi] found '{}' signature at 0x{:16X}. Checking if valid RSDP..".format(ACPI_RSDP_SIG,rsdp_pa) )
rsdp = self.read_RSDP(rsdp_pa)
if rsdp.is_RSDP_valid():
if logger().HAL: logger().log( "[acpi] found RSDP in EFI memory: 0x{:016X}".format(rsdp_pa) )
break
pa -= CHUNK_SZ
return rsdp, rsdp_pa
#
# Searches for Root System Description Pointer (RSDP) in various locations for legacy/EFI systems
#
def find_RSDP( self ):
rsdp, rsdp_pa = self._find_RSDP_in_EBDA()
if rsdp_pa is None:
rsdp, rsdp_pa = self._find_RSDP_in_legacy_BIOS_segments()
if rsdp_pa is None:
rsdp, rsdp_pa = self._find_RSDP_in_EFI_config_table()
if rsdp_pa is None:
rsdp, rsdp_pa = self._find_RSDP_in_EFI()
if rsdp_pa is not None:
if logger().HAL: logger().log( rsdp )
return (rsdp_pa, rsdp)
#
# Retrieves System Description Table (RSDT or XSDT) either from RSDP or using OS API
#
def get_SDT( self, search_rsdp=True ):
if search_rsdp:
(rsdp_pa, rsdp) = self.find_RSDP()
if 0x0 == rsdp.Revision:
sdt_pa = rsdp.RsdtAddress
is_xsdt = False
elif 0x2 == rsdp.Revision:
sdt_pa = rsdp.XsdtAddress
is_xsdt = True
else:
return (False,None,None,None)
if logger().HAL: logger().log( "[acpi] found {} at PA: 0x{:016X}".format('XSDT' if is_xsdt else 'RSDT', sdt_pa) )
sdt_header_buf = self.cs.mem.read_physical_mem( sdt_pa, ACPI_TABLE_HEADER_SIZE )
sdt_header = self._parse_table_header( sdt_header_buf )
sdt_buf = self.cs.mem.read_physical_mem( sdt_pa, sdt_header.Length )
else:
sdt_pa = None
if logger().HAL: logger().log( "[acpi] reading RSDT/XSDT using OS API.." )
(sdt_buf, is_xsdt) = self.cs.helper.get_ACPI_SDT()
sdt_header = self._parse_table_header( sdt_buf[ :ACPI_TABLE_HEADER_SIZE] )
sdt_contents = sdt_buf[ ACPI_TABLE_HEADER_SIZE : ]
sdt = ACPI_TABLES[ACPI_TABLE_SIG_XSDT if is_xsdt else ACPI_TABLE_SIG_RSDT]()
sdt.parse( sdt_contents )
return (is_xsdt,sdt_pa,sdt,sdt_header)
#
# Populates a list of ACPI tables available on the system
#
def get_ACPI_table_list( self ):
try:
# 1. Try to extract ACPI table(s) from physical memory
# read_physical_mem can be implemented using both
# CHIPSEC kernel module and OS native API
if logger().HAL: logger().log( "[acpi] trying to enumerate ACPI tables from physical memory..." )
# find RSDT/XSDT table
(is_xsdt,sdt_pa,sdt,sdt_header) = self.get_SDT()
# cache RSDT/XSDT in the list of ACPI tables
if sdt_pa is not None: self.tableList[ bytestostring(sdt_header.Signature) ].append(sdt_pa)
self.get_table_list_from_SDT(sdt, is_xsdt)
self.get_DSDT_from_FADT()
except oshelper.UnimplementedNativeAPIError:
# 2. If didn't work, try using get_ACPI_table if a helper implemented
# reading ACPI tables via native API which some OS may provide
if self.cs.use_native_api():
if logger().HAL: logger().log( "[acpi] trying to enumerate ACPI tables using get_ACPI_table..." )
for t in ACPI_TABLES.keys():
table = self.cs.helper.get_ACPI_table( t )
if table: self.tableList[ t ].append( 0 )
return self.tableList
#
# Gets table list from entries in RSDT/XSDT
#
def get_table_list_from_SDT(self, sdt, is_xsdt):
if logger().HAL: logger().log( '[acpi] Getting table list from entries in {}'.format('XSDT' if is_xsdt else 'RSDT') )
for a in sdt.Entries:
_sig = self.cs.mem.read_physical_mem( a, ACPI_TABLE_SIG_SIZE )
_sig = bytestostring(_sig)
if _sig not in ACPI_TABLES.keys():
if logger().HAL: logger().warn( 'Unknown ACPI table signature: {}'.format(_sig) )
self.tableList[ _sig ].append(a)
#
# Gets DSDT from FADT
#
def get_DSDT_from_FADT(self):
if logger().HAL: logger().log( '[acpi] Getting DSDT from FADT' )
if ACPI_TABLE_SIG_FACP in self.tableList:
(_, parsed_fadt_content, _, _) = self.get_parse_ACPI_table('FACP')[0]
else:
if logger().HAL: logger().warn( 'Cannot find FADT in {}'.format('XSDT' if ACPI_TABLE_SIG_XSDT in self.tableList else 'RSDT') )
return
dsdt_address_to_use = parsed_fadt_content.get_DSDT_address_to_use()
if dsdt_address_to_use is None:
dsdt_address = parsed_fadt_content.dsdt
x_dsdt_address = parsed_fadt_content.x_dsdt
if logger().HAL: logger().error( 'Unable to determine the correct DSDT address' )
if logger().HAL: logger().error( ' DSDT address = 0x{:08X}'.format(dsdt_address) )
if logger().HAL: logger().error( ' X_DSDT address = 0x{}'.format("{:16X}".format(x_dsdt_address)) if x_dsdt_address is not None else 'Not found')
return
self.tableList[ ACPI_TABLE_SIG_DSDT ].append(dsdt_address_to_use)
#
# Checks is ACPI table with <name> is available on the system
#
def is_ACPI_table_present( self, name ):
return (name in self.tableList)
#
# Prints a list of ACPI tables available on the system
#
def print_ACPI_table_list(self):
if len( self.tableList ) == 0:
logger().error("Couldn't get a list of ACPI tables")
else:
if logger().HAL: logger().log( "[acpi] Found the following ACPI tables:" )
for tableName in sorted(self.tableList.keys()):
logger().log( " - {}: {}".format(tableName, ", ".join([("0x{:016X}".format(addr) ) for addr in self.tableList[tableName]])) )
#
# Retrieves contents of ACPI table from memory or from file
#
def get_parse_ACPI_table( self, name, isfile = False ):
acpi_tables = self.get_ACPI_table(name, isfile)
return [self._parse_table( name, table_header_blob, table_blob ) for (table_header_blob, table_blob) in acpi_tables if table_header_blob is not None]
def get_ACPI_table( self, name, isfile = False ):
acpi_tables_data = []
if isfile:
acpi_tables_data.append(read_file( name ))
else:
try:
# 1. Try to extract ACPI table(s) from physical memory
# read_physical_mem can be implemented using both
# CHIPSEC kernel module and OS native API
if logger().HAL: logger().log( "[acpi] trying to extract ACPI table from physical memory..." )
for table_address in self.tableList[name]:
t_size = self.cs.mem.read_physical_mem_dword( table_address + 4 )
t_data = self.cs.mem.read_physical_mem( table_address, t_size )
acpi_tables_data.append( t_data )
except oshelper.UnimplementedNativeAPIError:
# 2. If didn't work, try using get_ACPI_table if a helper implemented
# reading ACPI tables via native API which some OS may provide
if self.cs.use_native_api():
if logger().HAL: logger().log( "[acpi] trying to extract ACPI table using get_ACPI_table..." )
t_data = self.cs.helper.get_ACPI_table( name )
acpi_tables_data.append( t_data )
acpi_tables = []
for data in acpi_tables_data:
acpi_tables.append((data[ : ACPI_TABLE_HEADER_SIZE ], data[ ACPI_TABLE_HEADER_SIZE : ]))
return acpi_tables
#
# Dumps contents of ACPI table
#
def dump_ACPI_table( self, name, isfile = False ):
acpi_tables = self.get_parse_ACPI_table( name, isfile )
for acpi_table in acpi_tables:
(table_header,table,table_header_blob,table_blob) = acpi_table
logger().log( "==================================================================" )
logger().log( "ACPI Table: {}".format(name) )
logger().log( "==================================================================" )
# print table header
logger().log( table_header )
print_buffer( bytestostring(table_header_blob) )
# print table contents
logger().log( '' )
logger().log( table )
print_buffer( bytestostring(table_blob) )
logger().log( '' )
# --------------------------------------------------------------------
# Internal ACPI table parsing functions
# --------------------------------------------------------------------
def _parse_table( self, name, table_header_blob, table_blob ):
table_header = self._parse_table_header( table_header_blob )
table = self._parse_table_contents( name, table_blob, table_header_blob )
return (table_header,table,table_header_blob,table_blob)
def _parse_table_header( self, header ):
acpi_table_hdr = ACPI_TABLE_HEADER( *struct.unpack_from( ACPI_TABLE_HEADER_FORMAT, header ) )
if logger().HAL: logger().log( acpi_table_hdr )
return acpi_table_hdr
def _parse_table_contents( self, signature, contents, header ):
table = None
if ACPI_TABLES.__contains__(signature):
if logger().HAL: logger().log('{}'.format(signature))
if 'BERT' in signature:
table = (ACPI_TABLES[signature])(self.cs)
elif 'NFIT' in signature:
table = (ACPI_TABLES[signature])(header)
else:
table = (ACPI_TABLES[signature])()
table.parse( contents )
return table