Skip to content

Commit

Permalink
dracut: add support for one only module groups
Browse files Browse the repository at this point in the history
This supports the case where only a single module from a group
will be put into the initramfs to keep initramfs sizes down where
firmware files are getting large.

The kernel will denote a group like this:

MODULE_FIRMWARE_GROUP_ONLY_ONE("ga106-gsp");
MODULE_FIRMWARE("nvidia/ga106/gsp/gsp-5258902.bin");
MODULE_FIRMWARE("nvidia/ga106/gsp/gsp-5303002.bin");
MODULE_FIRMWARE_GROUP_ONLY_ONE("ga106-gsp");

dracut will then scan this group and install at least one
of the modules between the brackets for that group.

The ordering is decided by the way modinfo is written which
is reversed from the order things are specified, so dracut
will pick the first entry in the group, which will be the
last entry the kernel module specifies.

The kernel driver will then handle whatever it ends up finding.

Signed-off-by: Dave Airlie <[email protected]>
  • Loading branch information
airlied committed Apr 19, 2023
1 parent a62e895 commit 3be5c40
Showing 1 changed file with 38 additions and 7 deletions.
45 changes: 38 additions & 7 deletions src/install/dracut-install.c
Original file line number Diff line number Diff line change
Expand Up @@ -1396,6 +1396,7 @@ static int install_firmware(struct kmod_module *mod)
struct kmod_list *l = NULL;
_cleanup_kmod_module_info_free_list_ struct kmod_list *list = NULL;
int ret;
bool in_group_only_one = false, group_only_one_found = false;

char **q;

Expand All @@ -1408,10 +1409,36 @@ static int install_firmware(struct kmod_module *mod)
const char *key = kmod_module_info_get_key(l);
const char *value = NULL;

if (!streq("firmware", key))
if (!streq("firmware", key) &&
!streq("firmware_group_only_one", key))
continue;

value = kmod_module_info_get_value(l);

if (streq("firmware_group_only_one", key)) {
/*
* firmware group only one, picks one firmware from the given group.
* dracut will pick the first firmware it can find on the disk from
* the modinfo section.
* This section is written by the kernel in reverse order, so the
* the kernel modules should add the preferred ones last, and that
* will ensure dracut picks them first.
*/
if (in_group_only_one) {
in_group_only_one = false;
if (!group_only_one_found)
log_info("Possible missing firmware for group %s for kernel module %s", value,
kmod_module_get_name(mod));
} else {
in_group_only_one = true;
group_only_one_found = false;
}
continue;
}

if (in_group_only_one && group_only_one_found)
continue;

log_debug("Firmware %s", value);
ret = -1;
STRV_FOREACH(q, firmwaredirs) {
Expand All @@ -1428,16 +1455,20 @@ static int install_firmware(struct kmod_module *mod)
for (i = 0; i < globbuf.gl_pathc; i++) {
ret = install_firmware_fullpath(globbuf.gl_pathv[i]);
if (ret != 0) {
log_info("Possible missing firmware %s for kernel module %s", value,
kmod_module_get_name(mod));
}
if (!in_group_only_one)
log_info("Possible missing firmware %s for kernel module %s", value,
kmod_module_get_name(mod));
} else if (in_group_only_one)
group_only_one_found = true;
}
} else {
ret = install_firmware_fullpath(fwpath);
if (ret != 0) {
log_info("Possible missing firmware %s for kernel module %s", value,
kmod_module_get_name(mod));
}
if (!in_group_only_one)
log_info("Possible missing firmware %s for kernel module %s", value,
kmod_module_get_name(mod));
} else if (in_group_only_one)
group_only_one_found = true;
}
}
}
Expand Down

0 comments on commit 3be5c40

Please sign in to comment.