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

149 lines
6.2 KiB
Python

# CHIPSEC: Platform Security Assessment Framework
# Copyright (c) 2024, 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
#
# -------------------------------------------------------------------------------
import os
from enum import Enum
from importlib import import_module
from typing import Dict, Any, List
from chipsec.hal.hal_base import HALBase
from chipsec.library.logger import logger
from chipsec.library.file import get_main_dir
from chipsec.library.strings import make_hex_key_str
from chipsec.library.exceptions import HALNotFoundError, HALInitializationError
if logger().DEBUG:
import traceback
else:
traceback = type('traceback', (), {})() # Create a dummy traceback object if not in debug mode
traceback.format_exc = lambda: "Traceback not available in non-debug mode"
class Hals:
"""
HALs manager class
Search for HAL modules in chipsec/hal/ subdirectories
Will look for Architecture specific HALs based on mfgid first, then generic HALs in the common directory. If both are found, it will use the Architecture specific HAL.
For all HAL modules, it will look for a 'haldata' attribute that contains the following information:
name: dict of HAL class names with keys as the HAL name (e.g., 'memory', 'msr', etc.) and values as the class name (e.g., 'Memory', 'Msr', etc.)
arch: list of supported architectures (MfgIds) for the HAL module. See MfgIds enum in hal_base.py for available architectures.
"""
def __init__(self, cs):
self.cs = cs
self.hals_import_location = "chipsec.hal."
self._available_hals = []
self.update_available_hals() #['mem', 'msr', 'ucode', 'io', 'cpu', 'msgbus', 'mmio', 'iobar', 'igd']
def available_hals(self) -> list:
a_hals = []
for i in self._available_hals:
a_hals += i['name']
return a_hals
def list_loadable_hals(self) -> list:
loadable_list = []
if not self._available_hals:
self.update_available_hals()
for halobjs in self._available_hals:
for hal in halobjs['name']:
try:
loadable_list.append(self.find_best_hal_by_name(hal))
except HALNotFoundError:
continue
return loadable_list
def __getattr__(self, name):
best_hal = self.find_best_hal_by_name(name)
try:
hal_class = getattr(best_hal['mod'], best_hal['name'][name])
setattr(self, name, hal_class(self.cs))
except Exception as err:
logger().log_debug(traceback.format_exc())
raise HALInitializationError(f'HAL with name {name} was not able to be initialized: {str(err)}')
return super(Hals, self).__getattribute__(name)
def find_best_hal_by_name(self, name:str) -> Any:
# hal_path = f'{self.hals_import_location}{name}'
selected_hals = []
for hal in self._available_hals:
if name in hal['name'].keys() and self.is_mfgid_in_haldata(hal):
hal['priority'] = 1
selected_hals.append(hal)
elif name in hal['name'].keys() and self.is_any_mfgid_in_haldata(hal):
hal['priority'] = 2
selected_hals.append(hal)
if not selected_hals:
raise HALNotFoundError(f'HAL with name {name} was not found.')
return sorted(selected_hals, key=lambda x: x['priority'])[0]
def is_mfgid_in_haldata(self, haldata: List) -> bool:
return any(self.cs.Cfg.mfgid in subl.value for subl in haldata['arch'])
def is_any_mfgid_in_haldata(self, haldata: List) -> bool:
return HALBase.MfgIds.Any in haldata['arch']
def update_available_hals(self) -> Dict[str, Any]:
"""Determine available HAL modules"""
hal_base_dir = os.path.join(get_main_dir(), "chipsec", "hal")
hal_dirs = [f.name for f in os.scandir(hal_base_dir) if f.is_dir() and '__' not in f.name]
hals = []
for hal_dir in hal_dirs:
hals += ([f'{hal_dir}.{i[:-3]}' for i in os.listdir(os.path.join(hal_base_dir, hal_dir)) if i[-3:] == ".py" and not i[:2] == "__"])
logger().log_debug('[CHIPSEC] Loaded HALs:')
logger().log_debug('\t' + '\n\t'.join(hals))
module = None
halsdata = []
for hal in hals:
try:
hal_path = f'{self.hals_import_location}{hal}'
module = import_module(hal_path)
hd = getattr(module, 'haldata')
hd['mod'] = module
halsdata.append(hd)
except ImportError as err:
# Display the import error and continue to import commands
logger().log_error(f"Exception occurred during import of {hal}: '{str(err)}'")
logger().log_debug(traceback.format_exc())
continue
except AttributeError as err:
logger().log_error(f"HAL {hal} has not been updated with 'haldata' attribute: '{str(err)}'")
continue
self._available_hals = halsdata
# self.pci = pci.Pci(self)
# self.mem = physmem.Memory(self)
# self.msr = msr.Msr(self)
# self.ucode = ucode.Ucode(self)
# self.io = io.PortIO(self)
# self.cpu = cpu.CPU(self)
# self.msgbus = msgbus.MsgBus(self)
# self.mmio = mmio.MMIO(self)
# self.iobar = iobar.IOBAR(self)
# self.igd = igd.IGD(self)