Subversion Repositories DevTools

Rev

Rev 1111 | Rev 4769 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1111 thunter 1
########################################################################
2
# Copyright (C) 2008 ERG Limited, All rights reserved
3
#
4
# Module name   : Proc_day0fs_script.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   :
10
#
11
# Usage:
12
#
13
#......................................................................#
14
 
15
require 5.008_002;
16
 
17
use strict;
18
use warnings;
19
 
20
use Pod::Usage;
21
use Getopt::Long;
22
use File::Path;
23
use File::Copy;
24
 
25
use FindBin;                                    # Determine the current directory
26
use lib "$FindBin::Bin";                        # Allow Modules in current directory
27
 
28
use JatsError;
29
use JatsSystem;
30
use FileUtils;
31
use JatsCopy qw(SetCopyDirDefaults DeleteDir CopyDir CreateDir);
32
use CreateSdImage qw( CreateSdImage );
33
 
34
#
35
#
36
#   Global Variables
37
#
38
my $VERSION = 1.0;
39
our $AUTOLOAD;
40
my $BUILD = 'build';                        # Build subdir
41
my $WORK = "${BUILD}/image";
42
 
43
my $source_specified = 0;                   # Ensure that source is specified
44
my $output_image = 0;                       # Ensure output is specified
45
my $output_sd = 0;
46
 
47
#
48
#   Command line options
49
#
50
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
51
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
52
my $opt_vargs;                              # Verbose arg
53
my $opt_help = 0;
54
my $opt_manual = 0;
55
my $opt_clean = 0;
56
my $opt_platform;
57
my $opt_type;
58
my $opt_buildname;
59
my $opt_packagedir;
60
my $opt_interfacedir;
61
my $opt_compilerpath;
62
my $opt_product;
63
my $opt_packagebindir;
64
our $opt_buildroot;
65
my $opt_target;
66
my $opt_version;
67
my $opt_userscript;
68
 
69
#-------------------------------------------------------------------------------
70
# Function        : Mainline Entry Point
71
#
72
# Description     :
73
#
74
# Inputs          :
75
#
76
my $result = GetOptions (
77
                "help+"             => \$opt_help,
78
                "manual"            => \$opt_manual,
79
                "verbose:s"         => \$opt_vargs,
80
                "clean"             => \$opt_clean,
81
                "Platform=s"        => \$opt_platform,
82
                "Type=s"            => \$opt_type,
83
                "BuildName=s"       => \$opt_buildname,
84
                "PackageDir=s"      => \$opt_packagedir,
85
                "InterfaceDir=s"    => \$opt_interfacedir,
86
                "CompilerPath=s"    => \$opt_compilerpath,
87
                "Product=s"         => \$opt_product,
88
                "PackageBinDir=s"   => \$opt_packagebindir,
89
                "BuildRoot=s"       => \$opt_buildroot,
90
                "Target=s"          => \$opt_target,
91
                "BuildVersion=s"    => \$opt_version,
92
                "UserScript=s"      => \$opt_userscript,
93
 
94
    );
95
 
96
#
97
#   Process help and manual options
98
#
99
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
100
pod2usage(-verbose => 1)  if ($opt_help == 2 );
101
pod2usage(-verbose => 2)  if ($opt_manual || ($opt_help > 2));
102
 
103
#
104
#   Configure the error reporting process now that we have the user options
105
#
106
$opt_verbose++ unless ( $opt_vargs eq '@' );
107
ErrorConfig( 'name'    => 'Proc_Day0fs',
108
             'verbose' => $opt_verbose );
109
 
110
#
111
#   Configure the System command to fail on any error
112
#
113
SystemConfig ( ExitOnError => 1 );
114
SetCopyDirDefaults ( 'EmptyDirs' => 1 ,Log => 0 );
115
 
116
#
117
#   Init the FileSystem Uiltity interface
118
#
119
InitFileUtils();
120
 
121
#
122
#   Ensure that we have all required options
123
#
124
Error ("CompilePath not set")       unless ( $opt_compilerpath );
125
Error ("Platform not set")          unless ( $opt_platform );
126
Error ("Type not set")              unless ( $opt_type );
127
Error ("BuildName not set")         unless ( $opt_buildname );
128
Error ("PackageBinDir not set")     unless ( $opt_packagebindir );
129
Error ("InterfaceDir not set")      unless ( $opt_interfacedir );
130
Error ("CompilePath not set")       unless ( $opt_compilerpath );
131
Error ("Product not set")           unless ( $opt_product );
132
Error ("BuildRoot not set")         unless ( $opt_buildroot );
133
Error ("Target not set")            unless ( $opt_target );
134
Error ("User Script not set")       unless ( $opt_userscript );
135
 
136
#
137
#   Calculate a few paths
138
#
139
my $TOOLSUITE = $opt_compilerpath;
140
$TOOLSUITE =~ s~^.*/~~;
141
$TOOLSUITE =~ s~-gcc$~~;
142
 
143
my $CROSSLIBS = $opt_compilerpath;
144
$CROSSLIBS =~ s~/bin/.*$~~;
145
$CROSSLIBS .= "/${TOOLSUITE}/lib";
146
 
147
my $CROSSEXE = $opt_compilerpath;
148
$CROSSEXE =~ s~/bin/.*$~~;
149
$CROSSEXE .= "/${TOOLSUITE}";
150
 
151
 
152
my $CROSS_COMPILE = $opt_compilerpath;
153
$CROSS_COMPILE =~ s~gcc$~~;
154
 
1113 alewis 155
my $CROSS_OBJCOPY = ${CROSS_COMPILE} . "objcopy";
1111 thunter 156
 
157
#
158
#   Display variables used
159
#
160
Message    "======================================================================";
161
Message    "Build day0 file system";
162
Message    "           Package: ${opt_buildname}";
163
Message    "           Version: ${opt_version}";
164
Message    "      Building for: ${opt_platform}, $opt_target";
165
Message    "           Product: ${opt_product}";
166
Message    "              Type: ${opt_type}";
167
Message    "            Script: ${opt_userscript}";
168
Verbose    "           Verbose: ${opt_verbose}";
169
Message    "         BuildRoot: ${opt_buildroot}";
170
Verbose    "         BuildRoot: ${opt_buildroot}";
171
Verbose    "      InterfaceDir: ${opt_interfacedir}";
172
Verbose    "     CROSS_COMPILE: ${CROSS_COMPILE}";
173
Verbose    "         CROSSLIBS: ${CROSSLIBS}";
1113 alewis 174
Verbose    "     CROSS_OBJCOPY: ${CROSS_OBJCOPY}";
1111 thunter 175
Message    "======================================================================";
176
 
177
#
178
#   Perform Clean up
179
#   Invoked during "make clean" or "make clobber"
180
#
181
if ( $opt_clean )
182
{
183
    Message ("Remove build directory: $BUILD");
184
    rmtree( $BUILD );
185
    exit;
186
}
187
 
