mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-08 17:05:09 +02:00
Since in the GenFds phase, the FV is generated as upper letter. This patch update the FV region name as upper letter, it can fix the build report generate failure on case sensitive file system. Cc: Liming Gao <liming.gao@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Yonghong Zhu <yonghong.zhu@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Andrew Fish <afish@apple.com>
4717 lines
194 KiB
Python
4717 lines
194 KiB
Python
## @file
|
|
# parse FDF file
|
|
#
|
|
# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
|
|
# Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
|
|
#
|
|
# This program and the accompanying materials
|
|
# are licensed and made available under the terms and conditions of the BSD License
|
|
# which accompanies this distribution. The full text of the license may be found at
|
|
# http://opensource.org/licenses/bsd-license.php
|
|
#
|
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
#
|
|
|
|
##
|
|
# Import Modules
|
|
#
|
|
import re
|
|
|
|
import Fd
|
|
import Region
|
|
import Fv
|
|
import AprioriSection
|
|
import FfsInfStatement
|
|
import FfsFileStatement
|
|
import VerSection
|
|
import UiSection
|
|
import FvImageSection
|
|
import DataSection
|
|
import DepexSection
|
|
import CompressSection
|
|
import GuidSection
|
|
import Capsule
|
|
import CapsuleData
|
|
import Rule
|
|
import RuleComplexFile
|
|
import RuleSimpleFile
|
|
import EfiSection
|
|
import Vtf
|
|
import ComponentStatement
|
|
import OptionRom
|
|
import OptRomInfStatement
|
|
import OptRomFileStatement
|
|
|
|
from GenFdsGlobalVariable import GenFdsGlobalVariable
|
|
from Common.BuildToolError import *
|
|
from Common import EdkLogger
|
|
from Common.Misc import PathClass
|
|
from Common.String import NormPath
|
|
import Common.GlobalData as GlobalData
|
|
from Common.Expression import *
|
|
from Common import GlobalData
|
|
from Common.String import ReplaceMacro
|
|
|
|
from Common.Misc import tdict
|
|
|
|
import Common.LongFilePathOs as os
|
|
from Common.LongFilePathSupport import OpenLongFilePath as open
|
|
|
|
##define T_CHAR_SPACE ' '
|
|
##define T_CHAR_NULL '\0'
|
|
##define T_CHAR_CR '\r'
|
|
##define T_CHAR_TAB '\t'
|
|
##define T_CHAR_LF '\n'
|
|
##define T_CHAR_SLASH '/'
|
|
##define T_CHAR_BACKSLASH '\\'
|
|
##define T_CHAR_DOUBLE_QUOTE '\"'
|
|
##define T_CHAR_SINGLE_QUOTE '\''
|
|
##define T_CHAR_STAR '*'
|
|
##define T_CHAR_HASH '#'
|
|
|
|
(T_CHAR_SPACE, T_CHAR_NULL, T_CHAR_CR, T_CHAR_TAB, T_CHAR_LF, T_CHAR_SLASH, \
|
|
T_CHAR_BACKSLASH, T_CHAR_DOUBLE_QUOTE, T_CHAR_SINGLE_QUOTE, T_CHAR_STAR, T_CHAR_HASH) = \
|
|
(' ', '\0', '\r', '\t', '\n', '/', '\\', '\"', '\'', '*', '#')
|
|
|
|
SEPERATOR_TUPLE = ('=', '|', ',', '{', '}')
|
|
|
|
RegionSizePattern = re.compile("\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*")
|
|
RegionSizeGuidPattern = re.compile("\s*(?P<base>\w+\.\w+)\s*\|\s*(?P<size>\w+\.\w+)\s*")
|
|
RegionOffsetPcdPattern = re.compile("\s*(?P<base>\w+\.\w+)\s*$")
|
|
ShortcutPcdPattern = re.compile("\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*")
|
|
|
|
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 "FDF Parser".
|
|
#
|
|
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
|
|
|
|
## The MACRO class that used to record macro value data when parsing include file
|
|
#
|
|
#
|
|
class MacroProfile :
|
|
## The constructor
|
|
#
|
|
# @param self The object pointer
|
|
# @param FileName The file that to be parsed
|
|
#
|
|
def __init__(self, FileName, Line):
|
|
self.FileName = FileName
|
|
self.DefinedAtLine = Line
|
|
self.MacroName = None
|
|
self.MacroValue = None
|
|
|
|
## 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:
|
|
fsock = open(FileName, "rb", 0)
|
|
try:
|
|
self.FileLinesList = fsock.readlines()
|
|
finally:
|
|
fsock.close()
|
|
|
|
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:
|
|
fsock = open(FileName, "rb", 0)
|
|
try:
|
|
self.FileLinesList = fsock.readlines()
|
|
finally:
|
|
fsock.close()
|
|
|
|
except:
|
|
EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
|
|
|
|
|
|
self.PcdDict = {}
|
|
self.InfList = []
|
|
# ECC will use this Dict and List information
|
|
self.PcdFileLineDict = {}
|
|
self.InfFileLineList = []
|
|
|
|
self.FdDict = {}
|
|
self.FdNameNotSet = False
|
|
self.FvDict = {}
|
|
self.CapsuleDict = {}
|
|
self.VtfList = []
|
|
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 = {}
|
|
|
|
self.__WipeOffArea = []
|
|
if GenFdsGlobalVariable.WorkSpaceDir == '':
|
|
GenFdsGlobalVariable.WorkSpaceDir = os.getenv("WORKSPACE")
|
|
|
|
## __IsWhiteSpace() method
|
|
#
|
|
# Whether char at current FileBufferPos is whitespace
|
|
#
|
|
# @param self The object pointer
|
|
# @param Char The char to test
|
|
# @retval True The char is a kind of white space
|
|
# @retval False The char is NOT a kind of white space
|
|
#
|
|
def __IsWhiteSpace(self, Char):
|
|
if Char in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_SPACE, T_CHAR_TAB, T_CHAR_LF):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## __SkipWhiteSpace() method
|
|
#
|
|
# Skip white spaces from current char, return number of chars skipped
|
|
#
|
|
# @param self The object pointer
|
|
# @retval Count The number of chars skipped
|
|
#
|
|
def __SkipWhiteSpace(self):
|
|
Count = 0
|
|
while not self.__EndOfFile():
|
|
Count += 1
|
|
if self.__CurrentChar() in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_LF, T_CHAR_SPACE, T_CHAR_TAB):
|
|
self.__SkippedChars += str(self.__CurrentChar())
|
|
self.__GetOneChar()
|
|
|
|
else:
|
|
Count = Count - 1
|
|
return Count
|
|
|
|
## __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
|
|
elif self.CurrentLineNumber > NumberOfLines:
|
|
return True
|
|
else:
|
|
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
|
|
else:
|
|
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]
|
|
else:
|
|
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]
|
|
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 ('\r', '\n'):
|
|
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 ('\r', '\n'):
|
|
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 __GetMacroName(self):
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber)
|
|
MacroName = self.__Token
|
|
NotFlag = False
|
|
if MacroName.startswith('!'):
|
|
NotFlag = True
|
|
MacroName = MacroName[1:].strip()
|
|
|
|
if not MacroName.startswith('$(') or not MacroName.endswith(')'):
|
|
raise Warning("Macro name expected(Please use '$(%(Token)s)' if '%(Token)s' is a macro.)" % {"Token" : MacroName},
|
|
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.
|
|
# 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() == T_CHAR_LF:
|
|
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() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH:
|
|
self.__SetCurrentCharValue(T_CHAR_SPACE)
|
|
self.__GetOneChar()
|
|
self.__SetCurrentCharValue(T_CHAR_SPACE)
|
|
self.__GetOneChar()
|
|
InComment = False
|
|
# set comments to spaces
|
|
elif InComment:
|
|
self.__SetCurrentCharValue(T_CHAR_SPACE)
|
|
self.__GetOneChar()
|
|
# check for // comment
|
|
elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH and not self.__EndOfLine():
|
|
InComment = True
|
|
DoubleSlashComment = True
|
|
# check for '#' comment
|
|
elif self.__CurrentChar() == T_CHAR_HASH and not self.__EndOfLine() and not InString:
|
|
InComment = True
|
|
HashComment = True
|
|
# check for /* comment start
|
|
elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR:
|
|
self.__SetCurrentCharValue( T_CHAR_SPACE)
|
|
self.__GetOneChar()
|
|
self.__SetCurrentCharValue( T_CHAR_SPACE)
|
|
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
|
|
while self.__GetNextToken():
|
|
|
|
if self.__Token == '!include':
|
|
Processed = True
|
|
IncludeLine = self.CurrentLineNumber
|
|
IncludeOffset = self.CurrentOffsetWithinLine - len('!include')
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected include file name", self.FileName, self.CurrentLineNumber)
|
|
IncFileName = self.__Token
|
|
__IncludeMacros = {}
|
|
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
|
|
#
|
|
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 != 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, '#')
|
|
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()
|
|
|
|
def __GetIfListCurrentItemStat(self, 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('['):
|
|
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 and self.__Token not in ['!ifdef', '!ifndef', '!if', '!elseif']:
|
|
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 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():
|
|
raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber)
|
|
Macro = self.__Token
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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.__GetNextPcdName()
|
|
PcdName = "%s.%s" % (PcdPair[1], PcdPair[0])
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
Value = self.__GetExpression()
|
|
Value = self.__EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
|
|
|
|
self.__PcdDict[PcdName] = Value
|
|
|
|
self.Profile.PcdDict[PcdPair] = Value
|
|
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 ('!ifdef', '!ifndef', '!if'):
|
|
IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token))
|
|
IfList.append([IfStartPos, None, None])
|
|
|
|
CondLabel = self.__Token
|
|
Expression = self.__GetExpression()
|
|
|
|
if CondLabel == '!if':
|
|
ConditionSatisfied = self.__EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
|
|
else:
|
|
ConditionSatisfied = self.__EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'in')
|
|
if CondLabel == '!ifndef':
|
|
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 ('!elseif', '!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 == '!elseif':
|
|
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['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:
|
|
if Value:
|
|
return ValueExpression(Expression, MacroPcdDict)(True)
|
|
else:
|
|
return ValueExpression(Expression, MacroPcdDict)()
|
|
except WrnExpression, 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, 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]),
|
|
*FileLineTuple)
|
|
else:
|
|
raise Warning("PCD (%s) is not defined in DSC file (%s)" % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE']),
|
|
*FileLineTuple)
|
|
else:
|
|
raise Warning(str(Excpt), *FileLineTuple)
|
|
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 SEPERATOR_TUPLE:
|
|
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 ['\r', '\n']:
|
|
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
|
|
|
|
## __GetNextToken() method
|
|
#
|
|
# Get next token unit before a seperator
|
|
# 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 seperator 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 SEPERATOR_TUPLE:
|
|
self.__GetOneChar()
|
|
# 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:
|
|
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 StartPos != self.CurrentOffsetWithinLine:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def __GetNextOp(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
|
|
while not self.__EndOfLine():
|
|
TempChar = self.__CurrentChar()
|
|
# Try to find the end char that is not a space
|
|
if not str(TempChar).isspace():
|
|
self.__GetOneChar()
|
|
else:
|
|
break
|
|
else:
|
|
return False
|
|
|
|
if StartPos != self.CurrentOffsetWithinLine:
|
|
self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
|
|
return True
|
|
else:
|
|
return False
|
|
## __GetNextGuid() method
|
|
#
|
|
# Get next token unit before a seperator
|
|
# 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
|
|
p = re.compile('[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}')
|
|
if p.match(self.__Token) != None:
|
|
return True
|
|
else:
|
|
self.__UndoToken()
|
|
return False
|
|
|
|
## __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 seperator 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 SEPERATOR_TUPLE:
|
|
if not self.__UndoOneChar():
|
|
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:
|
|
return
|
|
else:
|
|
break
|
|
|
|
self.__GetOneChar()
|
|
|
|
## __HexDigit() method
|
|
#
|
|
# Whether char input is a Hex data bit
|
|
#
|
|
# @param self The object pointer
|
|
# @param TempChar The char to test
|
|
# @retval True The char is a Hex data bit
|
|
# @retval False The char is NOT a Hex data bit
|
|
#
|
|
def __HexDigit(self, TempChar):
|
|
if (TempChar >= 'a' and TempChar <= 'f') or (TempChar >= 'A' and TempChar <= 'F') \
|
|
or (TempChar >= '0' and TempChar <= '9'):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def __IsHex(self, HexStr):
|
|
if not HexStr.upper().startswith("0X"):
|
|
return False
|
|
if len(self.__Token) <= 2:
|
|
return False
|
|
charList = [c for c in HexStr[2 : ] if not self.__HexDigit( c)]
|
|
if len(charList) == 0:
|
|
return True
|
|
else:
|
|
return False
|
|
## __GetNextHexNumber() method
|
|
#
|
|
# Get next HEX data before a seperator
|
|
# 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 self.__IsHex(self.__Token):
|
|
return True
|
|
else:
|
|
self.__UndoToken()
|
|
return False
|
|
|
|
## __GetNextDecimalNumber() method
|
|
#
|
|
# Get next decimal data before a seperator
|
|
# 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
|
|
|
|
## __GetNextPcdName() method
|
|
#
|
|
# Get next PCD token space C name and PCD C name pair before a seperator
|
|
# If found, the decimal data is put into self.__Token
|
|
#
|
|
# @param self The object pointer
|
|
# @retval Tuple PCD C name and PCD token space C name pair
|
|
#
|
|
def __GetNextPcdName(self):
|
|
if not self.__GetNextWord():
|
|
raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
|
|
pcdTokenSpaceCName = self.__Token
|
|
|
|
if not self.__IsToken( "."):
|
|
raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextWord():
|
|
raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
|
|
pcdCName = self.__Token
|
|
|
|
return (pcdCName, pcdTokenSpaceCName)
|
|
|
|
## __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):
|
|
if self.__Token.startswith("\"") or self.__Token.startswith("L\""):
|
|
self.__UndoToken()
|
|
self.__SkipToToken("\"")
|
|
currentLineNumber = self.CurrentLineNumber
|
|
|
|
if not self.__SkipToToken("\""):
|
|
raise Warning("Missing Quote \" for String", self.FileName, self.CurrentLineNumber)
|
|
if currentLineNumber != self.CurrentLineNumber:
|
|
raise Warning("Missing Quote \" for String", self.FileName, self.CurrentLineNumber)
|
|
self.__Token = self.__SkippedChars.rstrip('\"')
|
|
return True
|
|
|
|
elif self.__Token.startswith("\'") or self.__Token.startswith("L\'"):
|
|
self.__UndoToken()
|
|
self.__SkipToToken("\'")
|
|
currentLineNumber = self.CurrentLineNumber
|
|
|
|
if not self.__SkipToToken("\'"):
|
|
raise Warning("Missing Quote \' for String", self.FileName, self.CurrentLineNumber)
|
|
if currentLineNumber != self.CurrentLineNumber:
|
|
raise Warning("Missing Quote \' for String", self.FileName, self.CurrentLineNumber)
|
|
self.__Token = self.__SkippedChars.rstrip('\'')
|
|
return True
|
|
|
|
else:
|
|
return False
|
|
|
|
## __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()
|
|
while self.__GetFd():
|
|
pass
|
|
|
|
while self.__GetFv():
|
|
pass
|
|
|
|
while self.__GetFmp():
|
|
pass
|
|
|
|
while self.__GetCapsule():
|
|
pass
|
|
|
|
while self.__GetVtf():
|
|
pass
|
|
|
|
while self.__GetRule():
|
|
pass
|
|
|
|
while self.__GetOptionRom():
|
|
pass
|
|
|
|
except Warning, 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 != 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('\n').rstrip('\r'))
|
|
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("[VTF.") 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.], [VTF.], [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("[") 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( "]"):
|
|
raise Warning("expected ']'", 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("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
if not self.__GetNextToken() or self.__Token.startswith('['):
|
|
raise Warning("expected MACRO value", self.FileName, self.CurrentLineNumber)
|
|
Value = self.__Token
|
|
|
|
return False
|
|
|
|
## __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("[") and not S.startswith("[FD."):
|
|
if not S.startswith("[FV.") and not S.startswith('[FMPPAYLOAD.') and not S.startswith("[CAPSULE.") \
|
|
and not S.startswith("[VTF.") 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( "]"):
|
|
raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
|
|
|
|
FdObj = Fd.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) == 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( "="):
|
|
raise Warning("expected '='", 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
|
|
|
|
## __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( "="):
|
|
raise Warning("expected '='", 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( "|"):
|
|
pcdPair = self.__GetNextPcdName()
|
|
Obj.BaseAddressPcd = pcdPair
|
|
self.Profile.PcdDict[pcdPair] = Obj.BaseAddress
|
|
FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
|
|
self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
|
|
return True
|
|
|
|
if self.__IsKeyword( "Size"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextHexNumber():
|
|
raise Warning("expected Hex size", self.FileName, self.CurrentLineNumber)
|
|
|
|
Size = self.__Token
|
|
if self.__IsToken( "|"):
|
|
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)
|
|
return True
|
|
|
|
if self.__IsKeyword( "ErasePolarity"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Erase Polarity", self.FileName, self.CurrentLineNumber)
|
|
|
|
if self.__Token != "1" and self.__Token != "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( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
|
|
raise Warning("expected address", self.FileName, self.CurrentLineNumber)
|
|
|
|
BsAddress = long(self.__Token, 0)
|
|
Obj.BsBaseAddress = BsAddress
|
|
|
|
if self.__IsKeyword("RtBaseAddress"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
|
|
raise Warning("expected address", self.FileName, self.CurrentLineNumber)
|
|
|
|
RtAddress = long(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] == None or Item[1] == 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( "="):
|
|
raise Warning("expected '='", 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( "|"):
|
|
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
|
|
if self.__IsKeyword( "NumBlocks"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
|
|
raise Warning("expected block numbers", self.FileName, self.CurrentLineNumber)
|
|
|
|
BlockNumber = long(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("DEFINE"):
|
|
self.__GetNextToken()
|
|
Macro = self.__Token
|
|
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
|
|
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.__GetNextPcdName()
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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
|
|
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 long(
|
|
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 Fd for whom region is got
|
|
# @retval True Successfully find
|
|
# @retval False Not able to find
|
|
#
|
|
def __GetRegionLayout(self, Fd):
|
|
Offset = self.__CalcRegionExpr()
|
|
if Offset == None:
|
|
return False
|
|
|
|
RegionObj = Region.Region()
|
|
RegionObj.Offset = Offset
|
|
Fd.RegionList.append(RegionObj)
|
|
|
|
if not self.__IsToken( "|"):
|
|
raise Warning("expected '|'", self.FileName, self.CurrentLineNumber)
|
|
|
|
Size = self.__CalcRegionExpr()
|
|
if Size == 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", "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.__GetNextPcdName()
|
|
self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + long(Fd.BaseAddress, 0))
|
|
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( "|"):
|
|
RegionObj.PcdSize = self.__GetNextPcdName()
|
|
self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size
|
|
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 == "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(Fd):
|
|
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( "FV"):
|
|
raise Warning("expected Keyword 'FV'", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected FV name", self.FileName, self.CurrentLineNumber)
|
|
|
|
RegionObj.RegionType = "FV"
|
|
RegionObj.RegionDataList.append((self.__Token).upper())
|
|
|
|
while self.__IsKeyword( "FV"):
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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 Keyword 'CAPSULE'", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", 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("="):
|
|
raise Warning("expected '='", 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 Keyword 'FILE'", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken( "{"):
|
|
raise Warning("expected '{'", 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] + ","
|
|
AllStrLen = AllStrLen - 2
|
|
DataString = DataString + AllString[:AllStrLen] + ","
|
|
|
|
# byte value array
|
|
if len (self.__Token) <= 4:
|
|
while self.__IsToken(","):
|
|
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 += ","
|
|
|
|
if not self.__IsToken( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
DataString = DataString.rstrip(",")
|
|
RegionObj.RegionType = "DATA"
|
|
RegionObj.RegionDataList.append( DataString)
|
|
|
|
while self.__IsKeyword( "DATA"):
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken( "{"):
|
|
raise Warning("expected '{'", 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] + ","
|
|
AllStrLen = AllStrLen - 2
|
|
DataString = DataString + AllString[:AllStrLen] + ","
|
|
|
|
# byte value array
|
|
if len (self.__Token) <= 4:
|
|
while self.__IsToken(","):
|
|
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 += ","
|
|
|
|
if not self.__IsToken( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
DataString = DataString.rstrip(",")
|
|
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("[") 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( "]"):
|
|
raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
|
|
|
|
FvObj = Fv.FV()
|
|
FvObj.UiFvName = 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)
|
|
|
|
FvObj.FvExtEntryTypeValue = []
|
|
FvObj.FvExtEntryType = []
|
|
FvObj.FvExtEntryData = []
|
|
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, FvObj.DefineVarDict.copy())
|
|
self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy())
|
|
|
|
while True:
|
|
isInf = self.__GetInfStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy())
|
|
isFile = self.__GetFileStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy())
|
|
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( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected FV base address value", self.FileName, self.CurrentLineNumber)
|
|
|
|
IsValidBaseAddrValue = re.compile('^0[x|X][0-9a-fA-F]+')
|
|
|
|
if not IsValidBaseAddrValue.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( "="):
|
|
raise Warning("expected '='", 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"):
|
|
self.__UndoToken()
|
|
return False
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextGuid():
|
|
raise Warning("expected FV GUID value", self.FileName, self.CurrentLineNumber)
|
|
|
|
FvObj.FvNameGuid = self.__Token
|
|
|
|
return True
|
|
|
|
def __GetFvNameString(self, FvObj):
|
|
|
|
if not self.__IsKeyword( "FvNameString"):
|
|
return False
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken() or self.__Token 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"):
|
|
return False
|
|
|
|
if not self.__IsKeyword ("TYPE"):
|
|
raise Warning("expected 'TYPE'", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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 += [self.__Token]
|
|
|
|
if not self.__IsToken( "{"):
|
|
raise Warning("expected '{'", 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 += [self.__Token]
|
|
|
|
if self.__Token == 'DATA':
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken( "{"):
|
|
raise Warning("expected '{'", 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 += ","
|
|
|
|
while self.__IsToken(","):
|
|
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 += ","
|
|
|
|
if not self.__IsToken( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
DataString = DataString.rstrip(",")
|
|
FvObj.FvExtEntryData += [DataString]
|
|
|
|
if self.__Token == 'FILE':
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected FV Extension Entry file path At Line ", self.FileName, self.CurrentLineNumber)
|
|
|
|
FvObj.FvExtEntryData += [self.__Token]
|
|
|
|
if not self.__IsToken( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
return True
|
|
|
|
## __GetAprioriSection() method
|
|
#
|
|
# Get token statements
|
|
#
|
|
# @param self The object pointer
|
|
# @param FvObj for whom apriori is got
|
|
# @param MacroDict dictionary used to replace macro
|
|
# @retval True Successfully find apriori statement
|
|
# @retval False Not able to find apriori statement
|
|
#
|
|
def __GetAprioriSection(self, FvObj, MacroDict = {}):
|
|
|
|
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("expected '{'", self.FileName, self.CurrentLineNumber)
|
|
|
|
AprSectionObj = AprioriSection.AprioriSection()
|
|
AprSectionObj.AprioriType = AprType
|
|
|
|
self.__GetDefineStatements(AprSectionObj)
|
|
MacroDict.update(AprSectionObj.DefineVarDict)
|
|
|
|
while True:
|
|
IsInf = self.__GetInfStatement( AprSectionObj, MacroDict = MacroDict)
|
|
IsFile = self.__GetFileStatement( AprSectionObj)
|
|
if not IsInf and not IsFile:
|
|
break
|
|
|
|
if not self.__IsToken( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
FvObj.AprioriSectionList.append(AprSectionObj)
|
|
return True
|
|
|
|
def __ParseInfStatement(self):
|
|
if not self.__IsKeyword("INF"):
|
|
return None
|
|
|
|
ffsInf = FfsInfStatement.FfsInfStatement()
|
|
self.__GetInfOptions(ffsInf)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber)
|
|
ffsInf.InfFileName = self.__Token
|
|
|
|
ffsInf.CurrentLineNum = self.CurrentLineNumber
|
|
ffsInf.CurrentLineContent = self.__CurrentLine()
|
|
|
|
#Replace $(SAPCE) with real space
|
|
ffsInf.InfFileName = ffsInf.InfFileName.replace('$(SPACE)', ' ')
|
|
|
|
if ffsInf.InfFileName.replace('$(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)
|
|
|
|
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'):
|
|
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
|
|
# @param MacroDict dictionary used to replace macro
|
|
# @retval True Successfully find inf statement
|
|
# @retval False Not able to find inf statement
|
|
#
|
|
def __GetInfStatement(self, Obj, ForCapsule=False, MacroDict={}):
|
|
ffsInf = self.__ParseInfStatement()
|
|
if not ffsInf:
|
|
return False
|
|
|
|
if ForCapsule:
|
|
capsuleFfs = CapsuleData.CapsuleFfs()
|
|
capsuleFfs.Ffs = ffsInf
|
|
Obj.CapsuleDataList.append(capsuleFfs)
|
|
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("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
if not self.__GetNextGuid():
|
|
raise Warning("expected GUID value", self.FileName, self.CurrentLineNumber)
|
|
FfsInfObj.OverrideGuid = self.__Token
|
|
|
|
if self.__IsKeyword( "RuleOverride"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", 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( "UI"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", 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 = re.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(","):
|
|
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(","):
|
|
break
|
|
|
|
## __GetFileStatement() method
|
|
#
|
|
# Get FILE statements
|
|
#
|
|
# @param self The object pointer
|
|
# @param Obj for whom FILE statement is got
|
|
# @param MacroDict dictionary used to replace macro
|
|
# @retval True Successfully find FILE statement
|
|
# @retval False Not able to find FILE statement
|
|
#
|
|
def __GetFileStatement(self, Obj, ForCapsule = False, MacroDict = {}):
|
|
|
|
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 = FfsFileStatement.FileStatement()
|
|
FfsFileObj.FvFileType = self.__Token
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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.__GetNextPcdName()
|
|
if not self.__IsToken( ")"):
|
|
raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
|
|
self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')'
|
|
|
|
FfsFileObj.NameGuid = self.__Token
|
|
|
|
self.__GetFilePart( FfsFileObj, MacroDict.copy())
|
|
|
|
if ForCapsule:
|
|
capsuleFfs = CapsuleData.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 self The object pointer
|
|
# @param FileType The file type to check with
|
|
# @retval True This type could have relocation strip flag
|
|
# @retval False No way to have it
|
|
#
|
|
|
|
def __FileCouldHaveRelocFlag (self, FileType):
|
|
if FileType in ('SEC', 'PEI_CORE', 'PEIM', 'PEI_DXE_COMBO'):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## __SectionCouldHaveRelocFlag() method
|
|
#
|
|
# Check whether reloc strip flag can be set for a section type.
|
|
#
|
|
# @param self The object pointer
|
|
# @param SectionType The section type to check with
|
|
# @retval True This type could have relocation strip flag
|
|
# @retval False No way to have it
|
|
#
|
|
|
|
def __SectionCouldHaveRelocFlag (self, SectionType):
|
|
if SectionType in ('TE', '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
|
|
# @param MacroDict dictionary used to replace macro
|
|
#
|
|
def __GetFilePart(self, FfsFileObj, MacroDict = {}):
|
|
|
|
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("expected '{'", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected File name or section data", self.FileName, self.CurrentLineNumber)
|
|
|
|
if self.__Token == "FV":
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", 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 ("DEFINE", "APRIORI", "SECTION"):
|
|
self.__UndoToken()
|
|
self.__GetSectionData( FfsFileObj, MacroDict)
|
|
|
|
elif hasattr(FfsFileObj, 'FvFileType') and FfsFileObj.FvFileType == 'RAW':
|
|
self.__UndoToken()
|
|
self.__GetRAWData(FfsFileObj, MacroDict)
|
|
|
|
else:
|
|
FfsFileObj.CurrentLineNum = self.CurrentLineNumber
|
|
FfsFileObj.CurrentLineContent = self.__CurrentLine()
|
|
FfsFileObj.FileName = self.__Token.replace('$(SPACE)', ' ')
|
|
self.__VerifyFile(FfsFileObj.FileName)
|
|
|
|
if not self.__IsToken( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
## __GetRAWData() method
|
|
#
|
|
# Get RAW data for FILE statement
|
|
#
|
|
# @param self The object pointer
|
|
# @param FfsFileObj for whom section is got
|
|
# @param MacroDict dictionary used to replace macro
|
|
#
|
|
def __GetRAWData(self, FfsFileObj, MacroDict = {}):
|
|
FfsFileObj.FileName = []
|
|
FfsFileObj.SubAlignment = []
|
|
while True:
|
|
AlignValue = None
|
|
if self.__GetAlignment():
|
|
if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
|
|
raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
AlignValue = self.__Token
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Filename value", self.FileName, self.CurrentLineNumber)
|
|
|
|
FileName = self.__Token.replace('$(SPACE)', ' ')
|
|
if FileName == '}':
|
|
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( "}"):
|
|
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():
|
|
Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
|
|
if Pattern.match(self.__Token):
|
|
FfsFileObj.KeyStringList.append(self.__Token)
|
|
if self.__IsToken(","):
|
|
while self.__GetNextToken():
|
|
if not Pattern.match(self.__Token):
|
|
raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
|
|
FfsFileObj.KeyStringList.append(self.__Token)
|
|
|
|
if not self.__IsToken(","):
|
|
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 ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
|
|
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( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected alignment value", self.FileName, self.CurrentLineNumber)
|
|
return True
|
|
|
|
return False
|
|
|
|
## __GetFilePart() method
|
|
#
|
|
# Get section data for FILE statement
|
|
#
|
|
# @param self The object pointer
|
|
# @param FfsFileObj for whom section is got
|
|
# @param MacroDict dictionary used to replace macro
|
|
#
|
|
def __GetSectionData(self, FfsFileObj, MacroDict = {}):
|
|
Dict = {}
|
|
Dict.update(MacroDict)
|
|
|
|
self.__GetDefineStatements(FfsFileObj)
|
|
|
|
Dict.update(FfsFileObj.DefineVarDict)
|
|
self.__GetAprioriSection(FfsFileObj, Dict.copy())
|
|
self.__GetAprioriSection(FfsFileObj, Dict.copy())
|
|
|
|
while True:
|
|
IsLeafSection = self.__GetLeafSection(FfsFileObj, Dict)
|
|
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
|
|
# @param MacroDict dictionary used to replace macro
|
|
# @retval True Successfully find section statement
|
|
# @retval False Not able to find section statement
|
|
#
|
|
def __GetLeafSection(self, Obj, MacroDict = {}):
|
|
|
|
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 ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
|
|
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( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected version", self.FileName, self.CurrentLineNumber)
|
|
VerSectionObj = VerSection.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( "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( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected UI", self.FileName, self.CurrentLineNumber)
|
|
UiSectionObj = UiSection.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( "="):
|
|
raise Warning("expected '='", 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.FV()
|
|
FvObj.UiFvName = FvName.upper()
|
|
self.__GetDefineStatements(FvObj)
|
|
MacroDict.update(FvObj.DefineVarDict)
|
|
self.__GetBlockStatement(FvObj)
|
|
self.__GetSetStatements(FvObj)
|
|
self.__GetFvAlignment(FvObj)
|
|
self.__GetFvAttributes(FvObj)
|
|
self.__GetAprioriSection(FvObj, MacroDict.copy())
|
|
self.__GetAprioriSection(FvObj, MacroDict.copy())
|
|
|
|
while True:
|
|
IsInf = self.__GetInfStatement(FvObj, MacroDict.copy())
|
|
IsFile = self.__GetFileStatement(FvObj, MacroDict.copy())
|
|
if not IsInf and not IsFile:
|
|
break
|
|
|
|
if not self.__IsToken( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
FvImageSectionObj = FvImageSection.FvImageSection()
|
|
FvImageSectionObj.Alignment = AlignValue
|
|
if FvObj != 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.DepexSection()
|
|
DepexSectionObj.Alignment = AlignValue
|
|
DepexSectionObj.DepexType = self.__Token
|
|
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
if not self.__IsToken( "{"):
|
|
raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
|
|
if not self.__SkipToToken( "}"):
|
|
raise Warning("expected Depex expression ending '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
DepexSectionObj.Expression = self.__SkippedChars.rstrip('}')
|
|
Obj.SectionList.append(DepexSectionObj)
|
|
|
|
else:
|
|
if not self.__GetNextWord():
|
|
raise Warning("expected section type", self.FileName, self.CurrentLineNumber)
|
|
|
|
# Encapsulation section appear, UndoToken and return
|
|
if self.__Token == "COMPRESS" or self.__Token == "GUIDED":
|
|
self.SetFileBufferPos(OldPos)
|
|
return False
|
|
|
|
if self.__Token not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
|
|
"UI", "VERSION", "PEI_DEPEX", "SUBTYPE_GUID", "SMM_DEPEX"):
|
|
raise Warning("Unknown section type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
if AlignValue == 'Auto'and (not self.__Token == 'PE32') and (not self.__Token == 'TE'):
|
|
raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
|
|
|
|
# DataSection
|
|
DataSectionObj = DataSection.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("="):
|
|
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('$(WORKSPACE)', '').find('$') != -1:
|
|
return
|
|
if not GlobalData.gAutoGenPhase or not self.__GetMacroValue("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("expected '{'", self.FileName, self.CurrentLineNumber)
|
|
|
|
CompressSectionObj = CompressSection.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( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
Obj.SectionList.append(CompressSectionObj)
|
|
|
|
# else:
|
|
# raise Warning("Compress type not known")
|
|
|
|
return True
|
|
|
|
elif self.__IsKeyword( "GUIDED"):
|
|
GuidValue = None
|
|
if self.__GetNextGuid():
|
|
GuidValue = self.__Token
|
|
|
|
AttribDict = self.__GetGuidAttrib()
|
|
if not self.__IsToken("{"):
|
|
raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
|
|
GuidSectionObj = GuidSection.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( "}"):
|
|
raise Warning("expected '}'", 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("="):
|
|
raise Warning("expected '='", 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 ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
|
|
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("[") 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 = CapsuleData.CapsulePayload()
|
|
FmpData.UiName = FmpUiName
|
|
|
|
if not self.__IsToken( "]"):
|
|
raise Warning("expected ']'", 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']
|
|
while self.__Token in FmpKeyList:
|
|
Name = self.__Token
|
|
FmpKeyList.remove(Name)
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", 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
|
|
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':
|
|
FmpData.Version = Value
|
|
elif Name == 'IMAGE_INDEX':
|
|
FmpData.ImageIndex = Value
|
|
elif Name == 'HARDWARE_INSTANCE':
|
|
FmpData.HardwareInstance = Value
|
|
if not self.__GetNextToken():
|
|
break
|
|
else:
|
|
self.__UndoToken()
|
|
|
|
if FmpKeyList:
|
|
raise Warning("Missing keywords %s in FMP payload section" % ', '.join(FmpKeyList), self.FileName, self.CurrentLineNumber)
|
|
ImageFile = self.__ParseRawFileStatement()
|
|
if not ImageFile:
|
|
raise Warning("Missing image file in FMP payload section", self.FileName, self.CurrentLineNumber)
|
|
FmpData.ImageFile = ImageFile
|
|
VendorCodeFile = self.__ParseRawFileStatement()
|
|
if VendorCodeFile:
|
|
FmpData.VendorCodeFile = VendorCodeFile
|
|
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("[") 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.Capsule()
|
|
|
|
CapsuleName = self.__GetUiName()
|
|
if not CapsuleName:
|
|
raise Warning("expected capsule name", self.FileName, self.CurrentLineNumber)
|
|
|
|
CapsuleObj.UiCapsuleName = CapsuleName.upper()
|
|
|
|
if not self.__IsToken( "]"):
|
|
raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
|
|
|
|
if self.__IsKeyword("CREATE_FILE"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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("="):
|
|
raise Warning("expected '='", 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(","):
|
|
Value += ','
|
|
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 between 0x0000 and 0xFFFF", self.FileName, self.CurrentLineNumber)
|
|
try:
|
|
Value = int(Value, 0)
|
|
except ValueError:
|
|
raise Warning("expected hex value between 0x0000 and 0xFFFF", 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
|
|
|
|
## __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):
|
|
|
|
if not self.__IsKeyword("FV"):
|
|
return False
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", 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.keys():
|
|
raise Warning("FV name does not exist", self.FileName, self.CurrentLineNumber)
|
|
|
|
CapsuleFv = CapsuleData.CapsuleFv()
|
|
CapsuleFv.FvName = self.__Token
|
|
CapsuleObj.CapsuleDataList.append(CapsuleFv)
|
|
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):
|
|
|
|
if not self.__IsKeyword("FD"):
|
|
return False
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", 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.keys():
|
|
raise Warning("FD name does not exist", self.FileName, self.CurrentLineNumber)
|
|
|
|
CapsuleFd = CapsuleData.CapsuleFd()
|
|
CapsuleFd.FdName = self.__Token
|
|
CapsuleObj.CapsuleDataList.append(CapsuleFd)
|
|
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("="):
|
|
raise Warning("expected '='", 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("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected File name", self.FileName, self.CurrentLineNumber)
|
|
|
|
AnyFileName = self.__Token
|
|
self.__VerifyFile(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):
|
|
AnyFileName = self.__ParseRawFileStatement()
|
|
if not AnyFileName:
|
|
return False
|
|
|
|
CapsuleAnyFile = CapsuleData.CapsuleAnyFile()
|
|
CapsuleAnyFile.FileName = AnyFileName
|
|
CapsuleObj.CapsuleDataList.append(CapsuleAnyFile)
|
|
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("="):
|
|
raise Warning("expected '='", 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","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
|
|
|
|
CapsuleAfile = CapsuleData.CapsuleAfile()
|
|
CapsuleAfile.FileName = AfileName
|
|
CapsuleObj.CapsuleDataList.append(CapsuleAfile)
|
|
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("[") 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("."):
|
|
raise Warning("expected '.'", self.FileName, self.CurrentLineNumber)
|
|
|
|
Arch = self.__SkippedChars.rstrip(".")
|
|
if Arch.upper() not in ("IA32", "X64", "IPF", "EBC", "ARM", "AARCH64", "COMMON"):
|
|
raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber)
|
|
|
|
ModuleType = self.__GetModuleType()
|
|
|
|
TemplateName = ""
|
|
if self.__IsToken("."):
|
|
if not self.__GetNextWord():
|
|
raise Warning("expected template name", self.FileName, self.CurrentLineNumber)
|
|
TemplateName = self.__Token
|
|
|
|
if not self.__IsToken( "]"):
|
|
raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
|
|
|
|
RuleObj = self.__GetRuleFileStatements()
|
|
RuleObj.Arch = Arch.upper()
|
|
RuleObj.ModuleType = ModuleType
|
|
RuleObj.TemplateName = TemplateName
|
|
if TemplateName == '' :
|
|
self.Profile.RuleDict['RULE' + \
|
|
'.' + \
|
|
Arch.upper() + \
|
|
'.' + \
|
|
ModuleType.upper() ] = RuleObj
|
|
else :
|
|
self.Profile.RuleDict['RULE' + \
|
|
'.' + \
|
|
Arch.upper() + \
|
|
'.' + \
|
|
ModuleType.upper() + \
|
|
'.' + \
|
|
TemplateName.upper() ] = RuleObj
|
|
# self.Profile.RuleList.append(rule)
|
|
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 ("SEC", "PEI_CORE", "PEIM", "DXE_CORE", \
|
|
"DXE_DRIVER", "DXE_SAL_DRIVER", \
|
|
"DXE_SMM_DRIVER", "DXE_RUNTIME_DRIVER", \
|
|
"UEFI_DRIVER", "UEFI_APPLICATION", "USER_DEFINED", "DEFAULT", "BASE", \
|
|
"SECURITY_CORE", "COMBINED_PEIM_DRIVER", "PIC_PEIM", "RELOCATABLE_PEIM", \
|
|
"PE32_PEIM", "BS_DRIVER", "RT_DRIVER", "SAL_RT_DRIVER", "APPLICATION", "ACPITABLE", "SMM_CORE"):
|
|
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("."):
|
|
raise Warning("expected '.'", self.FileName, self.CurrentLineNumber)
|
|
|
|
Ext = ""
|
|
if self.__GetNextToken():
|
|
Pattern = re.compile(r'([a-zA-Z][a-zA-Z0-9]*)')
|
|
if Pattern.match(self.__Token):
|
|
Ext = self.__Token
|
|
return '.' + 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", "SEC", "PEI_CORE", "PEIM",\
|
|
"PEI_DXE_COMBO", "DRIVER", "DXE_CORE", "APPLICATION", "FV_IMAGE", "SMM", "SMM_CORE"):
|
|
raise Warning("Unknown FV type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsKeyword("$(NAMED_GUID)"):
|
|
if not self.__GetNextWord():
|
|
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.__GetNextPcdName()
|
|
if not self.__IsToken( ")"):
|
|
raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
|
|
self.__Token = 'PCD('+PcdPair[1]+'.'+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():
|
|
Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
|
|
if Pattern.match(self.__Token):
|
|
KeyStringList.append(self.__Token)
|
|
if self.__IsToken(","):
|
|
while self.__GetNextToken():
|
|
if not Pattern.match(self.__Token):
|
|
raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
|
|
KeyStringList.append(self.__Token)
|
|
|
|
if not self.__IsToken(","):
|
|
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 ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
|
|
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
|
|
Rule = RuleComplexFile.RuleComplexFile()
|
|
Rule.FvFileType = Type
|
|
Rule.NameGuid = NameGuid
|
|
Rule.Alignment = AlignValue
|
|
Rule.CheckSum = CheckSum
|
|
Rule.Fixed = Fixed
|
|
Rule.KeyStringList = KeyStringList
|
|
if KeepReloc != None:
|
|
Rule.KeepReloc = KeepReloc
|
|
|
|
while True:
|
|
IsEncapsulate = self.__GetRuleEncapsulationSection(Rule)
|
|
IsLeaf = self.__GetEfiSection(Rule)
|
|
if not IsEncapsulate and not IsLeaf:
|
|
break
|
|
|
|
if not self.__IsToken("}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
|
|
return Rule
|
|
|
|
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", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
|
|
"UI", "PEI_DEPEX", "VERSION", "SUBTYPE_GUID", "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 ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
|
|
raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
if self.__Token == 'Auto' and (not SectionName == 'PE32') and (not SectionName == '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('|'):
|
|
Ext = self.__GetFileExtension()
|
|
elif not self.__GetNextToken():
|
|
raise Warning("expected File name", self.FileName, self.CurrentLineNumber)
|
|
|
|
Rule = RuleSimpleFile.RuleSimpleFile()
|
|
Rule.SectionType = SectionName
|
|
Rule.FvFileType = Type
|
|
Rule.NameGuid = NameGuid
|
|
Rule.Alignment = AlignValue
|
|
Rule.SectAlignment = SectAlignment
|
|
Rule.CheckSum = CheckSum
|
|
Rule.Fixed = Fixed
|
|
Rule.KeyStringList = KeyStringList
|
|
if KeepReloc != None:
|
|
Rule.KeepReloc = KeepReloc
|
|
Rule.FileExtension = Ext
|
|
Rule.FileName = self.__Token
|
|
return Rule
|
|
|
|
## __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()
|
|
if not self.__GetNextWord():
|
|
return False
|
|
SectionName = self.__Token
|
|
|
|
if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
|
|
"UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"):
|
|
self.__UndoToken()
|
|
return False
|
|
|
|
if SectionName == "FV_IMAGE":
|
|
FvImageSectionObj = FvImageSection.FvImageSection()
|
|
if self.__IsKeyword("FV_IMAGE"):
|
|
pass
|
|
if self.__IsToken( "{"):
|
|
FvObj = Fv.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( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
FvImageSectionObj.Fv = FvObj
|
|
FvImageSectionObj.FvName = None
|
|
|
|
else:
|
|
if not self.__IsKeyword("FV"):
|
|
raise Warning("expected 'FV'", self.FileName, self.CurrentLineNumber)
|
|
FvImageSectionObj.FvFileType = self.__Token
|
|
|
|
if self.__GetAlignment():
|
|
if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
|
|
raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
FvImageSectionObj.Alignment = self.__Token
|
|
|
|
if self.__IsToken('|'):
|
|
FvImageSectionObj.FvFileExtension = self.__GetFileExtension()
|
|
elif self.__GetNextToken():
|
|
if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
|
|
"UI", "VERSION", "PEI_DEPEX", "GUID", "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 = EfiSection.EfiSection()
|
|
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('='):
|
|
raise Warning("expected '='", 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("="):
|
|
raise Warning("expected '='", 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("="):
|
|
raise Warning("expected '='", 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 ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
|
|
raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
if self.__Token == 'Auto' and (not SectionName == 'PE32') and (not SectionName == '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 != 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('|'):
|
|
EfiSectionObj.FileExtension = self.__GetFileExtension()
|
|
elif self.__GetNextToken():
|
|
if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
|
|
"UI", "VERSION", "PEI_DEPEX", "GUID", "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.__GetNextPcdName()
|
|
if not self.__IsToken( ")"):
|
|
raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
|
|
self.__Token = 'PCD('+PcdPair[1]+'.'+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 self The object pointer
|
|
# @param SectionType The section type to check
|
|
# @retval True section could be optional
|
|
# @retval False section never optional
|
|
#
|
|
def __RuleSectionCouldBeOptional(self, SectionType):
|
|
if SectionType in ("DXE_DEPEX", "UI", "VERSION", "PEI_DEPEX", "RAW", "SMM_DEPEX"):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## __RuleSectionCouldHaveBuildNum() method
|
|
#
|
|
# Get whether a section could have build number information
|
|
#
|
|
# @param self The object pointer
|
|
# @param SectionType The section type to check
|
|
# @retval True section could have build number information
|
|
# @retval False section never have build number information
|
|
#
|
|
def __RuleSectionCouldHaveBuildNum(self, SectionType):
|
|
if SectionType in ("VERSION"):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
## __RuleSectionCouldHaveString() method
|
|
#
|
|
# Get whether a section could have string
|
|
#
|
|
# @param self The object pointer
|
|
# @param SectionType The section type to check
|
|
# @retval True section could have string
|
|
# @retval False section never have string
|
|
#
|
|
def __RuleSectionCouldHaveString(self, SectionType):
|
|
if SectionType in ("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):
|
|
if SectionType == "COMPAT16":
|
|
if FileType not in ("COMPAT16", "SEC_COMPAT16"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "PE32":
|
|
if FileType not in ("PE32", "SEC_PE32"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "PIC":
|
|
if FileType not in ("PIC", "PIC"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "TE":
|
|
if FileType not in ("TE", "SEC_TE"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "RAW":
|
|
if FileType not in ("BIN", "SEC_BIN", "RAW", "ASL", "ACPI"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "DXE_DEPEX" or SectionType == "SMM_DEPEX":
|
|
if FileType not in ("DXE_DEPEX", "SEC_DXE_DEPEX", "SMM_DEPEX"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "UI":
|
|
if FileType not in ("UI", "SEC_UI"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "VERSION":
|
|
if FileType not in ("VERSION", "SEC_VERSION"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "PEI_DEPEX":
|
|
if FileType not in ("PEI_DEPEX", "SEC_PEI_DEPEX"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
elif SectionType == "GUID":
|
|
if FileType not in ("PE32", "SEC_GUID"):
|
|
raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
|
|
|
|
## __GetRuleEncapsulationSection() method
|
|
#
|
|
# Get encapsulation section for Rule
|
|
#
|
|
# @param self The object pointer
|
|
# @param Rule for whom section is got
|
|
# @retval True Successfully find section statement
|
|
# @retval False Not able to find section statement
|
|
#
|
|
def __GetRuleEncapsulationSection(self, Rule):
|
|
|
|
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("expected '{'", self.FileName, self.CurrentLineNumber)
|
|
|
|
CompressSectionObj = CompressSection.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( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
Rule.SectionList.append(CompressSectionObj)
|
|
|
|
return True
|
|
|
|
elif self.__IsKeyword( "GUIDED"):
|
|
GuidValue = None
|
|
if self.__GetNextGuid():
|
|
GuidValue = self.__Token
|
|
|
|
if self.__IsKeyword( "$(NAMED_GUID)"):
|
|
GuidValue = self.__Token
|
|
|
|
AttribDict = self.__GetGuidAttrib()
|
|
|
|
if not self.__IsToken("{"):
|
|
raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
|
|
GuidSectionObj = GuidSection.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( "}"):
|
|
raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
|
|
Rule.SectionList.append(GuidSectionObj)
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
## __GetVtf() method
|
|
#
|
|
# Get VTF section contents and store its data into VTF list of self.Profile
|
|
#
|
|
# @param self The object pointer
|
|
# @retval True Successfully find a VTF
|
|
# @retval False Not able to find a VTF
|
|
#
|
|
def __GetVtf(self):
|
|
|
|
if not self.__GetNextToken():
|
|
return False
|
|
|
|
S = self.__Token.upper()
|
|
if S.startswith("[") and not S.startswith("[VTF."):
|
|
self.SectionParser(S)
|
|
self.__UndoToken()
|
|
return False
|
|
|
|
self.__UndoToken()
|
|
if not self.__IsToken("[VTF.", 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 [VTF.]", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__SkipToToken("."):
|
|
raise Warning("expected '.'", self.FileName, self.CurrentLineNumber)
|
|
|
|
Arch = self.__SkippedChars.rstrip(".").upper()
|
|
if Arch not in ("IA32", "X64", "IPF", "ARM", "AARCH64"):
|
|
raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextWord():
|
|
raise Warning("expected VTF name", self.FileName, self.CurrentLineNumber)
|
|
Name = self.__Token.upper()
|
|
|
|
VtfObj = Vtf.Vtf()
|
|
VtfObj.UiName = Name
|
|
VtfObj.KeyArch = Arch
|
|
|
|
if self.__IsToken(","):
|
|
if not self.__GetNextWord():
|
|
raise Warning("expected Arch list", self.FileName, self.CurrentLineNumber)
|
|
if self.__Token.upper() not in ("IA32", "X64", "IPF", "ARM", "AARCH64"):
|
|
raise Warning("Unknown Arch '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
VtfObj.ArchList = self.__Token.upper()
|
|
|
|
if not self.__IsToken( "]"):
|
|
raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
|
|
|
|
if self.__IsKeyword("IA32_RST_BIN"):
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Reset file", self.FileName, self.CurrentLineNumber)
|
|
|
|
VtfObj.ResetBin = self.__Token
|
|
if VtfObj.ResetBin.replace('$(WORKSPACE)', '').find('$') == -1:
|
|
#check for file path
|
|
ErrorCode, ErrorInfo = PathClass(NormPath(VtfObj.ResetBin), GenFdsGlobalVariable.WorkSpaceDir).Validate()
|
|
if ErrorCode != 0:
|
|
EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
|
|
|
|
while self.__GetComponentStatement(VtfObj):
|
|
pass
|
|
|
|
self.Profile.VtfList.append(VtfObj)
|
|
return True
|
|
|
|
## __GetComponentStatement() method
|
|
#
|
|
# Get components in VTF
|
|
#
|
|
# @param self The object pointer
|
|
# @param VtfObj for whom component is got
|
|
# @retval True Successfully find a component
|
|
# @retval False Not able to find a component
|
|
#
|
|
def __GetComponentStatement(self, VtfObj):
|
|
|
|
if not self.__IsKeyword("COMP_NAME"):
|
|
return False
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextWord():
|
|
raise Warning("expected Component Name", self.FileName, self.CurrentLineNumber)
|
|
|
|
CompStatementObj = ComponentStatement.ComponentStatement()
|
|
CompStatementObj.CompName = self.__Token
|
|
|
|
if not self.__IsKeyword("COMP_LOC"):
|
|
raise Warning("expected COMP_LOC", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
CompStatementObj.CompLoc = ""
|
|
if self.__GetNextWord():
|
|
CompStatementObj.CompLoc = self.__Token
|
|
if self.__IsToken('|'):
|
|
if not self.__GetNextWord():
|
|
raise Warning("Expected Region Name", self.FileName, self.CurrentLineNumber)
|
|
|
|
if self.__Token not in ("F", "N", "S"): #, "H", "L", "PH", "PL"): not support
|
|
raise Warning("Unknown location type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
|
|
CompStatementObj.FilePos = self.__Token
|
|
else:
|
|
self.CurrentLineNumber += 1
|
|
self.CurrentOffsetWithinLine = 0
|
|
|
|
if not self.__IsKeyword("COMP_TYPE"):
|
|
raise Warning("expected COMP_TYPE", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Component type", self.FileName, self.CurrentLineNumber)
|
|
if self.__Token not in ("FIT", "PAL_B", "PAL_A", "OEM"):
|
|
if not self.__Token.startswith("0x") or len(self.__Token) < 3 or len(self.__Token) > 4 or \
|
|
not self.__HexDigit(self.__Token[2]) or not self.__HexDigit(self.__Token[-1]):
|
|
raise Warning("Unknown location type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
CompStatementObj.CompType = self.__Token
|
|
|
|
if not self.__IsKeyword("COMP_VER"):
|
|
raise Warning("expected COMP_VER", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Component version", self.FileName, self.CurrentLineNumber)
|
|
|
|
Pattern = re.compile('-$|[0-9a-fA-F]{1,2}\.[0-9a-fA-F]{1,2}$', re.DOTALL)
|
|
if Pattern.match(self.__Token) == None:
|
|
raise Warning("Unknown version format '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
CompStatementObj.CompVer = self.__Token
|
|
|
|
if not self.__IsKeyword("COMP_CS"):
|
|
raise Warning("expected COMP_CS", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Component CS", self.FileName, self.CurrentLineNumber)
|
|
if self.__Token not in ("1", "0"):
|
|
raise Warning("Unknown Component CS '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
CompStatementObj.CompCs = self.__Token
|
|
|
|
|
|
if not self.__IsKeyword("COMP_BIN"):
|
|
raise Warning("expected COMP_BIN", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Component file", self.FileName, self.CurrentLineNumber)
|
|
|
|
CompStatementObj.CompBin = self.__Token
|
|
if CompStatementObj.CompBin != '-' and CompStatementObj.CompBin.replace('$(WORKSPACE)', '').find('$') == -1:
|
|
#check for file path
|
|
ErrorCode, ErrorInfo = PathClass(NormPath(CompStatementObj.CompBin), GenFdsGlobalVariable.WorkSpaceDir).Validate()
|
|
if ErrorCode != 0:
|
|
EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
|
|
|
|
if not self.__IsKeyword("COMP_SYM"):
|
|
raise Warning("expected COMP_SYM", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__GetNextToken():
|
|
raise Warning("expected Component symbol file", self.FileName, self.CurrentLineNumber)
|
|
|
|
CompStatementObj.CompSym = self.__Token
|
|
if CompStatementObj.CompSym != '-' and CompStatementObj.CompSym.replace('$(WORKSPACE)', '').find('$') == -1:
|
|
#check for file path
|
|
ErrorCode, ErrorInfo = PathClass(NormPath(CompStatementObj.CompSym), GenFdsGlobalVariable.WorkSpaceDir).Validate()
|
|
if ErrorCode != 0:
|
|
EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
|
|
|
|
if not self.__IsKeyword("COMP_SIZE"):
|
|
raise Warning("expected COMP_SIZE", self.FileName, self.CurrentLineNumber)
|
|
|
|
if not self.__IsToken("="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
|
|
if self.__IsToken("-"):
|
|
CompStatementObj.CompSize = self.__Token
|
|
elif self.__GetNextDecimalNumber():
|
|
CompStatementObj.CompSize = self.__Token
|
|
elif self.__GetNextHexNumber():
|
|
CompStatementObj.CompSize = self.__Token
|
|
else:
|
|
raise Warning("Unknown size '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
|
|
|
|
VtfObj.ComponentStatementList.append(CompStatementObj)
|
|
return True
|
|
|
|
## __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("[") 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( "]"):
|
|
raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
|
|
|
|
OptRomObj = OptionRom.OPTIONROM()
|
|
OptRomObj.DriverName = 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.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('$(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)
|
|
|
|
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)
|
|
|
|
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 = OptionRom.OverrideAttribs()
|
|
while True:
|
|
if self.__IsKeyword( "PCI_VENDOR_ID"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
|
|
if not self.__GetNextHexNumber():
|
|
raise Warning("expected Hex device id", self.FileName, self.CurrentLineNumber)
|
|
|
|
Overrides.PciDeviceId = self.__Token
|
|
continue
|
|
|
|
if self.__IsKeyword( "PCI_REVISION"):
|
|
if not self.__IsToken( "="):
|
|
raise Warning("expected '='", 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( "="):
|
|
raise Warning("expected '='", 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( "}"):
|
|
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.OptRomFileStatement()
|
|
|
|
if not self.__IsKeyword("EFI") and not self.__IsKeyword("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('$(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.keys():
|
|
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 != 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 != None and CapsuleDataObj.FvName.upper() not in RefFvList:
|
|
RefFvList.append (CapsuleDataObj.FvName.upper())
|
|
elif hasattr(CapsuleDataObj, 'FdName') and CapsuleDataObj.FdName != None and CapsuleDataObj.FdName.upper() not in RefFdList:
|
|
RefFdList.append (CapsuleDataObj.FdName.upper())
|
|
elif CapsuleDataObj.Ffs != None:
|
|
if isinstance(CapsuleDataObj.Ffs, FfsFileStatement.FileStatement):
|
|
if CapsuleDataObj.Ffs.FvName != None and CapsuleDataObj.Ffs.FvName.upper() not in RefFvList:
|
|
RefFvList.append(CapsuleDataObj.Ffs.FvName.upper())
|
|
elif CapsuleDataObj.Ffs.FdName != 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.keys():
|
|
FdObj = self.Profile.FdDict[FdName.upper()]
|
|
for elementRegion in FdObj.RegionList:
|
|
if elementRegion.RegionType == 'FV':
|
|
for elementRegionData in elementRegion.RegionDataList:
|
|
if elementRegionData.endswith(".fv"):
|
|
continue
|
|
if elementRegionData != 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, FfsFileStatement.FileStatement):
|
|
if FfsObj.FvName != None and FfsObj.FvName.upper() not in RefFvList:
|
|
RefFvList.append(FfsObj.FvName.upper())
|
|
elif FfsObj.FdName != 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 = []
|
|
SectionStack.extend(FfsFile.SectionList)
|
|
while SectionStack != []:
|
|
SectionObj = SectionStack.pop()
|
|
if isinstance(SectionObj, FvImageSection.FvImageSection):
|
|
if SectionObj.FvName != None and SectionObj.FvName.upper() not in FvList:
|
|
FvList.append(SectionObj.FvName.upper())
|
|
if SectionObj.Fv != None and SectionObj.Fv.UiFvName != 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.CompressSection) or isinstance(SectionObj, GuidSection.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.keys():
|
|
LogStr = "\nCycle Reference Checking for FV: %s\n" % FvName
|
|
RefFvStack = []
|
|
RefFvStack.append(FvName)
|
|
FdAnalyzedList = []
|
|
|
|
Index = 0
|
|
while RefFvStack != [] and Index < MaxLength:
|
|
Index = Index + 1
|
|
FvNameFromStack = RefFvStack.pop()
|
|
if FvNameFromStack.upper() in self.Profile.FvDict.keys():
|
|
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.append(FvNameInFd)
|
|
|
|
if FvName in RefFvStack or FvNameFromStack in RefFvStack:
|
|
EdkLogger.info(LogStr)
|
|
return True
|
|
FdAnalyzedList.append(RefFdName)
|
|
|
|
for RefFvName in RefFvList:
|
|
LogStr += "FV %s contains FV %s\n" % (FvNameFromStack, RefFvName)
|
|
if RefFvName not in RefFvStack:
|
|
RefFvStack.append(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.keys():
|
|
#
|
|
# Capsule image to be checked.
|
|
#
|
|
LogStr = "\n\n\nCycle Reference Checking for Capsule: %s\n" % CapName
|
|
RefCapStack = []
|
|
RefCapStack.append(CapName)
|
|
FdAnalyzedList = []
|
|
FvAnalyzedList = []
|
|
|
|
Index = 0
|
|
while RefCapStack != [] and Index < MaxLength:
|
|
Index = Index + 1
|
|
CapNameFromStack = RefCapStack.pop()
|
|
if CapNameFromStack.upper() in self.Profile.CapsuleDict.keys():
|
|
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)
|
|
CapInFdList = self.__GetCapInFd(RefFdName)
|
|
if CapInFdList != []:
|
|
for CapNameInFd in CapInFdList:
|
|
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
|
|
|
|
FvInFdList = self.__GetFvInFd(RefFdName)
|
|
if FvInFdList != []:
|
|
for FvNameInFd in FvInFdList:
|
|
LogStr += "FD %s contains FV %s\n" % (RefFdName,FvNameInFd)
|
|
if FvNameInFd not in RefFvList:
|
|
RefFvList.append(FvNameInFd)
|
|
|
|
FdAnalyzedList.append(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.keys():
|
|
FvObj = self.Profile.FvDict[RefFvName.upper()]
|
|
else:
|
|
continue
|
|
self.__GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
|
|
FvAnalyzedList.append(RefFvName)
|
|
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
try:
|
|
test_file = sys.argv[1]
|
|
except IndexError, v:
|
|
print "Usage: %s filename" % sys.argv[0]
|
|
sys.exit(1)
|
|
|
|
parser = FdfParser(test_file)
|
|
try:
|
|
parser.ParseFile()
|
|
parser.CycleReferenceCheck()
|
|
except Warning, X:
|
|
print str(X)
|
|
else:
|
|
print "Success!"
|
|
|