Subversion Repositories DevTools

Rev

Rev 4773 | 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 );
4769 alewis 283
        System ( 'tar',
1111 thunter 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
    #
4769 alewis 376
    System ( 'tar',
1111 thunter 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$~ );
4773 alewis 495
        next if ( $dir =~ m~/linuxrc$~ );
1111 thunter 496
        System ('chmod', '-R', 'a+rx', $dir );
497
    }
498
 
499
    foreach my $dir ( glob ("$WORK/etc/*") )
500
    {
501
        next unless ( -d $dir );
502
        System ('chmod', '-R', 'a+rx', $dir );
503
    }
504
 
505
    #
506
    #   Special considertaion
507
    #       /etc/busybox.conf   - Accessible by root
508
    #       /bin/busybox        - setuid
509
    #
510
    System ('chmod', '600',  "$WORK/etc/busybox.conf" );
511
    System ('chmod', '4755', "$WORK/bin/busybox" );
512
 
513
    #
514
    #   Stop here if debugging
515
    #   Don't create the actual image as the process destroys the image
516
    #
517
    Error ("Day0BuildSdImage: Debug Image. SD Image not built")
518
        if ( $debug );
519
 
520
    #
521
    #   Invoke SD build function
522
    #   Held in another package to make this one readable
523
    #
524
    my $name = "${opt_buildname}-${opt_version}-${opt_target}";
525
    CreateSdImage( $opt_packagebindir, $name, $WORK, $BUILD, \%diskGeometry );
526
}
527
 
528
#-------------------------------------------------------------------------------
529
# Function        : AddInitScript
530
#
531
# Description     : Add an Init Script to the target
532
#                   Optionally create start and stop links
533
#
534
#                   Existing links will always be delete
535
#
536
# Inputs          : $script     - Name of the init script
537
#                   $start      - Start Number
538
#                   $stop       - Stop Number
539
#                   Options:
540
#                       --NoCopy    - Don't copy the script, just add links
541
#
542
# Returns         : 
543
#
544
sub AddInitScript
545
{
546
    my ( $script, $start, $stop, @opts ) = @_;
547
 
548
    Error ("Day0Source must be specified first")
549
        unless ( $source_specified );
550
 
551
    Message ("AddInitScript: $script, $start, $stop");
552
 
553
    my $tdir = "/etc/init.d/init.d";
554
    my $base = StripDir($script);
555
 
556
    unless ( grep '^--NoCopy', @opts )
557
    {
558
        ::CopyFile( $script, $tdir );
559
    }
560
 
561
    #
562
    #   Delete any existing links
563
    #
564
    foreach my $file ( glob("$WORK/etc/init.d/*$base") )
565
    {
566
        next unless ( $file =~ m~/[KS][\d]+${base}~ );
567
        unlink $file;
568
    }
569
 
570
    my $link;
571
    if ( $start )
572
    {
573
        $link = sprintf ("/etc/init.d/S%2.2d%s", $start, $base );
574
        Internal::MakeSymLink( "$tdir/$base", $link);
575
    }
576
 
577
    if ( $stop )
578
    {
579
        $link = sprintf ("/etc/init.d/K%2.2d%s", $stop, $base );
580
        Internal::MakeSymLink( "$tdir/$base", $link);
581
    }
582
}
583
 
584
#-------------------------------------------------------------------------------
585
# Function        : EchoFile
586
#
587
# Description     : Echo simple text to a file
588
#
589
# Inputs          : $file   - Within the output workspace
590
#                   $text
591
#
592
# Returns         : 
593
#
594
sub EchoFile
595
{
596
    my ($file, $text) = @_;
597
    Error ("Day0Source must be specified first")
598
        unless ( $source_specified );
599
 
600
    $file = $WORK . '/' . $file;
601
    $file =~ s~//~/~;
602
 
603
    unlink $file;
604
    open (DT, ">", $file ) || Error ("Cannot create $file");
605
    print DT  $text || Error ("Cannot print to $file");
606
    close DT;
607
}
608
 
