diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /BaseTools/Source/Python/GenFds/FdfParser.py | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'BaseTools/Source/Python/GenFds/FdfParser.py')
| -rw-r--r-- | BaseTools/Source/Python/GenFds/FdfParser.py | 9096 |
1 files changed, 4548 insertions, 4548 deletions
diff --git a/BaseTools/Source/Python/GenFds/FdfParser.py b/BaseTools/Source/Python/GenFds/FdfParser.py index feb4c72779..e3a780f302 100644 --- a/BaseTools/Source/Python/GenFds/FdfParser.py +++ b/BaseTools/Source/Python/GenFds/FdfParser.py @@ -1,4548 +1,4548 @@ -## @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 .SubTypeGuidSection import SubTypeGuidSection
-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(r"\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*")
-RegionSizeGuidPattern = compile(r"\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*\|\s*(?P<size>\w+\.\w+[\.\w\[\]]*)\s*")
-RegionOffsetPcdPattern = compile(r"\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*$")
-ShortcutPcdPattern = compile(r"\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*")
-BaseAddrValuePattern = compile(r'^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)
-
- elif self._IsKeyword("SUBTYPE_GUID"):
- if AlignValue == 'Auto':
- raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
- SubTypeGuidValue = None
- if not self._GetNextGuid():
- raise Warning.Expected("GUID", self.FileName, self.CurrentLineNumber)
- else:
- SubTypeGuidValue = self._Token
-
- if not self._IsToken(TAB_EQUAL_SPLIT):
- raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
- if not self._GetNextToken():
- raise Warning.Expected("section file path", self.FileName, self.CurrentLineNumber)
- FileName = self._Token
-
- SubTypeGuidSectionObj = SubTypeGuidSection()
- SubTypeGuidSectionObj.Alignment = AlignValue
- SubTypeGuidSectionObj.SubTypeGuid = SubTypeGuidValue
- SubTypeGuidSectionObj.SectFileName = FileName
- Obj.SectionList.append(SubTypeGuidSectionObj)
-
- 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, "SEC_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!")
-
+## @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 .SubTypeGuidSection import SubTypeGuidSection +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(r"\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*") +RegionSizeGuidPattern = compile(r"\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*\|\s*(?P<size>\w+\.\w+[\.\w\[\]]*)\s*") +RegionOffsetPcdPattern = compile(r"\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*$") +ShortcutPcdPattern = compile(r"\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*") +BaseAddrValuePattern = compile(r'^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) + + elif self._IsKeyword("SUBTYPE_GUID"): + if AlignValue == 'Auto': + raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber) + SubTypeGuidValue = None + if not self._GetNextGuid(): + raise Warning.Expected("GUID", self.FileName, self.CurrentLineNumber) + else: + SubTypeGuidValue = self._Token + + if not self._IsToken(TAB_EQUAL_SPLIT): + raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber) + if not self._GetNextToken(): + raise Warning.Expected("section file path", self.FileName, self.CurrentLineNumber) + FileName = self._Token + + SubTypeGuidSectionObj = SubTypeGuidSection() + SubTypeGuidSectionObj.Alignment = AlignValue + SubTypeGuidSectionObj.SubTypeGuid = SubTypeGuidValue + SubTypeGuidSectionObj.SectFileName = FileName + Obj.SectionList.append(SubTypeGuidSectionObj) + + 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, "SEC_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!") + |
