]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/Python/Trim/Trim.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / Trim / Trim.py
index 13485c72da51c22e6c12deb51777addcec2da3ae..c479f7d2b2e748dbdde411790be7f5f68cf1951b 100644 (file)
@@ -1,14 +1,8 @@
 ## @file\r
 # Trim files preprocessed by compiler\r
 #\r
-# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution.  The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# SPDX-License-Identifier: BSD-2-Clause-Patent\r
 #\r
 \r
 ##\r
 import Common.LongFilePathOs as os\r
 import sys\r
 import re\r
-\r
+from io import BytesIO\r
+import codecs\r
 from optparse import OptionParser\r
 from optparse import make_option\r
 from Common.BuildToolError import *\r
 from Common.Misc import *\r
+from Common.DataType import *\r
 from Common.BuildVersion import gBUILD_VERSION\r
 import Common.EdkLogger as EdkLogger\r
 from Common.LongFilePathSupport import OpenLongFilePath as open\r
@@ -29,7 +25,7 @@ from Common.LongFilePathSupport import OpenLongFilePath as open
 # Version and Copyright\r
 __version_number__ = ("0.10" + " " + gBUILD_VERSION)\r
 __version__ = "%prog Version " + __version_number__\r
-__copyright__ = "Copyright (c) 2007-2010, Intel Corporation. All rights reserved."\r
+__copyright__ = "Copyright (c) 2007-2018, Intel Corporation. All rights reserved."\r
 \r
 ## Regular expression for matching Line Control directive like "#line xxx"\r
 gLineControlDirective = re.compile('^\s*#(?:line)?\s+([0-9]+)\s+"*([^"]*)"')\r
@@ -37,6 +33,10 @@ gLineControlDirective = re.compile('^\s*#(?:line)?\s+([0-9]+)\s+"*([^"]*)"')
 gTypedefPattern = re.compile("^\s*typedef\s+struct(\s+\w+)?\s*[{]*$", re.MULTILINE)\r
 ## Regular expression for matching "#pragma pack"\r
 gPragmaPattern = re.compile("^\s*#pragma\s+pack", re.MULTILINE)\r
+## Regular expression for matching "typedef"\r
+gTypedef_SinglePattern = re.compile("^\s*typedef", re.MULTILINE)\r
+## Regular expression for matching "typedef struct, typedef union, struct, union"\r
+gTypedef_MulPattern = re.compile("^\s*(typedef)?\s+(struct|union)(\s+\w+)?\s*[{]*$", re.MULTILINE)\r
 \r
 #\r
 # The following number pattern match will only match if following criteria is met:\r
