[Feature]Upload Modem source code

Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/tools/AutoAdjustInputSection.pl b/mcu/tools/AutoAdjustInputSection.pl
new file mode 100644
index 0000000..8cd5de8
--- /dev/null
+++ b/mcu/tools/AutoAdjustInputSection.pl
@@ -0,0 +1,492 @@
+#!/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) 2018
+#
+#  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:
+#* ---------
+#*   AutoAdjustInputSection.pl
+#*
+#* Project:
+#* --------
+#*
+#*
+#* Description:
+#* ------------
+#*   This scripts is used to parse the configuration of Auto-Placement symbols with order.
+#*
+#* Author:
+#* -------
+#*   Frank Hu (mtk12175)
+#*
+#****************************************************************************/
+
+use strict;
+use warnings;
+
+BEGIN { push @INC , './tools/' }  # add additional library path
+use FileInfoParser;
+use CommonUtility;
+use File::Basename;
+use File::Spec;
+
+package Type;
+use constant Log        => 0;
+use constant Warning    => 1;
+use constant Fatal      => 2;
+package main;
+
+my ($ToolChainBase, $themf, $INFOMAKELOG, $LDSFileName) = (@ARGV);
+
+&msg_handler(Type::Log, "Input file: $ToolChainBase, $themf, $INFOMAKELOG, $LDSFileName\n");
+my $ConfigfileDir = "./interface/layout/InputSection/";
+if(!-e $ConfigfileDir) {
+    &msg_handler(Type::Warning, "$ConfigfileDir does not exist, thus ignore this step ...");
+    exit 0;
+}
+
+my %MAKEFILE_OPTIONS;
+my %CmplOption;
+my %RelOption;
+
+FileInfo::PreProcess($themf, \%MAKEFILE_OPTIONS, $INFOMAKELOG, \%CmplOption, \%RelOption,1);
+
+my ($Readelf, $AR, $GCC);
+my ($Project, $Flavor);
+my ($Original_Project, $Original_Flavor);
+my ($LibPath1Prefix, $LibPath2Prefix);
+my ($tempdir, $tempInputFolder);
+
+&GetEnvInfo();
+
+#record all the config info
+my %ConfigInfoHash;
+#record all the used lib and obj
+my %libObjHash;
+#extract the info of all symbols of a .obj
+my %SymLogInfoHash;
+#extract the info of all sections of a .obj
+my %SecLogInfoHash;
+#create a link between symbol name and the actual symbol name in .obj
+my %SymConvertHash;
+#check if duplicated symbols exist between different .ldf files
+my %SymCheckCrossFiles;
+#check if group name is unique in different lds files
+my %SecCheck;
+
+opendir(DIR, $ConfigfileDir) || &msg_handler(Type::Fatal, "Fail to open $ConfigfileDir: $!", __LINE__);
+my @FileList = grep { /\.ldf$/ && -f "$ConfigfileDir/$_" && !/^sample\.ldf$/ } readdir(DIR);
+close DIR;
+
+map { &ParseConfigFile("$ConfigfileDir/$_") } (@FileList);
+
+&ParseLibObj();
+&CheckUserConfiguration();
+
+&UpdateLDS($LDSFileName);
+
+&CleanTempFiles();
+
+exit 0;
+
+sub GetEnvInfo
+{
+    $AR      = File::Spec->rel2abs($ToolChainBase."ar");
+    $GCC     = $ToolChainBase."gcc";
+    $Readelf = File::Spec->rel2abs($ToolChainBase."readelf");
+
+    &msg_handler(Type::Fatal, "GCC tool does not exist", __LINE__) unless(-e $Readelf and -e $AR and -e $GCC);
+
+    my $RelPath = File::Basename::dirname($INFOMAKELOG);
+    my $AbsPath = File::Spec->rel2abs($RelPath);
+
+	$Original_Project = $MAKEFILE_OPTIONS{"ORIGINAL_PROJECT_NAME"};
+	$Original_Flavor = $MAKEFILE_OPTIONS{"ORIGINAL_FLAVOR"};
+	
+    if($AbsPath =~ m|/mcu/build/(\w+)/(\w+)/|) {
+        ($Project, $Flavor) = ($1, $2);
+    }
+    else {
+        &msg_handler(Type::Fatal, "Fail to get project and flavor", __LINE__);
+    }
+
+    ($tempdir) = ($LDSFileName =~ /(.*)custom/);
+    $tempdir .= "tmp/";
+
+    $LibPath1Prefix = File::Spec->rel2abs("./mtk_rel/$Original_Project/$Original_Flavor/TARGET/lib/");
+    $LibPath2Prefix = File::Spec->rel2abs("./build/$Project/$Flavor/bin/lib/");
+
+    $tempInputFolder = $tempdir . "CustomInputSection";
+    system("rm -rf $tempInputFolder") if(-e $tempInputFolder);
+    system("mkdir -p $tempInputFolder");
+    $? == 0 or &msg_handler(Type::Fatal, "Making $tempInputFolder failed $?", __LINE__);
+
+    my $OptFile = $tempdir."PreProcessOpt.txt";
+    my $cmpOpt = undef;
+    #Gather compiler options
+    foreach my $key ( keys %CmplOption ) {
+        next if($key eq lc $key);
+        if (defined $CmplOption{$key}) {
+	        $cmpOpt .= " -D$key=$CmplOption{$key}";
+	    } else {
+            $cmpOpt .= " -D$key";
+	    }
+    }
+
+    open (FILE, "> $OptFile") or &msg_handler(Type::Fatal, "$OptFile: open file error!", __LINE__);
+    print FILE $cmpOpt;
+    close FILE;
+}
+
+sub ParseConfigFile
+{
+    my ($ConfigFile) = (@_);
+    my $FileName = File::Basename::basename($ConfigFile);
+
+    my $OptFile = $tempdir."PreProcessOpt.txt";
+    #Preprocess CustomInputSection.txt
+    my $cmd = "$GCC -x c -E -undef \@$OptFile $ConfigFile";
+    my $output = qx($cmd);
+    $? == 0 or &msg_handler(Type::Fatal, "$ConfigFile preprosseing failed $?\n$output", __LINE__, $FileName);
+
+    #Tidy preprocessor output
+    my $tempOutput = undef;
+    map{ $tempOutput .= $_."\n" if (!($_ =~ /^#/)); } (split /\n/, $output);
+
+    my ($SubSection, $SecName, $PreSecName, $bFlag, $sFlag) = (undef, undef, undef, 0, 0);
+    my %UniqHash;
+    my (@TotalSecArray, @TotalSymArray, @SecNameArray);
+    my $BreakRegExp = "[\\*]{20}\\s[<]\\s(GROUP_CFG_\\w+)\\s[>]\\s[\\*]{20}";
+
+    #split entire config file into several configuration groups.
+    foreach my $line (split /\n/, $tempOutput) {
+        if($bFlag == 0) {
+            $bFlag = 1 if(($line =~ m/^\[Symbol\]\s+\[Obj\]\s+\[Lib\]$/));
+            next;
+        }
+        next if($line =~ m/^\s*$/);
+
+        if($line =~ m/^\s*$BreakRegExp\s*$/) {
+            $SecName = $1;
+            &msg_handler(Type::Fatal, "$SecName has been deifned in $SecCheck{$SecName}", __LINE__, $FileName) if(exists $SecCheck{$SecName});
+            $SecCheck{$SecName} = $FileName;
+            $sFlag = 1;
+            if(defined $SubSection) {
+                push @TotalSecArray, $SubSection;
+                push @SecNameArray, $PreSecName;
+                undef $SubSection;
+                undef $PreSecName;
+            }
+            next;
+        }
+        $SubSection .= $line."\n" if($sFlag == 1);
+        $PreSecName = $SecName;
+    }
+    push @TotalSecArray, $SubSection if(defined $SubSection);
+    push @SecNameArray, $PreSecName if(defined $SubSection);
+
+    &msg_handler(Type::Fatal, "The num of section name is not equal to section num", __LINE__, $FileName) if($#TotalSecArray != $#SecNameArray);
+    for (my $i = 0; $i <= $#TotalSecArray; $i++) {
+        my @SymArray = ();
+        my $align;
+        my @tempArray = split /\n/, $TotalSecArray[$i];
+        foreach my $line (@tempArray) {
+            if($line =~ m/^(\S+)\s+(\S+)\s+(\S+)\s*$/) {
+                if(exists $UniqHash{$1.$2.$3}) {
+                    &msg_handler(Type::Warning, "[Duplicated Lines]: $line", __LINE__, $FileName);
+                    next;
+                }
+                else {
+                    $UniqHash{$1.$2.$3} = 0;
+                }
+
+                if(not exists $SymCheckCrossFiles{$1.$2.$3}) {
+                    $SymCheckCrossFiles{$1.$2.$3} = $FileName;
+                    push @SymArray, [$1, $2, $3];
+                    $libObjHash{$3}{$2} = 0;
+                }
+                else {
+                    my $preLdf = $SymCheckCrossFiles{$1.$2.$3};
+                    &msg_handler(Type::Warning, "$1 has been defined in $preLdf", __LINE__, $FileName);
+                    next;
+                }
+            } elsif ($line =~ m/^ALIGN:(\w+)$/){
+                $align = $1;
+            } else {
+                my $msg = "Illegal Line Format: $line";
+                &msg_handler(Type::Fatal, "Illegal Line Format: $line", __LINE__, $FileName);
+                next;
+            }
+        }
+        $ConfigInfoHash{$FileName}{$SecNameArray[$i]}{"ALIGN"} = $align if($#SymArray >= 0);
+        $ConfigInfoHash{$FileName}{$SecNameArray[$i]}{"LIST"} = \@SymArray if($#SymArray >= 0);
+    }
+    &msg_handler(Type::Warning, "$FileName is an invalid file", __LINE__, $FileName) unless(exists $ConfigInfoHash{$FileName});
+}
+
+sub ParseLibObj
+{
+    foreach my $lib (keys %libObjHash) {
+        my $LibPath1 = $LibPath1Prefix . "/" . $lib;
+        my $LibPath2 = $LibPath2Prefix . "/" . $lib;
+        my $LibPath = (-e $LibPath1) ? $LibPath1 : $LibPath2;
+        if(!-e $LibPath) {
+            delete $libObjHash{$lib};
+            next;
+        }
+
+        my @ObjArray = keys %{$libObjHash{$lib}};
+        foreach my $obj (@ObjArray) {
+            my $ExtractObj = $lib . $obj;
+            my $SymLog = $ExtractObj . "." . "symbols.log";
+            my $SecLog = $ExtractObj . "." . "sections.log";
+            
+            next if(-f $SymLog && -f $SecLog); #have been parsed before.
+            my $tmp_dir = $tempdir . "CustomInputSection/";
+            chdir ($tmp_dir) or &msg_handler(Type::Fatal, "Fail to dir to $tmp_dir", __LINE__);
+
+            #extract the obj from lib
+            system("$AR -x $LibPath $obj 2> /dev/null");
+            unless(-f $obj) {
+                delete $libObjHash{$lib}{$obj};
+                next;
+            }
+
+            #move the obj to certain folder
+            system("mv $obj $ExtractObj");
+            $? == 0 or &msg_handler(Type::Fatal, "$ExtractObj moving failed", __LINE__);
+
+            #generate SYM log
+            system("$Readelf --syms -W $ExtractObj > $SymLog");
+            $? == 0 or &msg_handler(Type::Fatal, "Generating $SymLog failed", __LINE__);
+
+            #generate SECTION log
+            system("$Readelf -S -W $ExtractObj > $SecLog");
+            $? == 0 or &msg_handler(Type::Fatal, "Generating $SecLog failed", __LINE__);
+
+            &ParseSymAndSecLog($SymLog, $SecLog, $lib, $obj);
+            chdir ($ENV{'PWD'}) or &msg_handler(Type::Fatal, "Fail to dir to $ENV{'PWD'}", __LINE__);
+        }
+    }
+}
+
+sub ParseSymAndSecLog
+{
+    my ($tempSymLog, $tempSecLog, $tempLib, $tempObj) = (@_);
+    my $key = $tempLib . $tempObj;
+
+    open SYM_LOG, "< $tempSymLog" or &msg_handler(Type::Fatal, "Fail to open $tempSymLog", __LINE__);
+    while(my $line = <SYM_LOG>) {
+        #    17: 00000024    40 FUNC    LOCAL  DEFAULT [MIPS16]     9 ev_cmp_f
+        if($line =~ m/^\s*\d+\s*:\s*\S+\s+(\d+).*\s+(\d+)\s+(\w+)$/) {
+            my ($Symbol, $index, $size) = ($3, $2, $1);
+            $SymConvertHash{$Symbol}    = $Symbol;
+            $SymLogInfoHash{$key}{$Symbol}{'index'} = $index;
+            $SymLogInfoHash{$key}{$Symbol}{'size'}  = $size;
+        }
+    }
+    close SYM_LOG;
+
+    open SEC_LOG, "< $tempSecLog" or &msg_handler(Type::Fatal, "Fail to open $tempSecLog", __LINE__);
+    while(my $line = <SEC_LOG>) {
+        #  [22] .text.evshed_give PROGBITS        00000000 000bbc 00002c 00  AX  0   0  4
+        if($line =~ m/^\s*\[\s*(\d+)\s*\]\s+(\S+)\s+/) {
+            my ($index, $Section) = ($1, $2);
+            if($Section =~ m/^(\.?\w+)\.\w+$/) {
+                $SecLogInfoHash{$key}{$index}{'type'}  = $1;
+                $SecLogInfoHash{$key}{$index}{'valid'} = 'true';
+            }
+            elsif($Section =~ m/^[^\.]*$/) {
+                $SecLogInfoHash{$key}{$index}{'type'}  = $Section;
+                $SecLogInfoHash{$key}{$index}{'valid'} = 'false';
+            }
+        }
+    }
+    close SEC_LOG;
+}
+
+sub CheckUserConfiguration
+{
+    foreach my $ldf (keys %ConfigInfoHash) {
+        my $FileName = $ldf;
+        #check the validity of user config
+        foreach my $group (keys %{$ConfigInfoHash{$ldf}}) {
+            my @FinalSymList     = ();
+            my $CheckSectionType = undef;
+
+            foreach my $item (@{$ConfigInfoHash{$ldf}{$group}{"LIST"}}) {
+                my $SectionType = undef;
+                my $SymName = $item->[0];
+                my $key = $item->[2] . $item->[1];
+                my $SymNameInObj;
+
+                if(not exists $libObjHash{$item->[2]}) { #lib does not exist
+                    my $tips = $item->[2] . " does not exist.";
+                    &msg_handler(Type::Warning, "$SymName not found in Group" . "[$group]" . ": $tips", __LINE__, $FileName);
+                    next;
+                }
+                elsif(not exists $libObjHash{$item->[2]}{$item->[1]}) { #obj can't be found in lib
+                    my $tips = $item->[1] . " not exists in " . $item->[2];
+                    &msg_handler(Type::Warning, "$SymName not found in Group" . "[$group]" . ": $tips", __LINE__, $FileName);
+                    next;
+                }
+
+                if(not exists $SymConvertHash{$SymName}) { #the symbol not exists
+                    my $tips = "If your symbol type is C++, please use the full name in MAP/SYM, such as [ipfcore_task_init] -> [_Z17ipfcore_task_initv]";
+                    &msg_handler(Type::Warning, "$SymName can't be found in Group" . "[$group]" . ", $tips", __LINE__, $FileName);
+                    next;
+                }
+                else {
+                    $SymNameInObj = $SymConvertHash{$SymName};
+                }
+
+                my $index = $SymLogInfoHash{$key}{$SymNameInObj}{'index'};
+
+                if(not exists $SecLogInfoHash{$key}{$index}) { #the input section does not exist
+                    &msg_handler(Type::Warning, "can't find the input section of $SymNameInObj in Group" . "[$group]", __LINE__, $FileName);
+                    next;
+                }
+
+                if($SecLogInfoHash{$key}{$index}{'valid'} eq 'false') { #unsupported section type
+                    $SectionType = $SecLogInfoHash{$key}{$index}{'type'};
+                    my $NewType = $SectionType . '.' . $item->[0];
+                    my $tips = "Unsupported Inputsection: " . $item->[0] . " -> $SectionType in Group" . "[$group]" . ", please use __attribute__ ((sections(\"$NewType\"))) to re-try.";
+                    &msg_handler(Type::Warning, $tips, __LINE__, $FileName);
+                    $CheckSectionType = undef;
+                    next;
+                }
+
+                $SectionType = $SecLogInfoHash{$key}{$index}{'type'};
+                $CheckSectionType = $SectionType if(not defined $CheckSectionType);
+                if($CheckSectionType ne $SectionType) { #Inputsection type mismatch within one group
+                    my $msg = "Inputsection type mismatch in Group" . "[$group]: " . $item->[0] . " -> " . $SectionType;
+                    &msg_handler(Type::Warning, $msg, __LINE__, $FileName);
+                    next;
+                }
+
+                push @{$item}, $SymLogInfoHash{$key}{$SymNameInObj}{'size'}, $CheckSectionType;
+                push @FinalSymList, $item;
+            }
+            if($#FinalSymList >= 0) {
+                $ConfigInfoHash{$ldf}{$group}{"LIST"} = \@FinalSymList;
+            }
+            else {
+                delete $ConfigInfoHash{$ldf}{$group}{"LIST"};
+            }
+        }
+    }
+}
+
+sub UpdateLDS
+{
+    my ($LDSFile) = (@_);
+    my $output = undef;
+    open LDS, "< $LDSFile" or &msg_handler(Type::Fatal, "Fail to open $LDSFile", __LINE__);
+    my $CacheLineSize = undef;
+
+    while(my $line = <LDS>) {
+        #get the cache line size
+        $CacheLineSize = $1 if($line =~ m/^\s*CACHELINESIZE\s*=\s*(\d+);$/);
+
+        if($line =~ m/^(\s*)\*\s*\(\s*(\.?)(\w+)(\*?)\s*\)$/) {
+            my $suffix = ($4 eq '*') ? '.*' : '';
+            my ($space, $ResultLine) = ($1, undef);
+            my $RegularPattern = ($2 eq '.') ? ('\.' . $3) : $3;
+            foreach my $ldf (keys %ConfigInfoHash) {
+                foreach my $group (keys %{$ConfigInfoHash{$ldf}}) {
+                    my $GroupType = $ConfigInfoHash{$ldf}{$group}{"LIST"}->[0]->[4];
+                    next unless($GroupType =~ m/^$RegularPattern$suffix$/);
+
+                    my ($SubLine, $GroupSize) = (undef, 0);
+                    $SubLine = "$space$group\$\$Base = .;\n";
+                    foreach my $item (@{$ConfigInfoHash{$ldf}{$group}{"LIST"}}) {
+                        my ($sym, $obj, $size, $type) = ($item->[0], $item->[1], $item->[3], $item->[4]);
+                        $SubLine .= "${space}*$obj ($type.$sym.*)\n" . "${space}*$obj ($type.$sym)\n";
+                        $GroupSize  += $size;
+                    }
+                    $SubLine .= "$space$group\$\$Limit = . ;\n$space$group\$\$Length = ABSOLUTE($group\$\$Limit - $group\$\$Base);\n\n";
+                    if (defined $ConfigInfoHash{$ldf}{$group}{"ALIGN"}){
+                        $SubLine = "\n" . $space . ". = ALIGN($ConfigInfoHash{$ldf}{$group}{\"ALIGN\"});" . "\n" . $SubLine;
+                    } else{
+                        #if total size > 32, align 64B to gain L2$, else, align 32B
+                        my $AlignSize = (($GroupSize > 32) ? 64 : ((defined $CacheLineSize) ? $CacheLineSize : 32));
+                        $SubLine = "\n" . $space . ". = ALIGN($AlignSize);" . "\n" . $SubLine;
+                    }
+                    $ResultLine .= $SubLine;
+                    #avoid multiple match
+                    delete $ConfigInfoHash{$ldf}{$group};
+                }
+            }
+            $line = $ResultLine . $line if(defined $ResultLine);
+        }
+        $output .= $line;
+    }
+    close LDS;
+
+    open LDS, "> $LDSFile" or &msg_handler(Type::Fatal, "Fail to open $LDSFile", __LINE__);
+    print LDS $output;
+    close LDS;
+
+    &msg_handler(Type::Log, "\nLDS is updated successfully ^O^, please check $LDSFileName.", __LINE__);
+}
+
+sub CleanTempFiles
+{
+    system("rm -rf $tempInputFolder");
+    $? == 0 or &msg_handler(Type::Fatal, "Deleting $tempInputFolder failed $?", __LINE__);
+
+    my $OptFile = $tempdir."PreProcessOpt.txt";
+    system("rm -f $OptFile");
+    $? == 0 or &msg_handler(Type::Fatal, "Deleting $OptFile failed $?", __LINE__);
+}
+
+sub msg_handler
+{
+    my ($type, $msg, $line_no, $file_name) = (@_);
+    my $prompt_prefix;
+    if($type == Type::Log) {
+        print $msg . "\n";
+    }
+    elsif($type == Type::Warning) {
+        $prompt_prefix = ">> AAIS Warning : ";
+        my $location = (defined $file_name) ? "[$file_name] " : "";
+        print $prompt_prefix . $location . $msg . "\n";
+    }
+    elsif($type == Type::Fatal) {
+        $prompt_prefix = ">> *** AAIS Fatal : ";
+        my $location = (defined $file_name) ? "[$file_name] " : "";
+        $location .= "[at line $line_no] ";
+        die $prompt_prefix . $location . $msg . "\n";
+    }
+}