#!/usr/bin/perl # © 2021 Cyril Brulebois # # Generate ready-to-use .patterns files so that one can use grep to # perform hardware to firmware-package lookups in the installer # (see MODALIAS= lines in `udevadm info --export-db`), see the # hw-detect component. # # Parameters: dists//*/dep11/Components-.yml.(gz|xz) # # We're limiting ourselves to packages announcing Type: firmware, and # they need to include such information in their metadata, e.g. # src:firmware-nonfree; the --test option can be used until such # packages appear in the archive. # # See: https://salsa.debian.org/kernel-team/firmware-nonfree/-/merge_requests/19 use strict; use warnings; use File::Path qw(make_path); use File::Slurp; use Getopt::Long; use YAML::XS; # XXX: Drop support for --test once we have the required metadata in # the archive. my $output_dir = '.'; my $test; my $verbose; GetOptions( "output-dir=s" => \$output_dir, "test" => \$test, "verbose" => \$verbose ) or die "Error in command line arguments"; sub format_alias { return map { $a = $_; $a =~ s/[*]/.*/g; "^$a\$\n" } @_; } sub process_components { my $input = shift; my $content; print STDERR "processing $input\n" if $verbose; if ($input =~ /\.gz$/) { $content = `zcat $input`; } elsif ($input =~ /\.xz$/) { $content = `xzcat $input`; } else { die "only gz and xz suffixes are supported"; } my @packages; foreach my $array (Load $content) { # XXX: Drop the condition once we have the required metadata # in the archive. if (! $test) { next if not defined $array->{Type}; next if $array->{Type} ne 'firmware'; } next if not defined $array->{Provides}; next if not defined $array->{Provides}->{modaliases}; print STDERR "found modaliases entries for firmware package ", $array->{Package}, "\n" if $verbose; my $patterns_file = $output_dir . "/" . $array->{Package} . ".patterns"; printf STDERR "writing %d entries to %s\n", (scalar @{ $array->{Provides}->{modaliases} }), $patterns_file; # For each alias, anchor the pattern on the left (^) and on # the right ($), and replace each '*' with '.*': write_file($patterns_file, format_alias( @{ $array->{Provides}->{modaliases} } )); push @packages, $array->{Package}; } return @packages; } # Prepare output directory: if (! -d $output_dir) { print STDERR "creating output directory $output_dir\n" if $verbose; make_path($output_dir, { verbose => $verbose }); } write_file("$output_dir/README.txt", "These files help Debian Installer detect helpful firmware packages (via hw-detect).\n"); # Generate a .patterns file for each firmware package found in # Components-* files: my @all_packages; foreach my $component (@ARGV) { my @packages = process_components($component); push @all_packages, @packages; } @all_packages = sort @all_packages; print STDERR "all firmware packages found across all components: @all_packages\n" if $verbose;