@@ -55,70 +55,10 @@ gAslIncludePattern = re.compile("^(\s*)[iI]nclude\s*\(\"?([^\"\(\)]+)\"\)", re.M
 ## Regular expression for matching C style #include "XXX.asl" in asl file\r
 gAslCIncludePattern = re.compile(r'^(\s*)#include\s*[<"]\s*([-\\/\w.]+)\s*([>"])', re.MULTILINE)\r
 ## Patterns used to convert EDK conventions to EDK2 ECP conventions\r
-gImportCodePatterns = [\r
-    [\r
-        re.compile('^(\s*)\(\*\*PeiServices\)\.PciCfg\s*=\s*([^;\s]+);', re.MULTILINE),\r
-        '''\\1{\r
-\\1  STATIC EFI_PEI_PPI_DESCRIPTOR gEcpPeiPciCfgPpiList = {\r
-\\1    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-\\1    &gEcpPeiPciCfgPpiGuid,\r
-\\1    \\2\r
-\\1  };\r
-\\1  (**PeiServices).InstallPpi (PeiServices, &gEcpPeiPciCfgPpiList);\r
-\\1}'''\r
-    ],\r
-\r
-    [\r
-        re.compile('^(\s*)\(\*PeiServices\)->PciCfg\s*=\s*([^;\s]+);', re.MULTILINE),\r
-        '''\\1{\r
-\\1  STATIC EFI_PEI_PPI_DESCRIPTOR gEcpPeiPciCfgPpiList = {\r
-\\1    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-\\1    &gEcpPeiPciCfgPpiGuid,\r
-\\1    \\2\r
-\\1  };\r
-\\1  (**PeiServices).InstallPpi (PeiServices, &gEcpPeiPciCfgPpiList);\r
-\\1}'''\r
-    ],\r
-\r
-    [\r
-        re.compile("(\s*).+->Modify[\s\n]*\(", re.MULTILINE),\r
-        '\\1PeiLibPciCfgModify ('\r
-    ],\r
-\r
-    [\r
-        re.compile("(\W*)gRT->ReportStatusCode[\s\n]*\(", re.MULTILINE),\r
-        '\\1EfiLibReportStatusCode ('\r
-    ],\r
-\r
-    [\r
-        re.compile('#include\s+EFI_GUID_DEFINITION\s*\(FirmwareFileSystem\)', re.MULTILINE),\r
-        '#include EFI_GUID_DEFINITION (FirmwareFileSystem)\n#include EFI_GUID_DEFINITION (FirmwareFileSystem2)'\r
-    ],\r
-\r
-    [\r
-        re.compile('gEfiFirmwareFileSystemGuid', re.MULTILINE),\r
-        'gEfiFirmwareFileSystem2Guid'\r
-    ],\r
-\r
-    [\r
-        re.compile('EFI_FVH_REVISION', re.MULTILINE),\r
-        'EFI_FVH_PI_REVISION'\r
-    ],\r
-\r
-    [\r
-        re.compile("(\s*)\S*CreateEvent\s*\([\s\n]*EFI_EVENT_SIGNAL_READY_TO_BOOT[^,]*,((?:[^;]+\n)+)(\s*\));", re.MULTILINE),\r
-        '\\1EfiCreateEventReadyToBoot (\\2\\3;'\r
-    ],\r
-\r
-    [\r
-        re.compile("(\s*)\S*CreateEvent\s*\([\s\n]*EFI_EVENT_SIGNAL_LEGACY_BOOT[^,]*,((?:[^;]+\n)+)(\s*\));", re.MULTILINE),\r
-        '\\1EfiCreateEventLegacyBoot (\\2\\3;'\r
-    ],\r
-#    [\r
-#        re.compile("(\W)(PEI_PCI_CFG_PPI)(\W)", re.MULTILINE),\r
-#        '\\1ECP_\\2\\3'\r
-#    ]\r
-]\r
+\r
+## Regular expression for finding header file inclusions\r
+gIncludePattern = re.compile(r"^[ \t]*[%]?[ \t]*include(?:[ \t]*(?:\\(?:\r\n|\r|\n))*[ \t]*)*(?:\(?[\"<]?[ \t]*)([-\w.\\/() \t]+)(?:[ \t]*[\">]?\)?)", re.MULTILINE | re.UNICODE | re.IGNORECASE)\r
+\r
 \r
 ## file cache to avoid circular include in ASL file\r
 gIncludedAslFile = []\r
@@ -135,13 +75,12 @@ gIncludedAslFile = []
 def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong):\r
     CreateDirectory(os.path.dirname(Target))\r
     try:\r
-        f = open (Source, 'r')\r
-    except:\r
+        with open(Source, "r") as File:\r
+            Lines = File.readlines()\r
+    except IOError:\r
         EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source)\r
-\r
-    # read whole file\r
-    Lines = f.readlines()\r
-    f.close()\r
+    except:\r
+        EdkLogger.error("Trim", AUTOGEN_ERROR, "TrimPreprocessedFile: Error while processing file", File=Source)\r
 \r
     PreprocessedFile = ""\r
     InjectedFile = ""\r
@@ -160,7 +99,9 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong):
             if len(MatchList) == 2:\r
                 LineNumber = int(MatchList[0], 0)\r
                 InjectedFile = MatchList[1]\r
-                # The first injetcted file must be the preprocessed file itself\r
+                InjectedFile = os.path.normpath(InjectedFile)\r
+                InjectedFile = os.path.normcase(InjectedFile)\r
+                # The first injected file must be the preprocessed file itself\r
                 if PreprocessedFile == "":\r
                     PreprocessedFile = InjectedFile\r
             LineControlDirectiveFound = True\r
@@ -168,7 +109,7 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong):
         elif PreprocessedFile == "" or InjectedFile != PreprocessedFile:\r
             continue\r
 \r
-        if LineIndexOfOriginalFile == None:\r
+        if LineIndexOfOriginalFile is None:\r
             #\r
             # Any non-empty lines must be from original preprocessed file.\r
             # And this must be the first one.\r
@@ -177,18 +118,18 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong):
             EdkLogger.verbose("Found original file content starting from line %d"\r
                               % (LineIndexOfOriginalFile + 1))\r
 \r