609
#-------------------------------------------------------------------------------
610
# Function        : CopyPkgDir
611
#
612
# Description     : Copy a directory to a target dir
613
#                   Source directory is within a 'package'
614
#                   Does not delete the target directory, but will add files
615
#
616
#                   Currently does not support
617
#                       Recursion
618
#                       Flattening
619
#
620
#
621
# Inputs          : $src_dir    - Within a package
622
#                   $dst_dir    - Within the output workspace
623
#
624
#                   Options:
625
#                       --FilterIn=Filter           Simple filter
626
#                       --FilterOut=Filter          Simple filter
627
#
628
# Returns         :
629
#
630
sub CopyPkgDir
631
{
632
    my @filter_out;
633
    my @filter_in;
634
    my @args;
635
 
636
    Error ("Day0Source must be specified first")
637
        unless ( $source_specified );
638
 
639
    #
640
    #   Process options
641
    #
642
    foreach  ( @_ )
643
    {
644
        if ( m/^--FilterIn=(.+)/ ) {
645
            push @filter_in, $1;
646
 
647
        } elsif ( m/^--FilterOut=(.+)/ ) {
648
            push @filter_out, $1;
649
 
650
        } elsif ( m/^-/ ) {
651
            Error("CopyPkgDir: Unknown option: $_");
652
 
653
        } else {
654
            push @args, $_;
655
        }
656
    }
657
    my ($src_dir, $dst_dir) = @args;
658
    #
659
    #   Calculate the destination path
660
    #
661
    $dst_dir = $WORK . '/' . $dst_dir;
662
    $dst_dir =~ s~//~/~;
663
 
664
    #
665
    #   Validate source dir
666
    #
667
    my $full_src_dir = "$opt_interfacedir/$src_dir";
668
    Error("CopyPkgDir: Source dir not found: $src_dir") unless ( -d $full_src_dir );
669
 
670
    #
671
    #   Copy as required
672
    #
673
    CopyDir ( $full_src_dir, $dst_dir,
674
                    'Flatten' => 1,
675
                    'NoSubDirs' => 1,
676
                    'Ignore' =>  \@filter_out,
677
                    'Match' => \@filter_in,
678
                    );
679
}
680
 
681
#-------------------------------------------------------------------------------
682
# Function        : CopyPackage
683
#
684
# Description     : Copy in files from a package located in the interface
685
#                   directory.
686
#
687
#                   The source directory may be:
688
#                       pkg/<platform>
689
#                       pkg/<product>
690
#                       pkg/<target>
691
#
692
# Inputs          : $section    - Section to search
693
#                   $file       - Source Path within a package
694
#                   @llist      - list of softlinks
695
#                                 Abs or Relative to destination dir
696
#
697
#                   Embedded Options:
698
#                               --Dest=Dir (Default is taken from $file)
699
#                               --LinkFile (Append to .LINKS file)
700
#                               --Rename=Name
701
#
702
# Returns         :  Path to the target file
703
#
704
sub CopyPackage
705
{
706
    my $dest;
707
    my $isa_linkfile;
708
    my @args;
709
    my $dfile;
710
    my @options;
711
 
712
    Error ("Day0Source must be specified first")
713
        unless ( $source_specified );
714
 
715
    #
716
    #   Process and Remove options
717
    #
718
    foreach  ( @_ )
719
    {
720
        if ( m/^--Dest=(.*)/ ) {
721
            $dest = $1 . '/xxx';
722
 
723
        } elsif ( m/^--LinkFile/ ) {
724
            $isa_linkfile = 1;
725
 
726
        } elsif ( m/^--Rename=(.+)/ ) {
727
            push @options, $_;
728
 
729
        } elsif ( m/^--/ ) {
730
            Error ("CopyPackage: Unknown option: $_");
731
 
732
        } else {
733
            push @args, $_;
734
 
735
        }
736
    }
737
 
738
    my ($section, $file, @llist) = @args;
739
 
740
    #
741
    #   Default destination is the same as the source
742
    #
743
    $dest = $file unless ( $dest );
744
    my $dest_dir = StripFileExt($dest);
745
 
746
    my $tfile = Internal::LocateFile($section, $file);
747
    Error ("CopyPackage: File not found: $file") unless $tfile;
748
 
749
    #
750
    #   LinkFiles are special
751
    #   They get concatenated to any existing Link File
752
    #
753
    if ( $isa_linkfile )
754
    {
755
        CatFile ( $tfile, "$dest_dir/.LINKS" );
756
    }
757
    else
758
    {
759
        $dfile = CopyFile ($tfile, $dest_dir, @options );
760
        foreach my $lname ( @llist )
761
        {
762
            $lname = $dest_dir . '/' . $lname unless ( $lname =~ m ~^/~ );
763
            my $dest_file = $dest_dir . '/' . StripDir($dfile);
764
            Internal::MakeSymLink($dest_file ,$lname);
765
        }
766
    }
767
 
768
    return $dfile;
769
}
770
 
771
#-------------------------------------------------------------------------------
772
# Function        : CatFile
773
#
774
# Description     : Copy a file to the end of a file
775
#
776
# Inputs          : $src
777
#                   $dst    - Within the output workspace
778
#
779
# Returns         :
780
#
781
sub CatFile
782
{
783
    my ($src, $dst) = @_;
784
    $dst = $WORK . '/' . $dst;
785
    $dst =~ s~//~/~;
786
    Verbose ("CatFile: $src, $dst");
787
 
788
    Error ("Day0Source must be specified first")
789
        unless ( $source_specified );
790
 
791
    open (SF, '<', $src)  || Error ("CatFile: Cannot open $src");
792
    open (DF, '>>', $dst) || Error ("CatFile: Cannot create:$dst");
793
    while ( <SF> )
794
    {
795
        print DF $_;
796
    }
797
    close (SF);
798
    close (DF);
799
}
800
 
801
 
