[Feature]Upload Modem source code

Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/tools/link.pl b/mcu/tools/link.pl
new file mode 100644
index 0000000..42d78ea
--- /dev/null
+++ b/mcu/tools/link.pl
@@ -0,0 +1,225 @@
+#!/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";
+    }
+}
\ No newline at end of file