[BACK]Return to firmware_patterns.pl CVS log [TXT][DIR] Up to [local] / openbsd / fw_update

File: [local] / openbsd / fw_update / firmware_patterns.pl (download)

Revision 1.2, Wed Dec 22 03:05:48 2021 UTC (2 years, 4 months ago) by afresh1
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -0 lines

Ignore devices with only a vendor

Not sure why they exist, but whatever.

#!/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 <sys/types.h>
#include <stdio.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
#include <dev/pci/pcidevs_data.h>

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;
}