#!/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 = ( | |
"CustENFBImg\0" => "plutommi\\Customer\\CustResource\\CustENFBImgData", | |
"CustENFBStr\0" => "plutommi\\Customer\\CustResource\\CustENFBStrData", | |
); | |
my $EnfbReservedHearderSize = 256; | |
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 "C11CVVC12", $buffer; | |
my $cid = $buf[11]; | |
my $begin = $buf[12]; | |
my $length = $buf[13]; | |
my $key = pack "C12", splice(@buf, 14, 12); | |
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"; | |
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"; | |
} | |