188
#
189
#   Have setup the basics
190
#   Invoke the user script to drive the remainder of the process
191
#       The script should only contain known directives
192
#       The directives will build up data structures that will be processed
193
#       after the script has been read
194
#
195
#
196
Message ("Process User Script: $opt_userscript");
197
Error ("Board Specfic file Not found: $opt_userscript") unless ( -f $opt_userscript );
198
require $opt_userscript;
199
 
200
#
201
#   The process of requiring the user script
202
#   will have done all the required work
203
#   Perform minor sanity testing
204
#
205
#
206
#   All done
207
#
208
Error ( "No package output specified" )
209
    unless ( $output_image || $output_sd );
210
exit 0;
211
 
212
 
213
################################################################################
214
################################################################################
215
#
216
#   The following functions are intended to be used to manipulate files within
217
#   the output image.
218
#
219
#   These may be used by the board specfic functions.
220
#
221
################################################################################
222
 
223
#-------------------------------------------------------------------------------
224
# Function        : Day0Source
225
#
226
# Description     : Determine the source of the Day0 File System
227
#                   Use of this directive is mandatory
228
#
229
#
230
# Inputs          : Options
231
#                       --Dir=name              - Source dir
232
#                       --Image=name            - Source image
233
#
234
# Returns         : Nothing
235
#
236
sub Day0Source
237
{
238
    my ($opt) = @_;
239
    #
240
    #   Can only use this directive ONCE
241
    #
242
    Error ("Multiple Day0Source directives not allowed")
243
        if ( $source_specified++ );
244
 
245
    #
246
    #   Start with a clean slate
247
    #
248
    DeleteDir ( $WORK );
249
 
250
    #
251
    #   Process options
252
    #
253
    if ( $opt =~ /^--Dir=(.+)/ ) {
254
        #
255
        #   User has specified a directory
256
        #   Copy the entire directory to the work area
257
        #
258
        Message ("Copy in Day0 source directory: $WORK");
259
        CopyDir ( $1, $WORK, 'DeleteFirst' => 1 );
260
 
261
    } elsif ( $opt =~ /^--Image=(.+)/ ) {
262
 
263
        #
264
        #   User has specified an Image
265
        #   Locate the image and extract it into the work area
266
        #
267
        my $name = $1;
268
        Message ("Extract File System Image: $name");
269
 
270
        #
271
        #   File will come from a Package
272
        #   This is where the tool places output files
273
        #
274
        my $fname = Internal::LocateFile ('bin', $name . '.tgz' );
275
        Error ("Cannot locate Day0 source image: $name")
276
            unless $fname;
277
 
278
        #
279
        #   Create a Tar command
280
        #   Assumes the presence of a GNU style tar
281
        #
282
        CreateDir ( $WORK );
283
        System ( 'gtar',
284
                 '--extract',
285
                 '--file',  $fname,
286
                 '--gzip',
287
                 IsVerbose(1) ? ( '--verbose' ) : (),
288
                 '--directory', $WORK,
289
                 );
290
 
291
    } else {
292
        Error ("Unknown Day0Source option: $opt");
293
    }
294
}
295
 
296
 
297
#-------------------------------------------------------------------------------
298
# Function        : Day0Operation
299
#
300
# Description     : Perform one of the special Day0 Operations
301
#
302
# Inputs          : $subfunction            - Sub function to perform
303
#                   @opts                   - Sub function options
304
#
305
# Returns         : Nothing
306
#
307
sub Day0Operation
308
{
309
    Error ("Day0Source must be specified first")
310
        unless ( $source_specified );
311
 
312
    #
313
    #   Perform the Day0Operation
314
    #   These are specialised operations and normally only performed on the
315
    #   the basic skelton.
316
    #
317
    #   Dispatch to the required function
318
    #
319
    my $opt = shift (@_);
320
    if ( my $fref = UNIVERSAL::can ( 'Day0Ops', lc($opt) ) )
321
    {
322
        &$fref( @_ );
323
    }
324
    else
325
    {
326
        Error ("Unknown Day0Operation option: $opt @_");
327
    }
328
}
329
 
330
#-------------------------------------------------------------------------------
331
# Function        : Day0BuildImage
332
#
333
# Description     : Package up the created image as a tar-zip file
334
#                   This allows the Image to be processed again later
335
#
336
# Inputs          : Options
337
#                       --name=Name             - Output Name
338
#
339
# Returns         : 
340
#
341
sub Day0BuildImage
342
{
343
    my $name = 'Day0Image';
344
    Message ("Create File System Image; $name");
345
 
346
    #
347
    #   Indicate that we have created some output
348
    #
349
    Error ("Day0Source must be specified first")
350
        unless ( $source_specified );
351
    $output_image++;
352
 
353
    #
354
    #   Process user options
355
    #
356
    foreach  ( @_ )
357
    {
358
        if ( m~^--Name=(.+)~i ) {
359
            $name = $1;
360
        } else {
361
            Error ("Day0BuildImage: Unknown option: $_");
362
        }
363
    }
364
 
365
    #
366
    #   Place the file in the BIN directory
367
    #   Have no reall good reason
368
    #
369
    $name = $opt_packagebindir . '/' . $name . '.tgz';
370
    CreateDir ( $opt_packagebindir);
371
 
372
    #
373
    #   Create a Tar command
374
    #   Assumes the presence of a GNU style tar
375
    #
376
    System ( 'gtar',
377
             '--create',
378
             '--file',  $name,
379
             '--gzip',
380
             IsVerbose(1) ? ( '--verbose' ) : (),
381
             '--directory', $WORK,
382
             '.' );
383
}
384
 
