Concepts¶
This page is going to elaborate on some important concepts in autokernel.
Modules¶
Modules are blocks in the autokernel configuration which are used to write the actual kernel configuration. A module can set symbol values, merge external kconf files, assert expressions, use (include) other modules and add commandline strings. They are intended to provide a level of encapsulation for groups of symbols.
Example module
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | module example {
# Asserts that the configured kernel is at least on version 4.0
assert $kernel_version >= 4.0: "this kernel is too old!";
# Merge in the x86_64 defconfig
merge "{KERNEL_DIR}/arch/x86/configs/x86_64_defconfig";
# Sets DEFAULT_MMAP_MIN_ADDR if X86 is set
if X86 {
set DEFAULT_MMAP_MIN_ADDR 65536;
}
# Include another module
use some_dependency;
}
module some_dependency {
# ...
}
|
Pinning symbol values¶
The first important concept is pinning. As soon as a symbol’s value is changed or observed, it will be pinned, meaning the value is then fixed. In the beginning, all symbols will start with their default values, as specified by the kernel’s Kconfig.
Successive assigments to these symbols will become hard errors, if they would change the pinned value. This allows modules to use logic based on symbol values, without imposing implicit ordering constraints, or surprise pitfalls down the road. Wrong ordering will lead to errors instead of silently breaking previous assumptions.
Note
Conflicts are always errors. This ensures that the same conditions always has the same outcome, no matter where it stands in the configuration.
Pinning Examples
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # Sets and pins NET to [y] (cause: explicit assignment)
set NET y;
# Pins USB to its current value (cause: evaluation in condition)
if USB {
set EXAMPLE y;
}
# Does not pin BT, because no statement depends on the condition
if BT { }
# Does nothing if IWLWIFI is already pinned. Otherwise assigns
# *without* pinning. Useful to set new defaults for values
# but still allowing explicit changes.
try set IWLWIFI y;
|
Conflict Example
1 2 3 4 5 6 7 8 9 | # If NET is enabled, also enable TUN. This pins NET.
if NET {
set TUN y;
}
# Assume NET was [y]. In that case NET is pinned to [y] in line 3.
# This would break the assumption in line 3, as a re-evaluation of
# the condition would have a different result.
set NET n; # error: confilict
|
Implicit vs. explicit changes¶
There are explicit and implict assignments of symbol values. All direct assignments
via set
are explicit. An implicit assignment occurrs, when an explicit assignment
triggers a change in a symbols that depends on the assigned symbol.
Note
Explicit changes will pin the value of a symbols, while implicit changes do not.
Implicit assignments also occurr when using the merge statement.
They can also be forced by using try set
instead of just set
. This should only be used in special occasions, like when
you want to set a new default value for a symbol while still allowing the user to override it.
Correct usage of try set
It’s a common pattern to use try set
directly followed by a conditional on the same
symbol. This way you can ensure a module works with either setting, but add a default
in case the user didn’t care:
1 2 3 4 5 6 7 | # By default disable DEVMEM
try set DEVMEM n;
# If the user has still enabled it, at least enable STRICT mode
if DEVMEM {
set STRICT_DEVMEM y;
}
|
Warning
Do not use try set
to resolve conflicts! A conflict always means that there is
something wrong with your configuration or ordering. Only use try set
to
set new defaults.
Explicit assignments
1 2 3 4 5 | # Explicitly sets NET to n
set NET n;
# Explicitly sets symbols mentioned in the given kconf file
merge "{KERNEL_DIR}/arch/x86/configs/x86_64_defconfig";
|
Implicit assignments
1 2 3 4 5 6 | # Implicitly sets NET to n
try set NET n;
# Implicitly assigns a lot of other options
# (all that indirectly depend on MODULES)
set MODULES n;
|