+        if TrimLong:\r
+            Line = gLongNumberPattern.sub(r"\1", Line)\r
         # convert HEX number format if indicated\r
         if ConvertHex:\r
             Line = gHexNumberPattern.sub(r"0\2h", Line)\r
         else:\r
             Line = gHexNumberPattern.sub(r"\1\2", Line)\r
-        if TrimLong:\r
-            Line = gLongNumberPattern.sub(r"\1", Line)\r
 \r
         # convert Decimal number format\r
         Line = gDecNumberPattern.sub(r"\1", Line)\r
 \r
-        if LineNumber != None:\r
+        if LineNumber is not None:\r
             EdkLogger.verbose("Got line directive: line=%d" % LineNumber)\r
             # in case preprocessor removed some lines, like blank or comment lines\r
             if LineNumber <= len(NewLines):\r
@@ -197,7 +138,7 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong):
             else:\r
                 if LineNumber > (len(NewLines) + 1):\r
                     for LineIndex in range(len(NewLines), LineNumber-1):\r
-                        NewLines.append(os.linesep)\r
+                        NewLines.append(TAB_LINE_BREAK)\r
                 NewLines.append(Line)\r
             LineNumber = None\r
             EdkLogger.verbose("Now we have lines: %d" % len(NewLines))\r
@@ -206,15 +147,41 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong):
 \r
     # in case there's no line directive or linemarker found\r
     if (not LineControlDirectiveFound) and NewLines == []:\r
-        NewLines = Lines\r
+        MulPatternFlag = False\r
+        SinglePatternFlag = False\r
+        Brace = 0\r
+        for Index in range(len(Lines)):\r
+            Line = Lines[Index]\r
+            if MulPatternFlag == False and gTypedef_MulPattern.search(Line) is None:\r
+                if SinglePatternFlag == False and gTypedef_SinglePattern.search(Line) is None:\r
+                    # remove "#pragram pack" directive\r
+                    if gPragmaPattern.search(Line) is None:\r
+                        NewLines.append(Line)\r
+                    continue\r
+                elif SinglePatternFlag == False:\r
+                    SinglePatternFlag = True\r
+                if Line.find(";") >= 0:\r
+                    SinglePatternFlag = False\r
+            elif MulPatternFlag == False:\r
+                # found "typedef struct, typedef union, union, struct", keep its position and set a flag\r
+                MulPatternFlag = True\r
+\r
+            # match { and } to find the end of typedef definition\r
+            if Line.find("{") >= 0:\r
+                Brace += 1\r
+            elif Line.find("}") >= 0:\r
+                Brace -= 1\r
+\r
+            # "typedef struct, typedef union, union, struct" must end with a ";"\r
+            if Brace == 0 and Line.find(";") >= 0:\r
+                MulPatternFlag = False\r
 \r
     # save to file\r
     try:\r
-        f = open (Target, 'wb')\r
+        with open(Target, 'w') as File:\r
+            File.writelines(NewLines)\r
     except:\r
         EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target)\r
-    f.writelines(NewLines)\r
-    f.close()\r
 \r
 ## Trim preprocessed VFR file\r
 #\r
@@ -226,14 +193,13 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong):
 #\r
 def TrimPreprocessedVfr(Source, Target):\r
     CreateDirectory(os.path.dirname(Target))\r
-    \r
+\r
     try:\r
-        f = open (Source,'r')\r
+        with open(Source, "r") as File:\r
+            Lines = File.readlines()\r
     except:\r
         EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source)\r
     # read whole file\r
-    Lines = f.readlines()\r
-    f.close()\r
 \r
     FoundTypedef = False\r
     Brace = 0\r
@@ -250,9 +216,9 @@ def TrimPreprocessedVfr(Source, Target):
             Lines[Index] = "\n"\r
             continue\r
 \r
-        if FoundTypedef == False and gTypedefPattern.search(Line) == None:\r
+        if FoundTypedef == False and gTypedefPattern.search(Line) is None:\r
             # keep "#pragram pack" directive\r
-            if gPragmaPattern.search(Line) == None:\r
+            if gPragmaPattern.search(Line) is None:\r
                 Lines[Index] = "\n"\r
             continue\r
         elif FoundTypedef == False:\r
@@ -271,17 +237,16 @@ def TrimPreprocessedVfr(Source, Target):
             FoundTypedef = False\r
             TypedefEnd = Index\r
             # keep all "typedef struct" except to GUID, EFI_PLABEL and PAL_CALL_RETURN\r
