~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/util/parserom.pl

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env perl
 
2
#
 
3
# Parse PCI_ROM and ISA_ROM entries from source file(s) specified as
 
4
# arguments and output the relevant Makefile rules to STDOUT.
 
5
#
 
6
# Originally based on portions of Ken Yap's genrules.pl. Completely
 
7
# rewritten by Robin Smidsrød to be more maintainable.
 
8
 
 
9
use strict;
 
10
use warnings;
 
11
use Getopt::Long;
 
12
 
 
13
# Parse command-line options
 
14
my @exclude_driver_classes = ();
 
15
my @exclude_drivers = ();
 
16
my $debug = 0;
 
17
my $help = 0;
 
18
GetOptions(
 
19
    "exclude-driver-class=s" => \@exclude_driver_classes,
 
20
    "exclude-driver=s"       => \@exclude_drivers,
 
21
    "debug"                  => \$debug,
 
22
    "help"                   => \$help,
 
23
);
 
24
 
 
25
# Convert exclution arrays to lookup tables
 
26
my $exclude_driver_class_map = { map { $_ => 1 } @exclude_driver_classes };
 
27
my $exclude_driver_map       = { map { $_ => 1 } @exclude_drivers        };
 
28
 
 
29
# Ensure STDOUT and STDERR are synchronized if debugging
 
30
if ( $debug ) {
 
31
    STDOUT->autoflush(1);
 
32
    STDERR->autoflush(1);
 
33
}
 
34
 
 
35
# Compile regular expressions here for slight performance boost
 
