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>
430 lines
17 KiB
Python
430 lines
17 KiB
Python
# !/usr/bin/python
|
|
# CHIPSEC: Platform Security Assessment Framework
|
|
# Copyright (c) 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
|
|
|
|
"""
|
|
>>> chipsec_util config show [config] <name>
|
|
|
|
Examples:
|
|
|
|
>>> chipsec_util config show ALL
|
|
>>> chipsec_util config show [CONFIG_PCI|MEMORY_RANGES|MM_MSGBUS|MSGBUS|IO|MSR]
|
|
>>> chipsec_util config show SCOPE
|
|
"""
|
|
|
|
from argparse import ArgumentParser
|
|
|
|
from chipsec.command import BaseCommand, toLoad
|
|
|
|
|
|
class CONFIGCommand(BaseCommand):
|
|
"""Command to display configuration information."""
|
|
|
|
# Initialize command
|
|
def __init__(self, argv, cs):
|
|
"""Initialize the command with base class and set options."""
|
|
super(CONFIGCommand, self).__init__(argv, cs)
|
|
self.skip_list = ["LOCKS", "CONTROLS", "ALL"]
|
|
try:
|
|
# Get parent keys from scope manager
|
|
self.all_options = (
|
|
self.cs.Cfg.scope_manager.parent_keys +
|
|
self.skip_list + ["SCOPE"]
|
|
)
|
|
except (AttributeError, TypeError):
|
|
# Fallback if scope_manager is not available
|
|
self.all_options = [
|
|
"CONFIG_PCI_RAW", "CONFIG_PCI", "MEMORY_RANGES", "MM_MSGBUS",
|
|
"MSGBUS", "IO", "MSR", "MMIO_BARS", "IO_BARS", "LOCKS",
|
|
"CONTROLS", "ALL", "SCOPE"
|
|
]
|
|
self.child_details = False # Default to not showing child details
|
|
|
|
# Command setup and infrastructure methods
|
|
def requirements(self):
|
|
"""Specify resource requirements for this command."""
|
|
return toLoad.All
|
|
|
|
def parse_arguments(self):
|
|
"""Parse command line arguments."""
|
|
parser = ArgumentParser(usage='chipsec_util config')
|
|
subparsers = parser.add_subparsers()
|
|
|
|
# Show command
|
|
parser_show = subparsers.add_parser('show')
|
|
parser_show.add_argument(
|
|
'config',
|
|
choices=self.all_options,
|
|
default="ALL"
|
|
)
|
|
parser_show.add_argument(
|
|
'-c', '--child-details',
|
|
action='store_true',
|
|
help='Include child details'
|
|
)
|
|
parser_show.set_defaults(func=self.show, config="ALL")
|
|
|
|
parser.parse_args(self.argv, namespace=self)
|
|
return True
|
|
|
|
# Main display methods
|
|
def show(self):
|
|
"""Show configuration information based on selected option."""
|
|
if self.config == "SCOPE":
|
|
self.scope_details()
|
|
return
|
|
|
|
if self.config == "ALL":
|
|
# Exclude SCOPE from all_options when processing ALL
|
|
config = [x for x in self.all_options if x != "SCOPE"]
|
|
# Also show scope information when 'ALL' is selected
|
|
self.scope_details()
|
|
else:
|
|
config = [self.config]
|
|
|
|
for mconfig in config:
|
|
if mconfig in self.skip_list:
|
|
continue
|
|
|
|
try:
|
|
cfg = getattr(self.cs.Cfg, mconfig)
|
|
except AttributeError:
|
|
self.logger.log(f"\n{mconfig} - Not available")
|
|
continue
|
|
|
|
self.logger.log(f"\n{mconfig}")
|
|
for vid in cfg.keys():
|
|
self.logger.log(f"{vid}:")
|
|
for name in cfg[vid].keys():
|
|
if mconfig in ["CONFIG_PCI_RAW"]:
|
|
cfg_data = cfg[vid][name]
|
|
self.logger.log(
|
|
f'\t{name} - {self.pci_details(cfg_data)}'
|
|
)
|
|
elif mconfig in ["CONFIG_PCI"]:
|
|
cfg_data = cfg[vid][name]
|
|
self.logger.log(
|
|
f'\t{name} - {self.pci_details(cfg_data)}'
|
|
)
|
|
elif mconfig == "MEMORY_RANGES":
|
|
self.logger.log(
|
|
f'\t{name} - {self.memory_details(cfg[vid][name])}'
|
|
)
|
|
elif mconfig in ["MM_MSGBUS", "MSGBUS", "IO"]:
|
|
port_details = self.get_port_details(cfg[vid][name])
|
|
self.logger.log(f'\t{name} - {port_details}')
|
|
elif mconfig in ["MMIO_BARS", "IO_BARS"]:
|
|
for cfg_data in cfg[vid][name]:
|
|
details = self.mmio_details(
|
|
cfg[vid][name][cfg_data]
|
|
)
|
|
self.logger.log(f'\t{cfg_data} - {details}')
|
|
elif mconfig == "MSR":
|
|
self.logger.log(
|
|
f'\t{name} - {self.msr_details(cfg[vid][name])}'
|
|
)
|
|
|
|
if (self.child_details and
|
|
mconfig not in ["CONFIG_PCI_RAW"]):
|
|
if mconfig not in ["MMIO_BARS", "IO_BARS"]:
|
|
self.get_child_details(vid, name)
|
|
else:
|
|
for cfg_data in cfg[vid][name]:
|
|
self.get_child_details(
|
|
vid, cfg[vid][name][cfg_data].name
|
|
)
|
|
|
|
if set(config).intersection({"LOCKS", "ALL"}):
|
|
self.lock_details()
|
|
if set(config).intersection({"CONTROLS", "ALL"}):
|
|
self.control_details()
|
|
return
|
|
|
|
# Detail formatting methods for different types of registers/configurations
|
|
def msr_details(self, regi):
|
|
"""Format MSR register details."""
|
|
ret = f'config: {regi.config}'
|
|
return ret
|
|
|
|
def memory_details(self, regi):
|
|
"""Format memory range details."""
|
|
try:
|
|
# Try to access as dictionary first
|
|
if isinstance(regi, dict):
|
|
# Basic attributes always displayed
|
|
ret = (f"access: {regi.get('access', 'N/A')}, "
|
|
f"address: {regi.get('address', 'N/A')}, "
|
|
f"size: {regi.get('size', 'N/A')}")
|
|
|
|
# Add configuration if available
|
|
if 'config' in regi:
|
|
ret += f", config: {regi['config']}"
|
|
|
|
# BEGIN: Extended MMIO Functionality
|
|
# Display extended MMIO attributes if available
|
|
if 'base_ref' in regi:
|
|
ret += f", base_ref: {regi['base_ref']}"
|
|
if 'base_value' in regi:
|
|
ret += f" (0x{regi['base_value']:x})"
|
|
|
|
if 'ip_ref' in regi:
|
|
ret += f", ip_ref: {regi['ip_ref']}"
|
|
if 'ip_value' in regi:
|
|
ret += f" (0x{regi['ip_value']:x})"
|
|
|
|
if 'scope' in regi:
|
|
ret += f", scope: {regi['scope']}"
|
|
# END: Extended MMIO Functionality
|
|
|
|
else:
|
|
# Fall back to attribute access if it's an object
|
|
ret = (f"access: {getattr(regi, 'access', 'N/A')}, "
|
|
f"address: {getattr(regi, 'address', 'N/A')}, "
|
|
f"size: {getattr(regi, 'size', 'N/A')}")
|
|
|
|
# Add configuration if available
|
|
if hasattr(regi, 'config'):
|
|
ret += f", config: {regi.config}"
|
|
|
|
# BEGIN: Extended MMIO Functionality
|
|
# Display extended MMIO attributes if available
|
|
if hasattr(regi, 'base_ref') and regi.base_ref:
|
|
ret += f", base_ref: {regi.base_ref}"
|
|
if hasattr(regi, 'base_value') and regi.base_value:
|
|
ret += f" (0x{regi.base_value:x})"
|
|
|
|
if hasattr(regi, 'ip_ref') and regi.ip_ref:
|
|
ret += f", ip_ref: {regi.ip_ref}"
|
|
if hasattr(regi, 'ip_value') and regi.ip_value:
|
|
ret += f" (0x{regi.ip_value:x})"
|
|
|
|
if hasattr(regi, 'scope') and regi.scope:
|
|
ret += f", scope: {regi.scope}"
|
|
# END: Extended MMIO Functionality
|
|
|
|
except (KeyError, AttributeError):
|
|
# In case of any error, just return the string representation
|
|
ret = str(regi)
|
|
return ret
|
|
|
|
def get_port_details(self, regi):
|
|
"""Format port details."""
|
|
ret = ''
|
|
if regi:
|
|
ret = f'port: {regi.port}, config: {regi.config}'
|
|
return ret
|
|
|
|
def ima_details(self, regi):
|
|
"""Format IMA register details."""
|
|
base_value = regi['base'] if 'base' in regi.keys() else None
|
|
ret = f"index: {regi['index']}, data: {regi['data']}, " \
|
|
f"base: {base_value}"
|
|
return ret
|
|
|
|
def register_details(self, regi):
|
|
"""Format register details based on type."""
|
|
ret = ""
|
|
if regi['type'] == 'pcicfg' or regi['type'] == 'mmcfg':
|
|
ret = f"device: {regi['device']}, offset: {regi['offset']}, " \
|
|
f"size: {regi['size']}"
|
|
elif regi['type'] == 'mmio':
|
|
ret = f"bar: {regi['bar']}, offset: {regi['offset']}, " \
|
|
f"size: {regi['size']}"
|
|
elif regi['type'] == 'mm_msgbus':
|
|
ret = f"offset: {regi['offset']}, size: {regi['size']}"
|
|
elif regi['type'] == 'io':
|
|
ret = f"size: {regi['size']}"
|
|
elif regi['type'] == 'iobar':
|
|
ret = f"bar: {regi['bar']}, offset: {regi['offset']}, " \
|
|
f"size: {regi['size']}"
|
|
elif regi['type'] == 'msr':
|
|
if 'size' in regi:
|
|
ret = f"msr: {regi['msr']}, size: {regi['size']}"
|
|
else:
|
|
ret = f"msr: {regi['msr']}"
|
|
elif regi['type'] == 'R Byte':
|
|
if 'size' in regi:
|
|
ret = f"offset: {regi['offset']}, size: {regi['size']}"
|
|
else:
|
|
ret = f"offset: {regi['offset']}"
|
|
elif regi['type'] == 'memory':
|
|
ret = f"access: {regi['access']}, offset: {regi['offset']}, " \
|
|
f"size: {regi['size']}"
|
|
|
|
# Add field information if available
|
|
try:
|
|
if isinstance(regi, (list, tuple)) and len(regi) > 0:
|
|
reg_obj = regi[0]
|
|
if hasattr(reg_obj, 'fields') and reg_obj.fields:
|
|
for key in reg_obj.fields:
|
|
bit = reg_obj.fields[key]['bit']
|
|
size = reg_obj.fields[key]['size']
|
|
end_bit = bit + size - 1
|
|
ret += f'\n\t\t\t{key} - bit {bit}:{end_bit}'
|
|
except (IndexError, AttributeError, TypeError):
|
|
# Silently ignore errors when accessing fields
|
|
pass
|
|
|
|
return ret
|
|
|
|
def pci_details(self, regi):
|
|
"""Format PCI configuration details."""
|
|
return str(regi)
|
|
|
|
def mmio_details(self, regi):
|
|
"""Format MMIO details."""
|
|
return str(regi)
|
|
|
|
def io_details(self, regi):
|
|
"""Format IO details."""
|
|
if 'register' in regi:
|
|
fixed_addr = (
|
|
regi['fixed_address'] if 'fixed_address' in regi else None
|
|
)
|
|
ret = (f"register: {regi['register']}, "
|
|
f"base_field: {regi['base_field']}, "
|
|
f"size: {regi['size']}, "
|
|
f"fixed_addr: {fixed_addr}")
|
|
else:
|
|
size = regi['size'] if 'size' in regi else None
|
|
fixed_addr = (
|
|
regi['fixed_address'] if 'fixed_address' in regi else None
|
|
)
|
|
ret = (f"bus: {regi['bus']}, "
|
|
f"dev: {regi['dev']}, "
|
|
f"func: {regi['fun']}, "
|
|
f"reg: {regi['reg']}, "
|
|
f"mask: {regi['mask']}, "
|
|
f"size: {size}, "
|
|
f"fixed_addr: {fixed_addr}")
|
|
return ret
|
|
|
|
# Data display methods for child details, controls, and locks
|
|
def get_child_details(self, vid, dev):
|
|
"""Get and display child configuration details."""
|
|
self.logger.log(f'get_child details {dev}')
|
|
config = self.cs.Cfg.child_keys
|
|
for mconfig in config:
|
|
if mconfig in ["CONTROLS", "LOCKS", "LOCKEDBY"]:
|
|
continue
|
|
|
|
cfg = getattr(self.cs.Cfg, mconfig)
|
|
self.logger.log(f"\t{mconfig}:")
|
|
|
|
if mconfig == "IMA_REGISTERS":
|
|
if vid in cfg and dev in cfg[vid]:
|
|
for name in cfg[vid][dev].keys():
|
|
details = self.ima_details(cfg[vid][dev][name])
|
|
self.logger.log(f'\t\t{name} - {details}')
|
|
elif mconfig == "REGISTERS":
|
|
try:
|
|
if vid in cfg and dev in cfg[vid]:
|
|
for name in cfg[vid][dev].keys():
|
|
details = self.register_details(
|
|
cfg[vid][dev][name]
|
|
)
|
|
self.logger.log(f'\t\t{name} - {details}')
|
|
except KeyError:
|
|
pass
|
|
self.logger.log("")
|
|
|
|
def control_details(self):
|
|
"""Display control details."""
|
|
self.logger.log("\nCONTROLS")
|
|
try:
|
|
cfg = getattr(self.cs.Cfg, "CONTROLS")
|
|
for regi in cfg.keys():
|
|
self.logger.log(f'\t{regi}')
|
|
except AttributeError as e:
|
|
self.logger.log(f"\tError retrieving controls: {e}")
|
|
return
|
|
|
|
def lock_details(self):
|
|
"""Display lock details."""
|
|
self.logger.log("\nLOCKS")
|
|
try:
|
|
locks = self.cs.Cfg.get_lock_list()
|
|
for lock in locks:
|
|
lock_cfg = self.cs.Cfg.get_lock_obj(lock)
|
|
self.logger.log(f'\t{lock_cfg}')
|
|
except AttributeError as e:
|
|
self.logger.log(f"\tError retrieving locks: {e}")
|
|
return
|
|
|
|
def scope_details(self):
|
|
"""Display the contents of the scope manager."""
|
|
self.logger.log("\nSCOPE MANAGER")
|
|
|
|
# Display parent keys
|
|
self.logger.log("\nParent Keys:")
|
|
for key in self.cs.Cfg.scope_manager.parent_keys:
|
|
self.logger.log(f"\t{key}")
|
|
|
|
# Display child keys
|
|
self.logger.log("\nChild Keys:")
|
|
for key in self.cs.Cfg.scope_manager.child_keys:
|
|
self.logger.log(f"\t{key}")
|
|
|
|
# Display current scope
|
|
self.logger.log("\nCurrent Scope:")
|
|
for scope_key, scope_value in self.cs.Cfg.scope.items():
|
|
key_name = scope_key if scope_key is not None else "DEFAULT"
|
|
self.logger.log(f"\t{key_name}: {scope_value}")
|
|
|
|
# BEGIN: Extended MMIO Functionality
|
|
# Display memory bases if available
|
|
if hasattr(self.cs.Cfg, 'memory_bases') and self.cs.Cfg.memory_bases:
|
|
self.logger.log("\nMemory Bases:")
|
|
for base_name, base_value in self.cs.Cfg.memory_bases.items():
|
|
self.logger.log(f"\t{base_name}: 0x{base_value:x}")
|
|
|
|
# Display IP addresses if available
|
|
if hasattr(self.cs.Cfg, 'ip_addresses') and self.cs.Cfg.ip_addresses:
|
|
self.logger.log("\nIP Addresses:")
|
|
for ip_name, ip_value in self.cs.Cfg.ip_addresses.items():
|
|
self.logger.log(f"\t{ip_name}: 0x{ip_value:x}")
|
|
# END: Extended MMIO Functionality
|
|
|
|
# Display available scopes in the configuration
|
|
self.logger.log("\nAvailable Configuration Items:")
|
|
|
|
# Go through parent keys and display available items
|
|
for parent_key in self.cs.Cfg.scope_manager.parent_keys:
|
|
if hasattr(self.cs.Cfg, parent_key):
|
|
cfg_data = getattr(self.cs.Cfg, parent_key)
|
|
if cfg_data:
|
|
self.logger.log(f"\n{parent_key}:")
|
|
for vid in cfg_data.keys():
|
|
self.logger.log(f"\t{vid}:")
|
|
if isinstance(cfg_data[vid], dict):
|
|
# Limit to first 10 items for readability
|
|
items = list(cfg_data[vid].keys())
|
|
for name in items[:10]:
|
|
self.logger.log(f"\t\t{name}")
|
|
if len(items) > 10:
|
|
remaining = len(items) - 10
|
|
self.logger.log(
|
|
f"\t\t... ({remaining} more items)"
|
|
)
|
|
return
|
|
|
|
|
|
commands = {'config': CONFIGCommand}
|