|  | @@ -0,0 +1,54 @@
 | 
		
	
		
			
			|  | 1 | +#!/usr/bin/perl -w
 | 
		
	
		
			
			|  | 2 | +
 | 
		
	
		
			
			|  | 3 | +use strict;
 | 
		
	
		
			
			|  | 4 | +use warnings;
 | 
		
	
		
			
			|  | 5 | +
 | 
		
	
		
			
			|  | 6 | +use constant DEVICES => "/proc/bus/pci/devices";
 | 
		
	
		
			
			|  | 7 | +
 | 
		
	
		
			
			|  | 8 | +open my $fh, DEVICES
 | 
		
	
		
			
			|  | 9 | +    or die "Could not open ".DEVICES.": $!";
 | 
		
	
		
			
			|  | 10 | +
 | 
		
	
		
			
			|  | 11 | +while ( ( my $line = <$fh> ) ) {
 | 
		
	
		
			
			|  | 12 | +
 | 
		
	
		
			
			|  | 13 | +  # Parse line from /proc/bus/pci/devices
 | 
		
	
		
			
			|  | 14 | +  chomp $line;
 | 
		
	
		
			
			|  | 15 | +  ( my $bus, my $devfn, my $vendor, my $device, my $irq, my $bars, my $lengths,
 | 
		
	
		
			
			|  | 16 | +    my $driver )
 | 
		
	
		
			
			|  | 17 | +      = ( $line =~ /^ ([0-9a-f]{2}) ([0-9a-f]{2}) \s+
 | 
		
	
		
			
			|  | 18 | +		      ([0-9a-f]{4}) ([0-9a-f]{4}) \s+ ([0-9a-f]+) \s+
 | 
		
	
		
			
			|  | 19 | +		      ((?:[0-9a-f]+\s+){7}) ((?:[0-9a-f]+\s+){7})
 | 
		
	
		
			
			|  | 20 | +		      (.+)?$/x )
 | 
		
	
		
			
			|  | 21 | +      or die "Invalid line \"".$line."\"\n";
 | 
		
	
		
			
			|  | 22 | +  ( $bus, $devfn, $vendor, $device, $irq ) =
 | 
		
	
		
			
			|  | 23 | +      map { hex ( $_ ) } ( $bus, $devfn, $vendor, $device, $irq );
 | 
		
	
		
			
			|  | 24 | +  my $dev = ( $devfn >> 3 );
 | 
		
	
		
			
			|  | 25 | +  my $fn = ( $devfn & 0x7 );
 | 
		
	
		
			
			|  | 26 | +  $bars = [ map { hex ( $_ ) } split ( /\s+/, $bars ) ];
 | 
		
	
		
			
			|  | 27 | +  $lengths = [ map { hex ( $_ ) } split ( /\s+/, $lengths ) ];
 | 
		
	
		
			
			|  | 28 | +
 | 
		
	
		
			
			|  | 29 | +  # Calculate expansion ROM BAR presence and length
 | 
		
	
		
			
			|  | 30 | +  my $rom_length = $lengths->[6];
 | 
		
	
		
			
			|  | 31 | +
 | 
		
	
		
			
			|  | 32 | +  # Look for a BAR that could support a .mrom
 | 
		
	
		
			
			|  | 33 | +  my $mrom_ok;
 | 
		
	
		
			
			|  | 34 | +  if ( $rom_length ) {
 | 
		
	
		
			
			|  | 35 | +    for ( my $bar = 0 ; $bar < 7 ; $bar++ ) {
 | 
		
	
		
			
			|  | 36 | +      # Skip I/O BARs
 | 
		
	
		
			
			|  | 37 | +      next if $bars->[$bar] & 0x01;
 | 
		
	
		
			
			|  | 38 | +      # Skip low half of 64-bit BARs
 | 
		
	
		
			
			|  | 39 | +      $bar++ if $bars->[$bar] & 0x04;
 | 
		
	
		
			
			|  | 40 | +      # Skip 64-bit BARs with high dword set
 | 
		
	
		
			
			|  | 41 | +      next if $bars->[$bar] >> 32;
 | 
		
	
		
			
			|  | 42 | +      # Skip BARs smaller than the expansion ROM BAR
 | 
		
	
		
			
			|  | 43 | +      next if $lengths->[$bar] < $rom_length;
 | 
		
	
		
			
			|  | 44 | +      # This BAR is usable!
 | 
		
	
		
			
			|  | 45 | +      $mrom_ok = 1;
 | 
		
	
		
			
			|  | 46 | +      last;
 | 
		
	
		
			
			|  | 47 | +    }
 | 
		
	
		
			
			|  | 48 | +  }
 | 
		
	
		
			
			|  | 49 | +
 | 
		
	
		
			
			|  | 50 | +  printf "%02x:%02x.%x (%04x:%04x)", $bus, $dev, $fn, $vendor, $device;
 | 
		
	
		
			
			|  | 51 | +  printf " supports a %dkB .rom", ( $rom_length / 1024 ) if $rom_length;
 | 
		
	
		
			
			|  | 52 | +  printf " or .mrom" if $mrom_ok;
 | 
		
	
		
			
			|  | 53 | +  printf "\n";
 | 
		
	
		
			
			|  | 54 | +}
 |