2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2026-09-24 16:54:03 +00:00

fix(xcat-core): the initrd firmware step reads the root image only

The step that fills lib/firmware in the Ubuntu netboot initrd asked modinfo
about $rootimg_dir/$module and looked a firmware name up under lib/firmware.
The copy step beside it takes a module from $customdir or $pathtofiles first,
and the kernel looks a firmware name up under updates/<kernel>, updates/,
<kernel>/ and lib/firmware. So a custom driver reached the initrd with no
firmware, even when the root image carried it, and a firmware override was left
out of the initrd altogether.

initrd_firmware_files now takes the module directories the copy step searches
and the kernel release. It resolves each module in that order before asking
modinfo, and keeps every firmware file that exists in the four directories the
kernel searches, so the override still wins on the node.

ubuntu_genimage_initrd_firmware.t covers both: its two new cases are red on the
commit before this one.

Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
Daniel Hilst
2026-09-17 07:38:47 -03:00
parent 2523a06b16
commit 5554b79c2d
2 changed files with 38 additions and 9 deletions
+35 -9
View File
@@ -1829,7 +1829,9 @@ EOMS
# The whole firmware tree is 666 MB on Ubuntu 26.04, and grub2 on a pseries node cannot
# load an initrd of that size. The initrd only has to reach the network.
foreach my $firmware (initrd_firmware_files($rootimg_dir, \@filestoadd)) {
foreach my $firmware (
initrd_firmware_files($rootimg_dir, \@filestoadd, $kernelver, $customdir, $pathtofiles))
{
copy_initrd_file("$rootimg_dir/lib/firmware/$firmware",
"/tmp/xcatinitrd.$$/lib/firmware/$firmware");
}
@@ -1904,13 +1906,16 @@ sub isnetdriver {
rootimg_dir - the root image directory
filestoadd - reference to the list of files that go into the initrd. A module
is either a plain path or a [ source, destination ] pair.
kernelver - the kernel release, which names one of the firmware directories
module_dirs - directories searched for a module before the root image, in the
same order the copy step searches them
Returns: the firmware files that exist, as paths below lib/firmware
=cut
#-------------------------------------------------------------------------------
sub initrd_firmware_files {
my ($rootimg_dir, $filestoadd) = @_;
my ($rootimg_dir, $filestoadd, $kernelver, @module_dirs) = @_;
return () unless (-d "$rootimg_dir/lib/firmware");
@@ -1918,9 +1923,18 @@ sub initrd_firmware_files {
foreach my $entry (@$filestoadd) {
my $module = ref($entry) ? $entry->[0] : $entry;
next unless ($module =~ /\.ko(?:\.(?:gz|xz|zst))?$/);
next unless (-f "$rootimg_dir/$module");
my $out = `modinfo -F firmware "$rootimg_dir/$module" 2>/dev/null`;
# Ask about the module the copy step takes, which is the custom one where there is
# one. A custom driver is not in the root image at all.
my $source;
foreach my $dir (grep { defined && length } @module_dirs, $rootimg_dir) {
next unless (-f "$dir/$module");
$source = "$dir/$module";
last;
}
next unless (defined $source);
my $out = `modinfo -F firmware "$source" 2>/dev/null`;
if ($?) {
print "Warning: cannot read the firmware of $module\n";
next;
@@ -1931,14 +1945,26 @@ sub initrd_firmware_files {
}
}
# The kernel looks for a firmware name in these directories below lib/firmware, in this
# order, and loads the first file it finds. Keep every one that exists, so an override
# still wins on the node.
my @dirs = ("updates", "");
if (defined $kernelver and length $kernelver) {
unshift @dirs, "updates/$kernelver";
splice(@dirs, 2, 0, $kernelver);
}
my @files;
foreach my $name (sort keys %wanted) {
foreach my $dir (@dirs) {
my $prefix = length($dir) ? "$dir/" : "";
# Ubuntu keeps the firmware compressed and the kernel asks for the plain name.
foreach my $candidate ($name, "$name.zst", "$name.xz", "$name.gz") {
next unless (-e "$rootimg_dir/lib/firmware/$candidate");
push @files, $candidate;
last;
# Ubuntu keeps the firmware compressed and the kernel asks for the plain name.
foreach my $candidate ($name, "$name.zst", "$name.xz", "$name.gz") {
next unless (-e "$rootimg_dir/lib/firmware/$prefix$candidate");
push @files, "$prefix$candidate";
last;
}
}
}
return @files;
@@ -103,6 +103,9 @@ close($custom);
use File::Copy;
use File::Path qw(mkpath);
our $rootimg_dir;
our $customdir;
our $pathtofiles;
our $kernelver;
our @filestoadd;
sub xdie { die @_ }
}