802
#-------------------------------------------------------------------------------
803
# Function        : CopyFile
804
#
805
# Description     : Copy a file to a target dir
806
#
807
# Inputs          : $src
808
#                   $dst_dir    - Within the output workspace
809
#                   Options     - Optional flags
810
#                                 --Symlink
811
#                                   Copies symlink, not symlink target
812
#                                 --Rename=xxx
813
#                                   Renames file
814
#
815
# Returns         : Full path to destination file
816
#
817
sub CopyFile
818
{
819
    my ($src, $dst_dir, @opts ) = @_;
820
    my $tfile = StripDir($src);
821
    my %opts;
822
 
823
    Error ("Day0Source must be specified first")
824
        unless ( $source_specified );
825
 
826
    #
827
    #   Extract options
828
    #
829
    foreach  ( @opts )
830
    {
831
        if ( m/^--Symlink/ ) {
832
            $opts{DuplicateLinks} = 1;
833
 
834
        } elsif ( m/^--Rename=(.+)/ ) {
835
            $tfile = $1;
836
 
837
        } else {
838
            Error("CopyFile: Unknown option: $_");
839
        }
840
    }
841
 
842
    #
843
    #   Calculate the destination path
844
    #
845
    $dst_dir = $WORK . '/' . $dst_dir;
846
    $dst_dir =~ s~//~/~;
847
 
848
    #
849
    #   Determine the full name of the target
850
    #
851
    my $dst_file = "$dst_dir/$tfile";
852
 
853
    Verbose ("CopyFile: $src, $dst_dir");
854
    return JatsCopy::CopyFile( $src, $dst_file, \%opts );
855
}
856
 
857
#-------------------------------------------------------------------------------
858
# Function        : AUTOLOAD
859
#
860
# Description     : Intercept bad user directives and issue a nice error message
861
#                   This is a simple routine to report unknown user directives
862
#                   It does not attempt to distinguish between user errors and
863
#                   programming errors. It assumes that the program has been
864
#                   tested. The function simply report filename and line number
865
#                   of the bad directive.
866
#
867
# Inputs          : Original function arguments ( not used )
868
#
869
# Returns         : This function does not return
870
#
871
sub AUTOLOAD
872
{
873
    my $fname = $::AUTOLOAD;
874
    $fname =~ s~^\w+::~~;
875
    my ($package, $filename, $line) = caller;
876
 
877
    Error ("Directive not known or not allowed in this context: $fname",
878
           "Directive: $fname( @_ );",
879
           "File: $filename, Line: $line" );
880
}
881
 
882
 
883
#-------------------------------------------------------------------------------
884
# Function        : FirstBoot
885
#
886
# Description     : Add a file to the first boot section
887
#                   Assumes that the firstboot directory is /var/afc/firstboot
888
#                   This is the default
889
#
890
# Inputs          : All options
891
#                       --Debian=xxx[,opts] - Locate debian package
892
#                                             Sub opts are:
893
#                                               --Arch=xxx
894
#                                               --Product=xxx
895
#                                               --Debug
896
#                                               --Prod
897
#                       --File=yyy          - Locate a files
898
#                       --Level=nn          - Level to run (default=50)
899
#
900
# Returns         : 
901
#
902
sub FirstBoot
903
{
904
    my  $file;
905
    my  $level = 50;
906
 
907
    Error ("Day0Source must be specified first")
908
        unless ( $source_specified );
909
 
910
    #
911
    #   Collect user items
912
    #
913
    foreach ( @_ )
914
    {
915
        if ( m~^--Debian=(.+)~ ) {
916
            Error ("FirstBoot: Multiple source files not supported in one directive: $_") if $file;
917
            $file = Internal::LocateDebianFile($1, $opt_target, $opt_product);
918
 
919
        } elsif ( m~^--File=(.+)~ ) {
920
            Error ("FirstBoot: Multiple source files not supported in one directive: $_") if $file;
921
            $file = $1;
922
 
923
        } elsif ( m~^--Level=(\d+)~ ) {
924
            $level = $1;
925
            Error ("FirstBoot: Invalid Level: $_") if ($level < 0 || $level > 99);
926
 
927
        } else {
928
            Error ("FirstBoot: Unknown option or argument: $_");
929
        }
930
    }
931
 
932
    #
933
    #   Insert the required file
934
    #       Prepend name with a two digit level
935
    #
936
    my $fname = sprintf ('%2.2d.%s', $level, StripDir($file)  );
937
    Message ("FirstBoot: $fname");
938
 
939
    CopyFile ( $file, '/var/afc/firstboot', "--Rename=$fname" );
940
}
941
 
942
################################################################################
943
################################################################################
944
#   
945
#   Package to contain DayOp opereration
946
#
947
package Day0Ops;
948
 
949
use strict;
950
use warnings;
951
 
952
 
953
use JatsError;
954
use JatsSystem;
955
use JatsCopy qw(SetCopyDirDefaults DeleteDir CopyDir CreateDir);
956
 
