Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
227 dpurdie 1
########################################################################
2
# Copyright ( C ) 2004 ERG Limited, All rights reserved
3
#
4
# Module name   : MugFiles.pl
5
# Module type   : JATS Build System
6
# Compiler(s)   : n/a
7
# Environment(s): jats
8
#
9
# Description   : This is a  JATS toolset extension package
10
#                 The package will add seeral directives to allow the
11
#                 creation of MUG files.
12
#
249 dpurdie 13
#                 The package is platform independant.
227 dpurdie 14
#
249 dpurdie 15
#                 Full details on the Mug File Generation process and the use of
16
#                 the functions provided by this extension are in:
17
#                       MASS-00099 Generating MUG files with JATS
227 dpurdie 18
#
19
#......................................................................#
20
 
21
use strict;
22
use warnings;
23
use File::Basename;
275 dpurdie 24
use JatsCopy;
227 dpurdie 25
 
26
#
27
#   Global data
28
#
247 dpurdie 29
my %Tiers;                              # Hash of Tiers already seen
30
my @ThxOnly;                            # Array of ThxOnly entries
227 dpurdie 31
my $verbose = 0;
32
 
33
MugInit();
34
 
35
#-------------------------------------------------------------------------------
36
# Function        : MugInit
37
#
38
# Description     : Module initialisation
39
#                   This function is run automaticlly when the package is loaded
40
#
41
# Inputs          :
42
#
43
# Returns         :
44
#
45
sub MugInit
46
{
247 dpurdie 47
}
48
 
49
#-------------------------------------------------------------------------------
50
# Function        : MugUtilities
51
#
52
# Description     : Ensure that required utilities can be located
53
#                   Only needs to be called if MugFiles are being created
54
#
55
# Inputs          : None
56
#
57
# Returns         : Will exit on error
58
#
59
sub MugUtilities
60
{
227 dpurdie 61
    #
62
    #   Ensure that required utilities can be located
63
    #
64
    my @not_found;
65
    foreach my $util ( qw(genappa.exe modcrc.exe) )
66
    {
67
        unless ( my $path = ToolExtensionProgram( $util ) )
68
        {
69
            push @not_found, $util;
70
        }
71
    }
72
 
73
    Error ("MugFiles: Required utility programs not found:", @not_found )
74
        if ( @not_found );
75
}
76
 
247 dpurdie 77
 
227 dpurdie 78
#-------------------------------------------------------------------------------
79
# Function        : MugFiles
80
#
81
# Description     : Collect MugFile information
82
#                   information
83
#
84
# Inputs          : $1  - platform(s)
85
#                   $*  - an argument list
86
#
87
# Returns         :
88
#
89
 
