Developer Guide¶
CHIPSEC modules are Python classes that assess or exercise a platform through the CHIPSEC framework. Module code runs with privileged hardware access on supported systems. Develop and test on a dedicated test system, and understand the effect of every hardware read or write before running a module.
Module layout and lifecycle¶
Place modules under chipsec/modules/. Use common/ for checks intended
to work across supported platforms, or a platform-code directory for a
platform-specific check. The module name is its path relative to
chipsec/modules without the .py suffix; for example,
chipsec/modules/common/bios_wp.py is run as common.bios_wp. The module
class name must match the Python file’s base name.
Subclass BaseModule from chipsec.module_common. CHIPSEC calls
is_supported() before run(module_argv). Return False from
is_supported when required hardware or configuration is unavailable; the
module is then reported as not applicable. run receives the arguments
provided with -a and returns the module result/return code. See
Sample Module Code for a starting point.
Core APIs¶
BaseModule provides these commonly used objects:
self.csis the active chipset object. Use its configuration interfacesto resolve platform-specific registers and controls instead of duplicating platform detection in a module.
self.cs.registeraccesses configured registers. Useget_list_by_name(name)to get anObjListof defined and enabled registers, then callobjlist.read()to read their values.
self.cs.controlaccesses abstract controls. A control maps a logicalsecurity setting to the register and field used by a platform.
get_list_by_name(name)returns anObjListof defined and enabled controls; callobjlist.read()to read their values.
self.cs.deviceprovides configured device information. For commonhardware operations, use the corresponding HAL exposed under
self.cs.hals(for example,self.cs.hals.spiorself.cs.hals.uefi). See Architecture Overview and the generated CHIPSEC HAL API documentation for the available HALs.
self.loggerprovidesstart_test,log,log_verbose,log_warning,log_passed,log_failedandlog_importantfor consistent output.
self.resulttracks return-code status bits. Useself.result.setStatusBit(...)to add a meaningful status such asLOCKS,CONFIGURATIONorVERIFY. Follow nearby modules for the result style used in that part of the codebase; CHIPSEC retains the legacyModuleResultinterface for compatibility.
Platform controls are declared in configuration XML, not hard-coded into a portable module. For example:
<control name="BiosLockEnable" register="BC" field="BLE"
desc="BIOS Lock Enable"/>
A module can then query the abstract control without knowing which register implements it on each platform:
lock = self.cs.control.get_list_by_name('BiosLockEnable')
lock.read_and_verbose_print()
if lock.is_all_value(1):
self.logger.log_passed('BIOS Lock is set.')
else:
self.logger.log_failed('BIOS Lock is not set.')
See Configuration Files for configuration structure and examples.
Development practices¶
- Prefer read-only checks. If a check must modify hardware state, make the
change explicit, preserve the original value, and restore it on every exit path. Document the risk and require an appropriate test platform.
- Use abstract controls and existing HALs so modules can be reused across
platform generations. Put platform-specific register mappings in configuration XML.
- Treat missing definitions, disabled devices, failed reads and all-ones
reads as unknown or unsupported input, not as evidence that a protection passed or failed. Report a warning or not-applicable result as appropriate.
- Validate assumptions and ranges before using hardware-derived values. Keep
parsing and result handling explicit, and avoid swallowing exceptions that indicate a programming error.
- Keep checks focused, log the observed state and expected state, and add
unit tests for parsing, decision logic and error paths. Follow the Python version and style rules in Python Version.
- Add module tags and metadata that accurately describe the module. Use
existing modules in the same directory as examples of repository conventions.
Debugging and testing¶
Start with a focused run from the CHIPSEC repository root:
python chipsec_main.py -m common.example
Increase diagnostic output with -v or -vv (verbose, HAL and debug
logging), and save it with -l example.log. Use --failfast when you
need exceptions to stop the run rather than be masked by normal module
handling. --no-driver is only suitable for operations that do not need
kernel-driver access.
When diagnosing a module:
- If it is not found, check the module path/name, class name, and any
additional module path passed with
-I.
- If it is not applicable, inspect
is_supportedand verify that the platform configuration defines and enables each required device, register and control.
- If it is not applicable, inspect
- If a result is unexpected, use verbose output to inspect the values read,
then confirm the register mapping and expected semantics against the platform documentation.
- If the module raises an exception, reproduce it with a single-module run
and
--failfast; add a focused test for the failing input or decision path.
Run a focused unit test from the repository root, for example:
python -m pytest tests/modules/test_example.py -q
Hardware validation is separate from unit testing and must be performed only on an appropriate test system. See Running CHIPSEC for command line options and the contribution guide for contribution requirements.