-            if Line.strip("} ;\r\n") in ["GUID", "EFI_PLABEL", "PAL_CALL_RETURN"]:\r
+            if Line.strip("} ;\r\n") in [TAB_GUID, "EFI_PLABEL", "PAL_CALL_RETURN"]:\r
                 for i in range(TypedefStart, TypedefEnd+1):\r
                     Lines[i] = "\n"\r
 \r
     # save all lines trimmed\r
     try:\r
-        f = open (Target,'w')\r
+        with open(Target, 'w') as File:\r
+            File.writelines(Lines)\r
     except:\r
         EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target)\r
-    f.writelines(Lines)\r
-    f.close()\r
 \r
 ## Read the content  ASL file, including ASL included, recursively\r
 #\r
@@ -292,9 +257,10 @@ def TrimPreprocessedVfr(Source, Target):
 #                           first for the included file; otherwise, only the path specified\r
 #                           in the IncludePathList will be searched.\r
 #\r
-def DoInclude(Source, Indent='', IncludePathList=[], LocalSearchPath=None):\r
+def DoInclude(Source, Indent='', IncludePathList=[], LocalSearchPath=None, IncludeFileList = None, filetype=None):\r
     NewFileContent = []\r
-\r
+    if IncludeFileList is None:\r
+        IncludeFileList = []\r
     try:\r
         #\r
         # Search LocalSearchPath first if it is specified.\r
@@ -303,18 +269,25 @@ def DoInclude(Source, Indent='', IncludePathList=[], LocalSearchPath=None):
             SearchPathList = [LocalSearchPath] + IncludePathList\r
         else:\r
             SearchPathList = IncludePathList\r
-  \r
+\r
         for IncludePath in SearchPathList:\r
             IncludeFile = os.path.join(IncludePath, Source)\r
             if os.path.isfile(IncludeFile):\r
-                F = open(IncludeFile, "r")\r
+                try:\r
+                    with open(IncludeFile, "r") as File:\r
+                        F = File.readlines()\r
+                except:\r
+                    with codecs.open(IncludeFile, "r", encoding='utf-8') as File:\r
+                        F = File.readlines()\r
                 break\r
         else:\r
-            EdkLogger.error("Trim", "Failed to find include file %s" % Source)\r
+            EdkLogger.warn("Trim", "Failed to find include file %s" % Source)\r
+            return []\r
     except:\r
-        EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source)\r
+        EdkLogger.warn("Trim", FILE_OPEN_FAILURE, ExtraData=Source)\r
+        return []\r
+\r
 \r
-    \r
     # avoid A "include" B and B "include" A\r
     IncludeFile = os.path.abspath(os.path.normpath(IncludeFile))\r
     if IncludeFile in gIncludedAslFile:\r
@@ -322,27 +295,39 @@ def DoInclude(Source, Indent='', IncludePathList=[], LocalSearchPath=None):
                        ExtraData= "%s -> %s" % (" -> ".join(gIncludedAslFile), IncludeFile))\r
         return []\r
     gIncludedAslFile.append(IncludeFile)\r
-    \r
+    IncludeFileList.append(IncludeFile.strip())\r
     for Line in F:\r
         LocalSearchPath = None\r
-        Result = gAslIncludePattern.findall(Line)\r
-        if len(Result) == 0:\r
-            Result = gAslCIncludePattern.findall(Line)\r
-            if len(Result) == 0 or os.path.splitext(Result[0][1])[1].lower() not in [".asl", ".asi"]:\r
+        if filetype == "ASL":\r
+            Result = gAslIncludePattern.findall(Line)\r
+            if len(Result) == 0:\r
+                Result = gAslCIncludePattern.findall(Line)\r
+                if len(Result) == 0 or os.path.splitext(Result[0][1])[1].lower() not in [".asl", ".asi"]:\r
+                    NewFileContent.append("%s%s" % (Indent, Line))\r
+                    continue\r
+                #\r
+                # We should first search the local directory if current file are using pattern #include "XXX"\r
+                #\r
+                if Result[0][2] == '"':\r
+                    LocalSearchPath = os.path.dirname(IncludeFile)\r
+            CurrentIndent = Indent + Result[0][0]\r
+            IncludedFile = Result[0][1]\r
+            NewFileContent.extend(DoInclude(IncludedFile, CurrentIndent, IncludePathList, LocalSearchPath,IncludeFileList,filetype))\r
+            NewFileContent.append("\n")\r
+        elif filetype == "ASM":\r
+            Result = gIncludePattern.findall(Line)\r
+            if len(Result) == 0:\r
                 NewFileContent.append("%s%s" % (Indent, Line))\r
                 continue\r