957
#-------------------------------------------------------------------------------
958
# Function        : hostname
959
#
960
# Description     : Insert hostname information into the target
961
#                       Insert /etc/devicetype
962
#                       Insert into hostname too
963
#
964
#
965
# Inputs          : 
966
#
967
# Returns         : 
968
#
969
sub hostname
970
{
971
    Message ("Insert Hostname an Devicename: ${opt_product}");
972
    ::EchoFile ( "/etc/devicetype", $opt_product );
973
    ::EchoFile ( "/etc/hostname", $opt_product );
974
    ::EchoFile ( "/etc/day0-version", "$opt_buildname $opt_version $opt_product $opt_platform $opt_target" );
975
}
976
 
977
#-------------------------------------------------------------------------------
978
# Function        : setupbusybox
979
#
980
# Description     : Insert busybox into the skeleton
981
#                   Locate busybox and associated links file
982
#
983
# Inputs          : None
984
#
985
# Returns         : Nothing
986
#
987
sub setupbusybox
988
{
989
    #
990
    #   Insert busybox into the skeleton
991
    #   Locate busybox and associated links file
992
    #
993
    Message ("Copy in busybox");
994
    my $bbfile  = ::CopyPackage ('bin', 'busybox',       "--Dest=bin" );
995
    my $bblinks = ::CopyPackage ('bin', 'busybox.links', "--Dest=bin" );
996
 
997
    #
998
    #   Expand the busybox links
999
    #   Use soft links. Expect that they will be easier to update in the field
1000
    #   Keep the .links file on the target.
1001
    #
1002
    Message "Expand busybox links";
1003
    open ( BBLINK, "<", $bblinks ) || Error ("Cannot open BusyBox Links file");
1004
    while ( <BBLINK> )
1005
    {
1006
        s~\s+~~;
1007
        Internal::MakeSymLink ("/bin/busybox", $_, '--NoDotDot'  );
1008
    }
1009
    close BBLINK;
1010
 
1011
    #
1012
    #   May want to convert busybox.links into a .LINKS file and process
1013
    #   it when we instantiate the file system
1014
    #
1015
 
1016
}
1017
 
1018
#-------------------------------------------------------------------------------
1019
# Function        : upgrade
1020
#
1021
# Description     : Insert day0 upgrade components
1022
#
1023
# Inputs          : None
1024
#
1025
# Returns         : Nothing
1026
#
1027
sub upgrade
1028
{
1029
    Message ("Copy in day0 upgrade");
1030
    my $DAY0BIN="/afc/day-zero/bin";       #/day-zero
1031
 
1032
    ::CopyPackage ('bin',     "--Dest=$DAY0BIN", 'udp_broadcast' );
1033
    ::CopyPackage ('bin',     "--Dest=$DAY0BIN", 'udp_listen' );
1034
    ::CopyPackage ('scripts', "--Dest=$DAY0BIN", 'day-zero.conf' );
1035
    ::CopyPackage ('scripts', "--Dest=$DAY0BIN", 'day-zero.sh', 'day-zero' );
1036
 
1037
    #
1038
    #   Start Day-Zero Service
1039
    #   The service script is a part of the skeleton
1040
    #
1041
    ::AddInitScript ("day-zero"   , 95, 100-95, "--NoCopy" );
1042
}
1043
 
1044
#-------------------------------------------------------------------------------
1045
# Function        : dams
1046
#
1047
# Description     : Insert DAMS
1048
#                   Only sutable for single exe versions
1049
#
1050
# Inputs          : 
1051
#
1052
# Returns         : 
1053
#
1054
sub dams
1055
{
1056
    Message ("Copy in DAMS");
1057
    ::CopyPackage ('bin',     "--Dest=/afc/dams/bin", 'dams' );
1058
}
1059
 
1060
#-------------------------------------------------------------------------------
1061
# Function        : wirelesstools
1062
#
1063
# Description     : Insert wireless tools
1064
#                   This is a multi-call binary
1065
# Inputs          :
1066
#
1067
# Returns         : 
1068
#
1069
sub wirelesstools
1070
{
1071
    Message ("Copy in wireless tools");
1072
 
1073
    ::CopyPackage ('bin', 'ifrename'  , "--Dest=/sbin");
1074
    ::CopyPackage ('bin', 'iwconfig'  , "--Dest=/sbin");
1075
    ::CopyPackage ('bin', 'iwevent'   , "--Dest=/sbin");
1076
    ::CopyPackage ('bin', 'iwgetid'   , "--Dest=/sbin");
1077
    ::CopyPackage ('bin', 'iwlist'    , "--Dest=/sbin");
1078
    ::CopyPackage ('bin', 'iwpriv'    , "--Dest=/sbin");
1079
    ::CopyPackage ('bin', 'iwspy'     , "--Dest=/sbin");
1080
}
1081
 
1082
#-------------------------------------------------------------------------------
1083
# Function        : zd1211
1084
#
1085
# Description     : Copy in the zd1211 support files
1086
#
1087
# Inputs          : 
1088
#
1089
# Returns         : 
1090
#
1091
 
