[Feature][Modem]Update MTK MODEM V1.6 baseline version: MOLY.NR15.R3.MD700.IVT.MP1MR3.MP.V1.6

MTK modem version: MT2735_IVT_MOLY.NR15.R3.MD700.IVT.MP1MR3.MP.V1.6.tar.gz
RF  modem version: NA

Change-Id: I45a4c2752fa9d1a618beacd5d40737fb39ab64fb
diff --git a/mcu/tools/MemoryUtility/BasicMemInfoQuery.pm b/mcu/tools/MemoryUtility/BasicMemInfoQuery.pm
new file mode 100644
index 0000000..065d6f3
--- /dev/null
+++ b/mcu/tools/MemoryUtility/BasicMemInfoQuery.pm
@@ -0,0 +1,630 @@
+#!/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) 2006
+#
+#  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:
+#* ---------
+#*   BasicInfoQuery.pm
+#*
+#* Project:
+#* --------
+#*
+#*
+#* Description:
+#* ------------
+#*   This perl module is used to get system basic information
+#*       
+#*
+#* Author:
+#* -------
+#*   Carl Kao (mtk08237)
+#*
+#****************************************************************************/
+
+BEGIN { push @INC, '../', './tools/', './tools/MemoryUtility/' }  # add additional library path
+
+use strict;
+use POSIX qw(floor ceil);
+use systemInfo;
+use LinkerOutputParser;
+use FileInfoParser;
+use CommonUtility;
+
+package FILEOPTION;
+use constant LIS         => 1;
+use constant MAP         => 2;
+use constant SYM         => 3;
+use constant MAKEFILE    => 4;
+use constant INFOMAKE    => 5;
+
+package BasicMemInfo;
+
+#****************************************************************************
+# Constants
+#****************************************************************************
+my $VERNO     = " v0.01";
+             # v0.01 , 2018/10/17,  Updated CMD_GetRAMUsage for 512MB memory
+             # e0.01 , 2018/08/06,  Updated CMD_GetRAMUsage
+             # a0.06 , 2018/05/14,  Limited memory padding count to 8 in CMD_GetRAMUsage
+             # a0.05 , 2017/11/28,  Provide DRDI usage info in CMD_GetRAMUsage
+             # a0.04 , 2017/07/04,  Fixed CMD_GetRAMUsage when calculating overlay section size
+             # a0.03 , 2017/07/04,  Refactored CMD_GetRAMUsage due DRDI
+             # a0.02 , 2017/01/28,  Fixed CMD_GetRAMUsage when using 64KB MPU granularity
+             # a0.01 , 2017/01/24,  Fixed GetTotalRAMUsageFromLDS function
+             # u0.06 , 2016/11/02,  Sort execution regions with start address in GetERsInRAM
+             # u0.05 , 2016/09/07,  RAM margin info modified to CMD_GetRAMUsage
+             # u0.04 , 2016/09/06,  Free RAM and RAM margin info modified to CMD_GetRAMUsage
+             # u0.03 , 2016/03/03,  Memory Utility Refinement (Add shared region info to CMD_GetRAMUsage)
+             # u0.02 , 2015/01/20,  Memory Utility Refinement (Add shared region info to CMD_GetRAMUsage)
+             # u0.01 , 2015/01/14,  Memory Utility Refinement
+             # m0.06 , 2014/02/20,  Correct GetTotalRAMUsageFromLDS's base address
+             # m0.05 , 2013/12/25,  Fix LoadView which can't count in .bss
+             # m0.04 , 2013/10/20,  Support Secure region
+             # m0.03 , 2013/06/25,  Support CMD_GetROMSize() for filtering out COPRO section
+             # m0.02 , 2013/03/21,  Support GetMBAlignment()
+             # m0.01 , 2013/01/08,  Initial revision
+
+#****************************************************************************
+# Global variable
+#****************************************************************************
+my $g_bParseSYM = 0;
+my $g_bParseMAP = 0;
+my $g_bParseMAKEFILE = 0;
+my %g_MAKEFILE_OPTIONS;
+
+#****************************************************************************
+# Subroutine:  BasicInfoQuery_verno - to query this package's version number
+# Parameters:  x
+# Returns:     version number string
+#****************************************************************************
+sub BasicInfoQuery_verno
+{
+    return $VERNO;
+}
+
+#****************************************************************************
+# oo >>>  Finished
+#****************************************************************************
+return 1;
+
+sub DispatchCommand
+{
+    my ($cmd, $MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+
+    # force the Parse to be called in DispatchCommand in order to make sure the only entry function of this file is DispatchCommand
+    sub Parse
+    {
+        my ($nOption, $PATH) = @_;
+        if($nOption == FILEOPTION::MAP and !$g_bParseMAP)
+        {
+            basicinfo_die("$PATH doesn't exist!") if(!-e $PATH);
+            &LinkerOutputParser::FileParse($PATH);
+            $g_bParseMAP = 1;
+        }
+        elsif($nOption == FILEOPTION::SYM and !$g_bParseSYM)
+        {
+            basicinfo_die("$PATH doesn't exist!") if(!-e $PATH);
+            &LinkerOutputParser::FileParse($PATH);
+            $g_bParseSYM = 1;
+        }
+        elsif($nOption == FILEOPTION::MAKEFILE and !$g_bParseMAKEFILE)
+        {
+            basicinfo_die("$PATH doesn't exist!") if(!-e $PATH);
+            &FileInfo::Parse_MAKEFILE($PATH, \%g_MAKEFILE_OPTIONS);
+            $g_bParseMAKEFILE = 1;
+        }
+    }
+    Parse(FILEOPTION::SYM, $SYM_PATH);
+    Parse(FILEOPTION::MAKEFILE, $MAKEFILE_PATH, \%g_MAKEFILE_OPTIONS);
+    $cmd = "help" if($cmd eq "-h" or $cmd eq "--help");
+    my ($pack_name, $file, $line_no) = caller;   
+    no strict 'refs';
+    &{$cmd}($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) if (exists &{$cmd})
+        or basicinfo_die("$cmd() doesn't exists!", $file, $line_no);
+}
+
+# It  HAS  L1core and Secure region !
+sub CMD_GetLoadViewSize
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my $ERs_aref = &LinkerOutputParser::ListAllExeRegion(1);
+    my $strLastRegion;
+    my $nLoadViewSize;
+
+    for (my $i = $#{$ERs_aref};$i >= 0; $i--)
+    {
+        $strLastRegion = $ERs_aref->[$i];
+        $nLoadViewSize = hex(&LinkerOutputParser::GetExeRegionInfo($strLastRegion, Region::LMA));
+        last if (LinkerOutputParser::GetExeRegionInfo($strLastRegion, Region::Attr) =~ /LOAD/);
+    }
+    my $strUROM_Base = sysInfo::GetMemoryInfo("UROM", 1, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+    my $strROM_Length = sysInfo::GetMemoryInfo("ROM", 2, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+
+    PrintLog($PrintFunc, "Load Information:\n");
+    PrintLog($PrintFunc, "ROM Base Address in LDS = $strUROM_Base\n");
+    PrintLog($PrintFunc, "ROM Length in LDS = $strROM_Length\n");
+    PrintLog($PrintFunc, "Last Region in load = $strLastRegion\n");
+    
+    if($strLastRegion !~/zi|bss/i) 
+    {
+        my $nLastRegionSize = hex(&LinkerOutputParser::GetExeRegionInfo($strLastRegion, Region::Size));
+        PrintLog($PrintFunc, "Last Region Size in Load = ". CommonUtil::Dec2Hex($nLastRegionSize) . " = $nLastRegionSize(Bytes) \n");
+        $nLoadViewSize += $nLastRegionSize;
+    }
+    else 
+    {
+        PrintLog($PrintFunc, "Last Region Size in load = 0 (Bytes) \n");
+    }
+    PrintLog($PrintFunc, "End address of last Region LMA in load = ". CommonUtil::Dec2Hex($nLoadViewSize) . "\n");
+    PrintLog($PrintFunc, "-------------------------------------------------------------------\n");
+    $nLoadViewSize -= hex($strUROM_Base);
+    PrintLog($PrintFunc, "Total Load Size (ROM) = ". CommonUtil::Dec2Hex($nLoadViewSize) . " = $nLoadViewSize(Bytes) \n");
+    return $nLoadViewSize;
+}
+
+#  NO  L1core and Secure region !
+sub CMD_GetROMSize
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my $strUROM_Base = sysInfo::GetMemoryInfo("UROM", 1, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+    my $strROM_Length = sysInfo::GetMemoryInfo("ROM", 2, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+    
+    PrintLog($PrintFunc, "ROM Information:\n");
+    PrintLog($PrintFunc, "ROM Base Address in LDS = $strUROM_Base\n");
+    PrintLog($PrintFunc, "ROM Length in LDS = $strROM_Length\n");
+    
+    my $ERs_aref = &LinkerOutputParser::ListAllExeRegion(1);
+    $ERs_aref = sysInfo::FilterOutCoproReservedRegion($ERs_aref); 
+    $ERs_aref = sysInfo::FilterOutSecureRegion($ERs_aref);# if(FileInfo::is_BuiltWithCopro());;
+    my $strLastRegion;
+    my $nLoadViewSize;
+    
+    for (my $i = $#{$ERs_aref};$i >= 0; $i--)
+    {
+        $strLastRegion = $ERs_aref->[$i];
+        $nLoadViewSize = hex(&LinkerOutputParser::GetExeRegionInfo($strLastRegion, Region::LMA));
+        last if (LinkerOutputParser::GetExeRegionInfo($strLastRegion, Region::Attr) =~ /LOAD/);
+    }
+    
+    my $nROMBase = hex($strUROM_Base);
+    my $nROMSize = ($nLoadViewSize&0x0fffffff) - ($nROMBase&0x0fffffff);
+    PrintLog($PrintFunc, "Last Load Region in ROM = $strLastRegion\n");
+    if($strLastRegion !~/zi|bss/i) 
+    {
+        my $nLastRegionSize = hex(&LinkerOutputParser::GetExeRegionInfo($strLastRegion, Region::Size));
+        PrintLog($PrintFunc, "Last Load Region Size in ROM = ". CommonUtil::Dec2Hex($nLastRegionSize) ." = $nLastRegionSize(Bytes) \n");
+        $nROMSize += $nLastRegionSize;
+    } 
+    else 
+    {
+        PrintLog($PrintFunc, "Last Load Region Size in ROM = 0 (Bytes) \n");
+    }
+    
+    my $strROMSize = CommonUtil::Dec2Hex($nROMSize); # $nROMSize = $nROMendAddress for pcore since $nROMBase=0
+    my $nROMendAddress = $nROMBase + $nROMSize;
+    PrintLog($PrintFunc, "End address of last Region LMA = ".  CommonUtil::Dec2Hex($nROMendAddress) ."\n");
+    PrintLog($PrintFunc, "-------------------------------------------------------------------\n");
+    PrintLog($PrintFunc, "Total ROM Size (Code + RO Data + RW Data) = $strROMSize = $nROMSize(Bytes) \n");
+    return $nROMSize;
+}
+
+sub CMD_GetNonSharedRAMUsage
+{
+
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+
+    my $ERinRAM_aref = GetERsInRAM($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc);
+    my ($nNonSharedRAMUsage, $nRAMMargin) = (0, 0, 0);
+    if(scalar(@$ERinRAM_aref)>0)
+    {   
+        my $EndRegion = @$ERinRAM_aref[scalar(@$ERinRAM_aref)-1];
+        
+        # 1. calculate current RAM usage by "end of last section - base of first section " 
+        #my $nFirstERInRAMVMA = hex(&LinkerOutputParser::GetExeRegionInfo($ERinRAM_aref->[0], Region::VMA)); 
+
+        my $nFirstNonSharedERInRAMVMAinBank0 = hex(&LinkerOutputParser::GetExeRegionInfo('CACHED_EXTSRAM', Region::VMA)) & 0x0FFFFFFF;
+        my $nEndRegionVMA =  hex(&LinkerOutputParser::GetExeRegionInfo($EndRegion, Region::VMA));        
+        my $nEndRegionSize = hex(&LinkerOutputParser::GetExeRegionInfo($EndRegion, Region::Size));
+        $nNonSharedRAMUsage = $nEndRegionVMA + $nEndRegionSize - $nFirstNonSharedERInRAMVMAinBank0;
+
+
+        # 2. get RAM Margin, 1:base, 2:length
+        my $nRAM_Base = hex(sysInfo::GetMemoryInfo("RAM", 1, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS));
+        my $nRAM_Length = hex(sysInfo::GetMemoryInfo("RAM", 2, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS));
+        my $nVRAM_Base = sysInfo::GetMemoryInfo("VRAM", 1, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+        $nRAMMargin = ($nRAM_Base + $nRAM_Length) - ($nEndRegionVMA + $nEndRegionSize);
+
+        
+        # 3. no need to get the space of dsp tx/rx since there is no region in the end of RAM
+        # $nReservedSize = GetReservedSize($IMAGELAYOUT_PATH, $SYM_PATH, $MAKEFILE_PATH);
+
+    }
+    return ($nNonSharedRAMUsage, $nRAMMargin);
+}
+
+sub CMD_GetRAMUsage
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc, $nRAM_Base) = @_;
+    $nRAM_Base = hex(sysInfo::GetMemoryInfo("RAM", 1, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS)) if(!defined $nRAM_Base);
+    my $ERinRAM_aref = GetERsInRAM($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc);
+    my $nRAMUsage = 0;
+    my @RAMMargins;
+    return $nRAMUsage if (!@$ERinRAM_aref);
+    
+    my $strRAM_Base = sysInfo::GetMemoryInfo("RAM", 1, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+    my $strVRAM_Base = sysInfo::GetMemoryInfo("VRAM", 1, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+    my $strRAM_Length = sysInfo::GetMemoryInfo("RAM", 2, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+    my $nDummyEndBase = hex(&LinkerOutputParser::Get_DUMMY_END_Base());
+    my $ER = $ERinRAM_aref->[-1];
+    my $nEndRegionVMA =  hex(&LinkerOutputParser::GetExeRegionInfo($ER, Region::VMA));
+    my $nEndRegionSize = hex(&LinkerOutputParser::GetExeRegionInfo($ER, Region::Size));
+    my $strEndRegionEndVMA = CommonUtil::Dec2Hex($nEndRegionVMA+$nEndRegionSize);
+    my $nFirstERInRAMVMA = hex(&LinkerOutputParser::GetExeRegionInfo($ERinRAM_aref->[0], Region::VMA));
+    my $strFirstERInRAMVMA = CommonUtil::Dec2Hex($nFirstERInRAMVMA);
+
+    PrintLog($PrintFunc, "RAM Information:\n");
+    PrintLog($PrintFunc, "RAM Base Address in LDS = $strRAM_Base\n");
+    PrintLog($PrintFunc, "VRAM Base Address in LDS = $strVRAM_Base\n");
+    PrintLog($PrintFunc, "1st Region in RAM: ".$ERinRAM_aref->[0].", VMA=$strFirstERInRAMVMA\n");
+    PrintLog($PrintFunc, "RegionBeforeDummyEnd: $ER, VMA=".CommonUtil::Dec2Hex($nEndRegionVMA).
+	     ", Size=".CommonUtil::Dec2Hex($nEndRegionSize).", End address=$strEndRegionEndVMA\n");
+    PrintLog($PrintFunc, "DummyEndBase = ".CommonUtil::Dec2Hex($nDummyEndBase)." (the end address of total MD memory)\n");
+    PrintLog($PrintFunc, "-------------------------------------------------------------------\n");
+    
+    my $nERend = CMD_GetROMSize(($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH));
+    my @FreeRAMAreas;
+    my @UsedRAMAreas;
+    my $drdi_start = 0;
+    my $drdi_load_start = 0;
+    my $drdi_end = 0;
+    my $drdi_load_end = 0;
+    my $drdi_found = 0;
+
+    foreach $ER (@$ERinRAM_aref) #Go through all regions in ram
+    {
+        my $strERsize = LinkerOutputParser::GetExeRegionInfo($ER, Region::Size);
+        my $nERaddr = get_physical_address(hex(&LinkerOutputParser::GetExeRegionInfo($ER, Region::VMA)));
+        if (hex($strERsize)) 
+        {
+            my $ERsize = hex($strERsize);
+            my $append = 0;
+            my $note = undef;
+            foreach my $used (@UsedRAMAreas)
+            {
+
+                if(($used->[0]<=$nERaddr) and (($used->[0]+$used->[1])>=$nERaddr))
+                {
+                    if (($used->[0]+$used->[1])<=($nERaddr+$ERsize)) 
+                    {
+                        $used->[1]= ($nERaddr+$ERsize)-$used->[0];
+                    }
+                    $append = 1;
+                } 
+                elsif(($used->[0]<=($nERaddr+$ERsize)) and (($used->[0]+$used->[1])>=($nERaddr+$ERsize))) 
+                {
+                    if ($used->[0] < $nERaddr) 
+                    {
+                        $used->[1] += $nERaddr-$used->[0];
+                        $used->[0] = $nERaddr;
+                        $append = 1;
+                    }
+                }
+                if($ER =~ /DRDI/)
+                {
+                    if($drdi_found == 0)
+                    {
+                        $drdi_start = $nERaddr;
+                        $drdi_load_start = hex(&LinkerOutputParser::GetExeRegionInfo($ER, Region::LMA));
+                        $drdi_end = $nERaddr + $ERsize;
+                        $drdi_load_end = $drdi_load_start + $ERsize;
+                        $drdi_found = 1;
+                    } 
+                    else 
+                    {
+                        $drdi_end = $nERaddr+$ERsize if($drdi_end <= ($nERaddr+$ERsize));
+                        $drdi_load_end = hex(&LinkerOutputParser::GetExeRegionInfo($ER, Region::LMA))+$ERsize;
+                    }
+                }
+                if ($append == 1) 
+                {
+                    $used->[2] = $note if($note ne undef);
+                }
+            }
+
+            if ($append == 1) 
+            {
+                $append = 0;
+            } 
+            else 
+            {
+                push @UsedRAMAreas, [$nERaddr, $ERsize, $note]
+            }
+        }
+    }
+    
+    @UsedRAMAreas = sort {$a->[0]<=>$b->[0]} @UsedRAMAreas;
+    
+    if($nERend < $UsedRAMAreas[0][0])
+    {
+        push @FreeRAMAreas, [$nERend,$UsedRAMAreas[0][0]-$nERend];
+    }
+    
+    for( my $i = 0;$i < $#UsedRAMAreas;$i+=1)
+    {
+        my $freeStart =$UsedRAMAreas[$i][0]+$UsedRAMAreas[$i][1];
+        my $freeSize  =$UsedRAMAreas[$i+1][0]-$freeStart;
+        push @FreeRAMAreas, [$freeStart,$freeSize]	 if ($freeSize > 0);
+    }
+
+    my $FRindex = 0;
+    my $totalRAM = 0;
+    foreach my $refUsed (@UsedRAMAreas)
+    {
+        $FRindex +=1;
+        $totalRAM += $refUsed->[1];
+        PrintLog($PrintFunc, "RAM Usage $FRindex  ".CommonUtil::Dec2Hex($refUsed->[1])." = " .GetSizeFromBytes($refUsed->[1])."\tfrom ". CommonUtil::Dec2Hex($refUsed->[0])." to ".CommonUtil::Dec2Hex($refUsed->[0]+$refUsed->[1])." ".$refUsed->[2]."\n");
+    }
+    PrintLog($PrintFunc,"Total allocated (used) RAM: ".CommonUtil::Dec2Hex($totalRAM)." = ".GetSizeFromBytes($totalRAM)."\n\n");
+
+    $nRAMUsage = $totalRAM;
+    $FRindex = 0;
+    $totalRAM = 0;
+    foreach my $refUsed (@FreeRAMAreas)
+    {
+        $FRindex +=1;
+        $totalRAM += $refUsed->[1];
+        PrintLog($PrintFunc, "RAM unused $FRindex ".CommonUtil::Dec2Hex($refUsed->[1])." = " .GetSizeFromBytes($refUsed->[1])."\tfrom ". CommonUtil::Dec2Hex($refUsed->[0])." to ".CommonUtil::Dec2Hex($refUsed->[0]+$refUsed->[1])."\n");
+    }
+    
+    PrintLog($PrintFunc,"Total unallocated (free) RAM: ".CommonUtil::Dec2Hex($totalRAM)." = ".GetSizeFromBytes($totalRAM)."\n\n");
+    PrintLog($PrintFunc, "RAM Usage consist of\n");
+    PrintLog($PrintFunc, "    1) RW + ZI : ".((hex($strEndRegionEndVMA)& 0x3fffffff)- get_physical_address($nFirstERInRAMVMA))."(Bytes) \tfrom $strFirstERInRAMVMA to $strEndRegionEndVMA\n");
+    PrintLog($PrintFunc, "Total used RAM Size (RW + ZI Data) = ". CommonUtil::Dec2Hex($nRAMUsage) . " = $nRAMUsage (Bytes) \n");
+    PrintLog($PrintFunc, "-------------------------------------------------------------------\n");
+    PrintLog($PrintFunc,"Top RAM Margins:\n");
+    
+    @FreeRAMAreas =sort {$b->[1] <=> $a->[1]} @FreeRAMAreas;
+    $FRindex =1;
+    my $AP_RAM = 0;
+    
+    foreach my $refUsed (@FreeRAMAreas)
+    {
+        my $MarginStart = ($refUsed->[0]+ 0xffff) & 0xffff0000;
+        my $MarginLength = (($refUsed->[0] + $refUsed->[1]) & 0xffff0000)- $MarginStart;
+        next if($MarginLength<0x10000);
+        $AP_RAM += $MarginLength;
+        if($g_MAKEFILE_OPTIONS{PLATFORM} =~ /MT6297/)
+        {
+            my $sib_area_start = hex(LinkerOutputParser::GetLinkerSymbolAddress("SIB_AREA", LinkerSymPostfix::Base,LinkerSymPrefix::Image));
+            my $sib_area_end = hex(LinkerOutputParser::GetLinkerSymbolAddress("SIB_AREA", LinkerSymPostfix::ZILimit,LinkerSymPrefix::Image));
+            if((($MarginStart <= $sib_area_start) && (($MarginStart+$MarginLength) >= $sib_area_start)) || (($MarginStart <= $sib_area_end) && (($MarginStart+$MarginLength) >= $sib_area_end))) 
+            {
+                PrintLog($PrintFunc, "RAM Margin $FRindex ".CommonUtil::Dec2Hex($MarginLength)." = " .GetSizeFromBytes($MarginLength)."\tfrom ". CommonUtil::Dec2Hex($MarginStart)." to ".CommonUtil::Dec2Hex($MarginStart+$MarginLength)." Used for SIB area\n");
+                $FRindex +=1;
+                next;
+            }
+        }
+        PrintLog($PrintFunc, "RAM Margin $FRindex ".CommonUtil::Dec2Hex($MarginLength)." = " .GetSizeFromBytes($MarginLength)."\tfrom ". CommonUtil::Dec2Hex($MarginStart)." to ".CommonUtil::Dec2Hex($MarginStart+$MarginLength)."\n");
+        $FRindex +=1;
+
+        push @RAMMargins, [$MarginStart,$MarginLength];
+    }
+    PrintLog($PrintFunc,"Total recycle free RAM: ".CommonUtil::Dec2Hex($AP_RAM). " = ". GetSizeFromBytes($AP_RAM)."\n\n");
+
+    for (my $item_count = $#RAMMargins+1; $item_count < 8; $item_count+=1)
+    {
+        push @RAMMargins, [0,0];
+    }
+    @RAMMargins = sort {$b->[1] <=> $a->[1]} @RAMMargins;
+    splice @RAMMargins, 8;
+    if ($drdi_found == 1) 
+    {
+        PrintLog($PrintFunc, "-------------------------------------------------------------------\n");
+        PrintLog($PrintFunc, "DRDI area\n");
+        PrintLog($PrintFunc, "Size     : ".(($drdi_end& 0x0fffffff)- ($drdi_start& 0x0fffffff))." (Bytes) \tfrom ".CommonUtil::Dec2Hex($drdi_start& 0x0fffffff)." to ".CommonUtil::Dec2Hex($drdi_end& 0x0fffffff)."\n");
+        PrintLog($PrintFunc, "Load size: ".(($drdi_load_end& 0x0fffffff)- ($drdi_load_start& 0x0fffffff))." (Bytes) \tfrom ".CommonUtil::Dec2Hex($drdi_load_start& 0x0fffffff)." to ".CommonUtil::Dec2Hex($drdi_load_end& 0x0fffffff)."\n");
+    }
+
+    return ($nRAMUsage, (@RAMMargins)); # add $strRAMMarin1 as return value,  the 3rd return value is different than l1core
+}
+
+sub GetSizeFromBytes
+{
+    my ($given_size) = @_;
+    return sprintf("%5.1f",$given_size)."(B)" if ($given_size < 1024);
+    if (($given_size/1024) < 1024) 
+    {
+        return sprintf("%5.1f",($given_size/1024))."(KB)" ;
+    }
+    return sprintf("%5.1f",($given_size/(1024*1024)))."(MB)";
+
+}
+
+sub GetERsInRAM
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my $ERs_aref = &LinkerOutputParser::ListAllExeRegion(1);
+    my $ERinRAM_aref = &sysInfo::FilterOutRegionInRAM($ERs_aref, \%g_MAKEFILE_OPTIONS);
+    my @regions;
+    my @sorted_regions;
+    foreach my $ER (@$ERinRAM_aref) 
+    {
+        my $ER_size = hex(&LinkerOutputParser::GetExeRegionInfo($ER, Region::VMA));
+        my $bank = $ER_size >> 28;
+        if($bank == 1 || $bank == 7)
+        {
+            $ER_size = $ER_size & 0x1FFFFFFF;
+        }
+        else
+        {
+            $ER_size = $ER_size & 0x0FFFFFFF;
+        }
+        push @regions, [$ER, $ER_size];
+    }
+    
+    @regions = sort { $a->[1] <=> $b->[1] } @regions;
+    
+    foreach my $ER (@regions) 
+    {
+        push @sorted_regions, $ER->[0];
+    }
+    return \@sorted_regions;
+}
+
+sub GetNonSharedMemoryERsInRAM
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my $ERinRAM_aref = GetERsInRAM($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc);
+    my $ERinRAMnoShared_aref = &sysInfo::FilterOutSharedRegion($ERinRAM_aref, \%g_MAKEFILE_OPTIONS);
+    return $ERinRAMnoShared_aref;
+}
+
+sub GetExpectedLoadViewSize
+{
+    basicinfo_die("not support GetExpectedLoadViewSize");
+
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my $nActualROMSize = CMD_GetLoadViewSize($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc);
+    PrintLog($PrintFunc, "ActualROMSize = ".CommonUtil::Dec2Hex($nActualROMSize)." = $nActualROMSize(Bytes)\n");
+    my $nExpectedROMSize = &CommonUtil::GetMBAligned($nActualROMSize, 1);
+    PrintLog($PrintFunc, "ExpectedROMSize = ".CommonUtil::Dec2Hex($nExpectedROMSize)." = $nExpectedROMSize(Bytes)\n");
+    return $nExpectedROMSize;
+}
+
+sub GetExpectedROMSize
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my $nActualROMSize = CMD_GetROMSize($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc);
+    PrintLog($PrintFunc, "ActualROMSize = ".CommonUtil::Dec2Hex($nActualROMSize)." = $nActualROMSize(Bytes)\n");
+    my $nExpectedROMSize = $nActualROMSize;
+    #$nExpectedROMSize = 0x80000 if ($nActualROMSize < hex(0x80000)) ;
+    PrintLog($PrintFunc, "ExpectedROMSize = ".CommonUtil::Dec2Hex($nExpectedROMSize)." = $nExpectedROMSize(Bytes)\n");
+    #PrintLog($PrintFunc, "(The space from ".CommonUtil::Dec2Hex($nActualROMSize)." to 0x80000 is reserved for l1core TCM space)\n") if ($nActualROMSize < hex(0x80000));
+    PrintLog($PrintFunc, "-------------------------------------------------------------------\n");
+    return $nExpectedROMSize;
+}
+
+sub GetExpectedRAMSize
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my ($nRAMUsage, @RAMMargins) =
+                    CMD_GetRAMUsage($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc);
+    my $nActualRAMSize = $nRAMUsage;
+    my $i = 0;
+    PrintLog($PrintFunc, "ActualRAMSize = ".CommonUtil::Dec2Hex($nActualRAMSize)." = $nActualRAMSize(Bytes)\n");
+    my $nExpectedRAMSize = $nRAMUsage ; #+ $nRAMMargin + $nRAMMargin1;
+    
+    foreach my $nRAMMargin (@RAMMargins)
+    {
+        $i += 1;
+        PrintLog($PrintFunc, "RAM Margin $i ".CommonUtil::Dec2Hex($nRAMMargin)." = $nRAMMargin(Bytes)\n");
+    }
+    PrintLog($PrintFunc, "ExpectedRAMSize = ".CommonUtil::Dec2Hex($nExpectedRAMSize)." = $nExpectedRAMSize(Bytes)\n");
+    return $nExpectedRAMSize;
+}
+
+sub GetTotalRAMUsageFromLDS
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my $strRAM_Length = LinkerOutputParser::Get_DUMMY_END_Base();
+    return hex($strRAM_Length);
+}
+
+sub CMD_GetPhysicalRAMUsage
+{
+    my ($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, $PrintFunc) = @_;
+    my $nExepectedROMSize = GetExpectedROMSize($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, undef);
+    my $nExpectedRAMSize = GetExpectedRAMSize($MAKEFILE_PATH, $IMAGELAYOUT_PATH, $MAP_PATH, $SYM_PATH, undef);
+    my $nPRAMUsage = $nExepectedROMSize + $nExpectedRAMSize;
+    PrintLog($PrintFunc, "Total Physical RAMUsage(ROM + RAM) = ".CommonUtil::Dec2Hex($nExepectedROMSize)." + ".
+             CommonUtil::Dec2Hex($nExpectedRAMSize)." = ". CommonUtil::Dec2Hex($nPRAMUsage) ."\n");
+    return $nPRAMUsage ;
+}
+
+sub wait_for_reuse
+#sub GetReservedSize
+{
+    my ($IMAGELAYOUT_PATH, $SYM_PATH, $MAKEFILE_PATH) = @_;
+    my @ERinRAM;
+    my $BB_PATH = dirname($IMAGELAYOUT_PATH);
+    sysInfo::GetRAMregion($BB_PATH, $IMAGELAYOUT_PATH, \@ERinRAM, \%g_MAKEFILE_OPTIONS);
+    my $FixedER_aref = &sysInfo::FilterOutFixedRegion(\@ERinRAM, \%g_MAKEFILE_OPTIONS);
+
+    #######################
+    # FIX_ME, what is the reserve size?
+    #######################
+
+#    my $nReservedSize = 0;
+#    foreach my $ER (@$FixedER_aref)
+#    {
+#        my $strSize = sysInfo::GetRegionInfo($ER, Region::MaxSize, $IMAGELAYOUT_PATH, \%g_MAKEFILE_OPTIONS);
+#        $nReservedSize += hex($strSize);
+#    }
+#    return $nReservedSize;
+}
+
+
+sub PrintLog
+{
+    my ($LogFunc, $strLog) = @_;
+    &{$LogFunc}($strLog) if(exists &{$LogFunc});
+}
+#****************************************************************************
+# Subroutine:  basicinfo_die
+# Parameters:  1. string error message, 2. __FILE__ 3. __LINE__
+# Returns:     x
+#****************************************************************************
+sub basicinfo_die
+{
+    my ($error_msg, $file, $line_no) = @_;
+    my $pack_name = undef;
+    if(!defined $file or !defined $line_no)
+    {
+        ($pack_name, $file, $line_no) = caller;    
+    }
+    &CommonUtil::error_handler($error_msg, $file, $line_no, 'BasicMemInfoPcore');    
+}
+
+sub get_physical_address
+{
+    my ($address) = @_;
+    my $addr_mask = 0x0fffffff;
+    my $bank = $address>>28;
+    if (($bank == 1) || ($bank == 7)) 
+    {
+        $addr_mask = 0x1fffffff;
+    }
+    return ($address & $addr_mask);
+  }
diff --git a/mcu/tools/MemoryUtility/ChkMemUsage.pl b/mcu/tools/MemoryUtility/ChkMemUsage.pl
new file mode 100644
index 0000000..f433c0c
--- /dev/null
+++ b/mcu/tools/MemoryUtility/ChkMemUsage.pl
@@ -0,0 +1,184 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   ChkMemUsage.pl

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   This perl is used to check memory usage. 

+#*   If the memory usage is more than 95%, then warning is send back. 

+#*       

+#*

+#* Author:

+#* -------

+#*   I-Chun Liu (mtk06123)

+#*

+#****************************************************************************/

+

+BEGIN { push @INC, '../', './tools/', './tools/MemoryUtility/' }  # add additional library path

+use systemInfo;

+use LinkerOutputParser;

+use CommonUtility;

+use FileInfoParser;

+use BasicMemInfoQuery;

+use strict;

+

+#****************************************************************************

+# Constants

+#****************************************************************************

+my $ChkMemUsage_VERNO     = " u0.01";

+             # u0.01 , 2015/01/19,  Initial revision for Memory Utility Refinement

+             # m0.01 , 2014/02/26,  Initial revision

+

+#****************************************************************************

+# Global variable

+#****************************************************************************

+my $DebugPrint = 0;

+

+#****************************************************************************

+# Subroutine:  ChkMemUsage_verno - to query this package's version number

+# Parameters:  x

+# Returns:     version number string

+#****************************************************************************

+sub ChkMemUsage_verno

+{

+    return $ChkMemUsage_VERNO;

+}

+

+#****************************************************************************

+# 1 >>>  Get in put parameters

+#****************************************************************************

+&Usage() if($#ARGV != 3);

+my ($makeFile, $lds_path, $map_path, $sym_path) = @ARGV;

+

+#****************************************************************************

+# 2 >>>  Parse make file

+#****************************************************************************

+my %MAKEFILE_OPTIONS;

+&FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS);

+

+#****************************************************************************

+# 3 >>>  ChkMemUsage

+#****************************************************************************

+&ChkMemUsage();

+

+#****************************************************************************

+# oo >>>  Finished

+#****************************************************************************

+exit 0;

+

+#****************************************************************************

+# subroutine:  ChkMemUsage - Check memory usage. If the memory usage is more than 95%, then warning is send back. 

+# Input:       x

+# Output:      x

+#****************************************************************************

+sub ChkMemUsage

+{

+    my $nPRAMUsage = 0;

+    my $nPRAM = 0;

+    my $threshold_val = 0;

+	my $percentage = 95; #95%

+	my $current_percentage = 0 ;

+	

+	my $platform = &FileInfo::get("PLATFORM", \%MAKEFILE_OPTIONS);

+	print "platform = $platform\n";

+	

+	my $coprocessor = &FileInfo::is_with_AP(\%MAKEFILE_OPTIONS);

+	print "isWithAP = $coprocessor\n";

+

+	#get ram size 

+

+	if($platform =~ /MT6595/) #MT6595

+	{

+		$nPRAM = 0x6000000; #96M

+		print "MT6595 memory size = $nPRAM\n";			

+	}

+	

+	else #MT6280, MT6290

+	{

+    	$nPRAM = BasicMemInfo::DispatchCommand("GetTotalRAMUsageFromLDS", $makeFile, $lds_path, $map_path, $sym_path, undef);

+		print "RAMUsageFromLDS = $nPRAM\n";

+	}

+

+	#set threshold size

+	$threshold_val = ($nPRAM * $percentage)/100 ; 

+	print "Threshold_val = $threshold_val\n";

+

+	#get current usage size

+    $nPRAMUsage = BasicMemInfo::DispatchCommand("CMD_GetPhysicalRAMUsage", $makeFile, $lds_path, $map_path, $sym_path, undef);

+    print "RAM usage = $nPRAMUsage\n";

+

+	#calculate current usage percentage

+	$current_percentage = ($nPRAMUsage * 100)/$nPRAM ;

+	my $current_percentage = sprintf "%.2f", $current_percentage;

+	print "Current usage: $current_percentage%\n";

+	

+    if ($nPRAMUsage >= $threshold_val && $threshold_val != 0)

+    {

+        #send warning

+        print "Warning: The memory usage is $nPRAMUsage over the memory usage threshold $threshold_val which is $percentage% of RAM size !\n";    

+    }

+    else

+    {

+    	print "Memory usage check OK!\n";

+    }

+}

+

+#****************************************************************************

+# subroutine:  Usage - usage template

+# Input:       x

+# Output:      x

+#****************************************************************************

+sub Usage

+{

+  print <<"__EOFUSAGE";

+

+usage: perl ChkMemUsage.pl makefile_path lds_file_path map_file_path sym_file_path 

+

+e.g. 

+perl ChkMemUsage.pl "/[path]/~MT6290E2_EVB(LWG).mak" "/[path]/ldsMT6290E2_EVB.txt" "/[path]/MT6290E2_EVB_PCB01_MT6290_S01.map" "/[path]/MT6290E2_EVB_PCB01_MT6290_S01.sym"

+

+__EOFUSAGE

+

+  exit 1;

+}

+

diff --git a/mcu/tools/MemoryUtility/CompareLibrarySize.pl b/mcu/tools/MemoryUtility/CompareLibrarySize.pl
new file mode 100644
index 0000000..0094902
--- /dev/null
+++ b/mcu/tools/MemoryUtility/CompareLibrarySize.pl
@@ -0,0 +1,235 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   CompareLibrarySize.pl

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   

+#* 

+#*

+#* Author:

+#* -------

+#*   Carl Kao (mtk08237)

+#*

+#*------------------------------------------------------------------------------

+#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!

+#*============================================================================

+#****************************************************************************/

+use strict;

+BEGIN { push @INC, "./" , '../', './tools/', './tools/MemoryUtility/' }

+use LinkerOutputParser;

+use File::Basename;

+

+&Usage() if ($#ARGV != 1); 

+

+my ($file1, $file2) = @ARGV;

+$file1 =~ s/\\/\\\\/;

+$file2 =~ s/\\/\\\\/;

+

+my ($libs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href, $libs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href, $maxlength);

+

+if(($file1 =~ /\.map$/) && ($file2 =~ /\.map$/))

+{

+	($libs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href) = &GetAllLibs($file1);

+	($libs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href) = &GetAllLibs($file2);

+}

+else

+{

+	&Usage();

+}

+

+my @libs1 = @$libs1_aref;

+my @libs2 = @$libs2_aref;

+

+my %libs1 = map{$_ => 1} @libs1;

+my %libs2 = map{$_ => 1} @libs2;

+

+my @inter = grep {$libs1{$_}} @libs2;

+

+my %merge = map {$_ => 1} @libs1,@libs2; 

+my @merge = sort keys (%merge);

+

+my @libs1_only = grep {!$libs2{$_}} @merge;

+my @libs2_only = grep {!$libs1{$_}} @merge;

+

+print "Compare result as below:\n";

+

+    printf "*" x ($maxlength+105) . "\n";

+    printf ("%-${maxlength}s%-35s%-35s\n"," ","Codebase1","Codebase2");

+    printf ("%-${maxlength}s%-35s%-35s%-35s\n","LibraryName","ROSize;RWSize;ZISize","ROSize;RWSize;ZISize","ROSize;RWSize;ZISize");

+    printf "*" x ($maxlength+105) . "\n";

+

+	my $total_RO_1 = 0;

+	my $total_RW_1 = 0;

+	my $total_ZI_1 = 0;

+	my $total_RO_2 = 0;

+	my $total_RW_2 = 0;

+	my $total_ZI_2 = 0;

+	my $total_RO_diff = 0;

+	my $total_RW_diff = 0;

+	my $total_ZI_diff = 0;

+	my $total_codebase1;

+	my $total_codebase2;

+	my $total_diff;

+		

+	foreach my $lib(@merge)

+	{

+		$$RO_2_href{$lib} = 0 if(!defined $$RO_2_href{$lib});

+		$$RO_1_href{$lib} = 0 if(!defined $$RO_1_href{$lib});

+		$$RW_2_href{$lib} = 0 if(!defined $$RW_2_href{$lib});

+		$$RW_1_href{$lib} = 0 if(!defined $$RW_1_href{$lib});

+		$$ZI_2_href{$lib} = 0 if(!defined $$ZI_2_href{$lib});

+		$$ZI_1_href{$lib} = 0 if(!defined $$ZI_1_href{$lib});

+		

+		my $RO_diff = $$RO_2_href{$lib} - $$RO_1_href{$lib};

+		my $RW_diff = $$RW_2_href{$lib} - $$RW_1_href{$lib};

+		my $ZI_diff = $$ZI_2_href{$lib} - $$ZI_1_href{$lib};

+

+		my $codebase1 = $$RO_1_href{$lib}.";".$$RW_1_href{$lib}.";".$$ZI_1_href{$lib};

+		my $codebase2 = $$RO_2_href{$lib}.";".$$RW_2_href{$lib}.";".$$ZI_2_href{$lib};

+		my $diff = $RO_diff.";".$RW_diff.";".$ZI_diff;

+		

+		$total_RO_1 += $$RO_1_href{$lib};

+		$total_RW_1 += $$RW_1_href{$lib};

+		$total_ZI_1 += $$ZI_1_href{$lib};

+		

+		$total_RO_2 += $$RO_2_href{$lib};

+		$total_RW_2 += $$RW_2_href{$lib};

+		$total_ZI_2 += $$ZI_2_href{$lib};

+		

+		$total_RO_diff += $RO_diff;

+		$total_RW_diff += $RW_diff;

+		$total_ZI_diff += $ZI_diff;

+	

+		$total_codebase1 = $total_RO_1.";".$total_RW_1.";".$total_ZI_1;

+		$total_codebase2 = $total_RO_2.";".$total_RW_2.";".$total_ZI_2;

+	    $total_diff = $total_RO_diff.";".$total_RW_diff.";".$total_ZI_diff;

+			

+        printf ("%-${maxlength}s%-35s%-35s%-35s\n",$lib,$codebase1,$codebase2,$diff);

+

+	}

+

+    printf ("%-${maxlength}s%-35s%-35s%-35s\n","Total",$total_codebase1,$total_codebase2,$total_diff);

+    printf "*" x ($maxlength+105) . "\n";

+

+

+sub GetAllLibs

+{

+	my ($file) = @_;

+	my $symfile = $file;

+	my $exeregion_aref;

+	

+	if($file =~ /\.map$/)

+	{

+		$symfile =~ s/map/sym/;

+		if(!-f $symfile)

+        {

+            my $file = basename($symfile);

+            my $dirname  = dirname($symfile);

+            $symfile = $dirname."\/dummy_$file";

+        }

+		&LinkerOutputParser::FileParse($symfile);

+	}

+	&LinkerOutputParser::FileParse($file);

+	$exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1);

+

+	my %libs = ();

+	my @uni_libs = ();

+	my %RO_Size = ();

+	my %RW_Size = ();

+	my %ZI_Size = ();

+	

+	if (defined $exeregion_aref)

+	{

+		foreach my $temp(@$exeregion_aref)

+		{

+			my $lib_aref = &LinkerOutputParser::GetLibByExeRegion($temp);

+			if (defined $lib_aref)

+			{

+				foreach (@$lib_aref)

+				{

+					map { $libs{$_} = 1} @$lib_aref;

+				}

+			}

+		}

+	}

+	

+	foreach my $lib(keys %libs)

+	{

+	    push (@uni_libs, $lib);

+		my ($nRO_Size, $nRW_Size, $nZI_Size) = (0,0,0);

+		

+        if($file1 =~ /\.map$/)

+		{

+			$nRO_Size = &LinkerOutputParser::ListLibSummaryInfo($lib, "RO");

+			$nRW_Size = &LinkerOutputParser::ListLibSummaryInfo($lib, "RW");

+			$nZI_Size = &LinkerOutputParser::ListLibSummaryInfo($lib, "ZI");

+			$RO_Size{$lib} = $nRO_Size;

+			$RW_Size{$lib} = $nRW_Size;

+		    $ZI_Size{$lib} = $nZI_Size;

+		    $maxlength = $maxlength > length($lib) ? $maxlength:length($lib);

+		}

+	}

+	

+	$maxlength += 10;

+	return (\@uni_libs, \%RO_Size, \%RW_Size, \%ZI_Size);

+}

+

+

+sub Usage

+{

+  print <<"__EOFUSAGE";

+

+usage: perl CompareLibrarySize.pl map_file_path1 map_file/path2

+

+map_file_path1: map file path for codebase1 you want to compare

+map_file_path2: map file path for codebase2 you want to compare

+

+e.g. perl CompareLibrarySize.pl "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map" "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map"

+

+Note: 

+For GCC linker output, there should be corresponding .sym file in the same folder of .map file.

+

+__EOFUSAGE

+  exit 1;

+}

diff --git a/mcu/tools/MemoryUtility/CompareObjSize.pl b/mcu/tools/MemoryUtility/CompareObjSize.pl
new file mode 100644
index 0000000..9fa575d
--- /dev/null
+++ b/mcu/tools/MemoryUtility/CompareObjSize.pl
@@ -0,0 +1,252 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   CompareObjSize.pl

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   

+#* 

+#*

+#* Author:

+#* -------

+#*   Carl Kao (mtk08237)

+#*

+#*------------------------------------------------------------------------------

+#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!

+#*============================================================================

+#****************************************************************************/

+use strict;

+BEGIN { push @INC, "./" , '../', './tools/', './tools/MemoryUtility/' }

+use LinkerOutputParser;

+use File::Basename;

+

+&Usage() if ($#ARGV != 1); 

+

+my ($file1, $file2) = @ARGV;

+$file1 =~ s/\\/\\\\/;

+$file2 =~ s/\\/\\\\/;

+

+my ($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href, $objs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href, $maxlength);

+

+if(($file1 =~ /\.lis$/) && ($file2 =~ /\.lis$/) or ($file1 =~ /\.map$/) && ($file2 =~ /\.map$/))

+{

+	($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href) = &GetAllOBJs($file1);

+	($objs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href) = &GetAllOBJs($file2);

+}

+else

+{

+	&Usage();

+}

+

+my @objs1 = @$objs1_aref;

+my @objs2 = @$objs2_aref;

+

+my %objs1 = map{$_ => 1} @objs1;

+my %objs2 = map{$_ => 1} @objs2;

+

+my @inter = grep {$objs1{$_}} @objs2;

+

+my %merge = map {$_ => 1} @objs1,@objs2; 

+my @merge = sort keys (%merge);

+

+my @objs1_only = grep {!$objs2{$_}} @merge;

+my @objs2_only = grep {!$objs1{$_}} @merge;

+

+print "Compare result as below:\n";

+

+    printf "*" x ($maxlength+105) . "\n";

+    printf ("%-${maxlength}s%-35s%-35s\n"," ","Codebase1","Codebase2");

+    printf ("%-${maxlength}s%-35s%-35s%-35s\n","ObjectName","ROSize;RWSize;ZISize","ROSize;RWSize;ZISize","ROSize;RWSize;ZISize");

+    printf "*" x ($maxlength+105) . "\n";

+

+	my $total_RO_1 = 0;

+	my $total_RW_1 = 0;

+	my $total_ZI_1 = 0;

+	my $total_RO_2 = 0;

+	my $total_RW_2 = 0;

+	my $total_ZI_2 = 0;

+	my $total_RO_diff = 0;

+	my $total_RW_diff = 0;

+	my $total_ZI_diff = 0;

+	my $total_codebase1;

+	my $total_codebase2;

+	my $total_diff;

+		

+	foreach my $obj(@merge)

+	{

+		$$RO_2_href{$obj} = 0 if(!defined $$RO_2_href{$obj});

+		$$RO_1_href{$obj} = 0 if(!defined $$RO_1_href{$obj});

+		$$RW_2_href{$obj} = 0 if(!defined $$RW_2_href{$obj});

+		$$RW_1_href{$obj} = 0 if(!defined $$RW_1_href{$obj});

+		$$ZI_2_href{$obj} = 0 if(!defined $$ZI_2_href{$obj});

+		$$ZI_1_href{$obj} = 0 if(!defined $$ZI_1_href{$obj});

+		

+		my $RO_diff = $$RO_2_href{$obj} - $$RO_1_href{$obj};

+		my $RW_diff = $$RW_2_href{$obj} - $$RW_1_href{$obj};

+		my $ZI_diff = $$ZI_2_href{$obj} - $$ZI_1_href{$obj};

+

+		my $codebase1 = $$RO_1_href{$obj}.";".$$RW_1_href{$obj}.";".$$ZI_1_href{$obj};

+		my $codebase2 = $$RO_2_href{$obj}.";".$$RW_2_href{$obj}.";".$$ZI_2_href{$obj};

+		my $diff = $RO_diff.";".$RW_diff.";".$ZI_diff;

+		

+		$total_RO_1 += $$RO_1_href{$obj};

+		$total_RW_1 += $$RW_1_href{$obj};

+		$total_ZI_1 += $$ZI_1_href{$obj};

+		

+		$total_RO_2 += $$RO_2_href{$obj};

+		$total_RW_2 += $$RW_2_href{$obj};

+		$total_ZI_2 += $$ZI_2_href{$obj};

+		

+		$total_RO_diff += $RO_diff;

+		$total_RW_diff += $RW_diff;

+		$total_ZI_diff += $ZI_diff;

+

+		$total_codebase1 = $total_RO_1.";".$total_RW_1.";".$total_ZI_1;

+		$total_codebase2 = $total_RO_2.";".$total_RW_2.";".$total_ZI_2;

+	    $total_diff = $total_RO_diff.";".$total_RW_diff.";".$total_ZI_diff;

+	    

+        printf ("%-${maxlength}s%-35s%-35s%-35s\n",$obj,$codebase1,$codebase2,$diff);

+

+	}

+

+    printf ("%-${maxlength}s%-35s%-35s%-35s\n","Total",$total_codebase1,$total_codebase2,$total_diff);

+    printf "*" x ($maxlength+105) . "\n";

+

+

+sub GetAllOBJs

+{

+	my ($file) = @_;

+	my $symfile = $file;

+	my $exeregion_aref;

+	

+	if($file =~ /\.map$/)

+	{

+		$symfile =~ s/map/sym/;

+		if(!-f $symfile)

+        {

+            my $file = basename($symfile);

+            my $dirname  = dirname($symfile);

+            $symfile = $dirname."\/dummy_$file";

+        } 

+		&LinkerOutputParser::FileParse($symfile);

+	}

+	&LinkerOutputParser::FileParse($file);

+	$exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1);

+	

+

+	my @objs = ();

+	my @uni_objs = ();

+	my %RO_Size;

+	my %RW_Size;

+	my %ZI_Size;

+	my %RWZI_Size;

+	my %count;

+	

+	if (defined $exeregion_aref)

+	{

+		foreach my $temp(@$exeregion_aref)

+		{

+			my $obj_aref = &LinkerOutputParser::GetObjByExeRegion($temp);

+			if (defined $obj_aref)

+			{

+				foreach (@$obj_aref)

+				{

+					push(@objs, $_);

+				}

+			}

+		}

+	}

+	

+	@uni_objs = grep { ++$count{ $_ } < 2; } @objs; 

+	$maxlength = 0;

+	

+	foreach my $obj(@uni_objs)

+	{

+		my ($nRO_Size, $nRW_Size, $nZI_Size) = (0,0,0);

+		

+		if($file1 =~ /\.lis$/)

+		{

+			$nRO_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "RO Data") + &LinkerOutputParser::ListObjSummaryInfo($obj, "Code");

+			$nRW_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "RW Data");

+			$nZI_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "ZI Data");

+			$RO_Size{$obj} = $nRO_Size;

+			$RW_Size{$obj} = $nRW_Size;

+		    $ZI_Size{$obj} = $nZI_Size;

+		    $maxlength = $maxlength > length($obj) ? $maxlength:length($obj);

+		}

+		elsif($file1 =~ /\.map$/)

+		{

+			$nRO_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "RO");

+			$nRW_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "RW");

+			$nZI_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "ZI");

+			$RO_Size{$obj} = $nRO_Size;

+			$RW_Size{$obj} = $nRW_Size;

+		    $ZI_Size{$obj} = $nZI_Size;

+		    $maxlength = $maxlength > length($obj) ? $maxlength:length($obj);

+		}	

+	}

+	

+	$maxlength += 10;

+	return (\@uni_objs, \%RO_Size, \%RW_Size, \%ZI_Size);

+}

+

+

+sub Usage

+{

+  print <<"__EOFUSAGE";

+

+usage: perl CompareobjrarySize.pl lis/map_file_path1 lis/map_file/path2

+

+lis/map_file_path1: lis/map file path for codebase1 you want to compare

+lis/map_file_path2: lis/map file path for codebase2 you want to compare

+

+lis/map_file_path1, lis/map_file_path2 should be the same file type (both .lis file or both .map file, comparison between .lis and .map is not supported)

+

+e.g. perl CompareobjrarySize.pl "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map" "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map"

+

+Note: 

+For GCC linker output, there should be corresponding .sym file in the same folder of .map file.

+

+__EOFUSAGE

+  exit 1;

+}

diff --git a/mcu/tools/MemoryUtility/DetectZI.pl b/mcu/tools/MemoryUtility/DetectZI.pl
new file mode 100644
index 0000000..72ae72c
--- /dev/null
+++ b/mcu/tools/MemoryUtility/DetectZI.pl
@@ -0,0 +1,425 @@
+#!/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) 2006
+#
+#  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:
+#* ---------
+#*   DetectZI.pl
+#*
+#* Project:
+#* --------
+#*
+#*
+#* Description:
+#* ------------
+#*   This perl is used to detect ZI which be declared as RW
+#*       
+#*
+#* Author:
+#* -------
+#*   Cark Kao (mtk08237)
+#*
+#****************************************************************************/
+
+BEGIN { push @INC, '../', './tools/', './tools/MemoryUtility/' }
+
+use strict;
+use File::Basename;
+use LinkerOutputParser;
+use CommonUtility;
+
+use constant EXEC_VIEW => 0;
+use constant LOAD_VIEW => 1;
+
+
+my $nVerion = "v1.10";
+             # v1.10 , 20160303 , Tero , Search RW sections from symbol file. Removed var and obj info hash table init.
+             # v1.09 , 20151105 , Carl , Change DSP TX/RX sections to ZI (.bss) section
+             # v1.08 , 20151030 , Carl , Parsing ELF file instead of parsing BIN file since there is CCCI header in front of bin file
+             # v1.07 , 20150918 , Carl , Modify for LR11
+             # v1.06 , 20150121 , Carl , Calaulate ROM base for L1core
+             # v1.05 , 20150121 , Carl , Add shared region to serach sections 
+             # v1.04 , 20150119 , Carl , Memory Utility Refinement
+             # v1.03 , 20141022 , Carl , Remove DSP section since they are ZI now
+             # v1.02 , 20140910 , Carl , Add symbol filter 
+             # v1.01 , 20140909 , Carl , Reduce parsing time of map, sym file for speedup
+             # v1.00 , 20140827 , Carl , Init version
+
+
+
+#################################################################
+#############  Configurable variable are list below  ############
+#################################################################
+
+# serach sections
+my @aSection;
+# filter-out symbol file
+my($filename, $dirs, $suffix) = fileparse($0);
+my $strSymbolFilterFilePath =  $dirs."config/detectZI_filter.txt";
+
+#################################################################
+#################################################################
+#################################################################
+
+
+
+# 1. input sym, map, bin file
+
+&Usage() if ($#ARGV < 2); 
+
+my ($sym_file, $map_file, $elf_file, $gnZIpercent, $gnZIthreshold) = @ARGV;
+
+$gnZIpercent = 100 if( $gnZIpercent eq "" );
+$gnZIthreshold = 0 if( $gnZIthreshold eq "" );
+
+$sym_file =~ s/\\/\\\\/;
+$map_file =~ s/\\/\\\\/;
+$elf_file =~ s/\\/\\\\/;
+
+print "project info: $map_file\n\n";
+
+
+# 2. main().  lisr all RW sections
+
+my $nTotalZI;
+my %var_info;  # var_name => [ var size, obj name, section name ]
+my %obj_info;  # obj_name  => [ total ZI var size, var_1, var_2, ... ]
+my %filter_out_symbol;
+my $gnROMBase;
+
+#&GenROMBase();
+
+&take_filter_out_symbol();
+
+&process_with_value(100,0) if ( 100==$gnZIpercent );
+&process_with_value($gnZIpercent, $gnZIthreshold) if ( 100!=$gnZIpercent );
+
+
+sub take_filter_out_symbol()
+{
+    my $strContent = CommonUtil::GetFileContent($strSymbolFilterFilePath);
+    my @symbol = split(/\s/, $strContent);
+
+    # note that  we also take the "commont" as filter out symbol
+    foreach (@symbol)
+    {
+        $filter_out_symbol{$_} = 1;
+    }
+}
+
+sub init_Glob()
+{
+    $nTotalZI=0;
+}
+
+sub process_with_value
+{
+    &init_Glob();
+
+    my ($nZIpercent, $nZIthreshold) = @_;
+
+    print "==============================================================\n";
+    print "=====nZIpercent: $nZIpercent, nZIthreshold: $nZIthreshold=====\n";
+    print "==============================================================\n";
+
+
+    my %sectionInfo;
+    LinkerOutputParser::FileParse($sym_file);
+    my $allSections = &LinkerOutputParser::ListAllExeRegion(1);
+    print "\nData load sections:\n";
+    foreach my $Section (@$allSections)
+      {
+	my $secinfo = LinkerOutputParser::GetExeRegionInfo($Section,Region::Attr);
+	if (($secinfo =~ /LOAD/) and ($secinfo =~ /DATA/))
+	  {
+	    print "$Section\n";
+	    push @aSection, $Section;
+	  }
+      }
+    print "\n";
+    if( 100 == $nZIpercent ) {
+        print("Section\tObj_file\tSymbol\tSize\n");
+    } else {
+        print("Section\tObj_file\tSymbol\tSymbol_size\tZI_Size\tRW_Size\tZI_percent\n");
+    }
+
+    foreach my $strSection (@aSection)
+    {
+        # (1) get base of load/execution address of section
+        my $nSectionElfOffset = hex(LinkerOutputParser::GetExeRegionInfo($strSection, Region::Offsets));
+        my $nSectionExecAddr = hex(LinkerOutputParser::GetExeRegionInfo($strSection, Region::VMA));
+
+        # (2) get all symbol in section
+        #[[SymbolName, address, size], ...] sorted by address
+        my $temp1_aref = LinkerOutputParser::GrepSymbolBySection("$strSection");
+
+        push @{$sectionInfo{$strSection}}, $nSectionElfOffset, $nSectionExecAddr, $temp1_aref;
+    }
+
+
+    LinkerOutputParser::FileParse($map_file);
+    foreach my $strSection (@aSection)
+    {
+        &detectZI($strSection, $nZIpercent, $nZIthreshold,
+            $sectionInfo{$strSection}[0],
+            $sectionInfo{$strSection}[1],
+            $sectionInfo{$strSection}[2]);
+    }
+    print "total ZI: $nTotalZI \n";
+
+    &print_result_by_var_size();
+    &print_result_by_obj_size();
+}
+
+
+# 3. start process section X
+
+sub detectZI
+{  
+    my ($strSection, $nZIpercent, $nZIthreshold,
+        $nSectionElfOffset, $nSectionExecAddr, $temp1_aref) = @_;
+
+    # (3) open file
+
+    open (ELF_FILE_HANDLE, "<$elf_file") or &detectZI_die("[1.0] no elf file $elf_file");
+    binmode ELF_FILE_HANDLE;
+
+    # (4) for each symbol in section
+    foreach my $item (@$temp1_aref)
+    {
+        my $strVarName = @$item[SymTable::Name];
+        my $nVarAddr = hex(@$item[SymTable::Addr]);
+        my $nVarSize = @$item[SymTable::Size];
+        my $nVarAddrInElf = $nVarAddr - $nSectionExecAddr + $nSectionElfOffset;
+        # print "\t$strVarName, $nVarAddr, $nVarSize, $nVarAddrInElf, $nOffset \n";
+
+        next if (0 == $nVarSize || defined $filter_out_symbol{$strVarName} );
+
+        # <1> read content of symbol: {load address, load address+length}
+        # <2> if only zeros in the content, report it shoulbe be a ZI data
+
+        my ($bDetectZI, $nSeekLen, $nVarRWSize, $nVarZISize, $nVarZIpercent) = (1,0,0,0,0);
+
+        seek ELF_FILE_HANDLE, $nVarAddrInElf, 0;
+        for ( ; $nSeekLen < $nVarSize && (1==$bDetectZI||100!=$nZIpercent) ; ++$nSeekLen ) 
+        {
+            my ($nReadLen, $nData, $strData);
+            $nReadLen = read ELF_FILE_HANDLE, $nData, 1;
+            $strData = sprintf($nData);
+            if( "\c@" ne $strData )
+            {
+                $bDetectZI = 0; 
+                $nVarRWSize++;
+            }
+        }
+
+        $nVarZISize = $nVarSize - $nVarRWSize;
+        $nVarZIpercent = $nVarZISize/$nVarSize*100;
+
+        if( $nZIpercent != 100 )
+        {
+            $bDetectZI = 1 if( 0 == $bDetectZI 
+                            && $nVarZIpercent >= $nZIpercent
+                            && $nVarSize >= $nZIthreshold );
+
+            # no not show again
+            $bDetectZI = 0 if( 100==$nVarZIpercent);
+        }
+
+        if ( 1 eq $bDetectZI )
+        {
+            my $refObj = LinkerOutputParser::GetParentOfSymbol($strVarName, "obj");
+            my $strObjName = (defined $refObj?@$refObj[0]:"not_found");
+
+            # warning, we do not process the case: more than one symbol with same name 
+            push @{$var_info{$strVarName}}, $nVarSize, $nVarZISize, $strObjName, $strSection;
+
+            if( !defined $obj_info{$strObjName } ){
+                push @{$obj_info{$strObjName}}, $nVarSize, $nVarZISize;
+            }else{
+                $obj_info{$strObjName}[0] += $nVarSize;
+                $obj_info{$strObjName}[1] += $nVarZISize;
+            }
+            push @{$obj_info{$strObjName}}, $strVarName;
+
+            print((defined $refObj?$strSection:"not_found_in_map_file"));
+            print("\t$strObjName\t$strVarName\t$nVarSize");
+            print(($nZIpercent != 100?"\t$nVarZISize\t$nVarRWSize\t$nVarZIpercent\n":"\n"));
+
+            $nTotalZI += $nVarSize;
+        }
+
+    }
+
+}
+
+
+sub print_result_by_var_size()
+{
+    return if (!%var_info); #No ZI variables
+    # sort by ZI size
+    my @list = sort { $var_info{$b}[1] <=> $var_info{$a}[1] } keys %var_info;
+
+    print "\n\n-->sort by symbol ZI size<--\n\n";
+
+    if( 100 == $gnZIpercent ) 
+    {
+        print("Symbol\tSize\tObj_file\tSection\n");
+        foreach my $strVarName (@list)
+        {
+            my $nVarSize   = $var_info{$strVarName}[0];
+            my $strObjName = $var_info{$strVarName}[2];
+            my $strSection = $var_info{$strVarName}[3];
+
+            print "$strVarName\t$nVarSize\t$strObjName\t$strSection\n";
+        }
+    }
+    else
+    {
+        print("Symbol\tSymbol_size\tZI_Size\tRW_Size\tZI_percent\tObj_file\tSection\t\n");
+        foreach my $strVarName (@list)
+        {
+            my $nVarSize      = $var_info{$strVarName}[0];
+            my $nVarZISize    = $var_info{$strVarName}[1];
+            my $strObjName    = $var_info{$strVarName}[2];
+            my $strSection    = $var_info{$strVarName}[3];
+
+            next if( !defined $nVarSize );
+            my $nVarRWSize    = $nVarSize - $nVarZISize; 
+            my $nVarZIpercent = $nVarZISize/$nVarSize*100; 
+
+            print "$strVarName\t$nVarSize\t$nVarZISize\t$nVarRWSize\t$nVarZIpercent\t$strObjName\t$strSection\n";
+        }
+        
+    }
+}
+
+sub print_result_by_obj_size()
+{
+    return if (!%obj_info); #No obj info
+    # sort by ZI size
+    my @list = sort { $obj_info{$b}[1] <=> $obj_info{$a}[1] } keys %obj_info;
+
+    print "\n\n-->sort by obj ZI size<--\n\n";
+
+    if( 100 == $gnZIpercent ) 
+    {
+        print("Obj file\tSymbol\tVar size\tSize of total ZI in obj\n");
+        foreach my $strObjName (@list)
+        {
+            my $nObjZiSize  = $obj_info{$strObjName}[0];
+        
+            print "$strObjName\t \t \t$nObjZiSize\n";
+ 
+            for( my $i=2; $i<= $#{$obj_info{$strObjName}}; ++$i )
+            {
+                my $strVarName = $obj_info{$strObjName}[$i];
+                my $nVarSize = $var_info{$strVarName}[0];
+                print "\t$strVarName\t$nVarSize\n";
+            }
+        }
+    }
+    else
+    {
+        print("Obj file\tSymbol\tSymbol_size\tZI_Size\tRW_Size\tZI_percent\tSection\t\n");
+        foreach my $strObjName (@list)
+        {
+            my $nObjZiSize  = $obj_info{$strObjName}[0];
+        
+            print "$strObjName\tsize:$nObjZiSize\n";
+ 
+            for( my $i=2; $i<=$#{$obj_info{$strObjName}}; ++$i )
+            {
+                my $strVarName = $obj_info{$strObjName}[$i];
+                my $nVarSize   = $var_info{$strVarName}[0];
+                my $nVarZISize = $var_info{$strVarName}[1];
+                my $strSection = $var_info{$strVarName}[3];
+
+                next if( !defined $nVarSize );
+                my $nVarRWSize    = $nVarSize - $nVarZISize; 
+                my $nVarZIpercent = $nVarZISize/$nVarSize*100; 
+
+                print "\t $strVarName\t$nVarSize\t$nVarZISize\t$nVarRWSize\t$nVarZIpercent\t$strSection\n";
+            }
+        }
+
+    }
+}
+
+#calculate ROM base for L1core
+sub GenROMBase
+{
+    LinkerOutputParser::FileParse($sym_file);
+    my $ERs_aref = &LinkerOutputParser::ListAllExeRegion(1);
+    &detectZI_die("no any section?!") if( scalar(@$ERs_aref)==0 );
+    $gnROMBase = hex(&LinkerOutputParser::GetExeRegionInfo($ERs_aref->[0], Region::LMA));    
+}
+
+sub detectZI_die
+{
+    my ($error_msg, $file, $line_no) = @_;
+    my $pack_name = undef;
+    if(!defined $file or !defined $line_no)
+    {
+        ($pack_name, $file, $line_no) = caller;    
+    }
+    &CommonUtil::error_handler($error_msg, $file, $line_no, 'detectZI');    
+}
+
+
+sub Usage
+{
+  print "version: $nVerion\n";
+  print <<"__EOFUSAGE";
+usage: perl $0  sym_file  map_file  elf_file ZI_percent ZI_threshold
+e.g. perl  ./tools/MemoryUtility/DetectZI.pl \
+        ./build/PROHECT_NAME/FLAVOR/bin/AAA.sym \
+        ./build/PROHECT_NAME/FLAVOR/bin/AAA.map \
+        ./build/PROHECT_NAME/FLAVOR/bin/AAA.elf
+        100 \
+        0 \
+
+e.g. perl  ./tools/MemoryUtility/DetectZI.pl \
+        ./build/PROHECT_NAME/FLAVOR/bin/AAA.sym \
+        ./build/PROHECT_NAME/FLAVOR/bin/AAA.map \
+        ./build/PROHECT_NAME/FLAVOR/bin/AAA.elf
+        90 \
+        1024 \
+
+__EOFUSAGE
+  exit 1;
+}
+
+
diff --git a/mcu/tools/MemoryUtility/LinkerOutputParser.pm b/mcu/tools/MemoryUtility/LinkerOutputParser.pm
new file mode 100644
index 0000000..3a0a07b
--- /dev/null
+++ b/mcu/tools/MemoryUtility/LinkerOutputParser.pm
@@ -0,0 +1,1495 @@
+#!/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) 2006
+#
+#  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:
+#* ---------
+#*   BasicMemInfoQuery.pm
+#*
+#* Project:
+#* --------
+#*
+#*
+#* Description:
+#* ------------
+#*   This perl module is used to collect information from map file
+#*       
+#*
+#* History:
+#* --------
+#*   2015/10/28, Carl, Support LinkerSymPostfix::ZILength
+#*
+#*
+#* Author:
+#* -------
+#*   Carl Kao (mtk08237)
+#*
+#****************************************************************************/
+package LinkerOutputParser;
+BEGIN { push @INC, './tools/', './tools/MemoryUtility/', '../' }
+use Storable;
+use MapFileParser;
+use SymFileParser;
+
+my $strFilePath;
+my $strFileType;
+
+my $check_parse = undef;
+
+my $VERNO     = " u0.01";
+                # u0.01 , 2015/01/19,  Initial revision
+    
+
+return 1;
+
+#****************************************************************************
+# subroutine:  FileParse
+#              Must be called first if you want to call other sub functions
+# input:  MAP Path string     
+# output: x  
+#****************************************************************************
+sub FileParse
+{
+	$check_parse = 1;
+	($strFilePath) = @_;
+	if ($strFilePath =~ /map$/)
+	{
+		&MapFileParser::ParseMAP($strFilePath);
+		$strFileType =~ s/map//ig;
+		$strFileType .= "MAP";
+	}
+	elsif ($strFilePath =~ /sym$/)
+	{
+		&SymFileParser::ParseSYM($strFilePath);
+		$strFileType =~ s/sym//ig;
+		$strFileType .= "SYM";
+	}
+}
+
+#****************************************************************************
+# subroutine:  StoreIntoTempFile
+# input:       N/A
+# output:      temp files which contain perl data structure
+#              MapParser_Temp.dat
+#              SymParser_Temp.dat
+#              data is stored into hash in xxxParser_Temp.dat
+#****************************************************************************
+sub StoreIntoTempFile
+{
+	die "Must run &FileParse subroutine before run &StoreIntoTempFile\n" if (!defined $check_parse);
+	my ($strPath) = @_; 
+	if ($strFileType =~ /MAP/i)
+	{
+		&MapFileParser::StoreIntoTempFile($strPath);
+	}
+	elsif ($strFileType =~ /SYM/i)
+	{
+		&SymFileParser::StoreIntoTempFile($strPath);
+	}
+}
+
+#****************************************************************************
+# subroutine:  GetParentOfSymbol
+# input:       Symbol Name, $strOption (Case sensitive)
+#                                     $strOption = "all" or "lib" or "obj"
+# output:      For map file, output is array reference,
+#                  $strOption = "all", array content:[array1,array2,...]
+#                                    array1:[obj1,lib1]
+#                  $strOption = "obj", array content:[obj1,obj2,...]
+#                  $strOption = "lib", array content:[lib1,lib2,...]
+#****************************************************************************
+sub GetParentOfSymbol
+{
+	die "Must run &FileParse subroutine before run &GetParentOfSymbol\n" if (!defined $check_parse);
+	my ($strSymbolName, $strOption) = @_;
+	my $parent_aref;
+if($strFileType =~ /MAP/i)
+	{
+		die "Option should be all/obj/lib\n" if (($strOption ne "all") && ($strOption ne "obj") && ($strOption ne "lib"));
+		$parent_aref = &MapFileParser::GetParentOfSymbol($strSymbolName, $strOption);
+	}
+	return $parent_aref;
+}
+
+#****************************************************************************
+# subroutine:  GetChildOfSymbol
+# input:       Symbol Name (Case sensitive)
+# output:  For map file,  output is array reference,
+#              array content:[sym1,sym2,...]
+#****************************************************************************
+sub GetChildOfSymbol
+{
+	die "Must run &FileParse subroutine before run &GetChildOfSymbol\n" if (!defined $check_parse);
+	my ($strSymbolName) = @_;
+	my $child_aref;
+    if($strFileType =~ /MAP/i)
+	{
+		$child_aref = &MapFileParser::GetChildOfSymbol($strSymbolName);
+	}
+	return $child_aref;
+}
+
+#****************************************************************************
+# subroutine:  ListAllExeRegion
+# input:       $bTrimDebugRegion: only useful for GCC. 
+#              1= NeedtoTrimDebugRegion, 0 or undef=NoNeedToTrimDebugRegion
+# output:  For map file,  output is array reference,
+#              array content:[ExeRegionName1,ExeRegionName2,...] 
+#****************************************************************************
+sub ListAllExeRegion
+{
+	die "Must run &FileParse subroutine before run &ListAllExeRegion\n" if (!defined $check_parse);
+	my ($bTrimDebugRegion) = @_;
+	my $ExeRegion_aref;
+	
+	if($strFileType =~ /SYM/i)
+	{
+		$ExeRegion_aref = &SymFileParser::ListAllExeRegion($bTrimDebugRegion);
+	}
+	return $ExeRegion_aref;
+}
+
+#****************************************************************************
+# subroutine:  ListAllLoadRegion
+# input:       N/A
+# output:      for map file, output array reference
+#                  array content: [LoadRegionName1,LoadRegionName2,...]
+#****************************************************************************
+sub ListAllLoadRegion
+{
+	die "Must run &FileParse subroutine before run &ListAllLoadRegion\n" if (!defined $check_parse);
+	my $LoadRegion_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$LoadRegion_aref = &MapFileParser::ListAllLoadRegion;
+	}
+	return $LoadRegion_aref;
+}
+
+#****************************************************************************
+# subroutine:  ListPadInfo
+# input:       N/A
+# output:      array reference
+#              for map file, array content:[pad_array1,pad_array2,...]
+#                            pad_array1:[strPadBaseAddress,[strPreObjName,strPreLibName],strPreObjAddress,[strPostObjName,strPostLibName],strPostObjAddress]
+#****************************************************************************
+sub ListPadInfo
+{
+	die "Must run &FileParse subroutine before run &ListPadInfo\n" if (!defined $check_parse);
+	my $pad_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$pad_aref = &MapFileParser::ListPadInfo;
+	}
+	return $pad_aref;
+}
+
+#****************************************************************************
+# subroutine:  GetVeneerInfo
+# input:       N/A
+# output:      array reference, array content:[veneer_array1,veneer_arry2,...]
+#              for map file, 
+#              veneer_array1 content:[strExeRegionName,strBaseAddress,strSize]
+#****************************************************************************
+sub GetVeneerInfo
+{
+	die "Must run &FileParse subroutine before run &GetVeneerInfo\n" if (!defined $check_parse);
+	my $veneer_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$veneer_aref = &MapFileParser::GetVeneerInfo;
+	}
+	return $veneer_aref;
+}
+
+#****************************************************************************
+# subroutine:  GetObjSizeByExeRegion
+# input:       ExeRegion Name, Object Name, Library Name(Case sensitive)
+#                              Object Name should contain ".obj"
+#                              Library Name should contain ".lib"
+# output:      size of object in given execution region
+#****************************************************************************
+sub GetObjSizeByExeRegion
+{
+	die "Must run &FileParse subroutine before run &GetObjSizeByExeRegion\n" if (!defined $check_parse);
+	my ($strExeRegionName, $strObjName, $strLibName) = @_;
+	die "Object name must contain .obj/.o postfix\n" if ($strObjName !~ /\.o|\*\S*\*|stub|DSP/);
+	die "Library name must contain .lib/.a postfix\n" if ($strLibName !~ /\.l|\.a|\*\S*\*|\*stub\*|DSP/);
+	my $n_size;
+	if($strFileType =~ /MAP/i)
+	{
+		$n_size = &MapFileParser::GetObjSizeByExeRegion($strExeRegionName, $strObjName, $strLibName);
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetObjSizeByCatExeRegion
+# input:       ExeRegion Name, Object Name, $strCategory(Case sensitive)
+#                              Object Name should contain ".obj"
+#                              $strCategory: RO Data/RW Data/ZI Data/Code for lis
+#                                            RO/RW/ZI for map
+# output:      RO/RW/ZI/RWZI size of object in given execution region
+#****************************************************************************
+sub GetObjSizeByCatExeRegion
+{
+	die "Must run &FileParse subroutine before run &GetObjSizeByExeRegion\n" if (!defined $check_parse);
+	my ($strExeRegionName, $strObjName, $strCategory) = @_;
+	my $n_size = 0;
+	die "Object name must contain .obj/.o postfix\n" if ($strObjName !~ /\.o|\*\S*\*|stub|DSP/);
+	if($strFileType =~ /MAP/i)
+	{
+	    die "Category should be RO/RW/ZI\n"
+	        if (($strCategory ne "RO") && ($strCategory ne "RW") && ($strCategory ne "ZI"));
+		my $nObjCateSize_ref = &MapFileParser::GetObjSizeByCatExeRegion($strExeRegionName, $strCategory);
+		$n_size = $$nObjCateSize_ref{$strObjName};
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetLibSizeByExeRegion
+# input:       Execution Region Name, Library Name (Case sensitive)
+#                                     Library Name should contain ".lib"
+# output:      size of given library in givin execution region
+#****************************************************************************
+sub GetLibSizeByExeRegion
+{
+	die "Must run &FileParse subroutine before run &GetLibSizeByExeRegion\n" if (!defined $check_parse);
+	my ($strExeRegionName, $strLibName) = @_;
+	die "Library name must contain .lib/.a postfix\n" if (($strLibName !~ /\.l|\.a|\*\S*\*|\*stub\*|DSP/));
+	my $n_size;
+	if($strFileType =~ /MAP/i)
+	{
+		$n_size = &MapFileParser::GetLibSizeByExeRegion($strExeRegionName, $strLibName);
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetObjByExeRegion
+# input:       Execution Region Name (Case sensitive)
+# output:      array reference which given execution region contains
+#              array content:[strObjName1,strObjName2,...]
+#****************************************************************************
+sub GetObjByExeRegion
+{
+	die "Must run &FileParse subroutine before run &GetObjByExeRegion\n" if (!defined $check_parse);
+	my ($strExeRegionName) = @_;
+	my $obj_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$obj_aref = &MapFileParser::GetObjByExeRegion($strExeRegionName);
+	}
+	return $obj_aref;
+}
+
+#****************************************************************************
+# subroutine:  GetLibByExeRegion
+# input:       Execution Region Name (Case sensitive)
+# output:      array reference which given execution region contains
+#              array content:[strLibName1,strLibName2,...]
+#****************************************************************************
+sub GetLibByExeRegion
+{
+	die "Must run &FileParse subroutine before run &GetLibByExeRegion\n" if (!defined $check_parse);
+	my ($strExeRegionName) = @_;
+	my $lib_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$lib_aref = &MapFileParser::GetLibByExeRegion($strExeRegionName);
+	}
+	return $lib_aref;
+}
+
+#****************************************************************************
+# subroutine:  ListObjSummaryInfo
+# input:       obj name, strOption represents which column to show(Case sensitive)
+#              OBJ name should contain ".obj"
+#                        strOption = "Code"
+#                                  = "inc.data"
+#                                  = "RO Data"
+#                                  = "RW Data"
+#                                  = "ZI Data"
+#                                  = "Debug"
+# output:  for map file, output undef
+#****************************************************************************
+sub ListObjSummaryInfo
+{
+	die "Must run &FileParse subroutine before run &ListObjSummaryInfo\n" if (!defined $check_parse);
+	my ($strObjName, $strOption) = @_;
+	die "Object name must contain .obj/.o postfix\n" if ($strObjName !~ /\.o|\*\S*\*|stub|DSP/);
+	my $n_size;
+	if($strFileType =~ /MAP/i)
+	{
+	    die "Input should be RO/RW/ZI/Debug\n" if (($strOption ne "RO") && ($strOption ne "RW") && ($strOption ne "ZI") && ($strOption ne "Debug"));
+		$n_size = &MapFileParser::ListObjSummaryInfo($strObjName, $strOption);
+	}
+	$n_size = 0 if(!defined $n_size or $n_size eq "");
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  ListLibSummaryInfo
+# input:       lib name, strOption represents which column to show(Case sensitive)
+#              Lib name should contain ".lib"
+#                        strOption = "Code"
+#                                = "inc.data"
+#                                = "RO Data"
+#                                = "RW Data"
+#                                = "ZI Data"
+#                                = "Debug"
+# output:  for map file, output undef
+#****************************************************************************
+sub ListLibSummaryInfo
+{
+	die "Must run &FileParse subroutine before run &ListLibSummaryInfo\n" if (!defined $check_parse);
+	my ($strLibName, $strOption) = @_;
+	die "Library name must contain .lib/.a postfix\n" if ($strLibName !~ /\.l|\.a|\*\S*\*|\*stub\*|DSP/);
+	my $n_size = 0;
+	if($strFileType =~ /MAP/i)
+	{
+	    die "Input should be RO/RW/ZI/Debug\n" if (($strOption ne "RO") && ($strOption ne "RW") && ($strOption ne "ZI") && ($strOption ne "Debug"));
+		$n_size = &MapFileParser::ListLibSummaryInfo($strLibName, $strOption);
+	}
+	$n_size = 0 if(!defined $n_size or $n_size eq "");
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetVMAByExeRegion
+# input:       $strRegionName: Execution Region Name (Case sensitive)
+# output:      VMA for given execution region
+#****************************************************************************
+sub GetVMAByExeRegion
+{
+	die "Must run &FileParse subroutine before run &GetBaseAddrByExeRegion\n" if (!defined $check_parse);
+	my ($strExeRegionName) = @_;
+	my $n_size;
+	if($strFileType =~ /SYM/i)
+	{
+		$n_size = hex(&SymFileParser::GetExeRegionInfo($strExeRegionName, Region::VMA));
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetTotalSizeByExeRegion
+# input:       $strRegionName: Execution Region Name (Case sensitive)
+# output:      total size for given execution region
+#****************************************************************************
+sub GetTotalSizeByExeRegion
+{
+	die "Must run &FileParse subroutine before run &GetTotalSizeByExeRegion\n" if (!defined $check_parse);
+	my ($strExeRegionName) = @_;
+	my $n_size;
+	if($strFileType =~ /SYM/i)
+	{
+		$n_size = hex(&SymFileParser::GetExeRegionInfo($strExeRegionName, Region::Size));
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetTotalSizeByLib
+# input:       $strLibName: Library Name (Case sensitive)
+#                           Library Name should contain ".lib"
+# output:      total size for given library
+#****************************************************************************
+sub GetTotalSizeByLib
+{
+	die "Must run &FileParse subroutine before run &GetTotalSizeByLib\n" if (!defined $check_parse);
+	my ($strLibName) = @_;
+	die "Library name must contain .lib/.a postfix\n" if (($strLibName !~ /\.l|\.a|\*\S*\*|\*stub\*|DSP/));
+	my $n_size;
+	if($strFileType =~ /MAP/i)
+	{
+		$n_size = &MapFileParser::GetTotalSizeByLib($strLibName);
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetTotalSizeByObj
+# input:       $strObjName: Obj Name, $strLibName: Library Name (Case sensitive)
+#                           Object Name should contain ".obj"
+#                           Library Name should contain ".lib"
+# output:      total size for given (obj, library)
+#****************************************************************************
+sub GetTotalSizeByObj
+{
+	die "Must run &FileParse subroutine before run &GetTotalSizeByObj\n" if (!defined $check_parse);
+	my ($strObjName, $strLibName) = @_;
+	die "Object name must contain .obj/.o postfix\n" if ($strObjName !~ /\.o|\*\S*\*|stub|DSP/);
+	die "Library name must contain .lib/.a postfix\n" if (($strLibName !~ /\.l|\.a|\*\S*\*|\*stub\*|DSP/));
+	my $n_size;
+	if($strFileType =~ /MAP/i)
+	{
+		$n_size = &MapFileParser::GetTotalSizeByObj($strObjName, $strLibName);
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  ListObjLibBySymbol
+# input:       $strSymName: Symbol Name (Case sensitive)
+# output:      for map file, output array reference
+#                            array content:[[strObjName1,strLibName1],[strObjName2,strLibName2],...]
+#****************************************************************************
+sub ListObjLibBySymbol
+{
+	die "Must run &FileParse subroutine before run &ListObjLibBySymbol\n" if (!defined $check_parse);
+	my ($strSymName) = @_;
+	my $obj_lib_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$obj_lib_aref = &MapFileParser::ListObjLibBySymbol($strSymName);
+	}
+	return $obj_lib_aref;
+}
+
+#****************************************************************************
+# subroutine:  ListObjByLib
+# input:       $strLibName: Library Name (Case sensitive)
+#                           Library Name should contain ".lib"
+# output:      obj array reference associated with given library
+#              array content:[strObjName1,strObjName2,...]
+#****************************************************************************
+sub ListObjByLib
+{
+	die "Must run &FileParse subroutine before run &ListObjByLib\n" if (!defined $check_parse);
+	my ($strLibName) = @_;
+	die "Library name must contain .lib/.a postfix\n" if (($strLibName !~ /\.l|\.a|\*\S*\*|\*stub\*|DSP/));
+	my $obj_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$obj_aref = &MapFileParser::ListObjByLib($strLibName);
+	}
+	return $obj_aref;
+}
+
+#****************************************************************************
+# subroutine:  ListLibByObj
+# input:       $ObjName: Object Name (Case sensitive)
+#                        Object Name should contain ".obj"
+# output:      Library array reference associated with given object
+#              array content:[strLibName1,strLibName2,...]
+#****************************************************************************
+sub ListLibByObj
+{
+	die "Must run &FileParse subroutine before run &ListLibByObj\n" if (!defined $check_parse);
+	my ($strObjName) = @_;
+	die "Object name must contain .obj/.o postfix\n" if ($strObjName !~ /\.o|\*\S*\*|stub|DSP/);	
+	my $lib_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$lib_aref = &MapFileParser::ListLibByObj($strObjName);
+	}	
+	return $lib_aref;
+}
+
+#****************************************************************************
+# subroutine:  ListObjLibByAddr
+# input:       symbol address
+# output:      objeck and lib info
+#****************************************************************************
+sub ListObjLibByAddr
+{
+    die "Must run &FileParse subroutine before run &ListObjLibByAddr\n" if (!defined $check_parse);
+
+    my ($strAddress) = @_;
+    my $obj_lib_by_addr;
+    
+    if($strFileType =~ /MAP/i)
+	{
+		$obj_lib_by_addr = &MapFileParser::ListObjLibByAddr($strAddress);
+	}	
+    return $obj_lib_by_addr;
+}
+
+#****************************************************************************
+# subroutine:  GetObjDebugInfoSize
+# input:       $strObjName: Obj Name (Case sensitive)
+#                           Object Name should contain ".obj"
+# output:      debug info size for given obj
+#****************************************************************************
+sub GetObjDebugInfoSize
+{
+	die "Must run &FileParse subroutine before run &GetObjDebugInfoSize\n" if (!defined $check_parse);
+	my ($strObjName) = @_;
+	die "Object name must contain .obj/.o postfix\n" if ($strObjName !~ /\.o|\*\S*\*|stub|DSP/);
+	my $n_debugsize;
+    if($strFileType =~ /MAP/i)
+	{
+		$n_debugsize = &MapFileParser::GetObjDebugInfoSize($strObjName);
+	}
+	return $n_debugsize;
+}
+
+#****************************************************************************
+# subroutine:  FootprintAnalyzeBySymbol
+# input:       $strSymName: Symbol Name, $strObjName: Obj Name (Case sensitive)
+#                           Object Name should contain ".obj" (Not necessary input for GCC SYM file)
+# output:      symbol info array reference
+#              for non Ven/Pad symbol in lis file,[strExeRegionName,strAttr,strBaseAddress,strSize]
+#              for Ven symbol in lis file,[strExeRegionName,strAttr,strBaseAddress,strSize,strDestinationSymbol]
+#              for symbol in sym file,[strExeRegionName,strAttr,strBaseAddress,strSize]
+#****************************************************************************
+sub FootprintAnalyzeBySymbol
+{
+	die "Must run &FileParse subroutine before run &FootprintAnalyzeBySymbol\n" if (!defined $check_parse);
+	my ($strSymName, $strObjName) = @_;
+	my $SymbolInfo_ref;
+	if($strFileType =~ /SYM/i)
+	{
+		$SymbolInfo_ref = &SymFileParser::FootprintAnalyzeBySymbol($strSymName);
+	}
+	return $SymbolInfo_ref;
+}
+#****************************************************************************
+# subroutine:  GetSymbolTable
+# input:       N/A
+# output:      symbol info hash reference in the following format:
+#              $strAddress.$strSymbolName => [strSymbol, $strAddress, strGroup, strRegion, nSize]
+#****************************************************************************
+sub GetSymbolTable
+{
+	die "Must run &FileParse subroutine before run &GetSymbolTable\n" if (!defined $check_parse);
+	my $SymbolInfo_aref;
+	if($strFileType =~ /SYM/i)
+	{
+		$SymbolInfo_aref = &SymFileParser::GetSymbolTable();
+	}
+	return $SymbolInfo_aref;
+}
+
+#****************************************************************************
+# subroutine:  GrepSymbolBySection
+# input:       $strSectionName
+# output:      symbol info array reference in order of address in the following format:
+#              [[strSymbol, $strAddress, strGroup, strRegion, nSize], ...]
+#****************************************************************************
+sub GrepSymbolBySection
+{
+	die "Must run &FileParse subroutine before run &GrepSymbolBySection\n" if (!defined $check_parse);
+	my ($strSectionName) = @_;
+	my $SymbolInfo_aref;
+	if($strFileType =~ /SYM/i)
+	{
+		$SymbolInfo_aref = &SymFileParser::GrepSymbolBySection($strSectionName);
+	}
+    return $SymbolInfo_aref;
+}
+
+#****************************************************************************
+# subroutine:  GetSymbolInfo
+# input:       $strAddress.".".$SymbolName
+# output:     [$SymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize]
+#                            
+#****************************************************************************
+sub GetSymbolInfo{
+
+	die "Must run &FileParse subroutine before run &GetSymbolInfo\n" if (!defined $check_parse);
+	my ($symbol_key) = @_;
+	my @symbol_info;
+	
+	if($strFileType =~ /MAP/i)
+	{
+		@symbol_info = &MapFileParser::GetSymbolInfo($symbol_key);
+	}
+	return @symbol_info;
+}
+
+sub GetSymbol
+{
+	my $SymbolInfo_aref;
+	if($strFileType =~ /SYM/i)
+	{
+		$SymbolInfo_aref = &SymFileParser::GetSymbol();
+	}
+    return $SymbolInfo_aref;
+}
+
+sub GetFillInfo
+{
+	my $FillInfo_href;
+	if($strFileType =~ /MAP/i)
+	{
+		$FillInfo_href = &MapFileParser::GetFillInfo();
+	}
+    return $FillInfo_href;
+}
+
+#****************************************************************************
+# subroutine:  GetLinkerSymbolAddress
+# input:       nRegionType = 0: Execution Region
+#              nRegionType = 1: Load Region
+#              nRegionType = 2: Input Section
+#              nLocation: Base       => LinkerSymPostfix::Base;
+#                         Limit      => LinkerSymPostfix::Limit;
+#                         ZIBase     => LinkerSymPostfix::ZIBase;
+#                         ZILimit    => LinkerSymPostfix::ZILimit;
+#                         Length     => LinkerSymPostfix::Length;
+#                         ZILength   => LinkerSymPostfix::ZILength;
+# output:      address in string
+#****************************************************************************
+sub GetLinkerSymbolAddress
+{
+	die "Must run &FileParse subroutine before run &GetLinkerSymbolAddress\n" if (!defined $check_parse);
+	my ($strRegionName, $nLocation, $nRegionType) = @_;
+	my $strAddr;
+	if($strFileType =~ /SYM/i)
+	{
+		$strAddr = &SymFileParser::GetLinkerSymbolAddress($strRegionName, $nLocation, $nRegionType);
+	}
+    return $strAddr;
+}
+
+#****************************************************************************
+# subroutine:  Get_DUMMY_END_Size
+# input:       N/A
+# output:      size of DUMMY_END region
+#****************************************************************************
+sub Get_DUMMY_END_Size
+{
+	my $DUMMY_END_size;
+	if($strFileType =~ /SYM/i)
+	{
+		$DUMMY_END_size = &SymFileParser::Get_DUMMY_END_Size;
+	}
+	return $DUMMY_END_size;
+}
+
+#****************************************************************************
+# subroutine:  Get_DUMMY_END_Base
+# input:       N/A
+# output:      base address of DUMMY_END region
+#****************************************************************************
+sub Get_DUMMY_END_Base
+{
+	my $DUMMY_END_base;
+	if($strFileType =~ /SYM/i)
+	{
+		$DUMMY_END_base = &SymFileParser::Get_DUMMY_END_Base;
+	}
+	return $DUMMY_END_base;
+}
+
+#****************************************************************************
+# subroutine:  GetExeRegionInfo - Get Execution Region information
+# input:       $strRegionName: Execution Name (Case sensitive)
+#              $nOption for MAP file: Region::VMA
+#                                    Region::LMA
+#                                    Region::Size 
+#                                    Region::Offsets
+#                                    Region::Align
+#                                    Region::Attr
+# output:      required ExeRegion Base address, Used Size, Region MaxSize, Attribute info...
+#****************************************************************************
+sub GetExeRegionInfo
+{
+	die "Must run &FileParse subroutine before run &GetExeRegionInfo\n" if (!defined $check_parse);
+	my ($strRegionName, $nOption) = @_;
+	my $strInfo;
+	if($strFileType =~ /SYM/i)
+	{
+		die "Option should be Region::VMA/Region::LMA/Region::Size/Region::Offsets/Region::Align/Region::Attr\n" if (($nOption ne Region::VMA) && ($nOption ne Region::LMA) && ($nOption ne Region::Size) && ($nOption ne Region::Offsets) && ($nOption ne Region::Align) && ($nOption ne Region::Attr));
+		$strInfo = &SymFileParser::GetExeRegionInfo($strRegionName, $nOption);
+	}
+	return $strInfo;
+}
+
+#****************************************************************************
+# subroutine:  GetLoadRegionInfo - Get Load Region information
+#              $nOption for map file: LoadRegion::Base
+#                                     LoadRegion::Size
+#                                     LoadRegion::MaxSize
+#                                     LoadRegion::Attr
+# output:      required LoadRegion Base address, Used Size, Region MaxSize, Attribute info
+#****************************************************************************
+sub GetLoadRegionInfo
+{
+	die "Must run &FileParse subroutine before run &GetLoadRegionInfo\n" if (!defined $check_parse);
+	my ($strRegionName, $nOption) = @_;
+	my $strInfo;
+    if($strFileType =~ /MAP/i)
+	{
+		$strInfo = &MapFileParser::GetLoadRegionInfo;
+	}
+	return $strInfo;
+}
+
+#****************************************************************************
+# subroutine:  GetExeRegionAttr - Get Region attribution
+# output:        region attribution =>[RO RW ZI]
+#****************************************************************************
+sub GetExeRegionAttr
+{
+	die "Must run &FileParse subroutine before run &GetExeRegionAttr\n" if (!defined $check_parse);
+	my $region_attr;
+    if($strFileType =~ /MAP/i)
+	{
+		$region_attr = &MapFileParser::GetExeRegionAttr;
+	}
+	return $region_attr;
+}
+
+#****************************************************************************
+# subroutine:  GetTotalROSize - Get total RO size
+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int
+# output:      $bNeedString=0:nROSize/ $bNeedString=1:strROSize
+#****************************************************************************
+sub GetTotalROSize
+{
+	die "Must run &FileParse subroutine before run &GetTotalROSize\n" if (!defined $check_parse);
+	my ($bNeedString) = @_;
+	my $n_size;
+	if($strFileType =~ /MAP/i)
+	{
+		$n_size = &MapFileParser::GetTotalROSize($bNeedString);
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetTotalRWZISize - Get total RWZI size
+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int
+# output:      $bNeedString=0:nRWZISize/ $bNeedString=1:strRWZISize
+#****************************************************************************
+sub GetTotalRWZISize
+{
+	die "Must run &FileParse subroutine before run &GetTotalRWZISize\n" if (!defined $check_parse);
+	my ($bNeedString) = @_;
+	my $n_size;
+	if($strFileType =~ /MAP/i)
+	{
+		$n_size = &MapFileParser::GetTotalRWZISize($bNeedString);
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  GetTotalROMSize - Get total ROM size
+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int
+# output:      $bNeedString=0:nROMSize/ $bNeedString=1:strROMSize
+#****************************************************************************
+sub GetTotalROMSize
+{
+	die "Must run &FileParse subroutine before run &GetTotalROMSize\n" if (!defined $check_parse);
+	my ($bNeedString) = @_;
+	my $n_size;
+	if($strFileType =~ /MAP/i)
+	{
+		$n_size = &MapFileParser::GetTotalROMSize($bNeedString);
+	}
+	return $n_size;
+}
+
+#****************************************************************************
+# subroutine:  PadFillExeregSize -- search *fill* padding info for RO and RWZI in INTSRAM region
+# input:       execution region name, memory type
+# output:      memory size
+#****************************************************************************
+sub PadFillExeregSize
+{
+	my ($exeregion, $type)= @_;
+	my $size;
+	$size = &MapFileParser::PadFillExeregSize($exeregion, $type);
+	return $size;
+}
+
+#****************************************************************************
+# subroutine:  GrepSymbolByInputSection
+# input:       input section name represent in regular expression
+#              ex: INTSRAM_ROCODE.*
+#                  INTSRAM_ROCODE_A
+#                  INTSRAM_ROCODE_B
+#
+# output:      symbol info array reference in order of address in the following format: 
+#              [[$strSymbolName, $strAddress, $strObjName, $strLibName, $strOutputSectionName, $strInputSectionName, $nSize], ...] 
+#****************************************************************************
+sub GrepSymbolByInputSection
+{
+	die "Must run &FileParse subroutine before run &GrepSymbolByInputSection\n" if (!defined $check_parse);
+	my ($strSectionNameInRegularExp) = @_;
+	my $syminfo_aref;
+	if($strFileType =~ /MAP/i)
+	{
+		$syminfo_aref = &MapFileParser::GrepSymbolByInputSection($strSectionNameInRegularExp);
+	}
+	return $syminfo_aref;
+}
+
+
+#****************************************************************************
+# subroutine:  GrepSymbolByOutputSection
+# input:       input section name represent in regular expression
+#              ex: CACHED_EXTSRAM_L2CACHE_LOCK_DATA
+#                  CACHED_EXTSRAM_L2CACHE_LOCK_DATA
+#                  CACHED_EXTSRAM_L2CACHE_LOCK_DATA_ZI
+#
+# output:      symbol info array reference in order of address in the following format: 
+#              [[$strObjName, $strLibName],  [$strObjName, $strLibName] ...] 
+#****************************************************************************
+sub GrepSymbolByOutputSection
+{
+	die "Must run &FileParse subroutine before run &GrepSymbolByInputSection\n" if (!defined $check_parse);
+	my ($strSectionNameInRegularExp) = @_;
+	my $syminfo_aref;
+	if($strFileType =~ /SYM/i)
+	{
+		$syminfo_aref = &SymFileParser::GrepSymbolByOutputSection($strSectionNameInRegularExp);
+	}
+	return $syminfo_aref;
+}
+
+
+__END__
+
+=head1 NAME
+
+LinkerOutputParser - Perl module to parse linker output files: .lis/.map/.sym
+
+=head1 SYNOPSIS
+
+    use LinkerOutputParser;
+
+=head2 Table of Contents
+
+LinkerOutputParser consists of a collection of modules whose details 
+are too big to fit in one document.  This POD itself explains the 
+top-level APIs and general topics at a glance.  For other topics and 
+more details, see the PODs below:
+
+  Name			        Description
+  --------------------------------------------------------
+  LisFileParser         Parser module for .lis file
+  MapFileParser         Parser module for .map file
+  SymFileParser         Parser module for .sym file
+  --------------------------------------------------------
+
+=head1 DESCRIPTION
+
+The module provides the interfaces to parse RVCT/GCC linker output files.
+
+=head1 EXAMPLES
+
+Here are some code samples showing a possible usage of LinkerOutputParser:
+
+1. How do I get all execution region list from .lis/.sym file?	
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $exeregion_aref = &LinkerOutputParser::ListAllExeRegion;
+	if (defined $exeregion_aref)
+	{
+		foreach my $temp(@$exeregion_aref)
+		{
+			print "$temp\n";
+		}
+	}
+
+which prints (on my machine):
+
+	BL_GFH_SECTION
+	READ_ONLY
+	READ_ONLY_HEAD
+	READ_ONLY_TAIL
+	READ_WRITE
+	READ_ONLY_INT
+	READ_WRITE_INT
+	EMIINIT_CODE
+	STACK_AREA
+	EXT_UN_INIT
+	SHARE_BUF
+	READ_WRITE_SYS_RAM
+	DUMMY_END
+	BL_SIGNATURE_SECTION
+
+2. How do I get al load region list from .lis file?
+
+    use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $loadregion_aref = &LinkerOutputParser::ListAllLoadRegion;
+	if (defined $loadregion_aref)
+	{
+		foreach my $temp(@$loadregion_aref)
+		{
+			print "$temp\n";
+		}
+	}
+
+which prints (on my machine):
+
+	READ_ONLY
+
+3. How do I get base address/size/maxsize/attribute of an execution region?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $base_address = &LinkerOutputParser::GetExeRegionInfo('BL_GFH_SECTION', ExecutionRegion::Base);
+	print "$base_address\n";
+
+	my $size = &LinkerOutputParser::GetExeRegionInfo('BL_GFH_SECTION', ExecutionRegion::Size);
+	print "$size\n";
+
+which prints (on my machine):
+
+	0x40000900
+	0x150
+	
+4. How do I get base address/size/maxsize/attribute of an load region?
+	
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $base_address = &LinkerOutputParser::GetLoadRegionInfo('READ_ONLY', LoadRegion::Base);
+	print "$base_address\n";
+
+	my $size = &LinkerOutputParser::GetLoadRegionInfo('READ_ONLY', LoadRegion::Size);
+	print "$size\n";
+
+which prints (on my machine):
+
+	0x40000900
+	0x4114
+	
+5. How do I get all objects in an execution region?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $obj_aref = &LinkerOutputParser::GetObjByExeRegion("BL_GFH_SECTION");
+	if (defined $obj_aref)
+	{
+		foreach my $temp(@$obj_aref)
+		{
+			print "$temp\n";
+		}
+	}
+
+which prints (on my machine):
+
+	bl_GFH_body.obj
+	custom_emi_MT6255.obj
+	bl_Secure_v5.obj
+
+6. How do I get all libraries in an execution region?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $lib_aref = &LinkerOutputParser::GetLibByExeRegion("READ_ONLY_TAIL");
+	if (defined $lib_aref)
+	{
+		foreach my $temp(@$lib_aref)
+		{
+			print "$temp\n";
+		}
+	}
+
+which prints (on my machine):
+
+	bootloader.lib
+	sss_rvct_sv5.lib
+	c_5.l
+	h_5.l
+	f_5s.l
+	sst_sec.lib
+	
+7. How do I get object, library associated with a symbol?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $objlib_aref = &LinkerOutputParser::ListObjLibBySymbol(".text");
+	foreach my $temp(@$objlib_aref)
+	{
+		print "$temp->[0], $temp->[1]\n";
+	}
+
+which prints (on my machine):
+
+	strcpy.o, c_5.l
+	_fptrap.o, c_5.l
+	defsig_fpe_outer.o, c_5.l
+	defsig_exit.o, c_5.l
+	defsig_fpe_inner.o, c_5.l
+	defsig_general.o, c_5.l
+	sys_wrch.o, c_5.l
+	rt_memcpy_w.o, c_5.l
+	rt_memclr_w.o, c_5.l
+	llmullu.o, h_5.l
+	rt_memmove_w.o, c_5.l
+	llmul.o, c_5.l
+	rt_fp_status_addr.o, c_5.l
+	sys_exit.o, c_5.l
+	use_no_semi.o, c_5.l
+	
+8. How do I get all objects in a library?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $obj_aref = &LinkerOutputParser::ListObjByLib("sst_sec.lib");
+	if(defined $obj_aref)
+	{
+		foreach my $temp(@$obj_aref)
+		{
+			print "$temp\n";
+		}
+	}
+
+which prints (on my machine):
+
+	SSS_interface.obj
+	br_crypto_platform.obj
+	
+9. How do I get all libraries associated with an object?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $lib_aref = &LinkerOutputParser::ListLibByObj("lpwr.obj");
+	if(defined $lib_aref)
+	{
+		foreach my $temp(@$lib_aref)
+		{
+			print "$temp\n";
+		}
+	}
+
+which prints (on my machine):
+
+	bootloader.lib
+	
+10. How do I get execution region total size?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $exeregion_size = &LinkerOutputParser::GetTotalSizeByExeRegion("BL_GFH_SECTION");  
+	print "$exeregion_size\n";
+
+which prints (on my machine):
+
+	336
+	
+11. How do I get total size of a library?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $lib_size = &LinkerOutputParser::GetTotalSizeByLib("f_5s.l");  
+	print "$lib_size\n";
+
+which prints (on my machine):
+
+	1320
+	
+12. How do I get total size of an object?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+
+	my $obj_size = &LinkerOutputParser::GetTotalSizeByObj("bl_BOOTARM.obj","bootloader.lib");  
+	print "$obj_size\n";
+	
+which prints (on my machine):
+
+	4304
+	
+13. How do I get size of an object in a certain execution region?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $obj_size = &LinkerOutputParser::GetObjSizeByExeRegion("READ_ONLY_TAIL", "bl_FTL.obj", "bootloader.lib"); 
+	print "$obj_size\n";
+	
+which prints (on my machine):
+
+	256
+
+14. How do I get size of a library in a certain execution region?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $lib_size = &LinkerOutputParser::GetLibSizeByExeRegion("BL_GFH_SECTION", "bootloader.lib");  ##300
+	print "$lib_size\n";
+	
+which prints (on my machine):
+
+	288
+
+15. How do I get total RO size for a .lis file?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $ROSize = &LinkerOutputParser::GetTotalROSize;
+	print "Total ROSize is $ROSize\n";
+	
+which prints (on my machine):
+
+	Total ROSize is 16452
+	
+16. How do I get total RWZI size for a .lis file?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $RWZISize = &LinkerOutputParser::GetTotalRWZISize;
+	print "Total RWZISize is $RWZISize\n";
+	
+which prints (on my machine):
+
+	Total RWZISize is 52864
+	
+17. How do I get total ROM size for a .lis file?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $ROMSize = &LinkerOutputParser::GetTotalROMSize;
+	print "Total ROMSize is $ROMSize\n";
+	
+which prints (on my machine):
+
+	Total ROMSize is 16660
+	
+18. How do I get debug info size for an object?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $debug_size = &LinkerOutputParser::GetObjDebugInfoSize('SSS_Secure_v5.obj');
+	print "$debug_size\n";
+	
+which prints (on my machine):
+
+	4683
+	
+19. How do I get footprint infomation of a symbol?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $footprint_info_ref = &LinkerOutputParser::FootprintAnalyzeBySymbol("i.CacheInitMini", "bl_Cache.obj");
+	foreach my $temp(@$footprint_info_ref)  ### array content: [ExecutionRegionName, Attribute, BaseAddress, Size] for common symbols
+	{                                       ### array content: [ExecutionRegionName, Attribute, BaseAddress, Size, DestinationSymbol] for veneers
+		print "$temp\n";
+	}
+	print "\n";
+	
+which prints (on my machine):
+
+	READ_ONLY_TAIL
+	RO-Code
+	0x40000b8c
+	0x0000000c
+	
+20. How do I get parent symbols which refer to certain symbol?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $parent_aref = &LinkerOutputParser::GetParentOfSymbol("NFIDriverInit");
+	if(defined $parent_aref)
+	{
+		foreach my $temp(@$parent_aref)
+		{
+			print "$temp\n";
+		}
+	}
+	
+which prints (on my machine):
+
+	Init
+	
+21. How do I get child symbols which certain symbol refers to?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $child_aref = &LinkerOutputParser::GetChildOfSymbol("itoa");
+	if(defined $child_aref)
+	{
+		foreach my $temp(@$child_aref)
+		{
+			print "$temp\n";
+		}
+	}
+	
+which prints (on my machine):
+
+	__aeabi_idivmod
+	.bss
+	
+22. How do I know pad infomation?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $pad_aref = &LinkerOutputParser::ListPadInfo;
+	if (defined $pad_aref)               
+	{
+		foreach my $temp(@$pad_aref)
+		{
+			print "$temp->[0], $temp->[1], $temp->[2], $temp->[3], $temp->[4]\n";
+			### array content: [pad_address, previous_symbol_name, previous_symbol_address, post_symbol_name, post_symbol_address]
+		}
+	}
+
+which prints (on my machine):
+
+	0x40004075, x$divrt, 0x40003e80, x$fpl$dcmpinfnan, 0x40004078
+	0x40004545, .constdata, 0x40004544, .constdata, 0x40004548
+	0x40004652, .constdata, 0x40004548, .constdata, 0x40004654
+	0x4000471a, .constdata, 0x40004654, .constdata, 0x4000471c
+	0x40004822, .constdata, 0x4000471c, .constdata, 0x40004824
+	0x40004b97, .bss, 0x4000496c, .bss, 0x40004b98
+	0x40004bed, .bss, 0x40004bec, .bss, 0x40004bf0
+	0x50000076, INTERNCODE, 0x50000068, INTERNCODE, 0x50000078
+	0x40000e9e, i.TimeStampInit, 0x40000e9c, i.VerifyExtBootloader, 0x40000ea0
+	0x40000ef2, EMIINITCODE, 0x40000eea, EMIINITCODE, 0x40000ef4
+	0x40001cbe, i.GFH_Find, 0x40001cac, i.GFH_Internal_Parser, 0x40001cc0
+	0x40003302, i.dbg_print, 0x400032ec, i.lpwr_default_callback, 0x40003304
+
+23. How do I know veneer infomation?	
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $veneer_aref = &LinkerOutputParser::GetVeneerInfo;
+	if(defined $veneer_aref)
+	{
+		foreach my $temp(@$veneer_aref)
+		{
+			print "$temp->[0], $temp->[1], $temp->[2], $temp->[3]\n";
+			### array content: [ExecutionRegionName, BaseAddress, Size, DestinationSymbolName]
+		}
+	}
+
+which prints (on my machine):
+
+	READ_ONLY_TAIL, 0x40000c84, 0x00000008, JumpToExtBootloader
+	READ_ONLY_TAIL, 0x40002808, 0x00000008, CP_Crypto_Init
+	READ_ONLY_TAIL, 0x40002810, 0x00000008, CP_Get_MTK_Cipher_Key_Len
+	READ_ONLY_TAIL, 0x40002818, 0x00000008, SaveAndSetIRQMask
+	READ_ONLY_TAIL, 0x40002820, 0x00000008, RestoreIRQMask
+	READ_ONLY_TAIL, 0x40002828, 0x00000008, JumpCmd
+	READ_ONLY_INT, 0x5000004c, 0x00000008, SSS_Crypto_Config_Init
+	READ_ONLY_INT, 0x50000054, 0x00000008, SSS_Crypto_Context_Validation
+	READ_ONLY_INT, 0x5000005c, 0x00000008, ASSERT
+
+24. What if I want to know Code/RO/RW/ZI/Debug size of an object?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $ZIData_size = &LinkerOutputParser::ListObjSummaryInfo("lpwr.obj", "ZI Data");
+	print "$ZIData_size\n";
+
+	my $Debug_size = &LinkerOutputParser::ListObjSummaryInfo("lpwr.obj", "Debug");
+	print "$Debug_size\n";
+
+which prints (on my machine):
+
+	1946
+	6344
+	
+25. What if I want to know Code/RO/RW/ZI/Debug size of a library?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);  # Must run this subroutine first for other activities
+	
+	my $ROData_size = &LinkerOutputParser::ListLibSummaryInfo("bootloader.lib", "RO Data");
+	print "$ROData_size\n";
+
+	my $RWData_size = &LinkerOutputParser::ListLibSummaryInfo("bootloader.lib", "RW Data");
+	print "$RWData_size\n";
+
+which prints (on my machine):
+
+	917
+	208
+
+26. How to retrieve data from temp files which reserved when parsing?
+
+	use LinkerOutputParser;
+
+	my $file = "E:\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis";
+	
+	&LinkerOutputParser::FileParse($file);
+	&LinkerOutputParser::StoreIntoTempFile("E:\\mtk80506");   ## You can identify your preferred path to store temp files
+	
+	my $data_hash = retrieve 'E:\\mtk80506\\LisParser_Temp.dat';    ## temp file names: your_path\LisParser_Temp.dat or your_path\SymParser_Temp.dat or your_path\MapParser_Temp.dat
+	foreach my $key (keys %$data_hash)
+	{
+		print "$key\n";
+	}
+
+which prints (on my machine):
+	
+	debug_size
+	parent_reference
+	symbol_info
+	obj_summary
+	execution_region
+	child_reference
+	load_region
+	lib_summary
+	
+	Then you can retrieve more detailed data, for example, you want to retrieve "child_reference" data (usually are hash/array reference):
+	
+	my $child_value = $$data_hash{"child_reference"};
+
+	foreach my $key (keys %$child_value)
+	{
+		my $array_ref = $$child_value{$key};
+		foreach my $temp(@$array_ref)
+		{
+			print "$key->$temp\n";
+		}
+	}
+
+which prints (on my machine):
+	
+	lpwr_group_init->.bss
+	lpwr_group_init->.constdata
+	_3DES_KeyOptionHandler->__aeabi_memcpy
+	Init->uart_init
+	Init->set_debug_level
+	Init->bl_print
+	Init->DclF32K_Initialize
+	Init->WaitFor32KStable
+	Init->lpwr_init
+	Init->DRVPDN_ini
+	Init->NFIDriverInit
+	Init->bl_Is_Brom_Cmd_Mode_Disabled
+	Init->DummyReference
+	Init->SSS_Init_Share_Crypto_Drv
+	Init->SST_SWB_Init
+	Init->bootloader_debug_level
+	Init->g_randomSeed
+	Init->BL_RESV_REGION
+	Init->g_bromCmdModeDisabled
+	Init->EMI_INFO_2
+	Init->__user_initial_stackheap
+	kal_assert_fail_specific_ext->dbg_print
+	drv_get_duration_ms->drv_get_duration_tick
+	...
+	
+=cut
diff --git a/mcu/tools/MemoryUtility/LisFileParser.pm b/mcu/tools/MemoryUtility/LisFileParser.pm
new file mode 100644
index 0000000..3cf60e3
--- /dev/null
+++ b/mcu/tools/MemoryUtility/LisFileParser.pm
@@ -0,0 +1,1115 @@
+use strict;

+BEGIN{push(@INC,'../', './tools/', './tools/MemoryUtility/')};

+use CommonUtility;

+

+#****************************************************************************

+# Constants

+#****************************************************************************

+package LoadRegion;

+use constant Base                  => 1;

+use constant Size                  => 2;

+use constant MaxSize               => 3;

+use constant Attr                  => 4;

+

+package ExecutionRegion;

+use constant ExeRegionName         => 0;

+use constant Base                  => 1;

+use constant Size                  => 2;

+use constant MaxSize               => 3;

+use constant Type                  => 3;

+use constant Attr                  => 4;

+use constant SectionAttr           => 5;

+use constant ObjName               => 6;

+use constant LibName               => 7;

+

+package LisFileParser;

+

+my $g_LISPath;

+# Load Region

+my %g_LoadRegion;

+my $g_LoadRegionCount = 0;

+my %g_LoadRegionLookUpTable; # RegionName -> Index

+# Execution Region

+my %g_ExeRegion;

+my $g_ExeRegionCount = 0;

+my %g_ExeRegionLookUpTable; # RegionName -> Index

+my %g_VeneerLookUpTable;

+

+# InputSection:

+my %g_InputSectionDetails; # {nIndex} => [0. strExecutionRegionName, 

+                           #              1. strBaseAddress, 

+                           #              2. strSize, 

+                           #              3. strType, 

+                           #              4. strAttr, 

+                           #              5. strSectionName, 

+                           #              6. strObjectName, 

+                           #              7. strLibName]

+                           # nIndex starts from 0

+my %g_InputSections; # {strExecutionRegionName} => [nIndex, ...]

+my $g_InputSectionCount = 0;

+my %debugInfoSize;

+my %ObjSummary;

+my %LibSummary;

+

+my %child;

+my %parent;

+

+# Total Size

+my $g_nTotalROSize = 0;

+my $g_nTotalRWZISize = 0;

+my $g_nTotalROMSize = 0;

+

+my @LoadRegions;

+my @ExeRegions;

+

+#****************************************************************************

+# oo >>>  Finished

+#****************************************************************************

+# return 1;

+

+#****************************************************************************

+# subroutine:  LIS_die

+# sample code: (message, __FILE__, __LINE__)

+# input:       $error_msg, $file, $line_no

+#****************************************************************************

+sub LIS_die

+{

+    my ($error_msg, $file, $line_no) = (@_);

+    &CommonUtil::error_handler($error_msg, $file, $line_no, 'LIS');    

+}

+#****************************************************************************

+# subroutine:  ParseLIS

+# input:  LIS Path string     

+# output: x     

+#****************************************************************************

+sub ParseLIS

+{

+    ($g_LISPath) = (@_);

+	

+	%g_LoadRegion = undef;

+	$g_LoadRegionCount = 0;

+	%g_LoadRegionLookUpTable = undef;

+    %g_ExeRegion = undef;

+	$g_ExeRegionCount = 0;

+	%g_ExeRegionLookUpTable = undef;

+	%g_VeneerLookUpTable = undef;

+	%g_InputSectionDetails = undef;

+	%g_InputSections = undef;

+	$g_InputSectionCount = 0;

+	%debugInfoSize = undef;

+	%ObjSummary = undef;

+	%LibSummary = undef;

+	%child = undef;

+	%parent = undef;

+	$g_nTotalROSize = 0;

+	$g_nTotalRWZISize = 0;

+	$g_nTotalROMSize = 0;

+	@LoadRegions = undef;

+    @ExeRegions = undef;

+	

+    if(defined $g_LISPath and -e $g_LISPath)

+    {

+        open (FILE_HANDLE, "<$g_LISPath") or &LIS_die("$g_LISPath: file error!", __FILE__, __LINE__);

+        my $strPreExeRegionName = undef;

+		my $strObjDebug = 0;

+		my $strLibDebug = 0;

+        while (<FILE_HANDLE>) 

+        {

+            my $strLine = $_;

+			

+			if(/\s+(\S+)\..*\((\S+)\)\srefers\s\S*\s*to\s(\S+)\..*\((\S+)\)\sfor\s(\S+)\s*/)

+			{ ### arm_unaligned.obj(i.memcpy) refers to rt_memcpy_w.o(.text) for __aeabi_memcpy4

+				my $parent = $2;

+				my $child = $5;

+				$parent =~ s/i\.//;

+				push(@{$child{$parent}}, $child);

+				push(@{$parent{$child}}, $parent);

+			}

+			elsif(/Veneer to (\w+)\s+(0x\w+)/)

+			{

+				$g_VeneerLookUpTable{$2} = $1;

+				## Long ARM to Thumb Veneer to ASSERT       0x5000005c   ARM Code       8  anon$$obj.o(Veneer$$Code)

+			}

+			elsif(/\s+Load Region\s(\w+)\s\(Base:\s(0x\w+)\,\sSize:\s(0x\w+),\sMax:\s(0x\w+),\s(\w+)\)/) 

+            {   #   Load Region READ_ONLY (Base: 0x40000900, Size: 0x00004114, Max: 0xffffffff, ABSOLUTE)

+                #$1=Region name, $2=nBaseAddress, $3=nActualSize, $4=nMaxSize, $5=strAttribute

+                $g_LoadRegion{++$g_LoadRegionCount}= [$1, hex($2), hex($3), hex($4), $5];

+                #print "Index=$g_LoadRegionCount, LoadRegionName=$1, BaseAddress=$2, MaxSize=$3, ActualSize=$4, Attribute=$5\n";

+                $g_LoadRegionLookUpTable{$1} = $g_LoadRegionCount;   ### use load region name to query load region id

+                $strPreExeRegionName = undef;

+				push(@LoadRegions, $1);

+            }

+            elsif (/\s+Execution Region\s(\w+)\s\(Base:\s(0x\w+)\,\sSize:\s(0x\w+),\sMax:\s(0x\w+),\s(\w+)(.*)\)/) 

+            {

+                #$1=Region name, $2=nBaseAddress, $3=nActualSize, $4=nMaxSize, $5=strAttribute

+                $g_ExeRegion{++$g_ExeRegionCount}= [$1, hex($2), hex($3), hex($4), $5];

+                #print "Index=$g_ExeRegionCount, ExeRegionName=$1, BaseAddress=$2, Size=$3, ActualSize=$4, Attribute=$5\n";

+                $g_ExeRegionLookUpTable{$1} = $g_ExeRegionCount;

+                # For parsing Input sections

+                $strPreExeRegionName = $1;

+                $g_InputSections{$strPreExeRegionName} = [];

+				push(@ExeRegions, $1);

+            }

+            elsif (/=========/)

+            {

+                $strPreExeRegionName = undef;

+            }

+			elsif (/\s+Code\s+\(inc\. data\)\s+RO Data\s+RW Data\s+ZI Data\s+Debug\s+Object Name/)

+			{  ## Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name

+				$strObjDebug = 1;

+			}

+			elsif (/\s+Code\s+\(inc\. data\)\s+RO Data\s+RW Data\s+ZI Data\s+Debug\s+Library Member Name/)

+			{

+				$strObjDebug = 1;

+			}

+			elsif (/\s+Code\s+\(inc\. data\)\s+RO Data\s+RW Data\s+ZI Data\s+Debug\s+Library Name/)

+			{  ##  Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Name

+				$strLibDebug = 1;

+			}

+			elsif (/Total RO  Size \(Code \+ RO Data\)\s+(\S+)/)

+            {

+                $g_nTotalROSize = $1;

+            }

+            elsif (/Total RW  Size \(RW Data \+ ZI Data\)\s+(\S+)/)

+            {

+                $g_nTotalRWZISize = $1;

+            }

+            elsif (/Total ROM Size \(Code \+ RO Data \+ RW Data\)\s+(\S+)/)

+            {

+                $g_nTotalROMSize  = $1;

+            }

+            &ParseInputSection($strPreExeRegionName, $strLine) if(defined $strPreExeRegionName);

+			&ParseDebugInfo($strObjDebug, $strLine) if ($strObjDebug);

+			&GetObjSummaryInfo($strObjDebug, $strLine) if ($strObjDebug);

+			&GetLibSummaryInfo($strLibDebug, $strLine) if ($strLibDebug);

+        }

+        close FILE_HANDLE;

+    }

+    else

+    {

+        &LIS_die("LIS Path($g_LISPath) doesn't exist", __FILE__, __LINE__);   

+    }    

+}

+

+#****************************************************************************

+# subroutine:  StoreIntoTempFile

+# input:       N/A

+# output:      temp files which contain perl data structure

+#****************************************************************************

+use Storable qw/lock_nstore/;

+sub StoreIntoTempFile

+{

+	my ($strPath) = @_;

+	my $file = $strPath."\\LisParser_Temp.dat";

+	my %tempfile;

+	$tempfile{"parent_reference"} = \%parent;

+	$tempfile{"child_reference"} = \%child;

+	$tempfile{"debug_size"} = \%debugInfoSize;

+	$tempfile{"execution_region"} = \%g_ExeRegion;

+	$tempfile{"load_region"} = \%g_LoadRegion;

+	$tempfile{"symbol_info"} = \%g_InputSectionDetails;

+	$tempfile{"obj_summary"} = \%ObjSummary;

+	$tempfile{"lib_summary"} = \%LibSummary;

+	

+	lock_nstore \%tempfile, $file;

+}

+

+#****************************************************************************

+# subroutine:  GetParentOfSymbol

+# input:       symbol name

+# output:      parent symbol array reference

+#****************************************************************************

+sub GetParentOfSymbol

+{

+	my ($strSymbolName) = @_;

+	foreach my $key (keys %parent)

+	{

+		next if ($strSymbolName ne $key);

+		my $parent = $parent{$key};

+		

+		return $parent;

+	}

+}

+

+#****************************************************************************

+# subroutine:  GetChildOfSymbol

+# input:       symbol name

+# output:      child symbol array reference

+#****************************************************************************

+sub GetChildOfSymbol

+{

+	my ($strSymbolName) = @_;

+	foreach my $key (keys %child)

+	{

+		next if ($strSymbolName ne $key);

+		my $child = $child{$key};

+		

+		return $child;

+	}

+}

+

+#****************************************************************************

+# subroutine:  ListAllExeRegion

+# input:       N/A

+# output:      execution region array reference 

+#****************************************************************************

+sub ListAllExeRegion

+{

+	$#ExeRegions = $#ExeRegions + 1;	

+	return \@ExeRegions;

+}

+

+#****************************************************************************

+# subroutine:  ListAllLoadRegion

+# input:       N/A

+# output:      load region array reference

+#****************************************************************************

+sub ListAllLoadRegion

+{

+	$#LoadRegions = $#LoadRegions + 1;

+	return \@LoadRegions;

+}

+#****************************************************************************

+# subroutine:  ParseInputSection used by ParseLIS

+#              to parse input sections

+# parsing format: 

+#     Base Addr    Size         Type   Attr      Idx    E Section Name        Object

+# 1.  0x70008230   0x00000020   Code   RO           18  * VECTOR_TBL          bl_BOOTARM.obj(bootloader.lib)   

+# 2.  0x1007bb30   0x00000008   Ven    RO       402248    Veneer$$Code        anon$$obj.o

+# 3.  0x106f9c72   0x00000002   PAD

+# we don't need Idx(Index) and E(Entry)

+# input:  1. Execution Name, 2. $strLine

+# output: x     

+#****************************************************************************

+sub ParseInputSection

+{

+    my ($strExeRegionName, $strLine) = @_;

+    return if(!defined $strExeRegionName);    ### setting for $strExeRegionName = undef

+

+    my ($strBaseAddress, $strSize, $strType, $strAttr, $strInputSection, $strObjName, $strLibName)

+     = (undef, undef, undef, undef, undef, undef, undef);

+    my $bMatchInputSection = 0; 

+    chomp($strLine);

+    if($strLine =~ /\s+(0x\w+)\s+(0x\w+)\s+(\w+)\s+(\w+)\s+\d+\s+\**\s+(\S+)\s+(\S+)\((\S+)\)/)

+    {

+    #    Base Addr    Size         Type   Attr      Idx    E Section Name        Object

+    #    0x70008230   0x00000020   Code   RO           18  * VECTOR_TBL          bl_BOOTARM.obj(bootloader.lib)    

+        $strBaseAddress = $1;

+        $strSize = $2;

+        $strType = $3;

+        $strAttr = $4;

+        $strInputSection = $5;

+        $strObjName = $6;

+        $strLibName = $7;

+        #print "[Pattern 1]$strLine:\n[Base]$strBaseAddress, [Size]$strSize, [Type]$strType, [Attr]$strAttr, [InputAttr]$strInputSection, [ObjName]$strObjName, [LibName]$strLibName\n";

+        $bMatchInputSection = 1; 

+    }

+    elsif($strLine =~ /\s+(0x\w+)\s+(0x\w+)\s+(\w+)\s+(\w+)\s+\d+\s+\**\s+(\S+)\s+(\S+)/)

+    {

+    #    Base Addr    Size         Type   Attr      Idx    E Section Name        Object

+    #    0x1007bb30   0x00000008   Ven    RO       402248    Veneer$$Code        anon$$obj.o

+        $strBaseAddress = $1;

+        $strSize = $2;

+        $strType = $3;

+        $strAttr = $4;

+        $strInputSection = $5;

+        $strObjName = $6;

+        #print "[Pattern 2]$strLine:\n[Base]$strBaseAddress, [Size]$strSize, [Type]$strType, [Attr]$strAttr, [InputAttr]$strInputSection, [ObjName]$strObjName, [LibName]x\n";

+        $bMatchInputSection = 1;

+    }

+    elsif($strLine =~ /\s+(0x\w+)\s+(0x\w+)\s+(\w+)/)

+    {

+    #    Base Addr    Size         Type   Attr      Idx    E Section Name        Object

+    #    0x106f9c72   0x00000002   PAD

+        $strBaseAddress = $1;

+        $strSize = $2;

+        $strType = $3;

+        #print "[Pattern 3]$strLine:\n[Base]$strBaseAddress, [Size]$strSize, [Type]$strType\n";

+        $bMatchInputSection = 1;

+    }

+    if($bMatchInputSection == 1)

+    {

+        $g_InputSectionDetails{$g_InputSectionCount} = [$strExeRegionName, $strBaseAddress, $strSize, 

+                                                        $strType, $strAttr, $strInputSection, 

+                                                        $strObjName, $strLibName];

+        push (@{$g_InputSections{$strExeRegionName}}, $g_InputSectionCount);

+        $g_InputSectionCount++;

+    }

+}

+

+#****************************************************************************

+# subroutine:  ListPadInfo

+# input:       N/A

+# output:      array reference

+#              for lis file, array content:[array1,array2,...]

+#                            array1:[strPadBaseAddress,strPreSymName,strPreSymAddress,strPostSymName,strPostSymAddress]

+#****************************************************************************

+sub ListPadInfo

+{

+	my @padstring;

+	foreach my $key (sort keys %g_InputSectionDetails)

+	{

+		my $type = $g_InputSectionDetails{$key}->[3];

+		next if ($type ne "PAD");

+		my $base_address = $g_InputSectionDetails{$key}->[1];

+		my $pre_address = $g_InputSectionDetails{$key-1}->[1];

+		my $pre_symbol = $g_InputSectionDetails{$key-1}->[5];

+		my $post_address = $g_InputSectionDetails{$key+1}->[1];

+		my $post_symbol = $g_InputSectionDetails{$key+1}->[5];

+

+		my @padinfo = [$base_address,$pre_symbol,$pre_address,$post_symbol,$post_address];

+		push (@padstring, @padinfo);

+	}

+	return \@padstring;

+}

+

+#****************************************************************************

+# subroutine:  ParseDebugInfo

+# input:       $strObjDebug, $strLine

+# output:      N/A

+#****************************************************************************

+sub ParseDebugInfo

+{

+	my ($strObjDebug, $strLine) = @_;

+	return if(!$strObjDebug);

+	###  0          0    7341676          0          0          0   IG_FT_CH_320X480.obj

+    chomp($strLine);

+	if($strLine =~ /\s+\d+\s+\d+\s+\d+\s+\d+\s+\d+\s+(\d+)\s+(\S+\.obj$|\S+\.o$)/)

+	{

+		$debugInfoSize{$2} = $1;

+	}  

+}

+

+#****************************************************************************

+# subroutine:  GetObjSummaryInfo

+# input:       flag $strObjDebug, $strLine

+# output:      N/A

+#****************************************************************************

+sub GetObjSummaryInfo

+{

+	my ($strObjDebug, $strLine) = @_;

+	return if(!$strObjDebug);

+	###  0          0    7341676          0          0          0   IG_FT_CH_320X480.obj

+    chomp($strLine);

+	if($strLine =~ /\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+\.obj$|\S+\.o$)/)

+	{

+		$ObjSummary{$7} = [$1,$2,$3,$4,$5,$6];

+	}

+}

+

+#****************************************************************************

+# subroutine:  GetLibSummaryInfo

+# input:       flag $strLibDebug, $strLine

+# output:      N/A

+#****************************************************************************

+sub GetLibSummaryInfo

+{

+	my ($strLibDebug, $strLine) = @_;

+	return if(!$strLibDebug);

+	###  0          0    7341676          0          0          0   IG_FT_CH_320X480.obj

+    chomp($strLine);

+	if($strLine =~ /\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+\.lib$|\S+\.l$|\S+\.a$)/)

+	{

+		$LibSummary{$7} = [$1,$2,$3,$4,$5,$6];

+	}

+}

+

+#****************************************************************************

+# subroutine:  ListObjSummaryInfo

+# input:       obj name, flag represents which column to show

+#                        flag = "Code"

+#                             = "inc.data"

+#                             = "RO Data"

+#                             = "RW Data"

+#                             = "ZI Data"

+#                             = "Debug"

+# output:      Code/inc.data/RO Data/RW Data/ZI Data/Debug size for given obj

+#****************************************************************************

+sub ListObjSummaryInfo

+{

+	my ($strObjName, $flag) = @_;

+	foreach my $key (keys %ObjSummary)

+	{

+		next if ($strObjName ne $key);

+		my $ObjSummaryInfo = $ObjSummary{$key};

+		if ($flag eq "Code")

+		{

+			return @$ObjSummaryInfo[0];

+		}

+		elsif ($flag eq "inc.data")

+		{

+			return @$ObjSummaryInfo[1];

+		}

+		elsif ($flag eq "RO Data")

+		{

+			return @$ObjSummaryInfo[2];

+		}

+		elsif ($flag eq "RW Data")

+		{

+			return @$ObjSummaryInfo[3];

+		}

+		elsif ($flag eq "ZI Data")

+		{

+			return @$ObjSummaryInfo[4];

+		}

+		elsif ($flag eq "Debug")

+		{

+			return @$ObjSummaryInfo[5];

+		}

+	}

+}

+

+#****************************************************************************

+# subroutine:  ListLibSummaryInfo

+# input:       lib name, flag represents which column to show

+#                        flag = "Code"

+#                             = "inc.data"

+#                             = "RO Data"

+#                             = "RW Data"

+#                             = "ZI Data"

+#                             = "Debug"

+# output:      Code/inc.data/RO Data/RW Data/ZI Data/Debug size for given lib

+#****************************************************************************

+sub ListLibSummaryInfo

+{

+	my ($strLibName, $flag) = @_;

+	foreach my $key (keys %LibSummary)

+	{

+		next if ($strLibName ne $key);

+		my $LibSummaryInfo = $LibSummary{$key};

+		if ($flag eq "Code")

+		{

+			return @$LibSummaryInfo[0];

+		}

+		elsif ($flag eq "inc.data")

+		{

+			return @$LibSummaryInfo[1];

+		}

+		elsif ($flag eq "RO Data")

+		{

+			return @$LibSummaryInfo[2];

+		}

+		elsif ($flag eq "RW Data")

+		{

+			return @$LibSummaryInfo[3];

+		}

+		elsif ($flag eq "ZI Data")

+		{

+			return @$LibSummaryInfo[4];

+		}

+		elsif ($flag eq "Debug")

+		{

+			return @$LibSummaryInfo[5];

+		}

+	}

+}

+

+#****************************************************************************

+# subroutine:  GetInputSectionsByExeRegion 

+# input:       $strExeRegionName: Execution Name (Case sensitive)

+# output:      Array_ref : InputSections: [[ExeRegionName, Base...], [ExeRegionName, Base...], ...]

+#              [ExeRegionName, Base...]: InputSectionDetails elements

+#****************************************************************************

+sub GetInputSectionsByExeRegion

+{

+    my ($strExeRegionName) = @_;

+    my @InputSections;

+    my $Indexes = $g_InputSections{$strExeRegionName};    ### array

+    foreach my $nIndex (@$Indexes)

+    {

+        push(@InputSections, $g_InputSectionDetails{$nIndex});  ## $g_InputSectionDetails{$g_InputSectionCount} = [$strExeRegionName, $strBaseAddress, $strSize, $strType, $strAttr, $strInputSection, $strObjName, $strLibName];

+    }

+    return \@InputSections;

+}

+

+#****************************************************************************

+# subroutine:  GetObjTotalSizesByExeRegion

+# input:       $strRegionName: Execution Name (Case sensitive)

+# output:      ObjTotalSize Hash Reference: {ObjName::LibName} => nSize

+# sample code:

+#        my $strExeRegionName = "xxx";

+#        my $nObjTotalSize_ref = &LISInfo::GetObjTotalSizesByExeRegion($strExeRegionName);

+#        foreach my $Obj_LibName (keys %$nObjTotalSize_ref) {...}

+#        => $Obj_LibName: "ObjName::LibName"

+#****************************************************************************

+sub GetObjTotalSizesByExeRegion

+{

+    my ($strExeRegionName) = @_;

+    my %nObjTotalSize; # {ObjName_LibName} = nSize;

+    my $InputSections_ref = &GetInputSectionsByExeRegion($strExeRegionName);

+    foreach my $Info ( @$InputSections_ref)

+    {

+        if(defined $Info->[ExecutionRegion::ObjName])

+        {

+            my $strKey = $Info->[ExecutionRegion::ObjName]."::".$Info->[ExecutionRegion::LibName];

+            if(exists $nObjTotalSize{$strKey})

+            {

+                $nObjTotalSize{$strKey} += hex($Info->[ExecutionRegion::Size]);

+                #print "$strKey = ". $ObjTotalSize{$strKey} ."\n";

+            }

+            else

+            {

+                $nObjTotalSize{$strKey} = hex($Info->[ExecutionRegion::Size]);

+                #print "$strKey = ". hex($Info->[InputSection::Size])."\n";

+            }

+        }

+        else #PAD

+        {

+            $nObjTotalSize{"PAD"} += hex($Info->[ExecutionRegion::Size]);

+        }

+    }

+    return \%nObjTotalSize;

+}

+

+#****************************************************************************

+# subroutine:  GetObjSizeByCatExeRegion

+# input:       $strRegionName: Execution Name (Case sensitive)

+#              $strCategory: RO Data/RW Data/ZI Data/Code (Case sensitive)

+# output:      ObjCateSize Hash Reference

+#****************************************************************************

+sub GetObjSizeByCatExeRegion

+{

+	 my ($strExeRegionName, $strCategory) = @_;

+	 my %nObjROSize; 

+	 my %nObjRWSize;

+	 my %nObjZISize;

+	 my %nObjCodeSize;

+	 

+	 my $InputSections_ref = &GetInputSectionsByExeRegion($strExeRegionName);

+	 foreach my $Info ( @$InputSections_ref)

+	 {

+		if(defined $Info->[ExecutionRegion::ObjName])

+		{

+			my $strKey = $Info->[ExecutionRegion::ObjName];

+

+			if(($strCategory eq "RO Data") && ($Info->[ExecutionRegion::Type] eq "Data") && ($Info->[ExecutionRegion::Attr] eq "RO"))

+			{

+				if(exists $nObjROSize{$strKey})

+				{

+					$nObjROSize{$strKey} += hex($Info->[ExecutionRegion::Size]);

+				}

+				else

+				{

+					$nObjROSize{$strKey} = hex($Info->[ExecutionRegion::Size]);

+				}

+			}

+			elsif(($strCategory eq "RW Data") && ($Info->[ExecutionRegion::Type] eq "Data") && ($Info->[ExecutionRegion::Attr] eq "RW"))

+			{

+				if(exists $nObjRWSize{$strKey})

+				{

+					$nObjRWSize{$strKey} += hex($Info->[ExecutionRegion::Size]);

+				}

+				else

+				{

+					$nObjRWSize{$strKey} = hex($Info->[ExecutionRegion::Size]);

+				}

+			}

+			elsif(($strCategory eq "ZI Data") && ($Info->[ExecutionRegion::Type] eq "Zero") && ($Info->[ExecutionRegion::Attr] eq "RW"))

+			{

+				if(exists $nObjZISize{$strKey})

+				{

+					$nObjZISize{$strKey} += hex($Info->[ExecutionRegion::Size]);

+				}

+				else

+				{

+					$nObjZISize{$strKey} = hex($Info->[ExecutionRegion::Size]);

+				}

+			}

+			elsif(($strCategory eq "Code") && ($Info->[ExecutionRegion::Type] eq "Code") && ($Info->[ExecutionRegion::Attr] eq "RO"))

+			{

+				if(exists $nObjCodeSize{$strKey})

+				{

+					$nObjCodeSize{$strKey} += hex($Info->[ExecutionRegion::Size]);

+				}

+				else

+				{

+					$nObjCodeSize{$strKey} = hex($Info->[ExecutionRegion::Size]);

+				}

+			}

+		}	

+	 }

+	 

+	 if($strCategory eq "RO Data")

+	 {

+		return \%nObjROSize;

+	 }

+	 elsif($strCategory eq "RW Data")

+	 {

+		return \%nObjRWSize;

+	 }

+	 elsif($strCategory eq "ZI Data")

+	 {	

+		return \%nObjZISize;

+	 }

+	 elsif($strCategory eq "Code")

+	 {

+		return \%nObjCodeSize;

+	 }

+}

+

+

+#****************************************************************************

+# subroutine:  GetTotalSizeByExeRegion

+# input:       $strRegionName: Execution Region Name (Case sensitive)

+# output:      total size for given execution region

+#****************************************************************************

+sub GetTotalSizeByExeRegion

+{

+	my ($strExeRegionName) = @_;

+    my %nExeRegionTotalSize; # {ObjName_LibName} = nSize;

+	my $TotalSize;

+    my $InputSections_ref = &GetInputSectionsByExeRegion($strExeRegionName);

+    foreach my $Info ( @$InputSections_ref)

+    {

+        if(defined $Info->[ExecutionRegion::ExeRegionName])

+        {

+            my $strKey = $Info->[ExecutionRegion::ExeRegionName];

+            if(exists $nExeRegionTotalSize{$strKey})

+            {

+                $nExeRegionTotalSize{$strKey} += hex($Info->[ExecutionRegion::Size]);

+                #print "$strKey = ". $ObjTotalSize{$strKey} ."\n";

+            }

+            else

+            {

+                $nExeRegionTotalSize{$strKey} = hex($Info->[ExecutionRegion::Size]);

+                #print "$strKey = ". hex($Info->[InputSection::Size])."\n";

+            }

+			$TotalSize = $nExeRegionTotalSize{$strKey};

+        }

+    }

+	return $TotalSize;

+}

+

+#****************************************************************************

+# subroutine:  GetObjByExeRegion

+# input:       Execution Region Name (Case sensitive)

+# output:      OBJ array reference which given execution region contains

+#****************************************************************************

+sub GetObjByExeRegion

+{

+	my ($strExeRegionName) = @_;

+	my $InputSections_ref = &GetInputSectionsByExeRegion($strExeRegionName);

+	my @obj;

+	my @uni_objs;

+	my %count;

+	foreach my $Info ( @$InputSections_ref)

+    {

+        if(defined $Info->[ExecutionRegion::ObjName])

+        {

+			my $strObj = $Info->[ExecutionRegion::ObjName];

+			push(@obj, $strObj);

+        }

+    }

+	@uni_objs = grep { ++$count{ $_ } < 2; } @obj; 

+	return \@uni_objs;

+}

+

+#****************************************************************************

+# subroutine:  GetLibByExeRegion

+# input:       Execution Region Name (Case sensitive)

+# output:      LIB array reference which given execution region contains

+#****************************************************************************

+sub GetLibByExeRegion

+{

+	my ($strExeRegionName) = @_;

+	my $InputSections_ref = &GetInputSectionsByExeRegion($strExeRegionName);

+	my @lib;

+	my @uni_libs;

+	my %count;

+	foreach my $Info (@$InputSections_ref)

+    {

+        if(defined $Info->[ExecutionRegion::LibName])

+        {

+			my $strLib = $Info->[ExecutionRegion::LibName];

+			push(@lib, $strLib);

+        }

+    }

+	@uni_libs = grep { ++$count{ $_ } < 2; } @lib; 

+	return \@uni_libs;

+}

+

+#****************************************************************************

+# subroutine:  GetLibSizeByExeRegion

+# input:       Execution Region Name, Library Name (Case sensitive)

+# output:      size of given library in givin execution region

+#****************************************************************************

+sub GetLibSizeByExeRegion

+{

+	my ($strExeRegion, $strLib) = @_;

+	my $InputSections_ref = &GetInputSectionsByExeRegion($strExeRegion);

+	my $size = 0;

+	foreach my $Info ( @$InputSections_ref)

+    {

+        if($Info->[ExecutionRegion::LibName] eq $strLib)

+        {

+            $size += hex($Info->[ExecutionRegion::Size]);

+        }

+    }

+	return $size;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalSizeByLib

+# input:       $strLibName: Library Name (Case sensitive)

+# output:      total size for given library

+#****************************************************************************

+sub GetTotalSizeByLib

+{

+    my ($strLibName) = @_;

+	my %nLibTotalSize;

+	my $TotalSize;

+	foreach my $ExeRegion (@ExeRegions)

+	{

+		my $InputSections_ref = &GetInputSectionsByExeRegion($ExeRegion);

+		foreach my $Info ( @$InputSections_ref)

+		{

+			if(defined $Info->[ExecutionRegion::LibName])

+			{

+				my $strKey = $Info->[ExecutionRegion::LibName];

+				next if ($strKey ne $strLibName);

+				if(exists $nLibTotalSize{$strKey})

+				{

+					$nLibTotalSize{$strKey} += hex($Info->[ExecutionRegion::Size]);

+					#print "$strKey = ". $ObjTotalSize{$strKey} ."\n";

+				}

+				else

+				{

+					$nLibTotalSize{$strKey} = hex($Info->[ExecutionRegion::Size]);

+					#print "$strKey = ". hex($Info->[InputSection::Size])."\n";

+				}

+				$TotalSize = $nLibTotalSize{$strKey};

+			}

+		}

+	}

+	return $TotalSize;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalSizeByObj

+# input:       $strObjName: Obj Name, $strLibName: Library Name (Case sensitive)

+# output:      total size for given (obj, library)

+#****************************************************************************

+sub GetTotalSizeByObj

+{

+    my ($strObjName, $strLibName) = @_;

+	my %nObjTotalSize;

+	my $TotalSize;

+	foreach my $ExeRegion(@ExeRegions)

+	{

+		my $InputSections_ref = &GetInputSectionsByExeRegion($ExeRegion);

+		foreach my $Info(@$InputSections_ref)

+		{

+			if(defined $Info->[ExecutionRegion::ObjName])

+			{

+				my $strKey = $Info->[ExecutionRegion::ObjName]."::".$Info->[ExecutionRegion::LibName];

+				my $Key = $strObjName."::".$strLibName;

+				next if ($Key ne $strKey);

+				if(exists $nObjTotalSize{$strKey})

+				{

+					$nObjTotalSize{$strKey} += hex($Info->[ExecutionRegion::Size]);

+					#print "$strKey = ". $ObjTotalSize{$strKey} ."\n";

+				}

+				else

+				{

+					$nObjTotalSize{$strKey} = hex($Info->[ExecutionRegion::Size]);

+					#print "$strKey = ". hex($Info->[InputSection::Size])."\n";

+				}

+				$TotalSize = $nObjTotalSize{$strKey};

+			}

+		}

+	}

+	return $TotalSize;

+}

+

+#****************************************************************************

+# subroutine:  ListObjLibBySymbol

+# input:       $SymName: Symbol Name (Case sensitive)

+# output:      [obj, library] list array reference

+#****************************************************************************

+sub ListObjLibBySymbol

+{

+	my ($SymName) = @_;

+	my @obj_lib;

+	foreach my $ExeRegion(@ExeRegions)

+	{

+		my $InputSections_ref = &GetInputSectionsByExeRegion($ExeRegion);

+		foreach my $Info(@$InputSections_ref)

+		{

+			if(defined $Info->[ExecutionRegion::SectionAttr])

+			{

+				my $strKey = $Info->[ExecutionRegion::SectionAttr];

+				if($strKey eq $SymName)

+				{

+					my $ObjName = $Info->[ExecutionRegion::ObjName];

+					my $LibName = $Info->[ExecutionRegion::LibName];

+					push(@obj_lib, [$ObjName, $LibName]);

+				}

+			}

+		}

+	}

+	return \@obj_lib;

+}

+

+#****************************************************************************

+# subroutine:  ListObjByLib

+# input:       $LibName: Library Name (Case sensitive)

+# output:      obj array reference

+#****************************************************************************

+sub ListObjByLib

+{

+	my ($LibName) = @_;

+	my @obj;

+	my @uni_objs;

+	my %count;

+	foreach my $ExeRegion(@ExeRegions)

+	{

+		my $InputSections_ref = &GetInputSectionsByExeRegion($ExeRegion);

+		foreach my $Info(@$InputSections_ref)

+		{

+			if(defined $Info->[ExecutionRegion::LibName])

+			{

+				my $strKey = $Info->[ExecutionRegion::LibName];

+				if($strKey eq $LibName)

+				{

+					my $ObjName = $Info->[ExecutionRegion::ObjName];

+					push(@obj, $ObjName);

+				}

+			}

+		}

+	}

+	@uni_objs = grep { ++$count{ $_ } < 2; } @obj; 

+	return \@uni_objs;

+}

+

+#****************************************************************************

+# subroutine:  ListLibByObj

+# input:       $ObjName: Object Name (Case sensitive)

+# output:      Library array reference

+#****************************************************************************

+sub ListLibByObj

+{

+	my ($ObjName) = @_;

+	my @lib;

+	my @uni_libs;

+	my %count;

+	foreach my $ExeRegion(@ExeRegions)

+	{

+		my $InputSections_ref = &GetInputSectionsByExeRegion($ExeRegion);

+		foreach my $Info(@$InputSections_ref)

+		{

+			if(defined $Info->[ExecutionRegion::ObjName])

+			{

+				my $strKey = $Info->[ExecutionRegion::ObjName];

+				if($strKey eq $ObjName)

+				{

+					my $LibName = $Info->[ExecutionRegion::LibName];

+					push(@lib, $LibName);

+				}

+			}

+		}

+	}

+	@uni_libs = grep { ++$count{ $_ } < 2; } @lib;		

+	return \@uni_libs;

+}

+

+#****************************************************************************

+# subroutine:  GetObjDebugInfoSize

+# input:       $strObjName: Obj Name (Case sensitive)

+# output:      debug info size for given obj

+#****************************************************************************

+sub GetObjDebugInfoSize

+{

+	my ($strObjName) = @_;

+    my $DebugInfoSize = $debugInfoSize{$strObjName};

+	return $DebugInfoSize;

+}

+

+#****************************************************************************

+# subroutine:  FootprintAnalyzeBySymbol

+# input:       $strSymName: Symbol Name, $strObjName: Obj Name (Case sensitive)

+# output:      symbol info array reference

+#****************************************************************************

+sub FootprintAnalyzeBySymbol

+{

+	my ($strSymName, $strObjName) = @_;

+	my %SymHash;

+	my @SymInfo;

+	foreach my $ExeRegion(@ExeRegions)

+	{

+		my $InputSections_ref = &GetInputSectionsByExeRegion($ExeRegion);

+		foreach my $Info(@$InputSections_ref)

+		{

+			if(defined $Info->[ExecutionRegion::SectionAttr])

+			{

+				my $strKey = $Info->[ExecutionRegion::SectionAttr]."::".$Info->[ExecutionRegion::ObjName];

+				my $Key = $strSymName."::".$strObjName;

+				next if ($Key ne $strKey);

+				

+				my $type = $Info->[ExecutionRegion::Type];

+				if (($type ne "Pad") && ($type ne "Ven"))

+				{

+					my $attr = $Info->[ExecutionRegion::Attr]."-".$type;

+					my $base = $Info->[ExecutionRegion::Base];

+					my $size = hex($Info->[ExecutionRegion::Size]);

+					my $region = $ExeRegion;

+					$SymHash{$strKey} = [$region, $attr, $base, $size];		

+					

+					push(@SymInfo, $region);

+					push(@SymInfo, $attr);

+					push(@SymInfo, $base);

+					push(@SymInfo, $size);

+				}

+				elsif ($type eq "Ven")

+				{

+					my $region = $ExeRegion;

+					my $base = $Info->[ExecutionRegion::Base];

+					my $dest = $g_VeneerLookUpTable{$base};

+					my $size = hex($Info->[ExecutionRegion::Size]);

+					$SymHash{$strKey} = [$region, $type, $base, $size, $dest];

+

+					push(@SymInfo, $region);

+					push(@SymInfo, $type);

+					push(@SymInfo, $base);

+					push(@SymInfo, $size);

+					push(@SymInfo, $dest);

+				}

+			}

+		}

+	}	

+	return \@SymInfo;

+}

+

+#****************************************************************************

+# subroutine:  GetVeneerInfo

+# input:       N/A

+# output:      [Execution Region, Base Address, Size, DestinationSymbolName] array reference for veneer

+#****************************************************************************

+sub GetVeneerInfo

+{

+	my @veneers;

+	foreach my $ExeRegion(@ExeRegions)

+	{

+		my $InputSections_ref = &GetInputSectionsByExeRegion($ExeRegion);

+		foreach my $Info(@$InputSections_ref)

+		{

+			if($Info->[ExecutionRegion::Type] eq "Ven")

+			{

+				my $base = $Info->[ExecutionRegion::Base];

+				my $size = hex($Info->[ExecutionRegion::Size]);

+				my $dest = $g_VeneerLookUpTable{$base};

+				my @veneerinfo = [$ExeRegion, $base, $size, $dest];

+				push(@veneers, @veneerinfo);

+			}

+		}

+	}

+	return \@veneers;

+}

+

+#****************************************************************************

+# subroutine:  GetExeRegionInfo - Get Execution Region information

+# input:       $strRegionName: Execution Name (Case sensitive)

+#              $nOption: ExecutionRegion::Base

+#                        ExecutionRegion::Size

+#                        ExecutionRegion::MaxSize

+#                        ExecutionRegion::Attr

+# output:      required Region Base address, Used Size, Region MaxSize, Attribute info

+#****************************************************************************

+sub GetExeRegionInfo

+{

+    my ($strRegionName, $nOption) = @_;

+    my ($nBase, $nSize, $nMaxSize, $strAttribute) = (0,0,0,'');

+    my $nIndex = $g_ExeRegionLookUpTable{$strRegionName};

+	my $strInfo;

+    if(defined $nIndex)

+    {

+		if($nOption == ExecutionRegion::Base)

+		{

+			$strInfo = &CommonUtil::Dec2Hex($g_ExeRegion{$nIndex}->[ExecutionRegion::Base]);

+		}

+		elsif($nOption == ExecutionRegion::Size)

+		{

+			$strInfo = $g_ExeRegion{$nIndex}->[ExecutionRegion::Size];

+		}

+		elsif($nOption == ExecutionRegion::MaxSize)

+		{

+			$strInfo = $g_ExeRegion{$nIndex}->[ExecutionRegion::MaxSize];

+		}

+		elsif($nOption == ExecutionRegion::Attr)

+		{

+			$strInfo = $g_ExeRegion{$nIndex}->[ExecutionRegion::Attr];

+		}

+    }

+    return $strInfo;

+}

+

+#****************************************************************************

+# subroutine:  GetLoadRegionInfo - Get Load Region information

+# input:       $strRegionName: Execution Name (Case sensitive)

+#              $nOption: LoadRegion::Base

+#                        LoadRegion::Size

+#                        LoadRegion::MaxSize

+#                        LoadRegion::Attr

+# output:      required Region Base address, Used Size, Region MaxSize, Attribute infosub GetLoadRegionInfo

+#****************************************************************************

+sub GetLoadRegionInfo

+{

+    my ($strRegionName, $nOption) = (@_);

+    my ($nBase, $nSize, $nMaxSize, $strAttribute) = (0,0,0,'');

+    my $nIndex = $g_LoadRegionLookUpTable{$strRegionName};

+	my $strInfo;

+    if(defined $nIndex)

+    {

+		if($nOption == LoadRegion::Base)

+		{

+			$strInfo = &CommonUtil::Dec2Hex($g_LoadRegion{$nIndex}->[LoadRegion::Base]);

+		}

+		elsif($nOption == LoadRegion::Size)

+		{

+			$strInfo = $g_LoadRegion{$nIndex}->[LoadRegion::Size];

+		}

+        elsif($nOption == LoadRegion::MaxSize)

+		{

+			$strInfo = $g_LoadRegion{$nIndex}->[LoadRegion::MaxSize];

+		}

+		elsif($nOption == LoadRegion::Attr)

+		{

+			$strInfo = $g_LoadRegion{$nIndex}->[LoadRegion::Attr];

+		}

+    }

+	return $strInfo;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalROSize - Get total RO size

+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int

+# output:      $bNeedString=0:nROSize/ $bNeedString=1:strROSize

+#****************************************************************************

+sub GetTotalROSize

+{

+    my ($bNeedString) = @_;

+    return $bNeedString ? &CommonUtil::Dec2Hex($g_nTotalROSize) : $g_nTotalROSize; 

+}

+

+#****************************************************************************

+# subroutine:  GetTotalRWZISize - Get total RWZI size

+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int

+# output:      $bNeedString=0:nRWZISize/ $bNeedString=1:strRWZISize

+#****************************************************************************

+sub GetTotalRWZISize

+{

+    my ($bNeedString) = @_;

+    return $bNeedString ? &CommonUtil::Dec2Hex($g_nTotalRWZISize) : $g_nTotalRWZISize;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalROMSize - Get total ROM size

+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int

+# output:      $bNeedString=0:nROMSize/ $bNeedString=1:strROMSize

+#****************************************************************************

+sub GetTotalROMSize

+{

+    my ($bNeedString) = @_;

+    return $bNeedString ? &CommonUtil::Dec2Hex($g_nTotalROMSize) : $g_nTotalROMSize;

+}

+

+1;
\ No newline at end of file
diff --git a/mcu/tools/MemoryUtility/ListTopSizeObj.pl b/mcu/tools/MemoryUtility/ListTopSizeObj.pl
new file mode 100644
index 0000000..f1d6fe7
--- /dev/null
+++ b/mcu/tools/MemoryUtility/ListTopSizeObj.pl
@@ -0,0 +1,158 @@
+use strict;

+BEGIN { push @INC, './', './tools/', './tools/MemoryUtility/' }

+use LinkerOutputParser;

+use File::Basename;

+use constant Top_N  => 25;

+

+&Usage() if ($#ARGV != 0); 

+

+my ($file) = @ARGV;

+$file =~ s/\\/\\\\/;

+

+my ($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href);

+

+if(($file =~ /\.lis$/) or ($file =~ /\.map$/))

+{

+	($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href) = &GetAllOBJs($file);

+}

+else

+{

+	&Usage();

+}

+

+my @objs1 = @$objs1_aref;

+

+my %objs1 = map{$_ => 1} @objs1;

+

+my $total_RO_1 = 0;

+my $total_RW_1 = 0;

+my $total_ZI_1 = 0;

+my $total_codebase1;

+

+foreach my $obj (@objs1)

+{

+	$total_RO_1 += $$RO_1_href{$obj};

+	$total_RW_1 += $$RW_1_href{$obj};

+	$total_ZI_1 += $$ZI_1_href{$obj};

+}

+

+my @RW_Top = sort { $$RW_1_href{$b} <=> $$RW_1_href{$a} } @objs1 ;

+my @ZI_Top = sort { $$ZI_1_href{$b} <=> $$ZI_1_href{$a} } @objs1 ;

+

+

+print "Top", Top_N, " result as below:\n";

+	print "*"x80 . "\n";

+	print "Rank  ObjectName                       RW/ZI_Size ROSize;RWSize;ZISize\n";

+	my $sum=0;

+	for my $i (0..Top_N)

+	{

+	printf (" %2d %-30s\t%5dK\t%d;%d;%d\n", $i+1, $RW_Top[$i], int($$RW_1_href{$RW_Top[$i]}/1024),

+		$$RO_1_href{$RW_Top[$i]}, $$RW_1_href{$RW_Top[$i]}, $$ZI_1_href{$RW_Top[$i]} );

+        $sum += $$RW_1_href{$RW_Top[$i]};

+	}

+	print "Top", Top_N, " Contribute ", $sum, "\tTotal:", $total_RW_1, "\t=", int(100*$sum/$total_RW_1), "%\n";

+	print "*"x80 . "\n";

+	my $sum=0;

+	for my $i (0..Top_N)

+	{

+	printf (" %2d %-30s\t%5dK\t%d;%d;%d\n", $i+1, $ZI_Top[$i], int($$ZI_1_href{$ZI_Top[$i]}/1024),

+		$$RO_1_href{$ZI_Top[$i]}, $$RW_1_href{$ZI_Top[$i]}, $$ZI_1_href{$ZI_Top[$i]} );

+        $sum += $$ZI_1_href{$ZI_Top[$i]};

+	}

+	print "Top", Top_N, " Contribute ", $sum, "\tTotal:", $total_ZI_1, "\t=", int(100*$sum/$total_ZI_1), "%\n";

+	print "*"x80 . "\n";

+	

+	printf ("Total RO = %d, RO+RW+RW+ZI = %9d\n",$total_RO_1, $total_RO_1+$total_ZI_1+$total_RW_1*2); 

+	my $sum1=1+int(($total_RO_1+$total_RW_1)/(1024*1024));

+	printf ("Estimate RAM Usage = ROM (RO+RW) %2dMB\n", $sum1);

+	my $sum2=1+int(($total_ZI_1+ 64*1024*(1+int($total_RW_1/(64*1024))))/(1024*1024));

+

+	printf ("                   +Data (RW+ZI) %2dMB\n", $sum2);

+	printf ("                   =        SUM  %2dMB\n", $sum1+$sum2);

+	print "*"x80 . "\n";

+

+sub GetAllOBJs

+{

+	my ($file) = @_;

+	my $symfile = $file;

+	my $exeregion_aref;

+	

+	if($file =~ /\.map$/)

+	{

+		$symfile =~ s/map/sym/;

+		if(!-f $symfile)

+        {

+            my $file = basename($symfile);

+            my $dirname  = dirname($symfile);

+            $symfile = $dirname."\/dummy_$file";

+        } 

+		&LinkerOutputParser::FileParse($symfile);

+	}

+	&LinkerOutputParser::FileParse($file);

+	$exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1);

+	

+

+	my @objs = ();

+	my @uni_objs = ();

+	my %RO_Size;

+	my %RW_Size;

+	my %ZI_Size;

+	my %RWZI_Size;

+	my %count;

+	

+	if (defined $exeregion_aref)

+	{

+		foreach my $temp(@$exeregion_aref)

+		{

+			my $obj_aref = &LinkerOutputParser::GetObjByExeRegion($temp);

+			if (defined $obj_aref)

+			{

+				foreach (@$obj_aref)

+				{

+					push(@objs, $_);

+				}

+			}

+		}

+	}

+	

+	@uni_objs = grep { ++$count{ $_ } < 2; } @objs; 

+	

+	foreach my $obj(@uni_objs)

+	{

+		my ($nRO_Size, $nRW_Size, $nZI_Size) = (0,0,0);

+		

+		if($file =~ /\.lis$/)

+		{

+			$nRO_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "RO Data") + &LinkerOutputParser::ListObjSummaryInfo($obj, "Code");

+			$nRW_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "RW Data");

+			$nZI_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "ZI Data");

+			$RO_Size{$obj} = $nRO_Size;

+			$RW_Size{$obj} = $nRW_Size;

+		    $ZI_Size{$obj} = $nZI_Size;

+		}

+		elsif($file =~ /\.map$/)

+		{

+			$nRO_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "RO");

+			$nRW_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "RW");

+			$nZI_Size = &LinkerOutputParser::ListObjSummaryInfo($obj, "ZI");

+			$RO_Size{$obj} = $nRO_Size;

+			$RW_Size{$obj} = $nRW_Size;

+		    $ZI_Size{$obj} = $nZI_Size;

+		}

+	}

+	

+	return (\@uni_objs, \%RO_Size, \%RW_Size, \%ZI_Size);

+}

+

+

+sub Usage

+{

+  print <<"__EOFUSAGE";

+

+usage: perl ./tools/MemoryUtility/ListTopSizeObj.pl lis/map_file_path

+

+e.g. ./tools/MemoryUtility/ListTopSizeObj.pl ./build/ELBRUS_FPGA/BASIC/bin/ELBRUS_FPGA_PCB01_P_ELBRUS_FPGAS00.map

+

+__EOFUSAGE

+  exit 1;

+}

diff --git a/mcu/tools/MemoryUtility/MapFileParser.pm b/mcu/tools/MemoryUtility/MapFileParser.pm
new file mode 100644
index 0000000..80fd695
--- /dev/null
+++ b/mcu/tools/MemoryUtility/MapFileParser.pm
@@ -0,0 +1,1089 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   MapFileParser.pm

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   This perl module is used to collect information from map file

+#*       

+#*

+#* Author:

+#* -------

+#*   Carl Kao (mtk08237)

+#*

+#****************************************************************************/

+use strict;

+BEGIN{push(@INC,'../../tools/', './tools/', './tools/MemoryUtility/')};

+use CommonUtility; 

+

+package SymbolInfoTable;

+use constant SymbolName         => 0;

+use constant Addr               => 1;

+use constant ObjName            => 2;

+use constant LibName            => 3;

+use constant OutputSectionName  => 4;

+use constant InputSectionName   => 5;

+use constant Size               => 6;

+

+package MapFileParser;

+

+my $VERNO     = " u0.01";

+                # u0.01 , 2015/01/19,  Initial revision for Memory Utility Refinement

+

+my $g_MAPPath;

+

+my %parent_of_symbol; #symbol info in "symbol table"

+my %parent_obj_of_symbol; #symbol info in "symbol table"

+my %parent_lib_of_symbol; #symbol info in "symbol table"

+my %contained_obj; # obj contained in lib

+my %related_lib; # lib related a obj

+my %obj_size; # obj total size

+my %lib_size; # lib total size

+my %region_obj_size;

+my %region_lib_size;

+my %region_contained_obj;

+my %region_obj;

+my %region_contained_lib;

+my @veneers;

+my %obj_pad;

+my %obj_lib_lookup;

+my $obj_pad_count = 0;

+my @pad;

+my %g_discard_symbols; #$inputsection.".".$obj => $nSize;

+

+my %obj_debuginfo;

+my %lib_debuginfo;

+my %OBJ_RO_Size; #{objname} => nSize

+my %LIB_RO_Size; #{libname} => nSize

+my %OBJ_RW_Size;

+my %LIB_RW_Size;

+my %OBJ_ZI_Size; 

+my %LIB_ZI_Size;

+

+my %region_OBJ_RO_Size; #{regionname-objname} => nSize  

+my %region_OBJ_RW_Size;

+my %region_OBJ_ZI_Size;

+

+my @sections; # input section

+

+my %symbol_info; #{$strSymbolName} => [strSymbolName, strAddress, strObjName, strLibName, strOutputSectionName, strInputSectionName, nInputSectionSize]

+my %symbol_lookup_table; #{$SymbolName.".".$strObjName.".".$strLibName} =>  [strSymbolName, strAddress, strObjName, strLibName, strOutputSectionName, strInputSectionName, nInputSectionSize]

+my %region_arribution;

+

+my $g_fill; #record ** zero fill ** part

+my %g_fill_info; #record all fill info.

+

+#****************************************************************************

+# oo >>>  Finished

+#****************************************************************************

+return 1;

+

+#****************************************************************************

+# subroutine:  MAP_die

+# sample code: (message, __FILE__, __LINE__)

+# input:       $error_msg, $file, $line_no

+#****************************************************************************

+sub MAP_die

+{

+    my ($error_msg, $file, $line_no) = (@_);

+    &CommonUtil::error_handler($error_msg, $file, $line_no, 'MAP');    

+}

+

+#****************************************************************************

+# subroutine:  ParseMAP

+# input:  MAP Path string     

+# output: x     

+#****************************************************************************

+sub initGlobalVariable

+{

+    %parent_of_symbol = ();

+    %parent_obj_of_symbol = ();

+    %parent_lib_of_symbol = ();

+    %contained_obj = ();

+    %related_lib = ();

+    %obj_size = ();

+    %lib_size = ();

+    %region_obj_size = ();

+    %region_lib_size = ();

+    %region_contained_obj = ();

+    %region_obj = ();

+    %region_contained_lib = ();

+    @veneers = ();

+    %obj_pad = ();

+    %obj_lib_lookup = ();

+    $obj_pad_count = 0;

+    @pad = ();

+    %obj_debuginfo = ();

+    %lib_debuginfo = ();

+    %OBJ_RO_Size = ();

+    %LIB_RO_Size = ();

+    %OBJ_RW_Size = ();

+    %LIB_RW_Size = ();

+    %OBJ_ZI_Size = ();

+    %LIB_ZI_Size = ();

+    %region_OBJ_RO_Size = ();

+    %region_OBJ_RW_Size = ();

+    %region_OBJ_ZI_Size = ();

+    @sections = ();

+    %g_discard_symbols = ();

+    %symbol_info = ();

+    %symbol_lookup_table = ();

+    %region_arribution = ();

+    $g_fill = undef;

+    %g_fill_info = ();

+}

+

+sub ParseMAP

+{

+    ($g_MAPPath) = @_;

+    initGlobalVariable();

+    

+    if(defined $g_MAPPath and -e $g_MAPPath)

+    {

+        open (FILE_HANDLE, "<$g_MAPPath") or &MAP_die("$g_MAPPath: file error!", __FILE__, __LINE__);

+        

+        my ($strPreSymbolName, $strPreExeRegion, $strPreInputSection,$strSymbolName) = (undef, undef, undef, undef);

+        my ($flag_end_group, $b_enter_reference_table, $b_enter_discard) = (1, 0, 0);

+        

+        #since $strPreInputSection will be set back to undef after _ParseContent(), we need another variable to store it

+        my ($strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName) = ("NOT_FOUND", undef, undef, undef, undef); 

+

+		my $prefix = '(?:startup|unlikely)';#prefix of symbol, ex: .text.unlikely.UL1_SEND_MSG_TO_NVRAM

+		

+        while (<FILE_HANDLE>)

+        {

+            my $strLine = $_;

+            if(/Discarded input sections/)

+            {

+                $b_enter_discard = 1; next;

+            }

+            elsif(/Memory Configuration/)

+            {

+                $b_enter_discard = 0; next;

+            }

+	        elsif(/Memory map/)

+	        {

+	            $b_enter_discard = 0;

+	            $flag_end_group = 0;

+		        next;

+	        }

+            elsif($b_enter_discard == 1)

+            {

+                $strPreSymbolName = _ParseDiscardInputSection($strLine, $strPreSymbolName);

+            }

+            elsif (/END GROUP/)

+            {

+                $flag_end_group = 0;  next;

+            }

+            elsif ($flag_end_group)

+            {

+                next;

+            }

+            elsif (/Symbol\s+File/ or /Cross Reference Table/)   

+            { #Symbol                                            File

+                $b_enter_reference_table = 1; next;

+            } 

+            elsif($b_enter_reference_table == 0 )

+            {

+                if(/^(\S+)/ and $strLine !~/^OUTPUT\(/)

+                {#ignore: OUTPUT(./build/MT6589_MD2_TDD128HSPA/SKYPA/bin/MT6589_MD2_TDD128HSPA_PCB01_MT6589_S00.elf elf32-littlearm)

+                    $strPreExeRegion = $1; next;

+                }

+                elsif(/^\s+(\.\b\w+\b)(\.\b$prefix\b)?(?:\.([^\.\s]+))?(\.\d+)?/)

+                {# .text.AsnDecode_RRC_BSIC => $strPreInputSection = .text; $strSymbolName = AsnDecode_RRC_BSIC

+               

+					$strInputSectionName = $1; 

+					$strSymbolName = ($4)?$3.$4:$3 if($3 or $4);

+					

+					#if symbol name and size are in same line, need to parse symbol size

+					#.rodata.off    0x913f3760        0x1 ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libatc.a(valatapi.obj)

+					next if ($strLine !~ /0x\w+/);

+                }

+                elsif(/^\s+(\S+)$/)

+                {# .debug_aranges

+                    $strInputSectionName = $1; next;

+                }

+                elsif(/^\s+\*\*\s+merge\s+(\S+)$/)

+                {# ** merge strings

+                    $strMergeName = $1; next

+                }

+                

+                ($strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName,$strSymbolName) 

+                    = _ParseContent($strLine, $strPreExeRegion, $strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName,$strSymbolName);

+            }

+            else

+            {

+                my $tmp_ref;

+                ($strPreSymbolName,$tmp_ref) = _ParseSymboltable($_, $strPreSymbolName);

+                $parent_of_symbol{$strPreSymbolName}=$tmp_ref;

+            }

+        }

+        close FILE_HANDLE;

+    }

+    else

+    {

+        &MAP_die("MAP Path($g_MAPPath) doesn't exist", __FILE__, __LINE__);   

+    }

+}

+

+sub _UpdateSize

+{

+    my ($href, $strKey, $strSize) = @_;

+    if(exists $href->{$strKey})

+    {

+        $href->{$strKey} += hex($strSize);

+    }

+    else

+    {

+        $href->{$strKey} = hex($strSize);

+    } 

+}

+

+sub _ParseDiscardInputSection

+{

+    my ($strInput, $strPreLine) = @_;

+    chomp($strInput);

+    if($strInput =~ /^\s+(\S+)\s*$/)

+    {# .debug_aranges

+     #               0x0000000000000000       0x20 ./build/MT6589_MD2_TDD128HSPA/SKYPA/bin/lib/libsys_drv.a(bootarm_gcc.obj)

+        return $1;

+    }

+    elsif(/^\s+(0x\w+)/)

+    {

+        $strInput =  $strPreLine . $strInput;

+    }

+    if (($strInput =~ /(\S+)\s+(0x\w+)\s+(0x\w+)\s+.*\\(.*)\((.*)\)/) || 

+        ($strInput =~ /(\S+)\s+(0x\w+)\s+(0x\w+)\s+.*\/(.*)\((.*)\)/))

+    { #  C$$code        0x0000000000000000      0x210 ./build/MT6572_DEMO_TDD128HSPA/DEFAULT/bin/lib/libsys_drv.a(bootarm_gcc.obj)

+        my $lib = $4;

+        my $obj = $5;

+        my $nSize = hex($3);

+        my $inputsection = $1;

+        _UpdateDiscardSymbol($inputsection, $nSize, $obj, $lib);

+    }

+    return "";

+}

+

+sub _UpdateDiscardSymbol

+{

+    my ($inputsection, $nSize, $obj, $lib) = @_;

+    $g_discard_symbols{$obj.'$$'.$inputsection} = $nSize;

+}

+

+sub _ParseContent

+{

+    my ($strInput, $strPreExeRegion, $strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName,$strSymbolName) = @_;

+    chomp($strInput);

+

+    ## parse lib, obj, symbol size

+    if (($strInput =~ /\s+(\S+)?\s+(0x\w+)\s+(0x\w+)\s+.*\\(.*)\((.*)\)/) || 

+        ($strInput =~ /\s+(\S+)?\s+(0x\w+)\s+(0x\w+)\s+.*\/(.*)\((.*)\)/))

+    {

+    	#**********************************************************

+    	# For beloew three cases:

+    	#  Case1:symbol and addr in same line

+    	#           .rodata.off    0x913f3760        0x1 ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libatc.a(valatapi.obj)

+        #  Case2: symbol and addr in diff line

+        #           .rodata.__FUNCTION__.108590

+        #           0x913f3764        0xb ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libatc.a(valatceng.obj)

+        #  Case3: contain input section 

+        #          EXTRAM_TXDATA  0x09e26864     0x63c8 ./mtk_rel/MT6297_EVB/NLWCTG_SAP/TARGET/lib//libgas_tdd.a(rlc_main.obj)

+    	#**********************************************************

+        my $base = $2;

+        my $size = $3;

+        my $obj = $5;

+        $strLibName = $4;

+        $nInputSectionSize = hex($size);

+        $strObjName = $obj;

+      

+        $strInputSectionName = $1 if ($1 and $1 !~ /\./);#case3:update input section.

+        

+        $obj_pad{++$obj_pad_count} = $base;

+        $obj_lib_lookup{$base} = [$strObjName,$strLibName];

+        &ParseObjLib($strPreExeRegion, $strInput);

+        push(@sections, $strInputSectionName);

+

+        if($g_fill)

+        {

+            $g_fill_info{$base} = [$g_fill->[0], $g_fill->[1], , $region_arribution{$strPreExeRegion}, $obj, $strLibName];

+            $g_fill = undef;

+        }

+        

+        _UpdateRORWZISize($strPreExeRegion, $base, $obj, $strLibName, $size);

+    }

+    elsif ($strInput =~ /(0x\w+)\s+(0x\w+)\s+linker stubs/)

+    {

+        &ParseObjLib($strPreExeRegion, $strInput);

+        _UpdateRORWZISize($strPreExeRegion, $1, "*stub*", undef, $2);

+    }

+    elsif(($strPreExeRegion =~ "EXTSRAM_L1DSP_ZI") and 

+        (($strInput =~ /\*fill\*\s+(0x\w+)\s+(0x\w+)/) or ($strInput =~ /\*\*\s+zero\s+fill\s+(0x\w+)\s+(0x\w+)/)))

+    {

+        my $base = $1;

+        my $size = $2;

+        my $obj = "DSP";

+        $strLibName = "DSP";

+        $nInputSectionSize = hex($size);

+        $strObjName = $obj;

+        

+        push(@sections, $strInputSectionName);

+      

+        _UpdateRORWZISize($strPreExeRegion, $base, $obj, $strLibName, $size);

+    }

+    elsif(($strInput =~ /\*fill\*\s+(0x\w+)\s+(0x\w+)/) or ($strInput =~ /\*\*\s+zero\s+fill\s+(0x\w+)\s+(0x\w+)/))

+    {

+        $obj_pad{++$obj_pad_count} = $1;

+        push(@pad, $obj_pad_count);

+        #record fill info

+        $g_fill = [$1,hex($2)];

+        _UpdateRORWZISize($strPreExeRegion, $1, "*fill*", undef, $2);

+    }

+    elsif($g_fill && $strInput =~ /\s+(0x\w+)\s+(\S+\$\$\S+)\s+/)

+    {    

+        #record fill info in hash table.

+        #there are same address for different linker symbols, in case get wrong info, here use address.symbol as the key of hash.

+        $g_fill_info{$1.".".$2} = [$g_fill->[0], $g_fill->[1], $region_arribution{$strPreExeRegion}, $2];

+        $g_fill = undef;

+    }

+

+    ## parse symbol

+    if(!defined $strMergeName)

+    {

+       ($strSymbolName, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize)

+           = _ParseSymbolInfo($strInput, $strSymbolName, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize);

+    }

+

+    ## parse ** merge

+    if(defined $strMergeName)

+    {

+        if ($strInput =~ /^\s+(0x\w+)\s+(0x\w+)/)

+	    {

+	        $obj_pad{++$obj_pad_count} = $1;

+	        push(@pad, $obj_pad_count);

+	        _UpdateRORWZISize($strPreExeRegion, $1, "*$strMergeName*", undef, $2);

+	    }

+	    $strMergeName =undef;

+    }

+    

+    return ($strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName,$strSymbolName);

+}

+

+sub _UpdateRORWZISize

+{

+    my ($strPreExeRegion, $base, $obj, $lib, $size) = @_;

+    $lib = $obj if(!defined $lib);

+    my $key = $strPreExeRegion."-".$obj;

+    my $objkey = $obj."-".$lib;

+

+    if($strPreExeRegion =~ /^\.debug/)

+    {

+        _UpdateSize(\%obj_debuginfo, $obj, $size);

+        _UpdateSize(\%lib_debuginfo, $lib, $size);

+    }

+    elsif(isZI($strPreExeRegion))

+    {

+        return if($base eq "0x0000000000000000");

+        _UpdateSize(\%OBJ_ZI_Size, $obj, $size);

+        _UpdateSize(\%LIB_ZI_Size, $lib, $size);

+        _UpdateSize(\%region_OBJ_ZI_Size, $key, $size);

+        _UpdateSize(\%obj_size, $objkey, $size);

+        $region_arribution{$strPreExeRegion} = "ZI";

+    }

+    elsif(isRW($strPreExeRegion))

+    {

+        return if($base eq "0x0000000000000000");

+        _UpdateSize(\%OBJ_RW_Size, $obj, $size);

+        _UpdateSize(\%LIB_RW_Size, $lib, $size);

+        _UpdateSize(\%region_OBJ_RW_Size, $key, $size);

+        _UpdateSize(\%obj_size, $objkey, $size);   

+        $region_arribution{$strPreExeRegion} = "RW";

+    }

+    elsif(isRO($strPreExeRegion))

+    {

+        return if($base eq "0x0000000000000000" and $obj !~ /bootarm/i);

+        _UpdateSize(\%OBJ_RO_Size, $obj, $size);

+        _UpdateSize(\%LIB_RO_Size, $lib, $size);

+        _UpdateSize(\%region_OBJ_RO_Size, $key, $size);

+        _UpdateSize(\%obj_size, $objkey, $size);

+        $region_arribution{$strPreExeRegion} = "RO";

+    }

+    ParseInputSection($strPreExeRegion, $obj, $lib, $size);

+}

+

+sub isZI

+{

+    my ($strRegionName) = @_;

+    my $bRet = ($strRegionName =~ /ZI|\.bss|EXTSRAM_DSP/);

+    return $bRet;

+}

+sub isRW

+{

+    my ($strRegionName) = @_;

+    my $bRet = 0;

+    $bRet = 1 if(!isZI($strRegionName) and $strRegionName =~ /DSPRAM|EXTSRAM|DATA|RW/);

+    return $bRet;

+}

+sub isRO

+{

+    my ($strRegionName) = @_;

+    my $bRet = 0;

+    $bRet = 1 if(!isZI($strRegionName) and !isRW($strRegionName) 

+                and ($strRegionName !~/\.ARM\.attributes|\.comment|\.debug|\.stab/));

+    return $bRet;

+}

+

+

+#****************************************************************************

+# subroutine:  _ParseSymbolInfo

+# input:       

+# output:      N/A

+#****************************************************************************

+sub _ParseSymbolInfo

+{

+    my ($strInput, $strSymbolName, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize) = @_;

+    my $skip_pattern = "Image\\$\\$|\\$\\$Base|\\$\\$Limit|\\$\\$Length|load address|\ LONG\ ";

+

+    if($strSymbolName and 

+      (($strInput =~ /^\s+(?:\S+\s+)?(0x\w+)\s+(0x\w+)\s+.*\\(.*)\((.*)\)/) || 

+      ($strInput =~ /^\s+(?:\S+\s+)?(0x\w+)\s+(0x\w+)\s+.*\/(.*)\((.*)\)/)))

+    {   #for below case

+        #    0x911c5d06      0x214 ./mtk_rel/MT6297_EVB/NLWCTG_SAP/TARGET/lib/liburr_fdd.a(slce_configuration_controller.obj)

+        # .bss.fsm_desc  0x23c30ac4       0xec ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libatc.a(valatud.obj)

+        my $strAddress = $1;

+        my $symbol_lookup_key = $strSymbolName.".".$strObjName.".".$strLibName;

+            

+        if($symbol_lookup_table{$symbol_lookup_key})

+        {

+            if($symbol_lookup_table{$symbol_lookup_key}->[1] > $strAddress)

+            {

+                delete $symbol_info{$symbol_lookup_table{$symbol_lookup_key}->[1].".".$strSymbolName};

+            }

+            else

+            {

+                $strAddress = $symbol_lookup_table{$symbol_lookup_key}->[1];

+            }

+            

+            $nInputSectionSize += $symbol_lookup_table{$symbol_lookup_key}->[6];

+        }

+            

+        $symbol_lookup_table{$symbol_lookup_key}  = [$strSymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize];

+        $symbol_info{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize];

+        $strSymbolName = undef;

+    }

+    elsif($strInput =~ /^\s+(0x\w+)\s+(\w+)$/ and $strInput !~/$skip_pattern/)

+    {

+        # for below case

+        #                0x00024054                p_SLILM

+        my $strAddress = $1;

+        my $SymbolName = $2;

+        my $symbol_lookup_key = $SymbolName.".".$strObjName.".".$strLibName;

+            

+        if(!$symbol_lookup_table{$symbol_lookup_key})

+        {# .bss           0x2443e1c0       0x20 ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libdevdrv.a(drv_mdcirq.obj)

+         #                  0x2443e1c0                drv_mdcirq_activate_lisr_lock

+            $nInputSectionSize = hex(0);

+            $symbol_lookup_table{$symbol_lookup_key}  = [$SymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize];

+            $symbol_info{$strAddress.".".$SymbolName} = [$SymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize];

+        }

+    }

+

+    return ($strSymbolName, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize);

+}

+

+

+#****************************************************************************

+# subroutine:  _ParseSymboltable

+# input:       ($strInput, $strPreSymbolName)

+# output:      N/A

+#****************************************************************************

+sub _ParseSymboltable

+{

+    my ($strInput, $strPreSymbolName) = @_;

+    if ($strInput =~ /(\S+)\s+.*[\/|\\](.*)\((.*)\)/)

+    {

+        $strPreSymbolName = $1;

+        my @lib_obj = [$2,$3];

+        my @obj_lib = [$3,$2];

+        push(@{$parent_of_symbol{$1}}, @lib_obj);

+        push(@{$parent_obj_of_symbol{$1}}, $3);

+        push(@{$parent_lib_of_symbol{$1}}, $2);

+    }

+    elsif ($strInput =~ /\s+.*[\/|\\](.*)\((.*)\)/)

+    {

+        my @lib_obj = [$1,$2];

+        my @obj_lib = [$2,$1];

+        push(@{$parent_of_symbol{$strPreSymbolName}}, @lib_obj);

+        push(@{$parent_obj_of_symbol{$strPreSymbolName}}, $2);

+        push(@{$parent_lib_of_symbol{$strPreSymbolName}}, $1);

+    }

+    return ($strPreSymbolName, $parent_of_symbol{$1} );

+}

+

+#****************************************************************************

+# subroutine:  ListAllSections

+# input:       N/A

+# output:      N/A

+#****************************************************************************

+sub ListAllSections

+{

+    my %count;

+    my @uni_sections = grep { ++$count{ $_ } < 2; } @sections; 

+    return \@uni_sections;

+}

+

+#****************************************************************************

+# subroutine:  ListAllLoadRegion (not support this function)

+# input:       N/A

+# output:      N/A

+#****************************************************************************

+sub ListAllLoadRegion

+{

+    return undef;

+}

+

+#****************************************************************************

+# subroutine:  ListPadInfo

+# input:       N/A

+# output:      array reference

+#              for map file, array content:[array1,array2,...]

+#                            array1:[strPadBaseAddress,[strPreObjName,strPreLibName],strPreObjAddress,[strPostObjName,strPostLibName],strPostObjAddress]

+#****************************************************************************

+sub ListPadInfo

+{

+	my @padstring;

+	foreach my $temp(@pad)

+	{

+		my $pad_address = $obj_pad{$temp};

+		my $previous = $obj_pad{$temp - 1};

+		my $post = $obj_pad{$temp + 1};

+		my @pre_obj = $obj_lib_lookup{$previous};

+		my @post_obj = $obj_lib_lookup{$post};

+		# next if(!$pad_address);

+		my @padinfo = [$pad_address,@pre_obj,$previous,@post_obj,$post];

+		push (@padstring, @padinfo);

+	}

+	return \@padstring;

+}

+

+#****************************************************************************

+# subroutine:  StoreIntoTempFile

+# input:       N/A

+# output:      temp files which contain perl data structure

+#****************************************************************************

+use Storable qw/lock_nstore/;

+sub StoreIntoTempFile

+{   

+    my ($strPath) = @_;

+    my $file = $strPath."\\MapParser_Temp.dat";

+    my %tempfile;

+    $tempfile{"parent_reference"} = \%parent_of_symbol;

+    $tempfile{"parent_obj_reference"} = \%parent_obj_of_symbol;

+    $tempfile{"parent_lib_reference"} = \%parent_lib_of_symbol;

+    $tempfile{"veneer"} = \@veneers;

+    $tempfile{"obj_in_exeregion"} = \%region_contained_obj;

+    $tempfile{"lib_in_exeregion"} = \%region_contained_lib;

+    $tempfile{"obj_by_lib"} = \%contained_obj;

+    $tempfile{"lib_by_obj"} = \%related_lib;

+    

+    lock_nstore \%tempfile, $file;

+}

+

+#****************************************************************************

+# subroutine:  ParseObjLib

+# input:       Execution Region Name, $strLine

+# output:      N/A 

+#****************************************************************************

+sub ParseObjLib

+{

+    my ($strPreExeRegion, $strLine) = @_;

+    if (($strPreExeRegion !~ /\.ARM\.attributes/) and ($strPreExeRegion !~ /\.comment/) 

+    and ($strPreExeRegion !~ /^\.debug/) and ($strPreExeRegion !~ /^\.stab/))

+    {

+        if ((/(0x\w+)\s+(0x\w+)\s+.*\\(.*)\((.*)\)/) || (/(0x\w+)\s+(0x\w+)\s+.*\/(.*)\((.*)\)/))

+        {

+            my $lib = $3;

+            my $obj = $4;

+            $contained_obj{$lib}{$obj} = 1;

+            $related_lib{$obj}{$lib} = 1;            

+        }

+        elsif(/(0x\w+)\s+(0x\w+)\s+linker stubs/)

+        {## C$$code.stub   0x7000a258        0x8 linker stubs

+            push (@veneers, [$strPreExeRegion, $1, hex($2)]);

+        }

+    }

+}

+

+#****************************************************************************

+# subroutine:  ParseInputSection

+# input:       Execution Region Name, $strLine

+# output:      N/A

+#****************************************************************************

+sub ParseInputSection

+{

+    my ($strExeRegionName, $obj, $lib, $size) = @_;

+    return if(!defined $strExeRegionName);    ### setting for $strExeRegionName = undef

+    

+    $region_contained_obj{$strExeRegionName}{$obj} = 1;

+    $region_contained_lib{$strExeRegionName}{$lib} = 1;

+    

+    my $obj_key = $strExeRegionName."-".$obj."-".$lib;

+    my $lib_key = $strExeRegionName."-".$lib;

+    _UpdateSize(\%region_obj_size, $obj_key, $size);

+    _UpdateSize(\%region_lib_size, $obj_key, $size);

+}

+

+sub GetDiscardSymbol

+{

+    my ($discard_href) = @_;

+    %$discard_href = %g_discard_symbols;

+}

+

+#****************************************************************************

+# subroutine:  GetSymbolInfo

+# input: 

+#

+#****************************************************************************

+sub GetSymbolInfo

+{

+    my ($symbol_key) = @_;

+    my @symbol_info_array = @{$symbol_info{$symbol_key}} if $symbol_info{$symbol_key};

+

+    return @symbol_info_array;

+}

+

+#****************************************************************************

+# subroutine:  GetFillInfo

+# input: 

+#

+#****************************************************************************

+sub GetFillInfo

+{

+    return \%g_fill_info;

+}

+

+#****************************************************************************

+# subroutine:  GetParentOfSymbol

+# input:       Execution Region Name, flag (all/lib/obj)

+# output:      (Object Name, Library Name) which refers to given symbol (flag = all)

+#              Object Name which refers to given symbol (flag = obj)

+#              Library Name which refers to given symbol (flag = lib)

+#****************************************************************************

+sub GetParentOfSymbol

+{   

+    # Name          Size      VMA       LMA       File off  Algn

+    my ($strSymName, $flag) = @_;

+    

+    my $parent_array;

+    if($flag eq "all")

+    {

+        $parent_array = $parent_of_symbol{$strSymName};

+    }

+    elsif($flag eq "lib")

+    {

+        $parent_array = $parent_lib_of_symbol{$strSymName};

+    }

+    elsif($flag eq "obj")

+    {

+        $parent_array = $parent_obj_of_symbol{$strSymName};

+    }

+    return $parent_array;

+}

+

+#****************************************************************************

+# subroutine:  GetChildOfSymbol

+# input:       symbol name

+# output:      undef(not support this function)

+#****************************************************************************

+sub GetChildOfSymbol

+{

+    my ($strSymbolName) = @_;

+    return undef;

+}

+

+#****************************************************************************

+# subroutine:  ListObjByLib

+# input:       Library Name

+# output:      Objects array reference

+#****************************************************************************

+sub ListObjByLib

+{

+    my ($lib_name) = @_;

+    my @obj_array = keys %{$contained_obj{$lib_name}};

+    return \@obj_array;

+}

+

+#****************************************************************************

+# subroutine:  ListLibByObj

+# input:       Object Name

+# output:      Library array reference

+#****************************************************************************

+sub ListLibByObj

+{

+    my ($obj_name) = @_;

+    my @lib_array = keys %{$related_lib{$obj_name}};

+    return \@lib_array;

+}

+

+#****************************************************************************

+# subroutine:  ListObjLibByAddr

+# input:       symbol address

+# output:      objeck and lib info

+#****************************************************************************

+sub ListObjLibByAddr

+{

+    my ($strAddress) = @_;

+    my @obj_lib_by_addr = @{$obj_lib_lookup{$strAddress}} if $obj_lib_lookup{$strAddress};

+

+    return \@obj_lib_by_addr;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalSizeByObj

+# input:       Object Name, Library Name

+# output:      Total size of given object

+#              (excluding size in .comment, .ARM.attribut, 

+#               execution region which begins with .debug or .stab)

+#****************************************************************************

+sub GetTotalSizeByObj

+{

+    my ($obj_name, $lib_name) = @_;

+    my $key = $obj_name."-".$lib_name;

+    my $obj_size = $obj_size{$key};

+    return $obj_size;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalSizeByLib

+# input:       Library Name

+# output:      Total size of given library 

+#              (excluding size in .comment, .ARM.attribut, 

+#               execution region which begins with .debug or .stab)

+#****************************************************************************

+sub GetTotalSizeByLib

+{

+    my ($lib_name) = @_;

+    my $obj_array = $contained_obj{$lib_name};

+    foreach my $temp (@$obj_array)

+    {

+        my $strObjSize = CommonUtil::Dec2Hex($obj_size{$temp});

+        _UpdateSize(\%lib_size, $lib_name, $strObjSize);

+    }

+    return $lib_size{$lib_name};

+}

+

+#****************************************************************************

+# subroutine:  GetObjByExeRegion

+# input:       Execution Region Name

+# output:      objects which given execution region contains

+#****************************************************************************

+sub GetObjByExeRegion

+{

+    my ($strExeRegionName) = @_;

+    my @obj_array = keys %{$region_contained_obj{$strExeRegionName}};

+    return \@obj_array;

+}

+

+#****************************************************************************

+# subroutine:  GetLibByExeRegion

+# input:       Execution Region Name

+# output:      libraries which given execution region contains

+#****************************************************************************

+sub GetLibByExeRegion

+{

+    my ($strExeRegionName) = @_;

+    my @lib_array = keys %{$region_contained_lib{$strExeRegionName}};

+    return \@lib_array;

+}

+

+#****************************************************************************

+# subroutine:  GetObjSizeByExeRegion

+# input:       ExeRegion Name, Object Name, Library Name

+# output:      size of object in given execution region

+#****************************************************************************

+sub GetObjSizeByExeRegion

+{

+    my ($strExeRegion, $strObj, $strLib) = @_;

+    my $string = $strExeRegion."-".$strObj."-".$strLib;

+    my $obj_size = $region_obj_size{$string};

+    return $obj_size;

+}

+

+#****************************************************************************

+# subroutine:  GetLibSizeByExeRegion

+# input:       ExeRegion Name, Library Name

+# output:      size of library in given execution region 

+#****************************************************************************

+sub GetLibSizeByExeRegion

+{

+    my ($strExeRegion, $strLib) = @_;

+    my $string = $strExeRegion."-".$strLib;

+    my $lib_size = $region_lib_size{$string};

+    return $lib_size;

+}

+

+#****************************************************************************

+# subroutine:  GetObjSizeByCatExeRegion

+# input:       $strRegionName: Execution Name (Case sensitive)

+#              $strCategory: RO/RW/ZI (Case sensitive)

+# output:      ObjCateSize Hash Reference

+#****************************************************************************

+sub GetObjSizeByCatExeRegion

+{

+    my ($strERName, $strCategory) = @_;

+    my %ObjSize; # {strObjName} => Size 

+    

+    my $included_obj_aref = &GetObjByExeRegion($strERName);

+    my $region_OBJ_href = undef;

+    $region_OBJ_href = \%region_OBJ_ZI_Size if(isZI($strERName) and $strCategory =~ /ZI/i);

+    $region_OBJ_href = \%region_OBJ_RW_Size if(isRW($strERName) and $strCategory =~ /RW/i);

+    $region_OBJ_href = \%region_OBJ_RO_Size if(isRO($strERName) and $strCategory =~ /RO/i);

+    

+    if(defined $region_OBJ_href)

+    {

+        foreach my $temp(@$included_obj_aref)

+        {

+            my $key = $strERName."-".$temp;

+            if(exists $region_OBJ_href->{$key})

+            {

+                $ObjSize{$temp} = $region_OBJ_href->{$key};

+            }

+            else

+            {

+                $ObjSize{$temp} = 0;

+            }

+        }

+    }

+    return \%ObjSize;

+}

+

+#****************************************************************************

+# subroutine:  GetVeneerInfo

+# input:       N/A

+# output:      [Execution Region, Base Address, Size] list for veneer

+#****************************************************************************

+sub GetVeneerInfo

+{

+    return \@veneers;

+}

+

+#****************************************************************************

+# subroutine:  GetExeRegionAttr

+# input:       N/A

+# output:     {region_name} = region attribution

+#****************************************************************************

+sub GetExeRegionAttr

+{

+    return \%region_arribution;

+}

+

+#****************************************************************************

+# subroutine:  ListObjLibBySymbol

+# input:       $strSymName: Symbol Name (Case sensitive)

+# output:      for map file, output array reference

+#                            array content:[[strObjName1,strLibName1],[strObjName2,strLibName2],...]

+#****************************************************************************

+sub ListObjLibBySymbol

+{

+    print "[Error] not support any more\n";

+    return undef;

+}

+

+#****************************************************************************

+# subroutine:  GetLoadRegionInfo - Get Load Region information

+# input:       N/A

+# output:      undef(not support this function)

+#****************************************************************************

+sub GetLoadRegionInfo

+{

+    return undef;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalROSize - Get total RO size

+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int

+# output:      undef(not support this function)

+#****************************************************************************

+sub GetTotalROSize

+{

+    my ($bNeedString) = @_;

+    return undef;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalRWZISize - Get total RWZI size

+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int

+# output:      undef(not support this function)

+#****************************************************************************

+sub GetTotalRWZISize

+{

+    my ($bNeedString) = @_;

+    return undef;

+}

+

+#****************************************************************************

+# subroutine:  GetTotalROMSize - Get total ROM size

+# input:       $bNeedString: 1=Return string, 0/default/no input=Return int

+# output:      undef(not support this function)

+#****************************************************************************

+sub GetTotalROMSize

+{

+    my ($bNeedString) = @_;

+    return undef;

+}

+

+#****************************************************************************

+# subroutine:  GetObjDebugInfoSize

+# input:       $strObjName: Obj Name (Case sensitive)

+# output:      debug info size for given obj

+#****************************************************************************

+sub GetObjDebugInfoSize

+{

+    my ($strObjName) = @_;

+    my $DebugInfoSize = $obj_debuginfo{$strObjName};

+    return $DebugInfoSize;

+}

+

+#****************************************************************************

+# subroutine:  ListObjSummaryInfo

+# input:       obj name, flag represents which column to show

+#                        flag = "RO"

+#                             = "RW"

+#                             = "ZI"

+#                             = "Debug"

+# output:      RO/RW/ZI/Debug size for given obj

+#****************************************************************************

+sub ListObjSummaryInfo

+{

+    my ($strName, $flag) = @_;

+    my $nSize = 0;

+    if ($flag =~ /RO/i)

+    {

+        $nSize =  $OBJ_RO_Size{$strName};

+    }

+    elsif ($flag =~ /RW/i)

+    {

+        $nSize =  $OBJ_RW_Size{$strName};

+    }

+    elsif ($flag =~ /ZI/i)

+    {

+        $nSize =  $OBJ_ZI_Size{$strName};

+    }

+    elsif ($flag eq "Debug")

+    {

+        $nSize = $obj_debuginfo{$strName};

+    }

+    return $nSize;

+}

+

+#****************************************************************************

+# subroutine:  ListLibSummaryInfo

+# input:       lib name, flag represents which column to show

+#                        flag = "RO"

+#                             = "RW"

+#                             = "ZI"

+#                             = "Debug"

+# output:      RO/RW/ZI/Debug size for given lib

+#****************************************************************************

+sub ListLibSummaryInfo

+{

+    my ($strLibName, $flag) = @_;

+    my $nSize = 0;

+    if ($flag =~ /RO/i)

+    {

+        $nSize =  $LIB_RO_Size{$strLibName};

+    }

+    elsif ($flag =~ /RW/i)

+    {

+        $nSize =  $LIB_RW_Size{$strLibName};

+    }

+    elsif ($flag =~ /ZI/i)

+    {

+        $nSize =  $LIB_ZI_Size{$strLibName};

+    }

+    elsif ($flag eq "Debug")

+    {

+        $nSize = $lib_debuginfo{$strLibName};

+    }

+    return $nSize;

+}

+

+#****************************************************************************

+# subroutine:  GrepSymbolByInputSection

+# input:       input section name represent in regular expression

+#              ex: INTSRAM_ROCODE.*

+#                  INTSRAM_ROCODE_A

+#                  INTSRAM_ROCODE_B

+#

+# output:      symbol info array reference in order of address in the following format: 

+#              [[$strSymbolName, $nSymbolAddr, $strObjName, $strLibName, $strOutputSectionName, $strInputSectionName, $nInputSectionSize], ...] 

+#****************************************************************************

+sub GrepSymbolByInputSection

+{

+    my ($strSectionNameInRegularExp) = @_;

+    my @SymInfoKeys = sort { hex($symbol_info{$a}->[SymbolInfoTable::Addr]) <=> hex($symbol_info{$b}->[SymbolInfoTable::Addr]) } 

+                      grep{$symbol_info{$_}->[SymbolInfoTable::InputSectionName] =~ /$strSectionNameInRegularExp/} keys %symbol_info;

+    #map {print $_."\n"} @SymInfoKeys;

+    my @SymInfo = map {$symbol_info{$_}} @SymInfoKeys;

+    return \@SymInfo;

+}

+

+#****************************************************************************

+# subroutine:  GrepSymbolByOutputSection

+# input:       input section name represent in regular expression

+#              ex: CACHED_EXTSRAM_L2CACHE_LOCK_DATA

+#                  CACHED_EXTSRAM_L2CACHE_LOCK_DATA

+#                  CACHED_EXTSRAM_L2CACHE_LOCK_DATA_ZI

+#

+# output:      symbol info array reference in order of address in the following format: 

+#              [[$strObjName, $strLibName],  [$strObjName, $strLibName] ...] 

+#****************************************************************************

+sub GrepSymbolByOutputSection

+{

+    my ($strSectionNameInRegularExp) = @_;

+    my @SymInfoKeys = sort { hex($symbol_info{$a}->[SymbolInfoTable::Addr]) <=> hex($symbol_info{$b}->[SymbolInfoTable::Addr]) } 

+                      grep{$symbol_info{$_}->[SymbolInfoTable::OutputSectionName] =~ /$strSectionNameInRegularExp/} keys %symbol_info;

+    #map {print $_."\n"} @SymInfoKeys;

+    my @SymInfo = map {$symbol_info{$_}} @SymInfoKeys;

+    return \@SymInfo;

+}

+

diff --git a/mcu/tools/MemoryUtility/QueryDiscardedSym.pl b/mcu/tools/MemoryUtility/QueryDiscardedSym.pl
new file mode 100644
index 0000000..b92c693
--- /dev/null
+++ b/mcu/tools/MemoryUtility/QueryDiscardedSym.pl
@@ -0,0 +1,147 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   QueryDiscardedSym.pl

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   

+#* 

+#*

+#* Author:

+#* -------

+#*   Carl Kao (mtk08237)

+#*

+#*------------------------------------------------------------------------------

+#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!

+#*============================================================================

+#****************************************************************************/

+use strict;

+BEGIN { push @INC, "./" , '../', './tools/', './tools/MemoryUtility/' }

+use MapFileParser;

+

+my ($option, $file1, $file2) = @ARGV;

+

+if(($option eq "-Q") || ($option eq "-q"))

+{

+    MapFileParser::ParseMAP($file1);

+    my %discard;

+    MapFileParser::GetDiscardSymbol(\%discard);

+    ListDiscardedSymbols(\%discard);

+}

+elsif(($option eq "-C") || ($option eq "-c"))

+{

+    MapFileParser::ParseMAP($file1);

+    my %discard1;

+    MapFileParser::GetDiscardSymbol(\%discard1);

+    

+    MapFileParser::ParseMAP($file2);

+    my %discard2;

+    MapFileParser::GetDiscardSymbol(\%discard2);

+    

+    DiffDiscardedSymbols(\%discard1, \%discard2);

+}

+

+

+

+

+sub ListDiscardedSymbols

+{

+    my ($DiscardSym_href) = @_;

+    print "SymbolName                                                                                  Size            \n";

+    print "*********************************************************************************************************************\n";

+    foreach my $key (sort keys %$DiscardSym_href)

+    {

+         $~ = "AAA";

+        format AAA =

+@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<    @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

+$key,$DiscardSym_href->{$key}

+.

+write;

+    }

+}

+

+

+sub DiffDiscardedSymbols

+{

+    my ($DiscardSym1_href, $DiscardSym2_href) = @_;

+    my %CompareDiscard;

+    foreach my $key1 (sort keys %$DiscardSym1_href)

+    {

+        $CompareDiscard{$key1} = [$DiscardSym1_href->{$key1}, ""];

+    }

+    foreach my $key2 (keys %$DiscardSym2_href)

+    {

+        if(!exists $CompareDiscard{$key2})

+        {

+            $CompareDiscard{$key2} = ["", $DiscardSym2_href->{$key2}];

+        }

+        else

+        {

+            $CompareDiscard{$key2}->[1] = $DiscardSym2_href->{$key2};

+        }

+    }

+    print "   $file1 \nvs. $file2\n";

+    print "Size1          Size2       SymbolName                                                                \n";

+    print "*********************************************************************************************************************\n";

+    my ($nTotalSize1, $nTotalSize2) = (0,0);

+    foreach my $key (sort keys %CompareDiscard)

+    {

+#        print $key, $CompareDiscard{$key}->[0] ,  $CompareDiscard{$key}->[1] ."\n";

+        next if($CompareDiscard{$key}[0] eq $CompareDiscard{$key}[1]);

+        $nTotalSize1 += $CompareDiscard{$key}[0];

+        $nTotalSize2 += $CompareDiscard{$key}[1];

+        $~ = "SYMBOLS";

+        format SYMBOLS =

+@<<<<<<<<<<<<@<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

+$CompareDiscard{$key}[0],$CompareDiscard{$key}[1],$key

+.

+write;

+    }

+    print "*********************************************************************************************************************\nTotal\n";

+    $~ = "TOTALDIFF";

+    format TOTALDIFF = 

+@<<<<<<<<<<<<@<<<<<<<<<<<<

+$nTotalSize1,$nTotalSize2

+.

+write;

+}
\ No newline at end of file
diff --git a/mcu/tools/MemoryUtility/QuerySize.pl b/mcu/tools/MemoryUtility/QuerySize.pl
new file mode 100644
index 0000000..808df83
--- /dev/null
+++ b/mcu/tools/MemoryUtility/QuerySize.pl
@@ -0,0 +1,135 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   QuerySize.pl

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   

+#* 

+#*

+#* Author:

+#* -------

+#*   Carl Kao (mtk08237)

+#*

+#*------------------------------------------------------------------------------

+#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!

+#*============================================================================

+#****************************************************************************/

+use strict;

+BEGIN { push @INC, "./" , './tools/', './tools/MemoryUtility/', '../' }

+use LinkerOutputParser;

+

+&Usage() if ($#ARGV != 1); 

+

+my ($file, $query_name) = @ARGV;

+$file =~ s/\\/\\\\/;

+&LinkerOutputParser::FileParse($file);

+

+my ($ROSize, $RWSize, $ZISize) = (0,0,0);

+

+if($file =~ /\.lis$/)

+{

+	if($query_name =~ /\.o/)

+	{

+		$ROSize = &LinkerOutputParser::ListObjSummaryInfo($query_name, "RO Data") + &LinkerOutputParser::ListObjSummaryInfo($query_name, "Code");

+		$RWSize = &LinkerOutputParser::ListObjSummaryInfo($query_name, "RW Data");

+		$ZISize = &LinkerOutputParser::ListObjSummaryInfo($query_name, "ZI Data");

+	}

+	elsif(($query_name =~ /\.l/) || ($query_name =~ /\.a/))

+	{

+		$ROSize = &LinkerOutputParser::ListLibSummaryInfo($query_name, "RO Data") + &LinkerOutputParser::ListLibSummaryInfo($query_name, "Code");

+		$RWSize = &LinkerOutputParser::ListLibSummaryInfo($query_name, "RW Data");

+		$ZISize = &LinkerOutputParser::ListLibSummaryInfo($query_name, "ZI Data");

+	}

+	else

+	{

+		&Usage();

+	}

+	print "RO Size: $ROSize\n";

+	print "RW Size: $RWSize\n";

+	print "ZI Size: $ZISize\n";

+}

+elsif($file =~ /\.map$/)

+{

+	if($query_name =~ /\.o/)

+	{

+		$ROSize = &LinkerOutputParser::ListObjSummaryInfo($query_name, "RO");

+		$RWSize = &LinkerOutputParser::ListObjSummaryInfo($query_name, "RW");

+		$ZISize = &LinkerOutputParser::ListObjSummaryInfo($query_name, "ZI");

+	}

+	elsif(($query_name =~ /\.l/) || ($query_name =~ /\.a/))

+	{

+		$ROSize = &LinkerOutputParser::ListLibSummaryInfo($query_name, "RO");

+		$RWSize = &LinkerOutputParser::ListLibSummaryInfo($query_name, "RW");

+		$ZISize = &LinkerOutputParser::ListLibSummaryInfo($query_name, "ZI");

+	}

+	else

+	{

+		&Usage();

+	}

+	print "RO Size: $ROSize\n";

+	print "RW Size: $RWSize\n";

+	print "ZI Size: $ZISize\n";

+}

+else

+{

+	&Usage();

+}

+

+

+sub Usage

+{

+  print <<"__EOFUSAGE";

+

+usage: perl QuerySize.pl lis/map_file_path obj_name

+       perl QuerySize.pl lis/map_file_path lib_name

+

+lis/map_file_path: lis/map file path for codebase you want to query

+obj_name/lib_name: object/library name with postfix (for example, bootloader.lib, lpwr.obj)

+

+e.g. perl QuerySize.pl "E:\\mtk80506\\APOLLO55N_V2_DEMO_TDD128HSPA(CMCC_FTE_HVGA).W12.08\\mcu\\build\\APOLLO55N_V2_DEMO\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis" bootloader.lib

+     perl QuerySize.pl "E:\\mtk80506\\APOLLO55N_V2_DEMO_TDD128HSPA(CMCC_FTE_HVGA).W12.08\\mcu\\build\\APOLLO55N_V2_DEMO\\APOLLO55N_V2_DEMO_BOOTLOADER_V005_MT6255_MAUI_11B_W12_08.lis" lpwr.obj

+

+__EOFUSAGE

+  exit 1;

+}
\ No newline at end of file
diff --git a/mcu/tools/MemoryUtility/RAMMargin.pl b/mcu/tools/MemoryUtility/RAMMargin.pl
new file mode 100644
index 0000000..96af5f1
--- /dev/null
+++ b/mcu/tools/MemoryUtility/RAMMargin.pl
@@ -0,0 +1,159 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   RAMmargin.pl

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   This perl is used to get RAM margin

+#*       

+#*

+#* Author:

+#* -------

+#*   Carina Liao (mtk04017)

+#*

+#****************************************************************************/

+

+BEGIN { push @INC, "./" , '../', './tools/', './tools/MemoryUtility/' }  # add additional library path

+use systemInfo;

+use LinkerOutputParser;

+use CommonUtility;

+use FileInfoParser;

+use BasicMemInfoQuery;

+use strict;

+

+#****************************************************************************

+# Constants

+#****************************************************************************

+my $RAMMARGIN_VERNO     = " u0.03";

+             # u0.03 , 2016/03/03,  CMD_GetRAMUsage functions returns now RAMmargin table

+             # u0.02 , 2015/01/27,  Correct pm name (CommonUtility)

+             # u0.01 , 2015/01/19,  Memory Utility Refinement

+             # m0.03 , 2013/02/12,  Fix RamMargin

+             # m0.02 , 2012/08/03,  Push additional library path

+             # m0.01 , 2012/07/21,  Initial revision

+

+#****************************************************************************

+# Global variable

+#****************************************************************************

+my $DebugPrint = 0;

+

+#****************************************************************************

+# 1 >>>  Get in put parameters

+#****************************************************************************

+&Usage() if($#ARGV != 2);

+my ($makeFile, $memorymapfile, $symfile) = @ARGV;

+

+#****************************************************************************

+# 2 >>>  Parse make file

+#****************************************************************************

+my %MAKEFILE_OPTIONS;

+&FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS);

+

+#****************************************************************************

+# 3 >>>  Calculate RAM margin

+#****************************************************************************

+&CalcRAMmargin($makeFile, $memorymapfile, $symfile);

+

+#****************************************************************************

+# oo >>>  Finished

+#****************************************************************************

+exit 0;

+

+#****************************************************************************

+# subroutine:  CalcRAMmargin - calculate RAM margin

+# Input:       x

+# Output:      x

+#****************************************************************************

+sub CalcRAMmargin

+{

+    my ($makeFile, $memorymapfile, $symfile) = @_;

+    my $mapfile = $symfile;

+    my $nRAMUsage = 0;

+    my @RAMmargins;

+    my $i = 0;

+    if($symfile =~ /sym$/)

+    {

+        $mapfile =~ s/\.sym/\.map/;

+        ($nRAMUsage, @RAMmargins) = BasicMemInfo::DispatchCommand("CMD_GetRAMUsage", $makeFile, $memorymapfile, $mapfile, $symfile, undef);

+    }

+    else

+    {

+        &Usage();

+    }

+    foreach my $RamMargin (@RAMmargins)

+    {

+        $i += 1;

+        my $RamMarginInHex = CommonUtil::Dec2Hex(@{$RamMargin}[1]);

+        print "RAM Margin $i = $RamMarginInHex = @{$RamMargin}[1] (Bytes)\n" if(@{$RamMargin}[1] != 0);

+    }

+    print "For more information, please use \"\.\/m memquery basicinfo\" command\n";

+}

+

+#****************************************************************************

+# subroutine:  Usage - usage template

+# Input:       x

+# Output:      x

+#****************************************************************************

+sub Usage

+{

+  print <<"__EOFUSAGE";

+

+usage: perl RAMMargin.pl makefile_path lds_file_path sym_file_path 

+

+e.g. 

+perl RAMMargin.pl "/[path]/MT6280_R7R8_HSPA(FULL_VERSION_RVCT).mak" "/[path]/lds_MT6280_R7R8.txt" "/[path]/MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.sym"

+

+__EOFUSAGE

+

+  exit 1;

+}

+

+#****************************************************************************

+# Subroutine:  TCMmargin_verno - to query this package's version number

+# Parameters:  x

+# Returns:     version number string

+#****************************************************************************

+sub RAMmargin_verno

+{

+    return $RAMMARGIN_VERNO;

+}

diff --git a/mcu/tools/MemoryUtility/SymFileParser.pm b/mcu/tools/MemoryUtility/SymFileParser.pm
new file mode 100644
index 0000000..efdd13f
--- /dev/null
+++ b/mcu/tools/MemoryUtility/SymFileParser.pm
@@ -0,0 +1,664 @@
+#!/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) 2006
+#
+#  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:
+#* ---------
+#*   FileInfoParser.pm
+#*
+#* Project:
+#* --------
+#*
+#*
+#* Description:
+#* ------------
+#*   This module collects the subroutines for common utility. 
+#*       
+#*
+#* Author:
+#* -------
+#*   Carl Kao (mtk08237)
+#*
+#****************************************************************************/
+
+use strict;
+BEGIN{push(@INC,'../', './tools/', './tools/MemoryUtility/')};
+use CommonUtility; 
+use Digest::MD5;
+
+package Region;
+use constant Size        => 1;
+use constant VMA         => 2;
+use constant LMA         => 3;
+use constant Offsets     => 4;
+use constant Align       => 5;
+use constant Attr        => 6;
+
+# for %g_SymTable = ();
+package SymTable;
+use constant Name       => 0;
+use constant Addr       => 1;
+use constant Group      => 2;
+use constant Region     => 3;
+use constant Size       => 4;
+use constant Obj        => 5;
+use constant NeedMerge  => 6;
+
+# for %symbol = ();
+package Symbol;
+use constant Addr       => 0;
+use constant Region     => 3;
+use constant Size       => 4;
+
+# for %g_LinkerSymbol = ();
+package LinkerSymbol;
+use constant Addr       => 0;
+use constant Group      => 1;
+use constant Region     => 2;
+use constant Size       => 3;
+
+package LinkerSymPostfix;
+use constant Base       => 0;
+use constant Limit      => 1;
+use constant ZIBase     => 2;
+use constant ZILimit    => 3;
+use constant Length     => 4;
+use constant ZILength   => 5;
+
+package LinkerSymPrefix;
+use constant Image      => 0;
+use constant Load       => 1;
+use constant None       => 2;
+
+#****************************************************************************
+# Constants
+#****************************************************************************
+my $SYM_FILE_PARSER_VERNO = " u0.07";
+                            #  u0.07 , 2015/10/28,  Carl,  Support LinkerSymPostfix::ZILength
+                            #  u0.06 , 2015/01/22,  Carl,  Add parsing rule for GCC 4.9.3
+                            #  u0.05 , 2015/01/19,  Carl,  Memory Utility Refinement
+                            #  u0.04,  2014/09/26,  Carl,  Add constant for LinkerSymPrefix
+                            #  u0.03,  2014/09/16,  Carl,  Add parsing rule for GCC 4.9.2
+                            #  u0.02,  2014/03/03,  BM,    Refine inculde path
+                            #  u0.01,  2014/02/20,  BM,    Init version, branch from MOLY
+
+#****************************************************************************
+# Global variable
+#****************************************************************************
+package SymFileParser;
+
+my $g_SYMPath;
+my %symbol;
+my $DUMMY_END_size;
+my $DUMMY_END_base;
+my %g_SymTable; # $strAddress.$strSymbolName => [strSymbol, $strAddress, strGroup, strRegion, nSize]
+my %g_LinkerSymbol; # $strSymbolName => [$strAddress, strGroup, strRegion, nSize]
+my %g_static_symbol_loookup; #$strSymbolName.".".$strObjName = [$strAddress, strGroup, strRegion, nSize]
+
+my $g_PreviousParsedSYMChecksum;
+my $g_PreviousParsedSYMPath;
+
+my %g_ExeRegion;# Execution Region
+my %g_ExeRegionLookUpTable; # RegionName -> Index
+my %Attr;
+
+#****************************************************************************
+# oo >>>  Finished
+#****************************************************************************
+return 1;
+
+#****************************************************************************
+# subroutine:  SYM_die
+# sample code: (message, __FILE__, __LINE__)
+# input:       $error_msg, $file, $line_no
+#****************************************************************************
+sub SYM_die
+{
+    my ($error_msg, $file, $line_no) = (@_);
+    &CommonUtil::error_handler($error_msg, $file, $line_no, 'SYM');    
+}
+
+#****************************************************************************
+# subroutine:  ParseSYM
+# input:  SYM Path string     
+# output: x     
+#****************************************************************************
+sub Clean
+{
+    %symbol = ();
+	%g_ExeRegion = ();
+	%g_ExeRegionLookUpTable = ();
+	%g_SymTable = ();
+	%g_LinkerSymbol = ();
+	%Attr = ();
+	$DUMMY_END_size = 0;
+	$DUMMY_END_size = 0;
+}
+
+sub ParseSYM
+{
+    ($g_SYMPath) = (@_);    
+    if(defined $g_SYMPath and -e $g_SYMPath)
+    {
+        open (my $fh, '<', $g_SYMPath) or &SYM_die("$g_SYMPath: file error!", __FILE__, __LINE__);
+        binmode ($fh);
+        my $SYMChecksum = Digest::MD5->new->addfile($fh)->hexdigest;
+        
+        if($g_SYMPath eq $g_PreviousParsedSYMPath and $SYMChecksum eq $g_PreviousParsedSYMChecksum)
+        {
+            #print "Sym File: $g_SYMPath was parsed before and not modified, skip PasrseSYM\n";
+            close($fh);
+            return;
+        }
+        close($fh);
+
+        Clean();
+        open (FILE_HANDLE, "<$g_SYMPath") or &SYM_die("$g_SYMPath: file error!", __FILE__, __LINE__);
+        my $strPreExeRegionName = undef;
+        my $bBegin = 0; #0= Program Header: begin, 1= Sections begin, 2=SYMBOL TABLE: begin
+        my $strObjName = undef; #parse static symbol's obj
+        
+        while (<FILE_HANDLE>) 
+        {
+            my $strLine = $_;
+            $bBegin = 1 if($strLine =~/^Sections:$/);#begin parse section table
+            $bBegin = 2 if($strLine =~/^SYMBOL TABLE:$/);#begin parse symbol table
+            
+            if ($strLine =~ /\.hidden\s/)
+            {
+                $strObjName = undef;#no static symbol after '.hidden'
+				
+				# add this rule for GCC 4.9.3
+            	# [4.9.2] a0401ee4 g     O CACHED_EXTSRAM	00000008 .hidden __CTOR_LIST__
+				$strLine =~ s|\.hidden\s||g;
+            }
+            
+            last if($strLine =~/^RELOCATION RECORDS FOR \[ROM\]:$/);
+
+            ## begin to parse section table
+            if ($bBegin == 1 and 
+                $strLine =~ /\s*(\d+)\s+(\S+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\S+)/) 
+            {   #  Idx Name                   Size          VMA         LMA          File off      Algn
+                #  0    BL_GFH_SECTION 00000170  7000a000  7000a000  00002000  2**2
+                $g_ExeRegion{$1}= [$2, $3, $4, $5, $6, $7];
+                $g_ExeRegionLookUpTable{$2} = $1;
+                $strPreExeRegionName = $2;
+                next;
+            }
+            elsif($bBegin == 1 and defined $strPreExeRegionName)
+            {   #parse section attribution
+                &ParseInputSection($strPreExeRegionName, $strLine);
+                next;
+            }        
+
+            ## begin to parse symbol table
+            $strObjName = ParseSymbolTable($strLine,$strObjName) if($bBegin == 2);
+
+            if ($bBegin ==2 and $strLine =~ /DUMMY_END\$\$Base/)
+            {  # f3fc0000 g       *ABS*    00000000 Image$$CACHED_DUMMY_END$$Base
+
+				if(/^(\w+)\s+(\w+)\s+(.*)\s+(\w+)/)
+				{
+					$DUMMY_END_size = hex($4);
+					$DUMMY_END_base = "0x".$1;
+				}
+				next;
+			}
+            elsif ($bBegin ==2 and 
+                   $strLine =~ /^(\w+)\s+(\w+)\s+(\w+)\s+(\S+)\s+(\w+)\s+(\w+)$/)
+            {   # 7000a000 l    d  BL_GFH_SECTION   00000000 BL_GFH_SECTION
+				next if (($2 ne "g") && ($2 ne "l") && ($2 ne "w"));
+				next if (($3 ne "F") && ($3 ne "O"));
+				my $symbol_name = $6;
+				my $base_address = $1;
+				my $execution_region = $4;
+				my $size = $5;
+				$symbol{$symbol_name} = [$1, $2, $3, $4, $5];
+				next;
+			}
+            elsif ($bBegin ==2 and 
+                   $strLine =~ /^(\w+)\s+(\w+)\s+(\w+)\s+(\S+)\s+(\w+)\s+(\w+)\s+(\w+)$/)
+            {    # 901c2ae8 g     F ROM  00000048 0xf0 EL1D_LPWR_Other_Core_Has_Run_Determine
+                next if (($2 ne "g") && ($2 ne "l") && ($2 ne "w"));
+                next if (($3 ne "F") && ($3 ne "O"));
+                my $symbol_name = $7;
+                my $base_address = $1;
+                my $execution_region = $4;
+                my $size = $5;
+                $symbol{$symbol_name} = [$1, $2, $3, $4, $5];
+                next;
+            }
+			
+        }
+        close FILE_HANDLE;
+        &FixInputSectionLMAValue();
+        
+        #record parsed sym file path and file checksum
+        $g_PreviousParsedSYMPath = $g_SYMPath;
+        $g_PreviousParsedSYMChecksum = $SYMChecksum;
+    }
+    else
+    {
+        &SYM_die("SYM Path($g_SYMPath) doesn't exist", __FILE__, __LINE__);   
+    }    
+}
+
+sub ParseSymbolTable
+{
+    my ($strLine,$strObjName) = @_;
+    my $bSearched = 0;
+    my ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize);
+
+    if($strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+.+\\(\S+)\./
+     ||$strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+.+\/(\S+)\./)
+    {   #parse file name
+        #00000000 l    df *ABS*	00000000 protocol/as_multimode/dbme/src/db_io.c
+        $strObjName = $2.".obj";
+    }
+    elsif($strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+(\S+)\./)
+    {   #parse file name
+        #00000000 l    df *ABS*	00000000 db_io.c
+        $strObjName = $2.".obj";
+    }
+    elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\S+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/)
+    {#90338508 g     F ROM  0000002e 0xf0 FT_GetDiskFreeSpace
+        ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($7, "0x".$1, $2.$3, $4, hex($5));
+        $bSearched = 1;
+    }
+    elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/)
+    {#0001622c l     F ROM	000001b4 ast_hif_mcu_lisr_handler       
+        ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($6, "0x".$1, $2.$3, $4, hex($5));
+        $bSearched = 1;
+    }
+    elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/)
+    {#90004200 l       ROM	00000000 IRQ0_VEC
+        ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($5, "0x".$1, $2, $3, hex($4));
+        $bSearched = 1;
+    }
+    elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\S+\$\$\S+)$/)
+    {#f06185f1 g       CACHED_EXTSRAM	00000000 BUILD_TIME_RW$$Base
+        ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($5, "0x".$1, $2, $3, hex($4));
+        $bSearched = 1;
+    }
+   
+    if($bSearched)
+    {
+        if($strGroup ne "l" and $strGroup ne "ldf" and $strGroup ne "ld")
+        {#skip 00000000 l       *ABS*	00000000 MT6589
+         #skip 00000000 l    df *ABS*	00000000 ft_fnc_fat.c
+
+            ## parse linker symbol
+            if($strSymbolName =~ /\$\$/ and (($strGroup eq "g") or ($strGroup eq "w")))
+            {
+                $g_LinkerSymbol{$strSymbolName} = [$strAddress, $strGroup, $strRegion, $nSize];
+            }
+            
+            ##parse static symbol
+            elsif($strObjName and (($strGroup eq "lO") or ($strGroup eq "lF")))
+            {  
+                #******************************************
+                # Static symbol need to be merged
+                #
+                # Before merge:
+				# 900bcdf0 l     F ROM	00000230 ssleay_rand_add.part.0
+				# 900bd020 l     F ROM	00000008 ssleay_rand_add
+				#
+				# After merge:
+				# 900bcdf0 l     F ROM	00000238 ssleay_rand_add
+				#******************************************
+				
+                my $need_merge = ($strLine=~/\.part\./)?1:0;
+				
+                if($g_static_symbol_loookup{$strSymbolName.".".$strObjName} && ($need_merge || $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::NeedMerge]))
+                {
+                    if($g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Addr] <= $strAddress)
+                    {
+                        $strAddress = $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Addr];
+                    }
+                    else
+                    {
+                        delete $g_SymTable{$strAddress.".".$strSymbolName};
+                    }
+             
+                    $nSize += $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Size];
+                    $g_static_symbol_loookup{$strSymbolName.".".$strObjName} = [$strSymbolName,$strAddress, $strGroup, $strRegion, $nSize, $strObjName, $need_merge];
+                    $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName];
+                }
+                else
+                {
+                    $g_static_symbol_loookup{$strSymbolName.".".$strObjName} = [$strSymbolName,$strAddress, $strGroup, $strRegion, $nSize, $strObjName, $need_merge];
+                    $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName];
+                }
+            }
+            ## parse global symbol
+            else
+            {
+                print "$strAddress.$strSymbolName appears before\n" if(exists $g_SymTable{$strAddress.".".$strSymbolName});
+                $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize];
+            }
+        }
+        elsif($strGroup eq "l" && $strSymbolName =~ /\$\$/)
+        {# add this rule for GCC 4.9.2 
+         # 01400000 l       L1CORE_RWZI	00000000 Image$$L1CORE_RWZI$$ZI$$Base
+            $g_LinkerSymbol{$strSymbolName} = [$strAddress, $strGroup, $strRegion, $nSize];
+        }        
+    }
+    return $strObjName;
+}
+
+#****************************************************************************
+# subroutine:  GetSymbolTable
+# input:       N/A
+# output:      get all symbol table in .sym file
+#
+#****************************************************************************
+sub GetSymbolTable
+{
+    my @symbol = values %g_SymTable;
+    return \@symbol;    
+}
+
+#****************************************************************************
+# subroutine:  GetSymbol
+# input:       N/A
+# output:      get all symbol info in .sym file
+# NOTE:       The info for global symbol is right; 
+#                 but for static symbol which has same name with other symbol, the info maybe wrong.
+#****************************************************************************
+sub GetSymbol
+{
+    return \%symbol;    
+}
+
+sub GetLinkerSymbol
+{
+    return \%g_LinkerSymbol;
+}
+
+sub GrepSymbolBySection
+{
+    my ($strSection) = @_;
+    my @SymKeys = sort { hex($g_SymTable{$a}->[SymTable::Addr]) <=> hex($g_SymTable{$b}->[SymTable::Addr]) } 
+                  grep{$g_SymTable{$_}->[SymTable::Region] eq $strSection} keys %g_SymTable;
+    #map {print $_."\n"} @SymKeys;
+    my @SymInfo = map {$g_SymTable{$_}} @SymKeys;
+    return \@SymInfo;
+}
+
+sub GrepSymbolByOutputSection
+{
+    my ($strSection) = @_;
+    my $strStart = GetLinkerSymbolAddress($strSection, LinkerSymPostfix::Base, LinkerSymPrefix::Image);
+    my $strEnd = GetLinkerSymbolAddress($strSection, LinkerSymPostfix::ZILimit, LinkerSymPrefix::Image);
+    my @SymInfo;
+
+    if((hex($strEnd) - hex($strStart)) > 0)
+    {
+        my @SymKeys = sort { hex($g_SymTable{$a}->[SymTable::Addr]) <=> hex($g_SymTable{$b}->[SymTable::Addr]) } 
+                      grep{(hex($g_SymTable{$_}->[SymTable::Addr]) >= hex($strStart)) and  
+                           (hex($g_SymTable{$_}->[SymTable::Addr]) < hex($strEnd  ))} keys %g_SymTable;
+        @SymInfo = map {$g_SymTable{$_}} @SymKeys;
+    }
+    return \@SymInfo;
+}
+
+#****************************************************************************
+# subroutine:  GetLinkerSymbolAddress
+# input:       $strRegionName, $nLocation, $nRegionType
+# output:     $strAddr
+# NOTE:      
+#                nRegionType = 0: Execution Region
+#                nRegionType = 1: Load Region
+#                nRegionType = 2: Input Section
+#****************************************************************************
+sub GetLinkerSymbolAddress
+{
+    my ($strRegionName, $nLocation, $nRegionType) = @_;
+    my $strPrefix = 'Image$$';
+    if($nRegionType == 1)
+    {
+        $strPrefix = 'Load$$' ;
+        $nLocation = 0;
+    }
+    elsif($nRegionType == 2)
+    {
+        $strPrefix = "";    
+    }
+    my $strPostfix = '$$Base';  #LinkerSymPostfix::Base
+    $strPostfix = '$$Limit'     if($nLocation == LinkerSymPostfix::Limit);
+    $strPostfix = '$$ZI$$Base'  if($nLocation == LinkerSymPostfix::ZIBase);
+    $strPostfix = '$$ZI$$Limit' if($nLocation == LinkerSymPostfix::ZILimit);
+    $strPostfix = '$$Length'    if($nLocation == LinkerSymPostfix::Length);
+    $strPostfix = '$$ZI$$Length'if($nLocation == LinkerSymPostfix::ZILength);
+    my $strSymbolName = $strPrefix.uc($strRegionName).$strPostfix;
+    my $strAddr = undef;
+    $strAddr = $g_LinkerSymbol{$strSymbolName}->[0] if(exists $g_LinkerSymbol{$strSymbolName});
+    return $strAddr;
+}
+
+#****************************************************************************
+# subroutine:  Get_DUMMY_END_Size
+# input:       N/A
+# output:      size of DUMMY_END region
+#****************************************************************************
+sub Get_DUMMY_END_Size
+{
+	return $DUMMY_END_size;
+}
+
+#****************************************************************************
+# subroutine:  Get_DUMMY_END_Base
+# input:       N/A
+# output:      base address of DUMMY_END region
+#****************************************************************************
+sub Get_DUMMY_END_Base
+{
+	return $DUMMY_END_base;
+}
+
+#****************************************************************************
+# subroutine:  StoreIntoTempFile
+# input:       N/A
+# output:      temp files which contain perl data structure
+#****************************************************************************
+use Storable qw/lock_nstore/;
+sub StoreIntoTempFile
+{
+	my ($strPath) = @_;
+	my $file = $strPath."\\SymParser_Temp.dat";
+	my %tempfile;
+
+	$tempfile{"execution_region"} = \%g_ExeRegion;
+	$tempfile{"symbol_info"} = \%symbol;
+
+	lock_nstore \%tempfile, $file;
+}
+
+#****************************************************************************
+# subroutine:  ParseInputSection. used by ParseSYM to parse Execution Region Attribute
+# input:  1. Execution Name, 2. $strLine
+# output: x     
+#****************************************************************************
+sub ParseInputSection
+{
+    my ($strExeRegionName, $strLine) = @_;
+    return if(!defined $strExeRegionName);#setting for $strExeRegionName = undef
+    
+    my $attr = undef;
+    chomp($strLine);
+    if($strLine =~ /\s+(.*)/)
+    {
+        #CONTENTS, ALLOC, LOAD, READONLY, DATA
+        $Attr{$strExeRegionName} = $1;
+    }
+}
+
+#****************************************************************************
+# subroutine:  FixInputSectionLMAValue is used to fix the wrong LMA value
+#              record in InputSection
+# input: x
+# output: x     
+#****************************************************************************
+sub FixInputSectionLMAValue
+{
+    while(my($strSymbolName, $arySymbolDataRef) = each %g_LinkerSymbol)
+    {
+        my @arySymbolData = @$arySymbolDataRef;# arySymbolData: 0x00760eb0 g *ABS* 0
+        #print "arySymbolData: @arySymbolData \n"; 
+        if($strSymbolName =~ /Load\$\$(\S+)\$\$Base/)# $strSymbolName = Load$$EXTSRAM_DSP_RX$$Base
+        {# Load$$EXTSRAM_DSP_RX$$Base
+            my $strExeRegionName = $1;# $strExeRegionName = EXTSRAM_DSP_RX
+            
+            #check if $strExeRegionName exist in $g_ExeRegionLookUpTable
+            if(exists $g_ExeRegionLookUpTable{$strExeRegionName})
+            {   
+                #extract the correct LMA value record in SymbolTable
+                my $strCorrectLMAValue = $arySymbolData[LinkerSymbol::Addr];
+                $strCorrectLMAValue =~ s/0x//;
+                #print "strCorrectLMAValue: $strCorrectLMAValue \n";
+                
+                #fix LMA value stored in %g_ExeRegion
+                my $lookupIndex = $g_ExeRegionLookUpTable{$strExeRegionName};
+                #print "look up index: ".$lookupIndex."\n";               
+                $g_ExeRegion{$lookupIndex}[Region::LMA] = $strCorrectLMAValue;               
+            }
+        }
+    }
+}
+
+#****************************************************************************
+# subroutine:  ListAllExeRegion
+# input:       $bTrimDebugRegion: 1= NeedtoTrimDebugRegion, 0 or undef=NoNeedToTrimDebugRegion
+# output:      Execution Region List 
+#****************************************************************************
+sub ListAllExeRegion
+{
+    my ($bTrimDebugRegion) = @_;
+	my @k = keys %g_ExeRegion;
+	my @ExeRegion;
+	my $ExeRegion_aref = undef;
+    for (my $i = 0; $i <= $#k; $i++)
+	{
+		push(@ExeRegion,$g_ExeRegion{$i}->[0]);
+	}
+	$ExeRegion_aref = \@ExeRegion;
+	if($bTrimDebugRegion)
+	{
+	    $ExeRegion_aref = TrimDebugRegion(\@ExeRegion);
+	}
+	return $ExeRegion_aref;
+}
+#****************************************************************************
+# subroutine:  TrimDebugRegion
+# input:       All Regions in array reference
+# output:      Execution Region List(array reference) after trimming
+#****************************************************************************
+sub TrimDebugRegion
+{
+    my ($ERs_aref) = @_;
+    my @RealERs;
+    foreach my $region (@$ERs_aref)
+    {
+        if ( $region !~ /^\.debug_/
+         and $region !~ /^\.ARM\.attributes/
+         and $region !~ /^\.comment/
+         and $region !~ /^\.stab/
+         and $region ne "")
+        {
+            push(@RealERs , $region);
+        }
+    }
+    return \@RealERs;
+}
+
+#****************************************************************************
+# subroutine:  GetExeRegionInfo
+# input:       Execution Region Name, $nOption
+#              $nOption = Region::VMA or Region::LMA or Region::Size 
+#                         or Region::Offsets or Region::Align or Region::Attr
+# output:      string of corresponding Execution Region Infomation 
+#****************************************************************************
+sub GetExeRegionInfo
+{	
+	# Name          Size      VMA       LMA       File off  Algn
+	my ($strExeRegionName, $nOption) = @_;
+	my $index = $g_ExeRegionLookUpTable{$strExeRegionName};
+	my @ExeRegionInfo;
+	my $strInfo;
+	my @k = keys %g_ExeRegion;
+	my $key_count = $#k + 1;
+	for (my $i = 0; $i <= $#k; $i++)
+	{
+		my $string = $g_ExeRegion{$i}->[0];
+		next if ($string ne $strExeRegionName);
+	}
+	
+	if ($nOption == Region::Size)
+	{
+		$strInfo = "0x".$g_ExeRegion{$index}->[Region::Size];
+	}
+	elsif ($nOption == Region::VMA)
+	{
+		$strInfo = "0x".$g_ExeRegion{$index}->[Region::VMA];
+	}
+	elsif ($nOption == Region::LMA)
+	{
+		$strInfo = "0x".$g_ExeRegion{$index}->[Region::LMA];
+	}
+    elsif ($nOption == Region::Offsets)
+	{
+        $strInfo = "0x".$g_ExeRegion{$index}->[Region::Offsets];
+	}
+	elsif ($nOption == Region::Align)
+	{
+		$strInfo = $g_ExeRegion{$index}->[Region::Align];
+	}
+	elsif ($nOption == Region::Attr)
+	{
+		$strInfo = $Attr{$strExeRegionName};
+	}
+	
+	return $strInfo;
+}
+
+#****************************************************************************
+# subroutine:  FootprintAnalyzeBySymbol
+# input:       $strSymName: Symbol Name (Case sensitive)
+# output:      symbol info array reference
+#****************************************************************************
+sub FootprintAnalyzeBySymbol
+{
+	return undef;
+}
diff --git a/mcu/tools/MemoryUtility/TCMMargin.pl b/mcu/tools/MemoryUtility/TCMMargin.pl
new file mode 100644
index 0000000..0c4e078
--- /dev/null
+++ b/mcu/tools/MemoryUtility/TCMMargin.pl
@@ -0,0 +1,195 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   TCMmargin.pl

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   This perl is used to get TCM margin

+#*       

+#*

+#* Author:

+#* -------

+#*   Carl Kao (mtk08237)

+#*

+#****************************************************************************/

+

+BEGIN { push @INC, "./" , '../', './tools/', './tools/MemoryUtility/' }  # add additional library path

+use systemInfo;

+use LinkerOutputParser;

+use CommonUtility;

+use FileInfoParser;

+use strict;

+

+#****************************************************************************

+# Constants

+#****************************************************************************

+my $TCMMARGIN_VERNO     = " LR12_v0.01";

+             # LR12_v0.01 , 2016/01/25,  Memory Utility Refinement for LR12 

+             # u0.01 , 2015/01/19,  Memory Utility Refinement for LR11

+             # m0.03 , 2012/08/03,  Shows more TCM information(Physical size)

+             # m0.02 , 2012/08/03,  Push additional library path

+             # m0.01 , 2012/07/21,  Initial revision

+

+#****************************************************************************

+# Global variable

+#****************************************************************************

+my $DebugPrint = 0;

+

+#****************************************************************************

+# Subroutine:  TCMmargin_verno - to query this package's version number

+# Parameters:  x

+# Returns:     version number string

+#****************************************************************************

+sub TCMmargin_verno

+{

+    return $TCMMARGIN_VERNO;

+}

+

+#****************************************************************************

+# 1 >>>  Get in put parameters

+#****************************************************************************

+&Usage() if($#ARGV != 2);

+my ($makeFile, $memorymapfile, $linkeroutputfile) = @ARGV;

+

+#****************************************************************************

+# 2 >>>  Parse make file

+#****************************************************************************

+my %MAKEFILE_OPTIONS;

+&FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS);

+

+#****************************************************************************

+# 3 >>>  Calculate TCM margin

+#****************************************************************************

+&CalcTCMmargin();

+

+#****************************************************************************

+# oo >>>  Finished

+#****************************************************************************

+exit 0;

+

+#****************************************************************************

+# subroutine:  CalcTCMmargin - calculate TCM margin

+# Input:       x

+# Output:      x

+#****************************************************************************

+sub CalcTCMmargin

+{

+    my %ChipInsideRam_region;

+    my $nChipInsideRAMnum = 0;

+    my %ChipInsideRAMinfo;

+    my $TCMmargin_href;

+

+    # Get all chipInsideRAM regions

+    $nChipInsideRAMnum =  &sysInfo::GetChipInsideRAMregion($memorymapfile, \%ChipInsideRam_region, \%MAKEFILE_OPTIONS);

+

+    # Parse link output file

+    &LinkerOutputParser::FileParse($linkeroutputfile);

+    

+    # Get the size of all chipInsideRAM regions and store to a Hash

+    foreach my $strRegionName (keys %ChipInsideRam_region)

+    {

+        $ChipInsideRAMinfo{$strRegionName}[0] =   # 0: size

+            &LinkerOutputParser::GetTotalSizeByExeRegion($strRegionName);

+        $ChipInsideRAMinfo{$strRegionName}[1] =   # 1: VMA

+            &LinkerOutputParser::GetVMAByExeRegion($strRegionName);

+    }

+

+    # Get TCM margin via the Hash content TCM size info

+    $TCMmargin_href =  &sysInfo::GetTCMmargin($memorymapfile, \%ChipInsideRAMinfo, \%MAKEFILE_OPTIONS);

+    

+    # Print TCM margin

+    print ("-------------------------------------------------------------------\n");

+    

+    my @sorted_keys = sort {

+        my @aa = $a =~ /^([A-Za-z]+)(\d*)$/;

+        my @bb = $b =~ /^([A-Za-z]+)(\d*)$/;

+        $aa[1] <=> $bb[1] or lc $aa[0] cmp lc $bb[0];

+    } keys %$TCMmargin_href;

+    

+    # foreach my $strRegionname (sort keys %$TCMmargin_href) # old way, no sort

+    for (my $i=0; $i<2; ++$i)

+    {

+        foreach (@sorted_keys)

+        {

+            my $strRegionname = $_;

+            

+            next if ( $i == 0 && $strRegionname !~ /\d$/ ); # show per-core part in first round

+            next if ( $i == 1 && $strRegionname =~ /\d$/ ); # show common part in first round

+            

+            printf("%10s %20s 0x%08x = %8d bytes = %5d KB\n", $strRegionname, "physical size = ", 

+                                                $TCMmargin_href->{$strRegionname}->[0], 

+                                                $TCMmargin_href->{$strRegionname}->[0], 

+                                                $TCMmargin_href->{$strRegionname}->[0]/1024);

+            printf("%10s %20s 0x%08x = %8d bytes = %5d KB \n", $strRegionname, "margin = ", 

+                                                $TCMmargin_href->{$strRegionname}->[1], 

+                                                $TCMmargin_href->{$strRegionname}->[1],

+                                                $TCMmargin_href->{$strRegionname}->[1]/1024);

+            #reserve for debugging

+            #printf("%10s %20s 0x%08x KB \n", $strRegionname, "end addr = ", ($TCMmargin_href->{$strRegionname}->[0]-$TCMmargin_href->{$strRegionname}->[1]));

+            print ("-------------------------------------------------------------------\n");

+        }

+    }

+}

+

+#****************************************************************************

+# subroutine:  Usage - usage template

+# Input:       x

+# Output:      x

+#****************************************************************************

+sub Usage

+{

+  print <<"__EOFUSAGE";

+

+usage: perl TCMMargin.pl makefile_path scatter_file_path/lds_file_path lis_file_path/sym_file_path 

+

+NOTE: scatter file should input with lis file

+      lds file should input with sym file

+

+e.g. 

+perl TCMMargin.pl "/[path]/MT6280_R7R8_HSPA(FULL_VERSION_RVCT).mak" "/[path]/scatMT6280_R7R8.txt" "/[path]/MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.lis"

+

+__EOFUSAGE

+

+  exit 1;

+}

+

diff --git a/mcu/tools/MemoryUtility/TCMQuery.pl b/mcu/tools/MemoryUtility/TCMQuery.pl
new file mode 100644
index 0000000..816d620
--- /dev/null
+++ b/mcu/tools/MemoryUtility/TCMQuery.pl
@@ -0,0 +1,801 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   TCMQuery.pl

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   This script is used to get symbol, object, and section information from sym file

+#* 

+#*

+#* Author:

+#* -------

+#*   Carl Kao (mtk08237)

+#*

+#*------------------------------------------------------------------------------

+#* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!

+#*============================================================================

+#****************************************************************************/

+#****************************************************************************

+# Included Modules

+#****************************************************************************

+use strict;

+BEGIN { push @INC, "./" , '../', './tools/', './tools/MemoryUtility/' }

+use LinkerOutputParser;

+use File::Basename;

+use POSIX;

+

+my $TCMQuery_VERNO     = " LR12_v0.03";

+                         # LR12_v0.03 , 2016/01/25,  Memory Utility Refinement for LR12

+                         # LR12_v0.02 , 2016/12/15,  fix memory utility .map file parsing feature for LR12 (64bit address)

+                         # LR12_v0.01 , 2016/10/26,  add GrepSymbolByInputSection feature to memory utility

+                         # u0.01 , 2015/01/19,  Initial revision for Memory Utility Refinement for LR11

+

+&Usage() if (($#ARGV != 2) && ($#ARGV != 3)); 

+

+my ($option, $region, $file1, $file2) = @ARGV;

+

+$file1 =~ s/\\/\\\\/;

+$file2 =~ s/\\/\\\\/;

+

+if(($option eq "-Q") || ($option eq "-q"))

+{

+    &TCMQuery($region, $file1);

+}

+elsif(($option eq "-C") || ($option eq "-c"))

+{

+    &TCMCompare($region, $file1, $file2);

+}

+elsif(($option eq "-S") || ($option eq "-s"))

+{

+    my @SymbolInfo; #[[SymbolName, address, size], ...] sorted by address

+    GetSymbolBySection($file1, $region, \@SymbolInfo);

+    ListAllSymbolInfo(\@SymbolInfo);

+}

+elsif(($option eq "-IS") || ($option eq "-is"))

+{

+    my @SymbolInfo; #[[SymbolName, Address, ObjectName, LibName, OutputSectionName, InputSectionName, InputSectionSize, SymbolSize], ...] sorted by address

+    GetSymbolByOutputSection($file1, $file2, $region, \@SymbolInfo);

+    ListAllSymbolAsMachineReadable(\@SymbolInfo, $region);

+}

+elsif(($option eq "-SC") || ($option eq "-sc"))

+{

+    my @SymbolInfo1; #[[SymbolName, address, size], ...] sorted by address

+    GetSymbolBySection($file1, $region, \@SymbolInfo1);

+    my @SymbolInfo2; #[[SymbolName, address, size], ...] sorted by address

+    GetSymbolBySection($file2, $region, \@SymbolInfo2);

+    my $diff_href = DiffSymbolInfo(\@SymbolInfo1, \@SymbolInfo2);

+    ListDiffSymbolInfo($diff_href, 0);

+}

+elsif(($option eq "-SCE") || ($option eq "-sce")) # section compare only in empty symbol

+{

+    my @SymbolInfo1; #[[SymbolName, address, size], ...] sorted by address

+    GetSymbolBySection($file1, $region, \@SymbolInfo1);

+    my @SymbolInfo2; #[[SymbolName, address, size], ...] sorted by address

+    GetSymbolBySection($file2, $region, \@SymbolInfo2);

+    my $diff_href = DiffSymbolInfo(\@SymbolInfo1, \@SymbolInfo2);

+    ListDiffSymbolInfo($diff_href, 1);

+}

+elsif(($option eq "-SO") || ($option eq "-so")) # parse symbols in specific lib

+{

+    my @SymbolInfo;

+    my $str_obj = $region;

+    GetSymbolByObj($file1,$file2,$str_obj,\@SymbolInfo);

+    ListAllSymbolAsMachineReadable(\@SymbolInfo,$str_obj);

+}

+elsif(($option eq "-SL") || ($option eq "-sl")) # parse symbols in specific obj

+{

+    my @SymbolInfo;

+    my $str_lib = $region;

+    GetSymbolByLib($file1,$file2,$str_lib,\@SymbolInfo);

+    ListAllSymbolAsMachineReadable(\@SymbolInfo,$str_lib);

+}

+elsif(($option eq "-ST") || ($option eq "-st")) # parse symbols whose size greater than specific size.

+{

+    my @SymbolInfo;

+    my $sym_size = $region;

+    GetSymbolByThreshold($file1,$file2,$sym_size,\@SymbolInfo);

+    ListAllSymbolAsMachineReadable(\@SymbolInfo,$sym_size);

+}

+elsif(($option eq "-SF") || ($option eq "-sf")) # parse fill info

+{

+    my $FillInfo_href;

+    &LinkerOutputParser::FileParse($region);

+    $FillInfo_href = &LinkerOutputParser::GetFillInfo();

+    ListFillInfo($FillInfo_href);

+}

+else

+{

+    &Usage();

+}

+

+sub GetSymbolBySection

+{

+    my ($symfile, $strSection, $SymbolInfo_aref) = @_;

+    LinkerOutputParser::FileParse($symfile);

+    my @regions = split(/\,/, $strSection);

+    foreach my $section (@regions)

+    {

+        if($section =~ /SPRAM/i or $section eq "L2SRAM")

+        {

+            my $exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1);

+            if (defined $exeregion_aref)

+            {

+                foreach my $temp(@$exeregion_aref)

+                {

+                    if ($temp =~ /$section/i)

+                    {

+                        my $temp1_aref = LinkerOutputParser::GrepSymbolBySection($temp);

+                        push @$SymbolInfo_aref, @$temp1_aref;

+                    }

+                }

+            }

+        }

+        else

+        {

+            my $temp_aref = LinkerOutputParser::GrepSymbolBySection($section);

+            push(@$SymbolInfo_aref , @$temp_aref);

+        }    

+    }

+}

+

+sub GetSymbolByOutputSection

+{

+    my ($mapfile, $symfile, $strSectionNameInRegularExp, $SymbolInfo_aref) = @_;

+    my $temp_aref;

+    

+    LinkerOutputParser::FileParse($symfile);

+

+    #list all symbol

+    if($strSectionNameInRegularExp =~ /^all$/)

+    {

+	    $temp_aref = GetAllSymbol($symfile);

+    }

+    else

+    {

+	    $temp_aref = LinkerOutputParser::GrepSymbolByOutputSection($strSectionNameInRegularExp);

+    }

+    

+    # remove inline functions

+    my $idx=0;

+    foreach (@{$temp_aref}) 

+    {   

+        delete @{$temp_aref}[$idx] if(@$_[3] eq "00000000"); 

+        $idx++;

+    }

+    @{$temp_aref} = grep { defined($_) } @{$temp_aref};

+

+    # append symbol obj/lib name to array if symbol exist in map file 

+    AppendLibAttriToSymbol($mapfile,$temp_aref);

+    push @$SymbolInfo_aref, @$temp_aref;

+}

+

+sub GetSymbolByObj{

+    my ($mapfile, $symfile, $str_obj, $SymbolInfo_aref) = @_;

+

+    my $symbol_aref = GetAllSymbol($symfile);

+    AppendLibAttriToSymbol($mapfile, $symbol_aref);

+ 

+    #list all symbol

+    if($str_obj =~ /^all$/)

+    {

+        push(@$SymbolInfo_aref,@$symbol_aref);

+    }

+    else

+    {

+        my %obj = map{$_.".obj" => 1} split(/\,/, $str_obj);

+        foreach(@{$symbol_aref})

+        {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName]

+            push(@$SymbolInfo_aref,$_) if($_->[5] && $obj{$_->[5]});

+        }    

+    }    

+}

+

+sub GetSymbolByLib{

+    my ($mapfile, $symfile, $str_lib, $SymbolInfo_aref) = @_;

+

+    my $symbol_aref = GetAllSymbol($symfile);

+    AppendLibAttriToSymbol($mapfile, $symbol_aref);

+  

+    #list all symbol

+    if($str_lib =~ /^all$/)

+    {

+        push(@$SymbolInfo_aref,@$symbol_aref);

+    }

+    else

+    {     

+        my %lib = map{$_.".a" => 1} split(/\,/, $str_lib);

+        foreach(@$symbol_aref)

+        {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName]

+            push(@$SymbolInfo_aref,$_) if($_->[6] && $lib{$_->[6]});

+        }    

+    } 

+}

+

+sub GetSymbolByThreshold{

+    my ($mapfile, $symfile, $sym_size, $SymbolInfo_aref) = @_;

+

+    my $symbol_aref = GetAllSymbol($symfile);

+    AppendLibAttriToSymbol($mapfile, $symbol_aref);

+

+    #list all symbol

+    foreach(@$symbol_aref)

+    {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName]

+        push(@$SymbolInfo_aref,$_) if($_->[4] >= $sym_size);

+    }    

+}

+

+sub DiffSymbolInfo

+{

+    my ($SymInfo1_aref, $SymInfo2_aref) = @_;

+    my %diff;

+    foreach my $item (@$SymInfo1_aref)

+    {

+        if(!exists $diff{$item->[SymTable::Name]})

+        {

+            $diff{$item->[SymTable::Name]} = [ $item->[SymTable::Size] , -1, $item->[SymTable::Region]];

+        }

+        else

+        {

+            $diff{$item->[SymTable::Name]."+"} = [ $item->[SymTable::Size] , -1, $item->[SymTable::Region]];

+        }

+    }

+    foreach my $item (@$SymInfo2_aref)

+    {

+        if(exists $diff{$item->[SymTable::Name]})

+        {

+            $diff{$item->[SymTable::Name]}[1] = $item->[SymTable::Size];

+        }

+        else

+        {

+            $diff{$item->[SymTable::Name]} = [ -1, $item->[SymTable::Size], $item->[SymTable::Region]];

+        }

+    }

+    return \%diff;

+}

+

+sub ListDiffSymbolInfo

+{

+    my ($diff_href, $bListEmptyOnly) = @_;

+    print "   $file1 \nvs. $file2\n";

+    print "SymbolName                                                                      Size1             Size2\n";

+    print "*********************************************************************************************************************\n";

+    my $strRegion;

+    my ($nTotalSize1, $nTotalSize2) = (0,0);

+    foreach my $key (sort keys %$diff_href)

+    {

+        my $strSize1 = $diff_href->{$key}[0] eq "-1" ? "" : $diff_href->{$key}[0];

+        my $strSize2 = $diff_href->{$key}[1] eq "-1" ? "" : $diff_href->{$key}[1];

+        next if(($strSize1 eq $strSize2));

+        if($bListEmptyOnly)

+        {

+            next if(!($diff_href->{$key}[0] eq "-1" or $diff_href->{$key}[1] eq "-1"));

+        }

+        $nTotalSize1 += $strSize1;

+        $nTotalSize2 += $strSize2;

+        $~ = "DIFF";

+        format DIFF =

+@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<<

+$key,$strSize1,$strSize2

+.

+write;

+    }

+    print "*********************************************************************************************************************\n";

+    $~ = "TOTALDIFF";

+    format TOTALDIFF = 

+@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<<

+'Total',$nTotalSize1,$nTotalSize2

+.

+write;

+}

+

+sub ListAllSymbolInfo

+{

+    my ($SymInfo_aref) = @_;

+    print "[Section]\n";

+    print "Address       Size    Group            Symbol Name\n";

+    print "*********************************************************************************************************************\n";

+    my $strSection;

+    my $nNextAddress = 0;

+    my $nIndex = 0;

+    foreach my $item (@$SymInfo_aref)

+    {

+        if($item->[SymTable::Region] ne $strSection)

+        {

+            $strSection = $item->[SymTable::Region];

+            print "[$strSection]\n";

+        }

+        

+        my $nSize = $item->[SymTable::Size];

+        my $strSize = $nSize;

+        if($nSize == 0)

+        {

+            if($nIndex+1 < scalar(@$SymInfo_aref) and $SymInfo_aref->[$nIndex+1][SymTable::Region] eq $strSection)

+            {

+                $nSize = hex($SymInfo_aref->[$nIndex+1][SymTable::Addr]) - hex($item->[SymTable::Addr]) ;

+            }

+            else

+            {

+                $nSize = "--";

+            }

+            $strSize = "0($nSize)";

+        }

+        $~ = "SYMBOLS";

+        format SYMBOLS =

+@<<<<<<<<<<<<<@<<<<<<<<<@<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

+$item->[SymTable::Addr],$strSize,$item->[SymTable::Group],$item->[SymTable::Name],

+.

+write;

+        $nIndex++;

+    }

+}

+

+sub ListAllSymbolInfoBySpecify

+{

+    my ($SymInfo_aref, $str_specify) = @_;

+

+    #calculate each string elements' max length

+    my @maxLengAry = ( length("SymbolName"), length("Address"), length("Attr"), length("OutputSectionName"), length("SymbolSize"), length("ObjectName"), length("LibName") );

+    CalStringMaxLength($SymInfo_aref, \@maxLengAry);

+    my $totalAryLength = 0;

+    my $strFormatStr = "";

+    

+    for ( @maxLengAry ) 

+    {

+        $_ += 4;

+        $totalAryLength += $_;

+    }     

+

+    my $nTotalSize = 0;

+

+    print "Specified parameter: $str_specify\n";

+

+    print "LibName"           . " " x ($maxLengAry[6]-length("LibName"))            .       # libc.a

+          "ObjectName"        . " " x ($maxLengAry[5]-length("ObjectName"))         .       # lib_a-memcpy.o

+          "Address"           . " " x ($maxLengAry[1]-length("Address"))            .       # 0x943a0000

+          "Attr"              . " " x ($maxLengAry[2]-length("Attr"))               .       # gF

+          "OutputSectionName" . " " x ($maxLengAry[3]-length("OutputSectionName"))  .       # CACHED_EXTSRAM_L2CACHE_LOCK_DATA

+          "SymbolSize"        . " " x ($maxLengAry[4]-length("SymbolSize"))         .       # 924

+          "SymbolName"        . " " x ($maxLengAry[0]-length("SymbolName"))         . "\n"; # memcpy

+

+    print "*" x $totalAryLength . "\n";

+    

+    foreach (sort{ $a->[6] cmp $b->[6] #sort by lib 

+      or $a->[5] cmp $b->[5] #sort by obj

+      or $a->[1] cmp $b->[1] #sort by address

+      } @$SymInfo_aref) 

+    {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize, $strObjName, $strLibName];

+        next if ($_->[4] == 0);#skip symbol whose size is 0.

+        printf("%-${maxLengAry[6]}s", "@$_[6]"); #LibName

+        printf("%-${maxLengAry[5]}s", "@$_[5]"); #ObjectName

+        printf("%-${maxLengAry[1]}s", "@$_[1]"); #Address

+        printf("%-${maxLengAry[2]}s", "@$_[2]"); #Attr

+        printf("%-${maxLengAry[3]}s", "@$_[3]"); #OutputSectionName

+        printf("%-${maxLengAry[4]}s", "@$_[4]"); #SymbolSize

+        printf("%-${maxLengAry[0]}s", "@$_[0]"); #SymbolName

+        print "\n";

+        $nTotalSize += @$_[4];

+    }

+    print "*" x $totalAryLength . "\n"; 

+    printf("Total size: %d bytes, %.3f KB\n\n\n", $nTotalSize, $nTotalSize/1024);

+}

+

+

+sub ListAllSymbolAsMachineReadable

+{

+

+    my ($SymInfo_aref, $str_specify) = @_;

+    #my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); 

+    #my $now = sprintf("%04d-%02d-%02d %02d:%02d:%06s", $year+1900, $mon+1, $mday, $hour, $min, $sec.".000");

+    

+    print "LibName,ObjectName,Address,Attr,OutputSectionName,SymbolSize,SymbolName\n"; 

+    

+    foreach (sort{ $a->[6] cmp $b->[6] #sort by lib 

+      or $a->[5] cmp $b->[5] #sort by obj

+      or $a->[1] cmp $b->[1] #sort by address

+      or $a->[0] cmp $b->[0] #sort by symbol name

+      } @$SymInfo_aref) 

+    {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize, $strObjName, $strLibName];

+        next if ($_->[4] == 0); #skip symbol whose size is 0.

+        #printf("%s,",$now); #timestamp

+        printf("%s,", "@$_[6]"); #LibName

+        printf("%s,", "@$_[5]"); #ObjectName

+        printf("%s,", "@$_[1]"); #Address

+        printf("%s,", "@$_[2]"); #Attr

+        printf("%s,", "@$_[3]"); #OutputSectionName

+        printf("%s,", "@$_[4]"); #SymbolSize

+        printf("%s", "@$_[0]"); #SymbolName

+        print "\n";

+    }

+}

+

+sub ListFillInfo

+{

+    my ($FillInfo_href) = @_;

+    

+    print "Address,Fill_Size,Attr,Object_Info,Libinfo\n";

+    

+    foreach (sort{$$FillInfo_href{$a}->[0] cmp $$FillInfo_href{$b}->[0]} keys %{$FillInfo_href}) 

+    {

+        printf("%s,", $$FillInfo_href{$_}->[0]); 

+        printf("%s,", $$FillInfo_href{$_}->[1]); 

+        printf("%s,", $$FillInfo_href{$_}->[2]);

+        printf("%s,", $$FillInfo_href{$_}->[3]); 

+        printf("%s", $$FillInfo_href{$_}->[4]) if $$FillInfo_href{$_}->[4];

+        print "\n";

+    }

+}

+

+sub TCMQuery

+{

+    my ($ExeRegion, $file) = @_;

+    

+    my ($objs_aref, $RO_href, $RW_href, $ZI_href) = &GetAllOBJ($ExeRegion, $file);

+    print "Object_Name                                   RO_Size             RW_Size            ZI_Size\n";

+    print "***********************************************************************************************\n";

+

+    my $total_RO;

+    my $total_RW;

+    my $total_ZI;

+    

+    foreach my $temp(sort @$objs_aref)

+    {

+        $~ = "LIS_QUERY";

+        format LIS_QUERY = 

+@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<

+$temp,$$RO_href{$temp},$$RW_href{$temp},$$ZI_href{$temp}

+.

+        

+write;

+            $total_RO += $$RO_href{$temp};

+            $total_RW += $$RW_href{$temp};

+            $total_ZI += $$ZI_href{$temp};          

+    }

+    $~ = "LIS_QUERY_TOTAL";

+    format LIS_QUERY_TOTAL = 

+@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<

+"Total",$total_RO,$total_RW,$total_ZI

+.

+        

+write;

+    

+    print "***********************************************************************************************\n";

+}

+

+sub TCMCompare

+{

+    my ($ExeRegion, $file1, $file2) = @_;

+    my ($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href, $objs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href);

+   

+    ($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href) = &GetAllOBJ($ExeRegion, $file1);

+    ($objs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href) = &GetAllOBJ($ExeRegion, $file2);

+    

+    my @objs1 = @$objs1_aref;

+    my @objs2 = @$objs2_aref;

+

+    my %objs1 = map{$_ => 1} @objs1;

+    my %objs2 = map{$_ => 1} @objs2;

+    my @arr = map{$_ => 1} @objs1; 

+

+    my @inter = grep {$objs1{$_}} @objs2;

+

+    my %merge = map {$_ => 1} @objs1,@objs2; 

+    my @merge = sort keys (%merge);

+

+    my @objs1_only = grep {!$objs2{$_}} @merge;

+    my @objs2_only = grep {!$objs1{$_}} @merge;

+

+    print "Compare result as below:\n";

+

+

+        print "**************************************************************************************************************************************\n";

+        print "                                               Codebase1                           Codebase2                              Diff\n";

+        print "ObjectName                                ROSize;RWSize;ZISize                ROSize;RWSize;ZISize                ROSize;RWSize;ZISize\n";

+        print "**************************************************************************************************************************************\n";

+

+        my $total_RO_1 = 0;

+        my $total_RW_1 = 0;

+        my $total_ZI_1 = 0;

+        my $total_RO_2 = 0;

+        my $total_RW_2 = 0;

+        my $total_ZI_2 = 0;

+        my $total_RO_diff = 0;

+        my $total_RW_diff = 0;

+        my $total_ZI_diff = 0;

+        my $total_codebase1;

+        my $total_codebase2;

+        my $total_diff;

+        

+        foreach my $obj(@merge)

+        {

+            $$RO_2_href{$obj} = 0 if(!defined $$RO_2_href{$obj});

+            $$RO_1_href{$obj} = 0 if(!defined $$RO_1_href{$obj});

+            $$RW_2_href{$obj} = 0 if(!defined $$RW_2_href{$obj});

+            $$RW_1_href{$obj} = 0 if(!defined $$RW_1_href{$obj});

+            $$ZI_2_href{$obj} = 0 if(!defined $$ZI_2_href{$obj});

+            $$ZI_1_href{$obj} = 0 if(!defined $$ZI_1_href{$obj});

+            

+            my $RO_diff = $$RO_2_href{$obj} - $$RO_1_href{$obj};

+            my $RW_diff = $$RW_2_href{$obj} - $$RW_1_href{$obj};

+            my $ZI_diff = $$ZI_2_href{$obj} - $$ZI_1_href{$obj};

+

+            my $codebase1 = $$RO_1_href{$obj}.";".$$RW_1_href{$obj}.";".$$ZI_1_href{$obj};

+            my $codebase2 = $$RO_2_href{$obj}.";".$$RW_2_href{$obj}.";".$$ZI_2_href{$obj};

+            my $diff = $RO_diff.";".$RW_diff.";".$ZI_diff;

+            

+            $total_RO_1 += $$RO_1_href{$obj};

+            $total_RW_1 += $$RW_1_href{$obj};

+            $total_ZI_1 += $$ZI_1_href{$obj};

+            

+            $total_RO_2 += $$RO_2_href{$obj};

+            $total_RW_2 += $$RW_2_href{$obj};

+            $total_ZI_2 += $$ZI_2_href{$obj};

+            

+            $total_RO_diff += $RO_diff;

+            $total_RW_diff += $RW_diff;

+            $total_ZI_diff += $ZI_diff;

+            

+            $~ = "LIS_COMPARE";

+            format LIS_COMPARE = 

+@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

+$obj,$codebase1,$codebase2,$diff

+.

+        

+write;

+        }

+        

+        $total_codebase1 = $total_RO_1.";".$total_RW_1.";".$total_ZI_1;

+        $total_codebase2 = $total_RO_2.";".$total_RW_2.";".$total_ZI_2;

+        $total_diff = $total_RO_diff.";".$total_RW_diff.";".$total_ZI_diff;

+            

+        $~ = "LIS_TOTAL";

+        format LIS_TOTAL = 

+@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

+"Total",$total_codebase1,$total_codebase2,$total_diff

+.

+        

+write;

+

+    print "**************************************************************************************************************************************\n";

+}

+

+sub GetAllOBJ

+{

+    my ($ExeRegion, $file) = @_;

+    my $symfile = $file;

+    my $exeregion_aref;

+    

+    if($file =~ /\.map$/)

+    {

+        $symfile =~ s/map/sym/;

+        if(!-f $symfile)

+        {

+            my $file = basename($symfile);

+            my $dirname  = dirname($symfile);

+            $symfile = $dirname."\/dummy_$file";

+        }        

+        &LinkerOutputParser::FileParse($symfile);

+    }

+    &LinkerOutputParser::FileParse($file);

+    $exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1);

+

+    my %objs;

+    my @uni_objs;

+    my %count; 

+    my %RO_Size;

+    my %RW_Size;

+    my %ZI_Size;

+    my $nSectionCount=0;

+    my $strListSections = "List of Sections:\n";

+    my $strLast = "";

+    if (defined $exeregion_aref)

+    {

+        foreach my $temp(@$exeregion_aref)

+        {

+            next if ($temp !~ /$ExeRegion/i);

+            if (($ExeRegion =~ /[D|I].+\d$/i) && ($temp =~ /DYNAMIC_SECTION/i))

+            {   # add this confition for query DSPRAM0 + DSPRAM0_ZI. User treat them as single section

+                $strLast .= "no overlap (dynamic loading) section: $temp\n";

+                next;

+            }

+            my $obj_aref = &LinkerOutputParser::GetObjByExeRegion($temp);

+            if (defined $obj_aref)

+            {

+                map { $objs{$_} = 1} @$obj_aref;

+            }

+            $strListSections .= sprintf("\tSection %3d:  %s", $nSectionCount++, $temp);

+            $strListSections .= (($temp =~ /DYNAMIC_SECTION/i) ? sprintf(" (overlap section)\n") : "\n");

+        }

+    }

+    print $strListSections.$strLast."\n\n";

+    

+    foreach my $obj(keys %objs)

+    {

+        push (@uni_objs, $obj);

+        my ($nRO_Size, $nRW_Size, $nZI_Size);

+        if (defined $exeregion_aref)

+        {

+            foreach my $temp(@$exeregion_aref)

+            {

+                next if ($temp !~ /$ExeRegion/i);

+                

+                if($file =~ /\.map$/)

+                {

+                    if ($obj =~ /\.o|\*\S*\*|stub/) #(/\*fill\*\s+(0x\w+)\s+(0x\w+)/)

+                    {

+                        $nRO_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "RO");

+                        $nRW_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "RW");

+                        $nZI_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "ZI");

+                        _UpdateSize(\%RO_Size, $obj, $nRO_Size);

+                        _UpdateSize(\%RW_Size, $obj, $nRW_Size);

+                        _UpdateSize(\%ZI_Size, $obj, $nZI_Size);

+                    }

+                }

+            }

+        }

+        

+    }

+    

+    return (\@uni_objs, \%RO_Size, \%RW_Size, \%ZI_Size);

+}

+

+#calculate each element in the array's max length

+#input:  [[str1_1, str2_1, str3_1, ...], [str1_2, str2_2, str3_2, ...], ...]

+#output: [max_length_str1, max_length_str2, max_length_str3, ...]

+sub CalStringMaxLength

+{

+    my ($CaluAry_aref, $MaxLengthAry_aref) = @_;

+

+    foreach my $curAry_aref (@{$CaluAry_aref}) 

+    {

+        for (my $i=0 ; $i <= $#$MaxLengthAry_aref ; $i++)

+        {

+            my $curStrLength = length(@$curAry_aref[$i]);

+            $MaxLengthAry_aref->[$i] = $curStrLength if $curStrLength > $MaxLengthAry_aref->[$i];

+        }

+    }

+}

+

+sub _UpdateSize

+{

+    my ($href, $strKey, $nSize) = @_;

+    if(exists $href->{$strKey})

+    {

+        $href->{$strKey} += $nSize;

+    }

+    else

+    {

+        $href->{$strKey} = $nSize;

+    } 

+}

+

+sub GetAllSymbol{

+

+    my ($symfile) = @_;

+    

+    LinkerOutputParser::FileParse($symfile); 

+    my $symbol_aref = &LinkerOutputParser::GetSymbolTable();

+

+    return $symbol_aref;

+}

+

+sub AppendLibAttriToSymbol{

+

+    my ($mapfile, $symbol_aref) = @_;

+    

+    # append symbol obj/lib name to array if symbol exist in map file 

+    LinkerOutputParser::FileParse($mapfile);

+    my $region_attr = LinkerOutputParser::GetExeRegionAttr();

+    

+    foreach (@{$symbol_aref}) 

+    {   #[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName]

+        my @symbol_info = LinkerOutputParser::GetSymbolInfo($_->[1].".".$_->[0]);

+		my $strLibName = undef;

+		my $obj_lib_by_addr = undef;

+		

+		$_->[2] = _updateAttr($_->[2], $region_attr->{$_->[3]});

+		

+        if (@symbol_info)

+        {   

+            #get non-static symbol info

+            #[$SymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize]

+            $_->[4] = $symbol_info[6] > $_->[4] ? $symbol_info[6] : $_->[4];#update symbol size

+            $_->[5] = $symbol_info[2];# obj name

+            $_->[6] = $symbol_info[3];# lib name

+        }

+        elsif(@{$obj_lib_by_addr = LinkerOutputParser::ListObjLibByAddr($_->[1])})

+        {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName];

+            if($#$_ == 4 && $_->[0] !~ /^_ZN/)

+            {

+                $_->[4] = 0;

+            }

+            $_->[5] = $obj_lib_by_addr->[0];# obj name

+            $_->[6] = $obj_lib_by_addr->[1];# lib name  

+        }

+        elsif($#$_ == 5 && @{$strLibName = LinkerOutputParser::ListLibByObj($_->[-1])})

+        {  

+            next if ($#$strLibName > 1);

+            $_->[6] = $strLibName->[0];# lib name

+        }

+    }

+    return $symbol_aref;    

+}

+

+sub _updateAttr

+{

+    my ($attr_group, $attr_sec) = @_;

+

+    if($attr_sec =~ /RO/ && $attr_group =~ /F/)

+    {

+        return "RO_CODE";

+    }

+    elsif($attr_sec =~ /RO/ && $attr_group =~ /O/)

+    {

+        return "RO_DATA";

+    }

+    else

+    {

+        return $attr_sec;

+    }

+}

+

+sub Usage

+{

+  print <<"__EOFUSAGE";

+

+usage: perl TCMQuery.pl -Q INTSRAM map_file_path

+       perl TCMQuery.pl -q INTSRAM map_file_path

+       perl TCMQuery.pl -C INTSRAM map_file_path1 map_file_path2

+       perl TCMQuery.pl -c INTSRAM map_file_path1 map_file_path2

+       perl TCMQuery.pl -S INTSRAM sym_file_path

+       perl TCMQuery.pl -s INTSRAM sym_file_path

+

+map_file_path1: map file path for codebase1 you want to compare

+map_file_path2: map file path for codebase2 you want to compare

+

+e.g. 

+perl TCMQuery.pl -Q INTSRAM "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map"

+perl TCMQuery.pl -C INTSRAM "E:\\mtk80506\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map" "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map"

+

+__EOFUSAGE

+  exit 1;

+}

diff --git "a/mcu/tools/MemoryUtility/ThresholdConf/MT6290_LTE\050MULTI_MODE\051.txt" "b/mcu/tools/MemoryUtility/ThresholdConf/MT6290_LTE\050MULTI_MODE\051.txt"
new file mode 100755
index 0000000..ec7193a
--- /dev/null
+++ "b/mcu/tools/MemoryUtility/ThresholdConf/MT6290_LTE\050MULTI_MODE\051.txt"
@@ -0,0 +1 @@
+Memory Threshold in Bytes = 69206015
\ No newline at end of file
diff --git "a/mcu/tools/MemoryUtility/ThresholdConf/MT6290_LTE\050MULTI_MODE_HOSTED\051.txt" "b/mcu/tools/MemoryUtility/ThresholdConf/MT6290_LTE\050MULTI_MODE_HOSTED\051.txt"
new file mode 100755
index 0000000..ec7193a
--- /dev/null
+++ "b/mcu/tools/MemoryUtility/ThresholdConf/MT6290_LTE\050MULTI_MODE_HOSTED\051.txt"
@@ -0,0 +1 @@
+Memory Threshold in Bytes = 69206015
\ No newline at end of file
diff --git a/mcu/tools/MemoryUtility/config/detectZI_filter.txt b/mcu/tools/MemoryUtility/config/detectZI_filter.txt
new file mode 100755
index 0000000..44b1049
--- /dev/null
+++ b/mcu/tools/MemoryUtility/config/detectZI_filter.txt
@@ -0,0 +1,6 @@
+#

+# Format: "symbol name"

+# The symbol list below will not be showed in final result

+#

+Test_Symbol_1

+Test_Symbol_2
\ No newline at end of file
diff --git a/mcu/tools/MemoryUtility/memquery.pl b/mcu/tools/MemoryUtility/memquery.pl
new file mode 100644
index 0000000..cb741ef
--- /dev/null
+++ b/mcu/tools/MemoryUtility/memquery.pl
@@ -0,0 +1,739 @@
+#!/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) 2006
+#
+#  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:
+#* ---------
+#*   MemoryUtility/memquery.pl
+#*
+#* Description:
+#* ------------
+#*  This script should be used in build flow
+#*  This provides corresponding memory utility command and system call
+#*
+#* Author:
+#* -------
+#*   Carl Kao  (mtk08237)
+#*
+#****************************************************************************/
+use strict;
+BEGIN { push @INC, "./" , './tools/', './tools/MemoryUtility/', '../' }
+use CommonUtility;
+use File::Basename;
+use BasicMemInfoQuery;
+
+my $nVerion = "LR13_v0.02";
+             # LR13_v0.02 ,  20180423 , updated l2cachelockinfo
+             # LR13_v0.01 ,  20160906 , Removed SPRAM2 support
+             # LR12_v0.06 ,  20160303 , Memory Utility implementation for LR12
+             # LR12_v0.05 ,  20160125 , Memory Utility Refinement for LR12
+             # LR12_v0.04 ,  20160113 , memquery remove l1 core related feature
+             # LR12_v0.03 ,  20151215 , fix memory utility .map file parsing feature for LR12 (64bit address)
+             # LR12_v0.02 ,  20151102 , detectZI parsing rule change
+             # LR12_v0.01 ,  20151026 , add GrepSymbolByInputSection feature to memory utility
+             # u0.07 , 20151030 , Carl , Parsing ELF file instead of parsing BIN file since there is CCCI header in front of bin file
+             # u0.06 , 20150127 , Carl , Take bin file path from build flow (final solution)
+             # u0.05 , 20150127 , Carl , Fix GetBinFile for UMOLY TRUNK since the nameing rule is different (temp solution)
+             # u0.04 , 20150121 , Carl , Fix GetBinFile for 91
+             # u0.03 , 20150119 , Carl , Memory Utility Refinement
+             # u0.02 , 20150107 , Carl , refine for 91 image layout
+             # u0.01 , 
+
+
+#****************************************************************************
+# Inputs
+#****************************************************************************
+my $ARGV_FILE_PATH              = $ARGV[0]; #./build/MT6297_EVB/NLWCTG_SAP/tmp/~memquery.tmp 
+my $IMAGELAYOUT_PATH            = $ARGV[1]; # scatter file or linker script
+my $MAKE_FILE                   = $ARGV[2];
+my $LINKER_OUTPUT_PATH          = $ARGV[3]; # map
+my $LOG_FOLDER                  = $ARGV[4];
+my $LOG_PATH                    = $ARGV[4]."/memquery.log";
+my $INFOMAKE_PATH               = $ARGV[5];
+my $BIN_FILE                    = $ARGV[6];
+my $SYM_FILE                    = $LINKER_OUTPUT_PATH;
+$SYM_FILE  =~ s/\.map$/\.sym/;
+if(!-f $SYM_FILE)
+{
+    print "\n[memquery][Note]$SYM_FILE doesn't exist!\n";
+    my $file = basename($SYM_FILE);
+    my $dirname  = dirname($SYM_FILE);
+    $SYM_FILE = $dirname."\/dummy_$file";
+    print "Use $SYM_FILE instead of it.\n";
+}
+
+#****************************************************************************
+# Global variable
+#****************************************************************************
+my @Supported_Cmd = qw(-h help --help 
+                      # basic comand
+                      symin objin libinfo objinfo discard 
+                      compareobj comparelib comparediscard 
+                      diff2symin diffsymin 
+                      basicinfo chkmemusage detectZI 
+                      symbolinfo sdatainfo  l2cachelockinfo
+                      topsizeobj
+                      syminobj syminlib symthreshold fillinfo
+                      # special command 
+                      tcmmargin     rammargin       l2srammargin    sprammargin 
+                      objinspram0   objinspram1     objinspramall   objinl2sram objintcm 
+                      syminspram0   syminspram1     syminspramall   syminl2sram symintcm 
+                      comparespram0 comparespram1   comparespramall comparetcm);  # no comparel2sram
+my $g_bToLog = 0;
+#****************************************************************************
+# MainFlow
+#****************************************************************************
+unlink $LOG_PATH if(-e $LOG_PATH);
+PrintLog("Command: $0 $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] $ARGV[4] $ARGV[5] $ARGV[6] \n\n");
+my $arg_aref = ParseARGV($ARGV_FILE_PATH);
+DispatchCommand($arg_aref, \@Supported_Cmd, $IMAGELAYOUT_PATH, $MAKE_FILE, 
+                $LINKER_OUTPUT_PATH, $SYM_FILE, $LOG_FOLDER, $BIN_FILE);
+
+#****************************************************************************
+# 0 >>> exit - no error: 0, error code: > 0
+#****************************************************************************
+exit 0;
+
+#****************************************************************************
+# subroutines
+#****************************************************************************
+sub DispatchCommand
+{
+    my ($arg_aref, $Supported_Cmd_aref,  
+         $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    my $str1stCmd = $arg_aref->[0];
+    $g_bToLog = 1 if (grep {$_ =~/log/i} @$arg_aref);
+    my $bRunCommand = 0;
+    foreach my $cmd (@$Supported_Cmd_aref)
+    {
+        if($str1stCmd =~ /^$cmd$/i)
+        {
+            $cmd = "help" if($cmd eq "-h" or $cmd eq "--help");
+            shift(@$arg_aref);
+            no strict 'refs';
+            my $Func = "CMD_$cmd";
+            PrintToScreen("\n-----------------------------[Memory Query]---------------------------\n");
+            &{$Func}($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) if (exists &{$Func})
+                or mem_die("$Func() doesn't exists!", __FILE__, __LINE__);
+            $bRunCommand = 1;
+            last;
+        }    
+    }
+    if(!$bRunCommand)
+    {
+        print "$str1stCmd is not supported. Please refer to the following command option:\n";
+        Usage();
+    }
+}
+
+sub ParseARGV
+{
+    my ($strTmpFilePath) = @_;
+    Usage() if(!-e $strTmpFilePath);
+    my $strContent = CommonUtil::GetFileContent($strTmpFilePath);
+    my @arguments = split(/\s/, $strContent);
+    return \@arguments;
+}
+
+sub GetLogName
+{
+    my ($makefile, $log_folder, $strPostfix) = @_;
+    my $project = basename($makefile);
+    $project =~ s/\.mak|~//ig;
+    return "$log_folder/$project\_$strPostfix\.txt";
+}
+sub DecideOuput
+{
+    my ($makefile, $log_folder, $strPostfix) = @_;
+    my $Func = \&PrintToScreen;
+    if($g_bToLog)
+    {
+        $Func = \&PrintLog;
+        $LOG_PATH = GetLogName($makefile, $log_folder, $strPostfix);
+        unlink $LOG_PATH if(-e $LOG_PATH);
+    }
+    return $Func;
+}
+#****************************************************************************
+# command
+#****************************************************************************
+sub CMD_basicinfo
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    my $Func = DecideOuput($makefile, $log_folder, "BasicInfo");
+    no strict 'refs';
+    &BasicMemInfo::DispatchCommand("CMD_GetROMSize", $makefile, $lds_path, $map_path, $sym_path, $Func);
+    &{$Func}("-------------------------------------------------------------------\n");
+    &BasicMemInfo::DispatchCommand("CMD_GetRAMUsage", $makefile, $lds_path, $map_path, $sym_path, $Func);
+    &{$Func}("-------------------------------------------------------------------\n");
+    &BasicMemInfo::DispatchCommand("CMD_GetPhysicalRAMUsage", $makefile, $lds_path, $map_path, $sym_path, $Func);
+    &{$Func}("-------------------------------------------------------------------\n");
+    print "The output is generated under: $LOG_PATH\n" if($g_bToLog);
+}
+sub system_cmd
+{
+    my ($cmd, $strPostfix, $makefile, $log_folder) =@_;
+    my $path = GetLogName($makefile, $log_folder, $strPostfix);
+    my $output = "> \"$path\"" if($g_bToLog);
+    print "cmd=$cmd $output\n\n";
+    system("$cmd $output");
+    print "The output is generated under: $path\n" if($g_bToLog);
+}
+
+sub system_cmd_csv
+{
+    my ($cmd, $strPostfix, $makefile, $log_folder) =@_;
+    my $project = basename($makefile); 
+    $project =~ s/\.mak|~//ig; 
+    my $path =  "$log_folder/$project\_$strPostfix\.csv";
+    my $output = "> \"$path\"" if($g_bToLog);
+    print "cmd=$cmd $output\n\n";
+    system("$cmd $output");
+    print "The output is generated under: $path\n" if($g_bToLog);
+}
+
+sub CMD_tcmmargin
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    print"Redirect to memquery sprammargin!\n";
+    CMD_sprammargin($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder);
+}
+
+sub CMD_sprammargin
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    system_cmd("perl ./tools/MemoryUtility/TCMMargin.pl \"$makefile\" \"$lds_path\" \"$sym_path\"",
+               "SPRAMMargin", $makefile, $log_folder);
+}
+
+sub CMD_l2srammargin
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    CMD_sprammargin($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder);
+}
+
+sub CMD_rammargin
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    system_cmd("perl ./tools/MemoryUtility/RAMMargin.pl \"$makefile\" \"$lds_path\" \"$sym_path\"",
+               "RAMMargin", $makefile, $log_folder);
+}
+
+sub _CMD_comparespram
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path, $query_range) = @_;
+    if(scalar(@$arg_aref) < 1)
+    {
+        print "Please add the map path after comparespram.\nFor more information, you can refer to memquery -h\n\n";
+    }
+    else
+    {
+        my $compare_path = $arg_aref->[0];
+        my $output_log = GetLogName($makefile, $log_folder, "Compare".$query_range.($query_range eq "SPRAM"?"All":""));
+        system("perl ./tools/MemoryUtility/TCMQuery.pl -c $query_range \"$map_path\" \"$compare_path\" > \"$output_log\"");
+        print "The output is generated under: $output_log\n";
+    }
+}
+sub CMD_comparespram0
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    &_CMD_comparespram($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path, "SPRAM0");
+}
+sub CMD_comparespram1
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    &_CMD_comparespram($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path, "SPRAM1");
+}
+sub CMD_comparespramall
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    &_CMD_comparespram($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path, "SPRAM");
+}
+
+sub CMD_comparetcm
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    print"Redirect to memquery comparespram!\n";
+    CMD_comparespram($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path);
+}
+
+sub CMD_objintcm
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    print"Redirect to memquery objinspramall!\n";
+    CMD_objinspramall($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path);  
+}
+
+
+sub _CMD_objinspram
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path, $query_range) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -q $query_range \"$map_path\"", "size".($query_range eq "SPRAM"?"All":""),  $makefile, $log_folder);
+}
+sub CMD_objinspram0
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;    
+    _CMD_objinspram($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path, "SPRAM0");
+}
+sub CMD_objinspram1
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;    
+    _CMD_objinspram($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path, "SPRAM1");
+}
+sub CMD_objinspramall
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;    
+    print "This command is euqal to objinspram0 + objinspram1\n";
+    _CMD_objinspram($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path, "SPRAM");
+}
+
+sub CMD_objinl2sram
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -q L2SRAM \"$map_path\"", "L2SRAMSize", $makefile, $log_folder);
+}
+
+sub CMD_objin
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -q $arg_aref->[0] \"$map_path\"", "ObjSize", $makefile, $log_folder);
+}
+
+sub CMD_symbolinfo
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd_csv("perl ./tools/MemoryUtility/TCMQuery.pl -is $arg_aref->[0] \"$map_path\" \"$sym_path\"", "SymbolInfo", $makefile, $log_folder);
+}
+
+sub CMD_sdatainfo
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    my $output_log = GetLogName($makefile, $log_folder, "sdata");
+    system("perl ./tools/MemoryUtility/TCMQuery.pl -is \"\\.s(data|bss)_0\\.{0,1}\" \"$map_path\"  \"$sym_path\" > \"$output_log\"");
+    system("perl ./tools/MemoryUtility/TCMQuery.pl -is \"\\.s(data|bss)_1\\.{0,1}\" \"$map_path\"  \"$sym_path\" >> \"$output_log\"");
+    print "The output is generated under: $output_log\n";
+}
+
+sub CMD_l2cachelockinfo
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -is \"L2CACHE_LOCK\" \"$map_path\" \"$sym_path\"", "l2cachelock", $makefile, $log_folder);
+}
+
+
+sub CMD_discard
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/QueryDiscardedSym.pl -q \"$map_path\"", "Discard", $makefile, $log_folder);
+}
+
+sub CMD_comparediscard
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/QueryDiscardedSym.pl -c \"$map_path\" \"$arg_aref->[0]\"", "CompareDiscard", $makefile, $log_folder);
+}
+
+sub CMD_symintcm
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    print "Redirect to objinspramall!\n";
+    CMD_objinspramall();
+}
+
+sub CMD_syminl2sram
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -s L2SRAM \"$sym_path\"", "L2SRAMsymbol", $makefile, $log_folder);
+}
+
+sub CMD_syminspramall
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    print "This command is euqal to syminspram0 + syminspram1\n";
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -s SPRAM \"$sym_path\"", "SPRAMsymbolAll", $makefile, $log_folder);
+}
+
+sub CMD_syminspram0
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -s SPRAM0 \"$sym_path\"", "SPRAM0symbol", $makefile, $log_folder);
+}
+
+sub CMD_syminspram1
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -s SPRAM1 \"$sym_path\"", "SPRAM1symbol", $makefile, $log_folder);
+}
+sub CMD_symin
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -s $arg_aref->[0] \"$sym_path\"", "SymbolsBySection", $makefile, $log_folder);
+}
+
+sub CMD_syminobj
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd_csv("perl ./tools/MemoryUtility/TCMQuery.pl -so $arg_aref->[0] \"$map_path\" \"$sym_path\"", "SymbolsByObj", $makefile, $log_folder);
+}
+
+sub CMD_syminlib
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd_csv("perl ./tools/MemoryUtility/TCMQuery.pl -sl $arg_aref->[0] \"$map_path\" \"$sym_path\"", "SymbolsByLib", $makefile, $log_folder);
+}
+
+sub CMD_symthreshold
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd_csv("perl ./tools/MemoryUtility/TCMQuery.pl -st $arg_aref->[0] \"$map_path\" \"$sym_path\"", "SymbolsThreshold", $makefile, $log_folder);
+}
+
+sub CMD_diffsymin
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -sc $arg_aref->[0] \"$sym_path\" \"$arg_aref->[1]\"", "DiffSymbol", $makefile, $log_folder);
+}
+
+#Only List the difference without existence
+sub CMD_diff2symin
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+    system_cmd("perl ./tools/MemoryUtility/TCMQuery.pl -sce $arg_aref->[0] \"$sym_path\" \"$arg_aref->[1]\"", "Diff2Symbol", $makefile, $log_folder);
+}
+
+sub CMD_objinfo
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    if(scalar(@$arg_aref) == 0)
+    {
+        my $output_log = GetLogName($makefile, $log_folder, "ObjectSize");
+        system("perl ./tools/MemoryUtility/CompareObjSize.pl \"$map_path\" \"$map_path\" > \"$output_log\" ");
+        print "The output of all library information is generated under: $output_log\n";
+    }
+    else
+    {
+        foreach my $obj (@$arg_aref)
+        {
+            $obj .= ".obj" if($obj !~ /\.o/);
+            print "$obj\n===================================================\n";
+            system("perl ./tools/MemoryUtility/QuerySize.pl \"$map_path\" $obj");
+            print "\n";
+        }
+    }
+}
+
+sub CMD_fillinfo
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    $g_bToLog = 1;
+
+    system_cmd_csv("perl ./tools/MemoryUtility/TCMQuery.pl -sf $arg_aref->[0] \"$map_path\" \"$sym_path\"", "FillInfo", $makefile, $log_folder);
+}
+
+sub CMD_comparelib
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    if(scalar(@$arg_aref) < 1)
+    {
+        print "Please add the map path after comparelibinfo.\nFor more information, you can refer to memquery -h\n\n";
+    }
+    else
+    {
+        my $compare_path = $arg_aref->[0];
+        my $output_log = GetLogName($makefile, $log_folder, "LibrarySize");
+        system("perl ./tools/MemoryUtility/CompareLibrarySize.pl \"$map_path\" \"$compare_path\" > \"$output_log\" ");
+        print "The output is generated under: $output_log\n";
+    }
+}
+
+sub CMD_compareobj
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    if(scalar(@$arg_aref) < 1)
+    {
+        print "Please add the map path after compareobjinfo.\nFor more information, you can refer to memquery -h\n\n";
+    }
+    else
+    {
+        my $compare_path = $arg_aref->[0];
+        my $output_log = GetLogName($makefile, $log_folder, "ObjectSize");
+        system("perl ./tools/MemoryUtility/CompareObjSize.pl \"$map_path\" \"$compare_path\" > \"$output_log\" ");
+        print "The output is generated under: $output_log\n";
+    }
+}
+
+sub CMD_libinfo
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    if(scalar(@$arg_aref) == 0)
+    {
+        my $output_log = GetLogName($makefile, $log_folder, "LibrarySize");
+        system("perl ./tools/MemoryUtility/CompareLibrarySize.pl \"$map_path\" \"$map_path\" > \"$output_log\" ");
+        print "The output of all library information is generated under: $output_log\n";
+    }
+    else
+    {
+        foreach my $lib (@$arg_aref)
+        {
+            if($lib !~ /\.l|\.a/)
+            {
+                print "Please add filename extension after $lib. Otherwise it can't be searched properly.";    
+            }
+            else
+            {
+                print "$lib\n===================================================\n";
+                system("perl ./tools/MemoryUtility/QuerySize.pl \"$map_path\" $lib");
+                print "\n";    
+            }
+        }
+    }
+}
+
+sub CMD_chkmemusage
+{
+	my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    system_cmd("perl ./tools/MemoryUtility/ChkMemUsage.pl \"$makefile\" \"$lds_path\" \"$map_path\" \"$sym_path\" ",
+               "chkmemusage", $makefile, $log_folder);
+}
+
+sub CMD_detectZI
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+
+    #my $bin_path = GetBinFile($map_path);
+    my $bin_path = $bin_path;
+    my $elf_path = $map_path;
+    $elf_path =~ s/map/elf/g;
+    my ($nZIpercent, $gnZIthreshold) = ($arg_aref->[0], $arg_aref->[1]);
+    
+    $g_bToLog = 1;
+    
+    system_cmd("perl ./tools/MemoryUtility/DetectZI.pl \"$sym_path\" \"$map_path\" \"$elf_path\" \"$nZIpercent\" \"$gnZIthreshold\"", 
+                "detectZI_".$nZIpercent."_".$gnZIthreshold, $makefile, $log_folder);    
+}
+
+sub CMD_topsizeobj
+{
+    my ($arg_aref, $lds_path, $makefile, $map_path, $sym_path, $log_folder, $bin_path) = @_;
+    my $output_log = GetLogName($makefile, $log_folder, "TopSizeObj");
+    system("perl ./tools/MemoryUtility/ListTopSizeObj.pl \"$map_path\" > \"$output_log\" ");
+    print "The output is generated under: $output_log\n";
+}
+
+# We don't use this function since the naming rule of bin file and map file are different in UMOLY
+sub GetBinFile()
+{
+    my ($map_path) = @_;
+    my $binDir = &dirname($map_path)."\/";
+    
+    opendir (DIR, $binDir) or mem_die("can not open bin folder $binDir", __FILE__, __LINE__);
+    my $binfilePrefix = &basename($map_path, ".map");
+    $binfilePrefix =~ s/\_P\_|\_L\_/\_/g;
+    my @TMP_BIN_FILE = grep { /$binfilePrefix\..+\.bin/ } readdir DIR;
+    closedir DIR;
+    if( scalar(@TMP_BIN_FILE) == 0 ) {
+        opendir (DIR, $binDir) or mem_die("can not open bin folder $binDir", __FILE__, __LINE__);
+        @TMP_BIN_FILE = grep { /.+\_MDBIN\_.+\..+\.bin/ } readdir DIR;
+        closedir DIR;
+    }
+    mem_die("no bin file is found") if( scalar(@TMP_BIN_FILE) == 0 );
+    return $binDir.$TMP_BIN_FILE[0];
+}
+
+sub CMD_help
+{
+    Usage();    
+}
+
+#****************************************************************************
+# Subroutine:  PrintLog
+# Parameters:  string log
+# Returns:     x
+#****************************************************************************
+sub PrintLog
+{
+    my ($strInput) = @_;
+    my ($pack_name, $file, $line_no) = caller;
+    open (FILE_HANDLE, ">>$LOG_PATH") or &mem_die("Cannot open log: $LOG_PATH\n", $file, $line_no);
+    print FILE_HANDLE $strInput if(defined $strInput);
+    close FILE_HANDLE;
+}
+
+sub PrintToScreen
+{
+    my ($strInput) = @_;
+    print $strInput if (defined $strInput);    
+}
+
+#****************************************************************************
+# Subroutine:  mem_die
+# Parameters:  1. string error message, 2. __FILE__ 3. __LINE__
+# Returns:     x
+#****************************************************************************
+sub mem_die
+{
+    my ($error_msg, $file, $line_no) = @_;
+    my $pack_name = undef;
+    if(!defined $file or !defined $line_no)
+    {
+        ($pack_name, $file, $line_no) = caller;    
+    }
+    &CommonUtil::error_handler($error_msg, $file, $line_no, 'Memory Query');    
+}
+
+#****************************************************************************
+# Subroutine:  Usage
+# Parameters:  x
+# Returns:     x
+#****************************************************************************
+sub Usage
+{
+    #system("clear"); # windows: cls, linux: clear
+    my $make = "m";
+    $make = "./m" if ($^O eq "linux") ;
+    print <<"__EOFUSAGE";
+
+----------------------------------------------------------------------------    
+[USAGE] 
+$make [MAKEFILE] memquery [OPTIONS]
+Note: The project must be built before using memquery.
+
+e.g.
+./m "MT6589_MD1_GPRS(SKYPA).mak" memquery sprammargin
+./m "MT6589_MD1_GPRS(SKYPA).mak" memquery objinfo abc.obj cde.obj
+./m "MT6589_MD1_GPRS(SKYPA).mak" memquery libinfo libabc.a libcde.a
+./m "MT6589_MD1_GPRS(SKYPA).mak" memquery libinfo
+./m "MT6589_MD1_GPRS(SKYPA).mak" memquery symin ROM
+[OPTIONS]
+help|-h|--help
+    Show how to use memquer
+basicinfo
+    Show ROM/RAM/PhysicalRAMUsage information
+chkmemusage
+    Check if the memory usage is more than the predefined percentage of hardware provided memory size 
+detectZI [ZIpercent, ZIthreshold]
+    List the RW with ZIpercent % of its contents are ZI and the size is larger than ZIthreshold byte.
+    If no ZIpercentand ZIthreshold and specified, default ZIpercent=100 and ZIthreshold=0
+sprammargin
+l2srammargin
+    Show spram and l2sram left sizes
+rammargin
+    Show ram left sizes
+syminspram[all,0,1]
+    Output the information of all symbol in all spram or SPRAM[0,1] to a log
+    e.g. syminspramall
+         syminspram0
+objinspram[all,0,1]
+    Output the information of all objects in all spram or SPRAM[0,1] to a log
+    e.g. objinspramall
+         objinspram0
+comparespram[all,0,1]
+    Compare object list in all spram or SPRAM[0,1,2] between current project with input map
+    e.g. comparespramall
+         comparespram0
+objinl2sram
+    Output the information of all objects in l2sram to a log
+objin 'section,section,...'
+    Output the information of all objects in specfic section to a log
+    e.g. objin 'ROM,INTSRAM_CODE'
+         objin ROM
+symin 'section,section,...'
+    Output the symbol information in specfic section to a log
+    e.g. symin 'ROM,INTSRAM_CODE'
+         symin L2SRAM
+objinfo [objname] 
+    Show ro/rwzi sizes of these objects
+libinfo [libname.l|libname.a]
+    Show ro/rwzi sizes of these libraries
+objinfo
+    Output all object information to a log
+libinfo
+    Output all library information to a log
+symbolinfo
+    Output symbol information in specfic input section to a log
+sdatainfo
+    Output symbol information in small data sections of core 0~1 to a log
+l2cachelockinfo
+    Output symbol information in static l2cache_lock sections to a log
+comparelib [map path]
+    Compare library list in current project with input map
+    [NOTE]sym filename should be the same as maps and 
+          be put under the same folder.
+compareobj [map path]
+    Compare object list in current project with input map
+    [NOTE]sym filename should be the same as maps and 
+          be put under the same folder.
+diffsymin 'section,section,...' [sym path]
+    Compare 2 sym files by section
+    (List all difference)
+diff2symin 'section,section,...' [sym path]
+    Compare 2 sym files by section
+    (List only difference if any one symbol doesnt exist)
+
+
+--Redirect command in LR13--
+symintcm
+    This command will be redirected to syminspramall
+objintcm
+    This command will be redirected to objinspramall
+comparetcm [map path]
+    This command will be redirected to comparespramall
+tcmmargin 
+    This command will be redirected to l2srammargin
+
+    
+--Not support command in LR13--
+
+----------------------------------------------------------------------------
+__EOFUSAGE
+  exit 0;
+}
diff --git a/mcu/tools/MemoryUtility/sysInfoProcessLds.pm b/mcu/tools/MemoryUtility/sysInfoProcessLds.pm
new file mode 100644
index 0000000..a6598cc
--- /dev/null
+++ b/mcu/tools/MemoryUtility/sysInfoProcessLds.pm
@@ -0,0 +1,747 @@
+#!/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) 2006
+#
+#  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:
+#* ---------
+#*   sysInfoProcessLds.pm
+#*
+#* Project:
+#* --------
+#*
+#*
+#* Description:
+#* ------------
+#*   This module collects the subroutines for system information. 
+#*       
+#*
+#* Author:
+#* -------
+#*   Carl Kao (mtk08237)
+#*
+#****************************************************************************/
+
+BEGIN { push @INC, '../', './tools/', './tools/MemoryUtility/' }
+package sysInfoProcLds;
+use CommonUtility;
+use sysGenUtility;
+use FileInfoParser;
+use scatInfo;
+use ldsInfo;
+use List::Util qw(min max);
+use strict;
+
+#****************************************************************************
+# Constants
+#****************************************************************************
+my $SYSINFOPROCLDS_VERNO     = " LR13_v0.02";
+                 # LR13_v0.02,  2018/04/13,  Added L2CACHE_LOCK area detection in FilterOutRegionInRAM
+                 # LR13_v0.01,  2017/03/29,  Modify GetTCMmargin to use physical ISPRAM address
+                 # LR12_v0.03,  2016/03/03,  BIN sections filtered out in FilterOutRegionInRAM
+                 # LR12_v0.02,  2016/01/26,  Avoid dump sections with name "PHYSICAL_BOUNDARY" (for SPRAM physical name)
+                 # LR12_v0.01 , 2016/01/25,  Memory Utility Refinement for LR12
+                 # u0.01 , 2015/01/14,  Memory Utility Refinement for LR11
+                 # m0.05 , 2013/05/17,  Fix GetChipInsideRAMregion() to add _ZI if it's a data region
+                 # m0.04 , 2013/02/14,  Support BTCM1 in MOLY
+                 # m0.03 , 2012/08/03,  Modify GetTCMmargin() to store TCM physical size
+                 # m0.02 , 2012/08/03,  Modify module name and push additional library path
+                 # m0.01 , 2012/07/05,  Initial revision
+                 
+#****************************************************************************
+# Global variable
+#****************************************************************************
+my $g_MAUIlds = undef;
+my $g_SavedLDSPath = undef;
+my $DebugPrint = 1;
+
+#****************************************************************************
+# oo >>>  Finished
+#****************************************************************************
+return 1;
+
+#****************************************************************************
+# Subroutine:  GetChipInsideRAMregion - to query all Chip inside RAM regions
+# Parameters:  $LDSFILE = the path of lds file
+#              $INTSRAMregion_href = a Hash reference to store ChipInsideRAM infomation
+#              $INTSRAMregion_href->{regionName} = []
+# Returns:     $nINTSRAMnum = the number of ChipInsideRAM regions
+#****************************************************************************
+sub GetChipInsideRAMregion
+{
+    my ($LDSFILE, $INTSRAMregion_href) = (@_);
+    my $nINTSRAMnum = 0;
+    my $strINTSRAMName = undef;
+
+    &GetLdsInfo($LDSFILE);
+    my $ExeRegion_ref = $g_MAUIlds->GetAllExeRegion();
+    foreach (@$ExeRegion_ref)
+    {
+        if($_ =~ /SPRAM|L2SRAM/)
+        {
+            $nINTSRAMnum++;
+            $INTSRAMregion_href -> {$_} = [];
+            if(($_ =~ /^DSPRAM/ || $_ =~ /DATA/) && !($_ =~ /DYNAMIC_SECTION/))
+            {
+                $nINTSRAMnum++;
+                $INTSRAMregion_href -> {$_."_ZI"} = [];
+            }
+        }
+    }
+    return ($nINTSRAMnum);
+}
+
+#****************************************************************************
+# Subroutine:  GetChipInsideRAMsize - to query ChipInsideRAM size
+# Parameters:  $LDSFILE = the path of lds file
+#              $INTSRAMinfo_href = a Hash reference to store ChipInsideRAM infomation
+#              ($INTSRAMinfo_href -> {ChipInsideRAM type} = MaxSize)
+# Returns:     $nINTSRAMnum = the number of ChipInsideRAM types
+#****************************************************************************
+sub GetChipInsideRAMsize
+{
+    my $strInsideRAMsizePattern = '[D|I].+\d$|L2SRAM|USPRAM';
+    my $strSkipPattern = 'IOCU';
+    my ($LDSFILE, $INTSRAMinfo_href) = (@_);
+    my $nINTSRAMnum = 0;
+    my $strINTSRAMName = undef;
+
+    &GetLdsInfo($LDSFILE);
+    my $MemoryInfo_ref = $g_MAUIlds->{ldsInfo}->{MEMORYInfo};
+    foreach (@$MemoryInfo_ref)
+    {
+        my $strMemory = $_->[0];
+        my $nMaxSize = hex($_->[2]);
+        if($strMemory =~ /$strInsideRAMsizePattern/ && $strMemory !~ /$strSkipPattern/)
+        {            
+            $INTSRAMinfo_href->{$strMemory} = $nMaxSize;
+            $nINTSRAMnum++ 
+        }
+    }
+    
+    return ($nINTSRAMnum);
+}
+
+#****************************************************************************
+# Subroutine:  GetTCMmargin - to query TCM margin
+# Parameters:  $LDSFILE = the path of lds file
+#              $TCMregion_href = a Hash reference to store TCM infomation
+#              $TCMregion_href->{'regionName'} = size
+# Returns:     $hTCMmargin = a Hash reference to store TCM information
+#              $TCMmargin_href->{ITCM}->[0] = ITCM physical size, $TCMmargin_href->{ITCM}->[1] = ITCM margin
+#              $TCMmargin_href->{DTCM}->[0] = DTCM physical size, $TCMmargin_href->{DTCM}->[1] = DTCM margin
+#              $TCMmargin_href->{TCM}->[0]  = TCM physical size , $TCMmargin_href->{TCM}->[1]  = TCM margin
+#****************************************************************************
+sub GetTCMmargin
+{
+    my ($LDSFILE, $TCMregion_href) = (@_);
+    my %hTCMmargin;
+    my %INTSRAMinfo;
+    &GetChipInsideRAMsize($LDSFILE, \%INTSRAMinfo);
+
+if (1)
+{
+    foreach my $strINTSRAMname (keys %INTSRAMinfo)
+    {
+        my $nSPRAMsize = $INTSRAMinfo{$strINTSRAMname};
+        my $nSPRAMregionBasAddr=0xFFFFFFFF;
+        my $nSPRAMregionEndAddr=0;
+            
+        foreach my $strINTSRAM (keys %{$TCMregion_href})
+        {
+            next if ($strINTSRAM !~ /$strINTSRAMname/ || $strINTSRAM =~ /PHYSICAL_BOUNDARY/);
+            
+            my $nINTSRAMSize = $TCMregion_href->{$strINTSRAM}->[0];
+            my $nINTSRAMVMA = $TCMregion_href->{$strINTSRAM}->[1];
+            #ISPRAM0 VMA adjustet to physical address to ISPRAM
+	    $nINTSRAMVMA &= 0xfff3ffff if ($strINTSRAMname =~ /ISPRAM0/);
+            my $nEndAddr = $nINTSRAMSize + $nINTSRAMVMA;
+
+            $nSPRAMregionBasAddr = $nINTSRAMVMA if ($nSPRAMregionBasAddr > $nINTSRAMVMA);
+            $nSPRAMregionEndAddr = $nEndAddr if ($nEndAddr > $nSPRAMregionEndAddr);
+        }
+        # no such outout section, reset base address to 0;
+        $nSPRAMregionBasAddr = 0 if ($nSPRAMregionBasAddr == 0xFFFFFFFF);
+
+        my $nSPRAMmargin = $nSPRAMsize-($nSPRAMregionEndAddr-$nSPRAMregionBasAddr);
+        $hTCMmargin{$strINTSRAMname} = [$nSPRAMsize, $nSPRAMmargin];
+    }
+    
+}
+else #if(0)
+{
+    # abandon to use this way since align will not be calculate in to size...
+    # e.g.
+    # 26 L2SRAM_L2C_CODE                                 00003e98 9fc00000  a0a472ec  00a472ec  2**2
+    # 27 DYNAMIC_SECTION_L2SRAM_8_UBIN_W 00000000  9fc03ea0  9fc03ea0  00b1be00  2**0
+    # end addr of L2SRAM_L2C_CODE is 0x9FC03E98 != base of DYNAMIC_SECTION_L2SRAM_8_UBIN_W = 0x9FC03EA0 since it needs 32 bytes alignment
+    
+    my %hCheckOverlapSection;
+    my @nISPRAMusedsize;
+    my @nDSPRAMusedsize;
+    my $L2SRAMusedsize = 0;
+
+    foreach my $strINTSRAM (keys %{$TCMregion_href})
+    {          
+        my $nINTSRAMSize = $TCMregion_href->{$strINTSRAM}->[0];
+        my $nINTSRAMVMA = $TCMregion_href->{$strINTSRAM}->[1];
+        
+        # record Dynamic Section Management
+        if( $strINTSRAM =~ /^DYNAMIC_SECTION/)
+        {
+            # next if this section is marked or size is 0
+            next if (defined $hCheckOverlapSection{$nINTSRAMVMA});
+            next if ($nINTSRAMVMA == 0);
+
+            # mark this overlap section is counting!
+            $hCheckOverlapSection{$nINTSRAMVMA} = 1;
+
+            # start find max size of overlap sections
+            my $maxSize = $nINTSRAMSize;        
+            foreach my $strSPRAM_tmp (keys %{$TCMregion_href})
+            {
+                my $nINTSRAMSize_tmp = $TCMregion_href->{$strSPRAM_tmp}->[0];
+                my $nINTSRAMVMA_tmp = $TCMregion_href->{$strSPRAM_tmp}->[1];
+
+                # no overlap section or no overlap
+                next if( $strSPRAM_tmp !~ /^DYNAMIC_SECTION/ || $nINTSRAMVMA_tmp != $nINTSRAMVMA);
+                
+                $maxSize = $nINTSRAMSize_tmp if ($nINTSRAMSize_tmp > $maxSize);
+            }
+
+            # set section size as max size of overlap sections
+            $nINTSRAMSize = $maxSize;
+        }
+
+        # now we process normal and overlap section by same rule
+        if( $strINTSRAM =~ /(\w)SPRAM(\d)/)
+        {
+            my $strIorD = $1;
+            my $nIdxOfSPRAM = $2;
+
+            sysInfoProcLDS_die("no such case IorD: $strIorD index: $nIdxOfSPRAM", __FILE__, __LINE__) if( $strIorD ne "I" && $strIorD ne "D" );
+             
+            $nISPRAMusedsize[$nIdxOfSPRAM] += $nINTSRAMSize if ($strIorD eq "I");
+            $nDSPRAMusedsize[$nIdxOfSPRAM] += $nINTSRAMSize if ($strIorD eq "D");
+        }
+        elsif($strINTSRAM =~ /^L2SRAM/)
+        {             
+            $L2SRAMusedsize += $nINTSRAMSize;
+        }
+    }
+    
+
+    foreach my $strINTSRAMname (keys %INTSRAMinfo)
+    {
+        if( $strINTSRAMname =~ /(\w)SPRAM(\d)/)
+        {
+            my $strIorD = $1;
+            my $nIdxOfSPRAM = $2;
+
+            sysInfoProcLDS_die("no such case IorD: $strIorD index: $nIdxOfSPRAM", __FILE__, __LINE__) if( $strIorD ne "I" && $strIorD ne "D" );
+            
+            my $nSPRAMsize = $INTSRAMinfo{$strINTSRAMname};
+            my $nSPRAMmargin = $nSPRAMsize - (($strIorD eq "I") ? $nISPRAMusedsize[$nIdxOfSPRAM] : $nDSPRAMusedsize[$nIdxOfSPRAM]);
+            $hTCMmargin{$strINTSRAMname} = [$nSPRAMsize, $nSPRAMmargin];
+        }
+        elsif($strINTSRAMname =~ /^L2SRAM/)
+        {
+            my $L2SRAMsize = $INTSRAMinfo{$strINTSRAMname};
+            my $L2SRAMMmargin = $L2SRAMsize - $L2SRAMusedsize;
+            $hTCMmargin{'L2SRAM'} = [$L2SRAMsize, $L2SRAMMmargin];
+        }
+    }
+} # end of  if(0)
+    return (\%hTCMmargin);
+}
+
+#****************************************************************************
+# Subroutine:  GetphysicalRAMsize - to query physical RAM size
+# Parameters:  $BB_PATH = the path of BB folder
+# Returns:     $nRAMsize = the physical RAM size
+#****************************************************************************
+sub GetphysicalRAMsize
+{
+    my ($BB_PATH) = (@_);
+    my $CUSTOM_EMI_RELEASE_H  = $BB_PATH . '/' . "custom_EMI_release.h";
+    my $nRAMsize = 0;
+    
+    open (EMIRELEASEH_HANDLE, "<$CUSTOM_EMI_RELEASE_H") or &sysInfoProcLDS_die("$CUSTOM_EMI_RELEASE_H: file error!", __FILE__, __LINE__);
+    while (<EMIRELEASEH_HANDLE>) {
+        if (/^#define EMI_EXTSRAM_SIZE\s+\(\s*\(*\s*\(*\s*(\S+)\)*\s*<<\s*20\s*\)*\s*>>\s*3\s*\)/)
+        {
+            $nRAMsize = $1 * 1024 * 1024 / 8;
+        }
+    }
+    close (EMIRELEASEH_HANDLE);
+    return $nRAMsize;
+}
+
+#****************************************************************************
+# Subroutine:  GetAvailableRAMsize - to query available RAM size
+# Parameters:  $BB_PATH = the path of BB folder
+# Returns:     $nRAMsize = the available RAM size
+#****************************************************************************
+sub GetAvailableRAMsize
+{
+    my ($BB_PATH) = (@_);
+    my $nRAMsize = undef;
+    my $CUSTOM_FEATURECONFIG_H   = $BB_PATH . '/' . "custom_FeatureConfig.h";
+    my $CUSTOM_EMI_RELEASE_H     = $BB_PATH . '/' . "custom_EMI_release.h";
+    my $bsetLimit = 0;
+    my $isNOR = (&FileInfo::is_NOR() and !FileInfo::is_SmartPhone()) ? 1 : 0;
+
+    open (FEATURECONFIGH_HANDLE, "<$CUSTOM_FEATURECONFIG_H") or &sysInfoProcLDS_die("$CUSTOM_FEATURECONFIG_H: file error!", __FILE__, __LINE__);
+    while (<FEATURECONFIGH_HANDLE>) {
+    if (/^#define PROJECT_EXPECTED_RAM_LIMIT\s*(\w*)/ && $isNOR)
+    {
+        $nRAMsize = hex($1);
+        $bsetLimit = 1;
+    }
+    elsif (/^#define PROJECT_EXPECTED_RAM_LIMIT_NFB\s*(\w*)/)
+    {
+        $nRAMsize = hex($1);
+        $bsetLimit = 1;
+    }
+    }
+    close (FEATURECONFIGH_HANDLE);
+    
+    if($bsetLimit == 0)
+    {
+        open (EMIRELEASEH_HANDLE, "<$CUSTOM_EMI_RELEASE_H") or &sysInfoProcLDS_die("$CUSTOM_EMI_RELEASE_H: file error!", __FILE__, __LINE__);
+        while (<EMIRELEASEH_HANDLE>) {
+        if (/^#define EMI_EXTSRAM_SIZE\s+\(\s*\(*\s*\(*\s*(\S+)\)*\s*<<\s*20\s*\)*\s*>>\s*3\s*\)/)
+        {
+            $nRAMsize = $1 * 1024 * 1024 / 8;
+        }
+        }
+        close (EMIRELEASEH_HANDLE);
+    }
+    return $nRAMsize;
+}
+
+#****************************************************************************
+# Subroutine:  GetRAMregion - to query all regions placed in RAM
+# Parameters:  $BB_PATH
+#              $LDSFILE = the path of lds file
+#              $RAMregion_href = a Array reference to store RAM regions
+#              $RAMregion_href->{regionName} = []
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nRAMnum = the number of RAM regions
+#****************************************************************************
+sub GetRAMregion
+{
+    my ($BB_path, $LDSFILE, $RAMregion_aref, $MAKEFILE_ref) = (@_);
+    &GetLdsInfo($LDSFILE);
+    my $allERs_aref = $g_MAUIlds->GetAllExeRegion();
+    FilterOutRegionInRAM($allERs_aref, $RAMregion_aref);
+    my $nRAMnum = scalar(@$RAMregion_aref);
+    return $nRAMnum;
+}
+
+
+sub FilterOutRegionInRAM
+{
+    my ($ERs_aref, $ERsInRAM_aref) = @_;
+    foreach my $ER (@$ERs_aref)
+    {
+        if($ER =~ /EXTSRAM|BOOT_CERT|.bss|PAGE_TABLE/i and $ER !~ /INTSRAM|BIN|L2CACHE_LOCK|CODE/i)
+        {
+            push(@$ERsInRAM_aref, $ER);
+        }
+    }
+}
+
+sub FilterOutFixedRegion
+{
+    sysInfoProcLDS_die("not support FilterOutFixedRegion", __FILE__, __LINE__);
+
+    my ($ERs_aref, $ERsInRAM_aref) = @_;
+    foreach my $ER (@$ERs_aref)
+    {
+        #######################
+        # FIX_ME: what is fixed region                below 1 line
+        #######################
+        if($ER =~ /TX|RX|FS|TMP_PAGE_TABLE|DSP|BOOT_CERT/i)
+        {
+            push(@$ERsInRAM_aref, $ER);
+        }
+    }
+}
+
+sub GetRegionInfoFromLDS
+{
+    my ($strRegionName, $nOption, $LDSFILE) = (@_);
+    &GetLdsInfo($LDSFILE);
+    return $g_MAUIlds->GetRegionInfo($strRegionName, $nOption);
+}
+
+sub GetMemoryInfoFromLDS
+{
+    #$nOption: 0=Name, 1=Base, 2=Length
+    my ($strRegionName, $nOption, $LDSFILE) = (@_);
+    my $strInfo = undef;
+    if($nOption < 3 or $nOption > 0)
+    {
+        &GetLdsInfo($LDSFILE);
+        my $MemoryInfo_aref = $g_MAUIlds->{ldsInfo}->{MEMORYInfo};
+        
+        foreach my $aref (@$MemoryInfo_aref)
+        {
+            if($strRegionName eq $aref->[0])
+            {
+                $strInfo = $aref->[$nOption];
+                last;
+            }    
+        }
+    }
+    return $strInfo;
+}
+
+
+#****************************************************************************
+# Subroutine:  GetRAMBoundaryregion - to query the boundary regions in RAM
+#              this function can be used to calculate RAM margin
+# Parameters:  $LDSFILE = the path of lds file
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $LAST_CACHED_REGION  = the last cached region in RAM
+#              $DUMMY_END   = the dummy_end region in RAM
+#****************************************************************************
+sub GetRAMBoundaryregion
+{
+    my ($LDSFILE, $MAKEFILE_ref) = (@_);
+    my $bb = $MAKEFILE_ref->{"platform"};
+    my $DUMMY_END = undef;
+    my $LAST_CACHED_REGION  = undef;
+
+    &GetLdsInfo($LDSFILE);
+
+    $DUMMY_END= &Gen_RegionName_EV_DUMMY_END_Base($bb);
+    $LAST_CACHED_REGION = &Gen_RegionName_EV_LAST_CACHED_REGION($bb);
+
+    return ($LAST_CACHED_REGION, $DUMMY_END);
+}
+
+#****************************************************************************
+# Subroutine:  GetphysicalROMsize - to query physical ROM size
+# Parameters:  $BB_PATH = the path of BB folder
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nROMsize = the physical ROM size
+#****************************************************************************
+sub GetphysicalROMsize
+{
+    my ($BB_PATH) = (@_);
+    my $nROMsize = undef;
+    my $CUSTOM_FLASH_H         = $BB_PATH . '/' . "custom_flash.h";
+    my $FLASH_OPT_GEN_H        = $BB_PATH . '/' . "flash_opt_gen.h";
+    my $isNOR = (&FileInfo::is_NOR() and !FileInfo::is_SmartPhone()) ? 1 : 0;
+    
+    if($isNOR)
+    {
+        open (FLASHH_HANDLE, "<$CUSTOM_FLASH_H") or &sysInfoProcLDS_die("$CUSTOM_FLASH_H: file error!", __FILE__, __LINE__);
+        while (<FLASHH_HANDLE>) {
+           if (/^\s*\*\s+NOR_FLASH_SIZE\(Mb\):\s*(\w*)/)
+           {
+               $nROMsize = $1 * 1024 * 1024 / 8;
+           }
+    }
+        close (FLASHH_HANDLE);
+    }
+    else
+    {
+        open (FLASHOPTGENH_HANDLE, "<$FLASH_OPT_GEN_H") or &sysInfoProcLDS_die("$FLASH_OPT_GEN_H: file error!", __FILE__, __LINE__);
+        while (<FLASHOPTGENH_HANDLE>) {
+        if (/^#define NAND_TOTAL_SIZE\s*(\w*)/)
+        {
+              $nROMsize = $1 * 1024 * 1024;
+        }
+    }
+        close (FLASHOPTGENH_HANDLE);
+    }
+    return $nROMsize;
+}
+
+#****************************************************************************
+# Subroutine:  GetAvailableROMsize - to query available ROM size
+# Parameters:  $BB_PATH = the path of BB folder
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nROMsize = the available ROM size
+#****************************************************************************
+sub GetAvailableROMsize
+{
+    my ($BB_PATH) = (@_);
+    my $nROMsize = 0;
+    my $CUSTOM_FEATURECONFIG_H         = $BB_PATH . '/' . "custom_FeatureConfig.h";
+    my $CUSTOM_MEMORYDEVICE_H        = $BB_PATH . '/' . "custom_MemoryDevice.h";
+    my $CUSTOM_FALSH_H        = $BB_PATH . '/' . "custom_flash.h";
+    my $isNOR = (&FileInfo::is_NOR() and !FileInfo::is_SmartPhone()) ? 1 : 0;
+    
+    #code/data can not be executed in NAND flash
+    return $nROMsize if(!$isNOR);
+
+    my %FEATURE_CONFIG_Value;
+    my %MEM_DEV_H_Value;
+    &ParseDefinition($CUSTOM_FEATURECONFIG_H, \%FEATURE_CONFIG_Value);
+    &ParseDefinition($CUSTOM_MEMORYDEVICE_H, \%MEM_DEV_H_Value);
+    
+    if (exists $FEATURE_CONFIG_Value{'PROJECT_EXPECTED_CODE_LIMIT'})
+    {
+        $nROMsize = hex($FEATURE_CONFIG_Value{'PROJECT_EXPECTED_CODE_LIMIT'});;
+    }
+    elsif (exists $MEM_DEV_H_Value{'NOR_BOOTING_NOR_FS_BASE_ADDRESS'})
+    {
+        $nROMsize = hex($MEM_DEV_H_Value{'NOR_BOOTING_NOR_FS_BASE_ADDRESS'});
+    }
+    else
+    {
+        my $flash_size = 0;
+        my $sum_of_regions = 0;
+        my $bisNORFDM5 = 0;
+        my %FLASH_H_Value;
+        my (@FLASH_H_Value_BLK_LIST, @FLASH_H_Value_REGION_LIST, @FLASH_H_Value_BANK_LIST);
+        &ParseFlashInfo($CUSTOM_FALSH_H, \%FLASH_H_Value, \@FLASH_H_Value_BLK_LIST,
+                                                  \@FLASH_H_Value_REGION_LIST,
+                                                  \@FLASH_H_Value_BANK_LIST);
+        $flash_size  = hex($FLASH_H_Value{'NOR_FLASH_DENSITY'});
+        $bisNORFDM5 = ((defined $MEM_DEV_H_Value{'__NOR_FDM5__'}) && ($MEM_DEV_H_Value{'__NOR_FDM5__'} eq 'TRUE')) ? 1 : 0;
+        $sum_of_regions = &Comp_lastBANKsize(\@FLASH_H_Value_REGION_LIST, \@FLASH_H_Value_BLK_LIST, $flash_size, $bisNORFDM5);
+        $nROMsize = $flash_size - $sum_of_regions;
+    }
+    return $nROMsize;
+}
+
+#****************************************************************************
+# Subroutine:  GetROMregion - to query all regions placed in ROM
+# Parameters:  $BB_PATH
+#              $LDSFILE = the path of lds file
+#              $ROMregion_aref = a Array reference to store ROM regions
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     N/A
+#****************************************************************************
+sub GetROMregion
+{
+    my ($BB_path, $LDSFILE, $ROMregion_aref, $MAKEFILE_ref) = @_;
+    
+}
+
+#****************************************************************************
+# Subroutine:  Gen_RegionName_EV_DUMMY_END_Base - to query DUMMY_END region
+# Parameters:  $bb = bb chip
+# Returns:     $strRegionName = region name
+#****************************************************************************
+sub Gen_RegionName_EV_DUMMY_END_Base
+{
+    my ($bb) = (@_);
+    my $strRegionName;
+    $strRegionName = "CACHED_DUMMY_END";
+    $strRegionName = $g_MAUIlds->SearchExeRegionName("DUMMY_END") if(! $g_MAUIlds->IsRegionExistent($strRegionName));
+    return $strRegionName;
+}
+
+#****************************************************************************
+# Subroutine:  Gen_RegionName_EV_LAST_CACHED_REGION - to query the last cached region 
+#              before dummy end
+# Parameters:  $bb = bb chip
+# Returns:     $strPreviousRegionName = region name
+#****************************************************************************
+sub Gen_RegionName_EV_LAST_CACHED_REGION
+{
+    my ($bb) = (@_);
+    #wrong
+    my $strPreviousRegionName;
+    my $strRegionName = &Gen_RegionName_EV_DUMMY_END_Base($bb);
+    $strPreviousRegionName = $g_MAUIlds->GetPreviousExeRegionName($strRegionName) if(defined $strRegionName);
+    &sysInfoProcScat_die("Region Name can't be empty!", __FILE__, __LINE__) if(!defined $strPreviousRegionName);
+    return $strPreviousRegionName;
+}
+
+#****************************************************************************
+# Subroutine: ParseFlashInfo - parse key definition in CUSTOM_FLASH_H
+# Parameters: $strFilePath
+#             $Hash_refResult Container) = a Hash reference to store the parse result
+#             $BLK_LIST_aref = an Array reference to store Block info
+#             $REGION_LIST_aref = an Array reference to store Region info
+#             $BANK_LIST_aref = an Array reference to store Bank info
+#****************************************************************************
+sub ParseFlashInfo
+{
+    my ($strFilePath, $Hash_ref, $BLK_LIST_aref, $REGION_LIST_aref, $BANK_LIST_aref) = @_;
+    open (FLASHC_HANDLE, "<$strFilePath") or &sysInfoProcLDS_die("$strFilePath: file error!", __FILE__, __LINE__);
+    while (<FLASHC_HANDLE>) {
+       if (/^FLASH_REGIONINFO_VAR_MODIFIER\s+FlashBlockTBL\s+\S+/)
+       {
+          $Hash_ref->{'BlockTBLFlag'} ++;
+       }
+       elsif (defined $Hash_ref->{'BlockTBLFlag'})
+       {
+          $Hash_ref->{'BlockTBLTxt'} .= $_;
+          # debug purpose
+          # print $_;
+          if (/\{\s*(\S+)\s*,\s*(\S+)\s*\}/)
+          {
+                push @$BLK_LIST_aref, $_;
+          }
+          delete $Hash_ref->{'BlockTBLFlag'} if (/^\s+EndBlockInfo\s+/);
+       }
+       elsif (/^FLASH_REGIONINFO_VAR_MODIFIER\s+FlashRegionInfo\s+oriRegionInfo\S+/)
+       {
+          $Hash_ref->{'RegionInfoFlag'} ++;
+       }
+       elsif (defined $Hash_ref->{'RegionInfoFlag'})
+       {
+          $Hash_ref->{'RegionInfoTxt'} .= $_;
+          if (/\{\s*(\S+)\s*,\s*(\S+)\s*\}/)
+          {
+             push @$REGION_LIST_aref, $_;
+          }
+          delete $Hash_ref->{'RegionInfoFlag'} if (/^\s+EndoriRegionInfo\s+/);
+       }
+       elsif (/^static\s+NORBankInfo\s+oriBankInfo\S+/)
+       {
+          $Hash_ref->{'BankInfoFlag'} ++;
+       }
+       elsif (defined $Hash_ref->{'BankInfoFlag'})
+       {
+          $Hash_ref->{'BankInfoTxt'} .= $_;
+          if (/\{\s*(\S+)\s*,\s*(\S+)\s*\}/)
+          {
+             push @$BANK_LIST_aref, $_;
+          }
+          delete $Hash_ref->{'BankInfoFlag'} if (/^\s+EndBankInfo\s+/);
+       }
+       elsif (/^\s*\*\s+NOR_FLASH_DENSITY:\s*(\w*)/)
+       {
+       	  $Hash_ref->{'NOR_FLASH_DENSITY'} = $1;
+       }
+       elsif (/^\s*\*\s+NOR_FLASH_SIZE\(Mb\):\s*(\w*)/)
+       {
+       	  $Hash_ref->{'NOR_FLASH_SIZE(Mb)'} = $1;
+       }
+    }
+    close (FLASHC_HANDLE);
+}
+
+#****************************************************************************
+# Subroutine: ParseDefinition - parse key definition in the input file
+# Parameters: $strFilePath
+#             $Hash_refResult Container) = a Hash reference to store the parse result
+#****************************************************************************
+sub ParseDefinition
+{
+    my ($strFilePath, $Hash_ref) = @_;
+    open (MEMDEVH_HANDLE, "<$strFilePath") or &sysInfoProcLDS_die("$strFilePath: file error!", __FILE__, __LINE__);
+    while (<MEMDEVH_HANDLE>) {
+        if (/^#define\s+(\w+)\s+\((\w*)\)/ || /^#define\s+(\w+)\s+(\w*)/)
+        {
+            my $option = $1;
+            my $value  = $2;
+            
+            &sysInfoProcLDS_die("$strFilePath: $option redefined in custom_MemoryDevice.h!", __FILE__, __LINE__) if defined($Hash_ref->{$option});
+            if (!defined $value)
+            {
+                $Hash_ref->{$option} = 'TRUE';
+            }
+            else
+            {
+                $Hash_ref->{$option} = $value;
+            }
+        }
+    }
+    close (MEMDEVH_HANDLE);
+}
+
+#****************************************************************************
+# Subroutine: ParseFlashInfo - parse key definition in CUSTOM_FLASH_H
+# Parameters: $regions_aref = an Array reference to store Region info
+#             $blk_aref = an Array reference to store Block info
+#             $flash_size = Total flash size
+#             $bisFDM5 = check if __NOR_FDM5__
+# Returns   : $fat_space = the size of FAT
+#****************************************************************************
+sub Comp_lastBANKsize
+{
+    my ($regions_aref, $blk_aref, $flash_size , $bisFDM5)  = (@_);
+    my @regions = @$regions_aref;
+    my @blocks              = @$blk_aref;
+    my $small_block_start   = $flash_size;
+    my $sum_of_regions      = 0;
+    my $fat_space           = 0;
+    
+    for (0..$#regions)
+    {
+        if ($regions[$_] =~ /\{(0x\w+),\s*(\d+)\}/) # match {0x20000, 7}
+        {
+            $sum_of_regions += hex($1) * $2;
+        }
+    }
+    
+    if (($#regions>=0) && $bisFDM5)
+    {
+        if ($blocks[$#blocks] =~ /\{(0x\w+),\s*(0x\w+)\}/) # match {0xFF0000,0x2000}
+        {
+            $small_block_start = hex($1);
+        }
+        $fat_space = $sum_of_regions - ($flash_size-$small_block_start);
+    }
+    else
+    {
+        $fat_space = $sum_of_regions;
+    }
+    return $fat_space;
+}
+
+#****************************************************************************
+# Subroutine:  GetLdsInfo - to query Lds info by LdsInfo.pm
+# Parameters:  $LDSFILE = lds file
+#****************************************************************************
+sub GetLdsInfo
+{
+    my ($LDSFILE) = (@_);
+    if(!defined $g_MAUIlds or $g_SavedLDSPath ne $LDSFILE)
+    {
+        $g_MAUIlds = lds_new scatInfo($LDSFILE, "AUROM");
+        $g_SavedLDSPath = $LDSFILE;
+    }
+}
+
+#****************************************************************************
+# subroutine:  sysInfoProcLDS_die
+# sample code: (message, __FILE__, __LINE__)
+# parameters:  $error_msg, $file, $line_no
+#****************************************************************************
+sub sysInfoProcLDS_die
+{
+    my ($error_msg, $file, $line_no) = (@_);
+    &CommonUtil::error_handler($error_msg, $file, $line_no, 'SYSINFOPROCESSLDS');
+}
diff --git a/mcu/tools/MemoryUtility/sysInfoProcessScat.pm b/mcu/tools/MemoryUtility/sysInfoProcessScat.pm
new file mode 100644
index 0000000..87968fe
--- /dev/null
+++ b/mcu/tools/MemoryUtility/sysInfoProcessScat.pm
@@ -0,0 +1,661 @@
+#!/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) 2006

+#

+#  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:

+#* ---------

+#*   sysInfoProcessScat.pm

+#*

+#* Project:

+#* --------

+#*

+#*

+#* Description:

+#* ------------

+#*   This module collects the subroutines for system information. 

+#*       

+#*

+#* Author:

+#* -------

+#*   Carl Kao (mtk08237)

+#*

+#****************************************************************************/

+

+BEGIN { push @INC, '../', './tools/', './tools/MemoryUtility/' }

+package sysInfoProcScat;

+use CommonUtility;

+use sysGenUtility;

+use scatInfo;

+use strict;

+

+#****************************************************************************

+# Constants

+#****************************************************************************

+my $SYSINFOPROCSCAT_VERNO     = " m0.04";

+                 # m0.04 , 2015/01/19,  Memory Utility Refinement

+                 # m0.03 , 2012/08/03,  Modify GetTCMmargin() to store TCM physical size                 

+                 # m0.02 , 2012/08/03,  Modify module name and push additional library path

+                 # m0.01 , 2012/07/05,  Initial revision

+

+#****************************************************************************

+# Global variable

+#****************************************************************************

+my $g_MAUIScat;

+my $DebugPrint = 1;

+

+#****************************************************************************

+# oo >>>  Finished

+#****************************************************************************

+return 1;

+

+#****************************************************************************

+# Subroutine:  GetChipInsideRAMregion - to query all Chip inside RAM regions

+# Parameters:  $SCATTERFILE = the path of scatter file

+#              $INTSRAMregion_href = a Hash reference to store ChipInsideRAM infomation

+#              $INTSRAMregion_href->{regionName} = []

+# Returns:     $nINTSRAMnum = the number of ChipInsideRAM regions

+#****************************************************************************

+sub GetChipInsideRAMregion

+{

+    my ($SCATTERFILE, $INTSRAMregion_href) = (@_);

+    my $nINTSRAMnum = 0;

+

+    &GetScatInfo($SCATTERFILE);

+    my $ExeRegion_ref = $g_MAUIScat->GetAllExeRegion();

+    foreach (@$ExeRegion_ref)

+    {

+        if($_ =~ /EMIINIT_CODE|^INTSRAM|^L2TCM/)

+        {

+            next if ($_ =~ /DUMMY/);

+            $nINTSRAMnum++;

+            $INTSRAMregion_href -> {$_} = [];

+        }

+    }

+    

+    return ($nINTSRAMnum);

+}

+

+#****************************************************************************

+# Subroutine:  GetChipInsideRAMsize - to query ChipInsideRAM size

+# Parameters:  $SCATTERFILE = the path of scatter file

+#              $INTSRAMinfo_href = a Hash reference to store ChipInsideRAM infomation

+#              ($INTSRAMinfo_href -> {ChipInsideRAM type} = MaxSize)

+# Returns:     $nINTSRAMnum = the number of ChipInsideRAM types

+#****************************************************************************

+sub GetChipInsideRAMsize

+{

+    my ($SCATTERFILE, $INTSRAMinfo_href) = (@_);

+    my $nINTSRAMnum = 0;

+    my $strINTSRAMName = undef;

+

+    &GetScatInfo($SCATTERFILE);

+    my $ExeRegion_ref = $g_MAUIScat->GetAllExeRegion();

+    foreach (@$ExeRegion_ref)

+    {

+        if($_ =~ /INTSRAM_CODE|INTSRAM_DATA$|L2TCM_CODE|L2TCM_DATA|INTSRAM_MULTIMEDIA/)

+        {

+            #print "region = $_"."\n";

+            $nINTSRAMnum++;

+            my $Info = $g_MAUIScat->GetExeRegionInfo($_);

+            my $nMaxSize = hex($Info->[Region::MaxSize]);

+            my $strOffest = $Info->[Region::Offset];

+            if($_ eq 'INTSRAM_CODE')

+            {

+                $strINTSRAMName = 'ITCM';

+            }

+            elsif($_ eq 'INTSRAM_DATA')

+            {

+                $strINTSRAMName = 'DTCM';

+                if($strOffest eq '+0x0')

+                {   

+                    $nINTSRAMnum--;

+                    my $TCMsize = $INTSRAMinfo_href->{'ITCM'};

+                    $INTSRAMinfo_href->{'TCM'} = $TCMsize;

+                    delete $INTSRAMinfo_href->{'ITCM'};

+                    next;

+                }

+            }

+            elsif($_ eq 'L2TCM_CODE')

+            {

+                $strINTSRAMName = 'L2TCM_CODE';

+            }

+            elsif($_ eq 'L2TCM_DATA')

+            {

+                $strINTSRAMName = 'L2TCM_DATA';

+            }

+            elsif($_ eq 'INTSRAM_MULTIMEDIA')

+            {

+                $strINTSRAMName = 'MM_SYSRAM';

+            }            

+            $INTSRAMinfo_href->{$strINTSRAMName} = $nMaxSize;

+        }

+    }

+    return ($nINTSRAMnum);

+}

+

+#****************************************************************************

+# Subroutine:  GetTCMmargin - to query TCM margin

+# Parameters:  $SCATTERFILE = the path of scatter file

+#              $TCMregion_href = a Hash reference to store TCM infomation

+#              $TCMregion_href->{'regionName'} = size

+# Returns:     $hTCMmargin = a Hash reference to store TCM information

+#              $TCMmargin_href->{ITCM}->[0] = ITCM physical size, $TCMmargin_href->{ITCM}->[1] = ITCM margin

+#              $TCMmargin_href->{DTCM}->[0] = DTCM physical size, $TCMmargin_href->{DTCM}->[1] = DTCM margin

+#              $TCMmargin_href->{TCM}->[0]  = TCM physical size , $TCMmargin_href->{TCM}->[1]  = TCM margin

+#****************************************************************************

+sub GetTCMmargin

+{

+    my ($SCATTERFILE, $TCMregion_href) = (@_);

+    my %hTCMmargin;

+    my %INTSRAMinfo;

+    my ($TCMmargin, $ITCMmargin, $DTCMmargin) = (undef,undef,undef);

+    my ($ITCMusedsize, $DTCMusedsize) = (0,0);

+    &GetChipInsideRAMsize($SCATTERFILE, \%INTSRAMinfo);

+    

+    foreach my $strINTSRAM (keys %{$TCMregion_href})

+    {

+        if( $strINTSRAM =~ /^INTSRAM/)

+        {

+            $ITCMusedsize += $TCMregion_href->{$strINTSRAM} if($strINTSRAM =~ /CODE/);

+            $DTCMusedsize += $TCMregion_href->{$strINTSRAM} if($strINTSRAM =~ /DATA/);

+        }

+    }

+

+    foreach my $strINTSRAMname (keys %INTSRAMinfo)

+    {

+        if($strINTSRAMname =~ /^TCM/)

+        {

+            my $TCMsize = $INTSRAMinfo{$strINTSRAMname};

+            $TCMmargin = $TCMsize - $ITCMusedsize - $DTCMusedsize;

+            $hTCMmargin{'TCM'} = [$TCMsize, $TCMmargin];

+        }

+        elsif($strINTSRAMname =~ /^ITCM/)

+        {

+            my $ITCMsize = $INTSRAMinfo{$strINTSRAMname};

+            $ITCMmargin = $ITCMsize - $ITCMusedsize;

+            $hTCMmargin{'ITCM'} = [$ITCMsize, $ITCMmargin];

+        }

+        elsif($strINTSRAMname =~ /^DTCM/)

+        {

+            my $DTCMsize = $INTSRAMinfo{$strINTSRAMname};

+            $DTCMmargin = $DTCMsize - $DTCMusedsize;

+            $hTCMmargin{'DTCM'} = [$DTCMsize, $DTCMmargin];

+        }

+    }

+    return (\%hTCMmargin);

+}

+

+

+#****************************************************************************

+# Subroutine:  GetphysicalRAMsize - to query physical RAM size

+# Parameters:  $BB_PATH = the path of BB folder

+# Returns:     $nRAMsize = the physical RAM size

+#****************************************************************************

+sub GetphysicalRAMsize

+{

+    my ($BB_PATH) = (@_);

+    my $CUSTOM_EMI_RELEASE_H  = $BB_PATH . '/' . "custom_EMI_release.h";

+    my $nRAMsize = 0;

+    

+    open (EMIRELEASEH_HANDLE, "<$CUSTOM_EMI_RELEASE_H") or &sysInfoProcess_die("$CUSTOM_EMI_RELEASE_H: file error!", __FILE__, __LINE__);

+    while (<EMIRELEASEH_HANDLE>) {

+        if (/^#define EMI_EXTSRAM_SIZE\s+\(\s*\(*\s*\(*\s*(\S+)\)*\s*<<\s*20\s*\)*\s*>>\s*3\s*\)/)

+        {

+            $nRAMsize = $1 * 1024 * 1024 / 8;

+        }

+    }

+    close (EMIRELEASEH_HANDLE);

+    return $nRAMsize;

+}

+

+

+#****************************************************************************

+# Subroutine:  GetAvailableRAMsize - to query available RAM size

+# Parameters:  $BB_PATH = the path of BB folder

+# Returns:     $nRAMsize = the available RAM size

+#****************************************************************************

+sub GetAvailableRAMsize

+{

+    my ($BB_PATH) = (@_);

+    my $nRAMsize = undef;

+    my $CUSTOM_FEATURECONFIG_H   = $BB_PATH . '/' . "custom_FeatureConfig.h";

+    my $CUSTOM_EMI_RELEASE_H     = $BB_PATH . '/' . "custom_EMI_release.h";

+    my $bsetLimit = 0;

+    my $isNOR = (&FileInfo::is_NOR() and !FileInfo::is_SmartPhone()) ? 1 : 0;

+

+    open (FEATURECONFIGH_HANDLE, "<$CUSTOM_FEATURECONFIG_H") or &sysInfoProcSCAT_die("$CUSTOM_FEATURECONFIG_H: file error!", __FILE__, __LINE__);

+    while (<FEATURECONFIGH_HANDLE>) {

+    if (/^#define PROJECT_EXPECTED_RAM_LIMIT\s*(\w*)/ && $isNOR)

+    {

+        $nRAMsize = hex($1);

+        $bsetLimit = 1;

+    }

+    elsif (/^#define PROJECT_EXPECTED_RAM_LIMIT_NFB\s*(\w*)/)

+    {

+        $nRAMsize = hex($1);

+        $bsetLimit = 1;

+    }

+    }

+    close (FEATURECONFIGH_HANDLE);

+    

+    if($bsetLimit == 0)

+    {

+        open (EMIRELEASEH_HANDLE, "<$CUSTOM_EMI_RELEASE_H") or &sysInfoProcess_die("$CUSTOM_EMI_RELEASE_H: file error!", __FILE__, __LINE__);

+        while (<EMIRELEASEH_HANDLE>) {

+        if (/^#define EMI_EXTSRAM_SIZE\s+\(\s*\(*\s*\(*\s*(\S+)\)*\s*<<\s*20\s*\)*\s*>>\s*3\s*\)/)

+        {

+            $nRAMsize = $1 * 1024 * 1024 / 8;

+        }

+        }

+        close (EMIRELEASEH_HANDLE);

+    }

+    return $nRAMsize;

+}

+

+#****************************************************************************

+# Subroutine:  GetRAMregion - to query all regions placed in RAM

+# Parameters:  $BB_PATH

+#              $SCATTERFILE = the path of scatter file

+#              $RAMregion_aref = a Array reference to store RAM regions

+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information

+# Returns:     $nRAMnum = the number of RAM regions

+#****************************************************************************

+sub GetRAMregion

+{

+    my ($BB_path, $SCATTERFILE, $RAMregion_aref, $MAKEFILE_ref) = (@_);

+    my $CUSTOM_FEATURECONFIG_H = $BB_path . '/' . "custom_FeatureConfig.h";

+    my $nRAMnum = 0;

+    my $isNOR = (&FileInfo::is_NOR() and !FileInfo::is_SmartPhone());

+    

+    &GetScatInfo($SCATTERFILE);

+    my $ExeRegion_ref = $g_MAUIScat->GetAllExeRegion();

+    

+    if(!$isNOR)

+    {

+        foreach (@$ExeRegion_ref)

+        {

+            #print $_."\n";

+            next if($_ =~ /GFH$|SIGNATURE|EMIINIT_CODE|^INTSRAM|^L2TCM|DUMMY|SHOULDBE_EMPTYSECTION/);

+            $nRAMnum++;

+            push(@$RAMregion_aref, $_);

+    }

+    }

+    else

+    {

+        foreach (@$ExeRegion_ref)

+        {

+            if($_ =~ /^EXTSRAM|^CACHED|^DYNAMIC|PAGETABLE/)

+            {

+                next if($_ =~ /DUMMY|SHOULDBE_EMPTYSECTION/);

+                $nRAMnum++;

+                push(@$RAMregion_aref, $_);

+            }

+        }

+    }

+    return ($nRAMnum);

+}

+

+#****************************************************************************

+# Subroutine:  GetRAMBoundaryregion - to query the boundary regions in RAM

+#              this function can be used to calculate RAM margin

+# Parameters:  $SCATTERFILE = the path of scatter file

+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information

+# Returns:     $LAST_CACHED_REGION  = the last cached region in RAM

+#              $DUMMY_END   = the dummy_end region in RAM

+#****************************************************************************

+sub GetRAMBoundaryregion

+{

+    my ($SCATTERFILE, $MAKEFILE_ref) = (@_);

+    my $bb = $MAKEFILE_ref->{"platform"};

+    my $DUMMY_END = undef;

+    my $LAST_CACHED_REGION  = undef;

+

+    &GetScatInfo($SCATTERFILE);

+    $DUMMY_END= &Gen_RegionName_EV_DUMMY_END_Base($bb);

+    $LAST_CACHED_REGION = &Gen_RegionName_EV_LAST_CACHED_REGION($bb);

+

+    return ($LAST_CACHED_REGION, $DUMMY_END);

+}

+

+#****************************************************************************

+# Subroutine:  GetphysicalROMsize - to query physical ROM size

+# Parameters:  $BB_PATH = the path of BB folder

+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information

+# Returns:     $nROMsize = the physical ROM size

+#****************************************************************************

+sub GetphysicalROMsize

+{

+    my ($BB_PATH) = (@_);

+    my $nROMsize = undef;

+    my $CUSTOM_FLASH_H         = $BB_PATH . '/' . "custom_flash.h";

+    my $FLASH_OPT_GEN_H        = $BB_PATH . '/' . "flash_opt_gen.h";

+    my $isNOR = (&FileInfo::is_NOR() and !FileInfo::is_SmartPhone()) ? 1 : 0;

+    

+    if($isNOR)

+    {

+        open (FLASHH_HANDLE, "<$CUSTOM_FLASH_H") or &sysInfoProcSCAT_die("$CUSTOM_FLASH_H: file error!", __FILE__, __LINE__);

+        while (<FLASHH_HANDLE>) {

+           if (/^\s*\*\s+NOR_FLASH_SIZE\(Mb\):\s*(\w*)/)

+           {

+               $nROMsize = $1 * 1024 * 1024 / 8;

+           }

+    }

+        close (FLASHH_HANDLE);

+    }

+    else

+    {

+        open (FLASHOPTGENH_HANDLE, "<$FLASH_OPT_GEN_H") or &sysInfoProcSCAT_die("$FLASH_OPT_GEN_H: file error!", __FILE__, __LINE__);

+        while (<FLASHOPTGENH_HANDLE>) {

+        if (/^#define NAND_TOTAL_SIZE\s*(\w*)/)

+        {

+              $nROMsize = $1 * 1024 * 1024;

+        }

+    }

+        close (FLASHOPTGENH_HANDLE);

+    }

+    return $nROMsize;

+}

+

+#****************************************************************************

+# Subroutine:  GetAvailableROMsize - to query available ROM size

+# Parameters:  $BB_PATH = the path of BB folder

+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information

+# Returns:     $nROMsize = the available ROM size

+#****************************************************************************

+sub GetAvailableROMsize

+{

+    my ($BB_PATH) = (@_);

+    my $nROMsize = 0;

+    my $CUSTOM_FEATURECONFIG_H         = $BB_PATH . '/' . "custom_FeatureConfig.h";

+    my $CUSTOM_MEMORYDEVICE_H        = $BB_PATH . '/' . "custom_MemoryDevice.h";

+    my $CUSTOM_FALSH_H        = $BB_PATH . '/' . "custom_flash.h";

+    my $isNOR = (&FileInfo::is_NOR() and !FileInfo::is_SmartPhone()) ? 1 : 0;

+    

+    #code/data can not be executed in NAND flash

+    return $nROMsize if(!$isNOR);

+

+    my %FEATURE_CONFIG_Value;

+    my %MEM_DEV_H_Value;

+    &ParseDefinition($CUSTOM_FEATURECONFIG_H, \%FEATURE_CONFIG_Value);

+    &ParseDefinition($CUSTOM_MEMORYDEVICE_H, \%MEM_DEV_H_Value);

+    

+    if (exists $FEATURE_CONFIG_Value{'PROJECT_EXPECTED_CODE_LIMIT'})

+    {

+        $nROMsize = hex($FEATURE_CONFIG_Value{'PROJECT_EXPECTED_CODE_LIMIT'});;

+    }

+    elsif (exists $MEM_DEV_H_Value{'NOR_BOOTING_NOR_FS_BASE_ADDRESS'})

+    {

+        $nROMsize = hex($MEM_DEV_H_Value{'NOR_BOOTING_NOR_FS_BASE_ADDRESS'});

+    }

+    else

+    {

+        my $flash_size = 0;

+        my $sum_of_regions = 0;

+        my $bisNORFDM5 = 0;

+        my %FLASH_H_Value;

+        my (@FLASH_H_Value_BLK_LIST, @FLASH_H_Value_REGION_LIST, @FLASH_H_Value_BANK_LIST);

+        &ParseFlashInfo($CUSTOM_FALSH_H, \%FLASH_H_Value, \@FLASH_H_Value_BLK_LIST,

+                                                  \@FLASH_H_Value_REGION_LIST,

+                                                  \@FLASH_H_Value_BANK_LIST);

+        $flash_size  = hex($FLASH_H_Value{'NOR_FLASH_DENSITY'});

+        $bisNORFDM5 = ((defined $MEM_DEV_H_Value{'__NOR_FDM5__'}) && ($MEM_DEV_H_Value{'__NOR_FDM5__'} eq 'TRUE')) ? 1 : 0;

+        $sum_of_regions = &Comp_lastBANKsize(\@FLASH_H_Value_REGION_LIST, \@FLASH_H_Value_BLK_LIST, $flash_size, $bisNORFDM5);

+        $nROMsize = $flash_size - $sum_of_regions;

+    }

+    return $nROMsize;

+}

+

+#****************************************************************************

+# Subroutine:  GetROMregion - to query all regions placed in ROM

+# Parameters:  $BB_PATH

+#              $SCATTERFILE = the path of scatter file

+#              $ROMregion_href = a Hash reference to store ROM regions

+#              $ROMregion_href->{regionName} = []

+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information

+# Returns:     $nROMnum = the number of ROM regions

+#****************************************************************************

+sub GetROMregion

+{

+    my ($BB_path, $SCATTERFILE, $ROMregion_href, $MAKEFILE_ref) = (@_);

+    my $CUSTOM_FEATURECONFIG_H = $BB_path . '/' . "custom_FeatureConfig.h";

+    my $nROMnum = 0;

+    my $isNOR = (&FileInfo::is_NOR() and !FileInfo::is_SmartPhone()) ? 1 : 0;

+

+    return $nROMnum if(!$isNOR);

+

+    &GetScatInfo($SCATTERFILE);

+    my $ExeRegion_ref = $g_MAUIScat->GetAllExeRegion();

+    foreach (@$ExeRegion_ref)

+    {

+        if($_ =~ /^ROM/)

+        {

+            $nROMnum++;

+            $ROMregion_href -> {$_} = [];

+        }

+    }

+    return ($nROMnum);

+}

+

+#****************************************************************************

+# Subroutine:  Gen_RegionName_EV_DUMMY_END_Base - to query DUMMY_END region

+# Parameters:  $bb = bb chip

+# Returns:     $strRegionName = region name

+#****************************************************************************

+sub Gen_RegionName_EV_DUMMY_END_Base

+{

+    my ($bb) = (@_);

+    my $strRegionName;

+    if(1 == &sysUtil::is_mmu($bb))

+    {

+        $strRegionName = "CACHED_DUMMY_END";

+        $strRegionName = $g_MAUIScat->SearchExeRegionName("DUMMY_END") if(! $g_MAUIScat->IsRegionExistent($strRegionName));

+    }

+    return $strRegionName;

+}

+

+#****************************************************************************

+# Subroutine:  Gen_RegionName_EV_LAST_CACHED_REGION - to query the last cached region 

+#              before dummy end

+# Parameters:  $bb = bb chip

+# Returns:     $strPreviousRegionName = region name

+#****************************************************************************

+sub Gen_RegionName_EV_LAST_CACHED_REGION

+{

+    my ($bb) = (@_);

+    my $strPreviousRegionName;

+    if(1 == &sysUtil::is_mmu($bb))

+    {

+        my $strRegionName = &Gen_RegionName_EV_DUMMY_END_Base($bb);

+        $strPreviousRegionName = $g_MAUIScat->GetPreviousExeRegionName($strRegionName) if(defined $strRegionName);

+        &sysInfoProcSCAT_die("Region Name can't be empty!", __FILE__, __LINE__) if(!defined $strPreviousRegionName);

+    }

+    return $strPreviousRegionName;

+}

+#****************************************************************************

+# Subroutine: ParseFlashInfo - parse key definition in CUSTOM_FLASH_H

+# Parameters: $strFilePath

+#             $Hash_refResult Container) = a Hash reference to store the parse result

+#             $BLK_LIST_aref = an Array reference to store Block info

+#             $REGION_LIST_aref = an Array reference to store Region info

+#             $BANK_LIST_aref = an Array reference to store Bank info

+#****************************************************************************

+sub ParseFlashInfo

+{

+    my ($strFilePath, $Hash_ref, $BLK_LIST_aref, $REGION_LIST_aref, $BANK_LIST_aref) = @_;

+    open (FLASHC_HANDLE, "<$strFilePath") or &sysInfoProcSCAT_die("$strFilePath: file error!", __FILE__, __LINE__);

+    while (<FLASHC_HANDLE>) {

+       if (/^FLASH_REGIONINFO_VAR_MODIFIER\s+FlashBlockTBL\s+\S+/)

+       {

+          $Hash_ref->{'BlockTBLFlag'} ++;

+       }

+       elsif (defined $Hash_ref->{'BlockTBLFlag'})

+       {

+          $Hash_ref->{'BlockTBLTxt'} .= $_;

+          # debug purpose

+          # print $_;

+          if (/\{\s*(\S+)\s*,\s*(\S+)\s*\}/)

+          {

+                push @$BLK_LIST_aref, $_;

+          }

+          delete $Hash_ref->{'BlockTBLFlag'} if (/^\s+EndBlockInfo\s+/);

+       }

+       elsif (/^FLASH_REGIONINFO_VAR_MODIFIER\s+FlashRegionInfo\s+oriRegionInfo\S+/)

+       {

+          $Hash_ref->{'RegionInfoFlag'} ++;

+       }

+       elsif (defined $Hash_ref->{'RegionInfoFlag'})

+       {

+          $Hash_ref->{'RegionInfoTxt'} .= $_;

+          if (/\{\s*(\S+)\s*,\s*(\S+)\s*\}/)

+          {

+             push @$REGION_LIST_aref, $_;

+          }

+          delete $Hash_ref->{'RegionInfoFlag'} if (/^\s+EndoriRegionInfo\s+/);

+       }

+       elsif (/^static\s+NORBankInfo\s+oriBankInfo\S+/)

+       {

+          $Hash_ref->{'BankInfoFlag'} ++;

+       }

+       elsif (defined $Hash_ref->{'BankInfoFlag'})

+       {

+          $Hash_ref->{'BankInfoTxt'} .= $_;

+          if (/\{\s*(\S+)\s*,\s*(\S+)\s*\}/)

+          {

+             push @$BANK_LIST_aref, $_;

+          }

+          delete $Hash_ref->{'BankInfoFlag'} if (/^\s+EndBankInfo\s+/);

+       }

+       elsif (/^\s*\*\s+NOR_FLASH_DENSITY:\s*(\w*)/)

+       {

+       	  $Hash_ref->{'NOR_FLASH_DENSITY'} = $1;

+       }

+       elsif (/^\s*\*\s+NOR_FLASH_SIZE\(Mb\):\s*(\w*)/)

+       {

+       	  $Hash_ref->{'NOR_FLASH_SIZE(Mb)'} = $1;

+       }

+    }

+    close (FLASHC_HANDLE);

+}

+

+#****************************************************************************

+# Subroutine: ParseDefinition - parse key definition in the input file

+# Parameters: $strFilePath

+#             $Hash_refResult Container) = a Hash reference to store the parse result

+#****************************************************************************

+sub ParseDefinition

+{

+    my ($strFilePath, $Hash_ref) = @_;

+    open (MEMDEVH_HANDLE, "<$strFilePath") or &sysInfoProcSCAT_die("$strFilePath: file error!", __FILE__, __LINE__);

+    while (<MEMDEVH_HANDLE>) {

+        if (/^#define\s+(\w+)\s+\((\w*)\)/ || /^#define\s+(\w+)\s+(\w*)/)

+        {

+            my $option = $1;

+            my $value  = $2;

+            

+            &sysInfoProcSCAT_die("$strFilePath: $option redefined in custom_MemoryDevice.h!", __FILE__, __LINE__) if defined($Hash_ref->{$option});

+            if (!defined $value)

+            {

+                $Hash_ref->{$option} = 'TRUE';

+            }

+            else

+            {

+                $Hash_ref->{$option} = $value;

+            }

+        }

+    }

+    close (MEMDEVH_HANDLE);

+}

+

+#****************************************************************************

+# Subroutine: ParseFlashInfo - parse key definition in CUSTOM_FLASH_H

+# Parameters: $regions_aref = an Array reference to store Region info

+#             $blk_aref = an Array reference to store Block info

+#             $flash_size = Total flash size

+#             $bisFDM5 = check if __NOR_FDM5__

+# Returns   : $fat_space = the size of FAT

+#****************************************************************************

+sub Comp_lastBANKsize

+{

+    my ($regions_aref, $blk_aref, $flash_size , $bisFDM5)  = (@_);

+    my @regions = @$regions_aref;

+    my @blocks              = @$blk_aref;

+    my $small_block_start   = $flash_size;

+    my $sum_of_regions      = 0;

+    my $fat_space           = 0;

+    

+    for (0..$#regions)

+    {

+        if ($regions[$_] =~ /\{(0x\w+),\s*(\d+)\}/) # match {0x20000, 7}

+        {

+            $sum_of_regions += hex($1) * $2;

+        }

+    }

+    

+    if (($#regions>=0) && $bisFDM5)

+    {

+        if ($blocks[$#blocks] =~ /\{(0x\w+),\s*(0x\w+)\}/) # match {0xFF0000,0x2000}

+        {

+            $small_block_start = hex($1);

+        }

+        $fat_space = $sum_of_regions - ($flash_size-$small_block_start);

+    }

+    else

+    {

+        $fat_space = $sum_of_regions;

+    }

+    return $fat_space;

+}

+

+#****************************************************************************

+# Subroutine:  GetLdsInfo - to query Scat info by LdsInfo.pm

+# Parameters:  $LDSFILE = lds file

+#****************************************************************************

+sub GetScatInfo

+{

+    my ($SCATTERFILE) = (@_);

+    $g_MAUIScat = new scatInfo;

+    $g_MAUIScat->ParseScatterFile($SCATTERFILE);

+}

+

+#****************************************************************************

+# subroutine:  sysInfoProcSCAT_die

+# sample code: (message, __FILE__, __LINE__)

+# parameters:  $error_msg, $file, $line_no

+#****************************************************************************

+sub sysInfoProcSCAT_die

+{

+    my ($error_msg, $file, $line_no) = (@_);

+    &CommonUtil::error_handler($error_msg, $file, $line_no, 'SYSINFOPROCESSSCAT');

+}
\ No newline at end of file
diff --git a/mcu/tools/MemoryUtility/systemInfo.pm b/mcu/tools/MemoryUtility/systemInfo.pm
new file mode 100644
index 0000000..be06e4d
--- /dev/null
+++ b/mcu/tools/MemoryUtility/systemInfo.pm
@@ -0,0 +1,749 @@
+#!/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) 2006
+#
+#  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:
+#* ---------
+#*   SystemInfo.pm
+#*
+#* Project:
+#* --------
+#*
+#*
+#* Description:
+#* ------------
+#*   This module collects the subroutines for system information. 
+#*       
+#*
+#* Author:
+#* -------
+#*   Carl Kao (mtk08237)
+#*
+#****************************************************************************/
+
+BEGIN { push @INC, '../', './tools/', './tools/MemoryUtility/' }
+package sysInfo;
+use sysInfoProcessScat; #this module is applied to RVCT compiler
+use sysInfoProcessLds;  #this module is applied to GCC compiler
+use FileInfoParser;
+use strict;
+
+#****************************************************************************
+# Constants
+#****************************************************************************
+my $SYSINFO_VERNO     = " u0.02";
+             # u0.02 , 2015/01/23,  Add TX/RX section to FilterOutSharedRegion
+             # u0.01 , 2015/01/14,  Memory Utility Refinement
+             # m0.05 , 2013/10/20,  Support FilterOutSecureRegion()
+             # m0.04 , 2013/06/25,  Support FilterOutCoproReservedRegion()
+             # m0.03 , 2012/08/03,  Modify the comment of GetTCMmargin()
+             # m0.02 , 2012/08/03,  Modify module name and push additional library path
+             # m0.01 , 2012/07/05,  Initial revision
+
+#****************************************************************************
+# Global variable
+#****************************************************************************
+my $DebugPrint = 0;
+
+#****************************************************************************
+# oo >>>  Finished
+#****************************************************************************
+return 1;
+
+#****************************************************************************
+# Subroutine:  systemInfo_verno - to query this package's version number
+# Parameters:  x
+# Returns:     version number string
+#****************************************************************************
+sub systemInfo_verno
+{
+    return $SYSINFO_VERNO;
+}
+
+#****************************************************************************
+# Subroutine:  GetChipInsideRAMregion - to query all Chip inside RAM regions
+# Parameters:  $strFilePath = the path of file (scatter file or lds file)
+#              $INTSRAMregion_href = a Hash reference to store ChipInsideRAM infomation
+#              $INTSRAMregion_href->{regionName} = []
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nINTSRAMnum = the number of ChipInsideRAM regions
+#****************************************************************************
+sub GetChipInsideRAMregion
+{
+    my ($strFilePath, $INTSRAMregion_href, $MAKEFILE_ref) = (@_);
+    print "file path = $strFilePath\n" if($DebugPrint == 1);
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+
+    my $nINTSRAMnum = 0;
+    if($strCompiler eq "RVCT")
+    {
+        $nINTSRAMnum = &sysInfoProcScat::GetChipInsideRAMregion($strFilePath, $INTSRAMregion_href);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $nINTSRAMnum = &sysInfoProcLds::GetChipInsideRAMregion($strFilePath, $INTSRAMregion_href);  
+    }
+    return ($nINTSRAMnum);
+}
+
+#****************************************************************************
+# Subroutine:  GetChipInsideRAMsize - to query ChipInsideRAM size
+# Parameters:  $strFilePath = the path of file (scatter file or lds file)
+#              $INTSRAMinfo_href = a Hash reference to store ChipInsideRAM infomation
+#              ($INTSRAMinfo_href -> {ChipInsideRAM type} = MaxSize)
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nINTSRAMnum = the number of ChipInsideRAM types
+#****************************************************************************
+sub GetChipInsideRAMsize
+{
+    my ($strFilePath, $INTSRAMinfo_href, $MAKEFILE_ref) = (@_);
+    print "file path = $strFilePath\n" if($DebugPrint == 1);
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+    
+    my $nINTSRAMnum = 0;
+    if($strCompiler eq "RVCT")
+    {
+        $nINTSRAMnum = &sysInfoProcScat::GetChipInsideRAMsize($strFilePath, $INTSRAMinfo_href);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $nINTSRAMnum = &sysInfoProcLds::GetChipInsideRAMsize($strFilePath, $INTSRAMinfo_href);
+    }
+    return ($nINTSRAMnum);
+}
+
+#****************************************************************************
+# Subroutine:  GetTCMmargin - to query TCM margin
+# Parameters:  $strFilePath = the path of file (scatter file or lds file)
+#              $TCMregion_href = a Hash reference to store TCM infomation
+#              $TCMregion_href->{'regionName'} = size
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $TCMmargin_href = a Hash reference to store TCM information
+#              $TCMmargin_href->{ITCM}->[0] = ITCM physical size, $TCMmargin_href->{ITCM}->[1] = ITCM margin
+#              $TCMmargin_href->{DTCM}->[0] = DTCM physical size, $TCMmargin_href->{DTCM}->[1] = DTCM margin
+#              $TCMmargin_href->{TCM}->[0]  = TCM physical size , $TCMmargin_href->{TCM}->[1]  = TCM margin
+#****************************************************************************
+sub GetTCMmargin
+{
+    my ($strFilePath, $TCMregion_href, $MAKEFILE_ref) = (@_);
+    print "file path = $strFilePath\n" if($DebugPrint == 1);
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+
+    my $TCMmargin_href = undef;
+    if($strCompiler eq "RVCT")
+    {
+        $TCMmargin_href = &sysInfoProcScat::GetTCMmargin($strFilePath, $TCMregion_href);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $TCMmargin_href = &sysInfoProcLds::GetTCMmargin($strFilePath, $TCMregion_href);
+    }
+    return ($TCMmargin_href);
+}
+
+#****************************************************************************
+# Subroutine:  GetphysicalRAMsize - to query physical RAM size
+# Parameters:  $BB_PATH = the path of BB folder
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nRAMsize = the physical RAM size
+#****************************************************************************
+sub GetphysicalRAMsize
+{
+    my ($BB_PATH, $MAKEFILE_ref) = (@_);
+    my $nRAMsize = undef;
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+
+    if($strCompiler eq "RVCT")
+    {
+        $nRAMsize = &sysInfoProcScat::GetphysicalRAMsize($BB_PATH);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $nRAMsize = &sysInfoProcLds::GetphysicalRAMsize($BB_PATH);
+    }
+    return $nRAMsize;
+}
+
+#****************************************************************************
+# Subroutine:  GetAvailableRAMsize - to query available RAM size
+# Parameters:  $BB_PATH = the path of BB folder
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nRAMsize = the available RAM size
+#****************************************************************************
+sub GetAvailableRAMsize
+{
+    my ($BB_PATH, $MAKEFILE_ref) = (@_);
+    my $nRAMsize = undef;
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+
+    if($strCompiler eq "RVCT")
+    {
+        $nRAMsize = &sysInfoProcScat::GetAvailableRAMsize($BB_PATH);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $nRAMsize = &sysInfoProcLds::GetAvailableRAMsize($BB_PATH);
+    }
+    return $nRAMsize;
+}
+
+#****************************************************************************
+# Subroutine:  GetRAMregion - to query all regions placed in RAM
+# Parameters:  $BB_PATH
+#              $strFilePath = the path of file (scatter file or lds file)
+#              $RAMregion_aref = a Array reference to store RAM regions 
+#              $RAMregion_href->{regionName} = []
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nRAMnum = the number of RAM regions
+#****************************************************************************
+sub GetRAMregion
+{
+    my ($BB_PATH, $strFilePath, $RAMregion_aref, $MAKEFILE_ref) = @_;
+    print "file path = $strFilePath\n" if($DebugPrint == 1);
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+    
+    my $nRAMnum = 0;
+    if($strCompiler eq "RVCT")
+    {
+        $nRAMnum = &sysInfoProcScat::GetRAMregion($BB_PATH, $strFilePath, $RAMregion_aref, $MAKEFILE_ref);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $nRAMnum = &sysInfoProcLds::GetRAMregion($BB_PATH, $strFilePath, $RAMregion_aref, $MAKEFILE_ref);  
+    }
+    return ($nRAMnum);
+}
+
+#****************************************************************************
+# Subroutine:  GetRAMBoundaryregion - to query the boundary regions in RAM
+#              this function can be used to calculate RAM margin
+# Parameters:  $strFilePath  = the path of file (scatter file or lds file)
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $LAST_CACHED_REGION  = the last cached region in RAM
+#              $DUMMY_END   = the dummy_end region in RAM
+#****************************************************************************
+sub GetRAMBoundaryregion
+{
+    my ($strFilePath, $MAKEFILE_ref) = (@_);
+    print "file path = $strFilePath\n" if($DebugPrint == 1);
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+
+    my ($LAST_CACHED_REGION, $DUMMY_END)= (undef, undef);
+    if($strCompiler eq "RVCT")
+    {   
+        ($LAST_CACHED_REGION, $DUMMY_END) = &sysInfoProcScat::GetRAMBoundaryregion($strFilePath, $MAKEFILE_ref);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        ($LAST_CACHED_REGION, $DUMMY_END) = &sysInfoProcLds::GetRAMBoundaryregion($strFilePath, $MAKEFILE_ref);  
+    }
+    return ($LAST_CACHED_REGION, $DUMMY_END);
+}
+
+#****************************************************************************
+# Subroutine:  GetphysicalROMsize - to query physical ROM size
+# Parameters:  $BB_PATH = the path of BB folder
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nROMsize = the physical ROM size
+#****************************************************************************
+sub GetphysicalROMsize
+{
+    my ($BB_PATH, $MAKEFILE_ref) = (@_);
+    my $nROMsize = undef;
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+
+    if($strCompiler eq "RVCT")
+    {
+        $nROMsize = &sysInfoProcScat::GetphysicalROMsize($BB_PATH);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $nROMsize = &sysInfoProcLds::GetphysicalROMsize($BB_PATH);
+    }
+    return $nROMsize;
+}
+
+#****************************************************************************
+# Subroutine:  GetAvailableROMsize - to query available ROM size
+# Parameters:  $BB_PATH = the path of BB folder
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nROMsize = the available ROM size
+#****************************************************************************
+sub GetAvailableROMsize
+{
+    my ($BB_PATH, $MAKEFILE_ref) = (@_);
+    my $nROMsize = undef;
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+
+    if($strCompiler eq "RVCT")
+    {
+        $nROMsize = &sysInfoProcScat::GetAvailableROMsize($BB_PATH);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $nROMsize = &sysInfoProcLds::GetAvailableROMsize($BB_PATH);
+    }
+    return $nROMsize;
+}
+
+#****************************************************************************
+# Subroutine:  GetROMregion - to query all regions placed in ROM
+# Parameters:  $BB_PATH
+#              $strFilePath = the path of file (scatter file or lds file)
+#              $ROMregion_href = a Hash reference to store ROM regions
+#              $ROMregion_href->{regionName} = []
+#              $MAKEFILE_ref = a Hash to contain MAKEFILE information
+# Returns:     $nROMnum = the number of ROM regions
+#****************************************************************************
+sub GetROMregion
+{
+    my ($BB_PATH, $strFilePath, $ROMregion_href, $MAKEFILE_ref) = (@_);
+    print "file path = $strFilePath\n" if($DebugPrint == 1);
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+
+    my $nROMnum = 0;
+    if($strCompiler eq "RVCT")
+    {
+        $nROMnum = &sysInfoProcScat::GetROMregion($BB_PATH, $strFilePath, $ROMregion_href, $MAKEFILE_ref);
+    }
+    elsif($strCompiler eq "GCC")
+    {
+        $nROMnum = &sysInfoProcLds::GetROMregion($BB_PATH, $strFilePath, $ROMregion_href, $MAKEFILE_ref);  
+    }
+    return ($nROMnum);
+}
+
+sub FilterOutRegionInRAM
+{
+    my ($prvER_aref, $MAKEFILE_ref) = @_;
+    my @ERInRAM;
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+    if($strCompiler eq "GCC")
+    {
+        &sysInfoProcLds::FilterOutRegionInRAM($prvER_aref, \@ERInRAM);
+    }
+    return \@ERInRAM;
+}
+sub FilterOutFixedRegion
+{
+    my ($prvER_aref, $MAKEFILE_ref) = @_;
+    my @ERInRAM;
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+    if($strCompiler eq "GCC")
+    {
+        &sysInfoProcLds::FilterOutFixedRegion($prvER_aref, \@ERInRAM);
+    }
+    return \@ERInRAM;
+}
+
+sub FilterOutCoproReservedRegion
+{
+    my ($prvER_aref) = @_;
+    my @ERs;
+    my @ReversePrvER = reverse @$prvER_aref;
+    my $bTrim = 0;
+    foreach my $item (@ReversePrvER)
+    {
+        #######################
+        # add L1CORE_LV and L1CORE_RWZI to list
+        #######################
+        if($item !~/copro|L1CORE_LV|L1CORE_RWZI/i)
+        {
+           push (@ERs , $item);   
+        }
+        else
+        {
+           # print "[FilterOutCoproReservedRegion]Skip $item\n";    
+        }
+    }
+    @ERs = reverse @ERs;
+    return \@ERs;
+}
+
+sub FilterOutSecureRegion
+{
+    my ($prvER_aref) = @_;
+    my @ERs;
+    my @ReversePrvER = reverse @$prvER_aref;
+    my $bTrim = 0;
+    foreach my $item (@ReversePrvER)
+    {
+        if($item !~/SECURE_RO|SIGNATURE/i)
+        {
+           push (@ERs , $item);   
+        }
+        else
+        {
+           # print "[FilterOutCoproReservedRegion]Skip $item\n";    
+        }
+    }
+    @ERs = reverse @ERs;
+    return \@ERs;
+}
+
+sub FilterOutSharedRegion
+{
+    my ($prvER_aref) = @_;
+    my @ERs;
+    my @ReversePrvER = reverse @$prvER_aref;
+    my $bTrim = 0;
+    foreach my $item (@ReversePrvER)
+    {
+        if($item !~/SHARED|TX|RX/i)
+        {
+           push (@ERs , $item);   
+        }
+        else
+        {
+           # print "[FilterOutCoproReservedRegion]Skip $item\n";    
+        }
+    }
+    @ERs = reverse @ERs;
+    return \@ERs;
+}
+
+sub GetRegionInfo
+{
+    my ($ER, $nOption, $strFilePath, $MAKEFILE_ref) = @_;
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+    my $Info;
+    if($strCompiler eq "GCC")
+    {
+        $Info = &sysInfoProcLds::GetRegionInfoFromLDS($ER, $nOption, $strFilePath);
+    }
+    return $Info;
+}
+
+sub GetMemoryInfo
+{
+    my ($strName, $nOption, $strFilePath, $MAKEFILE_ref) = @_;
+    my $strCompiler = &FileInfo::GetCompiler($MAKEFILE_ref);
+    my $strInfo;
+    if($strCompiler eq "GCC")
+    {
+        $strInfo = &sysInfoProcLds::GetMemoryInfoFromLDS($strName, $nOption, $strFilePath);
+    }
+    return $strInfo;
+}
+
+__END__
+
+=head1 NAME
+
+systemInfo.pm - Perl module to get system Infomation
+
+=head1 SYNOPSIS
+
+    use systemInfo;
+
+=head2 Table of Contents
+
+systemInfo consists of a collection of modules whose details 
+are too big to fit in one document.  This POD explains the
+top-level APIs and general topics.  For detailed implementation
+, please see the PODs below:
+
+  Name			        Description
+  --------------------------------------------------------
+  sysInfoProcessGCC         Process module for GCC compiler
+  sysInfoProcessRVCT        Process module for RVCT compiler
+  --------------------------------------------------------
+
+=head1 DESCRIPTION
+
+The module provides the interfaces to get the system information under GCC/RVCT build environment
+
+=head1 EXAMPLES
+
+Here are some code samples showing a possible usage of systemInfo:
+
+1. Get all ChipInside-RAM regions
+
+    use systemInfo;
+    use FileInfoParser;
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $file = "/proj/[usrID]/[path]/ldsMT6280_R7R8.txt";
+    my %MAKEFILE_OPTIONS;
+    my %ChipInsideRam_region;
+    my $nChipInsideRAMnum = 0;
+    
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities
+
+    $nChipInsideRAMnum =  &sysInfo::GetChipInsideRAMregion($file, \%ChipInsideRam_region, \%MAKEFILE_OPTIONS);
+    
+    print "nChipInsideRAMnum = $nChipInsideRAMnum\n";
+    foreach my $strRegionName (keys %ChipInsideRam_region)
+    {
+        print "ChipInsideRAMregion = $strINTSRAMname\n";
+    }
+
+    <OUTPUT>
+    
+    nChipInsideRAMnum = 5
+    ChipInsideRAMregion = INTSRAM_PHYSICAL_BOUNDARY
+    ChipInsideRAMregion = INTSRAM_DATA
+    ChipInsideRAMregion = EMIINIT_CODE
+    ChipInsideRAMregion = INTSRAM_DATA_PREINIT_ZI
+    ChipInsideRAMregion = INTSRAM_CODE
+
+2. Get the size of all ChipInside RAM
+
+    use systemInfo;
+    use FileInfoParser;
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $file = "/proj/[usrID]/[path]/ldsMT6280_R7R8.txt";
+    my %MAKEFILE_OPTIONS;
+    my %ChipInsideRAMInfo;
+    my $nChipInsideRAMnum = 0;
+    
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities
+    $nChipInsideRAMnum =  &sysInfo::GetINTSRAMsize($file, \%ChipInsideRAMInfo, \%MAKEFILE_OPTIONS);
+    
+    print "nChipInsideRAMnum = $nChipInsideRAMnum\n";
+    foreach my $strRegionName (keys %ChipInsideRAMInfo)
+    {
+        print "$strRegionName size = ".%ChipInsideRAMInfo->{$strRegionName}."\n";
+    }
+
+    <OUTPUT>
+    
+    nChipInsideRAMnum = 1
+    TCM size = 229376
+    
+3. Get TCM margin (TCM or DTCM/ITCM)
+
+   to use this API, the following steps are listed:
+   
+   [step1]
+       Get all ChipInside RAM regions - run GetChipInsideRAMregion() subroutine in systemInf.pm
+   
+   [step2]
+       Get the usage of each ChipInside RAM region - run GetTotalSizeByExeRegion() subroutine in LinkerOutputParser.pm
+       Store these information in a hash - please refer to the example below
+       ([size] need to replace to the real size get from LinkerOutputParser.pm)
+       my %ChipInsideRAMinfo= (
+            INTSRAM_PHYSICAL_BOUNDARY => [size],
+            INTSRAM_DATA => [size],
+            EMIINIT_CODE => [size],
+            INTSRAM_DATA_PREINIT_ZI => [size],
+            INTSRAM_CODE => [size],
+            );
+   [step3]
+       run this script to get TCM margin
+       (%ChipInsideRAMinfo is created in step2)
+    
+        my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+        my $file = "/proj/[usrID]/[path]/ldsMT6280_R7R8.txt";
+        my %MAKEFILE_OPTIONS;
+        my $TCMmargin_href = undef;
+    
+        &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities   
+        $TCMmargin_href =  &sysInfo::GetTCMmargin($file, \%ChipInsideRAMinfo, \%MAKEFILE_OPTIONS);
+
+        foreach my $strRegionname (keys %$TCMmargin_href)
+        {
+            print "$strRegionname margin = ". $TCMmargin_href->{$strRegionname}."\n";
+        }
+
+    <OUTPUT>
+
+    TCM margin = 228926
+
+4. Get physical RAM size
+    
+    use systemInfo;
+    use FileInfoParser;
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $BB_PATH  = "/proj/[usrID]/[path]/mcu/build/[project]/[flavor]/custom/system";;
+    my %MAKEFILE_OPTIONS;
+    
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities    
+    my $nPhyRAMsize = 0;
+    $nPhyRAMsize = &sysInfo::GetphysicalRAMsize($BB_PATH, \%MAKEFILE_OPTIONS);
+    print "nPhyRAMsize = $phyRAMsize\n";
+    
+    <OUTPUT>
+
+    nPhyRAMsize = 8388608
+    
+5. Get available RAM size
+
+    use systemInfo;
+    use FileInfoParser;
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $BB_PATH  = "/proj/[usrID]/[path]/mcu/build/[project]/[flavor]/custom/system";;
+    my %MAKEFILE_OPTIONS;
+    
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities
+    my $nPhyRAMsize = 0;
+    $nPhyRAMsize = &sysInfo::GetphysicalRAMsize($BB_PATH, \%MAKEFILE_OPTIONS);
+    print "nPhyRAMsize = $phyRAMsize\n";
+    
+    <OUTPUT>
+
+    nPhyRAMsize = 8388608
+
+6. Get RAM regions
+
+    use systemInfo;
+    use FileInfoParser;
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $BB_PATH  = "/proj/[usrID]/[path]/mcu/build/[project]/[flavor]/custom/system";
+    my $file = "/proj/[usrID]/[path]/ldsMT6280_R7R8.txt";    
+    my %MAKEFILE_OPTIONS;
+    my %RAM_region;
+    my $nRAMnum = 0;
+
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities
+    $nRAMnum =  &sysInfo::GetRAMregion($BB_PATH, $file, \%RAM_region, \%MAKEFILE_OPTIONS);
+
+    print "nRAMnum = $nRAMnum\n";
+    foreach my $strRAMname (keys %RAM_region)
+    {
+        print "RAMregion = $strRAMname\n";
+    }
+
+    <OUTPUT>
+    
+    nRAMnum = 15
+    RAMregion = ROM0
+    RAMregion = DYNAMIC_CACHEABLE_EXTSRAM_DEFAULT_NONCACHEABLE_RW
+    RAMregion = DYNAMIC_CACHEABLE_EXTSRAM_DEFAULT_NONCACHEABLE_ZI_MMIPOOL
+    RAMregion = ROMHEAD
+    RAMregion = DYNAMIC_CACHEABLE_EXTSRAM_DEFAULT_CACHEABLE_ZI_MMIPOOL
+    RAMregion = CACHED_EXTSRAM
+    RAMregion = EXTSRAM
+    RAMregion = CACHED_EXTSRAM_NVRAM_LTABLE
+    RAMregion = ROM
+    RAMregion = ROM1
+    RAMregion = EXTSRAM_DSP_TX
+    RAMregion = DYNAMIC_CACHEABLE_EXTSRAM_DEFAULT_CACHEABLE_ZI
+    RAMregion = DYNAMIC_CACHEABLE_EXTSRAM_DEFAULT_NONCACHEABLE_ZI
+    RAMregion = EXTSRAM_DSP_RX
+    RAMregion = DYNAMIC_CACHEABLE_EXTSRAM_DEFAULT_CACHEABLE_RW
+    
+    NOTE: This function can not be applied to 11B branch
+
+7. Get RAM boundary regions
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $file = "/proj/[usrID]/[path]/ldsMT6280_R7R8.txt";
+    my %MAKEFILE_OPTIONS;
+
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities
+    my($LastRegionBeforeDUMMYEND, $DUMMY_END) =  &sysInfo::GetRAMBoundaryregion($file,\%MAKEFILE_OPTIONS);
+
+    print "Last Region Before DUMMY_END = $LastRegionBeforeDUMMYEND\nDUMMY_END = $DUMMY_END\n";
+    
+    <OUTPUT>
+    
+    Last Region Before DUMMY_END = DYNAMIC_CACHEABLE_EXTSRAM_DEFAULT_CACHEABLE_ZI
+    DUMMY_END = CACHED_DUMMY_END
+    
+    Note: This API can be used to get RAM margin
+          RAM margin = DUMMY_END_base - (LastRegionBeforeDUMMYEND_base + LastRegionBeforeDUMMYEND_size);
+    
+8. Get physical ROM size
+    
+    use systemInfo;
+    use FileInfoParser;
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $BB_PATH  = "/proj/[usrID]/[path]/mcu/build/[project]/[flavor]/custom/system";;
+    my %MAKEFILE_OPTIONS;
+    
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities    
+    my $nPhyROMsize = 0;
+    $nPhyROMsize = &sysInfo::GetphysicalROMsize($BB_PATH, \%MAKEFILE_OPTIONS);
+    print "nPhyROMsize = $phyROMsize\n";
+
+    <OUTPUT>
+
+    nPhyROMsize = 268435456
+
+9. Get available ROM size
+
+    use systemInfo;
+    use FileInfoParser;
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $BB_PATH  = "/proj/[usrID]/[path]/mcu/build/[project]/[flavor]/custom/system";;
+    my %MAKEFILE_OPTIONS;
+    
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities
+    my $nPhyROMsize = 0;
+    $nPhyROMsize = &sysInfo::GetphysicalROMsize($BB_PATH, \%MAKEFILE_OPTIONS);
+    print "nPhyRAMsize = $phyRAMsize\n";
+    
+    <OUTPUT>
+
+    nPhyROMsize = 0
+
+10. Get ROM regions
+
+    use systemInfo;
+    use FileInfoParser;
+
+    my $makeFile = "/proj/[usrID]/[path]/MT6280_R7R8_HSPA(FULL_VERSION).mak";
+    my $BB_PATH  = "/proj/[usrID]/[path]/mcu/build/[project]/[flavor]/custom/system";
+    my $file = "/proj/[usrID]/[path]/ldsMT6280_R7R8.txt";
+    my %MAKEFILE_OPTIONS;
+    my %ROM_region;
+    my $nROMnum = 0;
+
+    &FileInfo::Parse_MAKEFILE($makeFile, \%MAKEFILE_OPTIONS); #Must run this subroutine first for other activities
+    $nROMnum =  &sysInfo::GetROMregion($BB_PATH, $file, \%ROM_region, \%MAKEFILE_OPTIONS);
+
+    print "nROMnum = $nROMnum\n";
+    foreach my $strROMname (keys %ROM_region)
+    {
+        print "ROMregion = $strROMname\n";
+    }
+
+    <OUTPUT>
+    
+    nROMnum = 0
+    
+    NOTE: This function can not be applied to 11B branch.
+          for MOLY, all regions will be moved to RAM.
+
+=cut
+
+