Subversion Repositories DevTools

Rev

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