NFBPack3rdROM.pl 10.3 KB
#!/usr/bin/perl -W
#
#  Copyright Statement:
#  --------------------
#  This software is protected by Copyright and the information contained
#  herein is confidential. The software may not be copied and the information
#  contained herein may not be used or disclosed except with the written
#  permission of MediaTek Inc. (C) 2005
#
#  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
#  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
#  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
#  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
#  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
#  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
#  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
#  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
#  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
#  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
#
#  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
#  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
#  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
#  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
#  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
#
#  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
#  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
#  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
#  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
#  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
#
#
#*****************************************************************************

#use strict;
use Fcntl;

if ($#ARGV != 1) { &Usage; }
#die "Please use 5.8.6 or later Perl interpreter\n" if $] < 5.008005;

#
# NP3R - 0 : (under construction) pre-processing & info gathering from makefile
#
$prefix_path = $ARGV[0];
$themf = $ARGV[1];

die "$themf did NOT exist!\n" if (!-e $themf);
open (FILE_HANDLE, "<$themf") or die "cannot open $themf\n";
while (<FILE_HANDLE>) {
  if (/^(\S+)\s*=\s*(\S+)/) {
    $keyname = lc($1);
    defined($${keyname}) && warn "$1 redefined in $themf!\n";
    $${keyname} = uc($2);
  }
}
close (FILE_HANDLE);

#
# NP3R - 1 : determine if _NAND_FLASH_BOOTING_ defined
#

if (not defined $nand_flash_booting)
{
    exit(0);
}

if ($nand_flash_booting ne "ENFB" and $nand_flash_booting ne "MIXED")
{
    exit(0);
}
#
# NP3R - 2 : Global Configuration section
#
my $EnfbOutputfile = "THIRD_ROM";
my %EnfbInputFiles = (
"ENFBMMIResB" => "plutommi\\Customer\\CustResource\\CustMMI3rdROM",
"CustENFBThm" => "plutommi\\Customer\\ResGenerator\\ThemeXML\\Temp\\CustEnfbVenusThemeData",
"CustENFBIcn" => "plutommi\\Customer\\ResGenerator\\ThemeXML\\Temp\\CustEnfbVenusAppIconData",
"IME_HW_DATA" => "plutommi\\Customer\\ResGenerator\\hw_data.gbd",
"CustENFBFnt" => "plutommi\\Customer\\CustResource\\CustENFBFontData",
);

my @MREInputFileContentArray = split "\n",`type "plutommi\\Customer\\CustResource\\NFBpack3rdromCust.txt"`;
foreach my $line (@MREInputFileContentArray)
{
	if($line =~ /"(.*)"=>"(.*)"/)
	{
		$EnfbInputFiles{$1} = $2;
	}
}

foreach my $k (keys %EnfbInputFiles){printf "$k=>$EnfbInputFiles{$k}\n";}

my $EnfbReservedHearderSize = 3240;
my $EnfbAlignToSize         =  64;
my $sv5_offset              =  0;
#
# NP3R - 3 : read the pre-defined 3rd ROM header content
#
my %EnfbInputKeys;  # Key ==> id
my %EnfbInputBegin; # Key ==> begin
my %EnfbInputEnd;   # Key ==> end
my %EnfbBinFiles;   # Key ==> external bin file length
my $buffer;
$EnfbOutputfile = $prefix_path . $EnfbOutputfile;

sysopen( HANDLE, $EnfbOutputfile, O_RDWR ) or die $!;
binmode(HANDLE);

#SV5 binary has "MMM" tag in its first 3 bytes
sysread(HANDLE, $buffer, 3);

if($buffer eq 'MMM')
{
   $sv5_offset = 56;
   print "SV5 detected\n";
}

sysseek(HANDLE, $sv5_offset, 0);

while ( sysread(HANDLE, $buffer, 32) )
{
#   my (@ID, $cid, $begin, $length, @Desc) = unpack "C11CVVC12", $buffer;
   my @buf = unpack "C11CVVC11", $buffer;
   my $cid = $buf[11];
   my $begin = $buf[12];
   my $length = $buf[13];
   my $key = pack "C11", splice(@buf, 14, 11);
   my $idstring = pack "C7", splice(@buf, 0, 7);
   #printf "ID = %x , \t %s \t %x \t %x \n", $cid, $key, $begin, $length;
   if ($cid eq 0xff)
   {
       &AdjustDynamicCodeBeginEnd($begin);
       last;
   }
   if (defined $EnfbInputFiles{$key}) # external binary file ...
   {
       $EnfbInputKeys{$key}  = $cid;
       next;
   }
   if ($length > 0                  ) # dynamic code linked ...
   {
       $EnfbInputKeys{$key}  = $cid;
       $EnfbInputBegin{$key} = $begin;
       $EnfbInputEnd{$key}   = $begin + $length - 1;
   }
   last unless ($idstring eq "ENFB3RD");
}
#
# NP3R - 4 : testing existing of external members in the 3rd rom
#
&ChkAllExternalBehindDynamicCode();
foreach (keys %EnfbInputKeys)
{
    next if not defined $EnfbInputFiles{$_};
    my $f = $EnfbInputFiles{$_};
    if (-e $f)
    {
        $EnfbBinFiles{$_} = (stat $f )[7];
    }
    else
    {
        print "External Binary File $_ ==> $f not found\n";
        delete $EnfbInputKeys{$_};
    }
}
#
# NP3R - 5 : correct 3RD ROM header , synthetize external content to 3RD ROM
#
&SetupExternalBinOffset();
&DumpInternal3rdRomHeader();
my $read_pos = sysseek(HANDLE, 0, 1); # SEEK_CUR 
my @SortedKeyList = sort { $EnfbInputKeys{$a} <=> $EnfbInputKeys{$b} } keys %EnfbInputKeys;
sysseek(HANDLE, $sv5_offset, 0);

foreach my $h (@SortedKeyList)
{
   $buffer = &Pack_enfb_header( $EnfbInputKeys{$h},
                                $EnfbInputBegin{$h},
                                $EnfbInputEnd{$h},
                                $h);
   syswrite(HANDLE, $buffer, 32);
}
$buffer = &Pack_enfb_header( 0xff, 0, 0, "ENDMARK");
syswrite(HANDLE, $buffer, 32);
   # Zero Padding ---
my $write_pos = sysseek(HANDLE, 0, 1); # SEEK_CUR 
#print "Read position : $read_pos\n";
#print "Write position : $write_pos\n";
if ($read_pos > $write_pos)
{
   $buffer = chr(0) x ($read_pos - $write_pos);
   syswrite(HANDLE, $buffer, $read_pos - $write_pos);
}
   # External Binary Append
my $cur_pos;
#$cur_pos = sysseek(HANDLE, 0, 2); # SEEK_END
#print "Current position : $cur_pos\n";
foreach my $h (@SortedKeyList)
{
    next if not defined $EnfbBinFiles{$h};
    # Padding To
    $cur_pos = sysseek(HANDLE, 0, 2); # SEEK_END
    if ($EnfbInputBegin{$h} > $cur_pos)
    {
       $buffer = chr(0) x ($EnfbInputBegin{$h} - $cur_pos);
       syswrite(HANDLE, $buffer, ($EnfbInputBegin{$h} - $cur_pos));
    }
    # Append To
    sysopen(EXTBIN, $EnfbInputFiles{$h} , O_RDONLY) or die $!;
    binmode(EXTBIN);
    my $read_len = sysread(EXTBIN, $buffer, 8192);
    while ($read_len)
    {
       syswrite(HANDLE, $buffer, $read_len);
       $read_len = sysread(EXTBIN, $buffer, 8192);
    }
    close(EXTBIN);
}
$cur_pos = sysseek(HANDLE, 0, 2); # SEEK_END
print "Tail position : $cur_pos\n";
if($cur_pos % 2 == 1)
{
	syswrite(HANDLE,"0",1);
	$cur_pos = sysseek(HANDLE, 0, 2);
	print "Tail position after padding : $cur_pos\n";
}

close (HANDLE);
exit(0);
#
# NP3R ------ End of MAIN BODY ----------- 
#

sub Align
{
   my ($size, $orig) = @_;

   return $size * (int($orig/$size) + 1);
}

sub Pack_enfb_header
{
   my ($cid, $begin, $end, $description ) = @_;
   my $ID = "ENFB3RDROM!";
   my @ID = unpack "C*", $ID;
   my $buf;
   my @Desc  = unpack "C*", $description;

   $buf = pack "C11CVVC12", @ID, $cid, $begin, $end, @Desc ;
   return $buf;
}

#
# NP3R ------ Shift the being & end ------
#
sub AdjustDynamicCodeBeginEnd
{
    my ($base)  = @_;
    foreach my $k (keys %EnfbInputKeys)
    {
        next unless defined $EnfbInputBegin{$k};
        $EnfbInputBegin{$k} -= $base;
        $EnfbInputEnd{$k}   -= $base;
    }
}

#
# NP3R ------ Debug use ------
#
sub DumpInternal3rdRomHeader
{
    foreach my $k (sort { $EnfbInputKeys{$a} <=> $EnfbInputKeys{$b} } keys %EnfbInputKeys)
    {
        if (defined $EnfbBinFiles{$k})  # external binary files
        {
           print $k, "\t", $EnfbInputKeys{$k}, "\t", $EnfbInputBegin{$k}, "\t", $EnfbInputEnd{$k}, "\t";
           print "External BIN files\t size : ", $EnfbBinFiles{$k} , "\n";
        }
        else   # linked dynamic code on NAND flash
        {
           print $k, "\t", $EnfbInputKeys{$k}, "\t", $EnfbInputBegin{$k}, "\t", $EnfbInputEnd{$k}, "\n";
        }
    }
}

#
# NP3R ------ check if external bin cid larger than internal code cid ------
#
sub ChkAllExternalBehindDynamicCode
{
    my @codelist = keys %EnfbInputEnd;
    #print "CODE LIST at Chk: $#codelist \n";
    #map { print "CODE: ", $_, "\n"; } @codelist;
    return if ($#codelist == -1);
    my @SortedKeyList = sort { $EnfbInputKeys{$a} <=> $EnfbInputKeys{$b} } keys %EnfbInputKeys;
    my @SortedCodeList = sort { $EnfbInputKeys{$a} <=> $EnfbInputKeys{$b} } @codelist;
    my $lastidx = $#codelist;
    die "External BIN cid must behind code cid" 
    unless ($SortedCodeList[$lastidx] eq $SortedKeyList[$lastidx]);
}

#
# NP3R ------ check if external bin cid larger than internal code cid ------
#
sub SetupExternalBinOffset
{
    my @codelist = keys %EnfbInputEnd;
    #print "CODE LIST at Setup: $#codelist \n";
    #map { print "CODE: ", $_, "\n"; } @codelist;
    my $ExtBinBegin;
    if ($#codelist == -1)
    {
       $ExtBinBegin = $EnfbReservedHearderSize + $sv5_offset;
    }
    elsif ($#codelist == 0)
    {
       $ExtBinBegin = &Align( $EnfbAlignToSize, $EnfbInputEnd{ $codelist[-1] } );
    }
    else
    {
       my @SortedCodeList = sort { $EnfbInputKeys{$a} <=> $EnfbInputKeys{$b} } @codelist;
       #print "The Last one : ", $SortedCodeList[-1], "\n";
       $ExtBinBegin = &Align( $EnfbAlignToSize, $EnfbInputEnd{ $SortedCodeList[-1] } );
    }
    # okay , external bin setup begin and offset
    foreach my $ebin ( sort { $EnfbInputKeys{$a} <=> $EnfbInputKeys{$b} } keys %EnfbBinFiles)
    {
       $EnfbInputBegin{$ebin} = $ExtBinBegin;
       $EnfbInputEnd{$ebin}   = $ExtBinBegin + $EnfbBinFiles{$ebin} - 1;
       $ExtBinBegin  = &Align( $EnfbAlignToSize, $ExtBinBegin + $EnfbBinFiles{$ebin} );
    }
}

sub Usage {
   print "perl nfbpack3rdrom.pl <binary path> <Project MakeFile>\n";
}