summaryrefslogtreecommitdiffstats
path: root/src/include/ipxe/efi/import.pl
blob: 0a7669f43e8508ba923ca89a2d66a5abbff442e6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/perl -w

=head1 NAME

import.pl

=head1 SYNOPSIS

import.pl [options] /path/to/edk2/edk2

Options:

    -h,--help		Display brief help message
    -v,--verbose	Increase verbosity
    -q,--quiet		Decrease verbosity

=cut

use File::Spec::Functions qw ( :ALL );
use File::Find;
use File::Path;
use Getopt::Long;
use Pod::Usage;
use FindBin;
use strict;
use warnings;

my $verbosity = 0;

sub try_import_file {
  my $ipxedir = shift;
  my $edktop = shift;
  my $edkdirs = shift;
  my $filename = shift;

  # Skip everything except headers
  return unless $filename =~ /\.h$/;

  # Skip files that are iPXE native headers
  my $outfile = catfile ( $ipxedir, $filename );
  if ( -s $outfile ) {
    open my $outfh, "<$outfile" or die "Could not open $outfile: $!\n";
    my $line = <$outfh>;
    close $outfh;
    chomp $line;
    return if $line =~ /^\#ifndef\s+_IPXE_\S+_H$/;
  }

  # Search for importable header
  foreach my $edkdir ( @$edkdirs ) {
    my $infile = catfile ( $edktop, $edkdir, $filename );
    if ( -e $infile ) {
      # We have found a matching source file - import it
      print "$filename <- ".catfile ( $edkdir, $filename )."\n"
	  if $verbosity >= 1;
      open my $infh, "<$infile" or die "Could not open $infile: $!\n";
      ( undef, my $outdir, undef ) = splitpath ( $outfile );
      mkpath ( $outdir );
      open my $outfh, ">$outfile" or die "Could not open $outfile: $!\n";
      my @dependencies = ();
      my $licence;
      my $maybe_guard;
      my $guard;
      while ( <$infh> ) {
	# Strip CR and trailing whitespace
	s/\r//g;
	s/\s*$//g;
	chomp;
	# Update include lines, and record included files
	if ( s/^(\s*\#include\s+)[<\"](\S+)[>\"]/$1<ipxe\/efi\/$2>/ ) {
	  push @dependencies, $2;
	}
	# Check for BSD licence statement
	if ( /^\s*SPDX-License-Identifier: BSD-2-Clause-Patent$/ ) {
	  die "Licence detected after header guard\n" if $guard;
	  $licence = "BSD2_PATENT";
	}
	# Write out line
	print $outfh "$_\n";
	# Apply FILE_LICENCE() immediately after include guard
	if ( defined $maybe_guard && ! defined $guard ) {
	  if ( /^\#define\s+${maybe_guard}$/ ) {
	    $guard = $maybe_guard;
	    print $outfh "\nFILE_LICENCE ( $licence );\n" if $licence;
	  }
	  undef $maybe_guard;
	}
	if ( /^#ifndef\s+(_?_?\S+_?_)/ ) {
	  $maybe_guard = $1;
	}
      }
      close $outfh;
      close $infh;
      # Warn if no licence was detected
      warn "Cannot detect licence in $infile\n" unless $licence;
      warn "Cannot detect header guard in $infile\n" unless $guard;
      # Recurse to handle any included files that we don't already have
      foreach my $dependency ( @dependencies ) {
	if ( ! -e catfile ( $ipxedir, $dependency ) ) {
	  print "...following dependency on $dependency\n" if $verbosity >= 1;
	  try_import_file ( $ipxedir, $edktop, $edkdirs, $dependency );
	}
      }
      return;
    }
  }
  die "$filename has no equivalent in $edktop\n";
}

# Parse command-line options
Getopt::Long::Configure ( 'bundling', 'auto_abbrev' );
GetOptions (
  'verbose|v+' => sub { $verbosity++; },
  'quiet|q+' => sub { $verbosity--; },
  'help|h' => sub { pod2usage ( 1 ); },
) or die "Could not parse command-line options\n";
pod2usage ( 1 ) unless @ARGV == 1;
my $edktop = shift;

# Identify edk import directories
my $edkdirs = [ "MdePkg/Include", "MdeModulePkg/Include" ];
foreach my $edkdir ( @$edkdirs ) {
  die "Directory \"$edktop\" does not appear to contain the EFI EDK2 "
      ."(missing \"$edkdir\")\n" unless -d catdir ( $edktop, $edkdir );
}

# Identify iPXE EFI includes directory
my $ipxedir = $FindBin::Bin;
die "Directory \"$ipxedir\" does not appear to contain the iPXE EFI includes\n"
    unless -e catfile ( $ipxedir, "../../../include/ipxe/efi" );

if ( $verbosity >= 1 ) {
  print "Importing EFI headers into $ipxedir\nfrom ";
  print join ( "\n and ", map { catdir ( $edktop, $_ ) } @$edkdirs )."\n";
}

# Import headers
find ( { wanted => sub {
  try_import_file ( $ipxedir, $edktop, $edkdirs, abs2rel ( $_, $ipxedir ) );
}, no_chdir => 1 }, $ipxedir );