1092
sub zd1211
1093
{
1094
    Message ("Copy in zd1211 firmware");
1095
    ::CopyPkgDir  ( 'pkg/zd1211', '/lib/firmware/zd1211', '--FilterOut=READ*' );
1096
 
1097
    #
1098
    #   Install the start up script
1099
    #   This will be delivered by the kernel package
1100
    #
1101
    ::AddInitScript ("$opt_interfacedir/etc/zd1211", 41, 100-41 );
1102
}
1103
 
1104
#-------------------------------------------------------------------------------
1105
# Function        : kernelmodules
1106
#
1107
# Description     : Insert Kernel Modules
1108
#                   Note: The EMU flavour does not have any kernel modules (yet)
1109
#                          Allow for no files to be present or copied
1110
#
1111
# Inputs          : 
1112
#
1113
# Returns         : 
1114
#
1115
sub kernelmodules
1116
{
1117
    Message ("Copy in Kernel Modules");
1118
    CopyDir ( "${opt_interfacedir}/bin", "$WORK/lib/modules",
1119
                    'Flatten' => 1,
1120
                    'Match' => [ '*.ko' ],
1121
                    'Log' => 1,
1122
                     );
1123
}
1124
 
1125
#-------------------------------------------------------------------------------
1126
# Function        : e2fsprogs
1127
#
1128
# Description     : Insert e2fsprogs
1129
#                   Busybox 1.4.2 and later does not provide these utilities
1130
#                   so they have been built up.
1131
#
1132
# Inputs          :
1133
#
1134
# Returns         : 
1135
#
1136
sub e2fsprogs
1137
{
1138
    #
1139
    #   Only install the files that are needed
1140
    #
1141
    Message        ("Copy in e2fsprogs");
1142
    ::CopyPackage    ('pkg', "/etc/mke2fs.conf");
1143
    ::CopyPackage    ('pkg', "/sbin/fsck");
1144
    ::CopyPackage    ('pkg', "/sbin/tune2fs"   ,"e2label"   ,"findfs");
1145
    ::CopyPackage    ('pkg', "/sbin/mke2fs"    ,"mkfs.ext2" ,"mkfs.ext3");
1146
    ::CopyPackage    ('pkg', "/sbin/e2fsck"    ,"fsck.ext2" ,"fsck.ext3");
1147
    #::CopyPackage   ('pkg', "/sbin/badblocks");
1148
    #::CopyPackage   ('pkg', "/sbin/blkid");
1149
    #::CopyPackage   ('pkg', "/sbin/debugfs");
1150
    #::CopyPackage   ('pkg', "/sbin/dumpe2fs");
1151
    #::CopyPackage   ('pkg', "/sbin/logsave");
1152
    ::CopyPackage    ('pkg', "/sbin/resize2fs");
1153
}
1154
 
1155
#-------------------------------------------------------------------------------
1156
# Function        : compilerruntime
1157
#
1158
# Description     : Copy in the runtime shared libraries provided by the compiler
1159
#                       Many libraries are also symlinked
1160
#                       Need to ensure that the linkis copied
1161
#
1162
#                       Strip many ( but not all) of the libaries
1163
#                       Some are special
1164
# Inputs          : 
1165
#
1166
# Returns         : 
1167
#
1168
sub compilerruntime
1169
{
1170
    Message ("Copy in Compiler Shared Libaries");
1171
    my @slibs;
1172
    JatsCopy::CopyDir( $CROSSLIBS, "$WORK/lib",
1173
                            'Flatten' => 1,
1174
                            'NoSubDirs' => 1,
1175
                            'DuplicateLinks' => 1,
1176
                            'Match' => [ '*.so', '*.so.*[0-9]' ],
1177
                            'FileList' => \@slibs,
1178
                            );
1179
 
1180
 
1181
    foreach my $file (@slibs)
1182
    {
1183
        next if ( -d $file );
1184
        next if ( -l $file );
1185
        next if ( $file =~ m~libgcc_s.so$~ );
1186
        next if ( $file =~ m~libc.so$~ );
1187
        next if ( $file =~ m~libpthread.so$~ );
1188
        next if ( $file =~ m~libthread_db.*\.so~ );         # Needs symbols
1113 alewis 1189
 
1190
	    Verbose ("Creating debug data: $file");
1191
	    System ($CROSS_OBJCOPY, '--only-keep-debug', $file, $file . '.dbg' );
1192
 
1193
	    Verbose ("Stripping: $file");
1194
	    System ($CROSS_OBJCOPY, '--strip-all', $file);
1195
 
1196
	    Verbose ("Linking debug to stripped library: $file");
1197
	    System ($CROSS_OBJCOPY, '--add-gnu-debuglink=' . $file . '.dbg', $file);
1198
 
1199
	    Verbose ("Delecting debug file: $file" . ".dbg");
1200
	    System ("rm", "-f", $file . '.dbg'); 
1111 thunter 1201
    }
1202
 
1203
    #
1204
    #   Copy in ldconfig
1205
    #
1206
    Message ("Copy in the ldconfig utility");
1207
#    ::CopyFile ( "${CROSSEXE}/sbin/ldconfig", "/sbin" );
1208
    ::CopyFile ( "${CROSSEXE}/sbin/ldconfig",          "/sbin" ) if (${CROSSEXE} =~ m~gcc-4\.1\.1-glibc-2\.5~);
1209
    ::CopyFile ( "${CROSSEXE}/sys-root/sbin/ldconfig", "/sbin" ) if (${CROSSEXE} =~ m~gcc-4\.4\.3-glibc-2\.9~);
6702 whooper 1210
    # This is used for COBRA2 and VIPER2
1211
    ::CopyFile ( "${CROSSEXE}/sysroot/sbin/ldconfig", "/sbin" ) if (${CROSSEXE} =~ m~gcc-5\.2\.0-glibc-2\.17~);
1111 thunter 1212
}
1213
 
