Subversion Repositories DevTools

Rev

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