diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py')
-rwxr-xr-x | src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py | 4526 |
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!") + |