90
sub MugFiles
91
{
92
    my( $platforms, @elements ) = @_;
93
    my (%muginfo);
94
    my $tier;
95
 
96
    #
97
    #   Is this platform currently active
98
    #
99
    return if ( ! ActivePlatform($platforms) );
100
    DebugPush("MugFiles");
101
 
102
    #
275 dpurdie 103
    #   Insert defaults
104
    #
105
    $muginfo{'ThxBase'} = 'thx';
106
    $muginfo{'SubDirList'} = [ 'thx' ];
107
 
108
    #
227 dpurdie 109
    #   Process directive arguments
110
    #
111
    for (@elements)
112
    {
113
        if ( m/^--DeviceId=(.*)/ ) {
114
            $muginfo{'Device'} = $1;
115
 
116
        } elsif ( m/^--Name=(.*)/ ) {
117
            $muginfo{'Name'} = $1;
118
 
119
        } elsif ( m/^--Tier=(.*)/ ) {
120
            $muginfo{'Tier'} = $1;
121
            $tier = $1;
122
 
275 dpurdie 123
        } elsif ( m/^--SubDirs=(.*)/ ) {
124
            my @list = split( ',', $1 );
125
            $muginfo{'SubDirList'} = \@list;
126
 
227 dpurdie 127
        } elsif ( m/^--Package=(.*)/ ) {
128
            my $package_name = $1;
275 dpurdie 129
            my $warn = 0;
130
            my @dirs = @{$muginfo{'SubDirList'}};
227 dpurdie 131
            if ( $package_name =~ m/(.*?),--Subdir=(.*)/ )
132
            {
133
                $package_name = $1;
134
                @dirs = split( ',', $2 );
275 dpurdie 135
                $warn = 1;
227 dpurdie 136
            }
137
 
275 dpurdie 138
            my $package = GetPackageEntry( $package_name );
139
            Error("MugFiles: Required Package cannot be located: $package_name") unless ( $package );
140
 
227 dpurdie 141
            foreach my $subdir ( @dirs )
142
            {
143
                my $dir = "$package->{'ROOT'}/$subdir";
144
                if ( -d $dir )
145
                {
146
                    UniquePush( \@{$muginfo{'Dirs'}}, $dir );
147
                }
148
                else
149
                {
150
                    Warning("Directory not found in package: $package_name, Subdir: $subdir")
275 dpurdie 151
                        if ( $warn );
227 dpurdie 152
                }
153
            }
154
            UniquePush( \@{$muginfo{'Dirs'}}, "$package->{'ROOT'}" );
155
 
156
        } elsif ( m/^--Dir=(.*)/ ) {
157
            my $dir = $1;
158
 
159
            Error("Directory not found: $dir") unless ( -d $dir );
160
            UniquePush( \@{$muginfo{'Dirs'}}, $dir );
161
 
162
        } elsif ( m/^--Load=(.*)/ ) {
163
            Error("Multiple Load files specified") if ( $muginfo{'Load'} );
164
            $muginfo{'Load'} = $1;
165
 
166
        } elsif ( m/^--Exclude=(.*)/ ) {
167
            foreach ( split( ',', lc($1)) )
168
            {
169
                $muginfo{'Exclude'}{$_} = 0;
170
            }
171
 
172
        } elsif ( m/^--ThxDir=(.*)/ ) {
173
            $muginfo{'ThxCopyDir'} = $1;
174
 
247 dpurdie 175
        } elsif ( m{^--NoMugFiles} || m{^--ThxOnly}  ) {
176
            $muginfo{'NoMug'} = 1;
177
 
275 dpurdie 178
        } elsif ( m/^--File=(.*)/ ) {
179
            UniquePush( \@{$muginfo{'RawFiles'}}, $1 );
180
 
181
        } elsif ( m/^--ThxBase=(.*)/ ) {
182
            $muginfo{'ThxBase'} = $1;
183
 
227 dpurdie 184
        } else {
185
            Error("Unknown option: $_ ");
186
        }
187
    }
188
 
189
    #
190
    #   Ensure the user has provided all the parameters
191
    #
247 dpurdie 192
    unless ( $muginfo{'NoMug'} )
193
    {
194
        Error("No Device specified") unless ( $muginfo{'Device'} );
195
        Error("No Name specified") unless ( $muginfo{'Name'} );
196
        Error("No Tierspecified") unless ( $muginfo{'Tier'} );
197
        Error("Duplicated Tier: $tier") if ( exists $Tiers{$tier} );
198
 
199
        #
200
        #   Process Name
201
        #   It MUST be 4 characters padded with '-'
202
        #
203
        my $name = $muginfo{'Name'};
204
        Error( "Name too long. Must be less that 4: $name") if ( length($name) > 4 );
205
        $name .= '----';
206
        $name = substr($name,0,4);
207
        $muginfo{'Name'} = $name;
208
        $Tiers{$tier} = \%muginfo;
209
    }
210
    else
211
    {
212
        push @ThxOnly, \%muginfo;
213
    }
227 dpurdie 214
    Error("No Packages or directories specified") unless ( $muginfo{'Dirs'} );
215
 
216
    DebugPop();
217
}
218
 
219
#-------------------------------------------------------------------------------
275 dpurdie 220
# Function        : ThxFiles
221
#
222
# Description     : Simple wrapper to create a set of THX files
223
#                   without mug files
224
#
225
# Inputs          : Same as for MugFiles
226
#
227
# Returns         : Same as for MugFiles
228
#
229
sub ThxFiles
230
{
231
    MugFiles     ( @_, '--NoMugFiles' );
232
}
233
 
