summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py')
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py4526
1 files changed, 4526 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
new file mode 100755
index 00000000..73ae5b32
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
@@ -0,0 +1,4526 @@
+## @file
+# parse FDF file
+#
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+##
+# Import Modules
+#
+from __future__ import print_function
+from __future__ import absolute_import
+from re import compile, DOTALL
+from string import hexdigits
+from uuid import UUID
+
+from Common.BuildToolError import *
+from Common import EdkLogger
+from Common.Misc import PathClass, tdict, ProcessDuplicatedInf, GuidStructureStringToGuidString
+from Common.StringUtils import NormPath, ReplaceMacro
+from Common import GlobalData
+from Common.Expression import *
+from Common.DataType import *
+from Common.MultipleWorkspace import MultipleWorkspace as mws
+import Common.LongFilePathOs as os
+from Common.LongFilePathSupport import OpenLongFilePath as open
+from Common.RangeExpression import RangeExpression
+from collections import OrderedDict
+
+from .Fd import FD
+from .Region import Region
+from .Fv import FV
+from .AprioriSection import AprioriSection
+from .FfsInfStatement import FfsInfStatement
+from .FfsFileStatement import FileStatement
+from .VerSection import VerSection
+from .UiSection import UiSection
+from .FvImageSection import FvImageSection
+from .DataSection import DataSection
+from .DepexSection import DepexSection
+from .CompressSection import CompressSection
+from .GuidSection import GuidSection
+from .Capsule import EFI_CERT_TYPE_PKCS7_GUID, EFI_CERT_TYPE_RSA2048_SHA256_GUID, Capsule
+from .CapsuleData import CapsuleFfs, CapsulePayload, CapsuleFv, CapsuleFd, CapsuleAnyFile, CapsuleAfile
+from .RuleComplexFile import RuleComplexFile
+from .RuleSimpleFile import RuleSimpleFile
+from .EfiSection import EfiSection
+from .OptionRom import OPTIONROM
+from .OptRomInfStatement import OptRomInfStatement, OverrideAttribs
+from .OptRomFileStatement import OptRomFileStatement
+from .GenFdsGlobalVariable import GenFdsGlobalVariable
+
+T_CHAR_CR = '\r'
+T_CHAR_TAB = '\t'
+T_CHAR_DOUBLE_QUOTE = '\"'
+T_CHAR_SINGLE_QUOTE = '\''
+T_CHAR_BRACE_R = '}'
+
+SEPARATORS = {TAB_EQUAL_SPLIT, TAB_VALUE_SPLIT, TAB_COMMA_SPLIT, '{', T_CHAR_BRACE_R}
+ALIGNMENTS = {"Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K", "64K", "128K",
+ "256K", "512K", "1M", "2M", "4M", "8M", "16M"}
+ALIGNMENT_NOAUTO = ALIGNMENTS - {"Auto"}
+CR_LB_SET = {T_CHAR_CR, TAB_LINE_BREAK}
+
+RegionSizePattern = compile("\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*")
+RegionSizeGuidPattern = compile("\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*\|\s*(?P<size>\w+\.\w+[\.\w\[\]]*)\s*")
+RegionOffsetPcdPattern = compile("\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*$")
+ShortcutPcdPattern = compile("\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*")
+BaseAddrValuePattern = compile('^0[xX][0-9a-fA-F]+')
+FileExtensionPattern = compile(r'([a-zA-Z][a-zA-Z0-9]*)')
+TokenFindPattern = compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
+AllIncludeFileList = []
+
+# Get the closest parent
+def GetParentAtLine (Line):
+ for Profile in AllIncludeFileList:
+ if Profile.IsLineInFile(Line):
+ return Profile
+ return None
+
+# Check include loop
+def IsValidInclude (File, Line):
+ for Profile in AllIncludeFileList:
+ if Profile.IsLineInFile(Line) and Profile.FileName == File:
+ return False
+
+ return True
+
+def GetRealFileLine (File, Line):
+ InsertedLines = 0
+ for Profile in AllIncludeFileList:
+ if Profile.IsLineInFile(Line):
+ return Profile.GetLineInFile(Line)
+ elif Line >= Profile.InsertStartLineNumber and Profile.Level == 1:
+ InsertedLines += Profile.GetTotalLines()
+
+ return (File, Line - InsertedLines)
+
+## The exception class that used to report error messages when parsing FDF
+#
+# Currently the "ToolName" is set to be "FdfParser".
+#
+class Warning (Exception):
+ ## The constructor
+ #
+ # @param self The object pointer
+ # @param Str The message to record
+ # @param File The FDF name
+ # @param Line The Line number that error occurs
+ #
+ def __init__(self, Str, File = None, Line = None):
+ FileLineTuple = GetRealFileLine(File, Line)
+ self.FileName = FileLineTuple[0]
+ self.LineNumber = FileLineTuple[1]
+ self.OriginalLineNumber = Line
+ self.Message = Str
+ self.ToolName = 'FdfParser'
+
+ def __str__(self):
+ return self.Message
+
+ # helper functions to facilitate consistency in warnings
+ # each function is for a different common warning
+ @staticmethod
+ def Expected(Str, File, Line):
+ return Warning("expected {}".format(Str), File, Line)
+ @staticmethod
+ def ExpectedEquals(File, Line):
+ return Warning.Expected("'='", File, Line)
+ @staticmethod
+ def ExpectedCurlyOpen(File, Line):
+ return Warning.Expected("'{'", File, Line)
+ @staticmethod
+ def ExpectedCurlyClose(File, Line):
+ return Warning.Expected("'}'", File, Line)
+ @staticmethod
+ def ExpectedBracketClose(File, Line):
+ return Warning.Expected("']'", File, Line)
+
+## The Include file content class that used to record file data when parsing include file
+#
+# May raise Exception when opening file.
+#
+class IncludeFileProfile:
+ ## The constructor
+ #
+ # @param self The object pointer
+ # @param FileName The file that to be parsed
+ #
+ def __init__(self, FileName):
+ self.FileName = FileName
+ self.FileLinesList = []
+ try:
+ with open(FileName, "r") as fsock:
+ self.FileLinesList = fsock.readlines()
+ for index, line in enumerate(self.FileLinesList):
+ if not line.endswith(TAB_LINE_BREAK):
+ self.FileLinesList[index] += TAB_LINE_BREAK
+ except:
+ EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
+
+ self.InsertStartLineNumber = None
+ self.InsertAdjust = 0
+ self.IncludeFileList = []
+ self.Level = 1 # first level include file
+
+ def GetTotalLines(self):
+ TotalLines = self.InsertAdjust + len(self.FileLinesList)
+
+ for Profile in self.IncludeFileList:
+ TotalLines += Profile.GetTotalLines()
+
+ return TotalLines
+
+ def IsLineInFile(self, Line):
+ if Line >= self.InsertStartLineNumber and Line < self.InsertStartLineNumber + self.GetTotalLines():
+ return True
+
+ return False
+
+ def GetLineInFile(self, Line):
+ if not self.IsLineInFile (Line):
+ return (self.FileName, -1)
+
+ InsertedLines = self.InsertStartLineNumber
+
+ for Profile in self.IncludeFileList:
+ if Profile.IsLineInFile(Line):
+ return Profile.GetLineInFile(Line)
+ elif Line >= Profile.InsertStartLineNumber:
+ InsertedLines += Profile.GetTotalLines()
+
+ return (self.FileName, Line - InsertedLines + 1)
+
+## The FDF content class that used to record file data when parsing FDF
+#
+# May raise Exception when opening file.
+#
+class FileProfile:
+ ## The constructor
+ #
+ # @param self The object pointer
+ # @param FileName The file that to be parsed
+ #
+ def __init__(self, FileName):
+ self.FileLinesList = []
+ try:
+ with open(FileName, "r") as fsock:
+ self.FileLinesList = fsock.readlines()
+
+ except:
+ EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
+
+ self.FileName = FileName
+ self.PcdDict = OrderedDict()
+ self.PcdLocalDict = OrderedDict()
+ self.InfList = []
+ self.InfDict = {'ArchTBD':[]}
+ # ECC will use this Dict and List information
+ self.PcdFileLineDict = {}
+ self.InfFileLineList = []
+
+ self.FdDict = {}
+ self.FdNameNotSet = False
+ self.FvDict = {}
+ self.CapsuleDict = {}
+ self.RuleDict = {}
+ self.OptRomDict = {}
+ self.FmpPayloadDict = {}
+
+## The syntax parser for FDF
+#
+# PreprocessFile method should be called prior to ParseFile
+# CycleReferenceCheck method can detect cycles in FDF contents
+#
+# GetNext*** procedures mean these procedures will get next token first, then make judgement.
+# Get*** procedures mean these procedures will make judgement on current token only.
+#
+class FdfParser:
+ ## The constructor
+ #
+ # @param self The object pointer
+ # @param FileName The file that to be parsed
+ #
+ def __init__(self, FileName):
+ self.Profile = FileProfile(FileName)
+ self.FileName = FileName
+ self.CurrentLineNumber = 1
+ self.CurrentOffsetWithinLine = 0
+ self.CurrentFdName = None
+ self.CurrentFvName = None
+ self._Token = ""
+ self._SkippedChars = ""
+ GlobalData.gFdfParser = self
+
+ # Used to section info
+ self._CurSection = []
+ # Key: [section name, UI name, arch]
+ # Value: {MACRO_NAME: MACRO_VALUE}
+ self._MacroDict = tdict(True, 3)
+ self._PcdDict = OrderedDict()
+
+ self._WipeOffArea = []
+ if GenFdsGlobalVariable.WorkSpaceDir == '':
+ GenFdsGlobalVariable.WorkSpaceDir = os.getenv("WORKSPACE")
+
+ ## _SkipWhiteSpace() method
+ #
+ # Skip white spaces from current char.
+ #
+ # @param self The object pointer
+ #
+ def _SkipWhiteSpace(self):
+ while not self._EndOfFile():
+ if self._CurrentChar() in {TAB_PRINTCHAR_NUL, T_CHAR_CR, TAB_LINE_BREAK, TAB_SPACE_SPLIT, T_CHAR_TAB}:
+ self._SkippedChars += str(self._CurrentChar())
+ self._GetOneChar()
+ else:
+ return
+ return
+
+ ## _EndOfFile() method
+ #
+ # Judge current buffer pos is at file end
+ #
+ # @param self The object pointer
+ # @retval True Current File buffer position is at file end
+ # @retval False Current File buffer position is NOT at file end
+ #
+ def _EndOfFile(self):
+ NumberOfLines = len(self.Profile.FileLinesList)
+ SizeOfLastLine = len(self.Profile.FileLinesList[-1])
+ if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1:
+ return True
+ if self.CurrentLineNumber > NumberOfLines:
+ return True
+ return False
+
+ ## _EndOfLine() method
+ #
+ # Judge current buffer pos is at line end
+ #
+ # @param self The object pointer
+ # @retval True Current File buffer position is at line end
+ # @retval False Current File buffer position is NOT at line end
+ #
+ def _EndOfLine(self):
+ if self.CurrentLineNumber > len(self.Profile.FileLinesList):
+ return True
+ SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
+ if self.CurrentOffsetWithinLine >= SizeOfCurrentLine:
+ return True
+ return False
+
+ ## Rewind() method
+ #
+ # Reset file data buffer to the initial state
+ #
+ # @param self The object pointer
+ # @param DestLine Optional new destination line number.
+ # @param DestOffset Optional new destination offset.
+ #
+ def Rewind(self, DestLine = 1, DestOffset = 0):
+ self.CurrentLineNumber = DestLine
+ self.CurrentOffsetWithinLine = DestOffset
+
+ ## _UndoOneChar() method
+ #
+ # Go back one char in the file buffer
+ #
+ # @param self The object pointer
+ # @retval True Successfully go back one char
+ # @retval False Not able to go back one char as file beginning reached
+ #
+ def _UndoOneChar(self):
+ if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0:
+ return False
+ elif self.CurrentOffsetWithinLine == 0:
+ self.CurrentLineNumber -= 1
+ self.CurrentOffsetWithinLine = len(self._CurrentLine()) - 1
+ else:
+ self.CurrentOffsetWithinLine -= 1
+ return True
+
+ ## _GetOneChar() method
+ #
+ # Move forward one char in the file buffer
+ #
+ # @param self The object pointer
+ #
+ def _GetOneChar(self):
+ if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
+ self.CurrentLineNumber += 1
+ self.CurrentOffsetWithinLine = 0
+ else:
+ self.CurrentOffsetWithinLine += 1
+
+ ## _CurrentChar() method
+ #
+ # Get the char pointed to by the file buffer pointer
+ #
+ # @param self The object pointer
+ # @retval Char Current char
+ #
+ def _CurrentChar(self):
+ return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine]
+
+ ## _NextChar() method
+ #
+ # Get the one char pass the char pointed to by the file buffer pointer
+ #
+ # @param self The object pointer
+ # @retval Char Next char
+ #
+ def _NextChar(self):
+ if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
+ return self.Profile.FileLinesList[self.CurrentLineNumber][0]
+ return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1]
+
+ ## _SetCurrentCharValue() method
+ #
+ # Modify the value of current char
+ #
+ # @param self The object pointer
+ # @param Value The new value of current char
+ #
+ def _SetCurrentCharValue(self, Value):
+ self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value
+
+ ## _CurrentLine() method
+ #
+ # Get the list that contains current line contents
+ #
+ # @param self The object pointer
+ # @retval List current line contents
+ #
+ def _CurrentLine(self):
+ return self.Profile.FileLinesList[self.CurrentLineNumber - 1]
+
+ def _StringToList(self):
+ self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList]
+ if not self.Profile.FileLinesList:
+ EdkLogger.error('FdfParser', FILE_READ_FAILURE, 'The file is empty!', File=self.FileName)
+ self.Profile.FileLinesList[-1].append(' ')
+
+ def _ReplaceFragment(self, StartPos, EndPos, Value = ' '):
+ if StartPos[0] == EndPos[0]:
+ Offset = StartPos[1]
+ while Offset <= EndPos[1]:
+ self.Profile.FileLinesList[StartPos[0]][Offset] = Value
+ Offset += 1
+ return
+
+ Offset = StartPos[1]
+ while self.Profile.FileLinesList[StartPos[0]][Offset] not in CR_LB_SET:
+ self.Profile.FileLinesList[StartPos[0]][Offset] = Value
+ Offset += 1
+
+ Line = StartPos[0]
+ while Line < EndPos[0]:
+ Offset = 0
+ while self.Profile.FileLinesList[Line][Offset] not in CR_LB_SET:
+ self.Profile.FileLinesList[Line][Offset] = Value
+ Offset += 1
+ Line += 1
+
+ Offset = 0
+ while Offset <= EndPos[1]:
+ self.Profile.FileLinesList[EndPos[0]][Offset] = Value
+ Offset += 1
+
+ def _SetMacroValue(self, Macro, Value):
+ if not self._CurSection:
+ return
+
+ MacroDict = {}
+ if not self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]]:
+ self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]] = MacroDict
+ else:
+ MacroDict = self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]]
+ MacroDict[Macro] = Value
+
+ def _GetMacroValue(self, Macro):
+ # Highest priority
+ if Macro in GlobalData.gCommandLineDefines:
+ return GlobalData.gCommandLineDefines[Macro]
+ if Macro in GlobalData.gGlobalDefines:
+ return GlobalData.gGlobalDefines[Macro]
+
+ if self._CurSection:
+ MacroDict = self._MacroDict[
+ self._CurSection[0],
+ self._CurSection[1],
+ self._CurSection[2]
+ ]
+ if MacroDict and Macro in MacroDict:
+ return MacroDict[Macro]
+
+ # Lowest priority
+ if Macro in GlobalData.gPlatformDefines:
+ return GlobalData.gPlatformDefines[Macro]
+ return None
+
+ def _SectionHeaderParser(self, Section):
+ # [Defines]
+ # [FD.UiName]: use dummy instead if UI name is optional
+ # [FV.UiName]
+ # [Capsule.UiName]
+ # [Rule]: don't take rule section into account, macro is not allowed in this section
+ # [OptionRom.DriverName]
+ self._CurSection = []
+ Section = Section.strip()[1:-1].upper().replace(' ', '').strip(TAB_SPLIT)
+ ItemList = Section.split(TAB_SPLIT)
+ Item = ItemList[0]
+ if Item == '' or Item == 'RULE':
+ return
+
+ if Item == TAB_COMMON_DEFINES.upper():
+ self._CurSection = [TAB_COMMON, TAB_COMMON, TAB_COMMON]
+ elif len(ItemList) > 1:
+ self._CurSection = [ItemList[0], ItemList[1], TAB_COMMON]
+ elif len(ItemList) > 0:
+ self._CurSection = [ItemList[0], 'DUMMY', TAB_COMMON]
+
+ ## PreprocessFile() method
+ #
+ # Preprocess file contents, replace comments with spaces.
+ # In the end, rewind the file buffer pointer to the beginning
+ # BUGBUG: No !include statement processing contained in this procedure
+ # !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1]
+ #
+ # @param self The object pointer
+ #
+ def PreprocessFile(self):
+ self.Rewind()
+ InComment = False
+ DoubleSlashComment = False
+ HashComment = False
+ # HashComment in quoted string " " is ignored.
+ InString = False
+
+ while not self._EndOfFile():
+
+ if self._CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment:
+ InString = not InString
+ # meet new line, then no longer in a comment for // and '#'
+ if self._CurrentChar() == TAB_LINE_BREAK:
+ self.CurrentLineNumber += 1
+ self.CurrentOffsetWithinLine = 0
+ if InComment and DoubleSlashComment:
+ InComment = False
+ DoubleSlashComment = False
+ if InComment and HashComment:
+ InComment = False
+ HashComment = False
+ # check for */ comment end
+ elif InComment and not DoubleSlashComment and not HashComment and self._CurrentChar() == TAB_STAR and self._NextChar() == TAB_BACK_SLASH:
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ InComment = False
+ # set comments to spaces
+ elif InComment:
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ # check for // comment
+ elif self._CurrentChar() == TAB_BACK_SLASH and self._NextChar() == TAB_BACK_SLASH and not self._EndOfLine():
+ InComment = True
+ DoubleSlashComment = True
+ # check for '#' comment
+ elif self._CurrentChar() == TAB_COMMENT_SPLIT and not self._EndOfLine() and not InString:
+ InComment = True
+ HashComment = True
+ # check for /* comment start
+ elif self._CurrentChar() == TAB_BACK_SLASH and self._NextChar() == TAB_STAR:
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ self._SetCurrentCharValue(TAB_SPACE_SPLIT)
+ self._GetOneChar()
+ InComment = True
+ else:
+ self._GetOneChar()
+
+ # restore from ListOfList to ListOfString
+ self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
+ self.Rewind()
+
+ ## PreprocessIncludeFile() method
+ #
+ # Preprocess file contents, replace !include statements with file contents.
+ # In the end, rewind the file buffer pointer to the beginning
+ #
+ # @param self The object pointer
+ #
+ def PreprocessIncludeFile(self):
+ # nested include support
+ Processed = False
+ MacroDict = {}
+ while self._GetNextToken():
+
+ if self._Token == TAB_DEFINE:
+ if not self._GetNextToken():
+ raise Warning.Expected("Macro name", self.FileName, self.CurrentLineNumber)
+ Macro = self._Token
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ Value = self._GetExpression()
+ MacroDict[Macro] = Value
+
+ elif self._Token == TAB_INCLUDE:
+ Processed = True
+ IncludeLine = self.CurrentLineNumber
+ IncludeOffset = self.CurrentOffsetWithinLine - len(TAB_INCLUDE)
+ if not self._GetNextToken():
+ raise Warning.Expected("include file name", self.FileName, self.CurrentLineNumber)
+ IncFileName = self._Token
+ PreIndex = 0
+ StartPos = IncFileName.find('$(', PreIndex)
+ EndPos = IncFileName.find(')', StartPos+2)
+ while StartPos != -1 and EndPos != -1:
+ Macro = IncFileName[StartPos+2: EndPos]
+ MacroVal = self._GetMacroValue(Macro)
+ if not MacroVal:
+ if Macro in MacroDict:
+ MacroVal = MacroDict[Macro]
+ if MacroVal is not None:
+ IncFileName = IncFileName.replace('$(' + Macro + ')', MacroVal, 1)
+ if MacroVal.find('$(') != -1:
+ PreIndex = StartPos
+ else:
+ PreIndex = StartPos + len(MacroVal)
+ else:
+ raise Warning("The Macro %s is not defined" %Macro, self.FileName, self.CurrentLineNumber)
+ StartPos = IncFileName.find('$(', PreIndex)
+ EndPos = IncFileName.find(')', StartPos+2)
+
+ IncludedFile = NormPath(IncFileName)
+ #
+ # First search the include file under the same directory as FDF file
+ #
+ IncludedFile1 = PathClass(IncludedFile, os.path.dirname(self.FileName))
+ ErrorCode = IncludedFile1.Validate()[0]
+ if ErrorCode != 0:
+ #
+ # Then search the include file under the same directory as DSC file
+ #
+ PlatformDir = ''
+ if GenFdsGlobalVariable.ActivePlatform:
+ PlatformDir = GenFdsGlobalVariable.ActivePlatform.Dir
+ elif GlobalData.gActivePlatform:
+ PlatformDir = GlobalData.gActivePlatform.MetaFile.Dir
+ IncludedFile1 = PathClass(IncludedFile, PlatformDir)
+ ErrorCode = IncludedFile1.Validate()[0]
+ if ErrorCode != 0:
+ #
+ # Also search file under the WORKSPACE directory
+ #
+ IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
+ ErrorCode = IncludedFile1.Validate()[0]
+ if ErrorCode != 0:
+ raise Warning("The include file does not exist under below directories: \n%s\n%s\n%s\n"%(os.path.dirname(self.FileName), PlatformDir, GlobalData.gWorkspace),
+ self.FileName, self.CurrentLineNumber)
+
+ if not IsValidInclude (IncludedFile1.Path, self.CurrentLineNumber):
+ raise Warning("The include file {0} is causing a include loop.\n".format (IncludedFile1.Path), self.FileName, self.CurrentLineNumber)
+
+ IncFileProfile = IncludeFileProfile(IncludedFile1.Path)
+
+ CurrentLine = self.CurrentLineNumber
+ CurrentOffset = self.CurrentOffsetWithinLine
+ # list index of the insertion, note that line number is 'CurrentLine + 1'
+ InsertAtLine = CurrentLine
+ ParentProfile = GetParentAtLine (CurrentLine)
+ if ParentProfile is not None:
+ ParentProfile.IncludeFileList.insert(0, IncFileProfile)
+ IncFileProfile.Level = ParentProfile.Level + 1
+ IncFileProfile.InsertStartLineNumber = InsertAtLine + 1
+ # deal with remaining portions after "!include filename", if exists.
+ if self._GetNextToken():
+ if self.CurrentLineNumber == CurrentLine:
+ RemainingLine = self._CurrentLine()[CurrentOffset:]
+ self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine)
+ IncFileProfile.InsertAdjust += 1
+ self.CurrentLineNumber += 1
+ self.CurrentOffsetWithinLine = 0
+
+ for Line in IncFileProfile.FileLinesList:
+ self.Profile.FileLinesList.insert(InsertAtLine, Line)
+ self.CurrentLineNumber += 1
+ InsertAtLine += 1
+
+ # reversely sorted to better determine error in file
+ AllIncludeFileList.insert(0, IncFileProfile)
+
+ # comment out the processed include file statement
+ TempList = list(self.Profile.FileLinesList[IncludeLine - 1])
+ TempList.insert(IncludeOffset, TAB_COMMENT_SPLIT)
+ self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList)
+ if Processed: # Nested and back-to-back support
+ self.Rewind(DestLine = IncFileProfile.InsertStartLineNumber - 1)
+ Processed = False
+ # Preprocess done.
+ self.Rewind()
+
+ @staticmethod
+ def _GetIfListCurrentItemStat(IfList):
+ if len(IfList) == 0:
+ return True
+
+ for Item in IfList:
+ if Item[1] == False:
+ return False
+
+ return True
+
+ ## PreprocessConditionalStatement() method
+ #
+ # Preprocess conditional statement.
+ # In the end, rewind the file buffer pointer to the beginning
+ #
+ # @param self The object pointer
+ #
+ def PreprocessConditionalStatement(self):
+ # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined]
+ IfList = []
+ RegionLayoutLine = 0
+ ReplacedLine = -1
+ while self._GetNextToken():
+ # Determine section name and the location dependent macro
+ if self._GetIfListCurrentItemStat(IfList):
+ if self._Token.startswith(TAB_SECTION_START):
+ Header = self._Token
+ if not self._Token.endswith(TAB_SECTION_END):
+ self._SkipToToken(TAB_SECTION_END)
+ Header += self._SkippedChars
+ if Header.find('$(') != -1:
+ raise Warning("macro cannot be used in section header", self.FileName, self.CurrentLineNumber)
+ self._SectionHeaderParser(Header)
+ continue
+ # Replace macros except in RULE section or out of section
+ elif self._CurSection and ReplacedLine != self.CurrentLineNumber:
+ ReplacedLine = self.CurrentLineNumber
+ self._UndoToken()
+ CurLine = self.Profile.FileLinesList[ReplacedLine - 1]
+ PreIndex = 0
+ StartPos = CurLine.find('$(', PreIndex)
+ EndPos = CurLine.find(')', StartPos+2)
+ while StartPos != -1 and EndPos != -1 and self._Token not in {TAB_IF_DEF, TAB_IF_N_DEF, TAB_IF, TAB_ELSE_IF}:
+ MacroName = CurLine[StartPos+2: EndPos]
+ MacroValue = self._GetMacroValue(MacroName)
+ if MacroValue is not None:
+ CurLine = CurLine.replace('$(' + MacroName + ')', MacroValue, 1)
+ if MacroValue.find('$(') != -1:
+ PreIndex = StartPos
+ else:
+ PreIndex = StartPos + len(MacroValue)
+ else:
+ PreIndex = EndPos + 1
+ StartPos = CurLine.find('$(', PreIndex)
+ EndPos = CurLine.find(')', StartPos+2)
+ self.Profile.FileLinesList[ReplacedLine - 1] = CurLine
+ continue
+
+ if self._Token == TAB_DEFINE:
+ if self._GetIfListCurrentItemStat(IfList):
+ if not self._CurSection:
+ raise Warning("macro cannot be defined in Rule section or out of section", self.FileName, self.CurrentLineNumber)
+ DefineLine = self.CurrentLineNumber - 1
+ DefineOffset = self.CurrentOffsetWithinLine - len(TAB_DEFINE)
+ if not self._GetNextToken():
+ raise Warning.Expected("Macro name", self.FileName, self.CurrentLineNumber)
+ Macro = self._Token
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ Value = self._GetExpression()
+ self._SetMacroValue(Macro, Value)
+ self._WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ elif self._Token == 'SET':
+ if not self._GetIfListCurrentItemStat(IfList):
+ continue
+ SetLine = self.CurrentLineNumber - 1
+ SetOffset = self.CurrentOffsetWithinLine - len('SET')
+ PcdPair = self._GetNextPcdSettings()
+ PcdName = "%s.%s" % (PcdPair[1], PcdPair[0])
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ Value = self._GetExpression()
+ Value = self._EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
+
+ self._PcdDict[PcdName] = Value
+
+ self.Profile.PcdDict[PcdPair] = Value
+ self.SetPcdLocalation(PcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
+
+ self._WipeOffArea.append(((SetLine, SetOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ elif self._Token in {TAB_IF_DEF, TAB_IF_N_DEF, TAB_IF}:
+ IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self._Token))
+ IfList.append([IfStartPos, None, None])
+
+ CondLabel = self._Token
+ Expression = self._GetExpression()
+
+ if CondLabel == TAB_IF:
+ ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
+ else:
+ ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'in')
+ if CondLabel == TAB_IF_N_DEF:
+ ConditionSatisfied = not ConditionSatisfied
+
+ BranchDetermined = ConditionSatisfied
+ IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined]
+ if ConditionSatisfied:
+ self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ elif self._Token in {TAB_ELSE_IF, TAB_ELSE}:
+ ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self._Token))
+ if len(IfList) <= 0:
+ raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
+
+ if IfList[-1][1]:
+ IfList[-1] = [ElseStartPos, False, True]
+ self._WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ else:
+ self._WipeOffArea.append((IfList[-1][0], ElseStartPos))
+ IfList[-1] = [ElseStartPos, True, IfList[-1][2]]
+ if self._Token == TAB_ELSE_IF:
+ Expression = self._GetExpression()
+ ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
+ IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]]
+
+ if IfList[-1][1]:
+ if IfList[-1][2]:
+ IfList[-1][1] = False
+ else:
+ IfList[-1][2] = True
+ self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ elif self._Token == '!endif':
+ if len(IfList) <= 0:
+ raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
+ if IfList[-1][1]:
+ self._WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+ else:
+ self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
+
+ IfList.pop()
+ elif not IfList: # Don't use PCDs inside conditional directive
+ if self.CurrentLineNumber <= RegionLayoutLine:
+ # Don't try the same line twice
+ continue
+ SetPcd = ShortcutPcdPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
+ if SetPcd:
+ self._PcdDict[SetPcd.group('name')] = SetPcd.group('value')
+ RegionLayoutLine = self.CurrentLineNumber
+ continue
+ RegionSize = RegionSizePattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
+ if not RegionSize:
+ RegionLayoutLine = self.CurrentLineNumber
+ continue
+ RegionSizeGuid = RegionSizeGuidPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber])
+ if not RegionSizeGuid:
+ RegionLayoutLine = self.CurrentLineNumber + 1
+ continue
+ self._PcdDict[RegionSizeGuid.group('base')] = RegionSize.group('base')
+ self._PcdDict[RegionSizeGuid.group('size')] = RegionSize.group('size')
+ RegionLayoutLine = self.CurrentLineNumber + 1
+
+ if IfList:
+ raise Warning("Missing !endif", self.FileName, self.CurrentLineNumber)
+ self.Rewind()
+
+ def _CollectMacroPcd(self):
+ MacroDict = {}
+
+ # PCD macro
+ MacroDict.update(GlobalData.gPlatformPcds)
+ MacroDict.update(self._PcdDict)
+
+ # Lowest priority
+ MacroDict.update(GlobalData.gPlatformDefines)
+
+ if self._CurSection:
+ # Defines macro
+ ScopeMacro = self._MacroDict[TAB_COMMON, TAB_COMMON, TAB_COMMON]
+ if ScopeMacro:
+ MacroDict.update(ScopeMacro)
+
+ # Section macro
+ ScopeMacro = self._MacroDict[
+ self._CurSection[0],
+ self._CurSection[1],
+ self._CurSection[2]
+ ]
+ if ScopeMacro:
+ MacroDict.update(ScopeMacro)
+
+ MacroDict.update(GlobalData.gGlobalDefines)
+ MacroDict.update(GlobalData.gCommandLineDefines)
+ for Item in GlobalData.BuildOptionPcd:
+ if isinstance(Item, tuple):
+ continue
+ PcdName, TmpValue = Item.split(TAB_EQUAL_SPLIT)
+ TmpValue = BuildOptionValue(TmpValue, {})
+ MacroDict[PcdName.strip()] = TmpValue
+ # Highest priority
+
+ return MacroDict
+
+ def _EvaluateConditional(self, Expression, Line, Op = None, Value = None):
+ MacroPcdDict = self._CollectMacroPcd()
+ if Op == 'eval':
+ try:
+ if Value:
+ return ValueExpression(Expression, MacroPcdDict)(True)
+ else:
+ return ValueExpression(Expression, MacroPcdDict)()
+ except WrnExpression as Excpt:
+ #
+ # Catch expression evaluation warning here. We need to report
+ # the precise number of line and return the evaluation result
+ #
+ EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
+ File=self.FileName, ExtraData=self._CurrentLine(),
+ Line=Line)
+ return Excpt.result
+ except Exception as Excpt:
+ if hasattr(Excpt, 'Pcd'):
+ if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
+ Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
+ raise Warning("Cannot use this PCD (%s) in an expression as"
+ " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
+ " of the DSC file (%s), and it is currently defined in this section:"
+ " %s, line #: %d." % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE'], Info[0], Info[1]),
+ self.FileName, Line)
+ else:
+ raise Warning("PCD (%s) is not defined in DSC file (%s)" % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE']),
+ self.FileName, Line)
+ else:
+ raise Warning(str(Excpt), self.FileName, Line)
+ else:
+ if Expression.startswith('$(') and Expression[-1] == ')':
+ Expression = Expression[2:-1]
+ return Expression in MacroPcdDict
+
+ ## _IsToken() method
+ #
+ # Check whether input string is found from current char position along
+ # If found, the string value is put into self._Token
+ #
+ # @param self The object pointer
+ # @param String The string to search
+ # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
+ # @retval True Successfully find string, file buffer pointer moved forward
+ # @retval False Not able to find string, file buffer pointer not changed
+ #
+ def _IsToken(self, String, IgnoreCase = False):
+ self._SkipWhiteSpace()
+
+ # Only consider the same line, no multi-line token allowed
+ StartPos = self.CurrentOffsetWithinLine
+ index = -1
+ if IgnoreCase:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(String.upper())
+ else:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(String)
+ if index == 0:
+ self.CurrentOffsetWithinLine += len(String)
+ self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
+ return True
+ return False
+
+ ## _IsKeyword() method
+ #
+ # Check whether input keyword is found from current char position along, whole word only!
+ # If found, the string value is put into self._Token
+ #
+ # @param self The object pointer
+ # @param Keyword The string to search
+ # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
+ # @retval True Successfully find string, file buffer pointer moved forward
+ # @retval False Not able to find string, file buffer pointer not changed
+ #
+ def _IsKeyword(self, KeyWord, IgnoreCase = False):
+ self._SkipWhiteSpace()
+
+ # Only consider the same line, no multi-line token allowed
+ StartPos = self.CurrentOffsetWithinLine
+ index = -1
+ if IgnoreCase:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(KeyWord.upper())
+ else:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(KeyWord)
+ if index == 0:
+ followingChar = self._CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)]
+ if not str(followingChar).isspace() and followingChar not in SEPARATORS:
+ return False
+ self.CurrentOffsetWithinLine += len(KeyWord)
+ self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
+ return True
+ return False
+
+ def _GetExpression(self):
+ Line = self.Profile.FileLinesList[self.CurrentLineNumber - 1]
+ Index = len(Line) - 1
+ while Line[Index] in CR_LB_SET:
+ Index -= 1
+ ExpressionString = self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:Index+1]
+ self.CurrentOffsetWithinLine += len(ExpressionString)
+ ExpressionString = ExpressionString.strip()
+ return ExpressionString
+
+ ## _GetNextWord() method
+ #
+ # Get next C name from file lines
+ # If found, the string value is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a C name string, file buffer pointer moved forward
+ # @retval False Not able to find a C name string, file buffer pointer not changed
+ #
+ def _GetNextWord(self):
+ self._SkipWhiteSpace()
+ if self._EndOfFile():
+ return False
+
+ TempChar = self._CurrentChar()
+ StartPos = self.CurrentOffsetWithinLine
+ if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_':
+ self._GetOneChar()
+ while not self._EndOfLine():
+ TempChar = self._CurrentChar()
+ if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
+ or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-':
+ self._GetOneChar()
+
+ else:
+ break
+
+ self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
+ return True
+
+ return False
+
+ def _GetNextPcdWord(self):
+ self._SkipWhiteSpace()
+ if self._EndOfFile():
+ return False
+
+ TempChar = self._CurrentChar()
+ StartPos = self.CurrentOffsetWithinLine
+ if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_' or TempChar == TAB_SECTION_START or TempChar == TAB_SECTION_END:
+ self._GetOneChar()
+ while not self._EndOfLine():
+ TempChar = self._CurrentChar()
+ if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
+ or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-' or TempChar == TAB_SECTION_START or TempChar == TAB_SECTION_END:
+ self._GetOneChar()
+
+ else:
+ break
+
+ self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
+ return True
+
+ return False
+
+ ## _GetNextToken() method
+ #
+ # Get next token unit before a separator
+ # If found, the string value is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a token unit, file buffer pointer moved forward
+ # @retval False Not able to find a token unit, file buffer pointer not changed
+ #
+ def _GetNextToken(self):
+ # Skip leading spaces, if exist.
+ self._SkipWhiteSpace()
+ if self._EndOfFile():
+ return False
+ # Record the token start position, the position of the first non-space char.
+ StartPos = self.CurrentOffsetWithinLine
+ StartLine = self.CurrentLineNumber
+ while StartLine == self.CurrentLineNumber:
+ TempChar = self._CurrentChar()
+ # Try to find the end char that is not a space and not in separator tuple.
+ # That is, when we got a space or any char in the tuple, we got the end of token.
+ if not str(TempChar).isspace() and TempChar not in SEPARATORS:
+ self._GetOneChar()
+ # if we happen to meet a separator as the first char, we must proceed to get it.
+ # That is, we get a token that is a separator char. normally it is the boundary of other tokens.
+ elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPARATORS:
+ self._GetOneChar()
+ break
+ else:
+ break
+# else:
+# return False
+
+ EndPos = self.CurrentOffsetWithinLine
+ if self.CurrentLineNumber != StartLine:
+ EndPos = len(self.Profile.FileLinesList[StartLine-1])
+ self._Token = self.Profile.FileLinesList[StartLine-1][StartPos: EndPos]
+ if self._Token.lower() in {TAB_IF, TAB_END_IF, TAB_ELSE_IF, TAB_ELSE, TAB_IF_DEF, TAB_IF_N_DEF, TAB_ERROR, TAB_INCLUDE}:
+ self._Token = self._Token.lower()
+ if StartPos != self.CurrentOffsetWithinLine:
+ return True
+ else:
+ return False
+
+ ## _GetNextGuid() method
+ #
+ # Get next token unit before a separator
+ # If found, the GUID string is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a registry format GUID, file buffer pointer moved forward
+ # @retval False Not able to find a registry format GUID, file buffer pointer not changed
+ #
+ def _GetNextGuid(self):
+ if not self._GetNextToken():
+ return False
+ if GlobalData.gGuidPattern.match(self._Token) is not None:
+ return True
+ elif self._Token in GlobalData.gGuidDict:
+ return True
+ else:
+ self._UndoToken()
+ return False
+
+ @staticmethod
+ def _Verify(Name, Value, Scope):
+ # value verification only applies to numeric values.
+ if Scope not in TAB_PCD_NUMERIC_TYPES:
+ return
+
+ ValueNumber = 0
+ try:
+ ValueNumber = int(Value, 0)
+ except:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "The value is not valid dec or hex number for %s." % Name)
+ if ValueNumber < 0:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "The value can't be set to negative value for %s." % Name)
+ if ValueNumber > MAX_VAL_TYPE[Scope]:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)
+ return True
+
+ ## _UndoToken() method
+ #
+ # Go back one token unit in file buffer
+ #
+ # @param self The object pointer
+ #
+ def _UndoToken(self):
+ self._UndoOneChar()
+ while self._CurrentChar().isspace():
+ if not self._UndoOneChar():
+ self._GetOneChar()
+ return
+
+
+ StartPos = self.CurrentOffsetWithinLine
+ CurrentLine = self.CurrentLineNumber
+ while CurrentLine == self.CurrentLineNumber:
+
+ TempChar = self._CurrentChar()
+ # Try to find the end char that is not a space and not in separator tuple.
+ # That is, when we got a space or any char in the tuple, we got the end of token.
+ if not str(TempChar).isspace() and not TempChar in SEPARATORS:
+ if not self._UndoOneChar():
+ return
+ # if we happen to meet a separator as the first char, we must proceed to get it.
+ # That is, we get a token that is a separator char. normally it is the boundary of other tokens.
+ elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPARATORS:
+ return
+ else:
+ break
+
+ self._GetOneChar()
+
+ ## _GetNextHexNumber() method
+ #
+ # Get next HEX data before a separator
+ # If found, the HEX data is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a HEX data, file buffer pointer moved forward
+ # @retval False Not able to find a HEX data, file buffer pointer not changed
+ #
+ def _GetNextHexNumber(self):
+ if not self._GetNextToken():
+ return False
+ if GlobalData.gHexPatternAll.match(self._Token):
+ return True
+ else:
+ self._UndoToken()
+ return False
+
+ ## _GetNextDecimalNumber() method
+ #
+ # Get next decimal data before a separator
+ # If found, the decimal data is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a decimal data, file buffer pointer moved forward
+ # @retval False Not able to find a decimal data, file buffer pointer not changed
+ #
+ def _GetNextDecimalNumber(self):
+ if not self._GetNextToken():
+ return False
+ if self._Token.isdigit():
+ return True
+ else:
+ self._UndoToken()
+ return False
+
+ def _GetNextPcdSettings(self):
+ if not self._GetNextWord():
+ raise Warning.Expected("<PcdTokenSpaceCName>", self.FileName, self.CurrentLineNumber)
+ pcdTokenSpaceCName = self._Token
+
+ if not self._IsToken(TAB_SPLIT):
+ raise Warning.Expected(".", self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextWord():
+ raise Warning.Expected("<PcdCName>", self.FileName, self.CurrentLineNumber)
+ pcdCName = self._Token
+
+ Fields = []
+ while self._IsToken(TAB_SPLIT):
+ if not self._GetNextPcdWord():
+ raise Warning.Expected("Pcd Fields", self.FileName, self.CurrentLineNumber)
+ Fields.append(self._Token)
+
+ return (pcdCName, pcdTokenSpaceCName,TAB_SPLIT.join(Fields))
+
+ ## _GetStringData() method
+ #
+ # Get string contents quoted in ""
+ # If found, the decimal data is put into self._Token
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a string data, file buffer pointer moved forward
+ # @retval False Not able to find a string data, file buffer pointer not changed
+ #
+ def _GetStringData(self):
+ QuoteToUse = None
+ if self._Token.startswith(T_CHAR_DOUBLE_QUOTE) or self._Token.startswith("L\""):
+ QuoteToUse = T_CHAR_DOUBLE_QUOTE
+ elif self._Token.startswith(T_CHAR_SINGLE_QUOTE) or self._Token.startswith("L\'"):
+ QuoteToUse = T_CHAR_SINGLE_QUOTE
+ else:
+ return False
+
+ self._UndoToken()
+ self._SkipToToken(QuoteToUse)
+ currentLineNumber = self.CurrentLineNumber
+
+ if not self._SkipToToken(QuoteToUse):
+ raise Warning(QuoteToUse, self.FileName, self.CurrentLineNumber)
+ if currentLineNumber != self.CurrentLineNumber:
+ raise Warning(QuoteToUse, self.FileName, self.CurrentLineNumber)
+ self._Token = self._SkippedChars.rstrip(QuoteToUse)
+ return True
+
+ ## _SkipToToken() method
+ #
+ # Search forward in file buffer for the string
+ # The skipped chars are put into self._SkippedChars
+ #
+ # @param self The object pointer
+ # @param String The string to search
+ # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
+ # @retval True Successfully find the string, file buffer pointer moved forward
+ # @retval False Not able to find the string, file buffer pointer not changed
+ #
+ def _SkipToToken(self, String, IgnoreCase = False):
+ StartPos = self.GetFileBufferPos()
+
+ self._SkippedChars = ""
+ while not self._EndOfFile():
+ index = -1
+ if IgnoreCase:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(String.upper())
+ else:
+ index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(String)
+ if index == 0:
+ self.CurrentOffsetWithinLine += len(String)
+ self._SkippedChars += String
+ return True
+ self._SkippedChars += str(self._CurrentChar())
+ self._GetOneChar()
+
+ self.SetFileBufferPos(StartPos)
+ self._SkippedChars = ""
+ return False
+
+ ## GetFileBufferPos() method
+ #
+ # Return the tuple of current line and offset within the line
+ #
+ # @param self The object pointer
+ # @retval Tuple Line number and offset pair
+ #
+ def GetFileBufferPos(self):
+ return (self.CurrentLineNumber, self.CurrentOffsetWithinLine)
+
+ ## SetFileBufferPos() method
+ #
+ # Restore the file buffer position
+ #
+ # @param self The object pointer
+ # @param Pos The new file buffer position
+ #
+ def SetFileBufferPos(self, Pos):
+ (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos
+
+ ## Preprocess() method
+ #
+ # Preprocess comment, conditional directive, include directive, replace macro.
+ # Exception will be raised if syntax error found
+ #
+ # @param self The object pointer
+ #
+ def Preprocess(self):
+ self._StringToList()
+ self.PreprocessFile()
+ self.PreprocessIncludeFile()
+ self._StringToList()
+ self.PreprocessFile()
+ self.PreprocessConditionalStatement()
+ self._StringToList()
+ for Pos in self._WipeOffArea:
+ self._ReplaceFragment(Pos[0], Pos[1])
+ self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
+
+ while self._GetDefines():
+ pass
+
+ ## ParseFile() method
+ #
+ # Parse the file profile buffer to extract fd, fv ... information
+ # Exception will be raised if syntax error found
+ #
+ # @param self The object pointer
+ #
+ def ParseFile(self):
+ try:
+ self.Preprocess()
+ self._GetError()
+ #
+ # Keep processing sections of the FDF until no new sections or a syntax error is found
+ #
+ while self._GetFd() or self._GetFv() or self._GetFmp() or self._GetCapsule() or self._GetRule() or self._GetOptionRom():
+ pass
+
+ except Warning as X:
+ self._UndoToken()
+ #'\n\tGot Token: \"%s\" from File %s\n' % (self._Token, FileLineTuple[0]) + \
+ # At this point, the closest parent would be the included file itself
+ Profile = GetParentAtLine(X.OriginalLineNumber)
+ if Profile is not None:
+ X.Message += ' near line %d, column %d: %s' \
+ % (X.LineNumber, 0, Profile.FileLinesList[X.LineNumber-1])
+ else:
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ X.Message += ' near line %d, column %d: %s' \
+ % (FileLineTuple[1], self.CurrentOffsetWithinLine + 1, self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:].rstrip(TAB_LINE_BREAK).rstrip(T_CHAR_CR))
+ raise
+
+ ## SectionParser() method
+ #
+ # Parse the file section info
+ # Exception will be raised if syntax error found
+ #
+ # @param self The object pointer
+ # @param section The section string
+
+ def SectionParser(self, section):
+ S = section.upper()
+ if not S.startswith("[DEFINES") and not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \
+ and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM.") and not S.startswith('[FMPPAYLOAD.'):
+ raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [Rule.], [OptionRom.], [FMPPAYLOAD.])", self.FileName, self.CurrentLineNumber)
+
+ ## _GetDefines() method
+ #
+ # Get Defines section contents and store its data into AllMacrosList
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a Defines
+ # @retval False Not able to find a Defines
+ #
+ def _GetDefines(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[DEFINES"):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[DEFINES", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning.Expected("[DEFINES", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ while self._GetNextWord():
+ # handle the SET statement
+ if self._Token == 'SET':
+ self._UndoToken()
+ self._GetSetStatement(None)
+ continue
+
+ Macro = self._Token
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken() or self._Token.startswith(TAB_SECTION_START):
+ raise Warning.Expected("MACRO value", self.FileName, self.CurrentLineNumber)
+ Value = self._Token
+
+ return False
+
+ ##_GetError() method
+ def _GetError(self):
+ #save the Current information
+ CurrentLine = self.CurrentLineNumber
+ CurrentOffset = self.CurrentOffsetWithinLine
+ while self._GetNextToken():
+ if self._Token == TAB_ERROR:
+ EdkLogger.error('FdfParser', ERROR_STATEMENT, self._CurrentLine().replace(TAB_ERROR, '', 1), File=self.FileName, Line=self.CurrentLineNumber)
+ self.CurrentLineNumber = CurrentLine
+ self.CurrentOffsetWithinLine = CurrentOffset
+
+ ## _GetFd() method
+ #
+ # Get FD section contents and store its data into FD dictionary of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a FD
+ # @retval False Not able to find a FD
+ #
+ def _GetFd(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[FD."):
+ if not S.startswith("[FV.") and not S.startswith('[FMPPAYLOAD.') and not S.startswith("[CAPSULE.") \
+ and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
+ raise Warning("Unknown section", self.FileName, self.CurrentLineNumber)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[FD.", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning.Expected("[FD.]", self.FileName, self.CurrentLineNumber)
+
+ FdName = self._GetUiName()
+ if FdName == "":
+ if len (self.Profile.FdDict) == 0:
+ FdName = GenFdsGlobalVariable.PlatformName
+ if FdName == "" and GlobalData.gActivePlatform:
+ FdName = GlobalData.gActivePlatform.PlatformName
+ self.Profile.FdNameNotSet = True
+ else:
+ raise Warning.Expected("FdName in [FD.] section", self.FileName, self.CurrentLineNumber)
+ self.CurrentFdName = FdName.upper()
+
+ if self.CurrentFdName in self.Profile.FdDict:
+ raise Warning("Unexpected the same FD name", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ FdObj = FD()
+ FdObj.FdUiName = self.CurrentFdName
+ self.Profile.FdDict[self.CurrentFdName] = FdObj
+
+ if len (self.Profile.FdDict) > 1 and self.Profile.FdNameNotSet:
+ raise Warning.Expected("all FDs have their name", self.FileName, self.CurrentLineNumber)
+
+ Status = self._GetCreateFile(FdObj)
+ if not Status:
+ raise Warning("FD name error", self.FileName, self.CurrentLineNumber)
+
+ while self._GetTokenStatements(FdObj):
+ pass
+ for Attr in ("BaseAddress", "Size", "ErasePolarity"):
+ if getattr(FdObj, Attr) is None:
+ self._GetNextToken()
+ raise Warning("Keyword %s missing" % Attr, self.FileName, self.CurrentLineNumber)
+
+ if not FdObj.BlockSizeList:
+ FdObj.BlockSizeList.append((1, FdObj.Size, None))
+
+ self._GetDefineStatements(FdObj)
+
+ self._GetSetStatements(FdObj)
+
+ if not self._GetRegionLayout(FdObj):
+ raise Warning.Expected("region layout", self.FileName, self.CurrentLineNumber)
+
+ while self._GetRegionLayout(FdObj):
+ pass
+ return True
+
+ ## _GetUiName() method
+ #
+ # Return the UI name of a section
+ #
+ # @param self The object pointer
+ # @retval FdName UI name
+ #
+ def _GetUiName(self):
+ Name = ""
+ if self._GetNextWord():
+ Name = self._Token
+
+ return Name
+
+ ## _GetCreateFile() method
+ #
+ # Return the output file name of object
+ #
+ # @param self The object pointer
+ # @param Obj object whose data will be stored in file
+ # @retval FdName UI name
+ #
+ def _GetCreateFile(self, Obj):
+ if self._IsKeyword("CREATE_FILE"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("file name", self.FileName, self.CurrentLineNumber)
+
+ FileName = self._Token
+ Obj.CreateFileName = FileName
+
+ return True
+
+ def SetPcdLocalation(self,pcdpair):
+ self.Profile.PcdLocalDict[pcdpair] = (self.Profile.FileName,self.CurrentLineNumber)
+
+ ## _GetTokenStatements() method
+ #
+ # Get token statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom token statement is got
+ #
+ def _GetTokenStatements(self, Obj):
+ if self._IsKeyword("BaseAddress"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex base address", self.FileName, self.CurrentLineNumber)
+
+ Obj.BaseAddress = self._Token
+
+ if self._IsToken(TAB_VALUE_SPLIT):
+ pcdPair = self._GetNextPcdSettings()
+ Obj.BaseAddressPcd = pcdPair
+ self.Profile.PcdDict[pcdPair] = Obj.BaseAddress
+ self.SetPcdLocalation(pcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
+ return True
+
+ if self._IsKeyword("Size"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex size", self.FileName, self.CurrentLineNumber)
+
+ Size = self._Token
+ if self._IsToken(TAB_VALUE_SPLIT):
+ pcdPair = self._GetNextPcdSettings()
+ Obj.SizePcd = pcdPair
+ self.Profile.PcdDict[pcdPair] = Size
+ self.SetPcdLocalation(pcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
+ Obj.Size = int(Size, 0)
+ return True
+
+ if self._IsKeyword("ErasePolarity"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("Erase Polarity", self.FileName, self.CurrentLineNumber)
+
+ if not self._Token in {"1", "0"}:
+ raise Warning.Expected("1 or 0 Erase Polarity", self.FileName, self.CurrentLineNumber)
+
+ Obj.ErasePolarity = self._Token
+ return True
+
+ return self._GetBlockStatements(Obj)
+
+ ## _GetAddressStatements() method
+ #
+ # Get address statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom address statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetAddressStatements(self, Obj):
+ if self._IsKeyword("BsBaseAddress"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
+ raise Warning.Expected("address", self.FileName, self.CurrentLineNumber)
+
+ BsAddress = int(self._Token, 0)
+ Obj.BsBaseAddress = BsAddress
+
+ if self._IsKeyword("RtBaseAddress"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
+ raise Warning.Expected("address", self.FileName, self.CurrentLineNumber)
+
+ RtAddress = int(self._Token, 0)
+ Obj.RtBaseAddress = RtAddress
+
+ ## _GetBlockStatements() method
+ #
+ # Get block statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom block statement is got
+ #
+ def _GetBlockStatements(self, Obj):
+ IsBlock = False
+ while self._GetBlockStatement(Obj):
+ IsBlock = True
+
+ Item = Obj.BlockSizeList[-1]
+ if Item[0] is None or Item[1] is None:
+ raise Warning.Expected("block statement", self.FileName, self.CurrentLineNumber)
+ return IsBlock
+
+ ## _GetBlockStatement() method
+ #
+ # Get block statement
+ #
+ # @param self The object pointer
+ # @param Obj for whom block statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetBlockStatement(self, Obj):
+ if not self._IsKeyword("BlockSize"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber() and not self._GetNextDecimalNumber():
+ raise Warning.Expected("Hex or Integer block size", self.FileName, self.CurrentLineNumber)
+
+ BlockSize = self._Token
+ BlockSizePcd = None
+ if self._IsToken(TAB_VALUE_SPLIT):
+ PcdPair = self._GetNextPcdSettings()
+ BlockSizePcd = PcdPair
+ self.Profile.PcdDict[PcdPair] = BlockSize
+ self.SetPcdLocalation(PcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
+ BlockSize = int(BlockSize, 0)
+
+ BlockNumber = None
+ if self._IsKeyword("NumBlocks"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
+ raise Warning.Expected("block numbers", self.FileName, self.CurrentLineNumber)
+
+ BlockNumber = int(self._Token, 0)
+
+ Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd))
+ return True
+
+ ## _GetDefineStatements() method
+ #
+ # Get define statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom define statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetDefineStatements(self, Obj):
+ while self._GetDefineStatement(Obj):
+ pass
+
+ ## _GetDefineStatement() method
+ #
+ # Get define statement
+ #
+ # @param self The object pointer
+ # @param Obj for whom define statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetDefineStatement(self, Obj):
+ if self._IsKeyword(TAB_DEFINE):
+ self._GetNextToken()
+ Macro = self._Token
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
+
+ Value = self._Token
+ Macro = '$(' + Macro + ')'
+ Obj.DefineVarDict[Macro] = Value
+ return True
+
+ return False
+
+ ## _GetSetStatements() method
+ #
+ # Get set statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom set statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetSetStatements(self, Obj):
+ while self._GetSetStatement(Obj):
+ pass
+
+ ## _GetSetStatement() method
+ #
+ # Get set statement
+ #
+ # @param self The object pointer
+ # @param Obj for whom set statement is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetSetStatement(self, Obj):
+ if self._IsKeyword("SET"):
+ PcdPair = self._GetNextPcdSettings()
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ Value = self._GetExpression()
+ Value = self._EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
+
+ if Obj:
+ Obj.SetVarDict[PcdPair] = Value
+ self.Profile.PcdDict[PcdPair] = Value
+ self.SetPcdLocalation(PcdPair)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
+ return True
+
+ return False
+
+ ## _CalcRegionExpr(self)
+ #
+ # Calculate expression for offset or size of a region
+ #
+ # @return: None if invalid expression
+ # Calculated number if successfully
+ #
+ def _CalcRegionExpr(self):
+ StartPos = self.GetFileBufferPos()
+ Expr = ''
+ PairCount = 0
+ while not self._EndOfFile():
+ CurCh = self._CurrentChar()
+ if CurCh == '(':
+ PairCount += 1
+ elif CurCh == ')':
+ PairCount -= 1
+
+ if CurCh in '|\r\n' and PairCount == 0:
+ break
+ Expr += CurCh
+ self._GetOneChar()
+ try:
+ return int(
+ ValueExpression(Expr,
+ self._CollectMacroPcd()
+ )(True), 0)
+ except Exception:
+ self.SetFileBufferPos(StartPos)
+ return None
+
+ ## _GetRegionLayout() method
+ #
+ # Get region layout for FD
+ #
+ # @param self The object pointer
+ # @param theFd for whom region is got
+ # @retval True Successfully find
+ # @retval False Not able to find
+ #
+ def _GetRegionLayout(self, theFd):
+ Offset = self._CalcRegionExpr()
+ if Offset is None:
+ return False
+
+ RegionObj = Region()
+ RegionObj.Offset = Offset
+ theFd.RegionList.append(RegionObj)
+
+ if not self._IsToken(TAB_VALUE_SPLIT):
+ raise Warning.Expected("'|'", self.FileName, self.CurrentLineNumber)
+
+ Size = self._CalcRegionExpr()
+ if Size is None:
+ raise Warning.Expected("Region Size", self.FileName, self.CurrentLineNumber)
+ RegionObj.Size = Size
+
+ if not self._GetNextWord():
+ return True
+
+ if not self._Token in {"SET", BINARY_FILE_TYPE_FV, "FILE", "DATA", "CAPSULE", "INF"}:
+ #
+ # If next token is a word which is not a valid FV type, it might be part of [PcdOffset[|PcdSize]]
+ # Or it might be next region's offset described by an expression which starts with a PCD.
+ # PcdOffset[|PcdSize] or OffsetPcdExpression|Size
+ #
+ self._UndoToken()
+ IsRegionPcd = (RegionSizeGuidPattern.match(self._CurrentLine()[self.CurrentOffsetWithinLine:]) or
+ RegionOffsetPcdPattern.match(self._CurrentLine()[self.CurrentOffsetWithinLine:]))
+ if IsRegionPcd:
+ RegionObj.PcdOffset = self._GetNextPcdSettings()
+ self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + int(theFd.BaseAddress, 0))
+ self.SetPcdLocalation(RegionObj.PcdOffset)
+ self._PcdDict['%s.%s' % (RegionObj.PcdOffset[1], RegionObj.PcdOffset[0])] = "0x%x" % RegionObj.Offset
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple
+ if self._IsToken(TAB_VALUE_SPLIT):
+ RegionObj.PcdSize = self._GetNextPcdSettings()
+ self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size
+ self.SetPcdLocalation(RegionObj.PcdSize)
+ self._PcdDict['%s.%s' % (RegionObj.PcdSize[1], RegionObj.PcdSize[0])] = "0x%x" % RegionObj.Size
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple
+
+ if not self._GetNextWord():
+ return True
+
+ if self._Token == "SET":
+ self._UndoToken()
+ self._GetSetStatements(RegionObj)
+ if not self._GetNextWord():
+ return True
+
+ elif self._Token == BINARY_FILE_TYPE_FV:
+ self._UndoToken()
+ self._GetRegionFvType(RegionObj)
+
+ elif self._Token == "CAPSULE":
+ self._UndoToken()
+ self._GetRegionCapType(RegionObj)
+
+ elif self._Token == "FILE":
+ self._UndoToken()
+ self._GetRegionFileType(RegionObj)
+
+ elif self._Token == "INF":
+ self._UndoToken()
+ RegionObj.RegionType = "INF"
+ while self._IsKeyword("INF"):
+ self._UndoToken()
+ ffsInf = self._ParseInfStatement()
+ if not ffsInf:
+ break
+ RegionObj.RegionDataList.append(ffsInf)
+
+ elif self._Token == "DATA":
+ self._UndoToken()
+ self._GetRegionDataType(RegionObj)
+ else:
+ self._UndoToken()
+ if self._GetRegionLayout(theFd):
+ return True
+ raise Warning("A valid region type was not found. "
+ "Valid types are [SET, FV, CAPSULE, FILE, DATA, INF]. This error occurred",
+ self.FileName, self.CurrentLineNumber)
+
+ return True
+
+ ## _GetRegionFvType() method
+ #
+ # Get region fv data for region
+ #
+ # @param self The object pointer
+ # @param RegionObj for whom region data is got
+ #
+ def _GetRegionFvType(self, RegionObj):
+ if not self._IsKeyword(BINARY_FILE_TYPE_FV):
+ raise Warning.Expected("'FV'", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionType = BINARY_FILE_TYPE_FV
+ RegionObj.RegionDataList.append((self._Token).upper())
+
+ while self._IsKeyword(BINARY_FILE_TYPE_FV):
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionDataList.append((self._Token).upper())
+
+ ## _GetRegionCapType() method
+ #
+ # Get region capsule data for region
+ #
+ # @param self The object pointer
+ # @param RegionObj for whom region data is got
+ #
+ def _GetRegionCapType(self, RegionObj):
+ if not self._IsKeyword("CAPSULE"):
+ raise Warning.Expected("'CAPSULE'", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("CAPSULE name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionType = "CAPSULE"
+ RegionObj.RegionDataList.append(self._Token)
+
+ while self._IsKeyword("CAPSULE"):
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("CAPSULE name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionDataList.append(self._Token)
+
+ ## _GetRegionFileType() method
+ #
+ # Get region file data for region
+ #
+ # @param self The object pointer
+ # @param RegionObj for whom region data is got
+ #
+ def _GetRegionFileType(self, RegionObj):
+ if not self._IsKeyword("FILE"):
+ raise Warning.Expected("'FILE'", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionType = "FILE"
+ RegionObj.RegionDataList.append(self._Token)
+
+ while self._IsKeyword("FILE"):
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FILE name", self.FileName, self.CurrentLineNumber)
+
+ RegionObj.RegionDataList.append(self._Token)
+
+ ## _GetRegionDataType() method
+ #
+ # Get region array data for region
+ #
+ # @param self The object pointer
+ # @param RegionObj for whom region data is got
+ #
+ def _GetRegionDataType(self, RegionObj):
+ if not self._IsKeyword("DATA"):
+ raise Warning.Expected("Region Data type", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
+
+ if len(self._Token) > 18:
+ raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
+
+ # convert hex string value to byte hex string array
+ AllString = self._Token
+ AllStrLen = len (AllString)
+ DataString = ""
+ while AllStrLen > 4:
+ DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + TAB_COMMA_SPLIT
+ AllStrLen = AllStrLen - 2
+ DataString = DataString + AllString[:AllStrLen] + TAB_COMMA_SPLIT
+
+ # byte value array
+ if len (self._Token) <= 4:
+ while self._IsToken(TAB_COMMA_SPLIT):
+ if not self._GetNextHexNumber():
+ raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
+ if len(self._Token) > 4:
+ raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
+ DataString += self._Token
+ DataString += TAB_COMMA_SPLIT
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ DataString = DataString.rstrip(TAB_COMMA_SPLIT)
+ RegionObj.RegionType = "DATA"
+ RegionObj.RegionDataList.append(DataString)
+
+ while self._IsKeyword("DATA"):
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
+
+ if len(self._Token) > 18:
+ raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
+
+ # convert hex string value to byte hex string array
+ AllString = self._Token
+ AllStrLen = len (AllString)
+ DataString = ""
+ while AllStrLen > 4:
+ DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + TAB_COMMA_SPLIT
+ AllStrLen = AllStrLen - 2
+ DataString = DataString + AllString[:AllStrLen] + TAB_COMMA_SPLIT
+
+ # byte value array
+ if len (self._Token) <= 4:
+ while self._IsToken(TAB_COMMA_SPLIT):
+ if not self._GetNextHexNumber():
+ raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
+ if len(self._Token) > 4:
+ raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
+ DataString += self._Token
+ DataString += TAB_COMMA_SPLIT
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ DataString = DataString.rstrip(TAB_COMMA_SPLIT)
+ RegionObj.RegionDataList.append(DataString)
+
+ ## _GetFv() method
+ #
+ # Get FV section contents and store its data into FV dictionary of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a FV
+ # @retval False Not able to find a FV
+ #
+ def _GetFv(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[FV."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[FV.", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning("Unknown Keyword '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ FvName = self._GetUiName()
+ self.CurrentFvName = FvName.upper()
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ FvObj = FV(Name=self.CurrentFvName)
+ self.Profile.FvDict[self.CurrentFvName] = FvObj
+
+ Status = self._GetCreateFile(FvObj)
+ if not Status:
+ raise Warning("FV name error", self.FileName, self.CurrentLineNumber)
+
+ self._GetDefineStatements(FvObj)
+
+ self._GetAddressStatements(FvObj)
+
+ while True:
+ self._GetSetStatements(FvObj)
+
+ if not (self._GetBlockStatement(FvObj) or self._GetFvBaseAddress(FvObj) or
+ self._GetFvForceRebase(FvObj) or self._GetFvAlignment(FvObj) or
+ self._GetFvAttributes(FvObj) or self._GetFvNameGuid(FvObj) or
+ self._GetFvExtEntryStatement(FvObj) or self._GetFvNameString(FvObj)):
+ break
+
+ if FvObj.FvNameString == 'TRUE' and not FvObj.FvNameGuid:
+ raise Warning("FvNameString found but FvNameGuid was not found", self.FileName, self.CurrentLineNumber)
+
+ self._GetAprioriSection(FvObj)
+ self._GetAprioriSection(FvObj)
+
+ while True:
+ isInf = self._GetInfStatement(FvObj)
+ isFile = self._GetFileStatement(FvObj)
+ if not isInf and not isFile:
+ break
+
+ return True
+
+ ## _GetFvAlignment() method
+ #
+ # Get alignment for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom alignment is got
+ # @retval True Successfully find a alignment statement
+ # @retval False Not able to find a alignment statement
+ #
+ def _GetFvAlignment(self, Obj):
+ if not self._IsKeyword("FvAlignment"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("alignment value", self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() not in {"1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \
+ "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \
+ "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \
+ "1G", "2G"}:
+ raise Warning("Unknown alignment value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ Obj.FvAlignment = self._Token
+ return True
+
+ ## _GetFvBaseAddress() method
+ #
+ # Get BaseAddress for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom FvBaseAddress is got
+ # @retval True Successfully find a FvBaseAddress statement
+ # @retval False Not able to find a FvBaseAddress statement
+ #
+ def _GetFvBaseAddress(self, Obj):
+ if not self._IsKeyword("FvBaseAddress"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV base address value", self.FileName, self.CurrentLineNumber)
+
+ if not BaseAddrValuePattern.match(self._Token.upper()):
+ raise Warning("Unknown FV base address value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ Obj.FvBaseAddress = self._Token
+ return True
+
+ ## _GetFvForceRebase() method
+ #
+ # Get FvForceRebase for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom FvForceRebase is got
+ # @retval True Successfully find a FvForceRebase statement
+ # @retval False Not able to find a FvForceRebase statement
+ #
+ def _GetFvForceRebase(self, Obj):
+ if not self._IsKeyword("FvForceRebase"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FvForceRebase value", self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() not in {"TRUE", "FALSE", "0", "0X0", "0X00", "1", "0X1", "0X01"}:
+ raise Warning("Unknown FvForceRebase value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() in {"TRUE", "1", "0X1", "0X01"}:
+ Obj.FvForceRebase = True
+ elif self._Token.upper() in {"FALSE", "0", "0X0", "0X00"}:
+ Obj.FvForceRebase = False
+ else:
+ Obj.FvForceRebase = None
+
+ return True
+
+
+ ## _GetFvAttributes() method
+ #
+ # Get attributes for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom attribute is got
+ # @retval None
+ #
+ def _GetFvAttributes(self, FvObj):
+ IsWordToken = False
+ while self._GetNextWord():
+ IsWordToken = True
+ name = self._Token
+ if name not in {"ERASE_POLARITY", "MEMORY_MAPPED", \
+ "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \
+ "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \
+ "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \
+ "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \
+ "WRITE_POLICY_RELIABLE", "WEAK_ALIGNMENT", "FvUsedSizeEnable"}:
+ self._UndoToken()
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken() or self._Token.upper() not in {"TRUE", "FALSE", "1", "0"}:
+ raise Warning.Expected("TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvAttributeDict[name] = self._Token
+
+ return IsWordToken
+
+ ## _GetFvNameGuid() method
+ #
+ # Get FV GUID for FV
+ #
+ # @param self The object pointer
+ # @param Obj for whom GUID is got
+ # @retval None
+ #
+ def _GetFvNameGuid(self, FvObj):
+ if not self._IsKeyword("FvNameGuid"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextGuid():
+ raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+
+ FvObj.FvNameGuid = self._Token
+
+ return True
+
+ def _GetFvNameString(self, FvObj):
+ if not self._IsKeyword("FvNameString"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken() or self._Token.upper() not in {'TRUE', 'FALSE'}:
+ raise Warning.Expected("TRUE or FALSE for FvNameString", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvNameString = self._Token
+
+ return True
+
+ def _GetFvExtEntryStatement(self, FvObj):
+ if not (self._IsKeyword("FV_EXT_ENTRY") or self._IsKeyword("FV_EXT_ENTRY_TYPE")):
+ return False
+
+ if not self._IsKeyword ("TYPE"):
+ raise Warning.Expected("'TYPE'", self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber() and not self._GetNextDecimalNumber():
+ raise Warning.Expected("Hex FV extension entry type value At Line ", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvExtEntryTypeValue.append(self._Token)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsKeyword("FILE") and not self._IsKeyword("DATA"):
+ raise Warning.Expected("'FILE' or 'DATA'", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvExtEntryType.append(self._Token)
+
+ if self._Token == 'DATA':
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
+
+ if len(self._Token) > 4:
+ raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
+
+ DataString = self._Token
+ DataString += TAB_COMMA_SPLIT
+
+ while self._IsToken(TAB_COMMA_SPLIT):
+ if not self._GetNextHexNumber():
+ raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
+ if len(self._Token) > 4:
+ raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
+ DataString += self._Token
+ DataString += TAB_COMMA_SPLIT
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ DataString = DataString.rstrip(TAB_COMMA_SPLIT)
+ FvObj.FvExtEntryData.append(DataString)
+
+ if self._Token == 'FILE':
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV Extension Entry file path At Line ", self.FileName, self.CurrentLineNumber)
+
+ FvObj.FvExtEntryData.append(self._Token)
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ return True
+
+ ## _GetAprioriSection() method
+ #
+ # Get token statements
+ #
+ # @param self The object pointer
+ # @param FvObj for whom apriori is got
+ # @retval True Successfully find apriori statement
+ # @retval False Not able to find apriori statement
+ #
+ def _GetAprioriSection(self, FvObj):
+ if not self._IsKeyword("APRIORI"):
+ return False
+
+ if not self._IsKeyword("PEI") and not self._IsKeyword("DXE"):
+ raise Warning.Expected("Apriori file type", self.FileName, self.CurrentLineNumber)
+ AprType = self._Token
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ AprSectionObj = AprioriSection()
+ AprSectionObj.AprioriType = AprType
+
+ self._GetDefineStatements(AprSectionObj)
+
+ while True:
+ IsInf = self._GetInfStatement(AprSectionObj)
+ IsFile = self._GetFileStatement(AprSectionObj)
+ if not IsInf and not IsFile:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ FvObj.AprioriSectionList.append(AprSectionObj)
+ return True
+
+ def _ParseInfStatement(self):
+ if not self._IsKeyword("INF"):
+ return None
+
+ ffsInf = FfsInfStatement()
+ self._GetInfOptions(ffsInf)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("INF file path", self.FileName, self.CurrentLineNumber)
+ ffsInf.InfFileName = self._Token
+ if not ffsInf.InfFileName.endswith('.inf'):
+ raise Warning.Expected(".inf file path", self.FileName, self.CurrentLineNumber)
+
+ ffsInf.CurrentLineNum = self.CurrentLineNumber
+ ffsInf.CurrentLineContent = self._CurrentLine()
+
+ #Replace $(SAPCE) with real space
+ ffsInf.InfFileName = ffsInf.InfFileName.replace('$(SPACE)', ' ')
+
+ if ffsInf.InfFileName.replace(TAB_WORKSPACE, '').find('$') == -1:
+ #do case sensitive check for file path
+ ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ NewFileName = ffsInf.InfFileName
+ if ffsInf.OverrideGuid:
+ NewFileName = ProcessDuplicatedInf(PathClass(ffsInf.InfFileName,GenFdsGlobalVariable.WorkSpaceDir), ffsInf.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir).Path
+
+ if not NewFileName in self.Profile.InfList:
+ self.Profile.InfList.append(NewFileName)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.InfFileLineList.append(FileLineTuple)
+ if ffsInf.UseArch:
+ if ffsInf.UseArch not in self.Profile.InfDict:
+ self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
+ else:
+ self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
+ else:
+ self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
+
+ if self._IsToken(TAB_VALUE_SPLIT):
+ if self._IsKeyword('RELOCS_STRIPPED'):
+ ffsInf.KeepReloc = False
+ elif self._IsKeyword('RELOCS_RETAINED'):
+ ffsInf.KeepReloc = True
+ else:
+ raise Warning("Unknown reloc strip flag '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ return ffsInf
+
+ ## _GetInfStatement() method
+ #
+ # Get INF statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom inf statement is got
+ # @retval True Successfully find inf statement
+ # @retval False Not able to find inf statement
+ #
+ def _GetInfStatement(self, Obj, ForCapsule=False):
+ ffsInf = self._ParseInfStatement()
+ if not ffsInf:
+ return False
+
+ if ForCapsule:
+ myCapsuleFfs = CapsuleFfs()
+ myCapsuleFfs.Ffs = ffsInf
+ Obj.CapsuleDataList.append(myCapsuleFfs)
+ else:
+ Obj.FfsList.append(ffsInf)
+ return True
+
+ ## _GetInfOptions() method
+ #
+ # Get options for INF
+ #
+ # @param self The object pointer
+ # @param FfsInfObj for whom option is got
+ #
+ def _GetInfOptions(self, FfsInfObj):
+ if self._IsKeyword("FILE_GUID"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextGuid():
+ raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+ FfsInfObj.OverrideGuid = self._Token
+
+ if self._IsKeyword("RuleOverride"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("Rule name", self.FileName, self.CurrentLineNumber)
+ FfsInfObj.Rule = self._Token
+
+ if self._IsKeyword("VERSION"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("Version", self.FileName, self.CurrentLineNumber)
+
+ if self._GetStringData():
+ FfsInfObj.Version = self._Token
+
+ if self._IsKeyword(BINARY_FILE_TYPE_UI):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("UI name", self.FileName, self.CurrentLineNumber)
+
+ if self._GetStringData():
+ FfsInfObj.Ui = self._Token
+
+ if self._IsKeyword("USE"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("ARCH name", self.FileName, self.CurrentLineNumber)
+ FfsInfObj.UseArch = self._Token
+
+
+ if self._GetNextToken():
+ p = compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\))')
+ if p.match(self._Token) and p.match(self._Token).span()[1] == len(self._Token):
+ FfsInfObj.KeyStringList.append(self._Token)
+ if not self._IsToken(TAB_COMMA_SPLIT):
+ return
+ else:
+ self._UndoToken()
+ return
+
+ while self._GetNextToken():
+ if not p.match(self._Token):
+ raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
+ FfsInfObj.KeyStringList.append(self._Token)
+
+ if not self._IsToken(TAB_COMMA_SPLIT):
+ break
+
+ ## _GetFileStatement() method
+ #
+ # Get FILE statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom FILE statement is got
+ # @retval True Successfully find FILE statement
+ # @retval False Not able to find FILE statement
+ #
+ def _GetFileStatement(self, Obj, ForCapsule = False):
+ if not self._IsKeyword("FILE"):
+ return False
+
+ if not self._GetNextWord():
+ raise Warning.Expected("FFS type", self.FileName, self.CurrentLineNumber)
+
+ if ForCapsule and self._Token == 'DATA':
+ self._UndoToken()
+ self._UndoToken()
+ return False
+
+ FfsFileObj = FileStatement()
+ FfsFileObj.FvFileType = self._Token
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextGuid():
+ if not self._GetNextWord():
+ raise Warning.Expected("File GUID", self.FileName, self.CurrentLineNumber)
+ if self._Token == 'PCD':
+ if not self._IsToken("("):
+ raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
+ PcdPair = self._GetNextPcdSettings()
+ if not self._IsToken(")"):
+ raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
+ self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
+
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+ FfsFileObj.NameGuid = self._Token
+
+ self._GetFilePart(FfsFileObj)
+
+ if ForCapsule:
+ capsuleFfs = CapsuleFfs()
+ capsuleFfs.Ffs = FfsFileObj
+ Obj.CapsuleDataList.append(capsuleFfs)
+ else:
+ Obj.FfsList.append(FfsFileObj)
+
+ return True
+
+ ## _FileCouldHaveRelocFlag() method
+ #
+ # Check whether reloc strip flag can be set for a file type.
+ #
+ # @param FileType The file type to check with
+ # @retval True This type could have relocation strip flag
+ # @retval False No way to have it
+ #
+ @staticmethod
+ def _FileCouldHaveRelocFlag (FileType):
+ if FileType in {SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE, 'PEI_DXE_COMBO'}:
+ return True
+ else:
+ return False
+
+ ## _SectionCouldHaveRelocFlag() method
+ #
+ # Check whether reloc strip flag can be set for a section type.
+ #
+ # @param SectionType The section type to check with
+ # @retval True This type could have relocation strip flag
+ # @retval False No way to have it
+ #
+ @staticmethod
+ def _SectionCouldHaveRelocFlag (SectionType):
+ if SectionType in {BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32}:
+ return True
+ else:
+ return False
+
+ ## _GetFilePart() method
+ #
+ # Get components for FILE statement
+ #
+ # @param self The object pointer
+ # @param FfsFileObj for whom component is got
+ #
+ def _GetFilePart(self, FfsFileObj):
+ self._GetFileOpts(FfsFileObj)
+
+ if not self._IsToken("{"):
+ if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
+ if self._FileCouldHaveRelocFlag(FfsFileObj.FvFileType):
+ if self._Token == 'RELOCS_STRIPPED':
+ FfsFileObj.KeepReloc = False
+ else:
+ FfsFileObj.KeepReloc = True
+ else:
+ raise Warning("File type %s could not have reloc strip flag%d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("File name or section data", self.FileName, self.CurrentLineNumber)
+
+ if self._Token == BINARY_FILE_TYPE_FV:
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.FvName = self._Token
+
+ elif self._Token == "FD":
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("FD name", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.FdName = self._Token
+
+ elif self._Token in {TAB_DEFINE, "APRIORI", "SECTION"}:
+ self._UndoToken()
+ self._GetSectionData(FfsFileObj)
+
+ elif hasattr(FfsFileObj, 'FvFileType') and FfsFileObj.FvFileType == 'RAW':
+ self._UndoToken()
+ self._GetRAWData(FfsFileObj)
+
+ else:
+ FfsFileObj.CurrentLineNum = self.CurrentLineNumber
+ FfsFileObj.CurrentLineContent = self._CurrentLine()
+ FfsFileObj.FileName = self._Token.replace('$(SPACE)', ' ')
+ self._VerifyFile(FfsFileObj.FileName)
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ ## _GetRAWData() method
+ #
+ # Get RAW data for FILE statement
+ #
+ # @param self The object pointer
+ # @param FfsFileObj for whom section is got
+ #
+ def _GetRAWData(self, FfsFileObj):
+ FfsFileObj.FileName = []
+ FfsFileObj.SubAlignment = []
+ while True:
+ AlignValue = None
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ #For FFS, Auto is default option same to ""
+ if not self._Token == "Auto":
+ AlignValue = self._Token
+ if not self._GetNextToken():
+ raise Warning.Expected("Filename value", self.FileName, self.CurrentLineNumber)
+
+ FileName = self._Token.replace('$(SPACE)', ' ')
+ if FileName == T_CHAR_BRACE_R:
+ self._UndoToken()
+ raise Warning.Expected("Filename value", self.FileName, self.CurrentLineNumber)
+
+ self._VerifyFile(FileName)
+ File = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir)
+ FfsFileObj.FileName.append(File.Path)
+ FfsFileObj.SubAlignment.append(AlignValue)
+
+ if self._IsToken(T_CHAR_BRACE_R):
+ self._UndoToken()
+ break
+
+ if len(FfsFileObj.SubAlignment) == 1:
+ FfsFileObj.SubAlignment = FfsFileObj.SubAlignment[0]
+ if len(FfsFileObj.FileName) == 1:
+ FfsFileObj.FileName = FfsFileObj.FileName[0]
+
+ ## _GetFileOpts() method
+ #
+ # Get options for FILE statement
+ #
+ # @param self The object pointer
+ # @param FfsFileObj for whom options is got
+ #
+ def _GetFileOpts(self, FfsFileObj):
+ if self._GetNextToken():
+ if TokenFindPattern.match(self._Token):
+ FfsFileObj.KeyStringList.append(self._Token)
+ if self._IsToken(TAB_COMMA_SPLIT):
+ while self._GetNextToken():
+ if not TokenFindPattern.match(self._Token):
+ raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.KeyStringList.append(self._Token)
+
+ if not self._IsToken(TAB_COMMA_SPLIT):
+ break
+
+ else:
+ self._UndoToken()
+
+ if self._IsKeyword("FIXED", True):
+ FfsFileObj.Fixed = True
+
+ if self._IsKeyword("CHECKSUM", True):
+ FfsFileObj.CheckSum = True
+
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ #For FFS, Auto is default option same to ""
+ if not self._Token == "Auto":
+ FfsFileObj.Alignment = self._Token
+
+ ## _GetAlignment() method
+ #
+ # Return the alignment value
+ #
+ # @param self The object pointer
+ # @retval True Successfully find alignment
+ # @retval False Not able to find alignment
+ #
+ def _GetAlignment(self):
+ if self._IsKeyword("Align", True):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("alignment value", self.FileName, self.CurrentLineNumber)
+ return True
+
+ return False
+
+ ## _GetSectionData() method
+ #
+ # Get section data for FILE statement
+ #
+ # @param self The object pointer
+ # @param FfsFileObj for whom section is got
+ #
+ def _GetSectionData(self, FfsFileObj):
+ self._GetDefineStatements(FfsFileObj)
+
+ while True:
+ IsLeafSection = self._GetLeafSection(FfsFileObj)
+ IsEncapSection = self._GetEncapsulationSec(FfsFileObj)
+ if not IsLeafSection and not IsEncapSection:
+ break
+
+ ## _GetLeafSection() method
+ #
+ # Get leaf section for Obj
+ #
+ # @param self The object pointer
+ # @param Obj for whom leaf section is got
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetLeafSection(self, Obj):
+ OldPos = self.GetFileBufferPos()
+
+ if not self._IsKeyword("SECTION"):
+ if len(Obj.SectionList) == 0:
+ raise Warning.Expected("SECTION", self.FileName, self.CurrentLineNumber)
+ else:
+ return False
+
+ AlignValue = None
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ AlignValue = self._Token
+
+ BuildNum = None
+ if self._IsKeyword("BUILD_NUM"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("Build number value", self.FileName, self.CurrentLineNumber)
+
+ BuildNum = self._Token
+
+ if self._IsKeyword("VERSION"):
+ if AlignValue == 'Auto':
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("version", self.FileName, self.CurrentLineNumber)
+ VerSectionObj = VerSection()
+ VerSectionObj.Alignment = AlignValue
+ VerSectionObj.BuildNum = BuildNum
+ if self._GetStringData():
+ VerSectionObj.StringData = self._Token
+ else:
+ VerSectionObj.FileName = self._Token
+ Obj.SectionList.append(VerSectionObj)
+
+ elif self._IsKeyword(BINARY_FILE_TYPE_UI):
+ if AlignValue == 'Auto':
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("UI", self.FileName, self.CurrentLineNumber)
+ UiSectionObj = UiSection()
+ UiSectionObj.Alignment = AlignValue
+ if self._GetStringData():
+ UiSectionObj.StringData = self._Token
+ else:
+ UiSectionObj.FileName = self._Token
+ Obj.SectionList.append(UiSectionObj)
+
+ elif self._IsKeyword("FV_IMAGE"):
+ if AlignValue == 'Auto':
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name or FV file path", self.FileName, self.CurrentLineNumber)
+
+ FvName = self._Token
+ FvObj = None
+
+ if self._IsToken("{"):
+ FvObj = FV()
+ FvObj.UiFvName = FvName.upper()
+ self._GetDefineStatements(FvObj)
+
+ self._GetBlockStatement(FvObj)
+ self._GetSetStatements(FvObj)
+ self._GetFvAlignment(FvObj)
+ self._GetFvAttributes(FvObj)
+
+ while True:
+ IsInf = self._GetInfStatement(FvObj)
+ IsFile = self._GetFileStatement(FvObj)
+ if not IsInf and not IsFile:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ FvImageSectionObj = FvImageSection()
+ FvImageSectionObj.Alignment = AlignValue
+ if FvObj is not None:
+ FvImageSectionObj.Fv = FvObj
+ FvImageSectionObj.FvName = None
+ else:
+ FvImageSectionObj.FvName = FvName.upper()
+ FvImageSectionObj.FvFileName = FvName
+
+ Obj.SectionList.append(FvImageSectionObj)
+
+ elif self._IsKeyword("PEI_DEPEX_EXP") or self._IsKeyword("DXE_DEPEX_EXP") or self._IsKeyword("SMM_DEPEX_EXP"):
+ if AlignValue == 'Auto':
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ DepexSectionObj = DepexSection()
+ DepexSectionObj.Alignment = AlignValue
+ DepexSectionObj.DepexType = self._Token
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+ if not self._SkipToToken(T_CHAR_BRACE_R):
+ raise Warning.Expected("Depex expression ending '}'", self.FileName, self.CurrentLineNumber)
+
+ DepexSectionObj.Expression = self._SkippedChars.rstrip(T_CHAR_BRACE_R)
+ Obj.SectionList.append(DepexSectionObj)
+
+ else:
+ if not self._GetNextWord():
+ raise Warning.Expected("section type", self.FileName, self.CurrentLineNumber)
+
+ # Encapsulation section appear, UndoToken and return
+ if self._Token == "COMPRESS" or self._Token == "GUIDED":
+ self.SetFileBufferPos(OldPos)
+ return False
+
+ if self._Token not in {"COMPAT16", BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,\
+ BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "SUBTYPE_GUID", BINARY_FILE_TYPE_SMM_DEPEX}:
+ raise Warning("Unknown section type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ if AlignValue == 'Auto'and (not self._Token == BINARY_FILE_TYPE_PE32) and (not self._Token == BINARY_FILE_TYPE_TE):
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+
+ # DataSection
+ DataSectionObj = DataSection()
+ DataSectionObj.Alignment = AlignValue
+ DataSectionObj.SecType = self._Token
+
+ if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
+ if self._FileCouldHaveRelocFlag(Obj.FvFileType) and self._SectionCouldHaveRelocFlag(DataSectionObj.SecType):
+ if self._Token == 'RELOCS_STRIPPED':
+ DataSectionObj.KeepReloc = False
+ else:
+ DataSectionObj.KeepReloc = True
+ else:
+ raise Warning("File type %s, section type %s, could not have reloc strip flag%d" % (Obj.FvFileType, DataSectionObj.SecType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if self._IsToken(TAB_EQUAL_SPLIT):
+ if not self._GetNextToken():
+ raise Warning.Expected("section file path", self.FileName, self.CurrentLineNumber)
+ DataSectionObj.SectFileName = self._Token
+ self._VerifyFile(DataSectionObj.SectFileName)
+ else:
+ if not self._GetCglSection(DataSectionObj):
+ return False
+
+ Obj.SectionList.append(DataSectionObj)
+
+ return True
+
+ ## _VerifyFile
+ #
+ # Check if file exists or not:
+ # If current phase if GenFds, the file must exist;
+ # If current phase is AutoGen and the file is not in $(OUTPUT_DIRECTORY), the file must exist
+ # @param FileName: File path to be verified.
+ #
+ def _VerifyFile(self, FileName):
+ if FileName.replace(TAB_WORKSPACE, '').find('$') != -1:
+ return
+ if not GlobalData.gAutoGenPhase or not self._GetMacroValue(TAB_DSC_DEFINES_OUTPUT_DIRECTORY) in FileName:
+ ErrorCode, ErrorInfo = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ ## _GetCglSection() method
+ #
+ # Get compressed or GUIDed section for Obj
+ #
+ # @param self The object pointer
+ # @param Obj for whom leaf section is got
+ # @param AlignValue alignment value for complex section
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetCglSection(self, Obj, AlignValue = None):
+
+ if self._IsKeyword("COMPRESS"):
+ type = "PI_STD"
+ if self._IsKeyword("PI_STD") or self._IsKeyword("PI_NONE"):
+ type = self._Token
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ CompressSectionObj = CompressSection()
+ CompressSectionObj.Alignment = AlignValue
+ CompressSectionObj.CompType = type
+ # Recursive sections...
+ while True:
+ IsLeafSection = self._GetLeafSection(CompressSectionObj)
+ IsEncapSection = self._GetEncapsulationSec(CompressSectionObj)
+ if not IsLeafSection and not IsEncapSection:
+ break
+
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ Obj.SectionList.append(CompressSectionObj)
+ return True
+
+ elif self._IsKeyword("GUIDED"):
+ GuidValue = None
+ if self._GetNextGuid():
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+ GuidValue = self._Token
+
+ AttribDict = self._GetGuidAttrib()
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+ GuidSectionObj = GuidSection()
+ GuidSectionObj.Alignment = AlignValue
+ GuidSectionObj.NameGuid = GuidValue
+ GuidSectionObj.SectionType = "GUIDED"
+ GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
+ GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
+ GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
+ # Recursive sections...
+ while True:
+ IsLeafSection = self._GetLeafSection(GuidSectionObj)
+ IsEncapSection = self._GetEncapsulationSec(GuidSectionObj)
+ if not IsLeafSection and not IsEncapSection:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ Obj.SectionList.append(GuidSectionObj)
+
+ return True
+
+ return False
+
+ ## _GetGuidAttri() method
+ #
+ # Get attributes for GUID section
+ #
+ # @param self The object pointer
+ # @retval AttribDict Dictionary of key-value pair of section attributes
+ #
+ def _GetGuidAttrib(self):
+ AttribDict = {}
+ AttribDict["PROCESSING_REQUIRED"] = "NONE"
+ AttribDict["AUTH_STATUS_VALID"] = "NONE"
+ AttribDict["EXTRA_HEADER_SIZE"] = -1
+ while self._IsKeyword("PROCESSING_REQUIRED") or self._IsKeyword("AUTH_STATUS_VALID") \
+ or self._IsKeyword("EXTRA_HEADER_SIZE"):
+ AttribKey = self._Token
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("TRUE(1)/FALSE(0)/Number", self.FileName, self.CurrentLineNumber)
+ elif AttribKey == "EXTRA_HEADER_SIZE":
+ Base = 10
+ if self._Token[0:2].upper() == "0X":
+ Base = 16
+ try:
+ AttribDict[AttribKey] = int(self._Token, Base)
+ continue
+ except ValueError:
+ raise Warning.Expected("Number", self.FileName, self.CurrentLineNumber)
+ elif self._Token.upper() not in {"TRUE", "FALSE", "1", "0"}:
+ raise Warning.Expected("TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
+ AttribDict[AttribKey] = self._Token
+
+ return AttribDict
+
+ ## _GetEncapsulationSec() method
+ #
+ # Get encapsulation section for FILE
+ #
+ # @param self The object pointer
+ # @param FfsFile for whom section is got
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetEncapsulationSec(self, FfsFileObj):
+ OldPos = self.GetFileBufferPos()
+ if not self._IsKeyword("SECTION"):
+ if len(FfsFileObj.SectionList) == 0:
+ raise Warning.Expected("SECTION", self.FileName, self.CurrentLineNumber)
+ else:
+ return False
+
+ AlignValue = None
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENT_NOAUTO:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ AlignValue = self._Token
+
+ if not self._GetCglSection(FfsFileObj, AlignValue):
+ self.SetFileBufferPos(OldPos)
+ return False
+ else:
+ return True
+
+ def _GetFmp(self):
+ if not self._GetNextToken():
+ return False
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[FMPPAYLOAD."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ self._SkipToToken("[FMPPAYLOAD.", True)
+ FmpUiName = self._GetUiName().upper()
+ if FmpUiName in self.Profile.FmpPayloadDict:
+ raise Warning("Duplicated FMP UI name found: %s" % FmpUiName, self.FileName, self.CurrentLineNumber)
+
+ FmpData = CapsulePayload()
+ FmpData.UiName = FmpUiName
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning("The FMP payload section is empty!", self.FileName, self.CurrentLineNumber)
+ FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE', 'CERTIFICATE_GUID', 'MONOTONIC_COUNT']
+ while self._Token in FmpKeyList:
+ Name = self._Token
+ FmpKeyList.remove(Name)
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if Name == 'IMAGE_TYPE_ID':
+ if not self._GetNextGuid():
+ raise Warning.Expected("GUID value for IMAGE_TYPE_ID.", self.FileName, self.CurrentLineNumber)
+ FmpData.ImageTypeId = self._Token
+ elif Name == 'CERTIFICATE_GUID':
+ if not self._GetNextGuid():
+ raise Warning.Expected("GUID value for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
+ FmpData.Certificate_Guid = self._Token
+ if UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_RSA2048_SHA256_GUID and UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_PKCS7_GUID:
+ raise Warning("Only support EFI_CERT_TYPE_RSA2048_SHA256_GUID or EFI_CERT_TYPE_PKCS7_GUID for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
+ else:
+ if not self._GetNextToken():
+ raise Warning.Expected("value of %s" % Name, self.FileName, self.CurrentLineNumber)
+ Value = self._Token
+ if Name == 'IMAGE_HEADER_INIT_VERSION':
+ if FdfParser._Verify(Name, Value, 'UINT8'):
+ FmpData.Version = Value
+ elif Name == 'IMAGE_INDEX':
+ if FdfParser._Verify(Name, Value, 'UINT8'):
+ FmpData.ImageIndex = Value
+ elif Name == 'HARDWARE_INSTANCE':
+ if FdfParser._Verify(Name, Value, 'UINT8'):
+ FmpData.HardwareInstance = Value
+ elif Name == 'MONOTONIC_COUNT':
+ if FdfParser._Verify(Name, Value, 'UINT64'):
+ FmpData.MonotonicCount = Value
+ if FmpData.MonotonicCount.upper().startswith('0X'):
+ FmpData.MonotonicCount = int(FmpData.MonotonicCount, 16)
+ else:
+ FmpData.MonotonicCount = int(FmpData.MonotonicCount)
+ if not self._GetNextToken():
+ break
+ else:
+ self._UndoToken()
+
+ if (FmpData.MonotonicCount and not FmpData.Certificate_Guid) or (not FmpData.MonotonicCount and FmpData.Certificate_Guid):
+ EdkLogger.error("FdfParser", FORMAT_INVALID, "CERTIFICATE_GUID and MONOTONIC_COUNT must be work as a pair.")
+
+ # Only the IMAGE_TYPE_ID is required item
+ if FmpKeyList and 'IMAGE_TYPE_ID' in FmpKeyList:
+ raise Warning("'IMAGE_TYPE_ID' in FMP payload section.", self.FileName, self.CurrentLineNumber)
+ # get the Image file and Vendor code file
+ self._GetFMPCapsuleData(FmpData)
+ if not FmpData.ImageFile:
+ raise Warning("Missing image file in FMP payload section.", self.FileName, self.CurrentLineNumber)
+ # check whether more than one Vendor code file
+ if len(FmpData.VendorCodeFile) > 1:
+ raise Warning("Vendor code file max of 1 per FMP payload section.", self.FileName, self.CurrentLineNumber)
+ self.Profile.FmpPayloadDict[FmpUiName] = FmpData
+ return True
+
+ ## _GetCapsule() method
+ #
+ # Get capsule section contents and store its data into capsule list of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a capsule
+ # @retval False Not able to find a capsule
+ #
+ def _GetCapsule(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[CAPSULE."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[CAPSULE.", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning.Expected("[Capsule.]", self.FileName, self.CurrentLineNumber)
+
+ CapsuleObj = Capsule()
+
+ CapsuleName = self._GetUiName()
+ if not CapsuleName:
+ raise Warning.Expected("capsule name", self.FileName, self.CurrentLineNumber)
+
+ CapsuleObj.UiCapsuleName = CapsuleName.upper()
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ if self._IsKeyword("CREATE_FILE"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("file name", self.FileName, self.CurrentLineNumber)
+
+ CapsuleObj.CreateFile = self._Token
+
+ self._GetCapsuleStatements(CapsuleObj)
+ self.Profile.CapsuleDict[CapsuleObj.UiCapsuleName] = CapsuleObj
+ return True
+
+ ## _GetCapsuleStatements() method
+ #
+ # Get statements for capsule
+ #
+ # @param self The object pointer
+ # @param Obj for whom statements are got
+ #
+ def _GetCapsuleStatements(self, Obj):
+ self._GetCapsuleTokens(Obj)
+ self._GetDefineStatements(Obj)
+ self._GetSetStatements(Obj)
+ self._GetCapsuleData(Obj)
+
+ ## _GetCapsuleTokens() method
+ #
+ # Get token statements for capsule
+ #
+ # @param self The object pointer
+ # @param Obj for whom token statements are got
+ #
+ def _GetCapsuleTokens(self, Obj):
+ if not self._GetNextToken():
+ return False
+ while self._Token in {"CAPSULE_GUID", "CAPSULE_HEADER_SIZE", "CAPSULE_FLAGS", "OEM_CAPSULE_FLAGS", "CAPSULE_HEADER_INIT_VERSION"}:
+ Name = self._Token.strip()
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
+ if Name == 'CAPSULE_FLAGS':
+ if not self._Token in {"PersistAcrossReset", "PopulateSystemTable", "InitiateReset"}:
+ raise Warning.Expected("PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)
+ Value = self._Token.strip()
+ while self._IsToken(TAB_COMMA_SPLIT):
+ Value += TAB_COMMA_SPLIT
+ if not self._GetNextToken():
+ raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
+ if not self._Token in {"PersistAcrossReset", "PopulateSystemTable", "InitiateReset"}:
+ raise Warning.Expected("PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)
+ Value += self._Token.strip()
+ elif Name == 'OEM_CAPSULE_FLAGS':
+ Value = self._Token.strip()
+ if not Value.upper().startswith('0X'):
+ raise Warning.Expected("hex value starting with 0x", self.FileName, self.CurrentLineNumber)
+ try:
+ Value = int(Value, 0)
+ except ValueError:
+ raise Warning.Expected("hex string failed to convert to value", self.FileName, self.CurrentLineNumber)
+ if not 0x0000 <= Value <= 0xFFFF:
+ raise Warning.Expected("hex value between 0x0000 and 0xFFFF", self.FileName, self.CurrentLineNumber)
+ Value = self._Token.strip()
+ else:
+ Value = self._Token.strip()
+ Obj.TokensDict[Name] = Value
+ if not self._GetNextToken():
+ return False
+ self._UndoToken()
+
+ ## _GetCapsuleData() method
+ #
+ # Get capsule data for capsule
+ #
+ # @param self The object pointer
+ # @param Obj for whom capsule data are got
+ #
+ def _GetCapsuleData(self, Obj):
+ while True:
+ IsInf = self._GetInfStatement(Obj, True)
+ IsFile = self._GetFileStatement(Obj, True)
+ IsFv = self._GetFvStatement(Obj)
+ IsFd = self._GetFdStatement(Obj)
+ IsAnyFile = self._GetAnyFileStatement(Obj)
+ IsAfile = self._GetAfileStatement(Obj)
+ IsFmp = self._GetFmpStatement(Obj)
+ if not (IsInf or IsFile or IsFv or IsFd or IsAnyFile or IsAfile or IsFmp):
+ break
+
+ ## _GetFMPCapsuleData() method
+ #
+ # Get capsule data for FMP capsule
+ #
+ # @param self The object pointer
+ # @param Obj for whom capsule data are got
+ #
+ def _GetFMPCapsuleData(self, Obj):
+ while True:
+ IsFv = self._GetFvStatement(Obj, True)
+ IsFd = self._GetFdStatement(Obj, True)
+ IsAnyFile = self._GetAnyFileStatement(Obj, True)
+ if not (IsFv or IsFd or IsAnyFile):
+ break
+
+ ## _GetFvStatement() method
+ #
+ # Get FV for capsule
+ #
+ # @param self The object pointer
+ # @param CapsuleObj for whom FV is got
+ # @retval True Successfully find a FV statement
+ # @retval False Not able to find a FV statement
+ #
+ def _GetFvStatement(self, CapsuleObj, FMPCapsule = False):
+ if not self._IsKeyword(BINARY_FILE_TYPE_FV):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() not in self.Profile.FvDict:
+ raise Warning("FV name does not exist", self.FileName, self.CurrentLineNumber)
+
+ myCapsuleFv = CapsuleFv()
+ myCapsuleFv.FvName = self._Token
+ if FMPCapsule:
+ if not CapsuleObj.ImageFile:
+ CapsuleObj.ImageFile.append(myCapsuleFv)
+ else:
+ CapsuleObj.VendorCodeFile.append(myCapsuleFv)
+ else:
+ CapsuleObj.CapsuleDataList.append(myCapsuleFv)
+ return True
+
+ ## _GetFdStatement() method
+ #
+ # Get FD for capsule
+ #
+ # @param self The object pointer
+ # @param CapsuleObj for whom FD is got
+ # @retval True Successfully find a FD statement
+ # @retval False Not able to find a FD statement
+ #
+ def _GetFdStatement(self, CapsuleObj, FMPCapsule = False):
+ if not self._IsKeyword("FD"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("FD name", self.FileName, self.CurrentLineNumber)
+
+ if self._Token.upper() not in self.Profile.FdDict:
+ raise Warning("FD name does not exist", self.FileName, self.CurrentLineNumber)
+
+ myCapsuleFd = CapsuleFd()
+ myCapsuleFd.FdName = self._Token
+ if FMPCapsule:
+ if not CapsuleObj.ImageFile:
+ CapsuleObj.ImageFile.append(myCapsuleFd)
+ else:
+ CapsuleObj.VendorCodeFile.append(myCapsuleFd)
+ else:
+ CapsuleObj.CapsuleDataList.append(myCapsuleFd)
+ return True
+
+ def _GetFmpStatement(self, CapsuleObj):
+ if not self._IsKeyword("FMP_PAYLOAD"):
+ if not self._IsKeyword("FMP"):
+ return False
+
+ if not self._IsKeyword("PAYLOAD"):
+ self._UndoToken()
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("payload name after FMP_PAYLOAD =", self.FileName, self.CurrentLineNumber)
+ Payload = self._Token.upper()
+ if Payload not in self.Profile.FmpPayloadDict:
+ raise Warning("This FMP Payload does not exist: %s" % self._Token, self.FileName, self.CurrentLineNumber)
+ CapsuleObj.FmpPayloadList.append(self.Profile.FmpPayloadDict[Payload])
+ return True
+
+ def _ParseRawFileStatement(self):
+ if not self._IsKeyword("FILE"):
+ return None
+
+ if not self._IsKeyword("DATA"):
+ self._UndoToken()
+ return None
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
+
+ AnyFileName = self._Token
+ self._VerifyFile(AnyFileName)
+
+ if not os.path.isabs(AnyFileName):
+ AnyFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, AnyFileName)
+
+ return AnyFileName
+
+ ## _GetAnyFileStatement() method
+ #
+ # Get AnyFile for capsule
+ #
+ # @param self The object pointer
+ # @param CapsuleObj for whom AnyFile is got
+ # @retval True Successfully find a Anyfile statement
+ # @retval False Not able to find a AnyFile statement
+ #
+ def _GetAnyFileStatement(self, CapsuleObj, FMPCapsule = False):
+ AnyFileName = self._ParseRawFileStatement()
+ if not AnyFileName:
+ return False
+
+ myCapsuleAnyFile = CapsuleAnyFile()
+ myCapsuleAnyFile.FileName = AnyFileName
+ if FMPCapsule:
+ if not CapsuleObj.ImageFile:
+ CapsuleObj.ImageFile.append(myCapsuleAnyFile)
+ else:
+ CapsuleObj.VendorCodeFile.append(myCapsuleAnyFile)
+ else:
+ CapsuleObj.CapsuleDataList.append(myCapsuleAnyFile)
+ return True
+
+ ## _GetAfileStatement() method
+ #
+ # Get Afile for capsule
+ #
+ # @param self The object pointer
+ # @param CapsuleObj for whom Afile is got
+ # @retval True Successfully find a Afile statement
+ # @retval False Not able to find a Afile statement
+ #
+ def _GetAfileStatement(self, CapsuleObj):
+ if not self._IsKeyword("APPEND"):
+ return False
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("Afile name", self.FileName, self.CurrentLineNumber)
+
+ AfileName = self._Token
+ AfileBaseName = os.path.basename(AfileName)
+
+ if os.path.splitext(AfileBaseName)[1] not in {".bin", ".BIN", ".Bin", ".dat", ".DAT", ".Dat", ".data", ".DATA", ".Data"}:
+ raise Warning('invalid binary file type, should be one of "bin",BINARY_FILE_TYPE_BIN,"Bin","dat","DAT","Dat","data","DATA","Data"', \
+ self.FileName, self.CurrentLineNumber)
+
+ if not os.path.isabs(AfileName):
+ AfileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(AfileName)
+ self._VerifyFile(AfileName)
+ else:
+ if not os.path.exists(AfileName):
+ raise Warning('%s does not exist' % AfileName, self.FileName, self.CurrentLineNumber)
+ else:
+ pass
+
+ myCapsuleAfile = CapsuleAfile()
+ myCapsuleAfile.FileName = AfileName
+ CapsuleObj.CapsuleDataList.append(myCapsuleAfile)
+ return True
+
+ ## _GetRule() method
+ #
+ # Get Rule section contents and store its data into rule list of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a Rule
+ # @retval False Not able to find a Rule
+ #
+ def _GetRule(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[RULE."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+ self._UndoToken()
+ if not self._IsToken("[Rule.", True):
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
+ # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
+ raise Warning.Expected("[Rule.]", self.FileName, self.CurrentLineNumber)
+
+ if not self._SkipToToken(TAB_SPLIT):
+ raise Warning.Expected("'.'", self.FileName, self.CurrentLineNumber)
+
+ Arch = self._SkippedChars.rstrip(TAB_SPLIT)
+
+ ModuleType = self._GetModuleType()
+
+ TemplateName = ""
+ if self._IsToken(TAB_SPLIT):
+ if not self._GetNextWord():
+ raise Warning.Expected("template name", self.FileName, self.CurrentLineNumber)
+ TemplateName = self._Token
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ RuleObj = self._GetRuleFileStatements()
+ RuleObj.Arch = Arch.upper()
+ RuleObj.ModuleType = ModuleType
+ RuleObj.TemplateName = TemplateName
+ if TemplateName == '':
+ self.Profile.RuleDict['RULE' + \
+ TAB_SPLIT + \
+ Arch.upper() + \
+ TAB_SPLIT + \
+ ModuleType.upper() ] = RuleObj
+ else:
+ self.Profile.RuleDict['RULE' + \
+ TAB_SPLIT + \
+ Arch.upper() + \
+ TAB_SPLIT + \
+ ModuleType.upper() + \
+ TAB_SPLIT + \
+ TemplateName.upper() ] = RuleObj
+ return True
+
+ ## _GetModuleType() method
+ #
+ # Return the module type
+ #
+ # @param self The object pointer
+ # @retval string module type
+ #
+ def _GetModuleType(self):
+ if not self._GetNextWord():
+ raise Warning.Expected("Module type", self.FileName, self.CurrentLineNumber)
+ if self._Token.upper() not in {
+ SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM,
+ SUP_MODULE_DXE_CORE, SUP_MODULE_DXE_DRIVER,
+ SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_DXE_SMM_DRIVER,
+ SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_UEFI_DRIVER,
+ SUP_MODULE_UEFI_APPLICATION, SUP_MODULE_USER_DEFINED, SUP_MODULE_HOST_APPLICATION,
+ TAB_DEFAULT, SUP_MODULE_BASE,
+ EDK_COMPONENT_TYPE_SECURITY_CORE,
+ EDK_COMPONENT_TYPE_COMBINED_PEIM_DRIVER,
+ EDK_COMPONENT_TYPE_PIC_PEIM,
+ EDK_COMPONENT_TYPE_RELOCATABLE_PEIM, "PE32_PEIM",
+ EDK_COMPONENT_TYPE_BS_DRIVER, EDK_COMPONENT_TYPE_RT_DRIVER,
+ EDK_COMPONENT_TYPE_SAL_RT_DRIVER,
+ EDK_COMPONENT_TYPE_APPLICATION, "ACPITABLE",
+ SUP_MODULE_SMM_CORE, SUP_MODULE_MM_STANDALONE,
+ SUP_MODULE_MM_CORE_STANDALONE}:
+ raise Warning("Unknown Module type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ return self._Token
+
+ ## _GetFileExtension() method
+ #
+ # Return the file extension
+ #
+ # @param self The object pointer
+ # @retval string file name extension
+ #
+ def _GetFileExtension(self):
+ if not self._IsToken(TAB_SPLIT):
+ raise Warning.Expected("'.'", self.FileName, self.CurrentLineNumber)
+
+ Ext = ""
+ if self._GetNextToken():
+ if FileExtensionPattern.match(self._Token):
+ Ext = self._Token
+ return TAB_SPLIT + Ext
+ else:
+ raise Warning("Unknown file extension '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ else:
+ raise Warning.Expected("file extension", self.FileName, self.CurrentLineNumber)
+
+ ## _GetRuleFileStatement() method
+ #
+ # Get rule contents
+ #
+ # @param self The object pointer
+ # @retval Rule Rule object
+ #
+ def _GetRuleFileStatements(self):
+ if not self._IsKeyword("FILE"):
+ raise Warning.Expected("FILE", self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextWord():
+ raise Warning.Expected("FFS type", self.FileName, self.CurrentLineNumber)
+
+ Type = self._Token.strip().upper()
+ if Type not in {"RAW", "FREEFORM", SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM,
+ "PEI_DXE_COMBO", "DRIVER", SUP_MODULE_DXE_CORE, EDK_COMPONENT_TYPE_APPLICATION,
+ "FV_IMAGE", "SMM", SUP_MODULE_SMM_CORE, SUP_MODULE_MM_STANDALONE,
+ SUP_MODULE_MM_CORE_STANDALONE}:
+ raise Warning("Unknown FV type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._IsKeyword("$(NAMED_GUID)"):
+ if not self._GetNextWord():
+ NamedGuid = self._CurrentLine()[self.CurrentOffsetWithinLine:].split()[0].strip()
+ if GlobalData.gGuidPatternEnd.match(NamedGuid):
+ self.CurrentOffsetWithinLine += len(NamedGuid)
+ self._Token = NamedGuid
+ else:
+ raise Warning.Expected("$(NAMED_GUID)", self.FileName, self.CurrentLineNumber)
+ if self._Token == 'PCD':
+ if not self._IsToken("("):
+ raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
+ PcdPair = self._GetNextPcdSettings()
+ if not self._IsToken(")"):
+ raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
+ self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
+
+ NameGuid = self._Token
+
+ KeepReloc = None
+ if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
+ if self._FileCouldHaveRelocFlag(Type):
+ if self._Token == 'RELOCS_STRIPPED':
+ KeepReloc = False
+ else:
+ KeepReloc = True
+ else:
+ raise Warning("File type %s could not have reloc strip flag%d" % (Type, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ KeyStringList = []
+ if self._GetNextToken():
+ if TokenFindPattern.match(self._Token):
+ KeyStringList.append(self._Token)
+ if self._IsToken(TAB_COMMA_SPLIT):
+ while self._GetNextToken():
+ if not TokenFindPattern.match(self._Token):
+ raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
+ KeyStringList.append(self._Token)
+
+ if not self._IsToken(TAB_COMMA_SPLIT):
+ break
+
+ else:
+ self._UndoToken()
+
+
+ Fixed = False
+ if self._IsKeyword("Fixed", True):
+ Fixed = True
+
+ CheckSum = False
+ if self._IsKeyword("CheckSum", True):
+ CheckSum = True
+
+ AlignValue = ""
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ #For FFS, Auto is default option same to ""
+ if not self._Token == "Auto":
+ AlignValue = self._Token
+
+ if self._IsToken("{"):
+ # Complex file rule expected
+ NewRule = RuleComplexFile()
+ NewRule.FvFileType = Type
+ NewRule.NameGuid = NameGuid
+ NewRule.Alignment = AlignValue
+ NewRule.CheckSum = CheckSum
+ NewRule.Fixed = Fixed
+ NewRule.KeyStringList = KeyStringList
+ if KeepReloc is not None:
+ NewRule.KeepReloc = KeepReloc
+
+ while True:
+ IsEncapsulate = self._GetRuleEncapsulationSection(NewRule)
+ IsLeaf = self._GetEfiSection(NewRule)
+ if not IsEncapsulate and not IsLeaf:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+
+ return NewRule
+
+ else:
+ # Simple file rule expected
+ if not self._GetNextWord():
+ raise Warning.Expected("leaf section type", self.FileName, self.CurrentLineNumber)
+
+ SectionName = self._Token
+
+ if SectionName not in {
+ "COMPAT16", BINARY_FILE_TYPE_PE32,
+ BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE",
+ "RAW",BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI,
+ BINARY_FILE_TYPE_PEI_DEPEX, "VERSION", "SUBTYPE_GUID",
+ BINARY_FILE_TYPE_SMM_DEPEX}:
+ raise Warning("Unknown leaf section name '%s'" % SectionName, self.FileName, self.CurrentLineNumber)
+
+
+ if self._IsKeyword("Fixed", True):
+ Fixed = True
+
+ if self._IsKeyword("CheckSum", True):
+ CheckSum = True
+
+ SectAlignment = ""
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32) and (not SectionName == BINARY_FILE_TYPE_TE):
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ SectAlignment = self._Token
+
+ Ext = None
+ if self._IsToken(TAB_VALUE_SPLIT):
+ Ext = self._GetFileExtension()
+ elif not self._GetNextToken():
+ raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
+
+ NewRule = RuleSimpleFile()
+ NewRule.SectionType = SectionName
+ NewRule.FvFileType = Type
+ NewRule.NameGuid = NameGuid
+ NewRule.Alignment = AlignValue
+ NewRule.SectAlignment = SectAlignment
+ NewRule.CheckSum = CheckSum
+ NewRule.Fixed = Fixed
+ NewRule.KeyStringList = KeyStringList
+ if KeepReloc is not None:
+ NewRule.KeepReloc = KeepReloc
+ NewRule.FileExtension = Ext
+ NewRule.FileName = self._Token
+ return NewRule
+
+ ## _GetEfiSection() method
+ #
+ # Get section list for Rule
+ #
+ # @param self The object pointer
+ # @param Obj for whom section is got
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetEfiSection(self, Obj):
+ OldPos = self.GetFileBufferPos()
+ EfiSectionObj = EfiSection()
+ if not self._GetNextWord():
+ CurrentLine = self._CurrentLine()[self.CurrentOffsetWithinLine:].split()[0].strip()
+ if self._Token == '{' and Obj.FvFileType == "RAW" and TAB_SPLIT in CurrentLine:
+ if self._IsToken(TAB_VALUE_SPLIT):
+ EfiSectionObj.FileExtension = self._GetFileExtension()
+ elif self._GetNextToken():
+ EfiSectionObj.FileName = self._Token
+ EfiSectionObj.SectionType = BINARY_FILE_TYPE_RAW
+ Obj.SectionList.append(EfiSectionObj)
+ return True
+ else:
+ return False
+ SectionName = self._Token
+
+ if SectionName not in {
+ "COMPAT16", BINARY_FILE_TYPE_PE32,
+ BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE",
+ "RAW",BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI,
+ BINARY_FILE_TYPE_PEI_DEPEX, "VERSION", "SUBTYPE_GUID",
+ BINARY_FILE_TYPE_SMM_DEPEX, BINARY_FILE_TYPE_GUID}:
+ self._UndoToken()
+ return False
+
+ if SectionName == "FV_IMAGE":
+ FvImageSectionObj = FvImageSection()
+ if self._IsKeyword("FV_IMAGE"):
+ pass
+ if self._IsToken("{"):
+ FvObj = FV()
+ self._GetDefineStatements(FvObj)
+ self._GetBlockStatement(FvObj)
+ self._GetSetStatements(FvObj)
+ self._GetFvAlignment(FvObj)
+ self._GetFvAttributes(FvObj)
+ self._GetAprioriSection(FvObj)
+ self._GetAprioriSection(FvObj)
+
+ while True:
+ IsInf = self._GetInfStatement(FvObj)
+ IsFile = self._GetFileStatement(FvObj)
+ if not IsInf and not IsFile:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ FvImageSectionObj.Fv = FvObj
+ FvImageSectionObj.FvName = None
+
+ else:
+ if not self._IsKeyword(BINARY_FILE_TYPE_FV):
+ raise Warning.Expected("'FV'", self.FileName, self.CurrentLineNumber)
+ FvImageSectionObj.FvFileType = self._Token
+
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENT_NOAUTO:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ FvImageSectionObj.Alignment = self._Token
+
+ if self._IsToken(TAB_VALUE_SPLIT):
+ FvImageSectionObj.FvFileExtension = self._GetFileExtension()
+ elif self._GetNextToken():
+ if self._Token not in {
+ T_CHAR_BRACE_R, "COMPAT16", BINARY_FILE_TYPE_PE32,
+ BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE,
+ "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,
+ BINARY_FILE_TYPE_UI, "VERSION",
+ BINARY_FILE_TYPE_PEI_DEPEX, BINARY_FILE_TYPE_GUID,
+ BINARY_FILE_TYPE_SMM_DEPEX}:
+ FvImageSectionObj.FvFileName = self._Token
+ else:
+ self._UndoToken()
+ else:
+ raise Warning.Expected("FV file name", self.FileName, self.CurrentLineNumber)
+
+ Obj.SectionList.append(FvImageSectionObj)
+ return True
+
+ EfiSectionObj.SectionType = SectionName
+
+ if not self._GetNextToken():
+ raise Warning.Expected("file type", self.FileName, self.CurrentLineNumber)
+
+ if self._Token == "STRING":
+ if not self._RuleSectionCouldHaveString(EfiSectionObj.SectionType):
+ raise Warning("%s section could NOT have string data%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("Quoted String", self.FileName, self.CurrentLineNumber)
+
+ if self._GetStringData():
+ EfiSectionObj.StringData = self._Token
+
+ if self._IsKeyword("BUILD_NUM"):
+ if not self._RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
+ raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("Build number", self.FileName, self.CurrentLineNumber)
+ EfiSectionObj.BuildNum = self._Token
+
+ else:
+ EfiSectionObj.FileType = self._Token
+ self._CheckRuleSectionFileType(EfiSectionObj.SectionType, EfiSectionObj.FileType)
+
+ if self._IsKeyword("Optional"):
+ if not self._RuleSectionCouldBeOptional(EfiSectionObj.SectionType):
+ raise Warning("%s section could NOT be optional%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+ EfiSectionObj.Optional = True
+
+ if self._IsKeyword("BUILD_NUM"):
+ if not self._RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
+ raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
+
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("Build number", self.FileName, self.CurrentLineNumber)
+ EfiSectionObj.BuildNum = self._Token
+
+ if self._GetAlignment():
+ if self._Token not in ALIGNMENTS:
+ raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+ if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32) and (not SectionName == BINARY_FILE_TYPE_TE):
+ raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
+ EfiSectionObj.Alignment = self._Token
+
+ if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
+ if self._SectionCouldHaveRelocFlag(EfiSectionObj.SectionType):
+ if self._Token == 'RELOCS_STRIPPED':
+ EfiSectionObj.KeepReloc = False
+ else:
+ EfiSectionObj.KeepReloc = True
+ if Obj.KeepReloc is not None and Obj.KeepReloc != EfiSectionObj.KeepReloc:
+ raise Warning("Section type %s has reloc strip flag conflict with Rule" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber)
+ else:
+ raise Warning("Section type %s could not have reloc strip flag" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber)
+
+
+ if self._IsToken(TAB_VALUE_SPLIT):
+ EfiSectionObj.FileExtension = self._GetFileExtension()
+ elif self._GetNextToken():
+ if self._Token not in {
+ T_CHAR_BRACE_R, "COMPAT16", BINARY_FILE_TYPE_PE32,
+ BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE,
+ "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,
+ BINARY_FILE_TYPE_UI, "VERSION",
+ BINARY_FILE_TYPE_PEI_DEPEX, BINARY_FILE_TYPE_GUID,
+ BINARY_FILE_TYPE_SMM_DEPEX}:
+
+ if self._Token.startswith('PCD'):
+ self._UndoToken()
+ self._GetNextWord()
+
+ if self._Token == 'PCD':
+ if not self._IsToken("("):
+ raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
+ PcdPair = self._GetNextPcdSettings()
+ if not self._IsToken(")"):
+ raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
+ self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
+
+ EfiSectionObj.FileName = self._Token
+
+ else:
+ self._UndoToken()
+ else:
+ raise Warning.Expected("section file name", self.FileName, self.CurrentLineNumber)
+
+ Obj.SectionList.append(EfiSectionObj)
+ return True
+
+ ## _RuleSectionCouldBeOptional() method
+ #
+ # Get whether a section could be optional
+ #
+ # @param SectionType The section type to check
+ # @retval True section could be optional
+ # @retval False section never optional
+ #
+ @staticmethod
+ def _RuleSectionCouldBeOptional(SectionType):
+ if SectionType in {BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "RAW", BINARY_FILE_TYPE_SMM_DEPEX}:
+ return True
+ else:
+ return False
+
+ ## _RuleSectionCouldHaveBuildNum() method
+ #
+ # Get whether a section could have build number information
+ #
+ # @param SectionType The section type to check
+ # @retval True section could have build number information
+ # @retval False section never have build number information
+ #
+ @staticmethod
+ def _RuleSectionCouldHaveBuildNum(SectionType):
+ if SectionType == "VERSION":
+ return True
+ else:
+ return False
+
+ ## _RuleSectionCouldHaveString() method
+ #
+ # Get whether a section could have string
+ #
+ # @param SectionType The section type to check
+ # @retval True section could have string
+ # @retval False section never have string
+ #
+ @staticmethod
+ def _RuleSectionCouldHaveString(SectionType):
+ if SectionType in {BINARY_FILE_TYPE_UI, "VERSION"}:
+ return True
+ else:
+ return False
+
+ ## _CheckRuleSectionFileType() method
+ #
+ # Get whether a section matches a file type
+ #
+ # @param self The object pointer
+ # @param SectionType The section type to check
+ # @param FileType The file type to check
+ #
+ def _CheckRuleSectionFileType(self, SectionType, FileType):
+ WarningString = "Incorrect section file type '%s'"
+ if SectionType == "COMPAT16":
+ if FileType not in {"COMPAT16", "SEC_COMPAT16"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_PE32:
+ if FileType not in {BINARY_FILE_TYPE_PE32, "SEC_PE32"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_PIC:
+ if FileType not in {BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_PIC}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_TE:
+ if FileType not in {BINARY_FILE_TYPE_TE, "SEC_TE"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == "RAW":
+ if FileType not in {BINARY_FILE_TYPE_BIN, "SEC_BIN", "RAW", "ASL", "ACPI"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_DXE_DEPEX or SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
+ if FileType not in {BINARY_FILE_TYPE_DXE_DEPEX, "SEC_DXE_DEPEX", BINARY_FILE_TYPE_SMM_DEPEX}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_UI:
+ if FileType not in {BINARY_FILE_TYPE_UI, "SEC_UI"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == "VERSION":
+ if FileType not in {"VERSION", "SEC_VERSION"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_PEI_DEPEX:
+ if FileType not in {BINARY_FILE_TYPE_PEI_DEPEX, "SEC_PEI_DEPEX"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+ elif SectionType == BINARY_FILE_TYPE_GUID:
+ if FileType not in {BINARY_FILE_TYPE_PE32, "SEC_GUID"}:
+ raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
+
+ ## _GetRuleEncapsulationSection() method
+ #
+ # Get encapsulation section for Rule
+ #
+ # @param self The object pointer
+ # @param theRule for whom section is got
+ # @retval True Successfully find section statement
+ # @retval False Not able to find section statement
+ #
+ def _GetRuleEncapsulationSection(self, theRule):
+ if self._IsKeyword("COMPRESS"):
+ Type = "PI_STD"
+ if self._IsKeyword("PI_STD") or self._IsKeyword("PI_NONE"):
+ Type = self._Token
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+
+ CompressSectionObj = CompressSection()
+
+ CompressSectionObj.CompType = Type
+ # Recursive sections...
+ while True:
+ IsEncapsulate = self._GetRuleEncapsulationSection(CompressSectionObj)
+ IsLeaf = self._GetEfiSection(CompressSectionObj)
+ if not IsEncapsulate and not IsLeaf:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ theRule.SectionList.append(CompressSectionObj)
+
+ return True
+
+ elif self._IsKeyword("GUIDED"):
+ GuidValue = None
+ if self._GetNextGuid():
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
+ GuidValue = self._Token
+
+ if self._IsKeyword("$(NAMED_GUID)"):
+ GuidValue = self._Token
+
+ AttribDict = self._GetGuidAttrib()
+
+ if not self._IsToken("{"):
+ raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
+ GuidSectionObj = GuidSection()
+ GuidSectionObj.NameGuid = GuidValue
+ GuidSectionObj.SectionType = "GUIDED"
+ GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
+ GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
+ GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
+
+ # Efi sections...
+ while True:
+ IsEncapsulate = self._GetRuleEncapsulationSection(GuidSectionObj)
+ IsLeaf = self._GetEfiSection(GuidSectionObj)
+ if not IsEncapsulate and not IsLeaf:
+ break
+
+ if not self._IsToken(T_CHAR_BRACE_R):
+ raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
+ theRule.SectionList.append(GuidSectionObj)
+
+ return True
+
+ return False
+
+ ## _GetOptionRom() method
+ #
+ # Get OptionROM section contents and store its data into OptionROM list of self.Profile
+ #
+ # @param self The object pointer
+ # @retval True Successfully find a OptionROM
+ # @retval False Not able to find a OptionROM
+ #
+ def _GetOptionRom(self):
+ if not self._GetNextToken():
+ return False
+
+ S = self._Token.upper()
+ if S.startswith(TAB_SECTION_START) and not S.startswith("[OPTIONROM."):
+ self.SectionParser(S)
+ self._UndoToken()
+ return False
+
+ self._UndoToken()
+ if not self._IsToken("[OptionRom.", True):
+ raise Warning("Unknown Keyword '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
+
+ OptRomName = self._GetUiName()
+
+ if not self._IsToken(TAB_SECTION_END):
+ raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
+
+ OptRomObj = OPTIONROM(OptRomName)
+ self.Profile.OptRomDict[OptRomName] = OptRomObj
+
+ while True:
+ isInf = self._GetOptRomInfStatement(OptRomObj)
+ isFile = self._GetOptRomFileStatement(OptRomObj)
+ if not isInf and not isFile:
+ break
+
+ return True
+
+ ## _GetOptRomInfStatement() method
+ #
+ # Get INF statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom inf statement is got
+ # @retval True Successfully find inf statement
+ # @retval False Not able to find inf statement
+ #
+ def _GetOptRomInfStatement(self, Obj):
+ if not self._IsKeyword("INF"):
+ return False
+
+ ffsInf = OptRomInfStatement()
+ self._GetInfOptions(ffsInf)
+
+ if not self._GetNextToken():
+ raise Warning.Expected("INF file path", self.FileName, self.CurrentLineNumber)
+ ffsInf.InfFileName = self._Token
+ if ffsInf.InfFileName.replace(TAB_WORKSPACE, '').find('$') == -1:
+ #check for file path
+ ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ NewFileName = ffsInf.InfFileName
+ if ffsInf.OverrideGuid:
+ NewFileName = ProcessDuplicatedInf(PathClass(ffsInf.InfFileName,GenFdsGlobalVariable.WorkSpaceDir), ffsInf.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir).Path
+
+ if not NewFileName in self.Profile.InfList:
+ self.Profile.InfList.append(NewFileName)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.InfFileLineList.append(FileLineTuple)
+ if ffsInf.UseArch:
+ if ffsInf.UseArch not in self.Profile.InfDict:
+ self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
+ else:
+ self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
+ else:
+ self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
+
+
+ self._GetOptRomOverrides (ffsInf)
+
+ Obj.FfsList.append(ffsInf)
+ return True
+
+ ## _GetOptRomOverrides() method
+ #
+ # Get overrides for OptROM INF & FILE
+ #
+ # @param self The object pointer
+ # @param FfsInfObj for whom overrides is got
+ #
+ def _GetOptRomOverrides(self, Obj):
+ if self._IsToken('{'):
+ Overrides = OverrideAttribs()
+ while True:
+ if self._IsKeyword("PCI_VENDOR_ID"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex vendor id", self.FileName, self.CurrentLineNumber)
+ Overrides.PciVendorId = self._Token
+ continue
+
+ if self._IsKeyword("PCI_CLASS_CODE"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex class code", self.FileName, self.CurrentLineNumber)
+ Overrides.PciClassCode = self._Token
+ continue
+
+ if self._IsKeyword("PCI_DEVICE_ID"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ # Get a list of PCI IDs
+ Overrides.PciDeviceId = ""
+ while (self._GetNextHexNumber()):
+ Overrides.PciDeviceId = "{} {}".format(Overrides.PciDeviceId, self._Token)
+ if not Overrides.PciDeviceId:
+ raise Warning.Expected("one or more Hex device ids", self.FileName, self.CurrentLineNumber)
+ continue
+
+ if self._IsKeyword("PCI_REVISION"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextHexNumber():
+ raise Warning.Expected("Hex revision", self.FileName, self.CurrentLineNumber)
+ Overrides.PciRevision = self._Token
+ continue
+
+ if self._IsKeyword("PCI_COMPRESS"):
+ if not self._IsToken(TAB_EQUAL_SPLIT):
+ raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
+ if not self._GetNextToken():
+ raise Warning.Expected("TRUE/FALSE for compress", self.FileName, self.CurrentLineNumber)
+ Overrides.NeedCompress = self._Token.upper() == 'TRUE'
+ continue
+
+ if self._IsToken(T_CHAR_BRACE_R):
+ break
+ else:
+ EdkLogger.error("FdfParser", FORMAT_INVALID, File=self.FileName, Line=self.CurrentLineNumber)
+
+ Obj.OverrideAttribs = Overrides
+
+ ## _GetOptRomFileStatement() method
+ #
+ # Get FILE statements
+ #
+ # @param self The object pointer
+ # @param Obj for whom FILE statement is got
+ # @retval True Successfully find FILE statement
+ # @retval False Not able to find FILE statement
+ #
+ def _GetOptRomFileStatement(self, Obj):
+ if not self._IsKeyword("FILE"):
+ return False
+
+ FfsFileObj = OptRomFileStatement()
+
+ if not self._IsKeyword("EFI") and not self._IsKeyword(BINARY_FILE_TYPE_BIN):
+ raise Warning.Expected("Binary type (EFI/BIN)", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.FileType = self._Token
+
+ if not self._GetNextToken():
+ raise Warning.Expected("File path", self.FileName, self.CurrentLineNumber)
+ FfsFileObj.FileName = self._Token
+ if FfsFileObj.FileName.replace(TAB_WORKSPACE, '').find('$') == -1:
+ #check for file path
+ ErrorCode, ErrorInfo = PathClass(NormPath(FfsFileObj.FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
+ if ErrorCode != 0:
+ EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
+
+ if FfsFileObj.FileType == 'EFI':
+ self._GetOptRomOverrides(FfsFileObj)
+
+ Obj.FfsList.append(FfsFileObj)
+
+ return True
+
+ ## _GetCapInFd() method
+ #
+ # Get Cap list contained in FD
+ #
+ # @param self The object pointer
+ # @param FdName FD name
+ # @retval CapList List of Capsule in FD
+ #
+ def _GetCapInFd (self, FdName):
+ CapList = []
+ if FdName.upper() in self.Profile.FdDict:
+ FdObj = self.Profile.FdDict[FdName.upper()]
+ for elementRegion in FdObj.RegionList:
+ if elementRegion.RegionType == 'CAPSULE':
+ for elementRegionData in elementRegion.RegionDataList:
+ if elementRegionData.endswith(".cap"):
+ continue
+ if elementRegionData is not None and elementRegionData.upper() not in CapList:
+ CapList.append(elementRegionData.upper())
+ return CapList
+
+ ## _GetReferencedFdCapTuple() method
+ #
+ # Get FV and FD list referenced by a capsule image
+ #
+ # @param self The object pointer
+ # @param CapObj Capsule section to be searched
+ # @param RefFdList referenced FD by section
+ # @param RefFvList referenced FV by section
+ #
+ def _GetReferencedFdCapTuple(self, CapObj, RefFdList = [], RefFvList = []):
+ for CapsuleDataObj in CapObj.CapsuleDataList:
+ if hasattr(CapsuleDataObj, 'FvName') and CapsuleDataObj.FvName is not None and CapsuleDataObj.FvName.upper() not in RefFvList:
+ RefFvList.append (CapsuleDataObj.FvName.upper())
+ elif hasattr(CapsuleDataObj, 'FdName') and CapsuleDataObj.FdName is not None and CapsuleDataObj.FdName.upper() not in RefFdList:
+ RefFdList.append (CapsuleDataObj.FdName.upper())
+ elif CapsuleDataObj.Ffs is not None:
+ if isinstance(CapsuleDataObj.Ffs, FileStatement):
+ if CapsuleDataObj.Ffs.FvName is not None and CapsuleDataObj.Ffs.FvName.upper() not in RefFvList:
+ RefFvList.append(CapsuleDataObj.Ffs.FvName.upper())
+ elif CapsuleDataObj.Ffs.FdName is not None and CapsuleDataObj.Ffs.FdName.upper() not in RefFdList:
+ RefFdList.append(CapsuleDataObj.Ffs.FdName.upper())
+ else:
+ self._GetReferencedFdFvTupleFromSection(CapsuleDataObj.Ffs, RefFdList, RefFvList)
+
+ ## _GetFvInFd() method
+ #
+ # Get FV list contained in FD
+ #
+ # @param self The object pointer
+ # @param FdName FD name
+ # @retval FvList list of FV in FD
+ #
+ def _GetFvInFd (self, FdName):
+ FvList = []
+ if FdName.upper() in self.Profile.FdDict:
+ FdObj = self.Profile.FdDict[FdName.upper()]
+ for elementRegion in FdObj.RegionList:
+ if elementRegion.RegionType == BINARY_FILE_TYPE_FV:
+ for elementRegionData in elementRegion.RegionDataList:
+ if elementRegionData.endswith(".fv"):
+ continue
+ if elementRegionData is not None and elementRegionData.upper() not in FvList:
+ FvList.append(elementRegionData.upper())
+ return FvList
+
+ ## _GetReferencedFdFvTuple() method
+ #
+ # Get FD and FV list referenced by a FFS file
+ #
+ # @param self The object pointer
+ # @param FfsFile contains sections to be searched
+ # @param RefFdList referenced FD by section
+ # @param RefFvList referenced FV by section
+ #
+ def _GetReferencedFdFvTuple(self, FvObj, RefFdList = [], RefFvList = []):
+ for FfsObj in FvObj.FfsList:
+ if isinstance(FfsObj, FileStatement):
+ if FfsObj.FvName is not None and FfsObj.FvName.upper() not in RefFvList:
+ RefFvList.append(FfsObj.FvName.upper())
+ elif FfsObj.FdName is not None and FfsObj.FdName.upper() not in RefFdList:
+ RefFdList.append(FfsObj.FdName.upper())
+ else:
+ self._GetReferencedFdFvTupleFromSection(FfsObj, RefFdList, RefFvList)
+
+ ## _GetReferencedFdFvTupleFromSection() method
+ #
+ # Get FD and FV list referenced by a FFS section
+ #
+ # @param self The object pointer
+ # @param FfsFile contains sections to be searched
+ # @param FdList referenced FD by section
+ # @param FvList referenced FV by section
+ #
+ def _GetReferencedFdFvTupleFromSection(self, FfsFile, FdList = [], FvList = []):
+ SectionStack = list(FfsFile.SectionList)
+ while SectionStack != []:
+ SectionObj = SectionStack.pop()
+ if isinstance(SectionObj, FvImageSection):
+ if SectionObj.FvName is not None and SectionObj.FvName.upper() not in FvList:
+ FvList.append(SectionObj.FvName.upper())
+ if SectionObj.Fv is not None and SectionObj.Fv.UiFvName is not None and SectionObj.Fv.UiFvName.upper() not in FvList:
+ FvList.append(SectionObj.Fv.UiFvName.upper())
+ self._GetReferencedFdFvTuple(SectionObj.Fv, FdList, FvList)
+
+ if isinstance(SectionObj, CompressSection) or isinstance(SectionObj, GuidSection):
+ SectionStack.extend(SectionObj.SectionList)
+
+ ## CycleReferenceCheck() method
+ #
+ # Check whether cycle reference exists in FDF
+ #
+ # @param self The object pointer
+ # @retval True cycle reference exists
+ # @retval False Not exists cycle reference
+ #
+ def CycleReferenceCheck(self):
+ #
+ # Check the cycle between FV and FD image
+ #
+ MaxLength = len (self.Profile.FvDict)
+ for FvName in self.Profile.FvDict:
+ LogStr = "\nCycle Reference Checking for FV: %s\n" % FvName
+ RefFvStack = set(FvName)
+ FdAnalyzedList = set()
+
+ Index = 0
+ while RefFvStack and Index < MaxLength:
+ Index = Index + 1
+ FvNameFromStack = RefFvStack.pop()
+ if FvNameFromStack.upper() in self.Profile.FvDict:
+ FvObj = self.Profile.FvDict[FvNameFromStack.upper()]
+ else:
+ continue
+
+ RefFdList = []
+ RefFvList = []
+ self._GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
+
+ for RefFdName in RefFdList:
+ if RefFdName in FdAnalyzedList:
+ continue
+
+ LogStr += "FV %s contains FD %s\n" % (FvNameFromStack, RefFdName)
+ FvInFdList = self._GetFvInFd(RefFdName)
+ if FvInFdList != []:
+ for FvNameInFd in FvInFdList:
+ LogStr += "FD %s contains FV %s\n" % (RefFdName, FvNameInFd)
+ if FvNameInFd not in RefFvStack:
+ RefFvStack.add(FvNameInFd)
+
+ if FvName in RefFvStack or FvNameFromStack in RefFvStack:
+ EdkLogger.info(LogStr)
+ return True
+ FdAnalyzedList.add(RefFdName)
+
+ for RefFvName in RefFvList:
+ LogStr += "FV %s contains FV %s\n" % (FvNameFromStack, RefFvName)
+ if RefFvName not in RefFvStack:
+ RefFvStack.add(RefFvName)
+
+ if FvName in RefFvStack or FvNameFromStack in RefFvStack:
+ EdkLogger.info(LogStr)
+ return True
+
+ #
+ # Check the cycle between Capsule and FD image
+ #
+ MaxLength = len (self.Profile.CapsuleDict)
+ for CapName in self.Profile.CapsuleDict:
+ #
+ # Capsule image to be checked.
+ #
+ LogStr = "\n\n\nCycle Reference Checking for Capsule: %s\n" % CapName
+ RefCapStack = {CapName}
+ FdAnalyzedList = set()
+ FvAnalyzedList = set()
+
+ Index = 0
+ while RefCapStack and Index < MaxLength:
+ Index = Index + 1
+ CapNameFromStack = RefCapStack.pop()
+ if CapNameFromStack.upper() in self.Profile.CapsuleDict:
+ CapObj = self.Profile.CapsuleDict[CapNameFromStack.upper()]
+ else:
+ continue
+
+ RefFvList = []
+ RefFdList = []
+ self._GetReferencedFdCapTuple(CapObj, RefFdList, RefFvList)
+
+ FvListLength = 0
+ FdListLength = 0
+ while FvListLength < len (RefFvList) or FdListLength < len (RefFdList):
+ for RefFdName in RefFdList:
+ if RefFdName in FdAnalyzedList:
+ continue
+
+ LogStr += "Capsule %s contains FD %s\n" % (CapNameFromStack, RefFdName)
+ for CapNameInFd in self._GetCapInFd(RefFdName):
+ LogStr += "FD %s contains Capsule %s\n" % (RefFdName, CapNameInFd)
+ if CapNameInFd not in RefCapStack:
+ RefCapStack.append(CapNameInFd)
+
+ if CapName in RefCapStack or CapNameFromStack in RefCapStack:
+ EdkLogger.info(LogStr)
+ return True
+
+ for FvNameInFd in self._GetFvInFd(RefFdName):
+ LogStr += "FD %s contains FV %s\n" % (RefFdName, FvNameInFd)
+ if FvNameInFd not in RefFvList:
+ RefFvList.append(FvNameInFd)
+
+ FdAnalyzedList.add(RefFdName)
+ #
+ # the number of the parsed FV and FD image
+ #
+ FvListLength = len (RefFvList)
+ FdListLength = len (RefFdList)
+ for RefFvName in RefFvList:
+ if RefFvName in FvAnalyzedList:
+ continue
+ LogStr += "Capsule %s contains FV %s\n" % (CapNameFromStack, RefFvName)
+ if RefFvName.upper() in self.Profile.FvDict:
+ FvObj = self.Profile.FvDict[RefFvName.upper()]
+ else:
+ continue
+ self._GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
+ FvAnalyzedList.add(RefFvName)
+
+ return False
+
+ def GetAllIncludedFile (self):
+ global AllIncludeFileList
+ return AllIncludeFileList
+
+if __name__ == "__main__":
+ import sys
+ try:
+ test_file = sys.argv[1]
+ except IndexError as v:
+ print("Usage: %s filename" % sys.argv[0])
+ sys.exit(1)
+
+ parser = FdfParser(test_file)
+ try:
+ parser.ParseFile()
+ parser.CycleReferenceCheck()
+ except Warning as X:
+ print(str(X))
+ else:
+ print("Success!")
+