files=gen_required_kernel_modules(
context,
kver,
- include=finalize_kernel_modules_include(
+ modules_include=finalize_kernel_modules_include(
context,
include=context.config.kernel_modules_initrd_include,
host=context.config.kernel_modules_initrd_include_host,
),
- exclude=context.config.kernel_modules_initrd_exclude,
+ modules_exclude=context.config.kernel_modules_initrd_exclude,
+ firmware_include=context.config.firmware_include,
+ firmware_exclude=context.config.firmware_exclude,
),
sandbox=context.sandbox,
)
process_kernel_modules(
context,
kver,
- include=finalize_kernel_modules_include(
+ modules_include=finalize_kernel_modules_include(
context,
include=context.config.kernel_modules_include,
host=context.config.kernel_modules_include_host,
),
- exclude=context.config.kernel_modules_exclude,
+ modules_exclude=context.config.kernel_modules_exclude,
+ firmware_include=context.config.firmware_include,
+ firmware_exclude=context.config.firmware_exclude,
)
if context.config.output_format.is_extension_or_portable_image():
kernel_modules_include: list[str]
kernel_modules_exclude: list[str]
kernel_modules_include_host: bool
+ firmware_include: list[str]
+ firmware_exclude: list[str]
kernel_modules_initrd: bool
kernel_modules_initrd_include: list[str]
parse=config_make_list_parser(delimiter=","),
help="When building a kernel modules initrd, exclude the specified kernel modules",
),
+ ConfigSetting(
+ dest="firmware_include",
+ metavar="REGEX",
+ section="Content",
+ parse=config_make_list_parser(delimiter=","),
+ help="Include the specified firmware in the image",
+ ),
+ ConfigSetting(
+ dest="firmware_exclude",
+ metavar="REGEX",
+ section="Content",
+ parse=config_make_list_parser(delimiter=","),
+ help="Exclude the specified firmware from the image",
+ ),
ConfigSetting(
dest="locale",
section="Content",
Kernel Modules Include: {line_join_list(config.kernel_modules_include)}
Kernel Modules Exclude: {line_join_list(config.kernel_modules_exclude)}
Kernel Modules Include Host: {yes_no(config.kernel_modules_include_host)}
+ Firmware Include: {line_join_list(config.firmware_include)}
+ Firmware Exclude: {line_join_list(config.firmware_exclude)}
Kernel Modules Initrd: {yes_no(config.kernel_modules_initrd)}
Kernel Modules Initrd Include: {line_join_list(config.kernel_modules_initrd_include)}
return sorted(modules)
+def filter_firmware(
+ root: Path,
+ firmware: set[Path],
+ *,
+ include: Iterable[str],
+ exclude: Iterable[str],
+) -> set[Path]:
+ if not include and not exclude:
+ return firmware
+
+ if exclude:
+ remove = set()
+ regex = re.compile("|".join(exclude))
+ for f in firmware:
+ rel = os.fspath(Path(*f.parts[3:]))
+ if regex.search(rel):
+ remove.add(f)
+
+ firmware -= remove
+
+ if include:
+ firmwared = Path("usr/lib/firmware")
+ with chdir(root):
+ all_firmware = set(firmwared.rglob("*"))
+ regex = re.compile("|".join(include))
+ for f in all_firmware:
+ rel = os.fspath(Path(*f.parts[3:]))
+ if regex.search(rel):
+ firmware.add(f)
+
+ return firmware
+
+
def normalize_module_name(name: str) -> str:
return name.replace("_", "-")
context: Context,
kver: str,
*,
- include: Iterable[str],
- exclude: Iterable[str],
+ modules_include: Iterable[str],
+ modules_exclude: Iterable[str],
+ firmware_include: Iterable[str],
+ firmware_exclude: Iterable[str],
) -> Iterator[Path]:
modulesd = Path("usr/lib/modules") / kver
+ firmwared = Path("usr/lib/firmware")
# There is firmware in /usr/lib/firmware that is not depended on by any modules so if any firmware was
# installed we have to take the slow path to make sure we don't copy firmware into the initrd that is not
# depended on by any kernel modules.
- if exclude or (context.root / "usr/lib/firmware").glob("*"):
- modules = filter_kernel_modules(context.root, kver, include=include, exclude=exclude)
+ if modules_exclude or (context.root / firmwared).glob("*"):
+ modules = filter_kernel_modules(context.root, kver, include=modules_include, exclude=modules_exclude)
names = [module_path_to_name(m) for m in modules]
mods, firmware = resolve_module_dependencies(context, kver, names)
else:
mods = set(modulesd.rglob("*.ko*"))
firmware = set()
+ # Include or exclude firmware explicitly configured
+ firmware = filter_firmware(context.root, firmware, include=firmware_include, exclude=firmware_exclude)
+
# Some firmware dependencies are symbolic links, so the targets for those must be included in the list
# of required firmware files too. Intermediate symlinks are not included, and so links pointing to links
# results in dangling symlinks in the final image.
context: Context,
kver: str,
*,
- include: Iterable[str],
- exclude: Iterable[str],
+ modules_include: Iterable[str],
+ modules_exclude: Iterable[str],
+ firmware_include: Iterable[str],
+ firmware_exclude: Iterable[str],
) -> None:
- if not exclude:
+ if not modules_exclude and not firmware_exclude:
return
modulesd = Path("usr/lib/modules") / kver
firmwared = Path("usr/lib/firmware")
with complete_step("Applying kernel module filters"):
- required = set(gen_required_kernel_modules(context, kver, include=include, exclude=exclude))
+ required = set(
+ gen_required_kernel_modules(
+ context,
+ kver,
+ modules_include=modules_include,
+ modules_exclude=modules_exclude,
+ firmware_include=firmware_include,
+ firmware_exclude=firmware_exclude,
+ )
+ )
with chdir(context.root):
modules = sorted(modulesd.rglob("*.ko*"), reverse=True)
`KernelModulesInitrdExclude=`, `--kernel-modules-initrd-exclude=`
: Like `KernelModulesExclude=`, but applies to the kernel modules included in the kernel modules initrd.
+`FirmwareInclude=`, `--firmware-include=`
+: Takes a list of regex patterns that specify firmware files to include in the image. Patterns should be
+ relative to `/usr/lib/firmware/<subdir>` paths. **mkosi** checks for a match anywhere in the firmware path
+ (e.g. `bcm8483` will match against `cxgb4/bcm8483.bin`). All firmware files that match any of the specified
+ patterns are included in the image.
+
+`FirmwareExclude=`, `--firmware-exclude=`
+: Takes a list of regex patterns that specify firmware files to exclude from the image. Behaves the same as
+ `FirmwareInclude=` except that all firmware that match any of the specified patterns is excluded from the
+ image. Firmware specified with this option is excluded even if an included kernel module depends on it.
+
`Locale=`, `--locale=`, `LocaleMessages=`, `--locale-messages=`, `Keymap=`, `--keymap=`, `Timezone=`, `--timezone=`, `Hostname=`, `--hostname=`, `RootShell=`, `--root-shell=`
: The settings `Locale=`, `--locale=`, `LocaleMessages=`, `--locale-messages=`,
`Keymap=`, `--keymap=`, `Timezone=`, `--timezone=`, `Hostname=`,
"Files": [],
"FinalizeScripts": [],
"Firmware": "linux",
+ "FirmwareExclude": [
+ "brcm/"
+ ],
+ "FirmwareInclude": [
+ "ath3k-1"
+ ],
"FirmwareVariables": "/foo/bar",
"Format": "uki",
"ForwardJournal": "/mkosi.journal",
extra_trees=[],
files=[],
finalize_scripts=[],
+ firmware_exclude=["brcm/"],
+ firmware_include=["ath3k-1"],
firmware_variables=Path("/foo/bar"),
firmware=Firmware.linux,
forward_journal=Path("/mkosi.journal"),