234
#-------------------------------------------------------------------------------
227 dpurdie 235
# Function        : MugGenerate
236
#
237
# Description     : Process all the collected data and generate MUG files
238
#
239
#                   Create a genappa.ini file as required for genappa.exe
240
#                   Create load.cmd files as required for genappa.exe
241
#
242
# Inputs          : None
243
#
244
# Returns         : Even less
245
#
246
 
247
sub MugGenerate
248
{
249
    my (@args) = @_;
247 dpurdie 250
    my @versions;
251
    my $version_hex;
252
    my $version_decimal;
253
 
227 dpurdie 254
    foreach ( @args )
255
    {
256
        if ( /^--Debug$/ ) {
257
            $verbose++;
258
 
259
        } elsif ( /^--Debug=(\d+)/ ) {
260
            $verbose = $1;
261
 
262
        } else {
263
            Warning("MugFiles: Unknown option: $_");
264
        }
265
    }
266
 
267
    #
268
    #   Set new Debug header and level
269
    #   These will be popped later
270
    #
271
    $verbose = DebugPush("MugGenerate", $verbose);
272
    Debug("Mugfiles: Set Verbosity: $verbose");
273
 
275 dpurdie 274
    #
275
    #   Enable copy operation logging
276
    #
277
    SetCopyDirDefaults ('Log' => $verbose );
278
 
247 dpurdie 279
    if ( keys %Tiers )
280
    {
281
        #
282
        #   Ensure that utilities are available
283
        #
284
        MugUtilities();
285
 
286
        #
287
        #   Determine the system version
288
        #   This is based on the Build Version ( XX.YY.ZZ )
289
        #   This is massaged into the required system version, which is required
290
        #   in two forms:
291
        #       1) As hex XX.YY
292
        #       2) As the decimal version of 1)
293
        #
294
        #   The version is held in two bytes so it is limited
295
        #
296
        @versions = split( /\./, $::ScmBuildVersion );
297
        Error ("MugFiles: Cannot encode versions with a patch number: $::ScmBuildVersion",
298
                "Major: $versions[0]",
299
                "Minor: $versions[1]",
300
                "Patch: $versions[2]")
301
            if ( $versions[2] > 0 ) ;
227 dpurdie 302
 
247 dpurdie 303
        $version_hex = $versions[0] * 100 + $versions[1];
304
        $version_decimal = hex $version_hex;
305
        Debug ("MugSet version: $version_decimal, HEX:$version_hex");
306
    }
227 dpurdie 307
 
308
    #
309
    #   Create the list of THX files to be used for each device
310
    #   These files are calculated by:
311
    #       Merging all the THX files in the specified packages
312
    #       Excluding the specified files
313
    #
247 dpurdie 314
    foreach my $mugref ( values(%Tiers), @ThxOnly )
227 dpurdie 315
    {
316
 
317
        #
318
        #   If the user has specified a load file, then use it to provide
319
        #   the complete list of files to load
320
        #
321
        if ( $mugref->{'Load'} )
322
        {
323
            ReadLoadFile( $mugref, LocateLoadFile( $mugref, $mugref->{'Load'} ));
324
        }
325
 
326
        my %files_found;
327
        my @ffiles;
328
        foreach my $dir ( @{$mugref->{'Dirs'}} )
329
        {
330
            #
331
            #   Locate the THX files within the package ( directory )
332
            #   Exclude any user specified files
333
            #
334
            my @files = glob( "$dir/*.thx" );
335
            Debug("Searching for THX files in directory: $dir");
336
            foreach  ( @files )
337
            {
338
                my $base = lc(basename($_));
339
 
340
                #
341
                #   Include only loaded files
342
                #
343
                if ( exists $mugref->{'LoadList'} )
344
                {
345
                    next unless( exists $mugref->{'LoadList'}{$base} );
346
                    $mugref->{'LoadList'}{$base}++;
347
                }
348
 
349
                #
350
                #   Skip excluded files
351
                #
352
                if ( exists $mugref->{'Exclude'}{$base} )
353
                {
354
                    $mugref->{'Exclude'}{$base}++;
355
                    Debug2 ("   Excluding: $base");
356
                    next;
357
                }
358
 
359
                #
360
                #   Test for duplicated files
361
                #
362
                if ( exists($files_found{$base}) )
363
                {
364
                    Warning("Multiple instances a file ignored: $base",
365
                            "Using file: $files_found{$base}",
366
                            "Ignoring  : $_");
367
                    next;
368
                }
369
                $files_found{$base} = $_;
370
 
371
                push @ffiles, $_;
372
                Debug2 ("   File: $_");
373
 
374
            }
375
        }
376
        $mugref->{'Files'} = \@ffiles;
377
 
378
        #
379
        #   If using a Load file then reprocess the complete file list
380
        #   to retain only those
381
 
382
 
383
        #
384
        #   Report excluded files that were not excluded
385
        #
386
        foreach ( keys %{$mugref->{'Exclude'}} )
387
        {
388
            next if ( $mugref->{'Exclude'}{$_} );
389
            Warning ("Excluded THX file not encountered: $_" );
390
        }
391
 
392
        #
393
        #   Report loaded files that are not located
394
        #
395
        my @not_nice;
396
        foreach ( keys %{$mugref->{'LoadList'}} )
397
        {
398
            next if ( $mugref->{'LoadList'}{$_} );
399
            push @not_nice, $_;
400
        }
401
        Error ("Incomplete THX file set. Missing files", @not_nice)
402
            if ( $#not_nice >= 0 );
403
 
404
 
405
        #
406
        #   Generate the loadfull.ini file
407
        #   This file simply contains the full path names to all THXs
408
        #   Unique INI files will be created in the "interface" directory
409
        #
247 dpurdie 410
        unless ( $mugref->{'NoMug'} )
411
        {
412
            my $loadname = "$::ScmRoot/$::ScmInterface/load_$mugref->{'Tier'}.ini";
413
            $mugref->{'IniName'} = $loadname;
227 dpurdie 414
 
247 dpurdie 415
            Debug("Generating loadfile: $loadname" );
416
            open (INI, ">$loadname" ) || Error ("Cannot create: $loadname" );
417
            foreach ( @{$mugref->{'Files'}} )
418
            {
419
                (my $dos_path = $_) =~ s~/~\\~g;
420
                print INI "e=o:$dos_path\n";
421
            }
422
            close INI;
227 dpurdie 423
        }
424
 
275 dpurdie 425
        #
426
        #   Expand the list namewd files
427
        #   Search the packages for the files.
428
        #
429
        if ( $mugref->{'RawFiles'} )
430
        {
431
            my %files_found;
432
            my @ffiles;
433
            foreach my $dir ( @{$mugref->{'Dirs'}} )
434
            {
435
                Debug("Searching for specified files in directory: $dir");
436
                foreach  ( @{$mugref->{'RawFiles'}} )
437
                {
438
                    my $full_path = "$dir/$_";
439
                    next unless ( -f $full_path );
227 dpurdie 440
 
275 dpurdie 441
                    my $base = lc(basename($_));
442
 
443
                    #
444
                    #   Test for duplicated files
445
                    #
446
                    if ( exists($files_found{$base}) )
447
                    {
448
                        Warning("Multiple instances a file ignored: $base",
449
                                "Using file: $files_found{$base}",
450
                                "Ignoring  : $_");
451
                        next;
452
                    }
453
                    $files_found{$base} = $full_path;
454
                    push @ffiles, $full_path;
455
                    Debug2 ("   File: $_");
456
 
457
                }
458
            }
459
 
460
            #
461
            #   Test for missing files
462
            #
463
            my @missing;
464
            foreach  ( @{$mugref->{'RawFiles'}} )
465
            {
466
                unless ( exists ($files_found{ lc($_)})  )
467
                {
468
                    push @missing, $_;
469
                }
470
            }
471
            Error ("The following named files could not be found", @missing )
472
                if ( @missing );
473
 
474
            $mugref->{'RawFiles'} = \@ffiles;
475
        }
476
 
227 dpurdie 477
        #
478
        #   Transfer THX files into the package
479
        #
480
        if ( $mugref->{'ThxCopyDir'} )
481
        {
275 dpurdie 482
            my $thxdir = "$::ScmRoot/pkg/$::ScmBuildPackage/$mugref->{'ThxBase'}/$mugref->{'ThxCopyDir'}";
227 dpurdie 483
            $thxdir =~ s/-$//g;
275 dpurdie 484
            $thxdir =~ s~//~/~g;
485
            $thxdir =~ s~/\./~/~g;
227 dpurdie 486
            Debug("THX files will be placed in: $thxdir" );
275 dpurdie 487
 
488
            CreateDir ( $thxdir );
489
            CopyFile ($mugref->{'Files'}        ,$thxdir );
490
            CopyFile ($mugref->{'LoadFiles'}    ,$thxdir );
491
            CopyFile ($mugref->{'RawFiles'}     ,$thxdir );
227 dpurdie 492
        }
493
 
494
        DebugDumpData("Processed Mug", $mugref)
495
            if $verbose > 2;
496
    }
497
 
247 dpurdie 498
    if ( keys %Tiers )
499
    {
500
        #
501
        #   Create the master genappi.ini file
502
        #   This file will be created in the interface directory
503
        #
504
        my $genappa = "$::ScmRoot/$::ScmInterface/genappa.ini";
505
        Debug("Generating genappa control file: $genappa" );
506
        open (INI, ">$genappa" ) || Error ("Cannot create: $genappa" );
227 dpurdie 507
 
247 dpurdie 508
        #
509
        #   Insert the header
510
        #
511
        print INI "[Header]\n";
512
        print INI "SystemVer                = ",$version_hex, "\n";
513
        print INI "NumDevTypes              = ", scalar keys %Tiers, "\n";
514
        print INI "\n";
227 dpurdie 515
 
247 dpurdie 516
        #
517
        #   Insert per device information
518
        #   This is performed in reverse Tier order
519
        #
520
        my $device_number = 0;
521
        foreach my $tier ( reverse sort keys %Tiers )
522
        {
523
            $device_number++;
524
            my $mugref = $Tiers{$tier};
227 dpurdie 525
 
247 dpurdie 526
            print INI "[DeviceType$device_number]\n";
527
            print INI "Name                     = ", $mugref->{'Name'}, "\n";
528
            print INI "Id                       = ", $mugref->{'Device'}, "\n";
529
            print INI "Ver                      = ", $version_decimal, "\n";
530
            print INI "Tier                     = ", $mugref->{'Tier'}, "\n";
531
            print INI "ModulesPath              = ", $mugref->{'IniName'}, "\n";
532
            print INI "ScanMemBackupSuper       = N\n";
533
            print INI "ScanMemBackupUserSuper   = N\n";
534
            print INI "ScanMemFlashSuper        = Y\n";
535
            print INI "ScanMemFlashUserSuper    = Y\n";
536
            print INI "\n";
537
        }
538
 
539
        #
540
        #   Insert options
541
        #
542
        print INI "[Options]\n";
543
        print INI "SuppressCDHeader         = TRUE\n";
227 dpurdie 544
        print INI "\n";
545
 
546
 
247 dpurdie 547
        close INI;
227 dpurdie 548
 
247 dpurdie 549
        #
550
        #   Run the GENAPPA utility
551
        #   This will create a directory full of MUG files
552
        #   Generate the files directly into the pkg subdirectory
553
        #
554
        my $mugdir = "$::ScmRoot/pkg/$::ScmBuildPackage/mug";
555
        Debug("Mugfiles will be placed in: $mugdir" );
275 dpurdie 556
        CreateDir( $mugdir , 'DeleteFirst' => 1);
227 dpurdie 557
 
247 dpurdie 558
        #
559
        #   Extend the PATH to include the toolset extensions
560
        #   to allow use to find genappa and modcrc
561
        #
562
        my $PATH = join ';', ToolExtensionPaths(), $ENV{'PATH'};
563
        $ENV{'PATH'} = $PATH;
227 dpurdie 564
 
247 dpurdie 565
        my $opts = ($verbose > 1) ? " -d" : "";
566
        Debug( "Running GENAPPA");
567
        System( "genappa $genappa$opts -o $mugdir" ) && Error( "Problem running genappa" );
568
    }
227 dpurdie 569
 
570
    #
571
    #   Cleanup the debugging interface
572
    #
573
    DebugPop();
574
}
575
 
576
#-------------------------------------------------------------------------------
577
# Function        : LocateLoadFile
578
#
579
# Description     : Locate a specified loadfile
580
#
581
# Inputs          : $mugref         - Per device Data store
582
#                   $cmdfile        - The full path to the load file
583
#
584
# Returns         : Path to the load file
585
#                   Will not return on error
586
#
587
sub LocateLoadFile
588
{
589
    my( $mugref, $cmdfile) = @_;
590
    my @load_list;
591
    #
592
    #   Has the load file been sourced
593
    #
594
    Debug ("   Locate command file: $cmdfile");
595
    push @load_list, $::SRCS{$cmdfile}
596
        if ( exists $::SRCS{$cmdfile} && -f $::SRCS{$cmdfile} );
597
 
598
    #
599
    #   The load file must exist in one of the packages or directories
600
    #   Locate the file and warn if multiple files are found
601
    #
602
    foreach my $dir ( @{$mugref->{'Dirs'}} )
603
    {
604
        my $path = "$dir/$cmdfile";
605
        Debug2 ("   Locate command file. Try: $path");
606
        push @load_list, $path if ( -f $path );
607
    }
608
 
609
    Error ("Load file not found in any package or directory: $cmdfile")
610
        unless ( $#load_list >= 0 );
611
 
612
    Warning ("Multiple load files found. The first one will be used",
613
             @load_list ) if( $#load_list > 0) ;
614
 
615
    #
616
    #   Return the full path to the first loadfile located
617
    #
618
    return $load_list[0];
619
}
620
 
621
#-------------------------------------------------------------------------------
622
# Function        : ReadLoadFile
623
#
624
# Description     : Read and Process a load.cmd file
625
#                   This file will provide the complete list of files to be
626
#                   mugged
627
#
628
# Inputs          : $mugref         - Per device Data store
629
#                   $cmdfile        - The full path to the load file
630
#
631
# Returns         :
632
#
633
sub ReadLoadFile
634
{
635
    my( $mugref, @cmdfile) = @_;
636
    my %filelist;
637
    my %seen;
638
 
639
    while ( @cmdfile )
640
    {
641
        my $cmdfile = pop( @cmdfile );
642
        $cmdfile =~ tr~\\/~/~s;
643
        $seen{$cmdfile} = 1;
644
        push @{$mugref->{'LoadFiles'}}, $cmdfile;
645
 
646
        Debug ("Reading load file: $cmdfile");
647
 
648
        #
649
        #   Process the cmdfile and extract the names of files to transfer
650
        #   Extract data of the form
651
        #       e=o:pathname
652
        #       f=pathname
653
        #
654
        open (CMD, "<$cmdfile") || Error ("Cannot open command file: $cmdfile" );
655
        while ( <CMD> )
656
        {
657
            #
658
            #   Clean up whitespace and comments
659
            #
660
            chomp;
661
            s~^\s*~~;
662
            s~\*.*$~~;
663
            s~\s*$~~;
664
            next if ( length( $_) <= 0 );
665
 
666
            #
667
            #   Clean pathnames
668
            #
669
            tr~\\/~/~s;
670
 
671
            if ( m/e=o:(.*)/ )
672
            {
673
                    #
674
                    #   Ignore any path information
675
                    #       - Its not valid within the context of the package
676
                    #   Process excluded files
677
                    #
678
                    my $file = lc StripDir($1);
679
                    if ( exists $mugref->{'Exclude'}{$file} )
680
                    {
681
                        $mugref->{'Exclude'}{$file}++;
682
                        Debug2 ("   Excluding: $file");
683
                    }
684
                    else
685
                    {
686
                        Debug2 ("   Entry: $file");
687
                        $filelist{$file} = 0;
688
                    }
689
 
690
            } elsif ( m/f=(.*)/ )
691
            {
692
                my $file = lc StripDir($1);
693
                Debug2 ("   Included load file: $file");
694
 
695
                $file = LocateLoadFile($mugref, $file );
696
 
697
                Error ("Load file already processed: $file")
698
                    if ( exists $seen{ $file } );
699
 
700
                unshift @cmdfile, $file;
701
                $seen{$file} = 1;
702
            }
703
        }
704
        close( CMD );
705
    }
706
 
707
    $mugref->{'LoadList'} = \%filelist;
708
 
709
}
710
 
711
1;