mirror of https://github.com/acidanthera/audk.git
4666 lines
193 KiB
Python
4666 lines
193 KiB
Python
## @file
|
|
# parse FDF file
|
|
#
|
|
# Copyright (c) 2007 - 2015, 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 re
|
|
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
|
|
|
|
## __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"):
|
|
if 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."):
|
|
raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
|
|
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)
|
|
|
|
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)
|
|
|
|
## __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."):
|
|
if 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 or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
|
|
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)
|
|
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)
|
|
|
|
## __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 not S.startswith("[FMPPAYLOAD."):
|
|
if not S.startswith("[CAPSULE.") and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
|
|
raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [FmpPayload.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
|
|
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."):
|
|
if not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
|
|
raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
|
|
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"):
|
|
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
|
|
AnyFileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(AnyFileName)
|
|
if not os.path.exists(AnyFileName):
|
|
raise Warning("File %s not exists"%AnyFileName, self.FileName, self.CurrentLineNumber)
|
|
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."):
|
|
if not S.startswith("[OPTIONROM."):
|
|
raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
|
|
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."):
|
|
if not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
|
|
raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
|
|
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."):
|
|
raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
|
|
|
|
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!"
|
|
|