385
#-------------------------------------------------------------------------------
386
# Function        : Day0BuildSdImage
387
#
388
# Description     : Package up the created image and create an SD memory image
389
#                   This is destructive and can only be done one
390
#
391
# Inputs          : Options
392
#                       --disk_blocks           - Size the output disk
393
#                       --full_image            - Size of Full Image
394
#                       --debug
395
#
396
# Returns         : 
397
#
398
sub Day0BuildSdImage
399
{
400
    my $debug;
401
    my %diskGeometry = (
402
            fullfs  => 0,                   # Test Image Size
403
            size    => 501248,              # Block Size of Entire Disk
404
            rootfs  => 30,                  # Root Size (Megabytes)
405
            logfs   => 20,                  # Log
406
            afcfs   => 150,                 # AFC
407
            varfs   => 'rest'               # Var - has the rest
408
            );
409
 
410
 
411
    #
412
    #   Ensure that some work is being done
413
    #
414
    Error ("Day0Source must be specified first")
415
        unless ( $source_specified );
416
 
417
    Error ("Cannot create multiple SD images")
418
        if ( $output_sd++ );
419
 
420
    #
421
    #   Process user options
422
    #
423
    foreach  ( @_ )
424
    {
425
        if ( m~^--disk-blocks=(\d+)$~i ) {
426
            $diskGeometry{'size'} = $1;
427
 
428
        } elsif ( m~^--full_image=(\d+)$~i ) {
429
            $diskGeometry{'fullfs'} = $1;
430
 
431
        } elsif ( m~^--rootfs=(\d+)$~i ) {
432
            $diskGeometry{'rootfs'} = $1;
433
 
434
        } elsif ( m~^--logfs=(\d+)$~i ) {
435
            $diskGeometry{'logfs'} = $1;
436
 
437
        } elsif ( m~^--afcfs=(\d+)$~i ) {
438
            $diskGeometry{'afcfs'} = $1;
439
 
440
        } elsif ( m~^--varfs=~i ) {
441
            Error ('Var File System cannot be configured');
442
 
443
        } elsif ( m~^--debug~i ) {
444
            $debug = 1;
445
        } else {
446
            Error ("Day0BuildSdImage: Unknown option: $_");
447
        }
448
    }
449
 
450
    #
451
    #   Perform specific processing on the image
452
    #
453
 
454
    #
455
    #   Scan the skeleton and process .LINKS files
456
    #   File links do not store well in version control systems
457
    #   NOTE: .LINKS are a local invention and not a part of e2fsimage like
458
    #         .DEVICES on which they are modelled.
459
    #
460
    Message ("Locate LINKFILES in $WORK");
461
    foreach my $linkfile ( Internal::FindFiles( $WORK, ".LINKS" ))
462
    {
463
        my $BASEDIR = StripFileExt( $linkfile );
464
        $BASEDIR =~ s~^$WORK/~~;
465
        Message "Expand links: $BASEDIR";
466
        open (LF, "<", $linkfile ) || Error ("Cannot open link file: $linkfile" );
467
        while ( <LF> )
468
        {
469
            chomp;
470
            next if ( m~^#~ );
471
            next unless ( $_ );
472
            my ($link, $file) = split;
473
 
474
            Internal::MakeSymLink($file ,"$BASEDIR/$link", '--NoDotDot' );
475
        }
476
        close (LF);
477
        unlink $linkfile;
478
    }
479
 
480
 
481
    #   Update the Shared Library Cache
482
    #
483
    Message ("Create Shared Library Cache");
484
    System ('/sbin/ldconfig', '-r', $WORK );
485
 
486
    #
487
    #   Make every thing executable
488
    #       This is good for directories
489
    #       This is good for all files. Shouldn't be an issue to files in /etc
490
    #
491
    Message ("Mark files as executable");
492
    foreach my $dir ( glob ("$WORK/*") )
493
    {
494
        next if ( $dir =~ m~/etc$~ );
495
        System ('chmod', '-R', 'a+rx', $dir );
496
    }
497
 
498
    foreach my $dir ( glob ("$WORK/etc/*") )
499
    {
500
        next unless ( -d $dir );
501
        System ('chmod', '-R', 'a+rx', $dir );
502
    }
503
 
504
    #
505
    #   Special considertaion
506
    #       /etc/busybox.conf   - Accessible by root
507
    #       /bin/busybox        - setuid
508
    #
509
    System ('chmod', '600',  "$WORK/etc/busybox.conf" );
510
    System ('chmod', '4755', "$WORK/bin/busybox" );
511
 
512
    #
513
    #   Stop here if debugging
514
    #   Don't create the actual image as the process destroys the image
515
    #
516
    Error ("Day0BuildSdImage: Debug Image. SD Image not built")
517
        if ( $debug );
518
 
519
    #
520
    #   Invoke SD build function
521
    #   Held in another package to make this one readable
522
    #
523
    my $name = "${opt_buildname}-${opt_version}-${opt_target}";
524
    CreateSdImage( $opt_packagebindir, $name, $WORK, $BUILD, \%diskGeometry );
525
}
526
 
527
#-------------------------------------------------------------------------------
528
# Function        : AddInitScript
529
#
530
# Description     : Add an Init Script to the target
531
#                   Optionally create start and stop links
532
#
533
#                   Existing links will always be delete
534
#
535
# Inputs          : $script     - Name of the init script
536
#                   $start      - Start Number
537
#                   $stop       - Stop Number
538
#                   Options:
539
#                       --NoCopy    - Don't copy the script, just add links
540
#
541
# Returns         : 
542
#
543
sub AddInitScript
544
{
545
    my ( $script, $start, $stop, @opts ) = @_;
546
 
547
    Error ("Day0Source must be specified first")
548
        unless ( $source_specified );
549
 
550
    Message ("AddInitScript: $script, $start, $stop");
551
 
552
    my $tdir = "/etc/init.d/init.d";
553
    my $base = StripDir($script);
554
 
555
    unless ( grep '^--NoCopy', @opts )
556
    {
557
        ::CopyFile( $script, $tdir );
558
    }
559
 
560
    #
561
    #   Delete any existing links
562
    #
563
    foreach my $file ( glob("$WORK/etc/init.d/*$base") )
564
    {
565
        next unless ( $file =~ m~/[KS][\d]+${base}~ );
566
        unlink $file;
567
    }
568
 
569
    my $link;
570
    if ( $start )
571
    {
572
        $link = sprintf ("/etc/init.d/S%2.2d%s", $start, $base );
573
        Internal::MakeSymLink( "$tdir/$base", $link);
574
    }
575
 
576
    if ( $stop )
577
    {
578
        $link = sprintf ("/etc/init.d/K%2.2d%s", $stop, $base );
579
        Internal::MakeSymLink( "$tdir/$base", $link);
580
    }
581
}
582
 
583
#-------------------------------------------------------------------------------
584
# Function        : EchoFile
585
#
586
# Description     : Echo simple text to a file
587
#
588
# Inputs          : $file   - Within the output workspace
589
#                   $text
590
#
591
# Returns         : 
592
#
593
sub EchoFile
594
{
595
    my ($file, $text) = @_;
596
    Error ("Day0Source must be specified first")
597
        unless ( $source_specified );
598
 
599
    $file = $WORK . '/' . $file;
600
    $file =~ s~//~/~;
601
 
602
    unlink $file;
603
    open (DT, ">", $file ) || Error ("Cannot create $file");
604
    print DT  $text || Error ("Cannot print to $file");
605
    close DT;
606
}
607
 
608
#-------------------------------------------------------------------------------
609
# Function        : CopyPkgDir
610
#
611
# Description     : Copy a directory to a target dir
612
#                   Source directory is within a 'package'
613
#                   Does not delete the target directory, but will add files
614
#
615
#                   Currently does not support
616
#                       Recursion
617
#                       Flattening
618
#
619
#
620
# Inputs          : $src_dir    - Within a package
621
#                   $dst_dir    - Within the output workspace
622
#
623
#                   Options:
624
#                       --FilterIn=Filter           Simple filter
625
#                       --FilterOut=Filter          Simple filter
626
#
627
# Returns         :
628
#
629
sub CopyPkgDir
630
{
631
    my @filter_out;
632
    my @filter_in;
633
    my @args;
634
 
635
    Error ("Day0Source must be specified first")
636
        unless ( $source_specified );
637
 
638
    #
639
    #   Process options
640
    #
641
    foreach  ( @_ )
642
    {
643
        if ( m/^--FilterIn=(.+)/ ) {
644
            push @filter_in, $1;
645
 
646
        } elsif ( m/^--FilterOut=(.+)/ ) {
647
            push @filter_out, $1;
648
 
649
        } elsif ( m/^-/ ) {
650
            Error("CopyPkgDir: Unknown option: $_");
651
 
652
        } else {
653
            push @args, $_;
654
        }
655
    }
656
    my ($src_dir, $dst_dir) = @args;
657
    #
658
    #   Calculate the destination path
659
    #
660
    $dst_dir = $WORK . '/' . $dst_dir;
661
    $dst_dir =~ s~//~/~;
662
 
663
    #
664
    #   Validate source dir
665
    #
666
    my $full_src_dir = "$opt_interfacedir/$src_dir";
667
    Error("CopyPkgDir: Source dir not found: $src_dir") unless ( -d $full_src_dir );
668
 
669
    #
670
    #   Copy as required
671
    #
672
    CopyDir ( $full_src_dir, $dst_dir,
673
                    'Flatten' => 1,
674
                    'NoSubDirs' => 1,
675
                    'Ignore' =>  \@filter_out,
676
                    'Match' => \@filter_in,
677
                    );
678
}
679
 
680
#-------------------------------------------------------------------------------
681
# Function        : CopyPackage
682
#
683
# Description     : Copy in files from a package located in the interface
684
#                   directory.
685
#
686
#                   The source directory may be:
687
#                       pkg/<platform>
688
#                       pkg/<product>
689
#                       pkg/<target>
690
#
691
# Inputs          : $section    - Section to search
692
#                   $file       - Source Path within a package
693
#                   @llist      - list of softlinks
694
#                                 Abs or Relative to destination dir
695
#
696
#                   Embedded Options:
697
#                               --Dest=Dir (Default is taken from $file)
698
#                               --LinkFile (Append to .LINKS file)
699
#                               --Rename=Name
700
#
701
# Returns         :  Path to the target file
702
#
703
sub CopyPackage
704
{
705
    my $dest;
706
    my $isa_linkfile;
707
    my @args;
708
    my $dfile;
709
    my @options;
710
 
711
    Error ("Day0Source must be specified first")
712
        unless ( $source_specified );
713
 
714
    #
715
    #   Process and Remove options
716
    #
717
    foreach  ( @_ )
718
    {
719
        if ( m/^--Dest=(.*)/ ) {
720
            $dest = $1 . '/xxx';
721
 
722
        } elsif ( m/^--LinkFile/ ) {
723
            $isa_linkfile = 1;
724
 
725
        } elsif ( m/^--Rename=(.+)/ ) {
726
            push @options, $_;
727
 
728
        } elsif ( m/^--/ ) {
729
            Error ("CopyPackage: Unknown option: $_");
730
 
731
        } else {
732
            push @args, $_;
733
 
734
        }
735
    }
736
 
737
    my ($section, $file, @llist) = @args;
738
 
739
    #
740
    #   Default destination is the same as the source
741
    #
742
    $dest = $file unless ( $dest );
743
    my $dest_dir = StripFileExt($dest);
744
 
745
    my $tfile = Internal::LocateFile($section, $file);
746
    Error ("CopyPackage: File not found: $file") unless $tfile;
747
 
748
    #
749
    #   LinkFiles are special
750
    #   They get concatenated to any existing Link File
751
    #
752
    if ( $isa_linkfile )
753
    {
754
        CatFile ( $tfile, "$dest_dir/.LINKS" );
755
    }
756
    else
757
    {
758
        $dfile = CopyFile ($tfile, $dest_dir, @options );
759
        foreach my $lname ( @llist )
760
        {
761
            $lname = $dest_dir . '/' . $lname unless ( $lname =~ m ~^/~ );
762
            my $dest_file = $dest_dir . '/' . StripDir($dfile);
763
            Internal::MakeSymLink($dest_file ,$lname);
764
        }
765
    }
766
 
767
    return $dfile;
768
}
769
 
770
#-------------------------------------------------------------------------------
771
# Function        : CatFile
772
#
773
# Description     : Copy a file to the end of a file
774
#
775
# Inputs          : $src
776
#                   $dst    - Within the output workspace
777
#
778
# Returns         :
779
#
780
sub CatFile
781
{
782
    my ($src, $dst) = @_;
783
    $dst = $WORK . '/' . $dst;
784
    $dst =~ s~//~/~;
785
    Verbose ("CatFile: $src, $dst");
786
 
787
    Error ("Day0Source must be specified first")
788
        unless ( $source_specified );
789
 
790
    open (SF, '<', $src)  || Error ("CatFile: Cannot open $src");
791
    open (DF, '>>', $dst) || Error ("CatFile: Cannot create:$dst");
792
    while ( <SF> )
793
    {
794
        print DF $_;
795
    }
796
    close (SF);
797
    close (DF);
798
}
799
 
800
 
801
#-------------------------------------------------------------------------------
802
# Function        : CopyFile
803
#
804
# Description     : Copy a file to a target dir
805
#
806
# Inputs          : $src
807
#                   $dst_dir    - Within the output workspace
808
#                   Options     - Optional flags
809
#                                 --Symlink
810
#                                   Copies symlink, not symlink target
811
#                                 --Rename=xxx
812
#                                   Renames file
813
#
814
# Returns         : Full path to destination file
815
#
816
sub CopyFile
817
{
818
    my ($src, $dst_dir, @opts ) = @_;
819
    my $tfile = StripDir($src);
820
    my %opts;
821
 
822
    Error ("Day0Source must be specified first")
823
        unless ( $source_specified );
824
 
825
    #
826
    #   Extract options
827
    #
828
    foreach  ( @opts )
829
    {
830
        if ( m/^--Symlink/ ) {
831
            $opts{DuplicateLinks} = 1;
832
 
833
        } elsif ( m/^--Rename=(.+)/ ) {
834
            $tfile = $1;
835
 
836
        } else {
837
            Error("CopyFile: Unknown option: $_");
838
        }
839
    }
840
 
841
    #
842
    #   Calculate the destination path
843
    #
844
    $dst_dir = $WORK . '/' . $dst_dir;
845
    $dst_dir =~ s~//~/~;
846
 
847
    #
848
    #   Determine the full name of the target
849
    #
850
    my $dst_file = "$dst_dir/$tfile";
851
 
852
    Verbose ("CopyFile: $src, $dst_dir");
853
    return JatsCopy::CopyFile( $src, $dst_file, \%opts );
854
}
855
 
856
#-------------------------------------------------------------------------------
857
# Function        : AUTOLOAD
858
#
859
# Description     : Intercept bad user directives and issue a nice error message
860
#                   This is a simple routine to report unknown user directives
861
#                   It does not attempt to distinguish between user errors and
862
#                   programming errors. It assumes that the program has been
863
#                   tested. The function simply report filename and line number
864
#                   of the bad directive.
865
#
866
# Inputs          : Original function arguments ( not used )
867
#
868
# Returns         : This function does not return
869
#
870
sub AUTOLOAD
871
{
872
    my $fname = $::AUTOLOAD;
873
    $fname =~ s~^\w+::~~;
874
    my ($package, $filename, $line) = caller;
875
 
876
    Error ("Directive not known or not allowed in this context: $fname",
877
           "Directive: $fname( @_ );",
878
           "File: $filename, Line: $line" );
879
}
880
 
881
 
882
#-------------------------------------------------------------------------------
883
# Function        : FirstBoot
884
#
885
# Description     : Add a file to the first boot section
886
#                   Assumes that the firstboot directory is /var/afc/firstboot
887
#                   This is the default
888
#
889
# Inputs          : All options
890
#                       --Debian=xxx[,opts] - Locate debian package
891
#                                             Sub opts are:
892
#                                               --Arch=xxx
893
#                                               --Product=xxx
894
#                                               --Debug
895
#                                               --Prod
896
#                       --File=yyy          - Locate a files
897
#                       --Level=nn          - Level to run (default=50)
898
#
899
# Returns         : 
900
#
901
sub FirstBoot
902
{
903
    my  $file;
904
    my  $level = 50;
905
 
906
    Error ("Day0Source must be specified first")
907
        unless ( $source_specified );
908
 
909
    #
910
    #   Collect user items
911
    #
912
    foreach ( @_ )
913
    {
914
        if ( m~^--Debian=(.+)~ ) {
915
            Error ("FirstBoot: Multiple source files not supported in one directive: $_") if $file;
916
            $file = Internal::LocateDebianFile($1, $opt_target, $opt_product);
917
 
918
        } elsif ( m~^--File=(.+)~ ) {
919
            Error ("FirstBoot: Multiple source files not supported in one directive: $_") if $file;
920
            $file = $1;
921
 
922
        } elsif ( m~^--Level=(\d+)~ ) {
923
            $level = $1;
924
            Error ("FirstBoot: Invalid Level: $_") if ($level < 0 || $level > 99);
925
 
926
        } else {
927
            Error ("FirstBoot: Unknown option or argument: $_");
928
        }
929
    }
930
 
931
    #
932
    #   Insert the required file
933
    #       Prepend name with a two digit level
934
    #
935
    my $fname = sprintf ('%2.2d.%s', $level, StripDir($file)  );
936
    Message ("FirstBoot: $fname");
937
 
938
    CopyFile ( $file, '/var/afc/firstboot', "--Rename=$fname" );
939
}
940
 
941
################################################################################
942
################################################################################
943
#   
944
#   Package to contain DayOp opereration
945
#
946
package Day0Ops;
947
 
948
use strict;
949
use warnings;
950
 
951
 
952
use JatsError;
953
use JatsSystem;
954
use JatsCopy qw(SetCopyDirDefaults DeleteDir CopyDir CreateDir);
955
 
956
#-------------------------------------------------------------------------------
957
# Function        : hostname
958
#
959
# Description     : Insert hostname information into the target
960
#                       Insert /etc/devicetype
961
#                       Insert into hostname too
962
#
963
#
964
# Inputs          : 
965
#
966
# Returns         : 
967
#
968
sub hostname
969
{
970
    Message ("Insert Hostname an Devicename: ${opt_product}");
971
    ::EchoFile ( "/etc/devicetype", $opt_product );
972
    ::EchoFile ( "/etc/hostname", $opt_product );
973
    ::EchoFile ( "/etc/day0-version", "$opt_buildname $opt_version $opt_product $opt_platform $opt_target" );
974
}
975
 
976
#-------------------------------------------------------------------------------
977
# Function        : setupbusybox
978
#
979
# Description     : Insert busybox into the skeleton
980
#                   Locate busybox and associated links file
981
#
982
# Inputs          : None
983
#
984
# Returns         : Nothing
985
#
986
sub setupbusybox
987
{
988
    #
989
    #   Insert busybox into the skeleton
990
    #   Locate busybox and associated links file
991
    #
992
    Message ("Copy in busybox");
993
    my $bbfile  = ::CopyPackage ('bin', 'busybox',       "--Dest=bin" );
994
    my $bblinks = ::CopyPackage ('bin', 'busybox.links', "--Dest=bin" );
995
 
996
    #
997
    #   Expand the busybox links
998
    #   Use soft links. Expect that they will be easier to update in the field
999
    #   Keep the .links file on the target.
1000
    #
1001
    Message "Expand busybox links";
1002
    open ( BBLINK, "<", $bblinks ) || Error ("Cannot open BusyBox Links file");
1003
    while ( <BBLINK> )
1004
    {
1005
        s~\s+~~;
1006
        Internal::MakeSymLink ("/bin/busybox", $_, '--NoDotDot'  );
1007
    }
1008
    close BBLINK;
1009
 
1010
    #
1011
    #   May want to convert busybox.links into a .LINKS file and process
1012
    #   it when we instantiate the file system
1013
    #
1014
 
1015
}
1016
 
1017
#-------------------------------------------------------------------------------
1018
# Function        : upgrade
1019
#
1020
# Description     : Insert day0 upgrade components
1021
#
1022
# Inputs          : None
1023
#
1024
# Returns         : Nothing
1025
#
1026
sub upgrade
1027
{
1028
    Message ("Copy in day0 upgrade");
1029
    my $DAY0BIN="/afc/day-zero/bin";       #/day-zero
1030
 
1031
    ::CopyPackage ('bin',     "--Dest=$DAY0BIN", 'udp_broadcast' );
1032
    ::CopyPackage ('bin',     "--Dest=$DAY0BIN", 'udp_listen' );
1033
    ::CopyPackage ('scripts', "--Dest=$DAY0BIN", 'day-zero.conf' );
1034
    ::CopyPackage ('scripts', "--Dest=$DAY0BIN", 'day-zero.sh', 'day-zero' );
1035
 
1036
    #
1037
    #   Start Day-Zero Service
1038
    #   The service script is a part of the skeleton
1039
    #
1040
    ::AddInitScript ("day-zero"   , 95, 100-95, "--NoCopy" );
1041
}
1042
 
1043
#-------------------------------------------------------------------------------
1044
# Function        : dams
1045
#
1046
# Description     : Insert DAMS
1047
#                   Only sutable for single exe versions
1048
#
1049
# Inputs          : 
1050
#
1051
# Returns         : 
1052
#
1053
sub dams
1054
{
1055
    Message ("Copy in DAMS");
1056
    ::CopyPackage ('bin',     "--Dest=/afc/dams/bin", 'dams' );
1057
}
1058
 
1059
#-------------------------------------------------------------------------------
1060
# Function        : wirelesstools
1061
#
1062
# Description     : Insert wireless tools
1063
#                   This is a multi-call binary
1064
# Inputs          :
1065
#
1066
# Returns         : 
1067
#
1068
sub wirelesstools
1069
{
1070
    Message ("Copy in wireless tools");
1071
 
1072
    ::CopyPackage ('bin', 'ifrename'  , "--Dest=/sbin");
1073
    ::CopyPackage ('bin', 'iwconfig'  , "--Dest=/sbin");
1074
    ::CopyPackage ('bin', 'iwevent'   , "--Dest=/sbin");
1075
    ::CopyPackage ('bin', 'iwgetid'   , "--Dest=/sbin");
1076
    ::CopyPackage ('bin', 'iwlist'    , "--Dest=/sbin");
1077
    ::CopyPackage ('bin', 'iwpriv'    , "--Dest=/sbin");
1078
    ::CopyPackage ('bin', 'iwspy'     , "--Dest=/sbin");
1079
}
1080
 
1081
#-------------------------------------------------------------------------------
1082
# Function        : zd1211
1083
#
1084
# Description     : Copy in the zd1211 support files
1085
#
1086
# Inputs          : 
1087
#
1088
# Returns         : 
1089
#
1090
 
1091
sub zd1211
1092
{
1093
    Message ("Copy in zd1211 firmware");
1094
    ::CopyPkgDir  ( 'pkg/zd1211', '/lib/firmware/zd1211', '--FilterOut=READ*' );
1095
 
1096
    #
1097
    #   Install the start up script
1098
    #   This will be delivered by the kernel package
1099
    #
1100
    ::AddInitScript ("$opt_interfacedir/etc/zd1211", 41, 100-41 );
1101
}
1102
 
1103
#-------------------------------------------------------------------------------
1104
# Function        : kernelmodules
1105
#
1106
# Description     : Insert Kernel Modules
1107
#                   Note: The EMU flavour does not have any kernel modules (yet)
1108
#                          Allow for no files to be present or copied
1109
#
1110
# Inputs          : 
1111
#
1112
# Returns         : 
1113
#
1114
sub kernelmodules
1115
{
1116
    Message ("Copy in Kernel Modules");
1117
    CopyDir ( "${opt_interfacedir}/bin", "$WORK/lib/modules",
1118
                    'Flatten' => 1,
1119
                    'Match' => [ '*.ko' ],
1120
                    'Log' => 1,
1121
                     );
1122
}
1123
 
1124
#-------------------------------------------------------------------------------
1125
# Function        : e2fsprogs
1126
#
1127
# Description     : Insert e2fsprogs
1128
#                   Busybox 1.4.2 and later does not provide these utilities
1129
#                   so they have been built up.
1130
#
1131
# Inputs          :
1132
#
1133
# Returns         : 
1134
#
1135
sub e2fsprogs
1136
{
1137
    #
1138
    #   Only install the files that are needed
1139
    #
1140
    Message        ("Copy in e2fsprogs");
1141
    ::CopyPackage    ('pkg', "/etc/mke2fs.conf");
1142
    ::CopyPackage    ('pkg', "/sbin/fsck");
1143
    ::CopyPackage    ('pkg', "/sbin/tune2fs"   ,"e2label"   ,"findfs");
1144
    ::CopyPackage    ('pkg', "/sbin/mke2fs"    ,"mkfs.ext2" ,"mkfs.ext3");
1145
    ::CopyPackage    ('pkg', "/sbin/e2fsck"    ,"fsck.ext2" ,"fsck.ext3");
1146
    #::CopyPackage   ('pkg', "/sbin/badblocks");
1147
    #::CopyPackage   ('pkg', "/sbin/blkid");
1148
    #::CopyPackage   ('pkg', "/sbin/debugfs");
1149
    #::CopyPackage   ('pkg', "/sbin/dumpe2fs");
1150
    #::CopyPackage   ('pkg', "/sbin/logsave");
1151
    ::CopyPackage    ('pkg', "/sbin/resize2fs");
1152
}
1153
 
1154
#-------------------------------------------------------------------------------
1155
# Function        : compilerruntime
1156
#
1157
# Description     : Copy in the runtime shared libraries provided by the compiler
1158
#                       Many libraries are also symlinked
1159
#                       Need to ensure that the linkis copied
1160
#
1161
#                       Strip many ( but not all) of the libaries
1162
#                       Some are special
1163
# Inputs          : 
1164
#
1165
# Returns         : 
1166
#
1167
sub compilerruntime
1168
{
1169
    Message ("Copy in Compiler Shared Libaries");
1170
    my @slibs;
1171
    JatsCopy::CopyDir( $CROSSLIBS, "$WORK/lib",
1172
                            'Flatten' => 1,
1173
                            'NoSubDirs' => 1,
1174
                            'DuplicateLinks' => 1,
1175
                            'Match' => [ '*.so', '*.so.*[0-9]' ],
1176
                            'FileList' => \@slibs,
1177
                            );
1178
 
1179
 
1180
    foreach my $file (@slibs)
1181
    {
1182
        next if ( -d $file );
1183
        next if ( -l $file );
1184
        next if ( $file =~ m~libgcc_s.so$~ );
1185
        next if ( $file =~ m~libc.so$~ );
1186
        next if ( $file =~ m~libpthread.so$~ );
1187
        next if ( $file =~ m~libthread_db.*\.so~ );         # Needs symbols
1113 alewis 1188
 
1189
	    Verbose ("Creating debug data: $file");
1190
	    System ($CROSS_OBJCOPY, '--only-keep-debug', $file, $file . '.dbg' );
1191
 
1192
	    Verbose ("Stripping: $file");
1193
	    System ($CROSS_OBJCOPY, '--strip-all', $file);
1194
 
1195
	    Verbose ("Linking debug to stripped library: $file");
1196
	    System ($CROSS_OBJCOPY, '--add-gnu-debuglink=' . $file . '.dbg', $file);
1197
 
1198
	    Verbose ("Delecting debug file: $file" . ".dbg");
1199
	    System ("rm", "-f", $file . '.dbg'); 
1111 thunter 1200
    }
1201
 
1202
    #
1203
    #   Copy in ldconfig
1204
    #
1205
    Message ("Copy in the ldconfig utility");
1206
#    ::CopyFile ( "${CROSSEXE}/sbin/ldconfig", "/sbin" );
1207
    ::CopyFile ( "${CROSSEXE}/sbin/ldconfig",          "/sbin" ) if (${CROSSEXE} =~ m~gcc-4\.1\.1-glibc-2\.5~);
1208
    ::CopyFile ( "${CROSSEXE}/sys-root/sbin/ldconfig", "/sbin" ) if (${CROSSEXE} =~ m~gcc-4\.4\.3-glibc-2\.9~);
1209
}
1210
 
1211
#-------------------------------------------------------------------------------
1212
# Function        : grub
1213
#
1214
# Description     : Install grub related files, if requested by the user
1215
#
1216
# Inputs          : Options
1217
#                       --Menu=file             - Found locally
1218
#                       --Kernel=file           - Found in Bin
1219
#
1220
# Returns         : 
1221
#
1222
sub grub
1223
{
1224
    my $menu;
1225
    my $kernel;
1226
 
1227
    Message ("Installing Grub");
1228
 
1229
    #
1230
    #   Extract options
1231
    #
1232
    foreach ( @_ )
1233
    {
1234
        if ( m~^--Menu=(.+)~ ) {
1235
            $menu = $1;
1236
        } elsif ( m~^--Kernel=(.+)~ ) {
1237
            $kernel = $1;
1238
        } else {
1239
            Error ("Day0 Grub: Unknown option: $_");
1240
        }
1241
    }
1242
 
1243
    Error ("Day0 Grub: No Menu file specified") unless ( $menu );
1244
    Error ("Day0 Grub: No Kernel file specified") unless ( $kernel );
1245
 
1246
    ::CopyPackage ( 'pkg', '/boot/grub/grub');                     # Not really needed
1247
    ::CopyPackage ( 'pkg', '/boot/grub/stage1');                   # These are ..
1248
    ::CopyPackage ( 'pkg', '/boot/grub/stage2');
1249
    ::CopyPackage ( 'pkg', '/boot/grub/e2fs_stage1_5');
1250
 
1251
    #
1252
    #   Copy in the user specified boot related files
1253
    #
1254
    ::CopyFile   ( $menu,  '/boot/grub' );
1255
    ::CopyPackage ('bin', $kernel, '--Dest=/boot');
1256
 
1257
}
1258
 
1259
 
1260
 
1261
################################################################################
1262
################################################################################
1263
#
1264
#   Package to contain Internal functions
1265
#   Functions placed here are not available to the user in the user scripts
1266
#   They have been placed here simply to hide them from the user
1267
#
1268
#
1269
package Internal;
1270
 
1271
use strict;
1272
use warnings;
1273
 
1274
use File::Find;
1275
use JatsError;
1276
use FileUtils;
1277
 
1278
#-------------------------------------------------------------------------------
1279
# Function        : MakeSymLink
1280
#
1281
# Description     : Create a symlink - with error detection
1282
#
1283
# Inputs          : old_file    - Link Target
1284
#                                 Path to the link target
1285
#                                 If an ABS path is provided, the routine will
1286
#                                 attempt to create a relative link.
1287
#                   new_file    - Relative to the output work space
1288
#                                 Path to where the 'link' file will be created
1289
#                   Options     - Must be last
1290
#                                 --NoClean         - Don't play with links
1291
#                                 --NoDotDot        - Don't create symlinks with ..
1292
#
1293
# Returns         : Nothing
1294
#
1295
sub MakeSymLink
1296
{
1297
    my $no_clean;
1298
    my $no_dot;
1299
    my @args;
1300
 
1301
    #
1302
    #   Extract options
1303
    #
1304
    foreach ( @_ )
1305
    {
1306
        if ( m/^--NoClean/i ) {
1307
            $no_clean = 1;
1308
 
1309
        } elsif ( m/^--NoDotDot/i ) {
1310
            $no_dot = 1;
1311
 
1312
        } elsif ( m/^--/ ) {
1313
            Error ("MakeSymLink: Unknown option: $_");
1314
 
1315
        } else {
1316
            push @args, $_;
1317
        }
1318
    }
1319
 
1320
    my ($old_file, $new_file) = @args;
1321
 
1322
    my $tfile = $WORK . '/' . $new_file;
1323
    $tfile =~ s~//~/~;
1324
    Verbose ("Symlink $old_file -> $new_file" );
1325
 
1326
    #
1327
    #   Create the directory in which the link will be placed
1328
    #   Remove any existing file of the same name
1329
    #
1330
    my $dir = StripFileExt( $tfile );
1331
    mkdir $dir unless -d $dir;
1332
    unlink $tfile;
1333
 
1334
    #
1335
    #   Determine a good name of the link
1336
    #   Convert to a relative link in an attempt to prune them
1337
    #
1338
    my $sfile = $old_file;
1339
    unless ( $no_clean )
1340
    {
1341
        $sfile = CalcRelPath( StripFileExt( $new_file ), $old_file );
1342
        if ( $no_dot && $sfile =~ m~^../~ )
1343
        {
1344
            $sfile = $old_file;
1345
        }
1346
    }
1347
 
1348
    my $result = symlink $sfile, $tfile;
1349
    Error ("Cannot create symlink. $old_file -> $new_file") unless ( $result );
1350
}
1351
 
1352
#-------------------------------------------------------------------------------
1353
# Function        : LocateFile
1354
#
1355
# Description     : Locate a file within the interface directory
1356
#                   These files will have come from an external package
1357
#
1358
# Inputs          : $section            One of: bin, lib, pkg, scripts
1359
#                                       Will be translated into a suitable path
1360
#                   $file               Path to file
1361
#
1362
# Returns         : Full path to the file
1363
#                   Will return 'undef' if not found
1364
#                   The user must generate the error
1365
#
1366
sub LocateFile
1367
{
1368
    my ($section, $file) = @_;
1369
    my $base = "$opt_interfacedir/$section";
1370
 
1371
    unless ( -d $base )
1372
    {
1373
        Warning("LocateFile: Section not found: $section");
1374
        return undef;
1375
    }
1376
 
1377
    my @done;
1378
    my @parts = GetBuildParts ($opt_interfacedir, $opt_platform );
1379
    push @parts, '';
1380
    foreach my $type ( $opt_type, '' )
1381
    {
1382
        foreach my $subdir ( @parts )
1383
        {
1384
            my $sfile = "$base/$subdir$type/$file";
1385
            $sfile =~ s~//~/~g;
1386
            Verbose2("LocateFile: $sfile");
1387
            if ( -f $sfile )
1388
            {
1389
                unless ( @done )
1390
                {
1391
                    push @done, $sfile;
1392
                }
1393
            }
1394
        }
1395
    }
1396
 
1397
    if ( $#done > 0)
1398
    {
1399
        Warning ("LocateFile: Multiple instances of file found. Only first is used", @done);
1400
    }
1401
    return $done[0];
1402
}
1403
 
1404
#-------------------------------------------------------------------------------
1405
# Function        : LocateDebianFile
1406
#
1407
# Description     : Locate a debian file
1408
#                   Internal Function
1409
#
1410
#                   Scan packages for the Debian package specified
1411
#                   The user provides the base name of the package
1412
#                   A Debian Package name has several fields
1413
#                   These are:
1414
#                       1) Base Name - Provided by the user
1415
#                       2) Version - Version will be wildcarded
1416
#                       3) Architecture - Wildcarded. Uses bin/arch directory
1417
#                   
1418
#                   Expect to find Debian Packages in the bin/PLATFORM subdir
1419
#
1420
# Inputs          : Debian base name, complete with suboptions
1421
#
1422
# Returns         : Full path of the file
1423
#
1424
sub LocateDebianFile
1425
{
1426
    my ($arg, $arch, $product) = @_;
1427
    Verbose("LocateDebianFile: Processing: $arg");
1428
 
1429
    my @type = qw( P D );
1430
    my %debian_file_path;
1431
 
1432
    #
1433
    #   Extract sub-options
1434
    #       --Prod[uction]
1435
    #       --Debug
1436
    #       --Arch[itecture]=yyy
1437
    #
1438
    my ($base_name, @opts) = split( ',', $arg );
1439
    foreach ( @opts )
1440
    {
1441
        if ( m/^--Arch(.*)=(.+)/ ) {
1442
            $arch=$2;
1443
        } elsif ( m/^--Product=(.+)/ ) {
1444
            $product=$1;
1445
        } elsif ( m/^--Prod/ ) {
1446
            @type = 'P';
1447
        } elsif ( m/^--Debug/ ) {
1448
            @type = 'D';
1449
        }
1450
    }
1451
 
1452
    #
1453
    #   Create a list of products
1454
    #   ie: PRODUCT_ARCH
1455
    #
1456
    my @products;
1457
    push @products, $product . '_' . $arch if ( $product );
1458
    push @products, $arch;
1459
 
1460
    #
1461
    #   Scan all packages for the specified debian package
1462
    #
1463
    foreach my $package_dir ( $opt_interfacedir )
1464
    {
1465
        foreach my $type ( @type )
1466
        {
1467
            foreach my $prd ( @products )
1468
            {
1469
                foreach my $joiner ( qw(/ .) )
1470
                {
1471
                    my $dir = "$package_dir/bin$joiner$prd$type";
1472
                    Verbose("LocateDebianFile: Search in $dir");
1473
                    next unless ( -d $dir );
1474
                    my @files = glob ( "$dir/${base_name}_*.deb" );
1475
                    next unless ( @files );
1476
                    push @{$debian_file_path{$type}}, @files;
1477
                }
1478
            }
1479
        }
1480
    }
1481
 
1482
    Error ("Required Debain package not found: $base_name",) unless %debian_file_path;
1483
 
1484
    #
1485
    #   Select 'preferred' type of file
1486
    #   If we are doing a debug build, then prefer debug package
1487
    #   If not available then use any available
1488
    #
1489
    my @debian_file_path = @{$debian_file_path{$opt_type}};
1490
    if ( ! @debian_file_path )
1491
    {
1492
        foreach ( keys %debian_file_path )
1493
        {
1494
            push @debian_file_path,@{$debian_file_path{$_}};
1495
        }
1496
    }
1497
 
1498
    Error ("Multiple matching Debian Packages located", @debian_file_path)
1499
        if ( $#debian_file_path > 0 );
1500
 
1501
    return $debian_file_path[0];
1502
}
1503
 
1504
#-------------------------------------------------------------------------------
1505
# Function        : CalcRelPath
1506
#
1507
# Description     : Return the relative path to the current working directory
1508
#                   as provided in $Cwd
1509
#
1510
# Inputs          : $Cwd - Base dir
1511
#                   $base - Path to convert
1512
#
1513
# Returns         : Relative path from the $Cwd
1514
#
1515
sub CalcRelPath
1516
{
1517
    my ($Cwd, $base) = @_;
1518
 
1519
    my @base = split ('/', $base );
1520
    my @here = split ('/', $Cwd );
1521
    my $result;
1522
 
1523
    Debug("CalcRelPath: Source: $base");
1524
 
1525
    return $base unless ( $base =~ m~^/~ );
1526
 
1527
    #
1528
    #   Remove common bits from the head of both lists
1529
    #
1530
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
1531
    {
1532
        shift @base;
1533
        shift @here;
1534
    }
1535
 
1536
    #
1537
    #   Need to go up some directories from here and then down into base
1538
    #
1539
    $result = '../' x ($#here + 1);
1540
    $result .= join ( '/', @base);
1541
    $result = '.' unless ( $result );
1542
    $result =~ s~//~/~g;
1543
    $result =~ s~/$~~;
1544
 
1545
    Debug("CalcRelPath: Result: $result");
1546
    return $result;
1547
}
1548
 
1549
#-------------------------------------------------------------------------------
1550
# Function        : GetBuildParts
1551
#
1552
# Description     : Determine the 'parts' of the build for the current platform
1553
#                   This is complex information. It is held within the build.cfg
1554
#                   file.
1555
#
1556
# Inputs          : $interface_dir          - Path to the interface dir
1557
#                   $platform               - Platform to process
1558
#
1559
# Returns         : An array of platform parts
1560
#
1561
 
1562
#
1563
#   The following varaibles are "read" in from the build.cfg file
1564
#   In order to access them we need to declare them
1565
#
1566
our %ScmBuildPkgRules;
1567
our %BUILDPLATFORM_PARTS;
1568
 
1569
sub GetBuildParts
1570
{
1571
    my ($interface_dir, $platform) = @_;
1572
 
1573
    #
1574
    #   Tthe build.cfg file is within the interface directory
1575
    #
1576
    my $cfgfile = "$interface_dir/build.cfg";
1577
    Error ("Cannot find file: $cfgfile" ) unless ( -f $cfgfile );
1578
 
1579
    #
1580
    #   Include the build.cfg data
1581
    #
1582
    require ( $cfgfile );
1583
 
1584
    #
1585
    #   Extract the platform parts
1586
    #
1587
    if ( exists  $BUILDPLATFORM_PARTS{$platform})
1588
    {
1589
        return @{$BUILDPLATFORM_PARTS{$platform}};
1590
    }
1591
    else
1592
    {
1593
        Error ("Platform not found in build.cfg: $platform");
1594
    }
1595
}
1596
 
1597
#-------------------------------------------------------------------------------
1598
# Function        : FindFiles
1599
#
1600
# Description     : Locate files within a given dir tree
1601
#
1602
# Inputs          : $root           - Base of the search
1603
#                   $match          - Re to match
1604
#
1605
# Returns         : A list of files that match
1606
#
1607
my @FIND_LIST;
1608
my $FIND_NAME;
1609
 
1610
sub FindFiles
1611
{
1612
    my ($root, $match ) = @_;
1613
    Verbose2("FindFiles: Root: $root, Match: $match");
1614
 
1615
    #
1616
    #   Becareful of closure, Must use globals
1617
    #
1618
    @FIND_LIST = ();
1619
    $FIND_NAME = $match;
1620
    File::Find::find( \&find_files, $root);
1621
 
1622
    #
1623
    #   Find callback program
1624
    #
1625
    sub find_files
1626
    {
1627
        my $item =  $File::Find::name;
1628
        return if ( -d $_ );
1629
        return unless ( $_ =~ m~$FIND_NAME~ );
1630
        push @FIND_LIST, $item;
1631
    }
1632
    return @FIND_LIST;
1633
}
1634
 
1635
 
1636