summaryrefslogtreecommitdiff
path: root/BaseTools/Source/Python/GenFds/FdfParser.py
diff options
context:
space:
mode:
Diffstat (limited to 'BaseTools/Source/Python/GenFds/FdfParser.py')
-rw-r--r--BaseTools/Source/Python/GenFds/FdfParser.py294
1 files changed, 199 insertions, 95 deletions
diff --git a/BaseTools/Source/Python/GenFds/FdfParser.py b/BaseTools/Source/Python/GenFds/FdfParser.py
index d3d50b638e..bdb7a77770 100644
--- a/BaseTools/Source/Python/GenFds/FdfParser.py
+++ b/BaseTools/Source/Python/GenFds/FdfParser.py
@@ -52,6 +52,8 @@ from Common.Expression import *
from Common import GlobalData
from Common.String import ReplaceMacro
+from Common.Misc import tdict
+
import re
import os
@@ -77,10 +79,6 @@ RegionSizePattern = re.compile("\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<s
RegionSizeGuidPattern = re.compile("\s*(?P<base>\w+\.\w+)\s*\|\s*(?P<size>\w+\.\w+)\s*")
IncludeFileList = []
-# Macro passed from command line, which has greatest priority and can NOT be overridden by those in FDF
-InputMacroDict = {}
-# All Macro values when parsing file, not replace existing Macro
-AllMacroList = []
def GetRealFileLine (File, Line):
@@ -182,7 +180,10 @@ class FileProfile :
self.PcdDict = {}
self.InfList = []
-
+ # ECC will use this Dict and List information
+ self.PcdFileLineDict = {}
+ self.InfFileLineList = []
+
self.FdDict = {}
self.FdNameNotSet = False
self.FvDict = {}
@@ -215,14 +216,17 @@ class FdfParser:
self.__Token = ""
self.__SkippedChars = ""
+ # Used to section info
+ self.__CurSection = []
+ # Key: [section name, UI name, arch]
+ # Value: {MACRO_NAME : MACRO_VALUE}
+ self.__MacroDict = tdict(True, 3)
+ self.__PcdDict = {}
+
self.__WipeOffArea = []
if GenFdsGlobalVariable.WorkSpaceDir == '':
GenFdsGlobalVariable.WorkSpaceDir = os.getenv("WORKSPACE")
- InputMacroDict.update(GlobalData.gPlatformDefines)
- InputMacroDict.update(GlobalData.gGlobalDefines)
- InputMacroDict.update(GlobalData.gCommandLineDefines)
-
## __IsWhiteSpace() method
#
# Whether char at current FileBufferPos is whitespace
@@ -381,30 +385,6 @@ class FdfParser:
self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList]
self.Profile.FileLinesList[-1].append(' ')
- def __ReplaceMacros(self, Str, File, Line):
- MacroEnd = 0
- while Str.find('$(', MacroEnd) >= 0:
- MacroStart = Str.find('$(', MacroEnd)
- if Str.find(')', MacroStart) > 0:
- MacroEnd = Str.find(')', MacroStart)
- Name = Str[MacroStart + 2 : MacroEnd]
- Value = None
- if Name in InputMacroDict:
- Value = InputMacroDict[Name]
-
- else:
- for Profile in AllMacroList:
- if Profile.FileName == File and Profile.MacroName == Name and Profile.DefinedAtLine <= Line:
- Value = Profile.MacroValue
-
- if Value != None:
- Str = Str.replace('$(' + Name + ')', Value)
- MacroEnd = MacroStart + len(Value)
-
- else:
- raise Warning("Macro not complete", self.FileName, self.CurrentLineNumber)
- return Str
-
def __ReplaceFragment(self, StartPos, EndPos, Value = ' '):
if StartPos[0] == EndPos[0]:
Offset = StartPos[1]
@@ -446,7 +426,67 @@ class FdfParser:
self.FileName, self.CurrentLineNumber)
MacroName = MacroName[2:-1]
return MacroName, NotFlag
-
+
+ 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
+ # [VTF.arch.UiName, arch]
+ # [OptionRom.DriverName]
+ self.__CurSection = []
+ Section = Section.strip()[1:-1].upper().replace(' ', '').strip('.')
+ ItemList = Section.split('.')
+ Item = ItemList[0]
+ if Item == '' or Item == 'RULE':
+ return
+
+ if Item == 'DEFINES':
+ self.__CurSection = ['COMMON', 'COMMON', 'COMMON']
+ elif Item == 'VTF' and len(ItemList) == 3:
+ UiName = ItemList[2]
+ Pos = UiName.find(',')
+ if Pos != -1:
+ UiName = UiName[:Pos]
+ self.__CurSection = ['VTF', UiName, ItemList[1]]
+ elif len(ItemList) > 1:
+ self.__CurSection = [ItemList[0], ItemList[1], 'COMMON']
+ elif len(ItemList) > 0:
+ self.__CurSection = [ItemList[0], 'DUMMY', 'COMMON']
+
## PreprocessFile() method
#
# Preprocess file contents, replace comments with spaces.
@@ -530,12 +570,17 @@ class FdfParser:
raise Warning("expected include file name", self.FileName, self.CurrentLineNumber)
IncFileName = self.__Token
__IncludeMacros = {}
- __IncludeMacros['WORKSPACE'] = InputMacroDict['WORKSPACE']
- __IncludeMacros['ECP_SOURCE'] = InputMacroDict['ECP_SOURCE']
- __IncludeMacros['EFI_SOURCE'] = InputMacroDict['EFI_SOURCE']
- __IncludeMacros['EDK_SOURCE'] = InputMacroDict['EDK_SOURCE']
-
- IncludedFile = NormPath(ReplaceMacro(IncFileName, __IncludeMacros, RaiseError=True))
+ for Macro in ['WORKSPACE', 'ECP_SOURCE', 'EFI_SOURCE', 'EDK_SOURCE']:
+ MacroVal = self.__GetMacroValue(Macro)
+ if MacroVal:
+ __IncludeMacros[Macro] = MacroVal
+
+ try:
+ IncludedFile = NormPath(ReplaceMacro(IncFileName, __IncludeMacros, RaiseError=True))
+ except:
+ raise Warning("only these system environment variables are permitted to start the path of the included file: "
+ "$(WORKSPACE), $(ECP_SOURCE), $(EFI_SOURCE), $(EDK_SOURCE)",
+ self.FileName, self.CurrentLineNumber)
#
# First search the include file under the same directory as FDF file
#
@@ -545,7 +590,12 @@ class FdfParser:
#
# Then search the include file under the same directory as DSC file
#
- IncludedFile1 = PathClass(IncludedFile, GenFdsGlobalVariable.ActivePlatform.Dir)
+ 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:
#
@@ -554,7 +604,7 @@ class FdfParser:
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), GenFdsGlobalVariable.ActivePlatform.Dir, GlobalData.gWorkspace),
+ 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)
IncFileProfile = IncludeFileProfile(IncludedFile1.Path)
@@ -608,9 +658,47 @@ class FdfParser:
# 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('['):
+ Header = self.__Token
+ if not self.__Token.endswith(']'):
+ self.__SkipToToken(']')
+ 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:
+ MacroName = CurLine[StartPos+2 : EndPos]
+ MacorValue = self.__GetMacroValue(MacroName)
+ if MacorValue != None:
+ CurLine = CurLine.replace('$(' + MacroName + ')', MacorValue, 1)
+ if MacorValue.find('$(') != -1:
+ PreIndex = StartPos
+ else:
+ PreIndex = StartPos + len(MacorValue)
+ else:
+ PreIndex = EndPos + 1
+ StartPos = CurLine.find('$(', PreIndex)
+ EndPos = CurLine.find(')', StartPos+2)
+ self.Profile.FileLinesList[ReplacedLine - 1] = CurLine
+ continue
+
if self.__Token == 'DEFINE':
- if self.__GetIfListCurrentItemStat(IfList):
+ 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('DEFINE')
if not self.__GetNextToken():
@@ -619,19 +707,8 @@ class FdfParser:
if not self.__IsToken( "="):
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
- if not self.__GetNextToken():
- raise Warning("expected value", self.FileName, self.CurrentLineNumber)
-
- if self.__GetStringData():
- pass
- Value = self.__Token
- if not Macro in InputMacroDict:
- FileLineTuple = GetRealFileLine(self.FileName, DefineLine + 1)
- MacProfile = MacroProfile(FileLineTuple[0], FileLineTuple[1])
- MacProfile.MacroName = Macro
- MacProfile.MacroValue = Value
- AllMacroList.append(MacProfile)
- InputMacroDict[MacProfile.MacroName] = MacProfile.MacroValue
+ Value = self.__GetExpression()
+ self.__SetMacroValue(Macro, Value)
self.__WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
elif self.__Token == 'SET':
PcdPair = self.__GetNextPcdName()
@@ -639,17 +716,10 @@ class FdfParser:
if not self.__IsToken( "="):
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
- if not self.__GetNextToken():
- raise Warning("expected value", self.FileName, self.CurrentLineNumber)
-
- Value = self.__Token
- if Value.startswith("{"):
- # deal with value with {}
- if not self.__SkipToToken( "}"):
- raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
- Value += self.__SkippedChars
+ Value = self.__GetExpression()
+ Value = self.__EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
- InputMacroDict[PcdName] = Value
+ self.__PcdDict[PcdName] = Value
elif self.__Token in ('!ifdef', '!ifndef', '!if'):
IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token))
IfList.append([IfStartPos, None, None])
@@ -691,6 +761,8 @@ class FdfParser:
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:
@@ -709,21 +781,53 @@ class FdfParser:
if not RegionSizeGuid:
RegionLayoutLine = self.CurrentLineNumber + 1
continue
- InputMacroDict[RegionSizeGuid.group('base')] = RegionSize.group('base')
- InputMacroDict[RegionSizeGuid.group('size')] = RegionSize.group('size')
+ 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(self.__PcdDict)
+
+ # Lowest priority
+ MacroDict.update(GlobalData.gPlatformDefines)
+
+ if self.__CurSection:
+ # Defines macro
+ ScopeMacro = self.__MacroDict['COMMON', 'COMMON', '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)
+ # Highest priority
+
+ return MacroDict
+
def __EvaluateConditional(self, Expression, Line, Op = None, Value = None):
FileLineTuple = GetRealFileLine(self.FileName, Line)
+ MacroPcdDict = self.__CollectMacroPcd()
if Op == 'eval':
try:
- return ValueExpression(Expression, InputMacroDict)()
- except SymbolNotFound:
- return False
+ if Value:
+ return ValueExpression(Expression, MacroPcdDict)(True)
+ else:
+ return ValueExpression(Expression, MacroPcdDict)()
except WrnExpression, Excpt:
#
# Catch expression evaluation warning here. We need to report
@@ -738,7 +842,7 @@ class FdfParser:
else:
if Expression.startswith('$(') and Expression[-1] == ')':
Expression = Expression[2:-1]
- return Expression in InputMacroDict
+ return Expression in MacroPcdDict
## __IsToken() method
#
@@ -856,7 +960,7 @@ class FdfParser:
# Record the token start position, the position of the first non-space char.
StartPos = self.CurrentOffsetWithinLine
StartLine = self.CurrentLineNumber
- while not self.__EndOfLine():
+ while StartLine == self.CurrentLineNumber:
TempChar = self.__CurrentChar()
# Try to find the end char that is not a space and not in seperator tuple.
# That is, when we got a space or any char in the tuple, we got the end of token.
@@ -946,7 +1050,7 @@ class FdfParser:
# 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 SEPERATOR_TUPLE:
if not self.__UndoOneChar():
- break
+ return
# if we happen to meet a seperator as the first char, we must proceed to get it.
# That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE:
@@ -1150,12 +1254,6 @@ class FdfParser:
while self.__GetDefines():
pass
-
- Index = 0
- while Index < len(self.Profile.FileLinesList):
- FileLineTuple = GetRealFileLine(self.FileName, Index + 1)
- self.Profile.FileLinesList[Index] = self.__ReplaceMacros(self.Profile.FileLinesList[Index], FileLineTuple[0], FileLineTuple[1])
- Index += 1
## ParseFile() method
#
@@ -1239,11 +1337,6 @@ class FdfParser:
if not self.__GetNextToken() or self.__Token.startswith('['):
raise Warning("expected MACRO value", self.FileName, self.CurrentLineNumber)
Value = self.__Token
- FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
- MacProfile = MacroProfile(FileLineTuple[0], FileLineTuple[1])
- MacProfile.MacroName = Macro
- MacProfile.MacroValue = Value
- AllMacroList.append(MacProfile)
return False
@@ -1279,6 +1372,8 @@ class FdfParser:
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)
@@ -1373,6 +1468,8 @@ class FdfParser:
pcdPair = self.__GetNextPcdName()
Obj.BaseAddressPcd = pcdPair
self.Profile.PcdDict[pcdPair] = Obj.BaseAddress
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
if not self.__IsKeyword( "Size"):
raise Warning("Size missing", self.FileName, self.CurrentLineNumber)
@@ -1389,6 +1486,8 @@ class FdfParser:
pcdPair = self.__GetNextPcdName()
Obj.SizePcd = pcdPair
self.Profile.PcdDict[pcdPair] = Size
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
Obj.Size = long(Size, 0)
if not self.__IsKeyword( "ErasePolarity"):
@@ -1484,6 +1583,8 @@ class FdfParser:
PcdPair = self.__GetNextPcdName()
BlockSizePcd = PcdPair
self.Profile.PcdDict[PcdPair] = BlockSize
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
BlockSize = long(BlockSize, 0)
BlockNumber = None
@@ -1567,19 +1668,14 @@ class FdfParser:
if not self.__IsToken( "="):
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
- if not self.__GetNextToken():
- raise Warning("expected value", self.FileName, self.CurrentLineNumber)
-
- Value = self.__Token
- if Value.startswith("{"):
- # deal with value with {}
- if not self.__SkipToToken( "}"):
- raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
- Value += self.__SkippedChars
+ Value = self.__GetExpression()
+ Value = self.__EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
if Obj:
Obj.SetVarDict[PcdPair] = Value
self.Profile.PcdDict[PcdPair] = Value
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
return True
return False
@@ -1615,9 +1711,13 @@ class FdfParser:
self.__UndoToken()
RegionObj.PcdOffset = self.__GetNextPcdName()
self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + long(Fd.BaseAddress, 0))
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple
if self.__IsToken( "|"):
RegionObj.PcdSize = self.__GetNextPcdName()
self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple
if not self.__GetNextWord():
return True
@@ -2195,6 +2295,8 @@ class FdfParser:
if not ffsInf.InfFileName in self.Profile.InfList:
self.Profile.InfList.append(ffsInf.InfFileName)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.InfFileLineList.append(FileLineTuple)
if self.__IsToken('|'):
if self.__IsKeyword('RELOCS_STRIPPED'):
@@ -2420,7 +2522,7 @@ class FdfParser:
if ErrorCode != 0:
EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
else:
- if not InputMacroDict["OUTPUT_DIRECTORY"] in FfsFileObj.FileName:
+ if not self.__GetMacroValue("OUTPUT_DIRECTORY") in FfsFileObj.FileName:
#do case sensitive check for file path
ErrorCode, ErrorInfo = PathClass(NormPath(FfsFileObj.FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
if ErrorCode != 0:
@@ -3872,6 +3974,8 @@ class FdfParser:
if not ffsInf.InfFileName in self.Profile.InfList:
self.Profile.InfList.append(ffsInf.InfFileName)
+ FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
+ self.Profile.InfFileLineList.append(FileLineTuple)
self.__GetOptRomOverrides (ffsInf)