#!/usr/bin/perl use v5.30; use warnings; use File::Temp qw<>; my %drivers = ( acx => undef, amdgpu => { dir => 'sys/dev/pci/drm/amd/amdgpu/', type => 'amdgpu' }, athn => undef, bwfm => undef, bwi => undef, intel => ['^cpu0: Intel'], inteldrm => { dir => 'sys/dev/pci/drm/i915/', type => 'i915' }, ipw => undef, iwi => undef, iwm => undef, iwn => undef, iwx => undef, malo => undef, ogx => undef, otus => undef, pgt => undef, radeondrm => { dir => 'sys/dev/pci/drm/radeon/', type => 'radeon' }, rsu => undef, rtwn => undef, uath => undef, upgt => undef, urtwn => undef, uvideo => undef, vmm => undef, wpi => undef, ); foreach my $driver (sort keys %drivers ) { my $def = $drivers{$driver}; say "$driver"; next unless defined $def; if ( ref $def eq 'ARRAY' ) { say "$driver $_" for @{ $def }; } elsif ( ref $def eq 'HASH' ) { say qq{$driver $_} for products($def); } else { die "Unknown def for $driver!" } } sub products { state $C = do { local $/; readline *DATA }; state $D = File::Temp->newdir("firmware_patterns-XXXXXXXXX"); my ($def) = @_; my $type = $def->{type}; my $f = "$D/$type"; { open my $fh, ">", "$f.c" or die "Unable to create $f.c: $!"; $fh->print( $C =~ s/%type%/$type/gr ); close $fh; } system(cc => '-o', $f, '-I', "/usr/src/$def->{dir}", "$f.c") == 0 or die "cc $f.c failed!"; open my $fh, '-|', $f or die "Unable to fork $f: $!"; my @patterns = $fh->getlines; close $fh; chomp @patterns; my %seen; return map { qq{"$_"} } grep { !$seen{$_}++ } sort grep { ! /\s$/ } # ignore items with just a vendor map { s/^\p{XDigit}+:\p{XDigit}+\s+//r } @patterns; } __DATA__ #include #include #include #include #include #include struct pci_matchid { pci_vendor_id_t pm_vid; pci_product_id_t pm_pid; }; #include "%type%_devlist.h" #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) const char * pci_findvendor(pci_vendor_id_t vendor) { const struct pci_known_vendor *kdp; kdp = pci_known_vendors; while (kdp->vendorname != NULL) { /* all have vendor name */ if (kdp->vendor == vendor) break; kdp++; } return (kdp->vendorname); } const char * pci_findproduct(pci_vendor_id_t vendor, pci_product_id_t product) { const struct pci_known_product *pkp; pkp = pci_known_products; while (pkp->productname != NULL) { /* all have product name */ if (pkp->vendor == vendor && pkp->product == product) break; pkp++; } return (pkp->productname); } int main(void) { int i; const char *v, *p; for (i = 0; i < nitems(%type%_devices); i++) { v = pci_findvendor(%type%_devices[i].pm_vid); p = pci_findproduct(%type%_devices[i].pm_vid, %type%_devices[i].pm_pid); printf("%04x:%04x", %type%_devices[i].pm_vid, %type%_devices[i].pm_pid); printf(" %s %s\n", v ? v : "", p ? p : ""); } return 0; }