mirror of
https://github.com/chipsec/chipsec
synced 2026-06-08 13:31:00 +00:00
79f81bbb7e
This commit fixes whitespace errors from checkers W291,W292,W293,W391. They were found by running "flake8 ." from the root directory. These are errors defined by "pycodestyle", and have no functional impact to the source. This is simply fixing whitespace as defined by CHIPSEC's .flake8 configuration. background: https://www.flake8rules.com/rules/W291.html https://www.flake8rules.com/rules/W292.html https://www.flake8rules.com/rules/W293.html https://www.flake8rules.com/rules/W391.html tool versions: flake8 v7.3.0, python v3.13.11 Signed-off-by: William Leara <william.leara@dell.com>
182 lines
7.7 KiB
Python
182 lines
7.7 KiB
Python
# CHIPSEC: Platform Security Assessment Framework
|
|
# Copyright (c) 2010-2021, 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
|
|
#
|
|
|
|
"""
|
|
Access to physical memory
|
|
|
|
usage:
|
|
>>> read_physical_mem( 0xf0000, 0x100 )
|
|
>>> write_physical_mem( 0xf0000, 0x100, buffer )
|
|
>>> write_physical_mem_dowrd( 0xf0000, 0xdeadbeef )
|
|
>>> read_physical_mem_dowrd( 0xfed40000 )
|
|
"""
|
|
|
|
from struct import unpack, pack
|
|
from typing import Any, Dict, Tuple, Optional
|
|
from chipsec.hal.hal_base import HALBase
|
|
from chipsec.library.logger import print_buffer_bytes
|
|
from chipsec.library.bits import make_mask
|
|
|
|
|
|
class Memory(HALBase):
|
|
def __init__(self, cs):
|
|
super(Memory, self).__init__(cs)
|
|
self.helper = cs.helper
|
|
|
|
####################################################################################
|
|
#
|
|
# Physical memory API using 64b Physical Address
|
|
# (Same functions as below just using 64b PA instead of High and Low 32b parts of PA)
|
|
#
|
|
####################################################################################
|
|
|
|
# Reading physical memory
|
|
|
|
def read_physical_mem(self, phys_address: int, length: int) -> bytes:
|
|
self.logger.log_hal(f'[mem] 0x{phys_address:016X}')
|
|
return self.helper.read_phys_mem(phys_address, length)
|
|
|
|
def read_physical_mem_qword(self, phys_address: int) -> int:
|
|
out_buf = self.read_physical_mem(phys_address, 8)
|
|
value = unpack('=Q', out_buf)[0]
|
|
self.logger.log_hal(f'[mem] qword at PA = 0x{phys_address:016X}: 0x{value:016X}')
|
|
return value
|
|
|
|
def read_physical_mem_dword(self, phys_address: int) -> int:
|
|
out_buf = self.read_physical_mem(phys_address, 4)
|
|
value = unpack('=I', out_buf)[0]
|
|
self.logger.log_hal(f'[mem] dword at PA = 0x{phys_address:016X}: 0x{value:08X}')
|
|
return value
|
|
|
|
def read_physical_mem_word(self, phys_address: int) -> int:
|
|
out_buf = self.read_physical_mem(phys_address, 2)
|
|
value = unpack('=H', out_buf)[0]
|
|
self.logger.log_hal(f'[mem] word at PA = 0x{phys_address:016X}: 0x{value:04X}')
|
|
return value
|
|
|
|
def read_physical_mem_byte(self, phys_address: int) -> int:
|
|
out_buf = self.read_physical_mem(phys_address, 1)
|
|
value = unpack('=B', out_buf)[0]
|
|
self.logger.log_hal(f'[mem] byte at PA = 0x{phys_address:016X}: 0x{value:02X}')
|
|
return value
|
|
|
|
# Writing physical memory
|
|
|
|
def write_physical_mem(self, phys_address: int, length: int, buf: bytes) -> int:
|
|
if self.logger.HAL:
|
|
self.logger.log(f'[mem] buffer len = 0x{length:X} to PA = 0x{phys_address:016X}')
|
|
print_buffer_bytes(buf)
|
|
return self.helper.write_phys_mem(phys_address, length, buf)
|
|
|
|
def write_physical_mem_dword(self, phys_address: int, dword_value: int) -> int:
|
|
self.logger.log_hal(f'[mem] dword to PA = 0x{phys_address:016X} <- 0x{dword_value:08X}')
|
|
return self.write_physical_mem(phys_address, 4, pack('I', dword_value))
|
|
|
|
def write_physical_mem_word(self, phys_address: int, word_value: int) -> int:
|
|
self.logger.log_hal(f'[mem] word to PA = 0x{phys_address:016X} <- 0x{word_value:04X}')
|
|
return self.write_physical_mem(phys_address, 2, pack('H', word_value))
|
|
|
|
def write_physical_mem_byte(self, phys_address: int, byte_value: int) -> int:
|
|
self.logger.log_hal(f'[mem] byte to PA = 0x{phys_address:016X} <- 0x{byte_value:02X}')
|
|
return self.write_physical_mem(phys_address, 1, pack('B', byte_value))
|
|
|
|
# Allocate physical memory buffer
|
|
|
|
def alloc_physical_mem(self, length: int, max_phys_address: int = 0xFFFFFFFFFFFFFFFF) -> Tuple[int, int]:
|
|
(va, pa) = self.helper.alloc_phys_mem(length, max_phys_address)
|
|
self.logger.log_hal(f'[mem] Allocated: PA = 0x{pa:016X}, VA = 0x{va:016X}')
|
|
return (va, pa)
|
|
|
|
def va2pa(self, va: int) -> Optional[int]:
|
|
(pa, error_code) = self.helper.va2pa(va)
|
|
if error_code:
|
|
self.logger.log_hal(f'[mem] Looks like VA (0x{va:016X}) not mapped')
|
|
return None
|
|
self.logger.log_hal(f'[mem] VA (0x{va:016X}) -> PA (0x{pa:016X})')
|
|
return pa
|
|
|
|
# Map physical address to virtual
|
|
|
|
def map_io_space(self, pa: int, length: int, cache_type: int) -> int:
|
|
va = self.helper.map_io_space(pa, length, cache_type)
|
|
self.logger.log_hal(f'[mem] Mapped: PA = 0x{pa:016X}, VA = 0x{va:016X}')
|
|
return va
|
|
|
|
# Free physical memory buffer
|
|
|
|
def free_physical_mem(self, pa: int) -> bool:
|
|
ret = self.helper.free_phys_mem(pa)
|
|
self.logger.log_hal(f'[mem] Deallocated : PA = 0x{pa:016X}')
|
|
return True if ret == 1 else False
|
|
|
|
def set_mem_bit(self, addr: int, bit: int) -> int:
|
|
addr += bit >> 3
|
|
byte = self.read_physical_mem_byte(addr)
|
|
self.write_physical_mem_byte(addr, (byte | (0x1 << (bit & 0x7))))
|
|
return byte
|
|
|
|
# reference: https://github.com/tianocore/edk2/blob/c4fdec0a83d69bd0399b1b4351fa9c3af3c6fd65/UefiCpuPkg/Library/MtrrLib/MtrrLib.c#L816
|
|
def get_max_memory_bit_size(self):
|
|
CPU_EXTENDED_FUNCTION = 0x80000000
|
|
CPU_VIR_PHY_ADDRESS_SIZE = 0x80000008
|
|
CPUID_SIG = 0
|
|
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS = 0x7
|
|
NONINTEL_DEFAULT_MAX_PA_SIZE = 36
|
|
MSR_IA32_TME_ACTIVATE = 0x982
|
|
MSR_TME_ACTIVATE_ENABLED_BIT = 1
|
|
MSR_TME_ACTIVATE_ENABLED_BIT_SIZE = 1
|
|
MSR_TME_ACTIVATE_MKTME_KEYID_BIT = 32
|
|
MSR_TME_ACTIVATE_MKTME_KEYID_BIT_SIZE = 4
|
|
phys_address_size = 0
|
|
DEFAULT_THREAD_ID = 0
|
|
eax, _, _, _ = self.helper.cpuid(CPU_EXTENDED_FUNCTION, 0)
|
|
if eax >= CPU_VIR_PHY_ADDRESS_SIZE:
|
|
eax, _, _, _ = self.helper.cpuid(CPU_VIR_PHY_ADDRESS_SIZE, 0)
|
|
phys_address_size = self.get_value_from_bit_def(eax, 0, 8)
|
|
else:
|
|
phys_address_size = NONINTEL_DEFAULT_MAX_PA_SIZE # If not defined in CPUID, assume size 36 and non-standard Intel CPU
|
|
max_func, _, _, _ = self.helper.cpuid(CPUID_SIG, 0)
|
|
if max_func >= 0x7:
|
|
_, _, ex_feature, _ = self.helper.cpuid(CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, 0)
|
|
ex_func = self.get_value_from_bit_def(ex_feature, 13, 1)
|
|
if ex_func == 1:
|
|
tme_active = self.helper.read_msr(DEFAULT_THREAD_ID, MSR_IA32_TME_ACTIVATE)
|
|
if self.get_value_from_bit_def(tme_active, MSR_TME_ACTIVATE_ENABLED_BIT, MSR_TME_ACTIVATE_ENABLED_BIT_SIZE) > 0:
|
|
phys_address_size -= self.get_value_from_bit_def(tme_active, MSR_TME_ACTIVATE_MKTME_KEYID_BIT, MSR_TME_ACTIVATE_MKTME_KEYID_BIT_SIZE)
|
|
return phys_address_size
|
|
|
|
def get_max_memory_mask(self):
|
|
size = self.get_max_memory_bit_size()
|
|
return make_mask(size)
|
|
|
|
|
|
def get_value_from_bit_def(self, inputValue, fieldStartBit, fieldSize):
|
|
return (inputValue >> fieldStartBit) & self.get_bit_mask(fieldSize)
|
|
|
|
def get_def(self, range_name: str) -> Dict[str, Any]:
|
|
'''Return address access of a MEM register'''
|
|
ranges = self.cs.Cfg.get_objlist(range_name)
|
|
if ranges:
|
|
return ranges[0]
|
|
return None
|
|
|
|
|
|
haldata = {"arch":[HALBase.MfgIds.Any], 'name': {'memory': "Memory"}}
|