-            #\r
-            # We should first search the local directory if current file are using pattern #include "XXX" \r
-            #\r
-            if Result[0][2] == '"':\r
-                LocalSearchPath = os.path.dirname(IncludeFile)\r
-        CurrentIndent = Indent + Result[0][0]\r
-        IncludedFile = Result[0][1]\r
-        NewFileContent.extend(DoInclude(IncludedFile, CurrentIndent, IncludePathList, LocalSearchPath))\r
-        NewFileContent.append("\n")\r
+\r
+            IncludedFile = Result[0]\r
+\r
+            IncludedFile = IncludedFile.strip()\r
+            IncludedFile = os.path.normpath(IncludedFile)\r
+            NewFileContent.extend(DoInclude(IncludedFile, '', IncludePathList, LocalSearchPath,IncludeFileList,filetype))\r
+            NewFileContent.append("\n")\r
 \r
     gIncludedAslFile.pop()\r
-    F.close()\r
 \r
     return NewFileContent\r
 \r
@@ -353,20 +338,20 @@ def DoInclude(Source, Indent='', IncludePathList=[], LocalSearchPath=None):
 #\r
 # @param  Source          File to be trimmed\r
 # @param  Target          File to store the trimmed content\r
-# @param  IncludePathFile The file to log the external include path \r
+# @param  IncludePathFile The file to log the external include path\r
 #\r
-def TrimAslFile(Source, Target, IncludePathFile):\r
+def TrimAslFile(Source, Target, IncludePathFile,AslDeps = False):\r
     CreateDirectory(os.path.dirname(Target))\r
-    \r
+\r
     SourceDir = os.path.dirname(Source)\r
     if SourceDir == '':\r
         SourceDir = '.'\r
-    \r
+\r
     #\r
     # Add source directory as the first search directory\r
     #\r
     IncludePathList = [SourceDir]\r
-    \r
+\r
     #\r
     # If additional include path file is specified, append them all\r
     # to the search directory list.\r
@@ -374,7 +359,9 @@ def TrimAslFile(Source, Target, IncludePathFile):
     if IncludePathFile:\r
         try:\r
             LineNum = 0\r
-            for Line in open(IncludePathFile,'r'):\r
+            with open(IncludePathFile, 'r') as File:\r
+                FileLines = File.readlines()\r
+            for Line in FileLines:\r
                 LineNum += 1\r
                 if Line.startswith("/I") or Line.startswith ("-I"):\r
                     IncludePathList.append(Line[2:].strip())\r
@@ -382,8 +369,10 @@ def TrimAslFile(Source, Target, IncludePathFile):
                     EdkLogger.warn("Trim", "Invalid include line in include list file.", IncludePathFile, LineNum)\r
         except:\r
             EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=IncludePathFile)\r
-\r
-    Lines = DoInclude(Source, '', IncludePathList)\r
+    AslIncludes = []\r
+    Lines = DoInclude(Source, '', IncludePathList,IncludeFileList=AslIncludes,filetype='ASL')\r
+    AslIncludes = [item for item in AslIncludes if item !=Source]\r
+    SaveFileOnChange(os.path.join(os.path.dirname(Target),os.path.basename(Source))+".trim.deps", " \\\n".join([Source+":"] +AslIncludes),False)\r
 \r
     #\r
     # Undef MIN and MAX to avoid collision in ASL source code\r
@@ -392,103 +381,118 @@ def TrimAslFile(Source, Target, IncludePathFile):
 \r
     # save all lines trimmed\r
     try:\r
-        f = open (Target,'w')\r
+        with open(Target, 'w') as File:\r
+            File.writelines(Lines)\r
     except:\r
         EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target)\r
 \r
