2014-01-27 06:23:15 +01:00
## @file
# Trim files preprocessed by compiler
#
2018-04-10 03:12:49 +02:00
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
2019-04-04 01:03:11 +02:00
# SPDX-License-Identifier: BSD-2-Clause-Patent
2014-01-27 06:23:15 +01:00
#
##
# Import Modules
#
2014-08-15 05:06:48 +02:00
import Common . LongFilePathOs as os
2014-01-27 06:23:15 +01:00
import sys
import re
2018-06-25 12:31:36 +02:00
from io import BytesIO
2019-03-28 03:12:31 +01:00
import codecs
2014-01-27 06:23:15 +01:00
from optparse import OptionParser
from optparse import make_option
from Common . BuildToolError import *
from Common . Misc import *
2018-04-26 18:57:56 +02:00
from Common . DataType import *
2014-01-27 06:23:15 +01:00
from Common . BuildVersion import gBUILD_VERSION
import Common . EdkLogger as EdkLogger
2014-08-15 05:06:48 +02:00
from Common . LongFilePathSupport import OpenLongFilePath as open
2014-01-27 06:23:15 +01:00
# Version and Copyright
__version_number__ = ( " 0.10 " + " " + gBUILD_VERSION )
__version__ = " % prog Version " + __version_number__
2018-07-05 11:40:04 +02:00
__copyright__ = " Copyright (c) 2007-2018, Intel Corporation. All rights reserved. "
2014-01-27 06:23:15 +01:00
## Regular expression for matching Line Control directive like "#line xxx"
gLineControlDirective = re . compile ( ' ^ \ s*#(?:line)? \ s+([0-9]+) \ s+ " *([^ " ]*) " ' )
## Regular expression for matching "typedef struct"
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 )
2016-02-17 07:58:02 +01:00
## 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 )
2014-01-27 06:23:15 +01:00
#
# The following number pattern match will only match if following criteria is met:
# There is leading non-(alphanumeric or _) character, and no following alphanumeric or _
# as the pattern is greedily match, so it is ok for the gDecNumberPattern or gHexNumberPattern to grab the maximum match
#
## Regular expression for matching HEX number
gHexNumberPattern = re . compile ( " (?<=[^a-zA-Z0-9_])(0[xX])([0-9a-fA-F]+)(U(?=$|[^a-zA-Z0-9_]))? " )
## Regular expression for matching decimal number with 'U' postfix
gDecNumberPattern = re . compile ( " (?<=[^a-zA-Z0-9_])([0-9]+)U(?=$|[^a-zA-Z0-9_]) " )
## Regular expression for matching constant with 'ULL' 'LL' postfix
gLongNumberPattern = re . compile ( " (?<=[^a-zA-Z0-9_])(0[xX][0-9a-fA-F]+|[0-9]+)U?LL(?=$|[^a-zA-Z0-9_]) " )
## Regular expression for matching "Include ()" in asl file
gAslIncludePattern = re . compile ( " ^( \ s*)[iI]nclude \ s* \ ( \" ?([^ \" \ ( \ )]+) \" \ ) " , re . MULTILINE )
## Regular expression for matching C style #include "XXX.asl" in asl file
gAslCIncludePattern = re . compile ( r ' ^( \ s*)#include \ s*[< " ] \ s*([- \\ / \ w.]+) \ s*([> " ]) ' , re . MULTILINE )
## Patterns used to convert EDK conventions to EDK2 ECP conventions
2019-11-20 03:58:28 +01:00
## Regular expression for finding header file inclusions
gIncludePattern = re . compile ( r " ^[ \ t]*[ % ]?[ \ t]*include(?:[ \ t]*(?: \\ (?: \ r \ n| \ r| \ n))*[ \ t]*)*(?: \ (?[ \" <]?[ \ t]*)([- \ w. \\ /() \ t]+)(?:[ \ t]*[ \" >]? \ )?) " , re . MULTILINE | re . UNICODE | re . IGNORECASE )
2014-01-27 06:23:15 +01:00
## file cache to avoid circular include in ASL file
gIncludedAslFile = [ ]
## Trim preprocessed source code
#
# Remove extra content made by preprocessor. The preprocessor must enable the
# line number generation option when preprocessing.
#
# @param Source File to be trimmed
# @param Target File to store the trimmed content
# @param Convert If True, convert standard HEX format to MASM format
#
def TrimPreprocessedFile ( Source , Target , ConvertHex , TrimLong ) :
CreateDirectory ( os . path . dirname ( Target ) )
try :
2019-03-28 03:12:31 +01:00
with open ( Source , " r " ) as File :
Lines = File . readlines ( )
2019-07-16 11:26:55 +02:00
except IOError :
2014-01-27 06:23:15 +01:00
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , ExtraData = Source )
2019-08-01 15:23:43 +02:00
except :
2019-07-16 11:26:55 +02:00
EdkLogger . error ( " Trim " , AUTOGEN_ERROR , " TrimPreprocessedFile: Error while processing file " , File = Source )
2014-01-27 06:23:15 +01:00
PreprocessedFile = " "
InjectedFile = " "
LineIndexOfOriginalFile = None
NewLines = [ ]
LineControlDirectiveFound = False
for Index in range ( len ( Lines ) ) :
Line = Lines [ Index ]
#
# Find out the name of files injected by preprocessor from the lines
# with Line Control directive
#
MatchList = gLineControlDirective . findall ( Line )
if MatchList != [ ] :
MatchList = MatchList [ 0 ]
if len ( MatchList ) == 2 :
LineNumber = int ( MatchList [ 0 ] , 0 )
InjectedFile = MatchList [ 1 ]
2018-06-28 21:31:21 +02:00
InjectedFile = os . path . normpath ( InjectedFile )
InjectedFile = os . path . normcase ( InjectedFile )
2019-02-06 08:44:39 +01:00
# The first injected file must be the preprocessed file itself
2014-01-27 06:23:15 +01:00
if PreprocessedFile == " " :
PreprocessedFile = InjectedFile
LineControlDirectiveFound = True
continue
elif PreprocessedFile == " " or InjectedFile != PreprocessedFile :
continue
2018-03-26 22:25:43 +02:00
if LineIndexOfOriginalFile is None :
2014-01-27 06:23:15 +01:00
#
# Any non-empty lines must be from original preprocessed file.
# And this must be the first one.
#
LineIndexOfOriginalFile = Index
EdkLogger . verbose ( " Found original file content starting from line %d "
% ( LineIndexOfOriginalFile + 1 ) )
2015-08-06 10:05:59 +02:00
if TrimLong :
Line = gLongNumberPattern . sub ( r " \ 1 " , Line )
2014-01-27 06:23:15 +01:00
# convert HEX number format if indicated
if ConvertHex :
Line = gHexNumberPattern . sub ( r " 0 \ 2h " , Line )
else :
Line = gHexNumberPattern . sub ( r " \ 1 \ 2 " , Line )
# convert Decimal number format
Line = gDecNumberPattern . sub ( r " \ 1 " , Line )
2018-03-26 22:25:43 +02:00
if LineNumber is not None :
2014-01-27 06:23:15 +01:00
EdkLogger . verbose ( " Got line directive: line= %d " % LineNumber )
# in case preprocessor removed some lines, like blank or comment lines
if LineNumber < = len ( NewLines ) :
# possible?
NewLines [ LineNumber - 1 ] = Line
else :
if LineNumber > ( len ( NewLines ) + 1 ) :
for LineIndex in range ( len ( NewLines ) , LineNumber - 1 ) :
2019-01-11 06:04:44 +01:00
NewLines . append ( TAB_LINE_BREAK )
2014-01-27 06:23:15 +01:00
NewLines . append ( Line )
LineNumber = None
EdkLogger . verbose ( " Now we have lines: %d " % len ( NewLines ) )
else :
NewLines . append ( Line )
# in case there's no line directive or linemarker found
if ( not LineControlDirectiveFound ) and NewLines == [ ] :
2016-02-17 07:58:02 +01:00
MulPatternFlag = False
SinglePatternFlag = False
Brace = 0
for Index in range ( len ( Lines ) ) :
Line = Lines [ Index ]
2018-03-26 22:25:43 +02:00
if MulPatternFlag == False and gTypedef_MulPattern . search ( Line ) is None :
if SinglePatternFlag == False and gTypedef_SinglePattern . search ( Line ) is None :
2016-02-17 07:58:02 +01:00
# remove "#pragram pack" directive
2018-03-26 22:25:43 +02:00
if gPragmaPattern . search ( Line ) is None :
2016-02-17 07:58:02 +01:00
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
2014-01-27 06:23:15 +01:00
# save to file
try :
2019-03-28 03:12:31 +01:00
with open ( Target , ' w ' ) as File :
File . writelines ( NewLines )
2014-01-27 06:23:15 +01:00
except :
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , ExtraData = Target )
## Trim preprocessed VFR file
#
# Remove extra content made by preprocessor. The preprocessor doesn't need to
# enable line number generation option when preprocessing.
#
# @param Source File to be trimmed
# @param Target File to store the trimmed content
#
def TrimPreprocessedVfr ( Source , Target ) :
CreateDirectory ( os . path . dirname ( Target ) )
2018-07-05 11:40:04 +02:00
2014-01-27 06:23:15 +01:00
try :
2019-03-28 03:12:31 +01:00
with open ( Source , " r " ) as File :
Lines = File . readlines ( )
2014-01-27 06:23:15 +01:00
except :
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , ExtraData = Source )
# read whole file
FoundTypedef = False
Brace = 0
TypedefStart = 0
TypedefEnd = 0
for Index in range ( len ( Lines ) ) :
Line = Lines [ Index ]
# don't trim the lines from "formset" definition to the end of file
if Line . strip ( ) == ' formset ' :
break
if FoundTypedef == False and ( Line . find ( ' #line ' ) == 0 or Line . find ( ' # ' ) == 0 ) :
# empty the line number directive if it's not aomong "typedef struct"
Lines [ Index ] = " \n "
continue
2018-03-26 22:25:43 +02:00
if FoundTypedef == False and gTypedefPattern . search ( Line ) is None :
2014-01-27 06:23:15 +01:00
# keep "#pragram pack" directive
2018-03-26 22:25:43 +02:00
if gPragmaPattern . search ( Line ) is None :
2014-01-27 06:23:15 +01:00
Lines [ Index ] = " \n "
continue
elif FoundTypedef == False :
# found "typedef struct", keept its position and set a flag
FoundTypedef = True
TypedefStart = Index
# match { and } to find the end of typedef definition
if Line . find ( " { " ) > = 0 :
Brace + = 1
elif Line . find ( " } " ) > = 0 :
Brace - = 1
# "typedef struct" must end with a ";"
if Brace == 0 and Line . find ( " ; " ) > = 0 :
FoundTypedef = False
TypedefEnd = Index
# keep all "typedef struct" except to GUID, EFI_PLABEL and PAL_CALL_RETURN
2018-04-26 18:57:56 +02:00
if Line . strip ( " } ; \r \n " ) in [ TAB_GUID , " EFI_PLABEL " , " PAL_CALL_RETURN " ] :
2014-01-27 06:23:15 +01:00
for i in range ( TypedefStart , TypedefEnd + 1 ) :
Lines [ i ] = " \n "
# save all lines trimmed
try :
2019-03-28 03:12:31 +01:00
with open ( Target , ' w ' ) as File :
File . writelines ( Lines )
2014-01-27 06:23:15 +01:00
except :
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , ExtraData = Target )
## Read the content ASL file, including ASL included, recursively
#
# @param Source File to be read
# @param Indent Spaces before the Include() statement
# @param IncludePathList The list of external include file
# @param LocalSearchPath If LocalSearchPath is specified, this path will be searched
# first for the included file; otherwise, only the path specified
# in the IncludePathList will be searched.
#
2019-11-20 03:58:28 +01:00
def DoInclude ( Source , Indent = ' ' , IncludePathList = [ ] , LocalSearchPath = None , IncludeFileList = None , filetype = None ) :
2014-01-27 06:23:15 +01:00
NewFileContent = [ ]
2019-11-20 03:58:28 +01:00
if IncludeFileList is None :
IncludeFileList = [ ]
2014-01-27 06:23:15 +01:00
try :
#
# Search LocalSearchPath first if it is specified.
#
if LocalSearchPath :
SearchPathList = [ LocalSearchPath ] + IncludePathList
else :
SearchPathList = IncludePathList
2018-07-05 11:40:04 +02:00
2014-01-27 06:23:15 +01:00
for IncludePath in SearchPathList :
IncludeFile = os . path . join ( IncludePath , Source )
if os . path . isfile ( IncludeFile ) :
2019-03-28 03:12:31 +01:00
try :
with open ( IncludeFile , " r " ) as File :
F = File . readlines ( )
except :
with codecs . open ( IncludeFile , " r " , encoding = ' utf-8 ' ) as File :
F = File . readlines ( )
2014-01-27 06:23:15 +01:00
break
else :
2020-06-01 08:40:10 +02:00
EdkLogger . warn ( " Trim " , " Failed to find include file %s " % Source )
return [ ]
2014-01-27 06:23:15 +01:00
except :
2020-06-01 08:40:10 +02:00
EdkLogger . warn ( " Trim " , FILE_OPEN_FAILURE , ExtraData = Source )
return [ ]
2014-01-27 06:23:15 +01:00
2018-07-05 11:40:04 +02:00
2014-01-27 06:23:15 +01:00
# avoid A "include" B and B "include" A
IncludeFile = os . path . abspath ( os . path . normpath ( IncludeFile ) )
if IncludeFile in gIncludedAslFile :
EdkLogger . warn ( " Trim " , " Circular include " ,
ExtraData = " %s -> %s " % ( " -> " . join ( gIncludedAslFile ) , IncludeFile ) )
return [ ]
gIncludedAslFile . append ( IncludeFile )
2019-11-20 03:58:28 +01:00
IncludeFileList . append ( IncludeFile . strip ( ) )
2014-01-27 06:23:15 +01:00
for Line in F :
LocalSearchPath = None
2019-11-20 03:58:28 +01:00
if filetype == " ASL " :
Result = gAslIncludePattern . findall ( Line )
if len ( Result ) == 0 :
Result = gAslCIncludePattern . findall ( Line )
if len ( Result ) == 0 or os . path . splitext ( Result [ 0 ] [ 1 ] ) [ 1 ] . lower ( ) not in [ " .asl " , " .asi " ] :
NewFileContent . append ( " %s %s " % ( Indent , Line ) )
continue
#
# We should first search the local directory if current file are using pattern #include "XXX"
#
if Result [ 0 ] [ 2 ] == ' " ' :
LocalSearchPath = os . path . dirname ( IncludeFile )
CurrentIndent = Indent + Result [ 0 ] [ 0 ]
IncludedFile = Result [ 0 ] [ 1 ]
NewFileContent . extend ( DoInclude ( IncludedFile , CurrentIndent , IncludePathList , LocalSearchPath , IncludeFileList , filetype ) )
NewFileContent . append ( " \n " )
elif filetype == " ASM " :
Result = gIncludePattern . findall ( Line )
if len ( Result ) == 0 :
2014-01-27 06:23:15 +01:00
NewFileContent . append ( " %s %s " % ( Indent , Line ) )
continue
2019-11-20 03:58:28 +01:00
IncludedFile = Result [ 0 ]
IncludedFile = IncludedFile . strip ( )
IncludedFile = os . path . normpath ( IncludedFile )
NewFileContent . extend ( DoInclude ( IncludedFile , ' ' , IncludePathList , LocalSearchPath , IncludeFileList , filetype ) )
NewFileContent . append ( " \n " )
2014-01-27 06:23:15 +01:00
gIncludedAslFile . pop ( )
return NewFileContent
## Trim ASL file
#
# Replace ASL include statement with the content the included file
#
# @param Source File to be trimmed
# @param Target File to store the trimmed content
2018-07-05 11:40:04 +02:00
# @param IncludePathFile The file to log the external include path
2014-01-27 06:23:15 +01:00
#
2019-11-20 03:58:28 +01:00
def TrimAslFile ( Source , Target , IncludePathFile , AslDeps = False ) :
2014-01-27 06:23:15 +01:00
CreateDirectory ( os . path . dirname ( Target ) )
2018-07-05 11:40:04 +02:00
2014-01-27 06:23:15 +01:00
SourceDir = os . path . dirname ( Source )
if SourceDir == ' ' :
SourceDir = ' . '
2018-07-05 11:40:04 +02:00
2014-01-27 06:23:15 +01:00
#
# Add source directory as the first search directory
#
IncludePathList = [ SourceDir ]
2018-07-05 11:40:04 +02:00
2014-01-27 06:23:15 +01:00
#
# If additional include path file is specified, append them all
# to the search directory list.
#
if IncludePathFile :
try :
LineNum = 0
2019-03-28 03:12:31 +01:00
with open ( IncludePathFile , ' r ' ) as File :
FileLines = File . readlines ( )
for Line in FileLines :
2014-01-27 06:23:15 +01:00
LineNum + = 1
if Line . startswith ( " /I " ) or Line . startswith ( " -I " ) :
IncludePathList . append ( Line [ 2 : ] . strip ( ) )
else :
EdkLogger . warn ( " Trim " , " Invalid include line in include list file. " , IncludePathFile , LineNum )
except :
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , ExtraData = IncludePathFile )
2019-11-20 03:58:28 +01:00
AslIncludes = [ ]
Lines = DoInclude ( Source , ' ' , IncludePathList , IncludeFileList = AslIncludes , filetype = ' ASL ' )
AslIncludes = [ item for item in AslIncludes if item != Source ]
2020-11-09 03:51:21 +01:00
SaveFileOnChange ( os . path . join ( os . path . dirname ( Target ) , os . path . basename ( Source ) ) + " .trim.deps " , " \\ \n " . join ( [ Source + " : " ] + AslIncludes ) , False )
2014-01-27 06:23:15 +01:00
#
# Undef MIN and MAX to avoid collision in ASL source code
#
Lines . insert ( 0 , " #undef MIN \n #undef MAX \n " )
# save all lines trimmed
try :
2019-03-28 03:12:31 +01:00
with open ( Target , ' w ' ) as File :
File . writelines ( Lines )
2014-01-27 06:23:15 +01:00
except :
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , ExtraData = Target )
2019-11-20 03:58:28 +01:00
## Trim ASM file
#
# Output ASM include statement with the content the included file
#
# @param Source File to be trimmed
# @param Target File to store the trimmed content
# @param IncludePathFile The file to log the external include path
#
def TrimAsmFile ( Source , Target , IncludePathFile ) :
CreateDirectory ( os . path . dirname ( Target ) )
SourceDir = os . path . dirname ( Source )
if SourceDir == ' ' :
SourceDir = ' . '
#
# Add source directory as the first search directory
#
IncludePathList = [ SourceDir ]
#
# If additional include path file is specified, append them all
# to the search directory list.
#
if IncludePathFile :
try :
LineNum = 0
with open ( IncludePathFile , ' r ' ) as File :
FileLines = File . readlines ( )
for Line in FileLines :
LineNum + = 1
if Line . startswith ( " /I " ) or Line . startswith ( " -I " ) :
IncludePathList . append ( Line [ 2 : ] . strip ( ) )
else :
EdkLogger . warn ( " Trim " , " Invalid include line in include list file. " , IncludePathFile , LineNum )
except :
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , ExtraData = IncludePathFile )
AsmIncludes = [ ]
Lines = DoInclude ( Source , ' ' , IncludePathList , IncludeFileList = AsmIncludes , filetype = ' ASM ' )
AsmIncludes = [ item for item in AsmIncludes if item != Source ]
if AsmIncludes :
SaveFileOnChange ( os . path . join ( os . path . dirname ( Target ) , os . path . basename ( Source ) ) + " .trim.deps " , " \\ \n " . join ( [ Source + " : " ] + AsmIncludes ) , False )
# save all lines trimmed
try :
with open ( Target , ' w ' ) as File :
File . writelines ( Lines )
except :
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , ExtraData = Target )
2017-09-29 01:54:12 +02:00
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 )
2018-04-10 03:12:49 +02:00
if Ext == ' .c ' and Name != ' AutoGen ' :
2017-09-29 01:54:12 +02:00
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 :
2019-03-28 03:12:31 +01:00
fInputfile = open ( OutputFile , " wb+ " )
2017-09-29 01:54:12 +02:00
except :
EdkLogger . error ( " Trim " , FILE_OPEN_FAILURE , " File open failed for %s " % OutputFile , None )
2018-06-25 12:31:36 +02:00
# Use a instance of BytesIO to cache data
2019-01-23 03:16:00 +01:00
fStringIO = BytesIO ( )
2017-09-29 01:54:12 +02:00
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 } }
#
2019-01-23 03:16:00 +01:00
UniGuid = b ' \xe0 \xc5 \x13 \x89 \xf6 3 \x86 M \x9b \xf1 C \xef \x89 \xfc \x06 f '
fStringIO . write ( UniGuid )
2017-09-29 01:54:12 +02:00
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 } };
#
2019-01-23 03:16:00 +01:00
VfrGuid = b ' \xb4 | \xbc \xd0 Gj_I \xaa \x11 q \x07 F \xda \x06 \xa2 '
fStringIO . write ( VfrGuid )
2018-10-15 02:27:53 +02:00
type ( Item [ 1 ] )
2017-09-29 01:54:12 +02:00
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 ( )
2014-01-27 06:23:15 +01:00
## Parse command line options
#
# Using standard Python module optparse to parse command line option of this tool.
#
# @retval Options A optparse.Values object containing the parsed options
# @retval InputFile Path of file to be trimmed
#
def Options ( ) :
OptionList = [
make_option ( " -s " , " --source-code " , dest = " FileType " , const = " SourceCode " , action = " store_const " ,
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 " ) ,
2017-09-29 01:54:12 +02:00
make_option ( " --Vfr-Uni-Offset " , dest = " FileType " , const = " VfrOffsetBin " , action = " store_const " ,
help = " The input file is EFI image " ) ,
2019-11-20 03:58:28 +01:00
make_option ( " --asl-deps " , dest = " AslDeps " , const = " True " , action = " store_const " ,
help = " Generate Asl dependent files. " ) ,
2014-01-27 06:23:15 +01:00
make_option ( " -a " , " --asl-file " , dest = " FileType " , const = " Asl " , action = " store_const " ,
help = " The input file is ASL file " ) ,
2019-11-20 03:58:28 +01:00
make_option ( " --asm-file " , dest = " FileType " , const = " Asm " , action = " store_const " ,
help = " The input file is asm file " ) ,
2014-01-27 06:23:15 +01:00
make_option ( " -c " , " --convert-hex " , dest = " ConvertHex " , action = " store_true " ,
help = " Convert standard hex format (0xabcd) to MASM format (abcdh) " ) ,
make_option ( " -l " , " --trim-long " , dest = " TrimLong " , action = " store_true " ,
help = " Remove postfix of long number " ) ,
make_option ( " -i " , " --include-path-file " , dest = " IncludePathFile " ,
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 " ) ,
2017-09-29 01:54:12 +02:00
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 " ) ,
2014-01-27 06:23:15 +01:00
make_option ( " -v " , " --verbose " , dest = " LogLevel " , action = " store_const " , const = EdkLogger . VERBOSE ,
help = " Run verbosely " ) ,
make_option ( " -d " , " --debug " , dest = " LogLevel " , type = " int " ,
help = " Run with debug information " ) ,
make_option ( " -q " , " --quiet " , dest = " LogLevel " , action = " store_const " , const = EdkLogger . QUIET ,
help = " Run quietly " ) ,
make_option ( " -? " , action = " help " , help = " show this help message and exit " ) ,
]
# use clearer usage to override default usage message
2017-09-29 01:54:12 +02:00
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>] "
2014-01-27 06:23:15 +01:00
Parser = OptionParser ( description = __copyright__ , version = __version__ , option_list = OptionList , usage = UsageString )
Parser . set_defaults ( FileType = " Vfr " )
Parser . set_defaults ( ConvertHex = False )
Parser . set_defaults ( LogLevel = EdkLogger . INFO )
Options , Args = Parser . parse_args ( )
# error check
2017-09-29 01:54:12 +02:00
if Options . FileType == ' VfrOffsetBin ' :
if len ( Args ) == 0 :
return Options , ' '
elif len ( Args ) > 1 :
EdkLogger . error ( " Trim " , OPTION_NOT_SUPPORTED , ExtraData = Parser . get_usage ( ) )
2014-01-27 06:23:15 +01:00
if len ( Args ) == 0 :
EdkLogger . error ( " Trim " , OPTION_MISSING , ExtraData = Parser . get_usage ( ) )
if len ( Args ) > 1 :
EdkLogger . error ( " Trim " , OPTION_NOT_SUPPORTED , ExtraData = Parser . get_usage ( ) )
InputFile = Args [ 0 ]
return Options , InputFile
## Entrance method
#
# This method mainly dispatch specific methods per the command line options.
# If no error found, return zero value so the caller of this tool can know
# if it's executed successfully or not.
#
# @retval 0 Tool was successful
# @retval 1 Tool failed
#
def Main ( ) :
try :
EdkLogger . Initialize ( )
CommandOptions , InputFile = Options ( )
if CommandOptions . LogLevel < EdkLogger . DEBUG_9 :
EdkLogger . SetLevel ( CommandOptions . LogLevel + 1 )
else :
EdkLogger . SetLevel ( CommandOptions . LogLevel )
2018-06-25 12:31:25 +02:00
except FatalError as X :
2014-01-27 06:23:15 +01:00
return 1
2018-07-05 11:40:04 +02:00
2014-01-27 06:23:15 +01:00
try :
if CommandOptions . FileType == " Vfr " :
2018-03-26 22:25:43 +02:00
if CommandOptions . OutputFile is None :
2014-01-27 06:23:15 +01:00
CommandOptions . OutputFile = os . path . splitext ( InputFile ) [ 0 ] + ' .iii '
TrimPreprocessedVfr ( InputFile , CommandOptions . OutputFile )
elif CommandOptions . FileType == " Asl " :
2018-03-26 22:25:43 +02:00
if CommandOptions . OutputFile is None :
2014-01-27 06:23:15 +01:00
CommandOptions . OutputFile = os . path . splitext ( InputFile ) [ 0 ] + ' .iii '
2019-11-20 03:58:28 +01:00
TrimAslFile ( InputFile , CommandOptions . OutputFile , CommandOptions . IncludePathFile , CommandOptions . AslDeps )
2017-09-29 01:54:12 +02:00
elif CommandOptions . FileType == " VfrOffsetBin " :
GenerateVfrBinSec ( CommandOptions . ModuleName , CommandOptions . DebugDir , CommandOptions . OutputFile )
2019-11-20 03:58:28 +01:00
elif CommandOptions . FileType == " Asm " :
TrimAsmFile ( InputFile , CommandOptions . OutputFile , CommandOptions . IncludePathFile )
2014-01-27 06:23:15 +01:00
else :
2018-03-26 22:25:43 +02:00
if CommandOptions . OutputFile is None :
2014-01-27 06:23:15 +01:00
CommandOptions . OutputFile = os . path . splitext ( InputFile ) [ 0 ] + ' .iii '
TrimPreprocessedFile ( InputFile , CommandOptions . OutputFile , CommandOptions . ConvertHex , CommandOptions . TrimLong )
2018-06-25 12:31:25 +02:00
except FatalError as X :
2014-01-27 06:23:15 +01:00
import platform
import traceback
2018-03-26 22:25:43 +02:00
if CommandOptions is not None and CommandOptions . LogLevel < = EdkLogger . DEBUG_9 :
2014-01-27 06:23:15 +01:00
EdkLogger . quiet ( " (Python %s on %s ) " % ( platform . python_version ( ) , sys . platform ) + traceback . format_exc ( ) )
return 1
except :
import traceback
import platform
EdkLogger . error (
" \n Trim " ,
CODE_ERROR ,
" Unknown fatal error when trimming [ %s ] " % InputFile ,
2019-05-21 04:06:52 +02:00
ExtraData = " \n (Please send email to %s for help, attaching following call stack trace!) \n " % MSG_EDKII_MAIL_ADDR ,
2014-01-27 06:23:15 +01:00
RaiseError = False
)
EdkLogger . quiet ( " (Python %s on %s ) " % ( platform . python_version ( ) , sys . platform ) + traceback . format_exc ( ) )
return 1
return 0
if __name__ == ' __main__ ' :
r = Main ( )
## 0-127 is a safe return range, and 1 is a standard default error
if r < 0 or r > 127 : r = 1
sys . exit ( r )