1214
#-------------------------------------------------------------------------------
1215
# Function        : grub
1216
#
1217
# Description     : Install grub related files, if requested by the user
1218
#
1219
# Inputs          : Options
1220
#                       --Menu=file             - Found locally
1221
#                       --Kernel=file           - Found in Bin
1222
#
1223
# Returns         : 
1224
#
1225
sub grub
1226
{
1227
    my $menu;
1228
    my $kernel;
1229
 
1230
    Message ("Installing Grub");
1231
 
1232
    #
1233
    #   Extract options
1234
    #
1235
    foreach ( @_ )
1236
    {
1237
        if ( m~^--Menu=(.+)~ ) {
1238
            $menu = $1;
1239
        } elsif ( m~^--Kernel=(.+)~ ) {
1240
            $kernel = $1;
1241
        } else {
1242
            Error ("Day0 Grub: Unknown option: $_");
1243
        }
1244
    }
1245
 
1246
    Error ("Day0 Grub: No Menu file specified") unless ( $menu );
1247
    Error ("Day0 Grub: No Kernel file specified") unless ( $kernel );
1248
 
1249
    ::CopyPackage ( 'pkg', '/boot/grub/grub');                     # Not really needed
1250
    ::CopyPackage ( 'pkg', '/boot/grub/stage1');                   # These are ..
1251
    ::CopyPackage ( 'pkg', '/boot/grub/stage2');
1252
    ::CopyPackage ( 'pkg', '/boot/grub/e2fs_stage1_5');
1253
 
1254
    #
1255
    #   Copy in the user specified boot related files
1256
    #
1257
    ::CopyFile   ( $menu,  '/boot/grub' );
1258
    ::CopyPackage ('bin', $kernel, '--Dest=/boot');
1259
 
1260
}
1261
 
1262
 
1263
 
1264
################################################################################
1265
################################################################################
1266
#
1267
#   Package to contain Internal functions
1268
#   Functions placed here are not available to the user in the user scripts
1269
#   They have been placed here simply to hide them from the user
1270
#
1271
#
1272
package Internal;
1273
 
1274
use strict;
1275
use warnings;
1276
 
1277
use File::Find;
1278
use JatsError;
1279
use FileUtils;
1280
 
1281
#-------------------------------------------------------------------------------
1282
# Function        : MakeSymLink
1283
#
1284
# Description     : Create a symlink - with error detection
1285
#
1286
# Inputs          : old_file    - Link Target
1287
#                                 Path to the link target
1288
#                                 If an ABS path is provided, the routine will
1289
#                                 attempt to create a relative link.
1290
#                   new_file    - Relative to the output work space
1291
#                                 Path to where the 'link' file will be created
1292
#                   Options     - Must be last
1293
#                                 --NoClean         - Don't play with links
1294
#                                 --NoDotDot        - Don't create symlinks with ..
1295
#
1296
# Returns         : Nothing
1297
#
1298
sub MakeSymLink
1299
{
1300
    my $no_clean;
1301
    my $no_dot;
1302
    my @args;
1303
 
1304
    #
1305
    #   Extract options
1306
    #
1307
    foreach ( @_ )
1308
    {
1309
        if ( m/^--NoClean/i ) {
1310
            $no_clean = 1;
1311
 
1312
        } elsif ( m/^--NoDotDot/i ) {
1313
            $no_dot = 1;
1314
 
1315
        } elsif ( m/^--/ ) {
1316
            Error ("MakeSymLink: Unknown option: $_");
1317
 
1318
        } else {
1319
            push @args, $_;
1320
        }
1321
    }
1322
 
1323
    my ($old_file, $new_file) = @args;
1324
 
1325
    my $tfile = $WORK . '/' . $new_file;
1326
    $tfile =~ s~//~/~;
1327
    Verbose ("Symlink $old_file -> $new_file" );
1328
 
1329
    #
1330
    #   Create the directory in which the link will be placed
1331
    #   Remove any existing file of the same name
1332
    #
1333
    my $dir = StripFileExt( $tfile );
1334
    mkdir $dir unless -d $dir;
1335
    unlink $tfile;
1336
 
1337
    #
1338
    #   Determine a good name of the link
1339
    #   Convert to a relative link in an attempt to prune them
1340
    #
1341
    my $sfile = $old_file;
1342
    unless ( $no_clean )
1343
    {
1344
        $sfile = CalcRelPath( StripFileExt( $new_file ), $old_file );
1345
        if ( $no_dot && $sfile =~ m~^../~ )
1346
        {
1347
            $sfile = $old_file;
1348
        }
1349
    }
1350
 
1351
    my $result = symlink $sfile, $tfile;
1352
    Error ("Cannot create symlink. $old_file -> $new_file") unless ( $result );
1353
}
1354
 