-    f.writelines(Lines)\r
-    f.close()\r
-\r
-## Trim EDK source code file(s)\r
-#\r
-#\r
-# @param  Source    File or directory to be trimmed\r
-# @param  Target    File or directory to store the trimmed content\r
-#\r
-def TrimEdkSources(Source, Target):\r
-    if os.path.isdir(Source):\r
-        for CurrentDir, Dirs, Files in os.walk(Source):\r
-            if '.svn' in Dirs:\r
-                Dirs.remove('.svn')\r
-            elif "CVS" in Dirs:\r
-                Dirs.remove("CVS")\r
-\r
-            for FileName in Files:\r
-                Dummy, Ext = os.path.splitext(FileName)\r
-                if Ext.upper() not in ['.C', '.H']: continue\r
-                if Target == None or Target == '':\r
-                    TrimEdkSourceCode(\r
-                        os.path.join(CurrentDir, FileName),\r
-                        os.path.join(CurrentDir, FileName)\r
-                        )\r
-                else:\r
-                    TrimEdkSourceCode(\r
-                        os.path.join(CurrentDir, FileName),\r
-                        os.path.join(Target, CurrentDir[len(Source)+1:], FileName)\r
-                        )\r
-    else:\r
-        TrimEdkSourceCode(Source, Target)\r
-\r
-## Trim one EDK source code file\r
+## Trim ASM file\r
 #\r
-# Do following replacement:\r
+# Output ASM include statement with the content the included file\r
 #\r
-#   (**PeiServices\).PciCfg = <*>;\r
-#   =>  {\r
-#         STATIC EFI_PEI_PPI_DESCRIPTOR gEcpPeiPciCfgPpiList = {\r
-#         (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-#         &gEcpPeiPciCfgPpiGuid,\r
-#         <*>\r
-#       };\r
-#       (**PeiServices).InstallPpi (PeiServices, &gEcpPeiPciCfgPpiList);\r
-#\r
-#   <*>Modify(<*>)\r
-#   =>  PeiLibPciCfgModify (<*>)\r
-#\r
-#   gRT->ReportStatusCode (<*>)\r
-#   => EfiLibReportStatusCode (<*>)\r
-#\r
-#   #include <LoadFile\.h>\r
-#   =>  #include <FvLoadFile.h>\r
-#\r
-#   CreateEvent (EFI_EVENT_SIGNAL_READY_TO_BOOT, <*>)\r
-#   => EfiCreateEventReadyToBoot (<*>)\r
-#\r
-#   CreateEvent (EFI_EVENT_SIGNAL_LEGACY_BOOT, <*>)\r
-#   =>  EfiCreateEventLegacyBoot (<*>)\r
-#\r
-# @param  Source    File to be trimmed\r
-# @param  Target    File to store the trimmed content\r
+# @param  Source          File to be trimmed\r
+# @param  Target          File to store the trimmed content\r
+# @param  IncludePathFile The file to log the external include path\r
 #\r
-def TrimEdkSourceCode(Source, Target):\r
-    EdkLogger.verbose("\t%s -> %s" % (Source, Target))\r
+def TrimAsmFile(Source, Target, IncludePathFile):\r
     CreateDirectory(os.path.dirname(Target))\r
 \r
+    SourceDir = os.path.dirname(Source)\r
+    if SourceDir == '':\r
+        SourceDir = '.'\r
+\r
+    #\r
+    # Add source directory as the first search directory\r
+    #\r
+    IncludePathList = [SourceDir]\r
+    #\r
+    # If additional include path file is specified, append them all\r
+    # to the search directory list.\r
+    #\r
+    if IncludePathFile:\r
+        try:\r
+            LineNum = 0\r
+            with open(IncludePathFile, 'r') as File:\r
+                FileLines = File.readlines()\r
+            for Line in FileLines:\r
+                LineNum += 1\r
+                if Line.startswith("/I") or Line.startswith ("-I"):\r
+                    IncludePathList.append(Line[2:].strip())\r
+                else:\r
+                    EdkLogger.warn("Trim", "Invalid include line in include list file.", IncludePathFile, LineNum)\r
+        except:\r
+            EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=IncludePathFile)\r
+    AsmIncludes = []\r
+    Lines = DoInclude(Source, '', IncludePathList,IncludeFileList=AsmIncludes,filetype='ASM')\r
+    AsmIncludes = [item for item in AsmIncludes if item != Source]\r
+    if AsmIncludes:\r
+        SaveFileOnChange(os.path.join(os.path.dirname(Target),os.path.basename(Source))+".trim.deps", " \\\n".join([Source+":"] +AsmIncludes),False)\r
+    # save all lines trimmed\r
     try:\r
-        f = open (Source,'rb')\r
+        with open(Target, 'w') as File:\r
+            File.writelines(Lines)\r
     except:\r
-        EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source)\r
-    # read whole file\r
-    Lines = f.read()\r
-    f.close()\r
+        EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target)\r
 \r
