blob: 42d78eafad25b73b3c5ea8bacb64ce0089caafd5 [file] [log] [blame]
#!/usr/bin/perl
#
# 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).
#
#
#*****************************************************************************
#*
#* Filename:
#* ---------
#* link.pl
#*
#* Project:
#* --------
#*
#*
#* Description:
#* ------------
#* 1. This script will read link error and decide to enter two-phase linking
#* 2. If need, it will adjust ROM LENGTH.
#*
#*
#* Author:
#* -------
#* Frank Hu
#*
#*============================================================================
#* HISTORY
#* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
#*------------------------------------------------------------------------------
#*
#*------------------------------------------------------------------------------
#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
#*============================================================================
#****************************************************************************
use strict;
BEGIN { push @INC , './tools/', './tools/MemoryUtility/' } # add additional library path
use LinkerOutputParser;
use POSIX qw(floor ceil);
use FileInfoParser;
package Type;
use constant Log => 0;
use constant Warning => 1;
use constant Fatal => 2;
my ($LD, $LDS, $LinkLog, $LibTemp, $Makefile, $Mapfile) = @ARGV;
die "$LD does not exist!\n" unless(-e $LD);
system("$LD \@$LibTemp > $LinkLog 2>&1");
exit 0 if($? == 0);
&msg_handler(Type::Warning, "First link failed and check if it is UROM overflow.", __FILE__, __LINE__);
my %makefile_option;
&msg_handler(Type::Fatal, "Fail to open $LinkLog.", __FILE__, __LINE__) if(1 != &FileInfo::Parse_MAKEFILE($Makefile, \%makefile_option));
my ($bUROMOverflow, $ExceedSize, $address, $new_UROM_size) = (0, undef);
if (FileInfo::is("COMPILER_ISA", "NANOMIPS")) {
open LINK, "< $LinkLog" or &msg_handler(Type::Fatal, "Fail to open $LinkLog.", __FILE__, __LINE__);
my $last_ROM_section;
if (FileInfo::is("AMMS_DRDI_SUPPORT", "TRUE")) {
$last_ROM_section = "CACHED_EXTSRAM_MCURO_HWRW_DRDI_NR_63";
} else {
$last_ROM_section = "ROM_SIGNATURE_SECTION";
}
map { ($address, $bUROMOverflow) = ($1, 1) if(/^$LD: error: address (0x\w+) of section $last_ROM_section is not within region UROM/); } (<LINK>);
close LINK;
$new_UROM_size = hex($address) + Get_LastSection_Size($last_ROM_section);
} elsif (FileInfo::is("COMPILER_ISA", "MIPS16") or FileInfo::is("COMPILER_ISA", "MIPS32")) {
open LINK, "< $LinkLog" or &msg_handler(Type::Fatal, "Fail to open $LinkLog.", __FILE__, __LINE__);
map { ($ExceedSize, $bUROMOverflow) = ($1, 1) if(/^$LD: region `UROM' overflowed by (\d+) bytes/); } (<LINK>);
close LINK;
} else {
&msg_handler(Type::Fatal, "Mismatch COMPILER_ISA, please check in project makefile.", __FILE__, __LINE__);
}
if($bUROMOverflow == 1) {
&msg_handler(Type::Warning, "UROM overflow, Second-Link will be executed next.", __FILE__, __LINE__);
my $nUROMAdjustedLength;
my ($nUROMOrigin, $nUROMLength) = &GetUROMInfo();
if (FileInfo::is("COMPILER_ISA", "NANOMIPS")) {
$nUROMAdjustedLength = POSIX::ceil(($new_UROM_size) / (1024 * 1024)) * 1024 * 1024 ;
} elsif (FileInfo::is("COMPILER_ISA", "MIPS16") or FileInfo::is("COMPILER_ISA", "MIPS32")) {
$nUROMAdjustedLength = POSIX::ceil(($nUROMLength + $ExceedSize) / (1024 * 1024)) * 1024 * 1024 ;
} else {
&msg_handler(Type::Fatal, "Mismatch COMPILER_ISA, please check in project makefile.", __FILE__, __LINE__);
}
my $nUROMAdjustedStrLength = sprintf("0x%08x", $nUROMAdjustedLength);
my $RAM_AdjustedOrigin = POSIX::ceil(($nUROMOrigin + $nUROMAdjustedLength) / (1024 * 1024)) * 1024 * 1024;
my $RAM_AdjustedStrOrigin = sprintf("0x%08x", $RAM_AdjustedOrigin);
&UpdateLDS($nUROMAdjustedStrLength, $RAM_AdjustedStrOrigin);
my $Log = "\n";
$Log .= sprintf "|----------------Memory Space Adjustment-------------|\n";
$Log .= sprintf "+----------------------+--------------+--------------+\n";
$Log .= sprintf "+----------------------+--------------+--------------+\n";
$Log .= sprintf "+ Memory Space + Old Setting + New Setting +\n";
$Log .= sprintf "+----------------------+--------------+--------------+\n";
$Log .= (sprintf "| %20s | 0x%.8x | 0x%.8x |\n", "UROM/ROM (LENGTH)", $nUROMLength, $nUROMAdjustedLength);
$Log .= (sprintf "| %20s | 0x%.8x | 0x%.8x |\n", "RAM (ORIGIN)", $nUROMLength, $RAM_AdjustedOrigin);
$Log .= sprintf "+----------------------+--------------+--------------+\n";
&msg_handler(Type::Log, $Log, __FILE__, __LINE__);
#start the second link.
&msg_handler(Type::Warning, "======== Second Linking Process Start ========", __FILE__, __LINE__);
system("$LD \@$LibTemp > $LinkLog 2>&1");
if($? == 0) {
&msg_handler(Type::Warning, "======== Second Linking Process End ========", __FILE__, __LINE__);
exit 0;
}
else {
&msg_handler(Type::Fatal, "======== *** Second Linking Process fail, please check link.log. ========", __FILE__, __LINE__);
}
} else {
&msg_handler(Type::Fatal, "link fail, please check link.log.", __FILE__, __LINE__);
}
sub GetUROMInfo
{
my ($nOrigin, $nLength) = (undef, undef);
open LDS, "< $LDS" or &msg_handler(Type::Fatal, "Fail to open $LDS.", __FILE__, __LINE__);
map { ($nOrigin, $nLength) = (hex($1), hex($2)) if(/^\s+UROM\s*:\s*ORIGIN\s*=\s*(\S+)\s*,\s*LENGTH\s*=\s*(\S+)\s*$/); } (<LDS>);
close LDS;
&msg_handler(Type::Fatal, "UROM can't be found in $LDS", __FILE__, __LINE__) unless(defined $nOrigin and defined $nLength);
return ($nOrigin, $nLength);
}
sub UpdateLDS
{
my ($UROMLength, $RAMOrigin) = @_;
my ($Out, $bit) = (undef, 0);
open LDS, "< $LDS" or &msg_handler(Type::Fatal, "Fail to open $LDS.", __FILE__, __LINE__);
while(<LDS>) {
$bit ++ if(s/^\s+UROM\s*:\s*ORIGIN\s*=\s*0x00000000\s*,\s*LENGTH\s*=\s*\S+\s*$/ UROM : ORIGIN = 0x00000000, LENGTH = $UROMLength\n/ ||
s/^\s+RAM\s*:\s*ORIGIN\s*=\s*\S+\s*,\s*LENGTH\s*=\s*(\S+)\s*$/ RAM : ORIGIN = $RAMOrigin, LENGTH = $1\n/);
$Out .= $_;
}
&msg_handler(Type::Fatal, "UROM/RAM can't be found in $LDS.", __FILE__, __LINE__) if ($bit != 2);
close LDS;
open LDS, "> $LDS" or &msg_handler(Type::Fatal, "Fail to open $LDS.", __FILE__, __LINE__);
print LDS $Out;
close LDS;
}
sub Get_LastSection_Size
{
my ($last_section_name) = @_;
my ($flag, $VMA, $size) = (0, 0, 0);
open MAP, "< $Mapfile" or &msg_handler(Type::Fatal, "Fail to open $Mapfile.", __FILE__, __LINE__);
foreach my $line (<MAP>) {
$flag = 1 if ($line =~ /^$last_section_name$/);
last if ($flag == 2);
next if ($flag != 1);
if ($flag == 1 and $line =~ /^\s+(0x\w+)\s+(0x\w+)/) {
($VMA, $size) = (hex($1), hex($2));
$flag = 2;
}
}
&msg_handler(Type::Fatal, "Cannot find size of last ROM section($last_section_name) in $Mapfile.", __FILE__, __LINE__) if ($flag != 2);
close MAP;
return $size;
}
sub msg_handler
{
my ($type, $msg, $file_name, $line_no) = (@_);
my $prompt_prefix;
if($type == Type::Log) {
print $msg . "\n";
}
elsif($type == Type::Warning) {
$prompt_prefix = ">> LINK Warning : ";
my $location = (defined $file_name) ? "[$file_name] " : "";
print $prompt_prefix . $location . $msg . "\n";
}
elsif($type == Type::Fatal) {
$prompt_prefix = ">> *** LINK Fatal : ";
my $location = "[at line $line_no] ";
die $prompt_prefix . $location . $msg . "\n";
}
}