X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FPython%2FTrim%2FTrim.py;h=b512d15243f83225457b2dc099ac0c026142a5ed;hp=c0ede0335993690727bfef6b4d3fd0edcc96511e;hb=92beb1e4c73a40a708c7c0cade5c7cee314b3887;hpb=f51461c829c124288a930829a78e2a5a799f4039 diff --git a/BaseTools/Source/Python/Trim/Trim.py b/BaseTools/Source/Python/Trim/Trim.py index c0ede03359..b512d15243 100644 --- a/BaseTools/Source/Python/Trim/Trim.py +++ b/BaseTools/Source/Python/Trim/Trim.py @@ -1,7 +1,7 @@ ## @file # Trim files preprocessed by compiler # -# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
# This program and the accompanying materials # are licensed and made available under the terms and conditions of the BSD License # which accompanies this distribution. The full text of the license may be found at @@ -14,21 +14,24 @@ ## # Import Modules # -import os +import Common.LongFilePathOs as os import sys import re +import StringIO from optparse import OptionParser from optparse import make_option from Common.BuildToolError import * from Common.Misc import * +from Common.DataType import * from Common.BuildVersion import gBUILD_VERSION import Common.EdkLogger as EdkLogger +from Common.LongFilePathSupport import OpenLongFilePath as open # Version and Copyright __version_number__ = ("0.10" + " " + gBUILD_VERSION) __version__ = "%prog Version " + __version_number__ -__copyright__ = "Copyright (c) 2007-2010, Intel Corporation. All rights reserved." +__copyright__ = "Copyright (c) 2007-2017, Intel Corporation. All rights reserved." ## Regular expression for matching Line Control directive like "#line xxx" gLineControlDirective = re.compile('^\s*#(?:line)?\s+([0-9]+)\s+"*([^"]*)"') @@ -36,6 +39,10 @@ gLineControlDirective = re.compile('^\s*#(?:line)?\s+([0-9]+)\s+"*([^"]*)"') gTypedefPattern = re.compile("^\s*typedef\s+struct(\s+\w+)?\s*[{]*$", re.MULTILINE) ## Regular expression for matching "#pragma pack" gPragmaPattern = re.compile("^\s*#pragma\s+pack", re.MULTILINE) +## Regular expression for matching "typedef" +gTypedef_SinglePattern = re.compile("^\s*typedef", re.MULTILINE) +## Regular expression for matching "typedef struct, typedef union, struct, union" +gTypedef_MulPattern = re.compile("^\s*(typedef)?\s+(struct|union)(\s+\w+)?\s*[{]*$", re.MULTILINE) # # The following number pattern match will only match if following criteria is met: @@ -167,7 +174,7 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong): elif PreprocessedFile == "" or InjectedFile != PreprocessedFile: continue - if LineIndexOfOriginalFile == None: + if LineIndexOfOriginalFile is None: # # Any non-empty lines must be from original preprocessed file. # And this must be the first one. @@ -176,18 +183,18 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong): EdkLogger.verbose("Found original file content starting from line %d" % (LineIndexOfOriginalFile + 1)) + if TrimLong: + Line = gLongNumberPattern.sub(r"\1", Line) # convert HEX number format if indicated if ConvertHex: Line = gHexNumberPattern.sub(r"0\2h", Line) else: Line = gHexNumberPattern.sub(r"\1\2", Line) - if TrimLong: - Line = gLongNumberPattern.sub(r"\1", Line) # convert Decimal number format Line = gDecNumberPattern.sub(r"\1", Line) - if LineNumber != None: + if LineNumber is not None: EdkLogger.verbose("Got line directive: line=%d" % LineNumber) # in case preprocessor removed some lines, like blank or comment lines if LineNumber <= len(NewLines): @@ -205,7 +212,34 @@ def TrimPreprocessedFile(Source, Target, ConvertHex, TrimLong): # in case there's no line directive or linemarker found if (not LineControlDirectiveFound) and NewLines == []: - NewLines = Lines + MulPatternFlag = False + SinglePatternFlag = False + Brace = 0 + for Index in range(len(Lines)): + Line = Lines[Index] + if MulPatternFlag == False and gTypedef_MulPattern.search(Line) is None: + if SinglePatternFlag == False and gTypedef_SinglePattern.search(Line) is None: + # remove "#pragram pack" directive + if gPragmaPattern.search(Line) is None: + NewLines.append(Line) + continue + elif SinglePatternFlag == False: + SinglePatternFlag = True + if Line.find(";") >= 0: + SinglePatternFlag = False + elif MulPatternFlag == False: + # found "typedef struct, typedef union, union, struct", keep its position and set a flag + MulPatternFlag = True + + # match { and } to find the end of typedef definition + if Line.find("{") >= 0: + Brace += 1 + elif Line.find("}") >= 0: + Brace -= 1 + + # "typedef struct, typedef union, union, struct" must end with a ";" + if Brace == 0 and Line.find(";") >= 0: + MulPatternFlag = False # save to file try: @@ -249,9 +283,9 @@ def TrimPreprocessedVfr(Source, Target): Lines[Index] = "\n" continue - if FoundTypedef == False and gTypedefPattern.search(Line) == None: + if FoundTypedef == False and gTypedefPattern.search(Line) is None: # keep "#pragram pack" directive - if gPragmaPattern.search(Line) == None: + if gPragmaPattern.search(Line) is None: Lines[Index] = "\n" continue elif FoundTypedef == False: @@ -270,7 +304,7 @@ def TrimPreprocessedVfr(Source, Target): FoundTypedef = False TypedefEnd = Index # keep all "typedef struct" except to GUID, EFI_PLABEL and PAL_CALL_RETURN - if Line.strip("} ;\r\n") in ["GUID", "EFI_PLABEL", "PAL_CALL_RETURN"]: + if Line.strip("} ;\r\n") in [TAB_GUID, "EFI_PLABEL", "PAL_CALL_RETURN"]: for i in range(TypedefStart, TypedefEnd+1): Lines[i] = "\n" @@ -398,6 +432,68 @@ def TrimAslFile(Source, Target, IncludePathFile): f.writelines(Lines) f.close() +def GenerateVfrBinSec(ModuleName, DebugDir, OutputFile): + VfrNameList = [] + if os.path.isdir(DebugDir): + for CurrentDir, Dirs, Files in os.walk(DebugDir): + for FileName in Files: + Name, Ext = os.path.splitext(FileName) + if Ext == '.c' and Name != 'AutoGen': + VfrNameList.append (Name + 'Bin') + + VfrNameList.append (ModuleName + 'Strings') + + EfiFileName = os.path.join(DebugDir, ModuleName + '.efi') + MapFileName = os.path.join(DebugDir, ModuleName + '.map') + VfrUniOffsetList = GetVariableOffset(MapFileName, EfiFileName, VfrNameList) + + if not VfrUniOffsetList: + return + + try: + fInputfile = open(OutputFile, "wb+", 0) + except: + EdkLogger.error("Trim", FILE_OPEN_FAILURE, "File open failed for %s" %OutputFile, None) + + # Use a instance of StringIO to cache data + fStringIO = StringIO.StringIO('') + + for Item in VfrUniOffsetList: + if (Item[0].find("Strings") != -1): + # + # UNI offset in image. + # GUID + Offset + # { 0x8913c5e0, 0x33f6, 0x4d86, { 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66 } } + # + UniGuid = [0xe0, 0xc5, 0x13, 0x89, 0xf6, 0x33, 0x86, 0x4d, 0x9b, 0xf1, 0x43, 0xef, 0x89, 0xfc, 0x6, 0x66] + UniGuid = [chr(ItemGuid) for ItemGuid in UniGuid] + fStringIO.write(''.join(UniGuid)) + UniValue = pack ('Q', int (Item[1], 16)) + fStringIO.write (UniValue) + else: + # + # VFR binary offset in image. + # GUID + Offset + # { 0xd0bc7cb4, 0x6a47, 0x495f, { 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2 } }; + # + VfrGuid = [0xb4, 0x7c, 0xbc, 0xd0, 0x47, 0x6a, 0x5f, 0x49, 0xaa, 0x11, 0x71, 0x7, 0x46, 0xda, 0x6, 0xa2] + VfrGuid = [chr(ItemGuid) for ItemGuid in VfrGuid] + fStringIO.write(''.join(VfrGuid)) + type (Item[1]) + VfrValue = pack ('Q', int (Item[1], 16)) + fStringIO.write (VfrValue) + + # + # write data into file. + # + try : + fInputfile.write (fStringIO.getvalue()) + except: + 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) + + fStringIO.close () + fInputfile.close () + ## Trim EDK source code file(s) # # @@ -415,7 +511,7 @@ def TrimEdkSources(Source, Target): for FileName in Files: Dummy, Ext = os.path.splitext(FileName) if Ext.upper() not in ['.C', '.H']: continue - if Target == None or Target == '': + if Target is None or Target == '': TrimEdkSourceCode( os.path.join(CurrentDir, FileName), os.path.join(CurrentDir, FileName) @@ -473,7 +569,7 @@ def TrimEdkSourceCode(Source, Target): NewLines = None for Re,Repl in gImportCodePatterns: - if NewLines == None: + if NewLines is None: NewLines = Re.sub(Repl, Lines) else: NewLines = Re.sub(Repl, NewLines) @@ -503,6 +599,8 @@ def Options(): help="The input file is preprocessed source code, including C or assembly code"), make_option("-r", "--vfr-file", dest="FileType", const="Vfr", action="store_const", help="The input file is preprocessed VFR file"), + make_option("--Vfr-Uni-Offset", dest="FileType", const="VfrOffsetBin", action="store_const", + help="The input file is EFI image"), make_option("-a", "--asl-file", dest="FileType", const="Asl", action="store_const", help="The input file is ASL file"), make_option("-8", "--Edk-source-code", dest="FileType", const="EdkSourceCode", action="store_const", @@ -517,6 +615,9 @@ def Options(): help="The input file is include path list to search for ASL include file"), make_option("-o", "--output", dest="OutputFile", help="File to store the trimmed content"), + make_option("--ModuleName", dest="ModuleName", help="The module's BASE_NAME"), + make_option("--DebugDir", dest="DebugDir", + help="Debug Output directory to store the output files"), make_option("-v", "--verbose", dest="LogLevel", action="store_const", const=EdkLogger.VERBOSE, help="Run verbosely"), make_option("-d", "--debug", dest="LogLevel", type="int", @@ -527,7 +628,7 @@ def Options(): ] # use clearer usage to override default usage message - UsageString = "%prog [-s|-r|-a] [-c] [-v|-d |-q] [-i ] [-o ] " + UsageString = "%prog [-s|-r|-a|--Vfr-Uni-Offset] [-c] [-v|-d |-q] [-i ] [-o ] [--ModuleName ] [--DebugDir ] []" Parser = OptionParser(description=__copyright__, version=__version__, option_list=OptionList, usage=UsageString) Parser.set_defaults(FileType="Vfr") @@ -537,6 +638,11 @@ def Options(): Options, Args = Parser.parse_args() # error check + if Options.FileType == 'VfrOffsetBin': + if len(Args) == 0: + return Options, '' + elif len(Args) > 1: + EdkLogger.error("Trim", OPTION_NOT_SUPPORTED, ExtraData=Parser.get_usage()) if len(Args) == 0: EdkLogger.error("Trim", OPTION_MISSING, ExtraData=Parser.get_usage()) if len(Args) > 1: @@ -562,28 +668,30 @@ def Main(): EdkLogger.SetLevel(CommandOptions.LogLevel + 1) else: EdkLogger.SetLevel(CommandOptions.LogLevel) - except FatalError, X: + except FatalError as X: return 1 try: if CommandOptions.FileType == "Vfr": - if CommandOptions.OutputFile == None: + if CommandOptions.OutputFile is None: CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii' TrimPreprocessedVfr(InputFile, CommandOptions.OutputFile) elif CommandOptions.FileType == "Asl": - if CommandOptions.OutputFile == None: + if CommandOptions.OutputFile is None: CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii' TrimAslFile(InputFile, CommandOptions.OutputFile, CommandOptions.IncludePathFile) elif CommandOptions.FileType == "EdkSourceCode": TrimEdkSources(InputFile, CommandOptions.OutputFile) + elif CommandOptions.FileType == "VfrOffsetBin": + GenerateVfrBinSec(CommandOptions.ModuleName, CommandOptions.DebugDir, CommandOptions.OutputFile) else : - if CommandOptions.OutputFile == None: + if CommandOptions.OutputFile is None: CommandOptions.OutputFile = os.path.splitext(InputFile)[0] + '.iii' TrimPreprocessedFile(InputFile, CommandOptions.OutputFile, CommandOptions.ConvertHex, CommandOptions.TrimLong) - except FatalError, X: + except FatalError as X: import platform import traceback - if CommandOptions != None and CommandOptions.LogLevel <= EdkLogger.DEBUG_9: + if CommandOptions is not None and CommandOptions.LogLevel <= EdkLogger.DEBUG_9: EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc()) return 1 except: @@ -593,7 +701,7 @@ def Main(): "\nTrim", CODE_ERROR, "Unknown fatal error when trimming [%s]" % InputFile, - ExtraData="\n(Please send email to edk2-buildtools-devel@lists.sourceforge.net for help, attaching following call stack trace!)\n", + ExtraData="\n(Please send email to edk2-devel@lists.01.org for help, attaching following call stack trace!)\n", RaiseError=False ) EdkLogger.quiet("(Python %s on %s) " % (platform.python_version(), sys.platform) + traceback.format_exc())