-    NewLines = None\r
-    for Re,Repl in gImportCodePatterns:\r
-        if NewLines == None:\r
-            NewLines = Re.sub(Repl, Lines)\r
-        else:\r
-            NewLines = Re.sub(Repl, NewLines)\r
+def GenerateVfrBinSec(ModuleName, DebugDir, OutputFile):\r
+    VfrNameList = []\r
+    if os.path.isdir(DebugDir):\r
+        for CurrentDir, Dirs, Files in os.walk(DebugDir):\r
+            for FileName in Files:\r
+                Name, Ext = os.path.splitext(FileName)\r
+                if Ext == '.c' and Name != 'AutoGen':\r
+                    VfrNameList.append (Name + 'Bin')\r
+\r
+    VfrNameList.append (ModuleName + 'Strings')\r
 \r
-    # save all lines if trimmed\r
-    if Source == Target and NewLines == Lines:\r
+    EfiFileName = os.path.join(DebugDir, ModuleName + '.efi')\r
+    MapFileName = os.path.join(DebugDir, ModuleName + '.map')\r
+    VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrNameList)\r
+\r
+    if not VfrUniOffsetList:\r
         return\r
 \r
     try:\r
-        f = open (Target,'wb')\r
+        fInputfile = open(OutputFile, "wb+")\r
     except:\r
-        EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Target)\r
-    f.write(NewLines)\r
-    f.close()\r
+        EdkLogger.error("Trim", FILE_OPEN_FAILURE, "File open failed for %s" %OutputFile, None)\r
+\r
+    # Use a instance of BytesIO to cache data\r
+    fStringIO = BytesIO()\r
+\r
+    for Item in VfrUniOffsetList:\r
+        if (Item[0].find("Strings") != -1):\r
+            #\r
+            # UNI offset in image.\r
+            # GUID + Offset\r
+            # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } }\r
+            #\r
+            UniGuid = b'\xe0\xc5\x13\x89\xf63\x86M\x9b\xf1C\xef\x89\xfc\x06f'\r
+            fStringIO.write(UniGuid)\r
+            UniValue = pack ('Q', int (Item[1], 16))\r
+            fStringIO.write (UniValue)\r
+        else:\r
+            #\r
+            # VFR binary offset in image.\r
+            # GUID + Offset\r
+            # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } };\r
+            #\r
+            VfrGuid = b'\xb4|\xbc\xd0Gj_I\xaa\x11q\x07F\xda\x06\xa2'\r
+            fStringIO.write(VfrGuid)\r
+            type (Item[1])\r
+            VfrValue = pack ('Q', int (Item[1], 16))\r
+            fStringIO.write (VfrValue)\r
+\r
+    #\r
+    # write data into file.\r
+    #\r
+    try :\r
+        fInputfile.write (fStringIO.getvalue())\r
+    except:\r
+        EdkLogger.error("Trim", FILE_WRITE_FAILURE, "Write data to file %s failed, please check whether the file been locked or using by other applications." %OutputFile, None)\r
+\r
+    fStringIO.close ()\r
+    fInputfile.close ()\r
 \r
 \r
 ## Parse command line options\r
@@ -504,11 +508,14 @@ def Options():
                           help="The input file is preprocessed source code, including C or assembly code"),\r
         make_option("-r", "--vfr-file", dest="FileType", const="Vfr", action="store_const",\r
                           help="The input file is preprocessed VFR file"),\r
+        make_option("--Vfr-Uni-Offset", dest="FileType", const="VfrOffsetBin", action="store_const",\r
+                          help="The input file is EFI image"),\r
+        make_option("--asl-deps", dest="AslDeps", const="True", action="store_const",\r
+                          help="Generate Asl dependent files."),\r
         make_option("-a", "--asl-file", dest="FileType", const="Asl", action="store_const",\r
                           help="The input file is ASL file"),\r
-        make_option("-8", "--Edk-source-code", dest="FileType", const="EdkSourceCode", action="store_const",\r
-                          help="The input file is source code for Edk to be trimmed for ECP"),\r
-\r
+        make_option( "--asm-file", dest="FileType", const="Asm", action="store_const",\r
+                          help="The input file is asm file"),\r
         make_option("-c", "--convert-hex", dest="ConvertHex", action="store_true",\r
                           help="Convert standard hex format (0xabcd) to MASM format (abcdh)"),\r
 \r
@@ -518,6 +525,9 @@ def Options():
                           help="The input file is include path list to search for ASL include file"),\r
         make_option("-o", "--output", dest="OutputFile",\r
                           help="File to store the trimmed content"),\r
