summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser')
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py1091
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py364
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py283
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py226
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py212
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py191
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py98
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py368
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py197
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py134
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py680
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py216
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py178
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py493
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py139
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/__init__.py14
16 files changed, 4884 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py
new file mode 100755
index 00000000..f6b8545b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParser.py
@@ -0,0 +1,1091 @@
+## @file
+# This file is used to parse DEC file. It will consumed by DecParser
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+'''
+DecParser
+'''
+## Import modules
+#
+import Logger.Log as Logger
+from Logger.ToolError import FILE_PARSE_FAILURE
+from Logger.ToolError import FILE_OPEN_FAILURE
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+
+import Library.DataType as DT
+from Library.ParserValidate import IsValidToken
+from Library.ParserValidate import IsValidPath
+from Library.ParserValidate import IsValidCFormatGuid
+from Library.ParserValidate import IsValidIdString
+from Library.ParserValidate import IsValidUserId
+from Library.ParserValidate import IsValidArch
+from Library.ParserValidate import IsValidWord
+from Library.ParserValidate import IsValidDecVersionVal
+from Parser.DecParserMisc import TOOL_NAME
+from Parser.DecParserMisc import CleanString
+from Parser.DecParserMisc import IsValidPcdDatum
+from Parser.DecParserMisc import ParserHelper
+from Parser.DecParserMisc import StripRoot
+from Parser.DecParserMisc import VERSION_PATTERN
+from Parser.DecParserMisc import CVAR_PATTERN
+from Parser.DecParserMisc import PCD_TOKEN_PATTERN
+from Parser.DecParserMisc import MACRO_PATTERN
+from Parser.DecParserMisc import FileContent
+from Object.Parser.DecObject import _DecComments
+from Object.Parser.DecObject import DecDefineObject
+from Object.Parser.DecObject import DecDefineItemObject
+from Object.Parser.DecObject import DecIncludeObject
+from Object.Parser.DecObject import DecIncludeItemObject
+from Object.Parser.DecObject import DecLibraryclassObject
+from Object.Parser.DecObject import DecLibraryclassItemObject
+from Object.Parser.DecObject import DecGuidObject
+from Object.Parser.DecObject import DecPpiObject
+from Object.Parser.DecObject import DecProtocolObject
+from Object.Parser.DecObject import DecGuidItemObject
+from Object.Parser.DecObject import DecUserExtensionObject
+from Object.Parser.DecObject import DecUserExtensionItemObject
+from Object.Parser.DecObject import DecPcdObject
+from Object.Parser.DecObject import DecPcdItemObject
+from Library.Misc import GuidStructureStringToGuidString
+from Library.Misc import CheckGuidRegFormat
+from Library.StringUtils import ReplaceMacro
+from Library.StringUtils import GetSplitValueList
+from Library.StringUtils import gMACRO_PATTERN
+from Library.StringUtils import ConvertSpecialChar
+from Library.CommentParsing import ParsePcdErrorCode
+
+##
+# _DecBase class for parsing
+#
+class _DecBase:
+ def __init__(self, RawData):
+ self._RawData = RawData
+ self._ItemDict = {}
+ self._LocalMacro = {}
+ #
+ # Data parsed by 'self' are saved to this object
+ #
+ self.ItemObject = None
+
+ def GetDataObject(self):
+ return self.ItemObject
+
+ def GetLocalMacro(self):
+ return self._LocalMacro
+
+ ## BlockStart
+ #
+ # Called if a new section starts
+ #
+ def BlockStart(self):
+ self._LocalMacro = {}
+
+ ## _CheckReDefine
+ #
+ # @param Key: to be checked if multi-defined
+ # @param Scope: Format: [[SectionName, Arch], ...].
+ # If scope is none, use global scope
+ #
+ def _CheckReDefine(self, Key, Scope = None):
+ if not Scope:
+ Scope = self._RawData.CurrentScope
+ return
+
+ SecArch = []
+ #
+ # Copy scope to SecArch, avoid Scope be changed outside
+ #
+ SecArch[0:1] = Scope[:]
+ if Key not in self._ItemDict:
+ self._ItemDict[Key] = [[SecArch, self._RawData.LineIndex]]
+ return
+
+ for Value in self._ItemDict[Key]:
+ for SubValue in Scope:
+ #
+ # If current is common section
+ #
+ if SubValue[-1] == 'COMMON':
+ for Other in Value[0]:
+ # Key in common cannot be redefined in other arches
+ # [:-1] means stripping arch info
+ if Other[:-1] == SubValue[:-1]:
+ self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1]))
+ return
+ continue
+ CommonScope = []
+ CommonScope[0:1] = SubValue
+ CommonScope[-1] = 'COMMON'
+ #
+ # Cannot be redefined if this key already defined in COMMON Or defined in same arch
+ #
+ if SubValue in Value[0] or CommonScope in Value[0]:
+ self._LoggerError(ST.ERR_DECPARSE_REDEFINE % (Key, Value[1]))
+ return
+ self._ItemDict[Key].append([SecArch, self._RawData.LineIndex])
+
+ ## CheckRequiredFields
+ # Some sections need to check if some fields exist, define section for example
+ # Derived class can re-implement, top parser will call this function after all parsing done
+ #
+ def CheckRequiredFields(self):
+ if self._RawData:
+ pass
+ return True
+
+ ## IsItemRequired
+ # In DEC spec, sections must have at least one statement except user
+ # extension.
+ # For example: "[guids" [<attribs>] "]" <EOL> <statements>+
+ # sub class can override this method to indicate if statement is a must.
+ #
+ def _IsStatementRequired(self):
+ if self._RawData:
+ pass
+ return False
+
+ def _LoggerError(self, ErrorString):
+ Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
+ Line = self._RawData.LineIndex,
+ ExtraData=ErrorString + ST.ERR_DECPARSE_LINE % self._RawData.CurrentLine)
+
+ def _ReplaceMacro(self, String):
+ if gMACRO_PATTERN.findall(String):
+ String = ReplaceMacro(String, self._LocalMacro, False,
+ FileName = self._RawData.Filename,
+ Line = ['', self._RawData.LineIndex])
+ String = ReplaceMacro(String, self._RawData.Macros, False,
+ FileName = self._RawData.Filename,
+ Line = ['', self._RawData.LineIndex])
+ MacroUsed = gMACRO_PATTERN.findall(String)
+ if MacroUsed:
+ Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE,
+ File=self._RawData.Filename,
+ Line = self._RawData.LineIndex,
+ ExtraData = ST.ERR_DECPARSE_MACRO_RESOLVE % (str(MacroUsed), String))
+ return String
+
+ def _MacroParser(self, String):
+ TokenList = GetSplitValueList(String, ' ', 1)
+ if len(TokenList) < 2 or TokenList[1] == '':
+ self._LoggerError(ST.ERR_DECPARSE_MACRO_PAIR)
+
+ TokenList = GetSplitValueList(TokenList[1], DT.TAB_EQUAL_SPLIT, 1)
+ if TokenList[0] == '':
+ self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME)
+ elif not IsValidToken(MACRO_PATTERN, TokenList[0]):
+ self._LoggerError(ST.ERR_DECPARSE_MACRO_NAME_UPPER % TokenList[0])
+
+ if len(TokenList) == 1:
+ self._LocalMacro[TokenList[0]] = ''
+ else:
+ self._LocalMacro[TokenList[0]] = self._ReplaceMacro(TokenList[1])
+
+ ## _ParseItem
+ #
+ # Parse specified item, this function must be derived by subclass
+ #
+ def _ParseItem(self):
+ if self._RawData:
+ pass
+ #
+ # Should never be called
+ #
+ return None
+
+
+ ## _TailCommentStrategy
+ #
+ # This function can be derived to parse tail comment
+ # default is it will not consume any lines
+ #
+ # @param Comment: Comment of current line
+ #
+ def _TailCommentStrategy(self, Comment):
+ if Comment:
+ pass
+ if self._RawData:
+ pass
+ return False
+
+ ## _StopCurrentParsing
+ #
+ # Called in Parse if current parsing should be stopped when encounter some
+ # keyword
+ # Default is section start and end
+ #
+ # @param Line: Current line
+ #
+ def _StopCurrentParsing(self, Line):
+ if self._RawData:
+ pass
+ return Line[0] == DT.TAB_SECTION_START and Line[-1] == DT.TAB_SECTION_END
+
+ ## _TryBackSlash
+ #
+ # Split comment and DEC content, concatenate lines if end of char is '\'
+ #
+ # @param ProcessedLine: ProcessedLine line
+ # @param ProcessedComments: ProcessedComments line
+ #
+ def _TryBackSlash(self, ProcessedLine, ProcessedComments):
+ CatLine = ''
+ Comment = ''
+ Line = ProcessedLine
+ CommentList = ProcessedComments
+ while not self._RawData.IsEndOfFile():
+ if Line == '':
+ self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
+ break
+
+ if Comment:
+ CommentList.append((Comment, self._RawData.LineIndex))
+ if Line[-1] != DT.TAB_SLASH:
+ CatLine += Line
+ break
+ elif len(Line) < 2 or Line[-2] != ' ':
+ self._LoggerError(ST.ERR_DECPARSE_BACKSLASH)
+ else:
+ CatLine += Line[:-1]
+ Line, Comment = CleanString(self._RawData.GetNextLine())
+ #
+ # Reach end of content
+ #
+ if self._RawData.IsEndOfFile():
+ if not CatLine:
+ if ProcessedLine[-1] == DT.TAB_SLASH:
+ self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
+ CatLine = ProcessedLine
+ else:
+ if not Line or Line[-1] == DT.TAB_SLASH:
+ self._LoggerError(ST.ERR_DECPARSE_BACKSLASH_EMPTY)
+ CatLine += Line
+
+ #
+ # All MACRO values defined by the DEFINE statements in any section
+ # (except [Userextensions] sections for Intel) of the INF or DEC file
+ # must be expanded before processing of the file.
+ #
+ __IsReplaceMacro = True
+ Header = self._RawData.CurrentScope[0] if self._RawData.CurrentScope else None
+ if Header and len(Header) > 2:
+ if Header[0].upper() == 'USEREXTENSIONS' and not (Header[1] == 'TianoCore' and Header[2] == '"ExtraFiles"'):
+ __IsReplaceMacro = False
+ if __IsReplaceMacro:
+ self._RawData.CurrentLine = self._ReplaceMacro(CatLine)
+ else:
+ self._RawData.CurrentLine = CatLine
+
+ return CatLine, CommentList
+
+ ## Parse
+ # This is a template method in which other member functions which might
+ # override by sub class are called. It is responsible for reading file
+ # line by line, and call other member functions to parse. This function
+ # should not be re-implement by sub class.
+ #
+ def Parse(self):
+ HeadComments = []
+ TailComments = []
+
+ #======================================================================
+ # CurComments may pointer to HeadComments or TailComments
+ #======================================================================
+ CurComments = HeadComments
+ CurObj = None
+ ItemNum = 0
+ FromBuf = False
+
+ #======================================================================
+ # Used to report error information if empty section found
+ #======================================================================
+ Index = self._RawData.LineIndex
+ LineStr = self._RawData.CurrentLine
+ while not self._RawData.IsEndOfFile() or self._RawData.NextLine:
+ if self._RawData.NextLine:
+ #==============================================================
+ # Have processed line in buffer
+ #==============================================================
+ Line = self._RawData.NextLine
+ HeadComments.extend(self._RawData.HeadComment)
+ TailComments.extend(self._RawData.TailComment)
+ self._RawData.ResetNext()
+ Comment = ''
+ FromBuf = True
+ else:
+ #==============================================================
+ # No line in buffer, read next line
+ #==============================================================
+ Line, Comment = CleanString(self._RawData.GetNextLine())
+ FromBuf = False
+ if Line:
+ if not FromBuf and CurObj and TailComments:
+ #==========================================================
+ # Set tail comments to previous statement if not empty.
+ #==========================================================
+ CurObj.SetTailComment(CurObj.GetTailComment()+TailComments)
+
+ if not FromBuf:
+ del TailComments[:]
+ CurComments = TailComments
+ Comments = []
+ if Comment:
+ Comments = [(Comment, self._RawData.LineIndex)]
+
+ #==============================================================
+ # Try if last char of line has backslash
+ #==============================================================
+ Line, Comments = self._TryBackSlash(Line, Comments)
+ CurComments.extend(Comments)
+
+ #==============================================================
+ # Macro found
+ #==============================================================
+ if Line.startswith('DEFINE '):
+ self._MacroParser(Line)
+ del HeadComments[:]
+ del TailComments[:]
+ CurComments = HeadComments
+ continue
+
+ if self._StopCurrentParsing(Line):
+ #==========================================================
+ # This line does not belong to this parse,
+ # Save it, can be used by next parse
+ #==========================================================
+ self._RawData.SetNext(Line, HeadComments, TailComments)
+ break
+
+ Obj = self._ParseItem()
+ ItemNum += 1
+ if Obj:
+ Obj.SetHeadComment(Obj.GetHeadComment()+HeadComments)
+ Obj.SetTailComment(Obj.GetTailComment()+TailComments)
+ del HeadComments[:]
+ del TailComments[:]
+ CurObj = Obj
+ else:
+ CurObj = None
+ else:
+ if id(CurComments) == id(TailComments):
+ #==========================================================
+ # Check if this comment belongs to tail comment
+ #==========================================================
+ if not self._TailCommentStrategy(Comment):
+ CurComments = HeadComments
+
+ if Comment:
+ CurComments.append(((Comment, self._RawData.LineIndex)))
+ else:
+ del CurComments[:]
+
+ if self._IsStatementRequired() and ItemNum == 0:
+ Logger.Error(
+ TOOL_NAME, FILE_PARSE_FAILURE,
+ File=self._RawData.Filename,
+ Line=Index,
+ ExtraData=ST.ERR_DECPARSE_STATEMENT_EMPTY % LineStr
+ )
+
+## _DecDefine
+# Parse define section
+#
+class _DecDefine(_DecBase):
+ def __init__(self, RawData):
+ _DecBase.__init__(self, RawData)
+ self.ItemObject = DecDefineObject(RawData.Filename)
+ self._LocalMacro = self._RawData.Macros
+ self._DefSecNum = 0
+
+ #
+ # Each field has a function to validate
+ #
+ self.DefineValidation = {
+ DT.TAB_DEC_DEFINES_DEC_SPECIFICATION : self._SetDecSpecification,
+ DT.TAB_DEC_DEFINES_PACKAGE_NAME : self._SetPackageName,
+ DT.TAB_DEC_DEFINES_PACKAGE_GUID : self._SetPackageGuid,
+ DT.TAB_DEC_DEFINES_PACKAGE_VERSION : self._SetPackageVersion,
+ DT.TAB_DEC_DEFINES_PKG_UNI_FILE : self._SetPackageUni,
+ }
+
+ def BlockStart(self):
+ self._DefSecNum += 1
+ if self._DefSecNum > 1:
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_MULTISEC)
+
+ ## CheckRequiredFields
+ #
+ # Check required fields: DEC_SPECIFICATION, PACKAGE_NAME
+ # PACKAGE_GUID, PACKAGE_VERSION
+ #
+ def CheckRequiredFields(self):
+ Ret = False
+ if self.ItemObject.GetPackageSpecification() == '':
+ Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
+ ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION)
+ elif self.ItemObject.GetPackageName() == '':
+ Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
+ ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_NAME)
+ elif self.ItemObject.GetPackageGuid() == '':
+ Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
+ ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_GUID)
+ elif self.ItemObject.GetPackageVersion() == '':
+ Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._RawData.Filename,
+ ExtraData=ST.ERR_DECPARSE_DEFINE_REQUIRED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION)
+ else:
+ Ret = True
+ return Ret
+
+ def _ParseItem(self):
+ Line = self._RawData.CurrentLine
+ TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1)
+ if TokenList[0] == DT.TAB_DEC_DEFINES_PKG_UNI_FILE:
+ self.DefineValidation[TokenList[0]](TokenList[1])
+ elif len(TokenList) < 2:
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_FORMAT)
+ elif TokenList[0] not in self.DefineValidation:
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_UNKNOWKEY % TokenList[0])
+ else:
+ self.DefineValidation[TokenList[0]](TokenList[1])
+
+ DefineItem = DecDefineItemObject()
+ DefineItem.Key = TokenList[0]
+ DefineItem.Value = TokenList[1]
+ self.ItemObject.AddItem(DefineItem, self._RawData.CurrentScope)
+ return DefineItem
+
+ def _SetDecSpecification(self, Token):
+ if self.ItemObject.GetPackageSpecification():
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_DEC_SPECIFICATION)
+ if not IsValidToken('0[xX][0-9a-fA-F]{8}', Token):
+ if not IsValidDecVersionVal(Token):
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_SPEC)
+ self.ItemObject.SetPackageSpecification(Token)
+
+ def _SetPackageName(self, Token):
+ if self.ItemObject.GetPackageName():
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_NAME)
+ if not IsValidWord(Token):
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGNAME)
+ self.ItemObject.SetPackageName(Token)
+
+ def _SetPackageGuid(self, Token):
+ if self.ItemObject.GetPackageGuid():
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_GUID)
+ if not CheckGuidRegFormat(Token):
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID)
+ self.ItemObject.SetPackageGuid(Token)
+
+ def _SetPackageVersion(self, Token):
+ if self.ItemObject.GetPackageVersion():
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PACKAGE_VERSION)
+ if not IsValidToken(VERSION_PATTERN, Token):
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGVERSION)
+ else:
+ if not DT.TAB_SPLIT in Token:
+ Token = Token + '.0'
+ self.ItemObject.SetPackageVersion(Token)
+
+ def _SetPackageUni(self, Token):
+ if self.ItemObject.GetPackageUniFile():
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_DEFINED % DT.TAB_DEC_DEFINES_PKG_UNI_FILE)
+ self.ItemObject.SetPackageUniFile(Token)
+
+## _DecInclude
+#
+# Parse include section
+#
+class _DecInclude(_DecBase):
+ def __init__(self, RawData):
+ _DecBase.__init__(self, RawData)
+ self.ItemObject = DecIncludeObject(RawData.Filename)
+
+ def _ParseItem(self):
+ Line = self._RawData.CurrentLine
+
+ if not IsValidPath(Line, self._RawData.PackagePath):
+ self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Line)
+
+ Item = DecIncludeItemObject(StripRoot(self._RawData.PackagePath, Line), self._RawData.PackagePath)
+ self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
+ return Item
+
+## _DecLibraryclass
+#
+# Parse library class section
+#
+class _DecLibraryclass(_DecBase):
+ def __init__(self, RawData):
+ _DecBase.__init__(self, RawData)
+ self.ItemObject = DecLibraryclassObject(RawData.Filename)
+
+ def _ParseItem(self):
+ Line = self._RawData.CurrentLine
+ TokenList = GetSplitValueList(Line, DT.TAB_VALUE_SPLIT)
+ if len(TokenList) != 2:
+ self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_SPLIT)
+ if TokenList[0] == '' or TokenList[1] == '':
+ self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_EMPTY)
+ if not IsValidToken('[A-Z][0-9A-Za-z]*', TokenList[0]):
+ self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_LIB)
+
+ self._CheckReDefine(TokenList[0])
+
+ Value = TokenList[1]
+ #
+ # Must end with .h
+ #
+ if not Value.endswith('.h'):
+ self._LoggerError(ST.ERR_DECPARSE_LIBCLASS_PATH_EXT)
+
+ #
+ # Path must be existed
+ #
+ if not IsValidPath(Value, self._RawData.PackagePath):
+ self._LoggerError(ST.ERR_DECPARSE_INCLUDE % Value)
+
+ Item = DecLibraryclassItemObject(TokenList[0], StripRoot(self._RawData.PackagePath, Value),
+ self._RawData.PackagePath)
+ self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
+ return Item
+
+## _DecPcd
+#
+# Parse PCD section
+#
+class _DecPcd(_DecBase):
+ def __init__(self, RawData):
+ _DecBase.__init__(self, RawData)
+ self.ItemObject = DecPcdObject(RawData.Filename)
+ #
+ # Used to check duplicate token
+ # Key is token space and token number (integer), value is C name
+ #
+ self.TokenMap = {}
+
+ def _ParseItem(self):
+ Line = self._RawData.CurrentLine
+ TokenList = Line.split(DT.TAB_VALUE_SPLIT)
+ if len(TokenList) < 4:
+ self._LoggerError(ST.ERR_DECPARSE_PCD_SPLIT)
+
+ #
+ # Token space guid C name
+ #
+ PcdName = GetSplitValueList(TokenList[0], DT.TAB_SPLIT)
+ if len(PcdName) != 2 or PcdName[0] == '' or PcdName[1] == '':
+ self._LoggerError(ST.ERR_DECPARSE_PCD_NAME)
+
+ Guid = PcdName[0]
+ if not IsValidToken(CVAR_PATTERN, Guid):
+ self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID)
+
+ #
+ # PCD C name
+ #
+ CName = PcdName[1]
+ if not IsValidToken(CVAR_PATTERN, CName):
+ self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_PCDCNAME)
+
+ self._CheckReDefine(Guid + DT.TAB_SPLIT + CName)
+
+ #
+ # Default value, may be C array, string or number
+ #
+ Data = DT.TAB_VALUE_SPLIT.join(TokenList[1:-2]).strip()
+
+ #
+ # PCD data type
+ #
+ DataType = TokenList[-2].strip()
+ Valid, Cause = IsValidPcdDatum(DataType, Data)
+ if not Valid:
+ self._LoggerError(Cause)
+ PcdType = self._RawData.CurrentScope[0][0]
+ if PcdType == DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() and DataType != 'BOOLEAN':
+ self._LoggerError(ST.ERR_DECPARSE_PCD_FEATUREFLAG)
+ #
+ # Token value is the last element in list.
+ #
+ Token = TokenList[-1].strip()
+ if not IsValidToken(PCD_TOKEN_PATTERN, Token):
+ self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN % Token)
+ elif not Token.startswith('0x') and not Token.startswith('0X'):
+ if int(Token) > 4294967295:
+ self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_INT % Token)
+ Token = '0x%x' % int(Token)
+
+ IntToken = int(Token, 0)
+ if (Guid, IntToken) in self.TokenMap:
+ if self.TokenMap[Guid, IntToken] != CName:
+ self._LoggerError(ST.ERR_DECPARSE_PCD_TOKEN_UNIQUE%(Token))
+ else:
+ self.TokenMap[Guid, IntToken] = CName
+
+ Item = DecPcdItemObject(Guid, CName, Data, DataType, Token)
+ self.ItemObject.AddItem(Item, self._RawData.CurrentScope)
+ return Item
+
+## _DecGuid
+#
+# Parse GUID, PPI, Protocol section
+#
+class _DecGuid(_DecBase):
+ def __init__(self, RawData):
+ _DecBase.__init__(self, RawData)
+ self.GuidObj = DecGuidObject(RawData.Filename)
+ self.PpiObj = DecPpiObject(RawData.Filename)
+ self.ProtocolObj = DecProtocolObject(RawData.Filename)
+ self.ObjectDict = \
+ {
+ DT.TAB_GUIDS.upper() : self.GuidObj,
+ DT.TAB_PPIS.upper() : self.PpiObj,
+ DT.TAB_PROTOCOLS.upper() : self.ProtocolObj
+ }
+
+ def GetDataObject(self):
+ if self._RawData.CurrentScope:
+ return self.ObjectDict[self._RawData.CurrentScope[0][0]]
+ return None
+
+ def GetGuidObject(self):
+ return self.GuidObj
+
+ def GetPpiObject(self):
+ return self.PpiObj
+
+ def GetProtocolObject(self):
+ return self.ProtocolObj
+
+ def _ParseItem(self):
+ Line = self._RawData.CurrentLine
+ TokenList = GetSplitValueList(Line, DT.TAB_EQUAL_SPLIT, 1)
+ if len(TokenList) < 2:
+ self._LoggerError(ST.ERR_DECPARSE_CGUID)
+ if TokenList[0] == '':
+ self._LoggerError(ST.ERR_DECPARSE_CGUID_NAME)
+ if TokenList[1] == '':
+ self._LoggerError(ST.ERR_DECPARSE_CGUID_GUID)
+ if not IsValidToken(CVAR_PATTERN, TokenList[0]):
+ self._LoggerError(ST.ERR_DECPARSE_PCD_CVAR_GUID)
+
+ self._CheckReDefine(TokenList[0])
+
+ if TokenList[1][0] != '{':
+ if not CheckGuidRegFormat(TokenList[1]):
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_PKGGUID)
+ GuidString = TokenList[1]
+ else:
+ #
+ # Convert C format GUID to GUID string and Simple error check
+ #
+ GuidString = GuidStructureStringToGuidString(TokenList[1])
+ if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidString == '':
+ self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT)
+
+ #
+ # Check C format GUID
+ #
+ if not IsValidCFormatGuid(TokenList[1]):
+ self._LoggerError(ST.ERR_DECPARSE_CGUID_GUIDFORMAT)
+
+ Item = DecGuidItemObject(TokenList[0], TokenList[1], GuidString)
+ ItemObject = self.ObjectDict[self._RawData.CurrentScope[0][0]]
+ ItemObject.AddItem(Item, self._RawData.CurrentScope)
+ return Item
+
+## _DecUserExtension
+#
+# Parse user extension section
+#
+class _DecUserExtension(_DecBase):
+ def __init__(self, RawData):
+ _DecBase.__init__(self, RawData)
+ self.ItemObject = DecUserExtensionObject(RawData.Filename)
+ self._Headers = []
+ self._CurItems = []
+
+ def BlockStart(self):
+ self._CurItems = []
+ for Header in self._RawData.CurrentScope:
+ if Header in self._Headers:
+ self._LoggerError(ST.ERR_DECPARSE_UE_DUPLICATE)
+ else:
+ self._Headers.append(Header)
+
+ for Item in self._CurItems:
+ if Item.UserId == Header[1] and Item.IdString == Header[2]:
+ Item.ArchAndModuleType.append(Header[3])
+ break
+ else:
+ Item = DecUserExtensionItemObject()
+ Item.UserId = Header[1]
+ Item.IdString = Header[2]
+ Item.ArchAndModuleType.append(Header[3])
+ self._CurItems.append(Item)
+ self.ItemObject.AddItem(Item, None)
+ self._LocalMacro = {}
+
+ def _ParseItem(self):
+ Line = self._RawData.CurrentLine
+ Item = None
+ for Item in self._CurItems:
+ if Item.UserString:
+ Item.UserString = '\n'.join([Item.UserString, Line])
+ else:
+ Item.UserString = Line
+ return Item
+
+## Dec
+#
+# Top dec parser
+#
+class Dec(_DecBase, _DecComments):
+ def __init__(self, DecFile, Parse = True):
+ try:
+ Content = ConvertSpecialChar(open(DecFile, 'r').readlines())
+ except BaseException:
+ Logger.Error(TOOL_NAME, FILE_OPEN_FAILURE, File=DecFile,
+ ExtraData=ST.ERR_DECPARSE_FILEOPEN % DecFile)
+
+ #
+ # Pre-parser for Private section
+ #
+ self._Private = ''
+ __IsFoundPrivate = False
+ NewContent = []
+ for Line in Content:
+ Line = Line.strip()
+ if Line.startswith(DT.TAB_SECTION_START) and Line.endswith(DT.TAB_PRIVATE + DT.TAB_SECTION_END):
+ __IsFoundPrivate = True
+ if Line.startswith(DT.TAB_SECTION_START) and Line.endswith(DT.TAB_SECTION_END)\
+ and not Line.endswith(DT.TAB_PRIVATE + DT.TAB_SECTION_END):
+ __IsFoundPrivate = False
+ if __IsFoundPrivate:
+ self._Private += Line + '\r'
+ if not __IsFoundPrivate:
+ NewContent.append(Line + '\r')
+
+ RawData = FileContent(DecFile, NewContent)
+
+ _DecComments.__init__(self)
+ _DecBase.__init__(self, RawData)
+
+ self.BinaryHeadComment = []
+ self.PcdErrorCommentDict = {}
+
+ self._Define = _DecDefine(RawData)
+ self._Include = _DecInclude(RawData)
+ self._Guid = _DecGuid(RawData)
+ self._LibClass = _DecLibraryclass(RawData)
+ self._Pcd = _DecPcd(RawData)
+ self._UserEx = _DecUserExtension(RawData)
+
+ #
+ # DEC file supported data types (one type per section)
+ #
+ self._SectionParser = {
+ DT.TAB_DEC_DEFINES.upper() : self._Define,
+ DT.TAB_INCLUDES.upper() : self._Include,
+ DT.TAB_LIBRARY_CLASSES.upper() : self._LibClass,
+ DT.TAB_GUIDS.upper() : self._Guid,
+ DT.TAB_PPIS.upper() : self._Guid,
+ DT.TAB_PROTOCOLS.upper() : self._Guid,
+ DT.TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : self._Pcd,
+ DT.TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : self._Pcd,
+ DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() : self._Pcd,
+ DT.TAB_PCDS_DYNAMIC_NULL.upper() : self._Pcd,
+ DT.TAB_PCDS_DYNAMIC_EX_NULL.upper() : self._Pcd,
+ DT.TAB_USER_EXTENSIONS.upper() : self._UserEx
+ }
+
+ if Parse:
+ self.ParseDecComment()
+ self.Parse()
+ #
+ # Parsing done, check required fields
+ #
+ self.CheckRequiredFields()
+
+ def CheckRequiredFields(self):
+ for SectionParser in self._SectionParser.values():
+ if not SectionParser.CheckRequiredFields():
+ return False
+ return True
+
+ ##
+ # Parse DEC file
+ #
+ def ParseDecComment(self):
+ IsFileHeader = False
+ IsBinaryHeader = False
+ FileHeaderLineIndex = -1
+ BinaryHeaderLineIndex = -1
+ TokenSpaceGuidCName = ''
+
+ #
+ # Parse PCD error comment section
+ #
+ while not self._RawData.IsEndOfFile():
+ self._RawData.CurrentLine = self._RawData.GetNextLine()
+ if self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT) and \
+ DT.TAB_SECTION_START in self._RawData.CurrentLine and \
+ DT.TAB_SECTION_END in self._RawData.CurrentLine:
+ self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip()
+
+ if self._RawData.CurrentLine[0] == DT.TAB_SECTION_START and \
+ self._RawData.CurrentLine[-1] == DT.TAB_SECTION_END:
+ RawSection = self._RawData.CurrentLine[1:-1].strip()
+ if RawSection.upper().startswith(DT.TAB_PCD_ERROR.upper()+'.'):
+ TokenSpaceGuidCName = RawSection.split(DT.TAB_PCD_ERROR+'.')[1].strip()
+ continue
+
+ if TokenSpaceGuidCName and self._RawData.CurrentLine.startswith(DT.TAB_COMMENT_SPLIT):
+ self._RawData.CurrentLine = self._RawData.CurrentLine.replace(DT.TAB_COMMENT_SPLIT, '').strip()
+ if self._RawData.CurrentLine != '':
+ if DT.TAB_VALUE_SPLIT not in self._RawData.CurrentLine:
+ self._LoggerError(ST.ERR_DECPARSE_PCDERRORMSG_MISS_VALUE_SPLIT)
+
+ PcdErrorNumber, PcdErrorMsg = GetSplitValueList(self._RawData.CurrentLine, DT.TAB_VALUE_SPLIT, 1)
+ PcdErrorNumber = ParsePcdErrorCode(PcdErrorNumber, self._RawData.Filename, self._RawData.LineIndex)
+ if not PcdErrorMsg.strip():
+ self._LoggerError(ST.ERR_DECPARSE_PCD_MISS_ERRORMSG)
+
+ self.PcdErrorCommentDict[(TokenSpaceGuidCName, PcdErrorNumber)] = PcdErrorMsg.strip()
+ else:
+ TokenSpaceGuidCName = ''
+
+ self._RawData.LineIndex = 0
+ self._RawData.CurrentLine = ''
+ self._RawData.NextLine = ''
+
+ while not self._RawData.IsEndOfFile():
+ Line, Comment = CleanString(self._RawData.GetNextLine())
+
+ #
+ # Header must be pure comment
+ #
+ if Line != '':
+ self._RawData.UndoNextLine()
+ break
+
+ if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) and Comment.find(DT.TAB_HEADER_COMMENT) > 0 \
+ and not Comment[2:Comment.find(DT.TAB_HEADER_COMMENT)].strip():
+ IsFileHeader = True
+ IsBinaryHeader = False
+ FileHeaderLineIndex = self._RawData.LineIndex
+
+ #
+ # Get license information before '@file'
+ #
+ if not IsFileHeader and not IsBinaryHeader and Comment and Comment.startswith(DT.TAB_COMMENT_SPLIT) and \
+ DT.TAB_BINARY_HEADER_COMMENT not in Comment:
+ self._HeadComment.append((Comment, self._RawData.LineIndex))
+
+ if Comment and IsFileHeader and \
+ not(Comment.startswith(DT.TAB_SPECIAL_COMMENT) \
+ and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0):
+ self._HeadComment.append((Comment, self._RawData.LineIndex))
+ #
+ # Double '#' indicates end of header comments
+ #
+ if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsFileHeader:
+ IsFileHeader = False
+ continue
+
+ if Comment and Comment.startswith(DT.TAB_SPECIAL_COMMENT) \
+ and Comment.find(DT.TAB_BINARY_HEADER_COMMENT) > 0:
+ IsBinaryHeader = True
+ IsFileHeader = False
+ BinaryHeaderLineIndex = self._RawData.LineIndex
+
+ if Comment and IsBinaryHeader:
+ self.BinaryHeadComment.append((Comment, self._RawData.LineIndex))
+ #
+ # Double '#' indicates end of header comments
+ #
+ if (not Comment or Comment == DT.TAB_SPECIAL_COMMENT) and IsBinaryHeader:
+ IsBinaryHeader = False
+ break
+
+ if FileHeaderLineIndex > -1 and not IsFileHeader and not IsBinaryHeader:
+ break
+
+ if FileHeaderLineIndex > BinaryHeaderLineIndex and FileHeaderLineIndex > -1 and BinaryHeaderLineIndex > -1:
+ self._LoggerError(ST.ERR_BINARY_HEADER_ORDER)
+
+ if FileHeaderLineIndex == -1:
+# self._LoggerError(ST.ERR_NO_SOURCE_HEADER)
+ Logger.Error(TOOL_NAME, FORMAT_INVALID,
+ ST.ERR_NO_SOURCE_HEADER,
+ File=self._RawData.Filename)
+ return
+
+ def _StopCurrentParsing(self, Line):
+ return False
+
+ def _ParseItem(self):
+ self._SectionHeaderParser()
+ if len(self._RawData.CurrentScope) == 0:
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_EMPTY)
+ SectionObj = self._SectionParser[self._RawData.CurrentScope[0][0]]
+ SectionObj.BlockStart()
+ SectionObj.Parse()
+ return SectionObj.GetDataObject()
+
+ def _UserExtentionSectionParser(self):
+ self._RawData.CurrentScope = []
+ ArchList = set()
+ Section = self._RawData.CurrentLine[1:-1]
+ Par = ParserHelper(Section, self._RawData.Filename)
+ while not Par.End():
+ #
+ # User extention
+ #
+ Token = Par.GetToken()
+ if Token.upper() != DT.TAB_USER_EXTENSIONS.upper():
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_UE)
+ UserExtension = Token.upper()
+ Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)
+
+ #
+ # UserID
+ #
+ Token = Par.GetToken()
+ if not IsValidUserId(Token):
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_USERID)
+ UserId = Token
+ Par.AssertChar(DT.TAB_SPLIT, ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)
+ #
+ # IdString
+ #
+ Token = Par.GetToken()
+ if not IsValidIdString(Token):
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_UE_IDSTRING)
+ IdString = Token
+ Arch = 'COMMON'
+ if Par.Expect(DT.TAB_SPLIT):
+ Token = Par.GetToken()
+ Arch = Token.upper()
+ if not IsValidArch(Arch):
+ self._LoggerError(ST.ERR_DECPARSE_ARCH)
+ ArchList.add(Arch)
+ if [UserExtension, UserId, IdString, Arch] not in \
+ self._RawData.CurrentScope:
+ self._RawData.CurrentScope.append(
+ [UserExtension, UserId, IdString, Arch]
+ )
+ if not Par.Expect(DT.TAB_COMMA_SPLIT):
+ break
+ elif Par.End():
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMA)
+ Par.AssertEnd(ST.ERR_DECPARSE_SECTION_UE, self._RawData.LineIndex)
+ if 'COMMON' in ArchList and len(ArchList) > 1:
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON)
+
+ ## Section header parser
+ #
+ # The section header is always in following format:
+ #
+ # [section_name.arch<.platform|module_type>]
+ #
+ def _SectionHeaderParser(self):
+ if self._RawData.CurrentLine[0] != DT.TAB_SECTION_START or self._RawData.CurrentLine[-1] != DT.TAB_SECTION_END:
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_IDENTIFY)
+
+ RawSection = self._RawData.CurrentLine[1:-1].strip().upper()
+ #
+ # Check defines section which is only allowed to occur once and
+ # no arch can be followed
+ #
+ if RawSection.startswith(DT.TAB_DEC_DEFINES.upper()):
+ if RawSection != DT.TAB_DEC_DEFINES.upper():
+ self._LoggerError(ST.ERR_DECPARSE_DEFINE_SECNAME)
+ #
+ # Check user extension section
+ #
+ if RawSection.startswith(DT.TAB_USER_EXTENSIONS.upper()):
+ return self._UserExtentionSectionParser()
+ self._RawData.CurrentScope = []
+ SectionNames = []
+ ArchList = set()
+ for Item in GetSplitValueList(RawSection, DT.TAB_COMMA_SPLIT):
+ if Item == '':
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine)
+
+ ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
+ #
+ # different types of PCD are permissible in one section
+ #
+ SectionName = ItemList[0]
+ if SectionName not in self._SectionParser:
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_UNKNOW % SectionName)
+ if SectionName not in SectionNames:
+ SectionNames.append(SectionName)
+ #
+ # In DEC specification, all section headers have at most two part:
+ # SectionName.Arch except UserExtension
+ #
+ if len(ItemList) > 2:
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBTOOMANY % Item)
+
+ if DT.TAB_PCDS_FEATURE_FLAG_NULL.upper() in SectionNames and len(SectionNames) > 1:
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_FEATUREFLAG % DT.TAB_PCDS_FEATURE_FLAG_NULL)
+ #
+ # S1 is always Arch
+ #
+ if len(ItemList) > 1:
+ Str1 = ItemList[1]
+ if not IsValidArch(Str1):
+ self._LoggerError(ST.ERR_DECPARSE_ARCH)
+ else:
+ Str1 = 'COMMON'
+ ArchList.add(Str1)
+
+ if [SectionName, Str1] not in self._RawData.CurrentScope:
+ self._RawData.CurrentScope.append([SectionName, Str1])
+ #
+ # 'COMMON' must not be used with specific ARCHs at the same section
+ #
+ if 'COMMON' in ArchList and len(ArchList) > 1:
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_COMMON)
+ if len(SectionNames) == 0:
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_SUBEMPTY % self._RawData.CurrentLine)
+ if len(SectionNames) != 1:
+ for Sec in SectionNames:
+ if not Sec.startswith(DT.TAB_PCDS.upper()):
+ self._LoggerError(ST.ERR_DECPARSE_SECTION_NAME % str(SectionNames))
+
+ def GetDefineSectionMacro(self):
+ return self._Define.GetLocalMacro()
+ def GetDefineSectionObject(self):
+ return self._Define.GetDataObject()
+ def GetIncludeSectionObject(self):
+ return self._Include.GetDataObject()
+ def GetGuidSectionObject(self):
+ return self._Guid.GetGuidObject()
+ def GetProtocolSectionObject(self):
+ return self._Guid.GetProtocolObject()
+ def GetPpiSectionObject(self):
+ return self._Guid.GetPpiObject()
+ def GetLibraryClassSectionObject(self):
+ return self._LibClass.GetDataObject()
+ def GetPcdSectionObject(self):
+ return self._Pcd.GetDataObject()
+ def GetUserExtensionSectionObject(self):
+ return self._UserEx.GetDataObject()
+ def GetPackageSpecification(self):
+ return self._Define.GetDataObject().GetPackageSpecification()
+ def GetPackageName(self):
+ return self._Define.GetDataObject().GetPackageName()
+ def GetPackageGuid(self):
+ return self._Define.GetDataObject().GetPackageGuid()
+ def GetPackageVersion(self):
+ return self._Define.GetDataObject().GetPackageVersion()
+ def GetPackageUniFile(self):
+ return self._Define.GetDataObject().GetPackageUniFile()
+ def GetPrivateSections(self):
+ return self._Private
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py
new file mode 100755
index 00000000..4731c85c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/DecParserMisc.py
@@ -0,0 +1,364 @@
+## @file
+# This file is used to define helper class and function for DEC parser
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+
+'''
+DecParserMisc
+'''
+
+## Import modules
+#
+import os
+import Logger.Log as Logger
+from Logger.ToolError import FILE_PARSE_FAILURE
+from Logger import StringTable as ST
+from Library.DataType import TAB_COMMENT_SPLIT
+from Library.DataType import TAB_COMMENT_EDK1_SPLIT
+from Library.ExpressionValidate import IsValidBareCString
+from Library.ParserValidate import IsValidCFormatGuid
+from Library.ExpressionValidate import IsValidFeatureFlagExp
+from Library.ExpressionValidate import IsValidLogicalExpr
+from Library.ExpressionValidate import IsValidStringTest
+from Library.Misc import CheckGuidRegFormat
+
+TOOL_NAME = 'DecParser'
+VERSION_PATTERN = '[0-9]+(\.[0-9]+)?'
+CVAR_PATTERN = '[_a-zA-Z][a-zA-Z0-9_]*'
+PCD_TOKEN_PATTERN = '(0[xX]0*[a-fA-F0-9]{1,8})|([0-9]+)'
+MACRO_PATTERN = '[A-Z][_A-Z0-9]*'
+
+## FileContent
+# Class to hold DEC file information
+#
+class FileContent:
+ def __init__(self, Filename, FileContent2):
+ self.Filename = Filename
+ self.PackagePath, self.PackageFile = os.path.split(Filename)
+ self.LineIndex = 0
+ self.CurrentLine = ''
+ self.NextLine = ''
+ self.HeadComment = []
+ self.TailComment = []
+ self.CurrentScope = None
+ self.Content = FileContent2
+ self.Macros = {}
+ self.FileLines = len(FileContent2)
+
+ def GetNextLine(self):
+ if self.LineIndex >= self.FileLines:
+ return ''
+ Line = self.Content[self.LineIndex]
+ self.LineIndex += 1
+ return Line
+
+ def UndoNextLine(self):
+ if self.LineIndex > 0:
+ self.LineIndex -= 1
+
+ def ResetNext(self):
+ self.HeadComment = []
+ self.TailComment = []
+ self.NextLine = ''
+
+ def SetNext(self, Line, HeadComment, TailComment):
+ self.NextLine = Line
+ self.HeadComment = HeadComment
+ self.TailComment = TailComment
+
+ def IsEndOfFile(self):
+ return self.LineIndex >= self.FileLines
+
+
+## StripRoot
+#
+# Strip root path
+#
+# @param Root: Root must be absolute path
+# @param Path: Path to be stripped
+#
+def StripRoot(Root, Path):
+ OrigPath = Path
+ Root = os.path.normpath(Root)
+ Path = os.path.normpath(Path)
+ if not os.path.isabs(Root):
+ return OrigPath
+ if Path.startswith(Root):
+ Path = Path[len(Root):]
+ if Path and Path[0] == os.sep:
+ Path = Path[1:]
+ return Path
+ return OrigPath
+
+## CleanString
+#
+# Split comments in a string
+# Remove spaces
+#
+# @param Line: The string to be cleaned
+# @param CommentCharacter: Comment char, used to ignore comment content,
+# default is DataType.TAB_COMMENT_SPLIT
+#
+def CleanString(Line, CommentCharacter=TAB_COMMENT_SPLIT, \
+ AllowCppStyleComment=False):
+ #
+ # remove whitespace
+ #
+ Line = Line.strip()
+ #
+ # Replace EDK1's comment character
+ #
+ if AllowCppStyleComment:
+ Line = Line.replace(TAB_COMMENT_EDK1_SPLIT, CommentCharacter)
+ #
+ # separate comments and statements
+ #
+ Comment = ''
+ InQuote = False
+ for Index in range(0, len(Line)):
+ if Line[Index] == '"':
+ InQuote = not InQuote
+ continue
+ if Line[Index] == CommentCharacter and not InQuote:
+ Comment = Line[Index:].strip()
+ Line = Line[0:Index].strip()
+ break
+
+ return Line, Comment
+
+
+## IsValidNumValUint8
+#
+# Check if Token is NumValUint8: <NumValUint8> ::= {<ShortNum>} {<UINT8>} {<Expression>}
+#
+# @param Token: Token to be checked
+#
+def IsValidNumValUint8(Token):
+ Valid = True
+ Cause = ""
+ TokenValue = None
+ Token = Token.strip()
+ if Token.lower().startswith('0x'):
+ Base = 16
+ else:
+ Base = 10
+ try:
+ TokenValue = int(Token, Base)
+ except BaseException:
+ Valid, Cause = IsValidLogicalExpr(Token, True)
+ if Cause:
+ pass
+ if not Valid:
+ return False
+ if TokenValue and (TokenValue < 0 or TokenValue > 0xFF):
+ return False
+ else:
+ return True
+
+## IsValidNList
+#
+# Check if Value has the format of <NumValUint8> ["," <NumValUint8>]{0,}
+# <NumValUint8> ::= {<ShortNum>} {<UINT8>} {<Expression>}
+#
+# @param Value: Value to be checked
+#
+def IsValidNList(Value):
+ Par = ParserHelper(Value)
+ if Par.End():
+ return False
+ while not Par.End():
+ Token = Par.GetToken(',')
+ if not IsValidNumValUint8(Token):
+ return False
+ if Par.Expect(','):
+ if Par.End():
+ return False
+ continue
+ else:
+ break
+ return Par.End()
+
+## IsValidCArray
+#
+# check Array is valid
+#
+# @param Array: The input Array
+#
+def IsValidCArray(Array):
+ Par = ParserHelper(Array)
+ if not Par.Expect('{'):
+ return False
+ if Par.End():
+ return False
+ while not Par.End():
+ Token = Par.GetToken(',}')
+ #
+ # ShortNum, UINT8, Expression
+ #
+ if not IsValidNumValUint8(Token):
+ return False
+ if Par.Expect(','):
+ if Par.End():
+ return False
+ continue
+ elif Par.Expect('}'):
+ #
+ # End of C array
+ #
+ break
+ else:
+ return False
+ return Par.End()
+
+## IsValidPcdDatum
+#
+# check PcdDatum is valid
+#
+# @param Type: The pcd Type
+# @param Value: The pcd Value
+#
+def IsValidPcdDatum(Type, Value):
+ if not Value:
+ return False, ST.ERR_DECPARSE_PCD_VALUE_EMPTY
+ Valid = True
+ Cause = ""
+ if Type not in ["UINT8", "UINT16", "UINT32", "UINT64", "VOID*", "BOOLEAN"]:
+ return False, ST.ERR_DECPARSE_PCD_TYPE
+ if Type == "VOID*":
+ if not ((Value.startswith('L"') or Value.startswith('"') and \
+ Value.endswith('"'))
+ or (IsValidCArray(Value)) or (IsValidCFormatGuid(Value)) \
+ or (IsValidNList(Value)) or (CheckGuidRegFormat(Value))
+ ):
+ return False, ST.ERR_DECPARSE_PCD_VOID % (Value, Type)
+ RealString = Value[Value.find('"') + 1 :-1]
+ if RealString:
+ if not IsValidBareCString(RealString):
+ return False, ST.ERR_DECPARSE_PCD_VOID % (Value, Type)
+ elif Type == 'BOOLEAN':
+ if Value in ['TRUE', 'FALSE', 'true', 'false', 'True', 'False',
+ '0x1', '0x01', '1', '0x0', '0x00', '0']:
+ return True, ""
+ Valid, Cause = IsValidStringTest(Value, True)
+ if not Valid:
+ Valid, Cause = IsValidFeatureFlagExp(Value, True)
+ if not Valid:
+ return False, Cause
+ else:
+ if Value and (Value[0] == '-' or Value[0] == '+'):
+ return False, ST.ERR_DECPARSE_PCD_INT_NEGTIVE % (Value, Type)
+ try:
+ StrVal = Value
+ if Value and not Value.startswith('0x') \
+ and not Value.startswith('0X'):
+ Value = Value.lstrip('0')
+ if not Value:
+ return True, ""
+ Value = int(Value, 0)
+ MAX_VAL_TYPE = {"BOOLEAN": 0x01, 'UINT8': 0xFF, 'UINT16': 0xFFFF, 'UINT32': 0xFFFFFFFF,
+ 'UINT64': 0xFFFFFFFFFFFFFFFF}
+ if Value > MAX_VAL_TYPE[Type]:
+ return False, ST.ERR_DECPARSE_PCD_INT_EXCEED % (StrVal, Type)
+ except BaseException:
+ Valid, Cause = IsValidLogicalExpr(Value, True)
+ if not Valid:
+ return False, Cause
+
+ return True, ""
+
+## ParserHelper
+#
+class ParserHelper:
+ def __init__(self, String, File=''):
+ self._String = String
+ self._StrLen = len(String)
+ self._Index = 0
+ self._File = File
+
+ ## End
+ #
+ # End
+ #
+ def End(self):
+ self.__SkipWhitespace()
+ return self._Index >= self._StrLen
+
+ ## __SkipWhitespace
+ #
+ # Skip whitespace
+ #
+ def __SkipWhitespace(self):
+ for Char in self._String[self._Index:]:
+ if Char not in ' \t':
+ break
+ self._Index += 1
+
+ ## Expect
+ #
+ # Expect char in string
+ #
+ # @param ExpectChar: char expected in index of string
+ #
+ def Expect(self, ExpectChar):
+ self.__SkipWhitespace()
+ for Char in self._String[self._Index:]:
+ if Char != ExpectChar:
+ return False
+ else:
+ self._Index += 1
+ return True
+ #
+ # Index out of bound of String
+ #
+ return False
+
+ ## GetToken
+ #
+ # Get token until encounter StopChar, front whitespace is consumed
+ #
+ # @param StopChar: Get token until encounter char in StopChar
+ # @param StkipPair: Only can be ' or ", StopChar in SkipPair are skipped
+ #
+ def GetToken(self, StopChar='.,|\t ', SkipPair='"'):
+ self.__SkipWhitespace()
+ PreIndex = self._Index
+ InQuote = False
+ LastChar = ''
+ for Char in self._String[self._Index:]:
+ if Char == SkipPair and LastChar != '\\':
+ InQuote = not InQuote
+ if Char in StopChar and not InQuote:
+ break
+ self._Index += 1
+ if Char == '\\' and LastChar == '\\':
+ LastChar = ''
+ else:
+ LastChar = Char
+ return self._String[PreIndex:self._Index]
+
+ ## AssertChar
+ #
+ # Assert char at current index of string is AssertChar, or will report
+ # error message
+ #
+ # @param AssertChar: AssertChar
+ # @param ErrorString: ErrorString
+ # @param ErrorLineNum: ErrorLineNum
+ #
+ def AssertChar(self, AssertChar, ErrorString, ErrorLineNum):
+ if not self.Expect(AssertChar):
+ Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._File,
+ Line=ErrorLineNum, ExtraData=ErrorString)
+
+ ## AssertEnd
+ #
+ # @param ErrorString: ErrorString
+ # @param ErrorLineNum: ErrorLineNum
+ #
+ def AssertEnd(self, ErrorString, ErrorLineNum):
+ self.__SkipWhitespace()
+ if self._Index != self._StrLen:
+ Logger.Error(TOOL_NAME, FILE_PARSE_FAILURE, File=self._File,
+ Line=ErrorLineNum, ExtraData=ErrorString)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py
new file mode 100755
index 00000000..0f9e9ad3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfAsBuiltProcess.py
@@ -0,0 +1,283 @@
+## @file
+# This file is used to provide method for process AsBuilt INF file. It will consumed by InfParser
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+'''
+InfAsBuiltProcess
+'''
+## Import modules
+#
+
+import os
+import re
+from Library import GlobalData
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger import ToolError
+
+from Library.StringUtils import GetSplitValueList
+from Library.Misc import GetHelpStringByRemoveHashKey
+from Library.Misc import ValidFile
+from Library.Misc import ProcessLineExtender
+from Library.ParserValidate import IsValidPath
+from Library.Parsing import MacroParser
+from Parser.InfParserMisc import InfExpandMacro
+
+from Library import DataType as DT
+
+## GetLibInstanceInfo
+#
+# Get the information from Library Instance INF file.
+#
+# @param string. A string start with # and followed by INF file path
+# @param WorkSpace. The WorkSpace directory used to combined with INF file path.
+#
+# @return GUID, Version
+def GetLibInstanceInfo(String, WorkSpace, LineNo, CurrentInfFileName):
+
+ FileGuidString = ""
+ VerString = ""
+
+ OriginalString = String
+ String = String.strip()
+ if not String:
+ return None, None
+ #
+ # Remove "#" characters at the beginning
+ #
+ String = GetHelpStringByRemoveHashKey(String)
+ String = String.strip()
+
+ #
+ # To deal with library instance specified by GUID and version
+ #
+ RegFormatGuidPattern = re.compile("\s*([0-9a-fA-F]){8}-"
+ "([0-9a-fA-F]){4}-"
+ "([0-9a-fA-F]){4}-"
+ "([0-9a-fA-F]){4}-"
+ "([0-9a-fA-F]){12}\s*")
+ VersionPattern = re.compile('[\t\s]*\d+(\.\d+)?[\t\s]*')
+ GuidMatchedObj = RegFormatGuidPattern.search(String)
+
+ if String.upper().startswith('GUID') and GuidMatchedObj and 'Version' in String:
+ VersionStr = String[String.upper().find('VERSION') + 8:]
+ VersionMatchedObj = VersionPattern.search(VersionStr)
+ if VersionMatchedObj:
+ Guid = GuidMatchedObj.group().strip()
+ Version = VersionMatchedObj.group().strip()
+ return Guid, Version
+
+ #
+ # To deal with library instance specified by file name
+ #
+ FileLinesList = GetFileLineContent(String, WorkSpace, LineNo, OriginalString)
+
+
+ ReFindFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$")
+ ReFindVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$")
+
+ for Line in FileLinesList:
+ if ReFindFileGuidPattern.match(Line):
+ FileGuidString = Line
+ if ReFindVerStringPattern.match(Line):
+ VerString = Line
+
+ if FileGuidString:
+ FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1]
+ if VerString:
+ VerString = GetSplitValueList(VerString, '=', 1)[1]
+
+ return FileGuidString, VerString
+
+## GetPackageListInfo
+#
+# Get the package information from INF file.
+#
+# @param string. A string start with # and followed by INF file path
+# @param WorkSpace. The WorkSpace directory used to combined with INF file path.
+#
+# @return GUID, Version
+def GetPackageListInfo(FileNameString, WorkSpace, LineNo):
+ PackageInfoList = []
+ DefineSectionMacros = {}
+ PackageSectionMacros = {}
+
+ FileLinesList = GetFileLineContent(FileNameString, WorkSpace, LineNo, '')
+
+ RePackageHeader = re.compile('^\s*\[Packages.*\].*$')
+ ReDefineHeader = re.compile('^\s*\[Defines].*$')
+
+ PackageHederFlag = False
+ DefineHeaderFlag = False
+ LineNo = -1
+ for Line in FileLinesList:
+ LineNo += 1
+ Line = Line.strip()
+
+ if Line.startswith('['):
+ PackageHederFlag = False
+ DefineHeaderFlag = False
+
+ if Line.startswith("#"):
+ continue
+
+ if not Line:
+ continue
+
+ #
+ # Found [Packages] section
+ #
+ if RePackageHeader.match(Line):
+ PackageHederFlag = True
+ continue
+
+ #
+ # Found [Define] section
+ #
+ if ReDefineHeader.match(Line):
+ DefineHeaderFlag = True
+ continue
+
+ if DefineHeaderFlag:
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((Line, LineNo),
+ FileNameString,
+ DT.MODEL_META_DATA_HEADER,
+ DefineSectionMacros)
+
+ if Name is not None:
+ DefineSectionMacros[Name] = Value
+ continue
+
+ if PackageHederFlag:
+
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((Line, LineNo),
+ FileNameString,
+ DT.MODEL_META_DATA_PACKAGE,
+ DefineSectionMacros)
+ if Name is not None:
+ PackageSectionMacros[Name] = Value
+ continue
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ Line = InfExpandMacro(Line, (FileNameString, Line, LineNo), DefineSectionMacros, PackageSectionMacros, True)
+
+ Line = GetSplitValueList(Line, "#", 1)[0]
+ Line = GetSplitValueList(Line, "|", 1)[0]
+ PackageInfoList.append(Line)
+
+ return PackageInfoList
+
+def GetFileLineContent(FileName, WorkSpace, LineNo, OriginalString):
+
+ if not LineNo:
+ LineNo = -1
+
+ #
+ # Validate file name exist.
+ #
+ FullFileName = os.path.normpath(os.path.realpath(os.path.join(WorkSpace, FileName)))
+ if not (ValidFile(FullFileName)):
+ return []
+
+ #
+ # Validate file exist/format.
+ #
+ if not IsValidPath(FileName, WorkSpace):
+ return []
+
+ FileLinesList = []
+
+ try:
+ FullFileName = FullFileName.replace('\\', '/')
+ Inputfile = open(FullFileName, "r")
+ try:
+ FileLinesList = Inputfile.readlines()
+ except BaseException:
+ Logger.Error("InfParser", ToolError.FILE_READ_FAILURE, ST.ERR_FILE_OPEN_FAILURE, File=FullFileName)
+ finally:
+ Inputfile.close()
+ except BaseException:
+ Logger.Error("InfParser",
+ ToolError.FILE_READ_FAILURE,
+ ST.ERR_FILE_OPEN_FAILURE,
+ File=FullFileName)
+
+ FileLinesList = ProcessLineExtender(FileLinesList)
+
+ return FileLinesList
+
+##
+# Get all INF files from current workspace
+#
+#
+def GetInfsFromWorkSpace(WorkSpace):
+ InfFiles = []
+ for top, dirs, files in os.walk(WorkSpace):
+ dirs = dirs # just for pylint
+ for File in files:
+ if File.upper().endswith(".INF"):
+ InfFiles.append(os.path.join(top, File))
+
+ return InfFiles
+
+##
+# Get GUID and version from library instance file
+#
+#
+def GetGuidVerFormLibInstance(Guid, Version, WorkSpace, CurrentInfFileName):
+ for InfFile in GetInfsFromWorkSpace(WorkSpace):
+ try:
+ if InfFile.strip().upper() == CurrentInfFileName.strip().upper():
+ continue
+ InfFile = InfFile.replace('\\', '/')
+ if InfFile not in GlobalData.gLIBINSTANCEDICT:
+ InfFileObj = open(InfFile, "r")
+ GlobalData.gLIBINSTANCEDICT[InfFile] = InfFileObj
+ else:
+ InfFileObj = GlobalData.gLIBINSTANCEDICT[InfFile]
+
+ except BaseException:
+ Logger.Error("InfParser",
+ ToolError.FILE_READ_FAILURE,
+ ST.ERR_FILE_OPEN_FAILURE,
+ File=InfFile)
+ try:
+ FileLinesList = InfFileObj.readlines()
+ FileLinesList = ProcessLineExtender(FileLinesList)
+
+ ReFindFileGuidPattern = re.compile("^\s*FILE_GUID\s*=.*$")
+ ReFindVerStringPattern = re.compile("^\s*VERSION_STRING\s*=.*$")
+
+ for Line in FileLinesList:
+ if ReFindFileGuidPattern.match(Line):
+ FileGuidString = Line
+ if ReFindVerStringPattern.match(Line):
+ VerString = Line
+
+ if FileGuidString:
+ FileGuidString = GetSplitValueList(FileGuidString, '=', 1)[1]
+ if VerString:
+ VerString = GetSplitValueList(VerString, '=', 1)[1]
+
+ if FileGuidString.strip().upper() == Guid.upper() and \
+ VerString.strip().upper() == Version.upper():
+ return Guid, Version
+
+ except BaseException:
+ Logger.Error("InfParser", ToolError.FILE_READ_FAILURE, ST.ERR_FILE_OPEN_FAILURE, File=InfFile)
+ finally:
+ InfFileObj.close()
+
+ return '', ''
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py
new file mode 100755
index 00000000..b3ee7084
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBinarySectionParser.py
@@ -0,0 +1,226 @@
+## @file
+# This file contained the parser for [Binaries] sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+'''
+InfBinarySectionParser
+'''
+##
+# Import Modules
+#
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Parser.InfParserMisc import InfExpandMacro
+from Library import DataType as DT
+from Library.Parsing import MacroParser
+from Library.Misc import GetSplitValueList
+from Object.Parser.InfCommonObject import InfLineCommentObject
+from Object.Parser.InfCommonObject import CurrentLine
+from Parser.InfParserMisc import InfParserSectionRoot
+
+class InfBinarySectionParser(InfParserSectionRoot):
+ ## InfBinaryParser
+ #
+ #
+ def InfBinaryParser(self, SectionString, InfSectionObject, FileName):
+ #
+ # Macro defined in this section
+ #
+ SectionMacros = {}
+ ValueList = []
+ #
+ # For UI (UI, SEC_UI, UNI_UI) binaries
+ # One and only one UI section can be included
+ #
+ UiBinaryList = []
+ #
+ # For Version (VER, SEC_VER, UNI_VER).
+ # One and only one VER section on be included
+ #
+ VerBinaryList = []
+ #
+ # For other common type binaries
+ #
+ ComBinaryList = []
+
+ StillCommentFalg = False
+ HeaderComments = []
+ LineComment = None
+
+ AllSectionContent = ''
+ #
+ # Parse section content
+ #
+ for Line in SectionString:
+ BinLineContent = Line[0]
+ BinLineNo = Line[1]
+
+ if BinLineContent.strip() == '':
+ continue
+
+ CurrentLineObj = CurrentLine()
+ CurrentLineObj.FileName = FileName
+ CurrentLineObj.LineString = BinLineContent
+ CurrentLineObj.LineNo = BinLineNo
+ #
+ # Found Header Comments
+ #
+ if BinLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ #
+ # Last line is comments, and this line go on.
+ #
+ if StillCommentFalg:
+ HeaderComments.append(Line)
+ AllSectionContent += BinLineContent + DT.END_OF_LINE
+ continue
+ #
+ # First time encounter comment
+ #
+ else:
+ #
+ # Clear original data
+ #
+ HeaderComments = []
+ HeaderComments.append(Line)
+ AllSectionContent += BinLineContent + DT.END_OF_LINE
+ StillCommentFalg = True
+ continue
+ else:
+ StillCommentFalg = False
+
+ if len(HeaderComments) >= 1:
+ LineComment = InfLineCommentObject()
+ LineCommentContent = ''
+ for Item in HeaderComments:
+ LineCommentContent += Item[0] + DT.END_OF_LINE
+ LineComment.SetHeaderComments(LineCommentContent)
+
+ #
+ # Find Tail comment.
+ #
+ if BinLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ TailComments = BinLineContent[BinLineContent.find(DT.TAB_COMMENT_SPLIT):]
+ BinLineContent = BinLineContent[:BinLineContent.find(DT.TAB_COMMENT_SPLIT)]
+ if LineComment is None:
+ LineComment = InfLineCommentObject()
+ LineComment.SetTailComments(TailComments)
+
+ #
+ # Find Macro
+ #
+ MacroDef = MacroParser((BinLineContent, BinLineNo),
+ FileName,
+ DT.MODEL_EFI_BINARY_FILE,
+ self.FileLocalMacros)
+ if MacroDef[0] is not None:
+ SectionMacros[MacroDef[0]] = MacroDef[1]
+ LineComment = None
+ HeaderComments = []
+ continue
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ LineContent = InfExpandMacro(BinLineContent,
+ (FileName, BinLineContent, BinLineNo),
+ self.FileLocalMacros,
+ SectionMacros, True)
+
+ AllSectionContent += LineContent + DT.END_OF_LINE
+ TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Should equal to UI/SEC_UI/UNI_UI
+ #
+ ValueList[0] = ValueList[0].strip()
+ if ValueList[0] == DT.BINARY_FILE_TYPE_UNI_UI or \
+ ValueList[0] == DT.BINARY_FILE_TYPE_SEC_UI or \
+ ValueList[0] == DT.BINARY_FILE_TYPE_UI:
+ if len(ValueList) == 2:
+ TokenList = GetSplitValueList(ValueList[1],
+ DT.TAB_VALUE_SPLIT,
+ 2)
+ NewValueList = []
+ NewValueList.append(ValueList[0])
+ for Item in TokenList:
+ NewValueList.append(Item)
+ UiBinaryList.append((NewValueList,
+ LineComment,
+ CurrentLineObj))
+ #
+ # Should equal to VER/SEC_VER/UNI_VER
+ #
+ elif ValueList[0] == DT.BINARY_FILE_TYPE_UNI_VER or \
+ ValueList[0] == DT.BINARY_FILE_TYPE_SEC_VER or \
+ ValueList[0] == DT.BINARY_FILE_TYPE_VER:
+ if len(ValueList) == 2:
+ TokenList = GetSplitValueList(ValueList[1],
+ DT.TAB_VALUE_SPLIT,
+ 2)
+ NewValueList = []
+ NewValueList.append(ValueList[0])
+ for Item in TokenList:
+ NewValueList.append(Item)
+ VerBinaryList.append((NewValueList,
+ LineComment,
+ CurrentLineObj))
+ else:
+ if len(ValueList) == 2:
+ if ValueList[0].strip() == 'SUBTYPE_GUID':
+ TokenList = GetSplitValueList(ValueList[1],
+ DT.TAB_VALUE_SPLIT,
+ 5)
+ else:
+ TokenList = GetSplitValueList(ValueList[1],
+ DT.TAB_VALUE_SPLIT,
+ 4)
+
+ NewValueList = []
+ NewValueList.append(ValueList[0])
+ for Item in TokenList:
+ NewValueList.append(Item)
+ ComBinaryList.append((NewValueList,
+ LineComment,
+ CurrentLineObj))
+ elif len(ValueList) == 1:
+ NewValueList = []
+ NewValueList.append(ValueList[0])
+ ComBinaryList.append((NewValueList,
+ LineComment,
+ CurrentLineObj))
+
+
+
+
+ ValueList = []
+ LineComment = None
+ TailComments = ''
+ HeaderComments = []
+ continue
+
+ #
+ # Current section archs
+ #
+ ArchList = []
+ for Item in self.LastSectionHeaderContent:
+ if Item[1] not in ArchList:
+ ArchList.append(Item[1])
+ InfSectionObject.SetSupArchList(Item[1])
+
+ InfSectionObject.SetAllContent(AllSectionContent)
+ if not InfSectionObject.SetBinary(UiBinaryList,
+ VerBinaryList,
+ ComBinaryList,
+ ArchList):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[Binaries]"),
+ File=FileName,
+ Line=Item[3])
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py
new file mode 100755
index 00000000..3f74ff0c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfBuildOptionSectionParser.py
@@ -0,0 +1,212 @@
+## @file
+# This file contained the parser for BuildOption sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+'''
+InfBuildOptionSectionParser
+'''
+##
+# Import Modules
+#
+from Library import DataType as DT
+from Library import GlobalData
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Parser.InfParserMisc import InfExpandMacro
+from Library.Misc import GetSplitValueList
+from Parser.InfParserMisc import IsAsBuildOptionInfo
+from Library.Misc import GetHelpStringByRemoveHashKey
+from Library.ParserValidate import IsValidFamily
+from Library.ParserValidate import IsValidBuildOptionName
+from Parser.InfParserMisc import InfParserSectionRoot
+
+class InfBuildOptionSectionParser(InfParserSectionRoot):
+ ## InfBuildOptionParser
+ #
+ #
+ def InfBuildOptionParser(self, SectionString, InfSectionObject, FileName):
+
+ BuildOptionList = []
+ SectionContent = ''
+
+ if not GlobalData.gIS_BINARY_INF:
+ ValueList = []
+ LineNo = 0
+
+ for Line in SectionString:
+ LineContent = Line[0]
+ LineNo = Line[1]
+ TailComments = ''
+ ReplaceFlag = False
+
+ if LineContent.strip() == '':
+ SectionContent += LineContent + DT.END_OF_LINE
+ continue
+ #
+ # Found Comment
+ #
+ if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ SectionContent += LineContent + DT.END_OF_LINE
+ continue
+
+ #
+ # Find Tail comment.
+ #
+ if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ TailComments = LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):]
+ LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
+
+ TokenList = GetSplitValueList(LineContent, DT.TAB_DEQUAL_SPLIT, 1)
+ if len(TokenList) == 2:
+ #
+ # "Replace" type build option
+ #
+ TokenList.append('True')
+ ReplaceFlag = True
+ else:
+ TokenList = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)
+ #
+ # "Append" type build option
+ #
+ if len(TokenList) == 2:
+ TokenList.append('False')
+ else:
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
+ ExtraData=LineContent,
+ File=FileName,
+ Line=LineNo)
+
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Replace with [Defines] section Macro
+ #
+ ValueList[0] = InfExpandMacro(ValueList[0], (FileName, LineContent, LineNo),
+ self.FileLocalMacros, None)
+ ValueList[1] = InfExpandMacro(ValueList[1], (FileName, LineContent, LineNo),
+ self.FileLocalMacros, None, True)
+ EqualString = ''
+ if not ReplaceFlag:
+ EqualString = ' = '
+ else:
+ EqualString = ' == '
+
+ SectionContent += ValueList[0] + EqualString + ValueList[1] + TailComments + DT.END_OF_LINE
+
+ Family = GetSplitValueList(ValueList[0], DT.TAB_COLON_SPLIT, 1)
+ if len(Family) == 2:
+ if not IsValidFamily(Family[0]):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
+ ExtraData=LineContent,
+ File=FileName,
+ Line=LineNo)
+ if not IsValidBuildOptionName(Family[1]):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
+ ExtraData=LineContent,
+ File=FileName,
+ Line=LineNo)
+ if len(Family) == 1:
+ if not IsValidBuildOptionName(Family[0]):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_BUILD_OPTION_FORMAT_INVALID,
+ ExtraData=LineContent,
+ File=FileName,
+ Line=LineNo)
+
+ BuildOptionList.append(ValueList)
+ ValueList = []
+ continue
+ else:
+ BuildOptionList = InfAsBuiltBuildOptionParser(SectionString, FileName)
+
+ #
+ # Current section archs
+ #
+ ArchList = []
+ LastItem = ''
+ for Item in self.LastSectionHeaderContent:
+ LastItem = Item
+ if not (Item[1] == '' or Item[1] == '') and Item[1] not in ArchList:
+ ArchList.append(Item[1])
+ InfSectionObject.SetSupArchList(Item[1])
+
+ InfSectionObject.SetAllContent(SectionContent)
+ if not InfSectionObject.SetBuildOptions(BuildOptionList, ArchList, SectionContent):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[BuilOptions]"),
+ File=FileName,
+ Line=LastItem[3])
+
+## InfBuildOptionParser
+#
+#
+def InfAsBuiltBuildOptionParser(SectionString, FileName):
+ BuildOptionList = []
+ #
+ # AsBuild Binary INF file.
+ #
+ AsBuildOptionFlag = False
+ BuildOptionItem = []
+ Count = 0
+ for Line in SectionString:
+ Count += 1
+ LineContent = Line[0]
+ LineNo = Line[1]
+
+ #
+ # The last line
+ #
+ if len(SectionString) == Count:
+ if LineContent.strip().startswith("##") and AsBuildOptionFlag:
+ BuildOptionList.append(BuildOptionItem)
+ BuildOptionList.append([GetHelpStringByRemoveHashKey(LineContent)])
+ elif LineContent.strip().startswith("#") and AsBuildOptionFlag:
+ BuildOptionInfo = GetHelpStringByRemoveHashKey(LineContent)
+ BuildOptionItem.append(BuildOptionInfo)
+ BuildOptionList.append(BuildOptionItem)
+ else:
+ if len(BuildOptionItem) > 0:
+ BuildOptionList.append(BuildOptionItem)
+
+ break
+
+ if LineContent.strip() == '':
+ AsBuildOptionFlag = False
+ continue
+
+ if LineContent.strip().startswith("##") and AsBuildOptionFlag:
+ if len(BuildOptionItem) > 0:
+ BuildOptionList.append(BuildOptionItem)
+
+ BuildOptionItem = []
+
+ if not LineContent.strip().startswith("#"):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_BO_CONTATIN_ASBUILD_AND_COMMON,
+ File=FileName,
+ Line=LineNo,
+ ExtraData=LineContent)
+
+ if IsAsBuildOptionInfo(LineContent):
+ AsBuildOptionFlag = True
+ continue
+
+ if AsBuildOptionFlag:
+ BuildOptionInfo = GetHelpStringByRemoveHashKey(LineContent)
+ BuildOptionItem.append(BuildOptionInfo)
+
+ return BuildOptionList
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py
new file mode 100755
index 00000000..2117da1c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDefineSectionParser.py
@@ -0,0 +1,191 @@
+## @file
+# This file contained the parser for define sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+'''
+InfDefineSectionParser
+'''
+##
+# Import Modules
+#
+import re
+
+from Library import DataType as DT
+from Library import GlobalData
+from Library.Parsing import MacroParser
+from Library.Misc import GetSplitValueList
+from Library.ParserValidate import IsValidArch
+from Object.Parser.InfCommonObject import InfLineCommentObject
+from Object.Parser.InfDefineObject import InfDefMember
+from Parser.InfParserMisc import InfExpandMacro
+from Object.Parser.InfMisc import ErrorInInf
+from Logger import StringTable as ST
+from Parser.InfParserMisc import InfParserSectionRoot
+
+## __GetValidateArchList
+#
+#
+def GetValidateArchList(LineContent):
+
+ TempArch = ''
+ ArchList = []
+ ValidateAcrhPatten = re.compile(r"^\s*#\s*VALID_ARCHITECTURES\s*=\s*.*$", re.DOTALL)
+
+ if ValidateAcrhPatten.match(LineContent):
+ TempArch = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)[1]
+
+ TempArch = GetSplitValueList(TempArch, '(', 1)[0]
+
+ ArchList = re.split('\s+', TempArch)
+ NewArchList = []
+ for Arch in ArchList:
+ if IsValidArch(Arch):
+ NewArchList.append(Arch)
+
+ ArchList = NewArchList
+
+ return ArchList
+
+class InfDefinSectionParser(InfParserSectionRoot):
+ def InfDefineParser(self, SectionString, InfSectionObject, FileName, SectionComment):
+
+ if SectionComment:
+ pass
+ #
+ # Parser Defines section content and fill self._ContentList dict.
+ #
+ StillCommentFalg = False
+ HeaderComments = []
+ SectionContent = ''
+ ArchList = []
+ _ContentList = []
+ _ValueList = []
+ #
+ # Add WORKSPACE to global Marco dict.
+ #
+ self.FileLocalMacros['WORKSPACE'] = GlobalData.gWORKSPACE
+
+ for Line in SectionString:
+ LineContent = Line[0]
+ LineNo = Line[1]
+ TailComments = ''
+ LineComment = None
+
+ LineInfo = ['', -1, '']
+ LineInfo[0] = FileName
+ LineInfo[1] = LineNo
+ LineInfo[2] = LineContent
+
+ if LineContent.strip() == '':
+ continue
+ #
+ # The first time encountered VALIDATE_ARCHITECHERS will be considered as support arch list.
+ #
+ if not ArchList:
+ ArchList = GetValidateArchList(LineContent)
+
+ #
+ # Parser Comment
+ #
+ if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ #
+ # Last line is comments, and this line go on.
+ #
+ if StillCommentFalg:
+ HeaderComments.append(Line)
+ SectionContent += LineContent + DT.END_OF_LINE
+ continue
+ #
+ # First time encounter comment
+ #
+ else:
+ #
+ # Clear original data
+ #
+ HeaderComments = []
+ HeaderComments.append(Line)
+ StillCommentFalg = True
+ SectionContent += LineContent + DT.END_OF_LINE
+ continue
+ else:
+ StillCommentFalg = False
+
+ if len(HeaderComments) >= 1:
+ LineComment = InfLineCommentObject()
+ LineCommentContent = ''
+ for Item in HeaderComments:
+ LineCommentContent += Item[0] + DT.END_OF_LINE
+ LineComment.SetHeaderComments(LineCommentContent)
+
+ #
+ # Find Tail comment.
+ #
+ if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ TailComments = LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):]
+ LineContent = LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
+ if LineComment is None:
+ LineComment = InfLineCommentObject()
+ LineComment.SetTailComments(TailComments)
+
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((LineContent, LineNo),
+ FileName,
+ DT.MODEL_META_DATA_HEADER,
+ self.FileLocalMacros)
+ if Name is not None:
+ self.FileLocalMacros[Name] = Value
+ continue
+
+ #
+ # Replace with [Defines] section Macro
+ #
+ LineContent = InfExpandMacro(LineContent,
+ (FileName, LineContent, LineNo),
+ self.FileLocalMacros,
+ None, True)
+
+ SectionContent += LineContent + DT.END_OF_LINE
+
+ TokenList = GetSplitValueList(LineContent, DT.TAB_EQUAL_SPLIT, 1)
+ if len(TokenList) < 2:
+ ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE,
+ LineInfo=LineInfo)
+ _ValueList[0:len(TokenList)] = TokenList
+ if not _ValueList[0]:
+ ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_NAME,
+ LineInfo=LineInfo)
+ if not _ValueList[1]:
+ ErrorInInf(ST.ERR_INF_PARSER_DEFINE_ITEM_NO_VALUE,
+ LineInfo=LineInfo)
+
+ Name, Value = _ValueList[0], _ValueList[1]
+
+ InfDefMemberObj = InfDefMember(Name, Value)
+ if (LineComment is not None):
+ InfDefMemberObj.Comments.SetHeaderComments(LineComment.GetHeaderComments())
+ InfDefMemberObj.Comments.SetTailComments(LineComment.GetTailComments())
+
+ InfDefMemberObj.CurrentLine.SetFileName(self.FullPath)
+ InfDefMemberObj.CurrentLine.SetLineString(LineContent)
+ InfDefMemberObj.CurrentLine.SetLineNo(LineNo)
+
+ _ContentList.append(InfDefMemberObj)
+ HeaderComments = []
+ TailComments = ''
+
+ #
+ # Current Define section archs
+ #
+ if not ArchList:
+ ArchList = ['COMMON']
+
+ InfSectionObject.SetAllContent(SectionContent)
+
+ InfSectionObject.SetDefines(_ContentList, Arch=ArchList)
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py
new file mode 100755
index 00000000..86634b32
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfDepexSectionParser.py
@@ -0,0 +1,98 @@
+## @file
+# This file contained the parser for [Depex] sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+'''
+InfDepexSectionParser
+'''
+##
+# Import Modules
+#
+import re
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Parser.InfParserMisc import InfExpandMacro
+from Library import DataType as DT
+from Library.Misc import GetSplitValueList
+from Parser.InfParserMisc import InfParserSectionRoot
+
+class InfDepexSectionParser(InfParserSectionRoot):
+ ## InfDepexParser
+ #
+ # For now, only separate Depex String and comments.
+ # Have two types of section header.
+ # 1. [Depex.Arch.ModuleType, ...]
+ # 2. [Depex.Arch|FFE, ...]
+ #
+ def InfDepexParser(self, SectionString, InfSectionObject, FileName):
+ DepexContent = []
+ DepexComment = []
+ ValueList = []
+ #
+ # Parse section content
+ #
+ for Line in SectionString:
+ LineContent = Line[0]
+ LineNo = Line[1]
+
+ #
+ # Found comment
+ #
+ if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ DepexComment.append((LineContent, LineNo))
+ continue
+ #
+ # Replace with [Defines] section Macro
+ #
+ LineContent = InfExpandMacro(LineContent,
+ (FileName, LineContent, Line[1]),
+ self.FileLocalMacros,
+ None, True)
+
+ CommentCount = LineContent.find(DT.TAB_COMMENT_SPLIT)
+
+ if CommentCount > -1:
+ DepexComment.append((LineContent[CommentCount:], LineNo))
+ LineContent = LineContent[:CommentCount-1]
+
+
+ CommentCount = -1
+ DepexContent.append((LineContent, LineNo))
+
+ TokenList = GetSplitValueList(LineContent, DT.TAB_COMMENT_SPLIT)
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Current section archs
+ #
+ KeyList = []
+ LastItem = ''
+ for Item in self.LastSectionHeaderContent:
+ LastItem = Item
+ if (Item[1], Item[2], Item[3]) not in KeyList:
+ KeyList.append((Item[1], Item[2], Item[3]))
+
+ NewCommentList = []
+ FormatCommentLn = -1
+ ReFormatComment = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)
+ for CommentItem in DepexComment:
+ CommentContent = CommentItem[0]
+ if ReFormatComment.match(CommentContent) is not None:
+ FormatCommentLn = CommentItem[1] + 1
+ continue
+
+ if CommentItem[1] != FormatCommentLn:
+ NewCommentList.append(CommentContent)
+ else:
+ FormatCommentLn = CommentItem[1] + 1
+
+ if not InfSectionObject.SetDepex(DepexContent, KeyList = KeyList, CommentList = NewCommentList):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[Depex]"),
+ File=FileName,
+ Line=LastItem[3])
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py
new file mode 100755
index 00000000..2716f8d7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfGuidPpiProtocolSectionParser.py
@@ -0,0 +1,368 @@
+## @file
+# This file contained the parser for [Guids], [Ppis], [Protocols] sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+'''
+InfGuidPpiProtocolSectionParser
+'''
+##
+# Import Modules
+#
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Parser.InfParserMisc import InfExpandMacro
+from Library import DataType as DT
+from Library import GlobalData
+from Library.Parsing import MacroParser
+from Library.Misc import GetSplitValueList
+from Library.ParserValidate import IsValidIdString
+from Library.ParserValidate import IsValidUserId
+from Library.ParserValidate import IsValidArch
+from Parser.InfParserMisc import InfParserSectionRoot
+
+class InfGuidPpiProtocolSectionParser(InfParserSectionRoot):
+ ## InfGuidParser
+ #
+ #
+ def InfGuidParser(self, SectionString, InfSectionObject, FileName):
+ #
+ # Macro defined in this section
+ #
+ SectionMacros = {}
+ ValueList = []
+ GuidList = []
+ CommentsList = []
+ CurrentLineVar = None
+ #
+ # Parse section content
+ #
+ for Line in SectionString:
+ LineContent = Line[0]
+ LineNo = Line[1]
+
+ if LineContent.strip() == '':
+ CommentsList = []
+ continue
+
+ if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ CommentsList.append(Line)
+ continue
+ else:
+ #
+ # Encounter a GUID entry
+ #
+ if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ CommentsList.append((
+ LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
+ LineNo))
+ LineContent = \
+ LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
+
+ if LineContent != '':
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((LineContent, LineNo),
+ FileName,
+ DT.MODEL_EFI_GUID,
+ self.FileLocalMacros)
+ if Name is not None:
+ SectionMacros[Name] = Value
+ CommentsList = []
+ ValueList = []
+ continue
+
+ TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo),
+ self.FileLocalMacros, SectionMacros, True)
+ for Value in ValueList]
+
+ CurrentLineVar = (LineContent, LineNo, FileName)
+
+
+ if len(ValueList) >= 1:
+ GuidList.append((ValueList, CommentsList, CurrentLineVar))
+ CommentsList = []
+ ValueList = []
+ continue
+
+ #
+ # Current section archs
+ #
+ ArchList = []
+ LineIndex = -1
+ for Item in self.LastSectionHeaderContent:
+ LineIndex = Item[3]
+ if Item[1] not in ArchList:
+ ArchList.append(Item[1])
+
+ if not InfSectionObject.SetGuid(GuidList, Arch=ArchList):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Guid]"),
+ File=FileName,
+ Line=LineIndex)
+
+ ## InfPpiParser
+ #
+ #
+ def InfPpiParser(self, SectionString, InfSectionObject, FileName):
+ #
+ # Macro defined in this section
+ #
+ SectionMacros = {}
+ ValueList = []
+ PpiList = []
+ CommentsList = []
+ CurrentLineVar = None
+ #
+ # Parse section content
+ #
+ for Line in SectionString:
+ LineContent = Line[0]
+ LineNo = Line[1]
+
+ if LineContent.strip() == '':
+ CommentsList = []
+ continue
+
+ if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ CommentsList.append(Line)
+ continue
+ else:
+ #
+ # Encounter a PPI entry
+ #
+ if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ CommentsList.append((
+ LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
+ LineNo))
+ LineContent = \
+ LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
+
+ if LineContent != '':
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((LineContent, LineNo),
+ FileName,
+ DT.MODEL_EFI_PPI,
+ self.FileLocalMacros)
+ if Name is not None:
+ SectionMacros[Name] = Value
+ ValueList = []
+ CommentsList = []
+ continue
+
+ TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), self.FileLocalMacros, SectionMacros)
+ for Value in ValueList]
+
+ CurrentLineVar = (LineContent, LineNo, FileName)
+
+ if len(ValueList) >= 1:
+ PpiList.append((ValueList, CommentsList, CurrentLineVar))
+ ValueList = []
+ CommentsList = []
+ continue
+
+ #
+ # Current section archs
+ #
+ ArchList = []
+ LineIndex = -1
+ for Item in self.LastSectionHeaderContent:
+ LineIndex = Item[3]
+ if Item[1] not in ArchList:
+ ArchList.append(Item[1])
+
+ if not InfSectionObject.SetPpi(PpiList, Arch=ArchList):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Ppis]"),
+ File=FileName,
+ Line=LineIndex)
+
+ ## InfUserExtensionParser
+ #
+ #
+ def InfUserExtensionParser(self, SectionString, InfSectionObject, FileName):
+
+ UserExtensionContent = ''
+
+ #
+ # Parse section content
+ #
+ for Line in SectionString:
+ LineContent = Line[0]
+
+# Comment the code to support user extension without any statement just the section header in []
+# if LineContent.strip() == '':
+# continue
+
+ UserExtensionContent += LineContent + DT.END_OF_LINE
+ continue
+
+ #
+ # Current section UserId, IdString
+ #
+ IdContentList = []
+ LastItem = ''
+ SectionLineNo = None
+ for Item in self.LastSectionHeaderContent:
+ UserId = Item[1]
+ IdString = Item[2]
+ Arch = Item[3]
+ SectionLineNo = Item[4]
+ if not IsValidArch(Arch):
+ Logger.Error(
+ 'InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (Arch),
+ File=GlobalData.gINF_MODULE_NAME,
+ Line=SectionLineNo,
+ ExtraData=None)
+
+ if (UserId, IdString, Arch) not in IdContentList:
+ #
+ # To check the UserId and IdString valid or not.
+ #
+ if not IsValidUserId(UserId):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_UE_SECTION_USER_ID_ERROR % (Item[1]),
+ File=GlobalData.gINF_MODULE_NAME,
+ Line=SectionLineNo,
+ ExtraData=None)
+
+ if not IsValidIdString(IdString):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_UE_SECTION_ID_STRING_ERROR % (IdString),
+ File=GlobalData.gINF_MODULE_NAME, Line=SectionLineNo,
+ ExtraData=None)
+ IdContentList.append((UserId, IdString, Arch))
+ else:
+ #
+ # Each UserExtensions section header must have a unique set
+ # of UserId, IdString and Arch values.
+ # This means that the same UserId can be used in more than one
+ # section header, provided the IdString or Arch values are
+ # different. The same IdString values can be used in more than
+ # one section header if the UserId or Arch values are
+ # different. The same UserId and the same IdString can be used
+ # in a section header if the Arch values are different in each
+ # of the section headers.
+ #
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_UE_SECTION_DUPLICATE_ERROR % (
+ IdString),
+ File=GlobalData.gINF_MODULE_NAME,
+ Line=SectionLineNo,
+ ExtraData=None)
+ LastItem = Item
+
+ if not InfSectionObject.SetUserExtension(UserExtensionContent,
+ IdContent=IdContentList,
+ LineNo=SectionLineNo):
+ Logger.Error\
+ ('InfParser', FORMAT_INVALID, \
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[UserExtension]"), \
+ File=FileName, Line=LastItem[4])
+
+ def InfProtocolParser(self, SectionString, InfSectionObject, FileName):
+ #
+ # Macro defined in this section
+ #
+ SectionMacros = {}
+ ValueList = []
+ ProtocolList = []
+ CommentsList = []
+ CurrentLineVar = None
+ #
+ # Parse section content
+ #
+ for Line in SectionString:
+ LineContent = Line[0]
+ LineNo = Line[1]
+
+ if LineContent.strip() == '':
+ CommentsList = []
+ continue
+
+ if LineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ CommentsList.append(Line)
+ continue
+ else:
+ #
+ # Encounter a Protocol entry
+ #
+ if LineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ CommentsList.append((
+ LineContent[LineContent.find(DT.TAB_COMMENT_SPLIT):],
+ LineNo))
+ LineContent = \
+ LineContent[:LineContent.find(DT.TAB_COMMENT_SPLIT)]
+
+ if LineContent != '':
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((LineContent, LineNo),
+ FileName,
+ DT.MODEL_EFI_PROTOCOL,
+ self.FileLocalMacros)
+ if Name is not None:
+ SectionMacros[Name] = Value
+ ValueList = []
+ CommentsList = []
+ continue
+
+ TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT, 1)
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ ValueList = [InfExpandMacro(Value, (FileName, LineContent, LineNo), self.FileLocalMacros, SectionMacros)
+ for Value in ValueList]
+
+ CurrentLineVar = (LineContent, LineNo, FileName)
+
+ if len(ValueList) >= 1:
+ ProtocolList.append((ValueList, CommentsList, CurrentLineVar))
+ ValueList = []
+ CommentsList = []
+ continue
+
+ #
+ # Current section archs
+ #
+ ArchList = []
+ LineIndex = -1
+ for Item in self.LastSectionHeaderContent:
+ LineIndex = Item[3]
+ if Item[1] not in ArchList:
+ ArchList.append(Item[1])
+
+ if not InfSectionObject.SetProtocol(ProtocolList, Arch=ArchList):
+ Logger.Error\
+ ('InfParser', FORMAT_INVALID, \
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Protocol]"), \
+ File=FileName, Line=LineIndex)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py
new file mode 100755
index 00000000..66fae2af
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfLibrarySectionParser.py
@@ -0,0 +1,197 @@
+## @file
+# This file contained the parser for [Libraries] sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+'''
+InfLibrarySectionParser
+'''
+##
+# Import Modules
+#
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Parser.InfParserMisc import InfExpandMacro
+from Library import DataType as DT
+from Library.Parsing import MacroParser
+from Library.Misc import GetSplitValueList
+from Object.Parser.InfCommonObject import InfLineCommentObject
+from Library import GlobalData
+from Parser.InfParserMisc import IsLibInstanceInfo
+from Parser.InfAsBuiltProcess import GetLibInstanceInfo
+from Parser.InfParserMisc import InfParserSectionRoot
+
+class InfLibrarySectionParser(InfParserSectionRoot):
+ ## InfLibraryParser
+ #
+ #
+ def InfLibraryParser(self, SectionString, InfSectionObject, FileName):
+ #
+ # For Common INF file
+ #
+ if not GlobalData.gIS_BINARY_INF:
+ #
+ # Macro defined in this section
+ #
+ SectionMacros = {}
+ ValueList = []
+ LibraryList = []
+ LibStillCommentFalg = False
+ LibHeaderComments = []
+ LibLineComment = None
+ #
+ # Parse section content
+ #
+ for Line in SectionString:
+ LibLineContent = Line[0]
+ LibLineNo = Line[1]
+
+ if LibLineContent.strip() == '':
+ continue
+
+ #
+ # Found Header Comments
+ #
+ if LibLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ #
+ # Last line is comments, and this line go on.
+ #
+ if LibStillCommentFalg:
+ LibHeaderComments.append(Line)
+ continue
+ #
+ # First time encounter comment
+ #
+ else:
+ #
+ # Clear original data
+ #
+ LibHeaderComments = []
+ LibHeaderComments.append(Line)
+ LibStillCommentFalg = True
+ continue
+ else:
+ LibStillCommentFalg = False
+
+ if len(LibHeaderComments) >= 1:
+ LibLineComment = InfLineCommentObject()
+ LineCommentContent = ''
+ for Item in LibHeaderComments:
+ LineCommentContent += Item[0] + DT.END_OF_LINE
+ LibLineComment.SetHeaderComments(LineCommentContent)
+
+ #
+ # Find Tail comment.
+ #
+ if LibLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ LibTailComments = LibLineContent[LibLineContent.find(DT.TAB_COMMENT_SPLIT):]
+ LibLineContent = LibLineContent[:LibLineContent.find(DT.TAB_COMMENT_SPLIT)]
+ if LibLineComment is None:
+ LibLineComment = InfLineCommentObject()
+ LibLineComment.SetTailComments(LibTailComments)
+
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((LibLineContent, LibLineNo),
+ FileName,
+ DT.MODEL_EFI_LIBRARY_CLASS,
+ self.FileLocalMacros)
+ if Name is not None:
+ SectionMacros[Name] = Value
+ LibLineComment = None
+ LibHeaderComments = []
+ continue
+
+ TokenList = GetSplitValueList(LibLineContent, DT.TAB_VALUE_SPLIT, 1)
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ ValueList = [InfExpandMacro(Value, (FileName, LibLineContent, LibLineNo),
+ self.FileLocalMacros, SectionMacros, True)
+ for Value in ValueList]
+
+ LibraryList.append((ValueList, LibLineComment,
+ (LibLineContent, LibLineNo, FileName)))
+ ValueList = []
+ LibLineComment = None
+ LibTailComments = ''
+ LibHeaderComments = []
+
+ continue
+
+ #
+ # Current section archs
+ #
+ KeyList = []
+ for Item in self.LastSectionHeaderContent:
+ if (Item[1], Item[2]) not in KeyList:
+ KeyList.append((Item[1], Item[2]))
+
+ if not InfSectionObject.SetLibraryClasses(LibraryList, KeyList=KeyList):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Library]"),
+ File=FileName,
+ Line=Item[3])
+ #
+ # For Binary INF
+ #
+ else:
+ self.InfAsBuiltLibraryParser(SectionString, InfSectionObject, FileName)
+
+ def InfAsBuiltLibraryParser(self, SectionString, InfSectionObject, FileName):
+ LibraryList = []
+ LibInsFlag = False
+ for Line in SectionString:
+ LineContent = Line[0]
+ LineNo = Line[1]
+
+ if LineContent.strip() == '':
+ LibInsFlag = False
+ continue
+
+ if not LineContent.strip().startswith("#"):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_LIB_CONTATIN_ASBUILD_AND_COMMON,
+ File=FileName,
+ Line=LineNo,
+ ExtraData=LineContent)
+
+ if IsLibInstanceInfo(LineContent):
+ LibInsFlag = True
+ continue
+
+ if LibInsFlag:
+ LibGuid, LibVer = GetLibInstanceInfo(LineContent, GlobalData.gWORKSPACE, LineNo, FileName)
+ #
+ # If the VERSION_STRING is missing from the INF file, tool should default to "0".
+ #
+ if LibVer == '':
+ LibVer = '0'
+ if LibGuid != '':
+ if (LibGuid, LibVer) not in LibraryList:
+ LibraryList.append((LibGuid, LibVer))
+
+ #
+ # Current section archs
+ #
+ KeyList = []
+ Item = ['', '', '']
+ for Item in self.LastSectionHeaderContent:
+ if (Item[1], Item[2]) not in KeyList:
+ KeyList.append((Item[1], Item[2]))
+
+ if not InfSectionObject.SetLibraryClasses(LibraryList, KeyList=KeyList):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Library]"),
+ File=FileName,
+ Line=Item[3])
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py
new file mode 100755
index 00000000..bb6777e8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPackageSectionParser.py
@@ -0,0 +1,134 @@
+## @file
+# This file contained the parser for [Packages] sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+'''
+InfPackageSectionParser
+'''
+##
+# Import Modules
+#
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Parser.InfParserMisc import InfExpandMacro
+from Library import DataType as DT
+from Library.Parsing import MacroParser
+from Library.Misc import GetSplitValueList
+from Object.Parser.InfCommonObject import InfLineCommentObject
+from Parser.InfParserMisc import InfParserSectionRoot
+
+class InfPackageSectionParser(InfParserSectionRoot):
+ ## InfPackageParser
+ #
+ #
+ def InfPackageParser(self, SectionString, InfSectionObject, FileName):
+ #
+ # Macro defined in this section
+ #
+ SectionMacros = {}
+ ValueList = []
+ PackageList = []
+ StillCommentFalg = False
+ HeaderComments = []
+ LineComment = None
+ #
+ # Parse section content
+ #
+ for Line in SectionString:
+ PkgLineContent = Line[0]
+ PkgLineNo = Line[1]
+
+ if PkgLineContent.strip() == '':
+ continue
+
+ #
+ # Find Header Comments
+ #
+ if PkgLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ #
+ # Last line is comments, and this line go on.
+ #
+ if StillCommentFalg:
+ HeaderComments.append(Line)
+ continue
+ #
+ # First time encounter comment
+ #
+ else:
+ #
+ # Clear original data
+ #
+ HeaderComments = []
+ HeaderComments.append(Line)
+ StillCommentFalg = True
+ continue
+ else:
+ StillCommentFalg = False
+
+ if len(HeaderComments) >= 1:
+ LineComment = InfLineCommentObject()
+ LineCommentContent = ''
+ for Item in HeaderComments:
+ LineCommentContent += Item[0] + DT.END_OF_LINE
+ LineComment.SetHeaderComments(LineCommentContent)
+
+ #
+ # Find Tail comment.
+ #
+ if PkgLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ TailComments = PkgLineContent[PkgLineContent.find(DT.TAB_COMMENT_SPLIT):]
+ PkgLineContent = PkgLineContent[:PkgLineContent.find(DT.TAB_COMMENT_SPLIT)]
+ if LineComment is None:
+ LineComment = InfLineCommentObject()
+ LineComment.SetTailComments(TailComments)
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((PkgLineContent, PkgLineNo),
+ FileName,
+ DT.MODEL_META_DATA_PACKAGE,
+ self.FileLocalMacros)
+ if Name is not None:
+ SectionMacros[Name] = Value
+ LineComment = None
+ HeaderComments = []
+ continue
+
+ TokenList = GetSplitValueList(PkgLineContent, DT.TAB_VALUE_SPLIT, 1)
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ ValueList = [InfExpandMacro(Value, (FileName, PkgLineContent, PkgLineNo),
+ self.FileLocalMacros, SectionMacros, True)
+ for Value in ValueList]
+
+ PackageList.append((ValueList, LineComment,
+ (PkgLineContent, PkgLineNo, FileName)))
+ ValueList = []
+ LineComment = None
+ TailComments = ''
+ HeaderComments = []
+ continue
+
+ #
+ # Current section archs
+ #
+ ArchList = []
+ for Item in self.LastSectionHeaderContent:
+ if Item[1] not in ArchList:
+ ArchList.append(Item[1])
+
+ if not InfSectionObject.SetPackages(PackageList, Arch = ArchList):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR\
+ %("[Packages]"),
+ File=FileName,
+ Line=Item[3])
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py
new file mode 100755
index 00000000..711b5e85
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParser.py
@@ -0,0 +1,680 @@
+## @file
+# This file contained the parser for INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+'''
+InfParser
+'''
+
+##
+# Import Modules
+#
+import re
+import os
+from copy import deepcopy
+
+from Library.StringUtils import GetSplitValueList
+from Library.StringUtils import ConvertSpecialChar
+from Library.Misc import ProcessLineExtender
+from Library.Misc import ProcessEdkComment
+from Library.Parsing import NormPath
+from Library.ParserValidate import IsValidInfMoudleTypeList
+from Library.ParserValidate import IsValidArch
+from Library import DataType as DT
+from Library import GlobalData
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Logger.ToolError import FILE_READ_FAILURE
+from Logger.ToolError import PARSER_ERROR
+
+from Object.Parser.InfCommonObject import InfSectionCommonDef
+from Parser.InfSectionParser import InfSectionParser
+from Parser.InfParserMisc import gINF_SECTION_DEF
+from Parser.InfParserMisc import IsBinaryInf
+
+## OpenInfFile
+#
+#
+def OpenInfFile(Filename):
+ FileLinesList = []
+
+ try:
+ FInputfile = open(Filename, "r")
+ try:
+ FileLinesList = FInputfile.readlines()
+ except BaseException:
+ Logger.Error("InfParser",
+ FILE_READ_FAILURE,
+ ST.ERR_FILE_OPEN_FAILURE,
+ File=Filename)
+ finally:
+ FInputfile.close()
+ except BaseException:
+ Logger.Error("InfParser",
+ FILE_READ_FAILURE,
+ ST.ERR_FILE_OPEN_FAILURE,
+ File=Filename)
+
+ return FileLinesList
+
+## InfParser
+#
+# This class defined the structure used in InfParser object
+#
+# @param InfObject: Inherited from InfSectionParser class
+# @param Filename: Input value for Filename of INF file, default is
+# None
+# @param WorkspaceDir: Input value for current workspace directory,
+# default is None
+#
+class InfParser(InfSectionParser):
+
+ def __init__(self, Filename = None, WorkspaceDir = None):
+
+ #
+ # Call parent class construct function
+ #
+ InfSectionParser.__init__()
+
+ self.WorkspaceDir = WorkspaceDir
+ self.SupArchList = DT.ARCH_LIST
+ self.EventList = []
+ self.HobList = []
+ self.BootModeList = []
+
+ #
+ # Load Inf file if filename is not None
+ #
+ if Filename is not None:
+ self.ParseInfFile(Filename)
+
+ ## Parse INF file
+ #
+ # Parse the file if it exists
+ #
+ # @param Filename: Input value for filename of INF file
+ #
+ def ParseInfFile(self, Filename):
+
+ Filename = NormPath(Filename)
+ (Path, Name) = os.path.split(Filename)
+ self.FullPath = Filename
+ self.RelaPath = Path
+ self.FileName = Name
+ GlobalData.gINF_MODULE_DIR = Path
+ GlobalData.gINF_MODULE_NAME = self.FullPath
+ GlobalData.gIS_BINARY_INF = False
+ #
+ # Initialize common data
+ #
+ LineNo = 0
+ CurrentSection = DT.MODEL_UNKNOWN
+ SectionLines = []
+
+ #
+ # Flags
+ #
+ HeaderCommentStart = False
+ HeaderCommentEnd = False
+ HeaderStarLineNo = -1
+ BinaryHeaderCommentStart = False
+ BinaryHeaderCommentEnd = False
+ BinaryHeaderStarLineNo = -1
+
+ #
+ # While Section ends. parse whole section contents.
+ #
+ NewSectionStartFlag = False
+ FirstSectionStartFlag = False
+
+ #
+ # Parse file content
+ #
+ CommentBlock = []
+
+ #
+ # Variables for Event/Hob/BootMode
+ #
+ self.EventList = []
+ self.HobList = []
+ self.BootModeList = []
+ SectionType = ''
+
+ FileLinesList = OpenInfFile (Filename)
+
+ #
+ # One INF file can only has one [Defines] section.
+ #
+ DefineSectionParsedFlag = False
+
+ #
+ # Convert special characters in lines to space character.
+ #
+ FileLinesList = ConvertSpecialChar(FileLinesList)
+
+ #
+ # Process Line Extender
+ #
+ FileLinesList = ProcessLineExtender(FileLinesList)
+
+ #
+ # Process EdkI INF style comment if found
+ #
+ OrigLines = [Line for Line in FileLinesList]
+ FileLinesList, EdkCommentStartPos = ProcessEdkComment(FileLinesList)
+
+ #
+ # Judge whether the INF file is Binary INF or not
+ #
+ if IsBinaryInf(FileLinesList):
+ GlobalData.gIS_BINARY_INF = True
+
+ InfSectionCommonDefObj = None
+
+ for Line in FileLinesList:
+ LineNo = LineNo + 1
+ Line = Line.strip()
+ if (LineNo < len(FileLinesList) - 1):
+ NextLine = FileLinesList[LineNo].strip()
+
+ #
+ # blank line
+ #
+ if (Line == '' or not Line) and LineNo == len(FileLinesList):
+ LastSectionFalg = True
+
+ #
+ # check whether file header comment section started
+ #
+ if Line.startswith(DT.TAB_SPECIAL_COMMENT) and \
+ (Line.find(DT.TAB_HEADER_COMMENT) > -1) and \
+ not HeaderCommentStart and not HeaderCommentEnd:
+
+ CurrentSection = DT.MODEL_META_DATA_FILE_HEADER
+ #
+ # Append the first line to section lines.
+ #
+ HeaderStarLineNo = LineNo
+ SectionLines.append((Line, LineNo))
+ HeaderCommentStart = True
+ continue
+
+ #
+ # Collect Header content.
+ #
+ if (Line.startswith(DT.TAB_COMMENT_SPLIT) and CurrentSection == DT.MODEL_META_DATA_FILE_HEADER) and\
+ HeaderCommentStart and not Line.startswith(DT.TAB_SPECIAL_COMMENT) and not\
+ HeaderCommentEnd and NextLine != '':
+ SectionLines.append((Line, LineNo))
+ continue
+ #
+ # Header content end
+ #
+ if (Line.startswith(DT.TAB_SPECIAL_COMMENT) or not Line.strip().startswith("#")) and HeaderCommentStart \
+ and not HeaderCommentEnd:
+ HeaderCommentEnd = True
+ BinaryHeaderCommentStart = False
+ BinaryHeaderCommentEnd = False
+ HeaderCommentStart = False
+ if Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1:
+ self.InfHeaderParser(SectionLines, self.InfHeader, self.FileName)
+ SectionLines = []
+ else:
+ SectionLines.append((Line, LineNo))
+ #
+ # Call Header comment parser.
+ #
+ self.InfHeaderParser(SectionLines, self.InfHeader, self.FileName)
+ SectionLines = []
+ continue
+
+ #
+ # check whether binary header comment section started
+ #
+ if Line.startswith(DT.TAB_SPECIAL_COMMENT) and \
+ (Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1) and \
+ not BinaryHeaderCommentStart:
+ SectionLines = []
+ CurrentSection = DT.MODEL_META_DATA_FILE_HEADER
+ #
+ # Append the first line to section lines.
+ #
+ BinaryHeaderStarLineNo = LineNo
+ SectionLines.append((Line, LineNo))
+ BinaryHeaderCommentStart = True
+ HeaderCommentEnd = True
+ continue
+
+ #
+ # check whether there are more than one binary header exist
+ #
+ if Line.startswith(DT.TAB_SPECIAL_COMMENT) and BinaryHeaderCommentStart and \
+ not BinaryHeaderCommentEnd and (Line.find(DT.TAB_BINARY_HEADER_COMMENT) > -1):
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_MULTIPLE_BINARYHEADER_EXIST,
+ File=Filename)
+
+ #
+ # Collect Binary Header content.
+ #
+ if (Line.startswith(DT.TAB_COMMENT_SPLIT) and CurrentSection == DT.MODEL_META_DATA_FILE_HEADER) and\
+ BinaryHeaderCommentStart and not Line.startswith(DT.TAB_SPECIAL_COMMENT) and not\
+ BinaryHeaderCommentEnd and NextLine != '':
+ SectionLines.append((Line, LineNo))
+ continue
+ #
+ # Binary Header content end
+ #
+ if (Line.startswith(DT.TAB_SPECIAL_COMMENT) or not Line.strip().startswith(DT.TAB_COMMENT_SPLIT)) and \
+ BinaryHeaderCommentStart and not BinaryHeaderCommentEnd:
+ SectionLines.append((Line, LineNo))
+ BinaryHeaderCommentStart = False
+ #
+ # Call Binary Header comment parser.
+ #
+ self.InfHeaderParser(SectionLines, self.InfBinaryHeader, self.FileName, True)
+ SectionLines = []
+ BinaryHeaderCommentEnd = True
+ continue
+ #
+ # Find a new section tab
+ # Or at the last line of INF file,
+ # need to process the last section.
+ #
+ LastSectionFalg = False
+ if LineNo == len(FileLinesList):
+ LastSectionFalg = True
+
+ if Line.startswith(DT.TAB_COMMENT_SPLIT) and not Line.startswith(DT.TAB_SPECIAL_COMMENT):
+ SectionLines.append((Line, LineNo))
+ if not LastSectionFalg:
+ continue
+
+ #
+ # Encountered a section. start with '[' and end with ']'
+ #
+ if (Line.startswith(DT.TAB_SECTION_START) and \
+ Line.find(DT.TAB_SECTION_END) > -1) or LastSectionFalg:
+
+ HeaderCommentEnd = True
+ BinaryHeaderCommentEnd = True
+
+ if not LastSectionFalg:
+ #
+ # check to prevent '#' inside section header
+ #
+ HeaderContent = Line[1:Line.find(DT.TAB_SECTION_END)]
+ if HeaderContent.find(DT.TAB_COMMENT_SPLIT) != -1:
+ Logger.Error("InfParser",
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID,
+ File=self.FullPath,
+ Line=LineNo,
+ ExtraData=Line)
+
+ #
+ # Keep last time section header content for section parser
+ # usage.
+ #
+ self.LastSectionHeaderContent = deepcopy(self.SectionHeaderContent)
+
+ #
+ # TailComments in section define.
+ #
+ TailComments = ''
+ CommentIndex = Line.find(DT.TAB_COMMENT_SPLIT)
+ if CommentIndex > -1:
+ TailComments = Line[CommentIndex:]
+ Line = Line[:CommentIndex]
+
+ InfSectionCommonDefObj = InfSectionCommonDef()
+ if TailComments != '':
+ InfSectionCommonDefObj.SetTailComments(TailComments)
+ if CommentBlock != '':
+ InfSectionCommonDefObj.SetHeaderComments(CommentBlock)
+ CommentBlock = []
+ #
+ # Call section parser before section header parer to avoid encounter EDKI INF file
+ #
+ if CurrentSection == DT.MODEL_META_DATA_DEFINE:
+ DefineSectionParsedFlag = self._CallSectionParsers(CurrentSection,
+ DefineSectionParsedFlag, SectionLines,
+ InfSectionCommonDefObj, LineNo)
+ #
+ # Compare the new section name with current
+ #
+ self.SectionHeaderParser(Line, self.FileName, LineNo)
+
+ self._CheckSectionHeaders(Line, LineNo)
+
+ SectionType = _ConvertSecNameToType(self.SectionHeaderContent[0][0])
+
+ if not FirstSectionStartFlag:
+ CurrentSection = SectionType
+ FirstSectionStartFlag = True
+ else:
+ NewSectionStartFlag = True
+ else:
+ SectionLines.append((Line, LineNo))
+ continue
+
+ if LastSectionFalg:
+ SectionLines, CurrentSection = self._ProcessLastSection(SectionLines, Line, LineNo, CurrentSection)
+
+ #
+ # End of section content collect.
+ # Parser the section content collected previously.
+ #
+ if NewSectionStartFlag or LastSectionFalg:
+ if CurrentSection != DT.MODEL_META_DATA_DEFINE or \
+ (LastSectionFalg and CurrentSection == DT.MODEL_META_DATA_DEFINE):
+ DefineSectionParsedFlag = self._CallSectionParsers(CurrentSection,
+ DefineSectionParsedFlag, SectionLines,
+ InfSectionCommonDefObj, LineNo)
+
+ CurrentSection = SectionType
+ #
+ # Clear section lines
+ #
+ SectionLines = []
+
+ if HeaderStarLineNo == -1:
+ Logger.Error("InfParser",
+ FORMAT_INVALID,
+ ST.ERR_NO_SOURCE_HEADER,
+ File=self.FullPath)
+ if BinaryHeaderStarLineNo > -1 and HeaderStarLineNo > -1 and HeaderStarLineNo > BinaryHeaderStarLineNo:
+ Logger.Error("InfParser",
+ FORMAT_INVALID,
+ ST.ERR_BINARY_HEADER_ORDER,
+ File=self.FullPath)
+ #
+ # EDKII INF should not have EDKI style comment
+ #
+ if EdkCommentStartPos != -1:
+ Logger.Error("InfParser",
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_EDKI_COMMENT_IN_EDKII,
+ File=self.FullPath,
+ Line=EdkCommentStartPos + 1,
+ ExtraData=OrigLines[EdkCommentStartPos])
+
+ #
+ # extract [Event] [Hob] [BootMode] sections
+ #
+ self._ExtractEventHobBootMod(FileLinesList)
+
+ ## _CheckSectionHeaders
+ #
+ #
+ def _CheckSectionHeaders(self, Line, LineNo):
+ if len(self.SectionHeaderContent) == 0:
+ Logger.Error("InfParser",
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_DEFINE_SECTION_HEADER_INVALID,
+ File=self.FullPath,
+ Line=LineNo, ExtraData=Line)
+ else:
+ for SectionItem in self.SectionHeaderContent:
+ ArchList = []
+ #
+ # Not cover Depex/UserExtension section header
+ # check.
+ #
+ if SectionItem[0].strip().upper() == DT.TAB_INF_FIXED_PCD.upper() or \
+ SectionItem[0].strip().upper() == DT.TAB_INF_PATCH_PCD.upper() or \
+ SectionItem[0].strip().upper() == DT.TAB_INF_PCD_EX.upper() or \
+ SectionItem[0].strip().upper() == DT.TAB_INF_PCD.upper() or \
+ SectionItem[0].strip().upper() == DT.TAB_INF_FEATURE_PCD.upper():
+ ArchList = GetSplitValueList(SectionItem[1].strip(), ' ')
+ else:
+ ArchList = [SectionItem[1].strip()]
+
+ for Arch in ArchList:
+ if (not IsValidArch(Arch)) and \
+ (SectionItem[0].strip().upper() != DT.TAB_DEPEX.upper()) and \
+ (SectionItem[0].strip().upper() != DT.TAB_USER_EXTENSIONS.upper()) and \
+ (SectionItem[0].strip().upper() != DT.TAB_COMMON_DEFINES.upper()):
+ Logger.Error("InfParser",
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(SectionItem[1]),
+ File=self.FullPath,
+ Line=LineNo, ExtraData=Line)
+ #
+ # Check if the ModuleType is valid
+ #
+ ChkModSectionList = ['LIBRARYCLASSES']
+ if (self.SectionHeaderContent[0][0].upper() in ChkModSectionList):
+ if SectionItem[2].strip().upper():
+ MoudleTypeList = GetSplitValueList(
+ SectionItem[2].strip().upper())
+ if (not IsValidInfMoudleTypeList(MoudleTypeList)):
+ Logger.Error("InfParser",
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID%(SectionItem[2]),
+ File=self.FullPath, Line=LineNo,
+ ExtraData=Line)
+
+ ## _CallSectionParsers
+ #
+ #
+ def _CallSectionParsers(self, CurrentSection, DefineSectionParsedFlag,
+ SectionLines, InfSectionCommonDefObj, LineNo):
+ if CurrentSection == DT.MODEL_META_DATA_DEFINE:
+ if not DefineSectionParsedFlag:
+ self.InfDefineParser(SectionLines,
+ self.InfDefSection,
+ self.FullPath,
+ InfSectionCommonDefObj)
+ DefineSectionParsedFlag = True
+ else:
+ Logger.Error("Parser",
+ PARSER_ERROR,
+ ST.ERR_INF_PARSER_MULTI_DEFINE_SECTION,
+ File=self.FullPath,
+ RaiseError = Logger.IS_RAISE_ERROR)
+
+ elif CurrentSection == DT.MODEL_META_DATA_BUILD_OPTION:
+ self.InfBuildOptionParser(SectionLines,
+ self.InfBuildOptionSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_EFI_LIBRARY_CLASS:
+ self.InfLibraryParser(SectionLines,
+ self.InfLibraryClassSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_META_DATA_PACKAGE:
+ self.InfPackageParser(SectionLines,
+ self.InfPackageSection,
+ self.FullPath)
+ #
+ # [Pcd] Sections, put it together
+ #
+ elif CurrentSection == DT.MODEL_PCD_FIXED_AT_BUILD or \
+ CurrentSection == DT.MODEL_PCD_PATCHABLE_IN_MODULE or \
+ CurrentSection == DT.MODEL_PCD_FEATURE_FLAG or \
+ CurrentSection == DT.MODEL_PCD_DYNAMIC_EX or \
+ CurrentSection == DT.MODEL_PCD_DYNAMIC:
+ self.InfPcdParser(SectionLines,
+ self.InfPcdSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_EFI_SOURCE_FILE:
+ self.InfSourceParser(SectionLines,
+ self.InfSourcesSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_META_DATA_USER_EXTENSION:
+ self.InfUserExtensionParser(SectionLines,
+ self.InfUserExtensionSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_EFI_PROTOCOL:
+ self.InfProtocolParser(SectionLines,
+ self.InfProtocolSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_EFI_PPI:
+ self.InfPpiParser(SectionLines,
+ self.InfPpiSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_EFI_GUID:
+ self.InfGuidParser(SectionLines,
+ self.InfGuidSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_EFI_DEPEX:
+ self.InfDepexParser(SectionLines,
+ self.InfDepexSection,
+ self.FullPath)
+
+ elif CurrentSection == DT.MODEL_EFI_BINARY_FILE:
+ self.InfBinaryParser(SectionLines,
+ self.InfBinariesSection,
+ self.FullPath)
+ #
+ # Unknown section type found, raise error.
+ #
+ else:
+ if len(self.SectionHeaderContent) >= 1:
+ Logger.Error("Parser",
+ PARSER_ERROR,
+ ST.ERR_INF_PARSER_UNKNOWN_SECTION,
+ File=self.FullPath, Line=LineNo,
+ RaiseError = Logger.IS_RAISE_ERROR)
+ else:
+ Logger.Error("Parser",
+ PARSER_ERROR,
+ ST.ERR_INF_PARSER_NO_SECTION_ERROR,
+ File=self.FullPath, Line=LineNo,
+ RaiseError = Logger.IS_RAISE_ERROR)
+
+ return DefineSectionParsedFlag
+
+ def _ExtractEventHobBootMod(self, FileLinesList):
+ SpecialSectionStart = False
+ CheckLocation = False
+ GFindSpecialCommentRe = \
+ re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)
+ GFindNewSectionRe2 = \
+ re.compile(r"""#?(\s*)\[(.*?)\](.*)""", re.DOTALL)
+ LineNum = 0
+ Element = []
+ for Line in FileLinesList:
+ Line = Line.strip()
+ LineNum += 1
+ MatchObject = GFindSpecialCommentRe.search(Line)
+ if MatchObject:
+ SpecialSectionStart = True
+ Element = []
+ if MatchObject.group(1).upper().startswith("EVENT"):
+ List = self.EventList
+ elif MatchObject.group(1).upper().startswith("HOB"):
+ List = self.HobList
+ elif MatchObject.group(1).upper().startswith("BOOTMODE"):
+ List = self.BootModeList
+ else:
+ SpecialSectionStart = False
+ CheckLocation = False
+ if SpecialSectionStart:
+ Element.append([Line, LineNum])
+ List.append(Element)
+ else:
+ #
+ # if currently in special section, try to detect end of current section
+ #
+ MatchObject = GFindNewSectionRe2.search(Line)
+ if SpecialSectionStart:
+ if MatchObject:
+ SpecialSectionStart = False
+ CheckLocation = False
+ Element = []
+ elif not Line:
+ SpecialSectionStart = False
+ CheckLocation = True
+ Element = []
+ else:
+ if not Line.startswith(DT.TAB_COMMENT_SPLIT):
+ Logger.Warn("Parser",
+ ST.WARN_SPECIAL_SECTION_LOCATION_WRONG,
+ File=self.FullPath, Line=LineNum)
+ SpecialSectionStart = False
+ CheckLocation = False
+ Element = []
+ else:
+ Element.append([Line, LineNum])
+ else:
+ if CheckLocation:
+ if MatchObject:
+ CheckLocation = False
+ elif Line:
+ Logger.Warn("Parser",
+ ST.WARN_SPECIAL_SECTION_LOCATION_WRONG,
+ File=self.FullPath, Line=LineNum)
+ CheckLocation = False
+
+ if len(self.BootModeList) >= 1:
+ self.InfSpecialCommentParser(self.BootModeList,
+ self.InfSpecialCommentSection,
+ self.FileName,
+ DT.TYPE_BOOTMODE_SECTION)
+
+ if len(self.EventList) >= 1:
+ self.InfSpecialCommentParser(self.EventList,
+ self.InfSpecialCommentSection,
+ self.FileName,
+ DT.TYPE_EVENT_SECTION)
+
+ if len(self.HobList) >= 1:
+ self.InfSpecialCommentParser(self.HobList,
+ self.InfSpecialCommentSection,
+ self.FileName,
+ DT.TYPE_HOB_SECTION)
+ ## _ProcessLastSection
+ #
+ #
+ def _ProcessLastSection(self, SectionLines, Line, LineNo, CurrentSection):
+ #
+ # The last line is a section header. will discard it.
+ #
+ if not (Line.startswith(DT.TAB_SECTION_START) and Line.find(DT.TAB_SECTION_END) > -1):
+ SectionLines.append((Line, LineNo))
+
+ if len(self.SectionHeaderContent) >= 1:
+ TemSectionName = self.SectionHeaderContent[0][0].upper()
+ if TemSectionName.upper() not in gINF_SECTION_DEF.keys():
+ Logger.Error("InfParser",
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_UNKNOWN_SECTION,
+ File=self.FullPath,
+ Line=LineNo,
+ ExtraData=Line,
+ RaiseError = Logger.IS_RAISE_ERROR
+ )
+ else:
+ CurrentSection = gINF_SECTION_DEF[TemSectionName]
+ self.LastSectionHeaderContent = self.SectionHeaderContent
+
+ return SectionLines, CurrentSection
+
+## _ConvertSecNameToType
+#
+#
+def _ConvertSecNameToType(SectionName):
+ SectionType = ''
+ if SectionName.upper() not in gINF_SECTION_DEF.keys():
+ SectionType = DT.MODEL_UNKNOWN
+ else:
+ SectionType = gINF_SECTION_DEF[SectionName.upper()]
+
+ return SectionType
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py
new file mode 100755
index 00000000..0a51ac28
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfParserMisc.py
@@ -0,0 +1,216 @@
+## @file
+# This file contained the miscellaneous functions for INF parser
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+'''
+InfParserMisc
+'''
+
+##
+# Import Modules
+#
+import re
+
+
+from Library import DataType as DT
+
+
+from Library.StringUtils import gMACRO_PATTERN
+from Library.StringUtils import ReplaceMacro
+from Object.Parser.InfMisc import ErrorInInf
+from Logger.StringTable import ERR_MARCO_DEFINITION_MISS_ERROR
+
+#
+# Global variable
+#
+
+#
+# Sections can exist in INF file
+#
+gINF_SECTION_DEF = {
+ DT.TAB_UNKNOWN.upper() : DT.MODEL_UNKNOWN,
+ DT.TAB_HEADER.upper() : DT.MODEL_META_DATA_FILE_HEADER,
+ DT.TAB_INF_DEFINES.upper() : DT.MODEL_META_DATA_DEFINE,
+ DT.TAB_BUILD_OPTIONS.upper() : DT.MODEL_META_DATA_BUILD_OPTION,
+ DT.TAB_LIBRARY_CLASSES.upper() : DT.MODEL_EFI_LIBRARY_CLASS,
+ DT.TAB_PACKAGES.upper() : DT.MODEL_META_DATA_PACKAGE,
+ DT.TAB_INF_FIXED_PCD.upper() : DT.MODEL_PCD_FIXED_AT_BUILD,
+ DT.TAB_INF_PATCH_PCD.upper() : DT.MODEL_PCD_PATCHABLE_IN_MODULE,
+ DT.TAB_INF_FEATURE_PCD.upper() : DT.MODEL_PCD_FEATURE_FLAG,
+ DT.TAB_INF_PCD_EX.upper() : DT.MODEL_PCD_DYNAMIC_EX,
+ DT.TAB_INF_PCD.upper() : DT.MODEL_PCD_DYNAMIC,
+ DT.TAB_SOURCES.upper() : DT.MODEL_EFI_SOURCE_FILE,
+ DT.TAB_GUIDS.upper() : DT.MODEL_EFI_GUID,
+ DT.TAB_PROTOCOLS.upper() : DT.MODEL_EFI_PROTOCOL,
+ DT.TAB_PPIS.upper() : DT.MODEL_EFI_PPI,
+ DT.TAB_DEPEX.upper() : DT.MODEL_EFI_DEPEX,
+ DT.TAB_BINARIES.upper() : DT.MODEL_EFI_BINARY_FILE,
+ DT.TAB_USER_EXTENSIONS.upper() : DT.MODEL_META_DATA_USER_EXTENSION
+ #
+ # EDK1 section
+ # TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE
+ #
+ }
+
+## InfExpandMacro
+#
+# Expand MACRO definition with MACROs defined in [Defines] section and specific section.
+# The MACROs defined in specific section has high priority and will be expanded firstly.
+#
+# @param LineInfo Contain information of FileName, LineContent, LineNo
+# @param GlobalMacros MACROs defined in INF [Defines] section
+# @param SectionMacros MACROs defined in INF specific section
+# @param Flag If the flag set to True, need to skip macros in a quoted string
+#
+def InfExpandMacro(Content, LineInfo, GlobalMacros=None, SectionMacros=None, Flag=False):
+ if GlobalMacros is None:
+ GlobalMacros = {}
+ if SectionMacros is None:
+ SectionMacros = {}
+
+ FileName = LineInfo[0]
+ LineContent = LineInfo[1]
+ LineNo = LineInfo[2]
+
+ # Don't expand macros in comments
+ if LineContent.strip().startswith("#"):
+ return Content
+
+ NewLineInfo = (FileName, LineNo, LineContent)
+
+ #
+ # First, replace MARCOs with value defined in specific section
+ #
+ Content = ReplaceMacro (Content,
+ SectionMacros,
+ False,
+ (LineContent, LineNo),
+ FileName,
+ Flag)
+ #
+ # Then replace MARCOs with value defined in [Defines] section
+ #
+ Content = ReplaceMacro (Content,
+ GlobalMacros,
+ False,
+ (LineContent, LineNo),
+ FileName,
+ Flag)
+
+ MacroUsed = gMACRO_PATTERN.findall(Content)
+ #
+ # no macro found in String, stop replacing
+ #
+ if len(MacroUsed) == 0:
+ return Content
+ else:
+ for Macro in MacroUsed:
+ gQuotedMacro = re.compile(".*\".*\$\(%s\).*\".*"%(Macro))
+ if not gQuotedMacro.match(Content):
+ #
+ # Still have MACROs can't be expanded.
+ #
+ ErrorInInf (ERR_MARCO_DEFINITION_MISS_ERROR,
+ LineInfo=NewLineInfo)
+
+ return Content
+
+
+## IsBinaryInf
+#
+# Judge whether the INF file is Binary INF or Common INF
+#
+# @param FileLineList A list contain all INF file content.
+#
+def IsBinaryInf(FileLineList):
+ if not FileLineList:
+ return False
+
+ ReIsSourcesSection = re.compile("^\s*\[Sources.*\]\s.*$", re.IGNORECASE)
+ ReIsBinarySection = re.compile("^\s*\[Binaries.*\]\s.*$", re.IGNORECASE)
+ BinarySectionFoundFlag = False
+
+ for Line in FileLineList:
+ if ReIsSourcesSection.match(Line):
+ return False
+ if ReIsBinarySection.match(Line):
+ BinarySectionFoundFlag = True
+
+ if BinarySectionFoundFlag:
+ return True
+
+ return False
+
+
+## IsLibInstanceInfo
+#
+# Judge whether the string contain the information of ## @LIB_INSTANCES.
+#
+# @param String
+#
+# @return Flag
+#
+def IsLibInstanceInfo(String):
+ ReIsLibInstance = re.compile("^\s*##\s*@LIB_INSTANCES\s*$")
+ if ReIsLibInstance.match(String):
+ return True
+ else:
+ return False
+
+
+## IsAsBuildOptionInfo
+#
+# Judge whether the string contain the information of ## @ASBUILD.
+#
+# @param String
+#
+# @return Flag
+#
+def IsAsBuildOptionInfo(String):
+ ReIsAsBuildInstance = re.compile("^\s*##\s*@AsBuilt\s*$")
+ if ReIsAsBuildInstance.match(String):
+ return True
+ else:
+ return False
+
+
+class InfParserSectionRoot(object):
+ def __init__(self):
+ #
+ # Macros defined in [Define] section are file scope global
+ #
+ self.FileLocalMacros = {}
+
+ #
+ # Current Section Header content.
+ #
+ self.SectionHeaderContent = []
+
+ #
+ # Last time Section Header content.
+ #
+ self.LastSectionHeaderContent = []
+
+ self.FullPath = ''
+
+ self.InfDefSection = None
+ self.InfBuildOptionSection = None
+ self.InfLibraryClassSection = None
+ self.InfPackageSection = None
+ self.InfPcdSection = None
+ self.InfSourcesSection = None
+ self.InfUserExtensionSection = None
+ self.InfProtocolSection = None
+ self.InfPpiSection = None
+ self.InfGuidSection = None
+ self.InfDepexSection = None
+ self.InfPeiDepexSection = None
+ self.InfDxeDepexSection = None
+ self.InfSmmDepexSection = None
+ self.InfBinariesSection = None
+ self.InfHeader = None
+ self.InfSpecialCommentSection = None
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py
new file mode 100755
index 00000000..e930398d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfPcdSectionParser.py
@@ -0,0 +1,178 @@
+## @file
+# This file contained the parser for [Pcds] sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+'''
+InfPcdSectionParser
+'''
+##
+# Import Modules
+#
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Parser.InfParserMisc import InfExpandMacro
+from Library import DataType as DT
+from Library.Parsing import MacroParser
+from Library.Misc import GetSplitValueList
+from Library import GlobalData
+from Library.StringUtils import SplitPcdEntry
+from Parser.InfParserMisc import InfParserSectionRoot
+
+class InfPcdSectionParser(InfParserSectionRoot):
+ ## Section PCD related parser
+ #
+ # For 5 types of PCD list below, all use this function.
+ # 'FixedPcd', 'FeaturePcd', 'PatchPcd', 'Pcd', 'PcdEx'
+ #
+ # This is a INF independent parser, the validation in this parser only
+ # cover
+ # INF spec scope, will not cross DEC/DSC to check pcd value
+ #
+ def InfPcdParser(self, SectionString, InfSectionObject, FileName):
+ KeysList = []
+ PcdList = []
+ CommentsList = []
+ ValueList = []
+ #
+ # Current section archs
+ #
+ LineIndex = -1
+ for Item in self.LastSectionHeaderContent:
+ if (Item[0], Item[1], Item[3]) not in KeysList:
+ KeysList.append((Item[0], Item[1], Item[3]))
+ LineIndex = Item[3]
+
+ if (Item[0].upper() == DT.TAB_INF_FIXED_PCD.upper() or \
+ Item[0].upper() == DT.TAB_INF_FEATURE_PCD.upper() or \
+ Item[0].upper() == DT.TAB_INF_PCD.upper()) and GlobalData.gIS_BINARY_INF:
+ Logger.Error('InfParser', FORMAT_INVALID, ST.ERR_ASBUILD_PCD_SECTION_TYPE%("\"" + Item[0] + "\""),
+ File=FileName, Line=LineIndex)
+
+ #
+ # For Common INF file
+ #
+ if not GlobalData.gIS_BINARY_INF:
+ #
+ # Macro defined in this section
+ #
+ SectionMacros = {}
+ for Line in SectionString:
+ PcdLineContent = Line[0]
+ PcdLineNo = Line[1]
+ if PcdLineContent.strip() == '':
+ CommentsList = []
+ continue
+
+ if PcdLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ CommentsList.append(Line)
+ continue
+ else:
+ #
+ # Encounter a PCD entry
+ #
+ if PcdLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ CommentsList.append((
+ PcdLineContent[PcdLineContent.find(DT.TAB_COMMENT_SPLIT):],
+ PcdLineNo))
+ PcdLineContent = PcdLineContent[:PcdLineContent.find(DT.TAB_COMMENT_SPLIT)]
+
+ if PcdLineContent != '':
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((PcdLineContent, PcdLineNo),
+ FileName,
+ DT.MODEL_EFI_PCD,
+ self.FileLocalMacros)
+ if Name is not None:
+ SectionMacros[Name] = Value
+ ValueList = []
+ CommentsList = []
+ continue
+
+ PcdEntryReturn = SplitPcdEntry(PcdLineContent)
+
+ if not PcdEntryReturn[1]:
+ TokenList = ['']
+ else:
+ TokenList = PcdEntryReturn[0]
+
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ ValueList = [InfExpandMacro(Value, (FileName, PcdLineContent, PcdLineNo),
+ self.FileLocalMacros, SectionMacros, True)
+ for Value in ValueList]
+
+ if len(ValueList) >= 1:
+ PcdList.append((ValueList, CommentsList, (PcdLineContent, PcdLineNo, FileName)))
+ ValueList = []
+ CommentsList = []
+ continue
+ #
+ # For Binary INF file
+ #
+ else:
+ for Line in SectionString:
+ LineContent = Line[0].strip()
+ LineNo = Line[1]
+
+ if LineContent == '':
+ CommentsList = []
+ continue
+
+ if LineContent.startswith(DT.TAB_COMMENT_SPLIT):
+ CommentsList.append(LineContent)
+ continue
+ #
+ # Have comments at tail.
+ #
+ CommentIndex = LineContent.find(DT.TAB_COMMENT_SPLIT)
+ if CommentIndex > -1:
+ CommentsList.append(LineContent[CommentIndex+1:])
+ LineContent = LineContent[:CommentIndex]
+
+ TokenList = GetSplitValueList(LineContent, DT.TAB_VALUE_SPLIT)
+ #
+ # PatchablePcd
+ # TokenSpace.CName | Value | Offset
+ #
+ if KeysList[0][0].upper() == DT.TAB_INF_PATCH_PCD.upper():
+ if len(TokenList) != 3:
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_ASBUILD_PATCHPCD_FORMAT_INVALID,
+ File=FileName,
+ Line=LineNo,
+ ExtraData=LineContent)
+ #
+ elif KeysList[0][0].upper() == DT.TAB_INF_PCD_EX.upper():
+ if len(TokenList) != 1:
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_ASBUILD_PCDEX_FORMAT_INVALID,
+ File=FileName,
+ Line=LineNo,
+ ExtraData=LineContent)
+ ValueList[0:len(TokenList)] = TokenList
+ if len(ValueList) >= 1:
+ PcdList.append((ValueList, CommentsList, (LineContent, LineNo, FileName)))
+ ValueList = []
+ CommentsList = []
+ continue
+
+ if not InfSectionObject.SetPcds(PcdList, KeysList = KeysList,
+ PackageInfo = self.InfPackageSection.GetPackages()):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR%("[PCD]"),
+ File=FileName,
+ Line=LineIndex)
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
new file mode 100755
index 00000000..9a0cd714
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
@@ -0,0 +1,493 @@
+## @file
+# This file contained the parser for sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+'''
+InfSectionParser
+'''
+##
+# Import Modules
+#
+from copy import deepcopy
+import re
+
+from Library.StringUtils import GetSplitValueList
+from Library.CommentParsing import ParseHeaderCommentSection
+from Library.CommentParsing import ParseComment
+
+from Library import DataType as DT
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+
+from Object.Parser.InfDefineObject import InfDefObject
+from Object.Parser.InfBuildOptionObject import InfBuildOptionsObject
+from Object.Parser.InfLibraryClassesObject import InfLibraryClassObject
+from Object.Parser.InfPackagesObject import InfPackageObject
+from Object.Parser.InfPcdObject import InfPcdObject
+from Object.Parser.InfSoucesObject import InfSourcesObject
+from Object.Parser.InfUserExtensionObject import InfUserExtensionObject
+from Object.Parser.InfProtocolObject import InfProtocolObject
+from Object.Parser.InfPpiObject import InfPpiObject
+from Object.Parser.InfGuidObject import InfGuidObject
+from Object.Parser.InfDepexObject import InfDepexObject
+from Object.Parser.InfBinaryObject import InfBinariesObject
+from Object.Parser.InfHeaderObject import InfHeaderObject
+from Object.Parser.InfMisc import InfSpecialCommentObject
+from Object.Parser.InfMisc import InfHobObject
+from Object.Parser.InfMisc import InfBootModeObject
+from Object.Parser.InfMisc import InfEventObject
+from Parser.InfParserMisc import gINF_SECTION_DEF
+from Parser.InfDefineSectionParser import InfDefinSectionParser
+from Parser.InfBuildOptionSectionParser import InfBuildOptionSectionParser
+from Parser.InfSourceSectionParser import InfSourceSectionParser
+from Parser.InfLibrarySectionParser import InfLibrarySectionParser
+from Parser.InfPackageSectionParser import InfPackageSectionParser
+from Parser.InfGuidPpiProtocolSectionParser import InfGuidPpiProtocolSectionParser
+from Parser.InfBinarySectionParser import InfBinarySectionParser
+from Parser.InfPcdSectionParser import InfPcdSectionParser
+from Parser.InfDepexSectionParser import InfDepexSectionParser
+
+## GetSpecialStr2
+#
+# GetSpecialStr2
+#
+def GetSpecialStr2(ItemList, FileName, LineNo, SectionString):
+ Str2 = ''
+ #
+ # S2 may be Platform or ModuleType
+ #
+ if len(ItemList) == 3:
+ #
+ # Except [LibraryClass], [Depex]
+ # section can has more than 2 items in section header string,
+ # others should report error.
+ #
+ if not (ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() or \
+ ItemList[0].upper() == DT.TAB_DEPEX.upper() or \
+ ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper()):
+ if ItemList[2] != '':
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID % (SectionString),
+ File=FileName,
+ Line=LineNo,
+ ExtraData=SectionString)
+ Str2 = ItemList[2]
+ elif len(ItemList) == 4:
+ #
+ # Except [UserExtension]
+ # section can has 4 items in section header string,
+ # others should report error.
+ #
+ if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper() or ItemList[0].upper() == DT.TAB_DEPEX.upper():
+ if ItemList[3] != '':
+ Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
+ % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
+
+ if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
+ Str2 = ItemList[2] + ' | ' + ItemList[3]
+ else:
+ Str2 = ItemList[2]
+
+ elif len(ItemList) > 4:
+ Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
+ % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
+
+ return Str2
+
+## ProcessUseExtHeader
+#
+#
+def ProcessUseExtHeader(ItemList):
+ NewItemList = []
+ AppendContent = ''
+ CompleteFlag = False
+ for Item in ItemList:
+ if Item.startswith('\"') and not Item.endswith('\"'):
+ AppendContent = Item
+ CompleteFlag = True
+ elif Item.endswith('\"') and not Item.startswith('\"'):
+ #
+ # Should not have an userId or IdString not starts with " before but ends with ".
+ #
+ if not CompleteFlag:
+ return False, []
+ AppendContent = AppendContent + "." + Item
+ NewItemList.append(AppendContent)
+ CompleteFlag = False
+ AppendContent = ''
+ elif Item.endswith('\"') and Item.startswith('\"'):
+ #
+ # Common item, not need to combine the information
+ #
+ NewItemList.append(Item)
+ else:
+ if not CompleteFlag:
+ NewItemList.append(Item)
+ else:
+ AppendContent = AppendContent + "." + Item
+
+ if len(NewItemList) > 4:
+ return False, []
+
+ return True, NewItemList
+
+## GetArch
+#
+# GetArch
+#
+def GetArch(ItemList, ArchList, FileName, LineNo, SectionString):
+ #
+ # S1 is always Arch
+ #
+ if len(ItemList) > 1:
+ Arch = ItemList[1]
+ else:
+ Arch = 'COMMON'
+ ArchList.add(Arch)
+
+ #
+ # 'COMMON' must not be used with specific ARCHs at the same section
+ #
+ if 'COMMON' in ArchList and len(ArchList) > 1:
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_SECTION_ARCH_CONFLICT,
+ File=FileName,
+ Line=LineNo,
+ ExtraData=SectionString)
+
+ return Arch, ArchList
+
+## InfSectionParser
+#
+# Inherit from object
+#
+class InfSectionParser(InfDefinSectionParser,
+ InfBuildOptionSectionParser,
+ InfSourceSectionParser,
+ InfLibrarySectionParser,
+ InfPackageSectionParser,
+ InfGuidPpiProtocolSectionParser,
+ InfBinarySectionParser,
+ InfPcdSectionParser,
+ InfDepexSectionParser):
+ #
+ # Parser objects used to implement singleton
+ #
+ MetaFiles = {}
+
+ ## Factory method
+ #
+ # One file, one parser object. This factory method makes sure that there's
+ # only one object constructed for one meta file.
+ #
+ # @param Class class object of real AutoGen class
+ # (InfParser, DecParser or DscParser)
+ # @param FilePath The path of meta file
+ #
+ def __new__(cls, FilePath, *args, **kwargs):
+ if args:
+ pass
+ if kwargs:
+ pass
+ if FilePath in cls.MetaFiles:
+ return cls.MetaFiles[FilePath]
+ else:
+ ParserObject = super(InfSectionParser, cls).__new__(cls)
+ cls.MetaFiles[FilePath] = ParserObject
+ return ParserObject
+
+ def __init__(self):
+ InfDefinSectionParser.__init__(self)
+ InfBuildOptionSectionParser.__init__(self)
+ InfSourceSectionParser.__init__(self)
+ InfLibrarySectionParser.__init__(self)
+ InfPackageSectionParser.__init__(self)
+ InfGuidPpiProtocolSectionParser.__init__(self)
+ InfBinarySectionParser.__init__(self)
+ InfPcdSectionParser.__init__(self)
+ InfDepexSectionParser.__init__(self)
+ #
+ # Initialize all objects that an INF file will generated.
+ #
+ self.InfDefSection = InfDefObject()
+ self.InfBuildOptionSection = InfBuildOptionsObject()
+ self.InfLibraryClassSection = InfLibraryClassObject()
+ self.InfPackageSection = InfPackageObject()
+ self.InfPcdSection = InfPcdObject(list(self.MetaFiles.keys())[0])
+ self.InfSourcesSection = InfSourcesObject()
+ self.InfUserExtensionSection = InfUserExtensionObject()
+ self.InfProtocolSection = InfProtocolObject()
+ self.InfPpiSection = InfPpiObject()
+ self.InfGuidSection = InfGuidObject()
+ self.InfDepexSection = InfDepexObject()
+ self.InfPeiDepexSection = InfDepexObject()
+ self.InfDxeDepexSection = InfDepexObject()
+ self.InfSmmDepexSection = InfDepexObject()
+ self.InfBinariesSection = InfBinariesObject()
+ self.InfHeader = InfHeaderObject()
+ self.InfBinaryHeader = InfHeaderObject()
+ self.InfSpecialCommentSection = InfSpecialCommentObject()
+
+ #
+ # A List for store define section content.
+ #
+ self._PcdNameList = []
+ self._SectionName = ''
+ self._SectionType = 0
+ self.RelaPath = ''
+ self.FileName = ''
+
+ #
+ # File Header content parser
+ #
+ def InfHeaderParser(self, Content, InfHeaderObject2, FileName, IsBinaryHeader = False):
+ if IsBinaryHeader:
+ (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName, True)
+ if not Abstract or not Description or not Copyright or not License:
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INVALID_BINARYHEADER_FORMAT,
+ File=FileName)
+ else:
+ (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName)
+ #
+ # Not process file name now, for later usage.
+ #
+ if self.FileName:
+ pass
+
+ #
+ # Insert Abstract, Description, CopyRight, License into header object
+ #
+ InfHeaderObject2.SetAbstract(Abstract)
+ InfHeaderObject2.SetDescription(Description)
+ InfHeaderObject2.SetCopyright(Copyright)
+ InfHeaderObject2.SetLicense(License)
+
+
+
+
+ ## Section header parser
+ #
+ # The section header is always in following format:
+ #
+ # [section_name.arch<.platform|module_type>]
+ #
+ # @param String A string contained the content need to be parsed.
+ #
+ def SectionHeaderParser(self, SectionString, FileName, LineNo):
+ _Scope = []
+ _SectionName = ''
+ ArchList = set()
+ _ValueList = []
+ _PcdNameList = [DT.TAB_INF_FIXED_PCD.upper(),
+ DT.TAB_INF_FEATURE_PCD.upper(),
+ DT.TAB_INF_PATCH_PCD.upper(),
+ DT.TAB_INF_PCD.upper(),
+ DT.TAB_INF_PCD_EX.upper()
+ ]
+ SectionString = SectionString.strip()
+ for Item in GetSplitValueList(SectionString[1:-1], DT.TAB_COMMA_SPLIT):
+ if Item == '':
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
+ File=FileName,
+ Line=LineNo,
+ ExtraData=SectionString)
+ ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
+ #
+ # different section should not mix in one section
+ # Allow different PCD type sections mixed together
+ #
+ if _SectionName.upper() not in _PcdNameList:
+ if _SectionName != '' and _SectionName.upper() != ItemList[0].upper():
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_SECTION_NAME_DUPLICATE,
+ File=FileName,
+ Line=LineNo,
+ ExtraData=SectionString)
+ elif _PcdNameList[1] in [_SectionName.upper(), ItemList[0].upper()] and \
+ (_SectionName.upper()!= ItemList[0].upper()):
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
+ File=FileName,
+ Line=LineNo,
+ ExtraData=SectionString)
+
+ _SectionName = ItemList[0]
+ if _SectionName.upper() in gINF_SECTION_DEF:
+ self._SectionType = gINF_SECTION_DEF[_SectionName.upper()]
+ else:
+ self._SectionType = DT.MODEL_UNKNOWN
+ Logger.Error("Parser",
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_UNKNOWN_SECTION,
+ File=FileName,
+ Line=LineNo,
+ ExtraData=SectionString)
+
+ #
+ # Get Arch
+ #
+ Str1, ArchList = GetArch(ItemList, ArchList, FileName, LineNo, SectionString)
+
+ #
+ # For [Defines] section, do special check.
+ #
+ if ItemList[0].upper() == DT.TAB_COMMON_DEFINES.upper():
+ if len(ItemList) != 1:
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
+ File=FileName, Line=LineNo, ExtraData=SectionString)
+
+ #
+ # For [UserExtension] section, do special check.
+ #
+ if ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
+
+ RetValue = ProcessUseExtHeader(ItemList)
+
+ if not RetValue[0]:
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
+ File=FileName, Line=LineNo, ExtraData=SectionString)
+ else:
+ ItemList = RetValue[1]
+
+ if len(ItemList) == 3:
+ ItemList.append('COMMON')
+
+ Str1 = ItemList[1]
+
+ #
+ # For Library classes, need to check module type.
+ #
+ if ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() and len(ItemList) == 3:
+ if ItemList[2] != '':
+ ModuleTypeList = GetSplitValueList(ItemList[2], DT.TAB_VALUE_SPLIT)
+ for Item in ModuleTypeList:
+ if Item.strip() not in DT.MODULE_LIST:
+ Logger.Error('Parser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID % (Item),
+ File=FileName,
+ Line=LineNo,
+ ExtraData=SectionString)
+ #
+ # GetSpecialStr2
+ #
+ Str2 = GetSpecialStr2(ItemList, FileName, LineNo, SectionString)
+
+ _Scope.append([Str1, Str2])
+
+ _NewValueList = []
+ _AppendFlag = True
+ if _SectionName.upper() in _PcdNameList:
+ for ValueItem in _ValueList:
+ if _SectionName.upper() == ValueItem[0].upper() and Str1.upper() not in ValueItem[1].split():
+ ValueItem[1] = ValueItem[1] + " " + Str1
+ _AppendFlag = False
+ elif _SectionName.upper() == ValueItem[0].upper() and Str1.upper() in ValueItem[1].split():
+ _AppendFlag = False
+
+ _NewValueList.append(ValueItem)
+
+ _ValueList = _NewValueList
+
+ if _AppendFlag:
+ if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
+ _ValueList.append([_SectionName, Str1, Str2, LineNo])
+ else:
+ if len(ItemList) == 4:
+ _ValueList.append([_SectionName, Str1, Str2, ItemList[3], LineNo])
+
+ self.SectionHeaderContent = deepcopy(_ValueList)
+
+ ## GenSpecialSectionList
+ #
+ # @param SpecialSectionList: a list of list, of which item's format
+ # (Comment, LineNum)
+ # @param ContainerFile: Input value for filename of Inf file
+ #
+ def InfSpecialCommentParser (self, SpecialSectionList, InfSectionObject, ContainerFile, SectionType):
+ ReFindSpecialCommentRe = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)
+ ReFindHobArchRe = re.compile(r"""[Hh][Oo][Bb]\.([^,]*)""", re.DOTALL)
+ if self.FileName:
+ pass
+ SpecialObjectList = []
+ ArchList = []
+ if SectionType == DT.TYPE_EVENT_SECTION:
+ TokenDict = DT.EVENT_TOKENS
+ elif SectionType == DT.TYPE_HOB_SECTION:
+ TokenDict = DT.HOB_TOKENS
+ else:
+ TokenDict = DT.BOOTMODE_TOKENS
+
+ for List in SpecialSectionList:
+ #
+ # Hob has Arch attribute, need to be handled specially here
+ #
+ if SectionType == DT.TYPE_HOB_SECTION:
+
+ MatchObject = ReFindSpecialCommentRe.search(List[0][0])
+ HobSectionStr = MatchObject.group(1)
+ ArchList = []
+ for Match in ReFindHobArchRe.finditer(HobSectionStr):
+ Arch = Match.groups(1)[0].upper()
+ ArchList.append(Arch)
+ CommentSoFar = ''
+ for Index in range(1, len(List)):
+ Result = ParseComment(List[Index], DT.ALL_USAGE_TOKENS, TokenDict, [], False)
+ Usage = Result[0]
+ Type = Result[1]
+ HelpText = Result[3]
+
+ if Usage == DT.ITEM_UNDEFINED and Type == DT.ITEM_UNDEFINED:
+ if HelpText is None:
+ HelpText = ''
+ if not HelpText.endswith('\n'):
+ HelpText += '\n'
+ CommentSoFar += HelpText
+ else:
+ if HelpText:
+ CommentSoFar += HelpText
+ if SectionType == DT.TYPE_EVENT_SECTION:
+ SpecialObject = InfEventObject()
+ SpecialObject.SetEventType(Type)
+ SpecialObject.SetUsage(Usage)
+ SpecialObject.SetHelpString(CommentSoFar)
+ elif SectionType == DT.TYPE_HOB_SECTION:
+ SpecialObject = InfHobObject()
+ SpecialObject.SetHobType(Type)
+ SpecialObject.SetUsage(Usage)
+ SpecialObject.SetHelpString(CommentSoFar)
+ if len(ArchList) >= 1:
+ SpecialObject.SetSupArchList(ArchList)
+ else:
+ SpecialObject = InfBootModeObject()
+ SpecialObject.SetSupportedBootModes(Type)
+ SpecialObject.SetUsage(Usage)
+ SpecialObject.SetHelpString(CommentSoFar)
+
+ SpecialObjectList.append(SpecialObject)
+ CommentSoFar = ''
+ if not InfSectionObject.SetSpecialComments(SpecialObjectList,
+ SectionType):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (SectionType),
+ ContainerFile
+ )
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py
new file mode 100755
index 00000000..ac61177a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/InfSourceSectionParser.py
@@ -0,0 +1,139 @@
+## @file
+# This file contained the parser for [Sources] sections in INF file
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+'''
+InfSourceSectionParser
+'''
+##
+# Import Modules
+#
+
+import Logger.Log as Logger
+from Logger import StringTable as ST
+from Logger.ToolError import FORMAT_INVALID
+from Parser.InfParserMisc import InfExpandMacro
+from Library import DataType as DT
+from Library.Parsing import MacroParser
+from Library.Misc import GetSplitValueList
+from Object.Parser.InfCommonObject import InfLineCommentObject
+from Parser.InfParserMisc import InfParserSectionRoot
+
+class InfSourceSectionParser(InfParserSectionRoot):
+ ## InfSourceParser
+ #
+ #
+ def InfSourceParser(self, SectionString, InfSectionObject, FileName):
+ SectionMacros = {}
+ ValueList = []
+ SourceList = []
+ StillCommentFalg = False
+ HeaderComments = []
+ LineComment = None
+ SectionContent = ''
+ for Line in SectionString:
+ SrcLineContent = Line[0]
+ SrcLineNo = Line[1]
+
+ if SrcLineContent.strip() == '':
+ continue
+
+ #
+ # Found Header Comments
+ #
+ if SrcLineContent.strip().startswith(DT.TAB_COMMENT_SPLIT):
+ #
+ # Last line is comments, and this line go on.
+ #
+ if StillCommentFalg:
+ HeaderComments.append(Line)
+ SectionContent += SrcLineContent + DT.END_OF_LINE
+ continue
+ #
+ # First time encounter comment
+ #
+ else:
+ #
+ # Clear original data
+ #
+ HeaderComments = []
+ HeaderComments.append(Line)
+ StillCommentFalg = True
+ SectionContent += SrcLineContent + DT.END_OF_LINE
+ continue
+ else:
+ StillCommentFalg = False
+
+ if len(HeaderComments) >= 1:
+ LineComment = InfLineCommentObject()
+ LineCommentContent = ''
+ for Item in HeaderComments:
+ LineCommentContent += Item[0] + DT.END_OF_LINE
+ LineComment.SetHeaderComments(LineCommentContent)
+
+ #
+ # Find Tail comment.
+ #
+ if SrcLineContent.find(DT.TAB_COMMENT_SPLIT) > -1:
+ TailComments = SrcLineContent[SrcLineContent.find(DT.TAB_COMMENT_SPLIT):]
+ SrcLineContent = SrcLineContent[:SrcLineContent.find(DT.TAB_COMMENT_SPLIT)]
+ if LineComment is None:
+ LineComment = InfLineCommentObject()
+ LineComment.SetTailComments(TailComments)
+
+ #
+ # Find Macro
+ #
+ Name, Value = MacroParser((SrcLineContent, SrcLineNo),
+ FileName,
+ DT.MODEL_EFI_SOURCE_FILE,
+ self.FileLocalMacros)
+ if Name is not None:
+ SectionMacros[Name] = Value
+ LineComment = None
+ HeaderComments = []
+ continue
+
+ #
+ # Replace with Local section Macro and [Defines] section Macro.
+ #
+ SrcLineContent = InfExpandMacro(SrcLineContent,
+ (FileName, SrcLineContent, SrcLineNo),
+ self.FileLocalMacros,
+ SectionMacros)
+
+ TokenList = GetSplitValueList(SrcLineContent, DT.TAB_VALUE_SPLIT, 4)
+ ValueList[0:len(TokenList)] = TokenList
+
+ #
+ # Store section content string after MACRO replaced.
+ #
+ SectionContent += SrcLineContent + DT.END_OF_LINE
+
+ SourceList.append((ValueList, LineComment,
+ (SrcLineContent, SrcLineNo, FileName)))
+ ValueList = []
+ LineComment = None
+ TailComments = ''
+ HeaderComments = []
+ continue
+
+ #
+ # Current section archs
+ #
+ ArchList = []
+ for Item in self.LastSectionHeaderContent:
+ if Item[1] not in ArchList:
+ ArchList.append(Item[1])
+ InfSectionObject.SetSupArchList(Item[1])
+
+ InfSectionObject.SetAllContent(SectionContent)
+ if not InfSectionObject.SetSources(SourceList, Arch = ArchList):
+ Logger.Error('InfParser',
+ FORMAT_INVALID,
+ ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % ("[Sources]"),
+ File=FileName,
+ Line=Item[3])
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/__init__.py
new file mode 100644
index 00000000..d6922c14
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Parser/__init__.py
@@ -0,0 +1,14 @@
+## @file
+# Python 'Parser' package initialization file.
+#
+# This file is required to make Python interpreter treat the directory
+# as containing package.
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+'''
+Parser
+'''