36
my %RE = (
 
37
    'parse_driver_class'    => qr{ drivers/ (\w+?) / }x,
 
38
    'parse_family'          => qr{^ (?:\./)? (.*) \..+? $}x,
 
39
    'find_rom_line'         => qr/^ \s* ( (PCI|ISA)_ROM \s* \( \s* (.*?) ) $/x,
 
40
    'extract_pci_id'        => qr/^ \s* 0x([0-9A-Fa-f]{4}) \s* ,? \s* (.*) $/x,
 
41
    'extract_quoted_string' => qr/^ \s* \" ([^\"]*?) \" \s* ,? \s* (.*) $/x,
 
42
);
 
43
 
 
44
# Show help if required arguments are missing or help was requested
 
45
show_usage_and_exit() if $help or @ARGV < 1;
 
46
 
 
47
# Process each source file specified
 
48
process_source_file($_) for @ARGV;
 
49
 
 
50
exit;
 
51
 
 
52
sub show_usage_and_exit {
 
53
    print STDERR <<"EOM";
 
54
Syntax: $0 [<options>] <source-file> [<source-file>]
 
55
Options:
 
56
    --exclude-driver-class Exclude specified driver classes
 
57
    --exclude-driver       Exclude specified drivers
 
58
    --debug                Output debug information on STDERR
 
59
    --help                 This help information
 
60
EOM
 
61
    exit 1;
 
62
}
 
63
 
 
64
# Figure out if source file is a driver and look for ROM declarations
 
65
sub process_source_file {
 
66
    my ($source_file) = @_;
 
67
    return unless defined $source_file;
 
68
    return unless length $source_file;
 
69
    my $state = { 'source_file' => $source_file };
 
70
    log_debug("SOURCE_FILE", $state->{source_file});
 
71
    # Skip source files that aren't drivers
 
72
    parse_driver_class( $state );
 
73
    unless ( $state->{'driver_class'} ) {
 
74
        log_debug("SKIP_NOT_DRIVER", $state->{source_file} );
 
75
        return;
 
76
    }
 
77
    # Skip source files with driver classes that are explicitly excluded
 
78
    if ( $exclude_driver_class_map->{ $state->{'driver_class'} } ) {
 
79
        log_debug("SKIP_EXCL_CLASS", $state->{'driver_class'} );
 
80
        return;
 
81
    }
 
82
    # Skip source files without driver information
 
83
    parse_family( $state );
 
84
    parse_driver_name( $state );
 
85
    unless ( $state->{'family'} and $state->{'driver_name'} ) {
 
86
        log_debug("SKIP_NO_DRV_INFO", $state->{source_file} );
 
87
        return;
 
88
    }
 
89
    # Skip source files with drivers that are explicitly excluded
 
90
    if ( $exclude_driver_map->{ $state->{'driver_name'} } ) {
 
91
        log_debug("SKIP_EXCL_DRV", $state->{'driver_name'} );
 
92
        return;
 
93
    }
 
94
    # Iterate through lines in source files looking for ROM declarations
 
95
    # and # output Makefile rules
 
96
    open( my $fh, "<", $state->{'source_file'} )
 
97
        or die "Couldn't open $state->{source_file}: $!\n";
 
98
    while (<$fh>) {
 
99
        process_rom_decl($state, $1, $2, $3) if m/$RE{find_rom_line}/;
 
100
    }
 
101
    close($fh) or die "Couldn't close $source_file: $!\n";
 
102
    return 1;
 
103
}
 
104
 
 
105
# Verify that the found ROM declaration is sane and dispatch to the right
 
106
# handler depending on type
 
107
sub process_rom_decl {
 
108
    my ($state, $rom_line, $rom_type, $rom_decl) = @_;
 
109
    return unless defined $rom_line;
 
110
    return unless length $rom_line;
 
111
    log_debug("ROM_LINE", $rom_line);
 
112
    return unless defined $rom_type;
 
113
    return unless length $rom_type;
 
114
    log_debug("ROM_TYPE", $rom_type);
 
115
    $state->{'type'} = lc $rom_type;
 
116
    return process_pci_rom($state, $rom_decl) if $rom_type eq "PCI";
 
117
    return process_isa_rom($state, $rom_decl) if $rom_type eq "ISA";
 
118
    return;
 
119
}
 
120
 
 
121
# Extract values from PCI_ROM declaration lines and dispatch to
 
122
# Makefile rule generator
 
123
sub process_pci_rom {
 
124
    my ($state, $decl) = @_;
 
125
    return unless defined $decl;
 
126
    return unless length $decl;
 
127
    (my $vendor, $decl) = extract_pci_id($decl,        'PCI_VENDOR');
 
128
    (my $device, $decl) = extract_pci_id($decl,        'PCI_DEVICE');
 
129
    (my $image,  $decl) = extract_quoted_string($decl, 'IMAGE');
 
130
    (my $desc,   $decl) = extract_quoted_string($decl, 'DESCRIPTION');
 
131
    if ( $vendor and $device and $image and $desc ) {
 
132
        print_make_rules( $state, "${vendor}${device}", $desc, $vendor, $device );
 
133
        print_make_rules( $state, $image, $desc, $vendor, $device, 1 );
 
134
    }
 
135
    else {
 
136
        log_debug("WARNING", "Malformed PCI_ROM macro on line $. of $state->{source_file}");
 
137
    }
 
138
    return 1;
 
139
}
 
140
 
 
141
# Extract values from ISA_ROM declaration lines and dispatch to
 
142
# Makefile rule generator
 
143
sub process_isa_rom {
 
144
    my ($state, $decl) = @_;
 
145
    return unless defined $decl;
 
146
    return unless length $decl;
 
147
    (my $image, $decl) = extract_quoted_string($decl, 'IMAGE');
 
148
    (my $desc,  $decl) = extract_quoted_string($decl, 'DESCRIPTION');
 
149
    if ( $image and $desc ) {
 
150
        print_make_rules( $state, $image, $desc );
 
151
    }
 
152
    else {
 
153
        log_debug("WARNING", "Malformed ISA_ROM macro on line $. of $state->{source_file}");
 
154
    }
 
155
    return 1;
 
156
}
 
157
 
 
158
# Output Makefile rules for the specified ROM declarations
 
159
sub print_make_rules {
 
160
    my ( $state, $image, $desc, $vendor, $device, $dup ) = @_;
 
161
    unless ( $state->{'is_header_printed'} ) {
 
162
        print "# NIC\t\n";
 
163
        print "# NIC\tfamily\t$state->{family}\n";
 
164
        print "DRIVERS_$state->{driver_class} += $state->{driver_name}\n";
 
165
        print "DRIVERS += $state->{driver_name}\n";
 
166
        print "\n";
 
167
        $state->{'is_header_printed'} = 1;
 
168
    }
 
169
    return if $vendor and ( $vendor eq "ffff" or $device eq "ffff" );
 
170
    my $ids = $vendor ? "$vendor,$device" : "-";
 
171
    print "# NIC\t$image\t$ids\t$desc\n";
 
172
    print "DRIVER_$image = $state->{driver_name}\n";
 
173
    print "ROM_TYPE_$image = $state->{type}\n";
 
174
    print "ROM_DESCRIPTION_$image = \"$desc\"\n";
 
175
    print "PCI_VENDOR_$image = 0x$vendor\n" if $vendor;
 
176
    print "PCI_DEVICE_$image = 0x$device\n" if $device;
 
177
    print "ROMS += $image\n" unless $dup;
 
178
    print "ROMS_$state->{driver_name} += $image\n" unless $dup;
 
179
    print "\n";
 
180
    return 1;
 
181
}
 
182
 
 
183
# Driver class is whatever comes after the "drivers" part of the filename (relative path)
 
184
sub parse_driver_class {
 
185
    my ($state) = @_;
 
186
    my $filename = $state->{'source_file'};
 
187
    return unless defined $filename;
 
188
    return unless length $filename;
 
189
    if ( $filename =~ m/$RE{parse_driver_class}/ ) {
 
190
        log_debug("DRIVER_CLASS", $1);
 
191
        $state->{'driver_class'} = $1;
 
192
    }
 
193
    return;
 
194
}
 
195
 
 
196
# Family name is filename (relative path) without extension
 
197
sub parse_family {
 
198
    my ($state) = @_;
 
199
    my $filename = $state->{'source_file'};
 
200
    return unless defined $filename;
 
201
    return unless length $filename;
 
202
    if ( $filename =~ m/$RE{parse_family}/ ) {
 
203
        log_debug("FAMILY", $1);
 
204
        $state->{'family'} = $1;
 
205
    }
 
206
    return;
 
207
}
 
208
 
 
209
# Driver name is last part of family name
 
210
sub parse_driver_name {
 
211
    my ($state) = @_;
 
212
    my $family = $state->{'family'};
 
213
    return unless defined $family;
 
214
    return unless length $family;
 
215
    my @parts = split "/", $family;
 
216
    $state->{'driver_name'} = $parts[-1];
 
217
    log_debug("DRIVER", $state->{'driver_name'});
 
218
    return;
 
219
}
 
220
 
 
221
# Extract a PCI vendor/device ID e.g. 0x8086, possibly followed by a comma
 
222
# Should always be 4-digit lower-case hex number
 
223
sub extract_pci_id {
 
224
    my ($str, $label) = @_;
 
225
    return "", $str unless defined $str;
 
226
    return "", $str unless length $str;
 
227
    if ( $str =~ m/$RE{extract_pci_id}/ ) {
 
228
        my $id = lc $1;
 
229
        log_debug($label, $id);
 
230
        return $id, $2;
 
231
    }
 
232
    return "", $str;
 
233
}
 
234
 
 
235
# Extract a double-quoted string, possibly followed by a comma
 
236
sub extract_quoted_string {
 
237
    my ($str, $label) = @_;
 
238
    return "", $str unless defined $str;
 
239
    return "", $str unless length $str;
 
240
    if ( $str =~ m/$RE{extract_quoted_string}/ ) {
 
241
        log_debug($label, $1);
 
242
        return $1, $2;
 
243
    }
 
244
    return "", $str;
 
245
}
 
246
 
 
247
# Output debug info to STDERR (off by default)
 
248
sub log_debug {
 
249
    my ($label, $str) = @_;
 
250
    return unless $debug;
 
251
    return unless defined $str;
 
252
    print STDERR "\n" if $label eq 'SOURCE_FILE';
 
253
    print STDERR "=";
 
254
    if ( defined $label ) {
 
255
        my $pad_count = 16 - length $label;
 
256
        print STDERR $label . ":" . ( " " x $pad_count );
 
257
    }
 
258
    print STDERR $str . "\n";
 
259
    return;
 
260
}