+        make_option("--ModuleName", dest="ModuleName", help="The module's BASE_NAME"),\r
+        make_option("--DebugDir", dest="DebugDir",\r
+                          help="Debug Output directory to store the output files"),\r
         make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE,\r
                           help="Run verbosely"),\r
         make_option("-d", "--debug", dest="LogLevel", type="int",\r
@@ -528,7 +538,7 @@ def Options():
     ]\r
 \r
     # use clearer usage to override default usage message\r
-    UsageString = "%prog [-s|-r|-a] [-c] [-v|-d <debug_level>|-q] [-i <include_path_file>] [-o <output_file>] <input_file>"\r
+    UsageString = "%prog [-s|-r|-a|--Vfr-Uni-Offset] [-c] [-v|-d <debug_level>|-q] [-i <include_path_file>] [-o <output_file>] [--ModuleName <ModuleName>] [--DebugDir <DebugDir>] [<input_file>]"\r
 \r
     Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString)\r
     Parser.set_defaults(FileType="Vfr")\r
@@ -538,6 +548,11 @@ def Options():
     Options, Args = Parser.parse_args()\r
 \r
     # error check\r
+    if Options.FileType == 'VfrOffsetBin':\r
+        if len(Args) == 0:\r
+            return Options, ''\r
+        elif len(Args) > 1:\r
+            EdkLogger.error("Trim", OPTION_NOT_SUPPORTED, ExtraData=Parser.get_usage())\r
     if len(Args) == 0:\r
         EdkLogger.error("Trim", OPTION_MISSING, ExtraData=Parser.get_usage())\r
     if len(Args) > 1:\r
@@ -563,28 +578,30 @@ def Main():
             EdkLogger.SetLevel(CommandOptions.LogLevel + 1)\r
         else:\r
             EdkLogger.SetLevel(CommandOptions.LogLevel)\r
-    except FatalError, X:\r
+    except FatalError as X:\r
         return 1\r
-    \r
+\r
     try:\r
         if CommandOptions.FileType == "Vfr":\r
-            if CommandOptions.OutputFile == None:\r
+            if CommandOptions.OutputFile is None:\r
                 CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii'\r
             TrimPreprocessedVfr(InputFile, CommandOptions.OutputFile)\r
         elif CommandOptions.FileType == "Asl":\r
-            if CommandOptions.OutputFile == None:\r
+            if CommandOptions.OutputFile is None:\r
                 CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii'\r
-            TrimAslFile(InputFile, CommandOptions.OutputFile, CommandOptions.IncludePathFile)\r
-        elif CommandOptions.FileType == "EdkSourceCode":\r
-            TrimEdkSources(InputFile, CommandOptions.OutputFile)\r
+            TrimAslFile(InputFile, CommandOptions.OutputFile, CommandOptions.IncludePathFile,CommandOptions.AslDeps)\r
+        elif CommandOptions.FileType == "VfrOffsetBin":\r
+            GenerateVfrBinSec(CommandOptions.ModuleName, CommandOptions.DebugDir, CommandOptions.OutputFile)\r
+        elif CommandOptions.FileType == "Asm":\r
+            TrimAsmFile(InputFile, CommandOptions.OutputFile, CommandOptions.IncludePathFile)\r
         else :\r
-            if CommandOptions.OutputFile == None:\r
+            if CommandOptions.OutputFile is None:\r
                 CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii'\r
             TrimPreprocessedFile(InputFile, CommandOptions.OutputFile, CommandOptions.ConvertHex, CommandOptions.TrimLong)\r
-    except FatalError, X:\r
+    except FatalError as X:\r
         import platform\r
         import traceback\r
-        if CommandOptions != None and CommandOptions.LogLevel <= EdkLogger.DEBUG_9:\r
+        if CommandOptions is not None and CommandOptions.LogLevel <= EdkLogger.DEBUG_9:\r
             EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r
         return 1\r
     except:\r
@@ -594,7 +611,7 @@ def Main():
                     "\nTrim",\r
                     CODE_ERROR,\r
                     "Unknown fatal error when trimming [%s]" % InputFile,\r
-                    ExtraData="\n(Please send email to edk2-buildtools-devel@lists.sourceforge.net for help, attaching following call stack trace!)\n",\r
+                    ExtraData="\n(Please send email to %s for help, attaching following call stack trace!)\n" % MSG_EDKII_MAIL_ADDR,\r
                     RaiseError=False\r
                     )\r
         EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())\r