Files
Nathaniel Mitchell 1259e568de Change all HAL objects in cs.hals to be lowercase
Signed-off-by: Nathaniel Mitchell <nathaniel.p.mitchell@intel.com>
2025-12-09 13:49:37 -08:00

211 lines
8.2 KiB
Python

# CHIPSEC: Platform Security Assessment Framework
# Copyright (c) 2019-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
#
__version__ = '1.2'
from typing import List, Optional, Tuple
from chipsec.library.defines import bit, is_set
from chipsec.hal.hal_base import HALBase
from chipsec.library.exceptions import CSReadError, HWAccessViolationError
class LockResult:
DEFINED = bit(0) # lock exists within configuration
HAS_CONFIG = bit(1) # lock configuration exists
LOCKED = bit(2) # lock matches value within xml
CAN_READ = bit(3) # system is able to access the lock
INCONSISTENT = bit(4) # all lock results do not match
class Locks(HALBase):
def __init__(self, cs):
super(Locks, self).__init__(cs)
def get_locks(self) -> List[str]:
"""
Return a list of locks defined within the configuration file
"""
return self.cs.lock.get_list()
def set_cache(self, lock_obj: "LOCKSHelper", reg_obj_list: List["RegisterHelper"]) -> None:
"""
Set the cache for the lock and its associated registers.
Arguments:
lock_obj: The lock object containing the lock definition.
reg_obj_list: A list of register objects associated with the lock.
"""
self.lock_cache = lock_obj
self.reg_cache = reg_obj_list
def clear_cache(self) -> None:
"""
Clear the cache for the lock and its associated registers.
"""
self.lock_cache = None
self.reg_cache = None
def get_cache(self) -> Tuple[Optional["LOCKSHelper"], Optional[List["RegisterHelper"]]]:
"""
Get the cached lock and register objects.
Returns:
A tuple containing the cached lock object and a list of register objects.
"""
return (self.lock_cache, self.reg_cache)
def read_lock(self) -> int:
"""
Read the lock value from the cached register.
Returns:
The value of the lock field.
"""
if self.lock_cache is None or self.reg_cache is None:
raise CSReadError('Lock cache is not set')
return self.reg_cache.read_field(self.lock_cache.field)
def lock_valid(self, lock_name: str, instance: Optional["instance"] = None) -> int:
"""
Validate the lock by its name and instance.
Arguments:
lock_name: The name of the lock to validate.
instance: Optional instance to validate against.
Returns:
An integer representing the validation result, which can include:
- LockResult.DEFINED: Lock is defined in the configuration.
- LockResult.HAS_CONFIG: Lock has a configuration.
- LockResult.CAN_READ: Lock can be read.
- LockResult.INCONSISTENT: Lock values are inconsistent.
- LockResult.LOCKED: Lock is locked with the expected value.
"""
self.clear_cache()
res = self.validate_lock_definition(lock_name)
if not res:
return res
lock_obj = self.cs.lock.get(lock_name)
reg_list = self.get_registers(lock_obj, instance)
self.set_cache(lock_obj, reg_list)
if not reg_list:
self.logger.log_hal(f"Lock '{lock_name}' has no register defined")
return res
if not lock_obj.has_lock_value():
self.logger.log_hal(f"Lock '{lock_name}' has no lock value defined")
return res
if not reg_list[0].has_field(lock_obj.get_field()):
self.logger.log_hal(f"Lock '{lock_name}' has no field defined")
return res
res |= LockResult.HAS_CONFIG
try:
self.read_lock()
res |= LockResult.CAN_READ
except CSReadError as e:
self.logger.log_hal(f"Error reading lock: {e}")
except HWAccessViolationError as e:
self.logger.log_hal(f"Hardware access violation: {e}")
return res
def is_locked(self, lock_name: str, bus: Optional[int] = None) -> int:
"""
Return whether the lock has the value setting
Arguments:
lock_name: The name of the lock to check.
bus: Optional bus number to specify the bus context.
Returns:
An integer representing the lock state, which can include:
- LockResult.INCONSISTENT: Lock values are inconsistent.
- LockResult.LOCKED: Lock is locked with the expected value.
"""
res = self.lock_valid(lock_name, bus)
if is_set(res, LockResult.HAS_CONFIG) and is_set(res, LockResult.CAN_READ):
res |= self._is_lock_consistent()
res |= self._check_lock_values()
return res
def _is_lock_consistent(self) -> int:
"""
Check if the lock is consistent across all registers.
Returns:
An integer indicating the consistency of the lock.
Returns LockResult.INCONSISTENT if the values are not consistent.
Returns 0 if they are consistent.
"""
lock_obj, reg_list = self.get_cache()
lock_field = lock_obj.get_field()
reg_list.read()
if not reg_list.is_all_field_value(reg_list[0].get_field(lock_field), lock_field):
return LockResult.INCONSISTENT
return 0
def _check_lock_values(self) -> int:
"""
Check if all registers in the list have the same value for the specified field.
Returns:
An integer indicating the lock state.
Returns LockResult.LOCKED if all registers have the expected value.
Returns 0 if they do not match.
"""
lock_obj, reg_list = self.get_cache()
locked_value = lock_obj.lock_value
reg_list.read()
if reg_list.is_all_field_value(locked_value, lock_obj.get_field()):
return LockResult.LOCKED
return 0
def validate_lock_definition(self, lock_name: str) -> int:
"""
Validate if the lock is defined in the configuration file.
Arguments:
lock_name: The name of the lock to validate.
Returns:
An integer representing the validation result, which can include:
- LockResult.DEFINED: Lock is defined in the configuration.
- 0: Lock is not defined.
"""
lock_obj = self.cs.lock.get(lock_name)
if lock_obj is None:
self.logger.log_hal(f"Lock '{lock_name}' is not defined in the configuration file")
return 0
return LockResult.DEFINED
def get_registers(self, lock_obj, instance: Optional["instance"]) -> List:
"""
Retrieve registers associated with the lock.
Arguments:
lock_obj: The lock object containing the lock definition.
instance: Optional instance to filter the registers.
Returns:
A list of register objects associated with the lock.
If an instance is provided, it returns the registers for that specific instance.
If no instance is provided, it returns all registers associated with the lock.
"""
lock_register = lock_obj.get_register()
if instance:
reg_obj = self.cs.register.get_instance_by_name(lock_register, instance)
return list(reg_obj)
return self.cs.register.get_list_by_name(lock_register)
haldata = {"arch": [HALBase.MfgIds.Any], 'name': {'locks': "Locks"}}