1355
#-------------------------------------------------------------------------------
1356
# Function        : LocateFile
1357
#
1358
# Description     : Locate a file within the interface directory
1359
#                   These files will have come from an external package
1360
#
1361
# Inputs          : $section            One of: bin, lib, pkg, scripts
1362
#                                       Will be translated into a suitable path
1363
#                   $file               Path to file
1364
#
1365
# Returns         : Full path to the file
1366
#                   Will return 'undef' if not found
1367
#                   The user must generate the error
1368
#
1369
sub LocateFile
1370
{
1371
    my ($section, $file) = @_;
1372
    my $base = "$opt_interfacedir/$section";
1373
 
1374
    unless ( -d $base )
1375
    {
1376
        Warning("LocateFile: Section not found: $section");
1377
        return undef;
1378
    }
1379
 
1380
    my @done;
1381
    my @parts = GetBuildParts ($opt_interfacedir, $opt_platform );
1382
    push @parts, '';
1383
    foreach my $type ( $opt_type, '' )
1384
    {
1385
        foreach my $subdir ( @parts )
1386
        {
1387
            my $sfile = "$base/$subdir$type/$file";
1388
            $sfile =~ s~//~/~g;
1389
            Verbose2("LocateFile: $sfile");
1390
            if ( -f $sfile )
1391
            {
1392
                unless ( @done )
1393
                {
1394
                    push @done, $sfile;
1395
                }
1396
            }
1397
        }
1398
    }
1399
 
1400
    if ( $#done > 0)
1401
    {
1402
        Warning ("LocateFile: Multiple instances of file found. Only first is used", @done);
1403
    }
1404
    return $done[0];
1405
}
1406
 
1407
#-------------------------------------------------------------------------------
1408
# Function        : LocateDebianFile
1409
#
1410
# Description     : Locate a debian file
1411
#                   Internal Function
1412
#
1413
#                   Scan packages for the Debian package specified
1414
#                   The user provides the base name of the package
1415
#                   A Debian Package name has several fields
1416
#                   These are:
1417
#                       1) Base Name - Provided by the user
1418
#                       2) Version - Version will be wildcarded
1419
#                       3) Architecture - Wildcarded. Uses bin/arch directory
1420
#                   
1421
#                   Expect to find Debian Packages in the bin/PLATFORM subdir
1422
#
1423
# Inputs          : Debian base name, complete with suboptions
1424
#
1425
# Returns         : Full path of the file
1426
#
1427
sub LocateDebianFile
1428
{
1429
    my ($arg, $arch, $product) = @_;
1430
    Verbose("LocateDebianFile: Processing: $arg");
1431
 
1432
    my @type = qw( P D );
1433
    my %debian_file_path;
1434
 
1435
    #
1436
    #   Extract sub-options
1437
    #       --Prod[uction]
1438
    #       --Debug
1439
    #       --Arch[itecture]=yyy
1440
    #
1441
    my ($base_name, @opts) = split( ',', $arg );
1442
    foreach ( @opts )
1443
    {
1444
        if ( m/^--Arch(.*)=(.+)/ ) {
1445
            $arch=$2;
1446
        } elsif ( m/^--Product=(.+)/ ) {
1447
            $product=$1;
1448
        } elsif ( m/^--Prod/ ) {
1449
            @type = 'P';
1450
        } elsif ( m/^--Debug/ ) {
1451
            @type = 'D';
1452
        }
1453
    }
1454
 
1455
    #
1456
    #   Create a list of products
1457
    #   ie: PRODUCT_ARCH
1458
    #
1459
    my @products;
1460
    push @products, $product . '_' . $arch if ( $product );
1461
    push @products, $arch;
1462
 
1463
    #
1464
    #   Scan all packages for the specified debian package
1465
    #
1466
    foreach my $package_dir ( $opt_interfacedir )
1467
    {
1468
        foreach my $type ( @type )
1469
        {
1470
            foreach my $prd ( @products )
1471
            {
1472
                foreach my $joiner ( qw(/ .) )
1473
                {
1474
                    my $dir = "$package_dir/bin$joiner$prd$type";
1475
                    Verbose("LocateDebianFile: Search in $dir");
1476
                    next unless ( -d $dir );
1477
                    my @files = glob ( "$dir/${base_name}_*.deb" );
1478
                    next unless ( @files );
1479
                    push @{$debian_file_path{$type}}, @files;
1480
                }
1481
            }
1482
        }
1483
    }
1484
 
1485
    Error ("Required Debain package not found: $base_name",) unless %debian_file_path;
1486
 
1487
    #
1488
    #   Select 'preferred' type of file
1489
    #   If we are doing a debug build, then prefer debug package
1490
    #   If not available then use any available
1491
    #
1492
    my @debian_file_path = @{$debian_file_path{$opt_type}};
1493
    if ( ! @debian_file_path )
1494
    {
1495
        foreach ( keys %debian_file_path )
1496
        {
1497
            push @debian_file_path,@{$debian_file_path{$_}};
1498
        }
1499
    }
1500
 
1501
    Error ("Multiple matching Debian Packages located", @debian_file_path)
1502
        if ( $#debian_file_path > 0 );
1503
 
1504
    return $debian_file_path[0];
1505
}
1506
 
1507
#-------------------------------------------------------------------------------
1508
# Function        : CalcRelPath
1509
#
1510
# Description     : Return the relative path to the current working directory
1511
#                   as provided in $Cwd
1512
#
1513
# Inputs          : $Cwd - Base dir
1514
#                   $base - Path to convert
1515
#
1516
# Returns         : Relative path from the $Cwd
1517
#
1518
sub CalcRelPath
1519
{
1520
    my ($Cwd, $base) = @_;
1521
 
1522
    my @base = split ('/', $base );
1523
    my @here = split ('/', $Cwd );
1524
    my $result;
1525
 
1526
    Debug("CalcRelPath: Source: $base");
1527
 
1528
    return $base unless ( $base =~ m~^/~ );
1529
 
1530
    #
1531
    #   Remove common bits from the head of both lists
1532
    #
1533
    while ( $#base >= 0 && $#here >= 0 && $base[0] eq $here[0] )
1534
    {
1535
        shift @base;
1536
        shift @here;
1537
    }
1538
 
1539
    #
1540
    #   Need to go up some directories from here and then down into base
1541
    #
1542
    $result = '../' x ($#here + 1);
1543
    $result .= join ( '/', @base);
1544
    $result = '.' unless ( $result );
1545
    $result =~ s~//~/~g;
1546
    $result =~ s~/$~~;
1547
 
1548
    Debug("CalcRelPath: Result: $result");
1549
    return $result;
1550
}
1551
 
1552
#-------------------------------------------------------------------------------
1553
# Function        : GetBuildParts
1554
#
1555
# Description     : Determine the 'parts' of the build for the current platform
1556
#                   This is complex information. It is held within the build.cfg
1557
#                   file.
1558
#
1559
# Inputs          : $interface_dir          - Path to the interface dir
1560
#                   $platform               - Platform to process
1561
#
1562
# Returns         : An array of platform parts
1563
#
1564
 
1565
#
1566
#   The following varaibles are "read" in from the build.cfg file
1567
#   In order to access them we need to declare them
1568
#
1569
our %ScmBuildPkgRules;
1570
our %BUILDPLATFORM_PARTS;
1571
 
1572
sub GetBuildParts
1573
{
1574
    my ($interface_dir, $platform) = @_;
1575
 
1576
    #
1577
    #   Tthe build.cfg file is within the interface directory
1578
    #
1579
    my $cfgfile = "$interface_dir/build.cfg";
1580
    Error ("Cannot find file: $cfgfile" ) unless ( -f $cfgfile );
1581
 
1582
    #
1583
    #   Include the build.cfg data
1584
    #
1585
    require ( $cfgfile );
1586
 
1587
    #
1588
    #   Extract the platform parts
1589
    #
1590
    if ( exists  $BUILDPLATFORM_PARTS{$platform})
1591
    {
1592
        return @{$BUILDPLATFORM_PARTS{$platform}};
1593
    }
1594
    else
1595
    {
1596
        Error ("Platform not found in build.cfg: $platform");
1597
    }
1598
}
1599
 
1600
#-------------------------------------------------------------------------------
1601
# Function        : FindFiles
1602
#
1603
# Description     : Locate files within a given dir tree
1604
#
1605
# Inputs          : $root           - Base of the search
1606
#                   $match          - Re to match
1607
#
1608
# Returns         : A list of files that match
1609
#
1610
my @FIND_LIST;
1611
my $FIND_NAME;
1612
 
1613
sub FindFiles
1614
{
1615
    my ($root, $match ) = @_;
1616
    Verbose2("FindFiles: Root: $root, Match: $match");
1617
 
1618
    #
1619
    #   Becareful of closure, Must use globals
1620
    #
1621
    @FIND_LIST = ();
1622
    $FIND_NAME = $match;
1623
    File::Find::find( \&find_files, $root);
1624
 
1625
    #
1626
    #   Find callback program
1627
    #
1628
    sub find_files
1629
    {
1630
        my $item =  $File::Find::name;
1631
        return if ( -d $_ );
1632
        return unless ( $_ =~ m~$FIND_NAME~ );
1633
        push @FIND_LIST, $item;
1634
    }
1635
    return @FIND_LIST;
1636
}
1637
 
1638
 
1639