• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1## @file
2# parse FDF file
3#
4#  Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
5#  Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
6#
7#  This program and the accompanying materials
8#  are licensed and made available under the terms and conditions of the BSD License
9#  which accompanies this distribution.  The full text of the license may be found at
10#  http://opensource.org/licenses/bsd-license.php
11#
12#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14#
15
16##
17# Import Modules
18#
19import re
20
21import Fd
22import Region
23import Fv
24import AprioriSection
25import FfsInfStatement
26import FfsFileStatement
27import VerSection
28import UiSection
29import FvImageSection
30import DataSection
31import DepexSection
32import CompressSection
33import GuidSection
34import Capsule
35import CapsuleData
36import Rule
37import RuleComplexFile
38import RuleSimpleFile
39import EfiSection
40import Vtf
41import ComponentStatement
42import OptionRom
43import OptRomInfStatement
44import OptRomFileStatement
45
46from GenFdsGlobalVariable import GenFdsGlobalVariable
47from Common.BuildToolError import *
48from Common import EdkLogger
49from Common.Misc import PathClass
50from Common.String import NormPath
51import Common.GlobalData as GlobalData
52from Common.Expression import *
53from Common import GlobalData
54from Common.String import ReplaceMacro
55import uuid
56from Common.Misc import tdict
57from Common.MultipleWorkspace import MultipleWorkspace as mws
58import Common.LongFilePathOs as os
59from Common.LongFilePathSupport import OpenLongFilePath as open
60from Capsule import EFI_CERT_TYPE_PKCS7_GUID
61from Capsule import EFI_CERT_TYPE_RSA2048_SHA256_GUID
62
63##define T_CHAR_SPACE                ' '
64##define T_CHAR_NULL                 '\0'
65##define T_CHAR_CR                   '\r'
66##define T_CHAR_TAB                  '\t'
67##define T_CHAR_LF                   '\n'
68##define T_CHAR_SLASH                '/'
69##define T_CHAR_BACKSLASH            '\\'
70##define T_CHAR_DOUBLE_QUOTE         '\"'
71##define T_CHAR_SINGLE_QUOTE         '\''
72##define T_CHAR_STAR                 '*'
73##define T_CHAR_HASH                 '#'
74
75(T_CHAR_SPACE, T_CHAR_NULL, T_CHAR_CR, T_CHAR_TAB, T_CHAR_LF, T_CHAR_SLASH, \
76T_CHAR_BACKSLASH, T_CHAR_DOUBLE_QUOTE, T_CHAR_SINGLE_QUOTE, T_CHAR_STAR, T_CHAR_HASH) = \
77(' ', '\0', '\r', '\t', '\n', '/', '\\', '\"', '\'', '*', '#')
78
79SEPERATOR_TUPLE = ('=', '|', ',', '{', '}')
80
81RegionSizePattern = re.compile("\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*")
82RegionSizeGuidPattern = re.compile("\s*(?P<base>\w+\.\w+)\s*\|\s*(?P<size>\w+\.\w+)\s*")
83RegionOffsetPcdPattern = re.compile("\s*(?P<base>\w+\.\w+)\s*$")
84ShortcutPcdPattern = re.compile("\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*")
85
86AllIncludeFileList = []
87
88# Get the closest parent
89def GetParentAtLine (Line):
90    for Profile in AllIncludeFileList:
91        if Profile.IsLineInFile(Line):
92            return Profile
93    return None
94
95# Check include loop
96def IsValidInclude (File, Line):
97    for Profile in AllIncludeFileList:
98        if Profile.IsLineInFile(Line) and Profile.FileName == File:
99            return False
100
101    return True
102
103def GetRealFileLine (File, Line):
104
105    InsertedLines = 0
106    for Profile in AllIncludeFileList:
107        if Profile.IsLineInFile(Line):
108            return Profile.GetLineInFile(Line)
109        elif Line >= Profile.InsertStartLineNumber and Profile.Level == 1:
110            InsertedLines += Profile.GetTotalLines()
111
112    return (File, Line - InsertedLines)
113
114## The exception class that used to report error messages when parsing FDF
115#
116# Currently the "ToolName" is set to be "FDF Parser".
117#
118class Warning (Exception):
119    ## The constructor
120    #
121    #   @param  self        The object pointer
122    #   @param  Str         The message to record
123    #   @param  File        The FDF name
124    #   @param  Line        The Line number that error occurs
125    #
126    def __init__(self, Str, File = None, Line = None):
127
128        FileLineTuple = GetRealFileLine(File, Line)
129        self.FileName = FileLineTuple[0]
130        self.LineNumber = FileLineTuple[1]
131        self.OriginalLineNumber = Line
132        self.Message = Str
133        self.ToolName = 'FdfParser'
134
135    def __str__(self):
136        return self.Message
137
138## The MACRO class that used to record macro value data when parsing include file
139#
140#
141class MacroProfile :
142    ## The constructor
143    #
144    #   @param  self        The object pointer
145    #   @param  FileName    The file that to be parsed
146    #
147    def __init__(self, FileName, Line):
148        self.FileName = FileName
149        self.DefinedAtLine  = Line
150        self.MacroName = None
151        self.MacroValue = None
152
153## The Include file content class that used to record file data when parsing include file
154#
155# May raise Exception when opening file.
156#
157class IncludeFileProfile :
158    ## The constructor
159    #
160    #   @param  self        The object pointer
161    #   @param  FileName    The file that to be parsed
162    #
163    def __init__(self, FileName):
164        self.FileName = FileName
165        self.FileLinesList = []
166        try:
167            fsock = open(FileName, "rb", 0)
168            try:
169                self.FileLinesList = fsock.readlines()
170            finally:
171                fsock.close()
172
173        except:
174            EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
175
176        self.InsertStartLineNumber = None
177        self.InsertAdjust = 0
178        self.IncludeFileList = []
179        self.Level = 1 # first level include file
180
181    def GetTotalLines(self):
182        TotalLines = self.InsertAdjust + len(self.FileLinesList)
183
184        for Profile in self.IncludeFileList:
185            TotalLines += Profile.GetTotalLines()
186
187        return TotalLines
188
189    def IsLineInFile(self, Line):
190        if Line >= self.InsertStartLineNumber and Line < self.InsertStartLineNumber + self.GetTotalLines():
191            return True
192
193        return False
194
195    def GetLineInFile(self, Line):
196        if not self.IsLineInFile (Line):
197            return (self.FileName, -1)
198
199        InsertedLines = self.InsertStartLineNumber
200
201        for Profile in self.IncludeFileList:
202            if Profile.IsLineInFile(Line):
203                return Profile.GetLineInFile(Line)
204            elif Line >= Profile.InsertStartLineNumber:
205                InsertedLines += Profile.GetTotalLines()
206
207        return (self.FileName, Line - InsertedLines + 1)
208
209
210
211## The FDF content class that used to record file data when parsing FDF
212#
213# May raise Exception when opening file.
214#
215class FileProfile :
216    ## The constructor
217    #
218    #   @param  self        The object pointer
219    #   @param  FileName    The file that to be parsed
220    #
221    def __init__(self, FileName):
222        self.FileLinesList = []
223        try:
224            fsock = open(FileName, "rb", 0)
225            try:
226                self.FileLinesList = fsock.readlines()
227            finally:
228                fsock.close()
229
230        except:
231            EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
232
233
234        self.PcdDict = {}
235        self.InfList = []
236        self.InfDict = {'ArchTBD':[]}
237        # ECC will use this Dict and List information
238        self.PcdFileLineDict = {}
239        self.InfFileLineList = []
240
241        self.FdDict = {}
242        self.FdNameNotSet = False
243        self.FvDict = {}
244        self.CapsuleDict = {}
245        self.VtfList = []
246        self.RuleDict = {}
247        self.OptRomDict = {}
248        self.FmpPayloadDict = {}
249
250## The syntax parser for FDF
251#
252# PreprocessFile method should be called prior to ParseFile
253# CycleReferenceCheck method can detect cycles in FDF contents
254#
255# GetNext*** procedures mean these procedures will get next token first, then make judgement.
256# Get*** procedures mean these procedures will make judgement on current token only.
257#
258class FdfParser:
259    ## The constructor
260    #
261    #   @param  self        The object pointer
262    #   @param  FileName    The file that to be parsed
263    #
264    def __init__(self, FileName):
265        self.Profile = FileProfile(FileName)
266        self.FileName = FileName
267        self.CurrentLineNumber = 1
268        self.CurrentOffsetWithinLine = 0
269        self.CurrentFdName = None
270        self.CurrentFvName = None
271        self.__Token = ""
272        self.__SkippedChars = ""
273        GlobalData.gFdfParser = self
274
275        # Used to section info
276        self.__CurSection = []
277        # Key: [section name, UI name, arch]
278        # Value: {MACRO_NAME : MACRO_VALUE}
279        self.__MacroDict = tdict(True, 3)
280        self.__PcdDict = {}
281
282        self.__WipeOffArea = []
283        if GenFdsGlobalVariable.WorkSpaceDir == '':
284            GenFdsGlobalVariable.WorkSpaceDir = os.getenv("WORKSPACE")
285
286    ## __IsWhiteSpace() method
287    #
288    #   Whether char at current FileBufferPos is whitespace
289    #
290    #   @param  self        The object pointer
291    #   @param  Char        The char to test
292    #   @retval True        The char is a kind of white space
293    #   @retval False       The char is NOT a kind of white space
294    #
295    def __IsWhiteSpace(self, Char):
296        if Char in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_SPACE, T_CHAR_TAB, T_CHAR_LF):
297            return True
298        else:
299            return False
300
301    ## __SkipWhiteSpace() method
302    #
303    #   Skip white spaces from current char, return number of chars skipped
304    #
305    #   @param  self        The object pointer
306    #   @retval Count       The number of chars skipped
307    #
308    def __SkipWhiteSpace(self):
309        Count = 0
310        while not self.__EndOfFile():
311            Count += 1
312            if self.__CurrentChar() in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_LF, T_CHAR_SPACE, T_CHAR_TAB):
313                self.__SkippedChars += str(self.__CurrentChar())
314                self.__GetOneChar()
315
316            else:
317                Count = Count - 1
318                return Count
319
320    ## __EndOfFile() method
321    #
322    #   Judge current buffer pos is at file end
323    #
324    #   @param  self        The object pointer
325    #   @retval True        Current File buffer position is at file end
326    #   @retval False       Current File buffer position is NOT at file end
327    #
328    def __EndOfFile(self):
329        NumberOfLines = len(self.Profile.FileLinesList)
330        SizeOfLastLine = len(self.Profile.FileLinesList[-1])
331        if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1:
332            return True
333        elif self.CurrentLineNumber > NumberOfLines:
334            return True
335        else:
336            return False
337
338    ## __EndOfLine() method
339    #
340    #   Judge current buffer pos is at line end
341    #
342    #   @param  self        The object pointer
343    #   @retval True        Current File buffer position is at line end
344    #   @retval False       Current File buffer position is NOT at line end
345    #
346    def __EndOfLine(self):
347        if self.CurrentLineNumber > len(self.Profile.FileLinesList):
348            return True
349        SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
350        if self.CurrentOffsetWithinLine >= SizeOfCurrentLine:
351            return True
352        else:
353            return False
354
355    ## Rewind() method
356    #
357    #   Reset file data buffer to the initial state
358    #
359    #   @param  self        The object pointer
360    #   @param  DestLine    Optional new destination line number.
361    #   @param  DestOffset  Optional new destination offset.
362    #
363    def Rewind(self, DestLine = 1, DestOffset = 0):
364        self.CurrentLineNumber = DestLine
365        self.CurrentOffsetWithinLine = DestOffset
366
367    ## __UndoOneChar() method
368    #
369    #   Go back one char in the file buffer
370    #
371    #   @param  self        The object pointer
372    #   @retval True        Successfully go back one char
373    #   @retval False       Not able to go back one char as file beginning reached
374    #
375    def __UndoOneChar(self):
376
377        if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0:
378            return False
379        elif self.CurrentOffsetWithinLine == 0:
380            self.CurrentLineNumber -= 1
381            self.CurrentOffsetWithinLine = len(self.__CurrentLine()) - 1
382        else:
383            self.CurrentOffsetWithinLine -= 1
384        return True
385
386    ## __GetOneChar() method
387    #
388    #   Move forward one char in the file buffer
389    #
390    #   @param  self        The object pointer
391    #
392    def __GetOneChar(self):
393        if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
394            self.CurrentLineNumber += 1
395            self.CurrentOffsetWithinLine = 0
396        else:
397            self.CurrentOffsetWithinLine += 1
398
399    ## __CurrentChar() method
400    #
401    #   Get the char pointed to by the file buffer pointer
402    #
403    #   @param  self        The object pointer
404    #   @retval Char        Current char
405    #
406    def __CurrentChar(self):
407        return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine]
408
409    ## __NextChar() method
410    #
411    #   Get the one char pass the char pointed to by the file buffer pointer
412    #
413    #   @param  self        The object pointer
414    #   @retval Char        Next char
415    #
416    def __NextChar(self):
417        if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
418            return self.Profile.FileLinesList[self.CurrentLineNumber][0]
419        else:
420            return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1]
421
422    ## __SetCurrentCharValue() method
423    #
424    #   Modify the value of current char
425    #
426    #   @param  self        The object pointer
427    #   @param  Value       The new value of current char
428    #
429    def __SetCurrentCharValue(self, Value):
430        self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value
431
432    ## __CurrentLine() method
433    #
434    #   Get the list that contains current line contents
435    #
436    #   @param  self        The object pointer
437    #   @retval List        current line contents
438    #
439    def __CurrentLine(self):
440        return self.Profile.FileLinesList[self.CurrentLineNumber - 1]
441
442    def __StringToList(self):
443        self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList]
444        self.Profile.FileLinesList[-1].append(' ')
445
446    def __ReplaceFragment(self, StartPos, EndPos, Value = ' '):
447        if StartPos[0] == EndPos[0]:
448            Offset = StartPos[1]
449            while Offset <= EndPos[1]:
450                self.Profile.FileLinesList[StartPos[0]][Offset] = Value
451                Offset += 1
452            return
453
454        Offset = StartPos[1]
455        while self.Profile.FileLinesList[StartPos[0]][Offset] not in ('\r', '\n'):
456            self.Profile.FileLinesList[StartPos[0]][Offset] = Value
457            Offset += 1
458
459        Line = StartPos[0]
460        while Line < EndPos[0]:
461            Offset = 0
462            while self.Profile.FileLinesList[Line][Offset] not in ('\r', '\n'):
463                self.Profile.FileLinesList[Line][Offset] = Value
464                Offset += 1
465            Line += 1
466
467        Offset = 0
468        while Offset <= EndPos[1]:
469            self.Profile.FileLinesList[EndPos[0]][Offset] = Value
470            Offset += 1
471
472
473    def __GetMacroName(self):
474        if not self.__GetNextToken():
475            raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber)
476        MacroName = self.__Token
477        NotFlag = False
478        if MacroName.startswith('!'):
479            NotFlag = True
480            MacroName = MacroName[1:].strip()
481
482        if not MacroName.startswith('$(') or not MacroName.endswith(')'):
483            raise Warning("Macro name expected(Please use '$(%(Token)s)' if '%(Token)s' is a macro.)" % {"Token" : MacroName},
484                          self.FileName, self.CurrentLineNumber)
485        MacroName = MacroName[2:-1]
486        return MacroName, NotFlag
487
488    def __SetMacroValue(self, Macro, Value):
489        if not self.__CurSection:
490            return
491
492        MacroDict = {}
493        if not self.__MacroDict[self.__CurSection[0], self.__CurSection[1], self.__CurSection[2]]:
494            self.__MacroDict[self.__CurSection[0], self.__CurSection[1], self.__CurSection[2]] = MacroDict
495        else:
496            MacroDict = self.__MacroDict[self.__CurSection[0], self.__CurSection[1], self.__CurSection[2]]
497        MacroDict[Macro] = Value
498
499    def __GetMacroValue(self, Macro):
500        # Highest priority
501        if Macro in GlobalData.gCommandLineDefines:
502            return GlobalData.gCommandLineDefines[Macro]
503        if Macro in GlobalData.gGlobalDefines:
504            return GlobalData.gGlobalDefines[Macro]
505
506        if self.__CurSection:
507            MacroDict = self.__MacroDict[
508                        self.__CurSection[0],
509                        self.__CurSection[1],
510                        self.__CurSection[2]
511            ]
512            if MacroDict and Macro in MacroDict:
513                return MacroDict[Macro]
514
515        # Lowest priority
516        if Macro in GlobalData.gPlatformDefines:
517            return GlobalData.gPlatformDefines[Macro]
518        return None
519
520    def __SectionHeaderParser(self, Section):
521        # [Defines]
522        # [FD.UiName]: use dummy instead if UI name is optional
523        # [FV.UiName]
524        # [Capsule.UiName]
525        # [Rule]: don't take rule section into account, macro is not allowed in this section
526        # [VTF.arch.UiName, arch]
527        # [OptionRom.DriverName]
528        self.__CurSection = []
529        Section = Section.strip()[1:-1].upper().replace(' ', '').strip('.')
530        ItemList = Section.split('.')
531        Item = ItemList[0]
532        if Item == '' or Item == 'RULE':
533            return
534
535        if Item == 'DEFINES':
536            self.__CurSection = ['COMMON', 'COMMON', 'COMMON']
537        elif Item == 'VTF' and len(ItemList) == 3:
538            UiName = ItemList[2]
539            Pos = UiName.find(',')
540            if Pos != -1:
541                UiName = UiName[:Pos]
542            self.__CurSection = ['VTF', UiName, ItemList[1]]
543        elif len(ItemList) > 1:
544            self.__CurSection = [ItemList[0], ItemList[1], 'COMMON']
545        elif len(ItemList) > 0:
546            self.__CurSection = [ItemList[0], 'DUMMY', 'COMMON']
547
548    ## PreprocessFile() method
549    #
550    #   Preprocess file contents, replace comments with spaces.
551    #   In the end, rewind the file buffer pointer to the beginning
552    #   BUGBUG: No !include statement processing contained in this procedure
553    #   !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1]
554    #
555    #   @param  self        The object pointer
556    #
557    def PreprocessFile(self):
558
559        self.Rewind()
560        InComment = False
561        DoubleSlashComment = False
562        HashComment = False
563        # HashComment in quoted string " " is ignored.
564        InString = False
565
566        while not self.__EndOfFile():
567
568            if self.__CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment:
569                InString = not InString
570            # meet new line, then no longer in a comment for // and '#'
571            if self.__CurrentChar() == T_CHAR_LF:
572                self.CurrentLineNumber += 1
573                self.CurrentOffsetWithinLine = 0
574                if InComment and DoubleSlashComment:
575                    InComment = False
576                    DoubleSlashComment = False
577                if InComment and HashComment:
578                    InComment = False
579                    HashComment = False
580            # check for */ comment end
581            elif InComment and not DoubleSlashComment and not HashComment and self.__CurrentChar() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH:
582                self.__SetCurrentCharValue(T_CHAR_SPACE)
583                self.__GetOneChar()
584                self.__SetCurrentCharValue(T_CHAR_SPACE)
585                self.__GetOneChar()
586                InComment = False
587            # set comments to spaces
588            elif InComment:
589                self.__SetCurrentCharValue(T_CHAR_SPACE)
590                self.__GetOneChar()
591            # check for // comment
592            elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH and not self.__EndOfLine():
593                InComment = True
594                DoubleSlashComment = True
595            # check for '#' comment
596            elif self.__CurrentChar() == T_CHAR_HASH and not self.__EndOfLine() and not InString:
597                InComment = True
598                HashComment = True
599            # check for /* comment start
600            elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR:
601                self.__SetCurrentCharValue( T_CHAR_SPACE)
602                self.__GetOneChar()
603                self.__SetCurrentCharValue( T_CHAR_SPACE)
604                self.__GetOneChar()
605                InComment = True
606            else:
607                self.__GetOneChar()
608
609        # restore from ListOfList to ListOfString
610        self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
611        self.Rewind()
612
613    ## PreprocessIncludeFile() method
614    #
615    #   Preprocess file contents, replace !include statements with file contents.
616    #   In the end, rewind the file buffer pointer to the beginning
617    #
618    #   @param  self        The object pointer
619    #
620    def PreprocessIncludeFile(self):
621	    # nested include support
622        Processed = False
623        while self.__GetNextToken():
624
625            if self.__Token == '!include':
626                Processed = True
627                IncludeLine = self.CurrentLineNumber
628                IncludeOffset = self.CurrentOffsetWithinLine - len('!include')
629                if not self.__GetNextToken():
630                    raise Warning("expected include file name", self.FileName, self.CurrentLineNumber)
631                IncFileName = self.__Token
632                __IncludeMacros = {}
633                for Macro in ['WORKSPACE', 'ECP_SOURCE', 'EFI_SOURCE', 'EDK_SOURCE']:
634                    MacroVal = self.__GetMacroValue(Macro)
635                    if MacroVal:
636                        __IncludeMacros[Macro] = MacroVal
637
638                try:
639                    IncludedFile = NormPath(ReplaceMacro(IncFileName, __IncludeMacros, RaiseError=True))
640                except:
641                    raise Warning("only these system environment variables are permitted to start the path of the included file: "
642                                  "$(WORKSPACE), $(ECP_SOURCE), $(EFI_SOURCE), $(EDK_SOURCE)",
643                                  self.FileName, self.CurrentLineNumber)
644                #
645                # First search the include file under the same directory as FDF file
646                #
647                IncludedFile1 = PathClass(IncludedFile, os.path.dirname(self.FileName))
648                ErrorCode = IncludedFile1.Validate()[0]
649                if ErrorCode != 0:
650                    #
651                    # Then search the include file under the same directory as DSC file
652                    #
653                    PlatformDir = ''
654                    if GenFdsGlobalVariable.ActivePlatform:
655                        PlatformDir = GenFdsGlobalVariable.ActivePlatform.Dir
656                    elif GlobalData.gActivePlatform:
657                        PlatformDir = GlobalData.gActivePlatform.MetaFile.Dir
658                    IncludedFile1 = PathClass(IncludedFile, PlatformDir)
659                    ErrorCode = IncludedFile1.Validate()[0]
660                    if ErrorCode != 0:
661                        #
662                        # Also search file under the WORKSPACE directory
663                        #
664                        IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
665                        ErrorCode = IncludedFile1.Validate()[0]
666                        if ErrorCode != 0:
667                            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),
668                                          self.FileName, self.CurrentLineNumber)
669
670                if not IsValidInclude (IncludedFile1.Path, self.CurrentLineNumber):
671                    raise Warning("The include file {0} is causing a include loop.\n".format (IncludedFile1.Path), self.FileName, self.CurrentLineNumber)
672
673                IncFileProfile = IncludeFileProfile(IncludedFile1.Path)
674
675                CurrentLine = self.CurrentLineNumber
676                CurrentOffset = self.CurrentOffsetWithinLine
677                # list index of the insertion, note that line number is 'CurrentLine + 1'
678                InsertAtLine = CurrentLine
679                ParentProfile = GetParentAtLine (CurrentLine)
680                if ParentProfile != None:
681                    ParentProfile.IncludeFileList.insert(0, IncFileProfile)
682                    IncFileProfile.Level = ParentProfile.Level + 1
683                IncFileProfile.InsertStartLineNumber = InsertAtLine + 1
684                # deal with remaining portions after "!include filename", if exists.
685                if self.__GetNextToken():
686                    if self.CurrentLineNumber == CurrentLine:
687                        RemainingLine = self.__CurrentLine()[CurrentOffset:]
688                        self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine)
689                        IncFileProfile.InsertAdjust += 1
690                        self.CurrentLineNumber += 1
691                        self.CurrentOffsetWithinLine = 0
692
693                for Line in IncFileProfile.FileLinesList:
694                    self.Profile.FileLinesList.insert(InsertAtLine, Line)
695                    self.CurrentLineNumber += 1
696                    InsertAtLine += 1
697
698                # reversely sorted to better determine error in file
699                AllIncludeFileList.insert(0, IncFileProfile)
700
701                # comment out the processed include file statement
702                TempList = list(self.Profile.FileLinesList[IncludeLine - 1])
703                TempList.insert(IncludeOffset, '#')
704                self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList)
705            if Processed: # Nested and back-to-back support
706                self.Rewind(DestLine = IncFileProfile.InsertStartLineNumber - 1)
707                Processed = False
708        # Preprocess done.
709        self.Rewind()
710
711    def __GetIfListCurrentItemStat(self, IfList):
712        if len(IfList) == 0:
713            return True
714
715        for Item in IfList:
716            if Item[1] == False:
717                return False
718
719        return True
720
721    ## PreprocessConditionalStatement() method
722    #
723    #   Preprocess conditional statement.
724    #   In the end, rewind the file buffer pointer to the beginning
725    #
726    #   @param  self        The object pointer
727    #
728    def PreprocessConditionalStatement(self):
729        # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined]
730        IfList = []
731        RegionLayoutLine = 0
732        ReplacedLine = -1
733        while self.__GetNextToken():
734            # Determine section name and the location dependent macro
735            if self.__GetIfListCurrentItemStat(IfList):
736                if self.__Token.startswith('['):
737                    Header = self.__Token
738                    if not self.__Token.endswith(']'):
739                        self.__SkipToToken(']')
740                        Header += self.__SkippedChars
741                    if Header.find('$(') != -1:
742                        raise Warning("macro cannot be used in section header", self.FileName, self.CurrentLineNumber)
743                    self.__SectionHeaderParser(Header)
744                    continue
745                # Replace macros except in RULE section or out of section
746                elif self.__CurSection and ReplacedLine != self.CurrentLineNumber:
747                    ReplacedLine = self.CurrentLineNumber
748                    self.__UndoToken()
749                    CurLine = self.Profile.FileLinesList[ReplacedLine - 1]
750                    PreIndex = 0
751                    StartPos = CurLine.find('$(', PreIndex)
752                    EndPos = CurLine.find(')', StartPos+2)
753                    while StartPos != -1 and EndPos != -1 and self.__Token not in ['!ifdef', '!ifndef', '!if', '!elseif']:
754                        MacroName = CurLine[StartPos+2 : EndPos]
755                        MacorValue = self.__GetMacroValue(MacroName)
756                        if MacorValue != None:
757                            CurLine = CurLine.replace('$(' + MacroName + ')', MacorValue, 1)
758                            if MacorValue.find('$(') != -1:
759                                PreIndex = StartPos
760                            else:
761                                PreIndex = StartPos + len(MacorValue)
762                        else:
763                            PreIndex = EndPos + 1
764                        StartPos = CurLine.find('$(', PreIndex)
765                        EndPos = CurLine.find(')', StartPos+2)
766                    self.Profile.FileLinesList[ReplacedLine - 1] = CurLine
767                    continue
768
769            if self.__Token == 'DEFINE':
770                if self.__GetIfListCurrentItemStat(IfList):
771                    if not self.__CurSection:
772                        raise Warning("macro cannot be defined in Rule section or out of section", self.FileName, self.CurrentLineNumber)
773                    DefineLine = self.CurrentLineNumber - 1
774                    DefineOffset = self.CurrentOffsetWithinLine - len('DEFINE')
775                    if not self.__GetNextToken():
776                        raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber)
777                    Macro = self.__Token
778                    if not self.__IsToken( "="):
779                        raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
780
781                    Value = self.__GetExpression()
782                    self.__SetMacroValue(Macro, Value)
783                    self.__WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
784            elif self.__Token == 'SET':
785                if not self.__GetIfListCurrentItemStat(IfList):
786                    continue
787                SetLine = self.CurrentLineNumber - 1
788                SetOffset = self.CurrentOffsetWithinLine - len('SET')
789                PcdPair = self.__GetNextPcdName()
790                PcdName = "%s.%s" % (PcdPair[1], PcdPair[0])
791                if not self.__IsToken( "="):
792                    raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
793
794                Value = self.__GetExpression()
795                Value = self.__EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
796
797                self.__PcdDict[PcdName] = Value
798
799                self.Profile.PcdDict[PcdPair] = Value
800                FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
801                self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
802
803                self.__WipeOffArea.append(((SetLine, SetOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
804            elif self.__Token in ('!ifdef', '!ifndef', '!if'):
805                IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token))
806                IfList.append([IfStartPos, None, None])
807
808                CondLabel = self.__Token
809                Expression = self.__GetExpression()
810
811                if CondLabel == '!if':
812                    ConditionSatisfied = self.__EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
813                else:
814                    ConditionSatisfied = self.__EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'in')
815                    if CondLabel == '!ifndef':
816                        ConditionSatisfied = not ConditionSatisfied
817
818                BranchDetermined = ConditionSatisfied
819                IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined]
820                if ConditionSatisfied:
821                    self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
822            elif self.__Token in ('!elseif', '!else'):
823                ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token))
824                if len(IfList) <= 0:
825                    raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
826
827                if IfList[-1][1]:
828                    IfList[-1] = [ElseStartPos, False, True]
829                    self.__WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
830                else:
831                    self.__WipeOffArea.append((IfList[-1][0], ElseStartPos))
832                    IfList[-1] = [ElseStartPos, True, IfList[-1][2]]
833                    if self.__Token == '!elseif':
834                        Expression = self.__GetExpression()
835                        ConditionSatisfied = self.__EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
836                        IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]]
837
838                    if IfList[-1][1]:
839                        if IfList[-1][2]:
840                            IfList[-1][1] = False
841                        else:
842                            IfList[-1][2] = True
843                            self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
844            elif self.__Token == '!endif':
845                if len(IfList) <= 0:
846                    raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
847                if IfList[-1][1]:
848                    self.__WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
849                else:
850                    self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
851
852                IfList.pop()
853            elif not IfList:    # Don't use PCDs inside conditional directive
854                if self.CurrentLineNumber <= RegionLayoutLine:
855                    # Don't try the same line twice
856                    continue
857                SetPcd = ShortcutPcdPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
858                if SetPcd:
859                    self.__PcdDict[SetPcd.group('name')] = SetPcd.group('value')
860                    RegionLayoutLine = self.CurrentLineNumber
861                    continue
862                RegionSize = RegionSizePattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
863                if not RegionSize:
864                    RegionLayoutLine = self.CurrentLineNumber
865                    continue
866                RegionSizeGuid = RegionSizeGuidPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber])
867                if not RegionSizeGuid:
868                    RegionLayoutLine = self.CurrentLineNumber + 1
869                    continue
870                self.__PcdDict[RegionSizeGuid.group('base')] = RegionSize.group('base')
871                self.__PcdDict[RegionSizeGuid.group('size')] = RegionSize.group('size')
872                RegionLayoutLine = self.CurrentLineNumber + 1
873
874        if IfList:
875            raise Warning("Missing !endif", self.FileName, self.CurrentLineNumber)
876        self.Rewind()
877
878    def __CollectMacroPcd(self):
879        MacroDict = {}
880
881        # PCD macro
882        MacroDict.update(GlobalData.gPlatformPcds)
883        MacroDict.update(self.__PcdDict)
884
885        # Lowest priority
886        MacroDict.update(GlobalData.gPlatformDefines)
887
888        if self.__CurSection:
889            # Defines macro
890            ScopeMacro = self.__MacroDict['COMMON', 'COMMON', 'COMMON']
891            if ScopeMacro:
892                MacroDict.update(ScopeMacro)
893
894            # Section macro
895            ScopeMacro = self.__MacroDict[
896                        self.__CurSection[0],
897                        self.__CurSection[1],
898                        self.__CurSection[2]
899            ]
900            if ScopeMacro:
901                MacroDict.update(ScopeMacro)
902
903        MacroDict.update(GlobalData.gGlobalDefines)
904        MacroDict.update(GlobalData.gCommandLineDefines)
905        # Highest priority
906
907        return MacroDict
908
909    def __EvaluateConditional(self, Expression, Line, Op = None, Value = None):
910        FileLineTuple = GetRealFileLine(self.FileName, Line)
911        MacroPcdDict = self.__CollectMacroPcd()
912        if Op == 'eval':
913            try:
914                if Value:
915                    return ValueExpression(Expression, MacroPcdDict)(True)
916                else:
917                    return ValueExpression(Expression, MacroPcdDict)()
918            except WrnExpression, Excpt:
919                #
920                # Catch expression evaluation warning here. We need to report
921                # the precise number of line and return the evaluation result
922                #
923                EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
924                                File=self.FileName, ExtraData=self.__CurrentLine(),
925                                Line=Line)
926                return Excpt.result
927            except Exception, Excpt:
928                if hasattr(Excpt, 'Pcd'):
929                    if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
930                        Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
931                        raise Warning("Cannot use this PCD (%s) in an expression as"
932                                      " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
933                                      " of the DSC file (%s), and it is currently defined in this section:"
934                                      " %s, line #: %d." % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE'], Info[0], Info[1]),
935                                      *FileLineTuple)
936                    else:
937                        raise Warning("PCD (%s) is not defined in DSC file (%s)" % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE']),
938                                      *FileLineTuple)
939                else:
940                    raise Warning(str(Excpt), *FileLineTuple)
941        else:
942            if Expression.startswith('$(') and Expression[-1] == ')':
943                Expression = Expression[2:-1]
944            return Expression in MacroPcdDict
945
946    ## __IsToken() method
947    #
948    #   Check whether input string is found from current char position along
949    #   If found, the string value is put into self.__Token
950    #
951    #   @param  self        The object pointer
952    #   @param  String      The string to search
953    #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive
954    #   @retval True        Successfully find string, file buffer pointer moved forward
955    #   @retval False       Not able to find string, file buffer pointer not changed
956    #
957    def __IsToken(self, String, IgnoreCase = False):
958        self.__SkipWhiteSpace()
959
960        # Only consider the same line, no multi-line token allowed
961        StartPos = self.CurrentOffsetWithinLine
962        index = -1
963        if IgnoreCase:
964            index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper())
965        else:
966            index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String)
967        if index == 0:
968            self.CurrentOffsetWithinLine += len(String)
969            self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
970            return True
971        return False
972
973    ## __IsKeyword() method
974    #
975    #   Check whether input keyword is found from current char position along, whole word only!
976    #   If found, the string value is put into self.__Token
977    #
978    #   @param  self        The object pointer
979    #   @param  Keyword     The string to search
980    #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive
981    #   @retval True        Successfully find string, file buffer pointer moved forward
982    #   @retval False       Not able to find string, file buffer pointer not changed
983    #
984    def __IsKeyword(self, KeyWord, IgnoreCase = False):
985        self.__SkipWhiteSpace()
986
987        # Only consider the same line, no multi-line token allowed
988        StartPos = self.CurrentOffsetWithinLine
989        index = -1
990        if IgnoreCase:
991            index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(KeyWord.upper())
992        else:
993            index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(KeyWord)
994        if index == 0:
995            followingChar = self.__CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)]
996            if not str(followingChar).isspace() and followingChar not in SEPERATOR_TUPLE:
997                return False
998            self.CurrentOffsetWithinLine += len(KeyWord)
999            self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
1000            return True
1001        return False
1002
1003    def __GetExpression(self):
1004        Line = self.Profile.FileLinesList[self.CurrentLineNumber - 1]
1005        Index = len(Line) - 1
1006        while Line[Index] in ['\r', '\n']:
1007            Index -= 1
1008        ExpressionString = self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:Index+1]
1009        self.CurrentOffsetWithinLine += len(ExpressionString)
1010        ExpressionString = ExpressionString.strip()
1011        return ExpressionString
1012
1013    ## __GetNextWord() method
1014    #
1015    #   Get next C name from file lines
1016    #   If found, the string value is put into self.__Token
1017    #
1018    #   @param  self        The object pointer
1019    #   @retval True        Successfully find a C name string, file buffer pointer moved forward
1020    #   @retval False       Not able to find a C name string, file buffer pointer not changed
1021    #
1022    def __GetNextWord(self):
1023        self.__SkipWhiteSpace()
1024        if self.__EndOfFile():
1025            return False
1026
1027        TempChar = self.__CurrentChar()
1028        StartPos = self.CurrentOffsetWithinLine
1029        if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_':
1030            self.__GetOneChar()
1031            while not self.__EndOfLine():
1032                TempChar = self.__CurrentChar()
1033                if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
1034                or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-':
1035                    self.__GetOneChar()
1036
1037                else:
1038                    break
1039
1040            self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
1041            return True
1042
1043        return False
1044
1045    ## __GetNextToken() method
1046    #
1047    #   Get next token unit before a seperator
1048    #   If found, the string value is put into self.__Token
1049    #
1050    #   @param  self        The object pointer
1051    #   @retval True        Successfully find a token unit, file buffer pointer moved forward
1052    #   @retval False       Not able to find a token unit, file buffer pointer not changed
1053    #
1054    def __GetNextToken(self):
1055        # Skip leading spaces, if exist.
1056        self.__SkipWhiteSpace()
1057        if self.__EndOfFile():
1058            return False
1059        # Record the token start position, the position of the first non-space char.
1060        StartPos = self.CurrentOffsetWithinLine
1061        StartLine = self.CurrentLineNumber
1062        while StartLine == self.CurrentLineNumber:
1063            TempChar = self.__CurrentChar()
1064            # Try to find the end char that is not a space and not in seperator tuple.
1065            # That is, when we got a space or any char in the tuple, we got the end of token.
1066            if not str(TempChar).isspace() and TempChar not in SEPERATOR_TUPLE:
1067                self.__GetOneChar()
1068            # if we happen to meet a seperator as the first char, we must proceed to get it.
1069            # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
1070            elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE:
1071                self.__GetOneChar()
1072                break
1073            else:
1074                break
1075#        else:
1076#            return False
1077
1078        EndPos = self.CurrentOffsetWithinLine
1079        if self.CurrentLineNumber != StartLine:
1080            EndPos = len(self.Profile.FileLinesList[StartLine-1])
1081        self.__Token = self.Profile.FileLinesList[StartLine-1][StartPos : EndPos]
1082        if StartPos != self.CurrentOffsetWithinLine:
1083            return True
1084        else:
1085            return False
1086
1087    def __GetNextOp(self):
1088        # Skip leading spaces, if exist.
1089        self.__SkipWhiteSpace()
1090        if self.__EndOfFile():
1091            return False
1092        # Record the token start position, the position of the first non-space char.
1093        StartPos = self.CurrentOffsetWithinLine
1094        while not self.__EndOfLine():
1095            TempChar = self.__CurrentChar()
1096            # Try to find the end char that is not a space
1097            if not str(TempChar).isspace():
1098                self.__GetOneChar()
1099            else:
1100                break
1101        else:
1102            return False
1103
1104        if StartPos != self.CurrentOffsetWithinLine:
1105            self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
1106            return True
1107        else:
1108            return False
1109    ## __GetNextGuid() method
1110    #
1111    #   Get next token unit before a seperator
1112    #   If found, the GUID string is put into self.__Token
1113    #
1114    #   @param  self        The object pointer
1115    #   @retval True        Successfully find a registry format GUID, file buffer pointer moved forward
1116    #   @retval False       Not able to find a registry format GUID, file buffer pointer not changed
1117    #
1118    def __GetNextGuid(self):
1119
1120        if not self.__GetNextToken():
1121            return False
1122        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}')
1123        if p.match(self.__Token) != None:
1124            return True
1125        else:
1126            self.__UndoToken()
1127            return False
1128
1129    def __Verify(self, Name, Value, Scope):
1130        if Scope in ['UINT64', 'UINT8']:
1131            ValueNumber = 0
1132            try:
1133                if Value.upper().startswith('0X'):
1134                    ValueNumber = int (Value, 16)
1135                else:
1136                    ValueNumber = int (Value)
1137            except:
1138                EdkLogger.error("FdfParser", FORMAT_INVALID, "The value is not valid dec or hex number for %s." % Name)
1139            if ValueNumber < 0:
1140                EdkLogger.error("FdfParser", FORMAT_INVALID, "The value can't be set to negative value for %s." % Name)
1141            if Scope == 'UINT64':
1142                if ValueNumber >= 0x10000000000000000:
1143                    EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)
1144            if Scope == 'UINT8':
1145                if ValueNumber >= 0x100:
1146                    EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)
1147            return True
1148
1149    ## __UndoToken() method
1150    #
1151    #   Go back one token unit in file buffer
1152    #
1153    #   @param  self        The object pointer
1154    #
1155    def __UndoToken(self):
1156        self.__UndoOneChar()
1157        while self.__CurrentChar().isspace():
1158            if not self.__UndoOneChar():
1159                self.__GetOneChar()
1160                return
1161
1162
1163        StartPos = self.CurrentOffsetWithinLine
1164        CurrentLine = self.CurrentLineNumber
1165        while CurrentLine == self.CurrentLineNumber:
1166
1167            TempChar = self.__CurrentChar()
1168            # Try to find the end char that is not a space and not in seperator tuple.
1169            # That is, when we got a space or any char in the tuple, we got the end of token.
1170            if not str(TempChar).isspace() and not TempChar in SEPERATOR_TUPLE:
1171                if not self.__UndoOneChar():
1172                    return
1173            # if we happen to meet a seperator as the first char, we must proceed to get it.
1174            # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
1175            elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE:
1176                return
1177            else:
1178                break
1179
1180        self.__GetOneChar()
1181
1182    ## __HexDigit() method
1183    #
1184    #   Whether char input is a Hex data bit
1185    #
1186    #   @param  self        The object pointer
1187    #   @param  TempChar    The char to test
1188    #   @retval True        The char is a Hex data bit
1189    #   @retval False       The char is NOT a Hex data bit
1190    #
1191    def __HexDigit(self, TempChar):
1192        if (TempChar >= 'a' and TempChar <= 'f') or (TempChar >= 'A' and TempChar <= 'F') \
1193                or (TempChar >= '0' and TempChar <= '9'):
1194                    return True
1195        else:
1196            return False
1197
1198    def __IsHex(self, HexStr):
1199        if not HexStr.upper().startswith("0X"):
1200            return False
1201        if len(self.__Token) <= 2:
1202            return False
1203        charList = [c for c in HexStr[2 : ] if not self.__HexDigit( c)]
1204        if len(charList) == 0:
1205            return True
1206        else:
1207            return False
1208    ## __GetNextHexNumber() method
1209    #
1210    #   Get next HEX data before a seperator
1211    #   If found, the HEX data is put into self.__Token
1212    #
1213    #   @param  self        The object pointer
1214    #   @retval True        Successfully find a HEX data, file buffer pointer moved forward
1215    #   @retval False       Not able to find a HEX data, file buffer pointer not changed
1216    #
1217    def __GetNextHexNumber(self):
1218        if not self.__GetNextToken():
1219            return False
1220        if self.__IsHex(self.__Token):
1221            return True
1222        else:
1223            self.__UndoToken()
1224            return False
1225
1226    ## __GetNextDecimalNumber() method
1227    #
1228    #   Get next decimal data before a seperator
1229    #   If found, the decimal data is put into self.__Token
1230    #
1231    #   @param  self        The object pointer
1232    #   @retval True        Successfully find a decimal data, file buffer pointer moved forward
1233    #   @retval False       Not able to find a decimal data, file buffer pointer not changed
1234    #
1235    def __GetNextDecimalNumber(self):
1236        if not self.__GetNextToken():
1237            return False
1238        if self.__Token.isdigit():
1239            return True
1240        else:
1241            self.__UndoToken()
1242            return False
1243
1244    ## __GetNextPcdName() method
1245    #
1246    #   Get next PCD token space C name and PCD C name pair before a seperator
1247    #   If found, the decimal data is put into self.__Token
1248    #
1249    #   @param  self        The object pointer
1250    #   @retval Tuple       PCD C name and PCD token space C name pair
1251    #
1252    def __GetNextPcdName(self):
1253        if not self.__GetNextWord():
1254            raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
1255        pcdTokenSpaceCName = self.__Token
1256
1257        if not self.__IsToken( "."):
1258            raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
1259
1260        if not self.__GetNextWord():
1261            raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
1262        pcdCName = self.__Token
1263
1264        return (pcdCName, pcdTokenSpaceCName)
1265
1266    ## __GetStringData() method
1267    #
1268    #   Get string contents quoted in ""
1269    #   If found, the decimal data is put into self.__Token
1270    #
1271    #   @param  self        The object pointer
1272    #   @retval True        Successfully find a string data, file buffer pointer moved forward
1273    #   @retval False       Not able to find a string data, file buffer pointer not changed
1274    #
1275    def __GetStringData(self):
1276        if self.__Token.startswith("\"") or self.__Token.startswith("L\""):
1277            self.__UndoToken()
1278            self.__SkipToToken("\"")
1279            currentLineNumber = self.CurrentLineNumber
1280
1281            if not self.__SkipToToken("\""):
1282                raise Warning("Missing Quote \" for String", self.FileName, self.CurrentLineNumber)
1283            if currentLineNumber != self.CurrentLineNumber:
1284                raise Warning("Missing Quote \" for String", self.FileName, self.CurrentLineNumber)
1285            self.__Token = self.__SkippedChars.rstrip('\"')
1286            return True
1287
1288        elif self.__Token.startswith("\'") or self.__Token.startswith("L\'"):
1289            self.__UndoToken()
1290            self.__SkipToToken("\'")
1291            currentLineNumber = self.CurrentLineNumber
1292
1293            if not self.__SkipToToken("\'"):
1294                raise Warning("Missing Quote \' for String", self.FileName, self.CurrentLineNumber)
1295            if currentLineNumber != self.CurrentLineNumber:
1296                raise Warning("Missing Quote \' for String", self.FileName, self.CurrentLineNumber)
1297            self.__Token = self.__SkippedChars.rstrip('\'')
1298            return True
1299
1300        else:
1301            return False
1302
1303    ## __SkipToToken() method
1304    #
1305    #   Search forward in file buffer for the string
1306    #   The skipped chars are put into self.__SkippedChars
1307    #
1308    #   @param  self        The object pointer
1309    #   @param  String      The string to search
1310    #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive
1311    #   @retval True        Successfully find the string, file buffer pointer moved forward
1312    #   @retval False       Not able to find the string, file buffer pointer not changed
1313    #
1314    def __SkipToToken(self, String, IgnoreCase = False):
1315        StartPos = self.GetFileBufferPos()
1316
1317        self.__SkippedChars = ""
1318        while not self.__EndOfFile():
1319            index = -1
1320            if IgnoreCase:
1321                index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper())
1322            else:
1323                index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String)
1324            if index == 0:
1325                self.CurrentOffsetWithinLine += len(String)
1326                self.__SkippedChars += String
1327                return True
1328            self.__SkippedChars += str(self.__CurrentChar())
1329            self.__GetOneChar()
1330
1331        self.SetFileBufferPos( StartPos)
1332        self.__SkippedChars = ""
1333        return False
1334
1335    ## GetFileBufferPos() method
1336    #
1337    #   Return the tuple of current line and offset within the line
1338    #
1339    #   @param  self        The object pointer
1340    #   @retval Tuple       Line number and offset pair
1341    #
1342    def GetFileBufferPos(self):
1343        return (self.CurrentLineNumber, self.CurrentOffsetWithinLine)
1344
1345    ## SetFileBufferPos() method
1346    #
1347    #   Restore the file buffer position
1348    #
1349    #   @param  self        The object pointer
1350    #   @param  Pos         The new file buffer position
1351    #
1352    def SetFileBufferPos(self, Pos):
1353        (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos
1354
1355    ## Preprocess() method
1356    #
1357    #   Preprocess comment, conditional directive, include directive, replace macro.
1358    #   Exception will be raised if syntax error found
1359    #
1360    #   @param  self        The object pointer
1361    #
1362    def Preprocess(self):
1363        self.__StringToList()
1364        self.PreprocessFile()
1365        self.PreprocessIncludeFile()
1366        self.__StringToList()
1367        self.PreprocessFile()
1368        self.PreprocessConditionalStatement()
1369        self.__StringToList()
1370        for Pos in self.__WipeOffArea:
1371            self.__ReplaceFragment(Pos[0], Pos[1])
1372        self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
1373
1374        while self.__GetDefines():
1375            pass
1376
1377    ## ParseFile() method
1378    #
1379    #   Parse the file profile buffer to extract fd, fv ... information
1380    #   Exception will be raised if syntax error found
1381    #
1382    #   @param  self        The object pointer
1383    #
1384    def ParseFile(self):
1385
1386        try:
1387            self.Preprocess()
1388            #
1389            # Keep processing sections of the FDF until no new sections or a syntax error is found
1390            #
1391            while self.__GetFd() or self.__GetFv() or self.__GetFmp() or self.__GetCapsule() or self.__GetVtf() or self.__GetRule() or self.__GetOptionRom():
1392                pass
1393
1394        except Warning, X:
1395            self.__UndoToken()
1396            #'\n\tGot Token: \"%s\" from File %s\n' % (self.__Token, FileLineTuple[0]) + \
1397            # At this point, the closest parent would be the included file itself
1398            Profile = GetParentAtLine(X.OriginalLineNumber)
1399            if Profile != None:
1400                X.Message += ' near line %d, column %d: %s' \
1401                % (X.LineNumber, 0, Profile.FileLinesList[X.LineNumber-1])
1402            else:
1403                FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1404                X.Message += ' near line %d, column %d: %s' \
1405                % (FileLineTuple[1], self.CurrentOffsetWithinLine + 1, self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :].rstrip('\n').rstrip('\r'))
1406            raise
1407
1408    ## SectionParser() method
1409    #
1410    #   Parse the file section info
1411    #   Exception will be raised if syntax error found
1412    #
1413    #   @param  self          The object pointer
1414    #   @param  section       The section string
1415
1416    def SectionParser(self, section):
1417        S = section.upper()
1418        if not S.startswith("[DEFINES") and not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \
1419            and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM.") and not S.startswith('[FMPPAYLOAD.'):
1420            raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.], [FMPPAYLOAD.])", self.FileName, self.CurrentLineNumber)
1421
1422    ## __GetDefines() method
1423    #
1424    #   Get Defines section contents and store its data into AllMacrosList
1425    #
1426    #   @param  self        The object pointer
1427    #   @retval True        Successfully find a Defines
1428    #   @retval False       Not able to find a Defines
1429    #
1430    def __GetDefines(self):
1431
1432        if not self.__GetNextToken():
1433            return False
1434
1435        S = self.__Token.upper()
1436        if S.startswith("[") and not S.startswith("[DEFINES"):
1437            self.SectionParser(S)
1438            self.__UndoToken()
1439            return False
1440
1441        self.__UndoToken()
1442        if not self.__IsToken("[DEFINES", True):
1443            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1444            #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1445            #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1446            raise Warning("expected [DEFINES", self.FileName, self.CurrentLineNumber)
1447
1448        if not self.__IsToken( "]"):
1449            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
1450
1451        while self.__GetNextWord():
1452            # handle the SET statement
1453            if self.__Token == 'SET':
1454                self.__UndoToken()
1455                self.__GetSetStatement(None)
1456                continue
1457
1458            Macro = self.__Token
1459
1460            if not self.__IsToken("="):
1461                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1462            if not self.__GetNextToken() or self.__Token.startswith('['):
1463                raise Warning("expected MACRO value", self.FileName, self.CurrentLineNumber)
1464            Value = self.__Token
1465
1466        return False
1467
1468    ## __GetFd() method
1469    #
1470    #   Get FD section contents and store its data into FD dictionary of self.Profile
1471    #
1472    #   @param  self        The object pointer
1473    #   @retval True        Successfully find a FD
1474    #   @retval False       Not able to find a FD
1475    #
1476    def __GetFd(self):
1477
1478        if not self.__GetNextToken():
1479            return False
1480
1481        S = self.__Token.upper()
1482        if S.startswith("[") and not S.startswith("[FD."):
1483            if not S.startswith("[FV.") and not S.startswith('[FMPPAYLOAD.') and not S.startswith("[CAPSULE.") \
1484                and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
1485                raise Warning("Unknown section", self.FileName, self.CurrentLineNumber)
1486            self.__UndoToken()
1487            return False
1488
1489        self.__UndoToken()
1490        if not self.__IsToken("[FD.", True):
1491            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1492            #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1493            #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1494            raise Warning("expected [FD.]", self.FileName, self.CurrentLineNumber)
1495
1496        FdName = self.__GetUiName()
1497        if FdName == "":
1498            if len (self.Profile.FdDict) == 0:
1499                FdName = GenFdsGlobalVariable.PlatformName
1500                if FdName == "" and GlobalData.gActivePlatform:
1501                    FdName = GlobalData.gActivePlatform.PlatformName
1502                self.Profile.FdNameNotSet = True
1503            else:
1504                raise Warning("expected FdName in [FD.] section", self.FileName, self.CurrentLineNumber)
1505        self.CurrentFdName = FdName.upper()
1506
1507        if self.CurrentFdName in self.Profile.FdDict:
1508            raise Warning("Unexpected the same FD name", self.FileName, self.CurrentLineNumber)
1509
1510        if not self.__IsToken( "]"):
1511            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
1512
1513        FdObj = Fd.FD()
1514        FdObj.FdUiName = self.CurrentFdName
1515        self.Profile.FdDict[self.CurrentFdName] = FdObj
1516
1517        if len (self.Profile.FdDict) > 1 and self.Profile.FdNameNotSet:
1518            raise Warning("expected all FDs have their name", self.FileName, self.CurrentLineNumber)
1519
1520        Status = self.__GetCreateFile(FdObj)
1521        if not Status:
1522            raise Warning("FD name error", self.FileName, self.CurrentLineNumber)
1523
1524        while self.__GetTokenStatements(FdObj):
1525            pass
1526        for Attr in ("BaseAddress", "Size", "ErasePolarity"):
1527            if getattr(FdObj, Attr) == None:
1528                self.__GetNextToken()
1529                raise Warning("Keyword %s missing" % Attr, self.FileName, self.CurrentLineNumber)
1530
1531        if not FdObj.BlockSizeList:
1532            FdObj.BlockSizeList.append((1, FdObj.Size, None))
1533
1534        self.__GetDefineStatements(FdObj)
1535
1536        self.__GetSetStatements(FdObj)
1537
1538        if not self.__GetRegionLayout(FdObj):
1539            raise Warning("expected region layout", self.FileName, self.CurrentLineNumber)
1540
1541        while self.__GetRegionLayout(FdObj):
1542            pass
1543        return True
1544
1545    ## __GetUiName() method
1546    #
1547    #   Return the UI name of a section
1548    #
1549    #   @param  self        The object pointer
1550    #   @retval FdName      UI name
1551    #
1552    def __GetUiName(self):
1553        Name = ""
1554        if self.__GetNextWord():
1555            Name = self.__Token
1556
1557        return Name
1558
1559    ## __GetCreateFile() method
1560    #
1561    #   Return the output file name of object
1562    #
1563    #   @param  self        The object pointer
1564    #   @param  Obj         object whose data will be stored in file
1565    #   @retval FdName      UI name
1566    #
1567    def __GetCreateFile(self, Obj):
1568
1569        if self.__IsKeyword( "CREATE_FILE"):
1570            if not self.__IsToken( "="):
1571                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1572
1573            if not self.__GetNextToken():
1574                raise Warning("expected file name", self.FileName, self.CurrentLineNumber)
1575
1576            FileName = self.__Token
1577            Obj.CreateFileName = FileName
1578
1579        return True
1580
1581    ## __GetTokenStatements() method
1582    #
1583    #   Get token statements
1584    #
1585    #   @param  self        The object pointer
1586    #   @param  Obj         for whom token statement is got
1587    #
1588    def __GetTokenStatements(self, Obj):
1589        if self.__IsKeyword( "BaseAddress"):
1590            if not self.__IsToken( "="):
1591                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1592
1593            if not self.__GetNextHexNumber():
1594                raise Warning("expected Hex base address", self.FileName, self.CurrentLineNumber)
1595
1596            Obj.BaseAddress = self.__Token
1597
1598            if self.__IsToken( "|"):
1599                pcdPair = self.__GetNextPcdName()
1600                Obj.BaseAddressPcd = pcdPair
1601                self.Profile.PcdDict[pcdPair] = Obj.BaseAddress
1602                FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1603                self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1604            return True
1605
1606        if self.__IsKeyword( "Size"):
1607            if not self.__IsToken( "="):
1608                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1609
1610            if not self.__GetNextHexNumber():
1611                raise Warning("expected Hex size", self.FileName, self.CurrentLineNumber)
1612
1613            Size = self.__Token
1614            if self.__IsToken( "|"):
1615                pcdPair = self.__GetNextPcdName()
1616                Obj.SizePcd = pcdPair
1617                self.Profile.PcdDict[pcdPair] = Size
1618                FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1619                self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1620            Obj.Size = long(Size, 0)
1621            return True
1622
1623        if self.__IsKeyword( "ErasePolarity"):
1624            if not self.__IsToken( "="):
1625                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1626
1627            if not self.__GetNextToken():
1628                raise Warning("expected Erase Polarity", self.FileName, self.CurrentLineNumber)
1629
1630            if self.__Token != "1" and self.__Token != "0":
1631                raise Warning("expected 1 or 0 Erase Polarity", self.FileName, self.CurrentLineNumber)
1632
1633            Obj.ErasePolarity = self.__Token
1634            return True
1635
1636        return self.__GetBlockStatements(Obj)
1637
1638    ## __GetAddressStatements() method
1639    #
1640    #   Get address statements
1641    #
1642    #   @param  self        The object pointer
1643    #   @param  Obj         for whom address statement is got
1644    #   @retval True        Successfully find
1645    #   @retval False       Not able to find
1646    #
1647    def __GetAddressStatements(self, Obj):
1648
1649        if self.__IsKeyword("BsBaseAddress"):
1650            if not self.__IsToken( "="):
1651                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1652
1653            if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1654                raise Warning("expected address", self.FileName, self.CurrentLineNumber)
1655
1656            BsAddress = long(self.__Token, 0)
1657            Obj.BsBaseAddress = BsAddress
1658
1659        if self.__IsKeyword("RtBaseAddress"):
1660            if not self.__IsToken( "="):
1661                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1662
1663            if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1664                raise Warning("expected address", self.FileName, self.CurrentLineNumber)
1665
1666            RtAddress = long(self.__Token, 0)
1667            Obj.RtBaseAddress = RtAddress
1668
1669    ## __GetBlockStatements() method
1670    #
1671    #   Get block statements
1672    #
1673    #   @param  self        The object pointer
1674    #   @param  Obj         for whom block statement is got
1675    #
1676    def __GetBlockStatements(self, Obj):
1677        IsBlock = False
1678        while self.__GetBlockStatement(Obj):
1679            IsBlock = True
1680
1681            Item = Obj.BlockSizeList[-1]
1682            if Item[0] == None or Item[1] == None:
1683                raise Warning("expected block statement", self.FileName, self.CurrentLineNumber)
1684        return IsBlock
1685
1686    ## __GetBlockStatement() method
1687    #
1688    #   Get block statement
1689    #
1690    #   @param  self        The object pointer
1691    #   @param  Obj         for whom block statement is got
1692    #   @retval True        Successfully find
1693    #   @retval False       Not able to find
1694    #
1695    def __GetBlockStatement(self, Obj):
1696        if not self.__IsKeyword( "BlockSize"):
1697            return False
1698
1699        if not self.__IsToken( "="):
1700            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1701
1702        if not self.__GetNextHexNumber() and not self.__GetNextDecimalNumber():
1703            raise Warning("expected Hex or Integer block size", self.FileName, self.CurrentLineNumber)
1704
1705        BlockSize = self.__Token
1706        BlockSizePcd = None
1707        if self.__IsToken( "|"):
1708            PcdPair = self.__GetNextPcdName()
1709            BlockSizePcd = PcdPair
1710            self.Profile.PcdDict[PcdPair] = BlockSize
1711            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1712            self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
1713        BlockSize = long(BlockSize, 0)
1714
1715        BlockNumber = None
1716        if self.__IsKeyword( "NumBlocks"):
1717            if not self.__IsToken( "="):
1718                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1719
1720            if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1721                raise Warning("expected block numbers", self.FileName, self.CurrentLineNumber)
1722
1723            BlockNumber = long(self.__Token, 0)
1724
1725        Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd))
1726        return True
1727
1728    ## __GetDefineStatements() method
1729    #
1730    #   Get define statements
1731    #
1732    #   @param  self        The object pointer
1733    #   @param  Obj         for whom define statement is got
1734    #   @retval True        Successfully find
1735    #   @retval False       Not able to find
1736    #
1737    def __GetDefineStatements(self, Obj):
1738        while self.__GetDefineStatement( Obj):
1739            pass
1740
1741    ## __GetDefineStatement() method
1742    #
1743    #   Get define statement
1744    #
1745    #   @param  self        The object pointer
1746    #   @param  Obj         for whom define statement is got
1747    #   @retval True        Successfully find
1748    #   @retval False       Not able to find
1749    #
1750    def __GetDefineStatement(self, Obj):
1751        if self.__IsKeyword("DEFINE"):
1752            self.__GetNextToken()
1753            Macro = self.__Token
1754            if not self.__IsToken( "="):
1755                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1756
1757            if not self.__GetNextToken():
1758                raise Warning("expected value", self.FileName, self.CurrentLineNumber)
1759
1760            Value = self.__Token
1761            Macro = '$(' + Macro + ')'
1762            Obj.DefineVarDict[Macro] = Value
1763            return True
1764
1765        return False
1766
1767    ## __GetSetStatements() method
1768    #
1769    #   Get set statements
1770    #
1771    #   @param  self        The object pointer
1772    #   @param  Obj         for whom set statement is got
1773    #   @retval True        Successfully find
1774    #   @retval False       Not able to find
1775    #
1776    def __GetSetStatements(self, Obj):
1777        while self.__GetSetStatement(Obj):
1778            pass
1779
1780    ## __GetSetStatement() method
1781    #
1782    #   Get set statement
1783    #
1784    #   @param  self        The object pointer
1785    #   @param  Obj         for whom set statement is got
1786    #   @retval True        Successfully find
1787    #   @retval False       Not able to find
1788    #
1789    def __GetSetStatement(self, Obj):
1790        if self.__IsKeyword("SET"):
1791            PcdPair = self.__GetNextPcdName()
1792
1793            if not self.__IsToken( "="):
1794                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1795
1796            Value = self.__GetExpression()
1797            Value = self.__EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
1798
1799            if Obj:
1800                Obj.SetVarDict[PcdPair] = Value
1801            self.Profile.PcdDict[PcdPair] = Value
1802            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1803            self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
1804            return True
1805
1806        return False
1807
1808    ## __CalcRegionExpr(self)
1809    #
1810    #   Calculate expression for offset or size of a region
1811    #
1812    #   @return: None if invalid expression
1813    #            Calculated number if successfully
1814    #
1815    def __CalcRegionExpr(self):
1816        StartPos = self.GetFileBufferPos()
1817        Expr = ''
1818        PairCount = 0
1819        while not self.__EndOfFile():
1820            CurCh = self.__CurrentChar()
1821            if CurCh == '(':
1822                PairCount += 1
1823            elif CurCh == ')':
1824                PairCount -= 1
1825
1826            if CurCh in '|\r\n' and PairCount == 0:
1827                break
1828            Expr += CurCh
1829            self.__GetOneChar()
1830        try:
1831            return long(
1832                ValueExpression(Expr,
1833                                self.__CollectMacroPcd()
1834                                )(True),0)
1835        except Exception:
1836            self.SetFileBufferPos(StartPos)
1837            return None
1838
1839    ## __GetRegionLayout() method
1840    #
1841    #   Get region layout for FD
1842    #
1843    #   @param  self        The object pointer
1844    #   @param  Fd          for whom region is got
1845    #   @retval True        Successfully find
1846    #   @retval False       Not able to find
1847    #
1848    def __GetRegionLayout(self, Fd):
1849        Offset = self.__CalcRegionExpr()
1850        if Offset == None:
1851            return False
1852
1853        RegionObj = Region.Region()
1854        RegionObj.Offset = Offset
1855        Fd.RegionList.append(RegionObj)
1856
1857        if not self.__IsToken( "|"):
1858            raise Warning("expected '|'", self.FileName, self.CurrentLineNumber)
1859
1860        Size = self.__CalcRegionExpr()
1861        if Size == None:
1862            raise Warning("expected Region Size", self.FileName, self.CurrentLineNumber)
1863        RegionObj.Size = Size
1864
1865        if not self.__GetNextWord():
1866            return True
1867
1868        if not self.__Token in ("SET", "FV", "FILE", "DATA", "CAPSULE", "INF"):
1869            #
1870            # If next token is a word which is not a valid FV type, it might be part of [PcdOffset[|PcdSize]]
1871            # Or it might be next region's offset described by an expression which starts with a PCD.
1872            #    PcdOffset[|PcdSize] or OffsetPcdExpression|Size
1873            #
1874            self.__UndoToken()
1875            IsRegionPcd = (RegionSizeGuidPattern.match(self.__CurrentLine()[self.CurrentOffsetWithinLine:]) or
1876                           RegionOffsetPcdPattern.match(self.__CurrentLine()[self.CurrentOffsetWithinLine:]))
1877            if IsRegionPcd:
1878                RegionObj.PcdOffset = self.__GetNextPcdName()
1879                self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + long(Fd.BaseAddress, 0))
1880                self.__PcdDict['%s.%s' % (RegionObj.PcdOffset[1], RegionObj.PcdOffset[0])] = "0x%x" % RegionObj.Offset
1881                FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1882                self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple
1883                if self.__IsToken( "|"):
1884                    RegionObj.PcdSize = self.__GetNextPcdName()
1885                    self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size
1886                    self.__PcdDict['%s.%s' % (RegionObj.PcdSize[1], RegionObj.PcdSize[0])] = "0x%x" % RegionObj.Size
1887                    FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1888                    self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple
1889
1890            if not self.__GetNextWord():
1891                return True
1892
1893        if self.__Token == "SET":
1894            self.__UndoToken()
1895            self.__GetSetStatements( RegionObj)
1896            if not self.__GetNextWord():
1897                return True
1898
1899        elif self.__Token == "FV":
1900            self.__UndoToken()
1901            self.__GetRegionFvType( RegionObj)
1902
1903        elif self.__Token == "CAPSULE":
1904            self.__UndoToken()
1905            self.__GetRegionCapType( RegionObj)
1906
1907        elif self.__Token == "FILE":
1908            self.__UndoToken()
1909            self.__GetRegionFileType(RegionObj)
1910
1911        elif self.__Token == "INF":
1912            self.__UndoToken()
1913            RegionObj.RegionType = "INF"
1914            while self.__IsKeyword("INF"):
1915                self.__UndoToken()
1916                ffsInf = self.__ParseInfStatement()
1917                if not ffsInf:
1918                    break
1919                RegionObj.RegionDataList.append(ffsInf)
1920
1921        elif self.__Token == "DATA":
1922            self.__UndoToken()
1923            self.__GetRegionDataType(RegionObj)
1924        else:
1925            self.__UndoToken()
1926            if self.__GetRegionLayout(Fd):
1927                return True
1928            raise Warning("A valid region type was not found. "
1929                          "Valid types are [SET, FV, CAPSULE, FILE, DATA, INF]. This error occurred",
1930                          self.FileName, self.CurrentLineNumber)
1931
1932        return True
1933
1934    ## __GetRegionFvType() method
1935    #
1936    #   Get region fv data for region
1937    #
1938    #   @param  self        The object pointer
1939    #   @param  RegionObj   for whom region data is got
1940    #
1941    def __GetRegionFvType(self, RegionObj):
1942
1943        if not self.__IsKeyword( "FV"):
1944            raise Warning("expected Keyword 'FV'", self.FileName, self.CurrentLineNumber)
1945
1946        if not self.__IsToken( "="):
1947            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1948
1949        if not self.__GetNextToken():
1950            raise Warning("expected FV name", self.FileName, self.CurrentLineNumber)
1951
1952        RegionObj.RegionType = "FV"
1953        RegionObj.RegionDataList.append((self.__Token).upper())
1954
1955        while self.__IsKeyword( "FV"):
1956
1957            if not self.__IsToken( "="):
1958                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1959
1960            if not self.__GetNextToken():
1961                raise Warning("expected FV name", self.FileName, self.CurrentLineNumber)
1962
1963            RegionObj.RegionDataList.append((self.__Token).upper())
1964
1965    ## __GetRegionCapType() method
1966    #
1967    #   Get region capsule data for region
1968    #
1969    #   @param  self        The object pointer
1970    #   @param  RegionObj   for whom region data is got
1971    #
1972    def __GetRegionCapType(self, RegionObj):
1973
1974        if not self.__IsKeyword("CAPSULE"):
1975            raise Warning("expected Keyword 'CAPSULE'", self.FileName, self.CurrentLineNumber)
1976
1977        if not self.__IsToken("="):
1978            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1979
1980        if not self.__GetNextToken():
1981            raise Warning("expected CAPSULE name", self.FileName, self.CurrentLineNumber)
1982
1983        RegionObj.RegionType = "CAPSULE"
1984        RegionObj.RegionDataList.append(self.__Token)
1985
1986        while self.__IsKeyword("CAPSULE"):
1987
1988            if not self.__IsToken("="):
1989                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1990
1991            if not self.__GetNextToken():
1992                raise Warning("expected CAPSULE name", self.FileName, self.CurrentLineNumber)
1993
1994            RegionObj.RegionDataList.append(self.__Token)
1995
1996    ## __GetRegionFileType() method
1997    #
1998    #   Get region file data for region
1999    #
2000    #   @param  self        The object pointer
2001    #   @param  RegionObj   for whom region data is got
2002    #
2003    def __GetRegionFileType(self, RegionObj):
2004
2005        if not self.__IsKeyword( "FILE"):
2006            raise Warning("expected Keyword 'FILE'", self.FileName, self.CurrentLineNumber)
2007
2008        if not self.__IsToken( "="):
2009            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2010
2011        if not self.__GetNextToken():
2012            raise Warning("expected File name", self.FileName, self.CurrentLineNumber)
2013
2014        RegionObj.RegionType = "FILE"
2015        RegionObj.RegionDataList.append( self.__Token)
2016
2017        while self.__IsKeyword( "FILE"):
2018
2019            if not self.__IsToken( "="):
2020                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2021
2022            if not self.__GetNextToken():
2023                raise Warning("expected FILE name", self.FileName, self.CurrentLineNumber)
2024
2025            RegionObj.RegionDataList.append(self.__Token)
2026
2027    ## __GetRegionDataType() method
2028    #
2029    #   Get region array data for region
2030    #
2031    #   @param  self        The object pointer
2032    #   @param  RegionObj   for whom region data is got
2033    #
2034    def __GetRegionDataType(self, RegionObj):
2035
2036        if not self.__IsKeyword( "DATA"):
2037            raise Warning("expected Region Data type", self.FileName, self.CurrentLineNumber)
2038
2039        if not self.__IsToken( "="):
2040            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2041
2042        if not self.__IsToken( "{"):
2043            raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2044
2045        if not self.__GetNextHexNumber():
2046            raise Warning("expected Hex byte", self.FileName, self.CurrentLineNumber)
2047
2048        if len(self.__Token) > 18:
2049            raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
2050
2051        # convert hex string value to byte hex string array
2052        AllString = self.__Token
2053        AllStrLen = len (AllString)
2054        DataString = ""
2055        while AllStrLen > 4:
2056            DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + ","
2057            AllStrLen  = AllStrLen - 2
2058        DataString = DataString + AllString[:AllStrLen] + ","
2059
2060        # byte value array
2061        if len (self.__Token) <= 4:
2062            while self.__IsToken(","):
2063                if not self.__GetNextHexNumber():
2064                    raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2065                if len(self.__Token) > 4:
2066                    raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2067                DataString += self.__Token
2068                DataString += ","
2069
2070        if not self.__IsToken( "}"):
2071            raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2072
2073        DataString = DataString.rstrip(",")
2074        RegionObj.RegionType = "DATA"
2075        RegionObj.RegionDataList.append( DataString)
2076
2077        while self.__IsKeyword( "DATA"):
2078
2079            if not self.__IsToken( "="):
2080                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2081
2082            if not self.__IsToken( "{"):
2083                raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2084
2085            if not self.__GetNextHexNumber():
2086                raise Warning("expected Hex byte", self.FileName, self.CurrentLineNumber)
2087
2088            if len(self.__Token) > 18:
2089                raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
2090
2091            # convert hex string value to byte hex string array
2092            AllString = self.__Token
2093            AllStrLen = len (AllString)
2094            DataString = ""
2095            while AllStrLen > 4:
2096                DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + ","
2097                AllStrLen  = AllStrLen - 2
2098            DataString = DataString + AllString[:AllStrLen] + ","
2099
2100            # byte value array
2101            if len (self.__Token) <= 4:
2102                while self.__IsToken(","):
2103                    if not self.__GetNextHexNumber():
2104                        raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2105                    if len(self.__Token) > 4:
2106                        raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2107                    DataString += self.__Token
2108                    DataString += ","
2109
2110            if not self.__IsToken( "}"):
2111                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2112
2113            DataString = DataString.rstrip(",")
2114            RegionObj.RegionDataList.append( DataString)
2115
2116    ## __GetFv() method
2117    #
2118    #   Get FV section contents and store its data into FV dictionary of self.Profile
2119    #
2120    #   @param  self        The object pointer
2121    #   @retval True        Successfully find a FV
2122    #   @retval False       Not able to find a FV
2123    #
2124    def __GetFv(self):
2125        if not self.__GetNextToken():
2126            return False
2127
2128        S = self.__Token.upper()
2129        if S.startswith("[") and not S.startswith("[FV."):
2130            self.SectionParser(S)
2131            self.__UndoToken()
2132            return False
2133
2134        self.__UndoToken()
2135        if not self.__IsToken("[FV.", True):
2136            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2137            #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
2138            #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
2139            raise Warning("Unknown Keyword '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2140
2141        FvName = self.__GetUiName()
2142        self.CurrentFvName = FvName.upper()
2143
2144        if not self.__IsToken( "]"):
2145            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
2146
2147        FvObj = Fv.FV()
2148        FvObj.UiFvName = self.CurrentFvName
2149        self.Profile.FvDict[self.CurrentFvName] = FvObj
2150
2151        Status = self.__GetCreateFile(FvObj)
2152        if not Status:
2153            raise Warning("FV name error", self.FileName, self.CurrentLineNumber)
2154
2155        self.__GetDefineStatements(FvObj)
2156
2157        self.__GetAddressStatements(FvObj)
2158
2159        FvObj.FvExtEntryTypeValue = []
2160        FvObj.FvExtEntryType = []
2161        FvObj.FvExtEntryData = []
2162        while True:
2163            self.__GetSetStatements(FvObj)
2164
2165            if not (self.__GetBlockStatement(FvObj) or self.__GetFvBaseAddress(FvObj) or
2166                self.__GetFvForceRebase(FvObj) or self.__GetFvAlignment(FvObj) or
2167                self.__GetFvAttributes(FvObj) or self.__GetFvNameGuid(FvObj) or
2168                self.__GetFvExtEntryStatement(FvObj) or self.__GetFvNameString(FvObj)):
2169                break
2170
2171        if FvObj.FvNameString == 'TRUE' and not FvObj.FvNameGuid:
2172            raise Warning("FvNameString found but FvNameGuid was not found", self.FileName, self.CurrentLineNumber)
2173
2174        self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy())
2175        self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy())
2176
2177        while True:
2178            isInf = self.__GetInfStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy())
2179            isFile = self.__GetFileStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy())
2180            if not isInf and not isFile:
2181                break
2182
2183        return True
2184
2185    ## __GetFvAlignment() method
2186    #
2187    #   Get alignment for FV
2188    #
2189    #   @param  self        The object pointer
2190    #   @param  Obj         for whom alignment is got
2191    #   @retval True        Successfully find a alignment statement
2192    #   @retval False       Not able to find a alignment statement
2193    #
2194    def __GetFvAlignment(self, Obj):
2195
2196        if not self.__IsKeyword( "FvAlignment"):
2197            return False
2198
2199        if not self.__IsToken( "="):
2200            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2201
2202        if not self.__GetNextToken():
2203            raise Warning("expected alignment value", self.FileName, self.CurrentLineNumber)
2204
2205        if self.__Token.upper() not in ("1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \
2206                                        "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \
2207                                        "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \
2208                                        "1G", "2G"):
2209            raise Warning("Unknown alignment value '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2210        Obj.FvAlignment = self.__Token
2211        return True
2212
2213    ## __GetFvBaseAddress() method
2214    #
2215    #   Get BaseAddress for FV
2216    #
2217    #   @param  self        The object pointer
2218    #   @param  Obj         for whom FvBaseAddress is got
2219    #   @retval True        Successfully find a FvBaseAddress statement
2220    #   @retval False       Not able to find a FvBaseAddress statement
2221    #
2222    def __GetFvBaseAddress(self, Obj):
2223
2224        if not self.__IsKeyword("FvBaseAddress"):
2225            return False
2226
2227        if not self.__IsToken( "="):
2228            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2229
2230        if not self.__GetNextToken():
2231            raise Warning("expected FV base address value", self.FileName, self.CurrentLineNumber)
2232
2233        IsValidBaseAddrValue = re.compile('^0[x|X][0-9a-fA-F]+')
2234
2235        if not IsValidBaseAddrValue.match(self.__Token.upper()):
2236            raise Warning("Unknown FV base address value '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2237        Obj.FvBaseAddress = self.__Token
2238        return True
2239
2240    ## __GetFvForceRebase() method
2241    #
2242    #   Get FvForceRebase for FV
2243    #
2244    #   @param  self        The object pointer
2245    #   @param  Obj         for whom FvForceRebase is got
2246    #   @retval True        Successfully find a FvForceRebase statement
2247    #   @retval False       Not able to find a FvForceRebase statement
2248    #
2249    def __GetFvForceRebase(self, Obj):
2250
2251        if not self.__IsKeyword("FvForceRebase"):
2252            return False
2253
2254        if not self.__IsToken( "="):
2255            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2256
2257        if not self.__GetNextToken():
2258            raise Warning("expected FvForceRebase value", self.FileName, self.CurrentLineNumber)
2259
2260        if self.__Token.upper() not in ["TRUE", "FALSE", "0", "0X0", "0X00", "1", "0X1", "0X01"]:
2261            raise Warning("Unknown FvForceRebase value '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2262
2263        if self.__Token.upper() in ["TRUE", "1", "0X1", "0X01"]:
2264            Obj.FvForceRebase = True
2265        elif self.__Token.upper() in ["FALSE", "0", "0X0", "0X00"]:
2266            Obj.FvForceRebase = False
2267        else:
2268            Obj.FvForceRebase = None
2269
2270        return True
2271
2272
2273    ## __GetFvAttributes() method
2274    #
2275    #   Get attributes for FV
2276    #
2277    #   @param  self        The object pointer
2278    #   @param  Obj         for whom attribute is got
2279    #   @retval None
2280    #
2281    def __GetFvAttributes(self, FvObj):
2282        IsWordToken = False
2283        while self.__GetNextWord():
2284            IsWordToken = True
2285            name = self.__Token
2286            if name not in ("ERASE_POLARITY", "MEMORY_MAPPED", \
2287                           "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \
2288                           "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \
2289                           "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \
2290                           "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \
2291                           "WRITE_POLICY_RELIABLE", "WEAK_ALIGNMENT"):
2292                self.__UndoToken()
2293                return False
2294
2295            if not self.__IsToken( "="):
2296                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2297
2298            if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"):
2299                raise Warning("expected TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
2300
2301            FvObj.FvAttributeDict[name] = self.__Token
2302
2303        return IsWordToken
2304
2305    ## __GetFvNameGuid() method
2306    #
2307    #   Get FV GUID for FV
2308    #
2309    #   @param  self        The object pointer
2310    #   @param  Obj         for whom GUID is got
2311    #   @retval None
2312    #
2313    def __GetFvNameGuid(self, FvObj):
2314
2315        if not self.__IsKeyword( "FvNameGuid"):
2316            return False
2317
2318        if not self.__IsToken( "="):
2319            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2320
2321        if not self.__GetNextGuid():
2322            raise Warning("expected FV GUID value", self.FileName, self.CurrentLineNumber)
2323
2324        FvObj.FvNameGuid = self.__Token
2325
2326        return True
2327
2328    def __GetFvNameString(self, FvObj):
2329
2330        if not self.__IsKeyword( "FvNameString"):
2331            return False
2332
2333        if not self.__IsToken( "="):
2334            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2335
2336        if not self.__GetNextToken() or self.__Token not in ('TRUE', 'FALSE'):
2337            raise Warning("expected TRUE or FALSE for FvNameString", self.FileName, self.CurrentLineNumber)
2338
2339        FvObj.FvNameString = self.__Token
2340
2341        return True
2342
2343    def __GetFvExtEntryStatement(self, FvObj):
2344
2345        if not self.__IsKeyword( "FV_EXT_ENTRY"):
2346            return False
2347
2348        if not self.__IsKeyword ("TYPE"):
2349            raise Warning("expected 'TYPE'", self.FileName, self.CurrentLineNumber)
2350
2351        if not self.__IsToken( "="):
2352            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2353
2354        if not self.__GetNextHexNumber() and not self.__GetNextDecimalNumber():
2355            raise Warning("expected Hex FV extension entry type value At Line ", self.FileName, self.CurrentLineNumber)
2356
2357        FvObj.FvExtEntryTypeValue += [self.__Token]
2358
2359        if not self.__IsToken( "{"):
2360            raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2361
2362        if not self.__IsKeyword ("FILE") and not self.__IsKeyword ("DATA"):
2363            raise Warning("expected 'FILE' or 'DATA'", self.FileName, self.CurrentLineNumber)
2364
2365        FvObj.FvExtEntryType += [self.__Token]
2366
2367        if self.__Token == 'DATA':
2368
2369            if not self.__IsToken( "="):
2370                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2371
2372            if not self.__IsToken( "{"):
2373                raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2374
2375            if not self.__GetNextHexNumber():
2376                raise Warning("expected Hex byte", self.FileName, self.CurrentLineNumber)
2377
2378            if len(self.__Token) > 4:
2379                raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2380
2381            DataString = self.__Token
2382            DataString += ","
2383
2384            while self.__IsToken(","):
2385                if not self.__GetNextHexNumber():
2386                    raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2387                if len(self.__Token) > 4:
2388                    raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2389                DataString += self.__Token
2390                DataString += ","
2391
2392            if not self.__IsToken( "}"):
2393                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2394
2395            if not self.__IsToken( "}"):
2396                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2397
2398            DataString = DataString.rstrip(",")
2399            FvObj.FvExtEntryData += [DataString]
2400
2401        if self.__Token == 'FILE':
2402
2403            if not self.__IsToken( "="):
2404                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2405
2406            if not self.__GetNextToken():
2407                raise Warning("expected FV Extension Entry file path At Line ", self.FileName, self.CurrentLineNumber)
2408
2409            FvObj.FvExtEntryData += [self.__Token]
2410
2411            if not self.__IsToken( "}"):
2412                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2413
2414        return True
2415
2416    ## __GetAprioriSection() method
2417    #
2418    #   Get token statements
2419    #
2420    #   @param  self        The object pointer
2421    #   @param  FvObj       for whom apriori is got
2422    #   @param  MacroDict   dictionary used to replace macro
2423    #   @retval True        Successfully find apriori statement
2424    #   @retval False       Not able to find apriori statement
2425    #
2426    def __GetAprioriSection(self, FvObj, MacroDict = {}):
2427
2428        if not self.__IsKeyword( "APRIORI"):
2429            return False
2430
2431        if not self.__IsKeyword("PEI") and not self.__IsKeyword("DXE"):
2432            raise Warning("expected Apriori file type", self.FileName, self.CurrentLineNumber)
2433        AprType = self.__Token
2434
2435        if not self.__IsToken( "{"):
2436            raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2437
2438        AprSectionObj = AprioriSection.AprioriSection()
2439        AprSectionObj.AprioriType = AprType
2440
2441        self.__GetDefineStatements(AprSectionObj)
2442        MacroDict.update(AprSectionObj.DefineVarDict)
2443
2444        while True:
2445            IsInf = self.__GetInfStatement( AprSectionObj, MacroDict = MacroDict)
2446            IsFile = self.__GetFileStatement( AprSectionObj)
2447            if not IsInf and not IsFile:
2448                break
2449
2450        if not self.__IsToken( "}"):
2451            raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2452
2453        FvObj.AprioriSectionList.append(AprSectionObj)
2454        return True
2455
2456    def __ParseInfStatement(self):
2457        if not self.__IsKeyword("INF"):
2458            return None
2459
2460        ffsInf = FfsInfStatement.FfsInfStatement()
2461        self.__GetInfOptions(ffsInf)
2462
2463        if not self.__GetNextToken():
2464            raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber)
2465        ffsInf.InfFileName = self.__Token
2466
2467        ffsInf.CurrentLineNum = self.CurrentLineNumber
2468        ffsInf.CurrentLineContent = self.__CurrentLine()
2469
2470        #Replace $(SAPCE) with real space
2471        ffsInf.InfFileName = ffsInf.InfFileName.replace('$(SPACE)', ' ')
2472
2473        if ffsInf.InfFileName.replace('$(WORKSPACE)', '').find('$') == -1:
2474            #do case sensitive check for file path
2475            ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
2476            if ErrorCode != 0:
2477                EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
2478
2479        if not ffsInf.InfFileName in self.Profile.InfList:
2480            self.Profile.InfList.append(ffsInf.InfFileName)
2481            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2482            self.Profile.InfFileLineList.append(FileLineTuple)
2483            if ffsInf.UseArch:
2484                if ffsInf.UseArch not in self.Profile.InfDict:
2485                    self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
2486                else:
2487                    self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
2488            else:
2489                self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
2490
2491        if self.__IsToken('|'):
2492            if self.__IsKeyword('RELOCS_STRIPPED'):
2493                ffsInf.KeepReloc = False
2494            elif self.__IsKeyword('RELOCS_RETAINED'):
2495                ffsInf.KeepReloc = True
2496            else:
2497                raise Warning("Unknown reloc strip flag '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2498        return ffsInf
2499
2500    ## __GetInfStatement() method
2501    #
2502    #   Get INF statements
2503    #
2504    #   @param  self        The object pointer
2505    #   @param  Obj         for whom inf statement is got
2506    #   @param  MacroDict   dictionary used to replace macro
2507    #   @retval True        Successfully find inf statement
2508    #   @retval False       Not able to find inf statement
2509    #
2510    def __GetInfStatement(self, Obj, ForCapsule=False, MacroDict={}):
2511        ffsInf = self.__ParseInfStatement()
2512        if not ffsInf:
2513            return False
2514
2515        if ForCapsule:
2516            capsuleFfs = CapsuleData.CapsuleFfs()
2517            capsuleFfs.Ffs = ffsInf
2518            Obj.CapsuleDataList.append(capsuleFfs)
2519        else:
2520            Obj.FfsList.append(ffsInf)
2521        return True
2522
2523    ## __GetInfOptions() method
2524    #
2525    #   Get options for INF
2526    #
2527    #   @param  self        The object pointer
2528    #   @param  FfsInfObj   for whom option is got
2529    #
2530    def __GetInfOptions(self, FfsInfObj):
2531        if self.__IsKeyword("FILE_GUID"):
2532            if not self.__IsToken("="):
2533                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2534            if not self.__GetNextGuid():
2535                raise Warning("expected GUID value", self.FileName, self.CurrentLineNumber)
2536            FfsInfObj.OverrideGuid = self.__Token
2537
2538        if self.__IsKeyword( "RuleOverride"):
2539            if not self.__IsToken( "="):
2540                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2541            if not self.__GetNextToken():
2542                raise Warning("expected Rule name", self.FileName, self.CurrentLineNumber)
2543            FfsInfObj.Rule = self.__Token
2544
2545        if self.__IsKeyword( "VERSION"):
2546            if not self.__IsToken( "="):
2547                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2548            if not self.__GetNextToken():
2549                raise Warning("expected Version", self.FileName, self.CurrentLineNumber)
2550
2551            if self.__GetStringData():
2552                FfsInfObj.Version = self.__Token
2553
2554        if self.__IsKeyword( "UI"):
2555            if not self.__IsToken( "="):
2556                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2557            if not self.__GetNextToken():
2558                raise Warning("expected UI name", self.FileName, self.CurrentLineNumber)
2559
2560            if self.__GetStringData():
2561                FfsInfObj.Ui = self.__Token
2562
2563        if self.__IsKeyword( "USE"):
2564            if not self.__IsToken( "="):
2565                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2566            if not self.__GetNextToken():
2567                raise Warning("expected ARCH name", self.FileName, self.CurrentLineNumber)
2568            FfsInfObj.UseArch = self.__Token
2569
2570
2571        if self.__GetNextToken():
2572            p = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\))')
2573            if p.match(self.__Token) and p.match(self.__Token).span()[1] == len(self.__Token):
2574                FfsInfObj.KeyStringList.append(self.__Token)
2575                if not self.__IsToken(","):
2576                    return
2577            else:
2578                self.__UndoToken()
2579                return
2580
2581            while self.__GetNextToken():
2582                if not p.match(self.__Token):
2583                    raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
2584                FfsInfObj.KeyStringList.append(self.__Token)
2585
2586                if not self.__IsToken(","):
2587                    break
2588
2589    ## __GetFileStatement() method
2590    #
2591    #   Get FILE statements
2592    #
2593    #   @param  self        The object pointer
2594    #   @param  Obj         for whom FILE statement is got
2595    #   @param  MacroDict   dictionary used to replace macro
2596    #   @retval True        Successfully find FILE statement
2597    #   @retval False       Not able to find FILE statement
2598    #
2599    def __GetFileStatement(self, Obj, ForCapsule = False, MacroDict = {}):
2600
2601        if not self.__IsKeyword( "FILE"):
2602            return False
2603
2604        if not self.__GetNextWord():
2605            raise Warning("expected FFS type", self.FileName, self.CurrentLineNumber)
2606
2607        if ForCapsule and self.__Token == 'DATA':
2608            self.__UndoToken()
2609            self.__UndoToken()
2610            return False
2611
2612        FfsFileObj = FfsFileStatement.FileStatement()
2613        FfsFileObj.FvFileType = self.__Token
2614
2615        if not self.__IsToken( "="):
2616            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2617
2618        if not self.__GetNextGuid():
2619            if not self.__GetNextWord():
2620                raise Warning("expected File GUID", self.FileName, self.CurrentLineNumber)
2621            if self.__Token == 'PCD':
2622                if not self.__IsToken( "("):
2623                    raise Warning("expected '('", self.FileName, self.CurrentLineNumber)
2624                PcdPair = self.__GetNextPcdName()
2625                if not self.__IsToken( ")"):
2626                    raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
2627                self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')'
2628
2629        FfsFileObj.NameGuid = self.__Token
2630
2631        self.__GetFilePart( FfsFileObj, MacroDict.copy())
2632
2633        if ForCapsule:
2634            capsuleFfs = CapsuleData.CapsuleFfs()
2635            capsuleFfs.Ffs = FfsFileObj
2636            Obj.CapsuleDataList.append(capsuleFfs)
2637        else:
2638            Obj.FfsList.append(FfsFileObj)
2639
2640        return True
2641
2642    ## __FileCouldHaveRelocFlag() method
2643    #
2644    #   Check whether reloc strip flag can be set for a file type.
2645    #
2646    #   @param  self        The object pointer
2647    #   @param  FileType    The file type to check with
2648    #   @retval True        This type could have relocation strip flag
2649    #   @retval False       No way to have it
2650    #
2651
2652    def __FileCouldHaveRelocFlag (self, FileType):
2653        if FileType in ('SEC', 'PEI_CORE', 'PEIM', 'PEI_DXE_COMBO'):
2654            return True
2655        else:
2656            return False
2657
2658    ## __SectionCouldHaveRelocFlag() method
2659    #
2660    #   Check whether reloc strip flag can be set for a section type.
2661    #
2662    #   @param  self        The object pointer
2663    #   @param  SectionType The section type to check with
2664    #   @retval True        This type could have relocation strip flag
2665    #   @retval False       No way to have it
2666    #
2667
2668    def __SectionCouldHaveRelocFlag (self, SectionType):
2669        if SectionType in ('TE', 'PE32'):
2670            return True
2671        else:
2672            return False
2673
2674    ## __GetFilePart() method
2675    #
2676    #   Get components for FILE statement
2677    #
2678    #   @param  self        The object pointer
2679    #   @param  FfsFileObj   for whom component is got
2680    #   @param  MacroDict   dictionary used to replace macro
2681    #
2682    def __GetFilePart(self, FfsFileObj, MacroDict = {}):
2683
2684        self.__GetFileOpts( FfsFileObj)
2685
2686        if not self.__IsToken("{"):
2687            if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
2688                if self.__FileCouldHaveRelocFlag(FfsFileObj.FvFileType):
2689                    if self.__Token == 'RELOCS_STRIPPED':
2690                        FfsFileObj.KeepReloc = False
2691                    else:
2692                        FfsFileObj.KeepReloc = True
2693                else:
2694                    raise Warning("File type %s could not have reloc strip flag%d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
2695
2696            if not self.__IsToken("{"):
2697                raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2698
2699        if not self.__GetNextToken():
2700            raise Warning("expected File name or section data", self.FileName, self.CurrentLineNumber)
2701
2702        if self.__Token == "FV":
2703            if not self.__IsToken( "="):
2704                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2705            if not self.__GetNextToken():
2706                raise Warning("expected FV name", self.FileName, self.CurrentLineNumber)
2707            FfsFileObj.FvName = self.__Token
2708
2709        elif self.__Token == "FD":
2710            if not self.__IsToken( "="):
2711                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2712            if not self.__GetNextToken():
2713                raise Warning("expected FD name", self.FileName, self.CurrentLineNumber)
2714            FfsFileObj.FdName = self.__Token
2715
2716        elif self.__Token in ("DEFINE", "APRIORI", "SECTION"):
2717            self.__UndoToken()
2718            self.__GetSectionData( FfsFileObj, MacroDict)
2719
2720        elif hasattr(FfsFileObj, 'FvFileType') and FfsFileObj.FvFileType == 'RAW':
2721            self.__UndoToken()
2722            self.__GetRAWData(FfsFileObj, MacroDict)
2723
2724        else:
2725            FfsFileObj.CurrentLineNum = self.CurrentLineNumber
2726            FfsFileObj.CurrentLineContent = self.__CurrentLine()
2727            FfsFileObj.FileName = self.__Token.replace('$(SPACE)', ' ')
2728            self.__VerifyFile(FfsFileObj.FileName)
2729
2730        if not self.__IsToken( "}"):
2731            raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2732
2733    ## __GetRAWData() method
2734    #
2735    #   Get RAW data for FILE statement
2736    #
2737    #   @param  self         The object pointer
2738    #   @param  FfsFileObj   for whom section is got
2739    #   @param  MacroDict    dictionary used to replace macro
2740    #
2741    def __GetRAWData(self, FfsFileObj, MacroDict = {}):
2742        FfsFileObj.FileName = []
2743        FfsFileObj.SubAlignment = []
2744        while True:
2745            AlignValue = None
2746            if self.__GetAlignment():
2747                if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
2748                    raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2749                #For FFS, Auto is default option same to ""
2750                if not self.__Token == "Auto":
2751                    AlignValue = self.__Token
2752            if not self.__GetNextToken():
2753                raise Warning("expected Filename value", self.FileName, self.CurrentLineNumber)
2754
2755            FileName = self.__Token.replace('$(SPACE)', ' ')
2756            if FileName == '}':
2757                self.__UndoToken()
2758                raise Warning("expected Filename value", self.FileName, self.CurrentLineNumber)
2759
2760            self.__VerifyFile(FileName)
2761            File = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir)
2762            FfsFileObj.FileName.append(File.Path)
2763            FfsFileObj.SubAlignment.append(AlignValue)
2764
2765            if self.__IsToken( "}"):
2766                self.__UndoToken()
2767                break
2768
2769        if len(FfsFileObj.SubAlignment) == 1:
2770            FfsFileObj.SubAlignment = FfsFileObj.SubAlignment[0]
2771        if len(FfsFileObj.FileName) == 1:
2772            FfsFileObj.FileName = FfsFileObj.FileName[0]
2773
2774    ## __GetFileOpts() method
2775    #
2776    #   Get options for FILE statement
2777    #
2778    #   @param  self        The object pointer
2779    #   @param  FfsFileObj   for whom options is got
2780    #
2781    def __GetFileOpts(self, FfsFileObj):
2782
2783        if self.__GetNextToken():
2784            Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
2785            if Pattern.match(self.__Token):
2786                FfsFileObj.KeyStringList.append(self.__Token)
2787                if self.__IsToken(","):
2788                    while self.__GetNextToken():
2789                        if not Pattern.match(self.__Token):
2790                            raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
2791                        FfsFileObj.KeyStringList.append(self.__Token)
2792
2793                        if not self.__IsToken(","):
2794                            break
2795
2796            else:
2797                self.__UndoToken()
2798
2799        if self.__IsKeyword( "FIXED", True):
2800            FfsFileObj.Fixed = True
2801
2802        if self.__IsKeyword( "CHECKSUM", True):
2803            FfsFileObj.CheckSum = True
2804
2805        if self.__GetAlignment():
2806            if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
2807                raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2808            #For FFS, Auto is default option same to ""
2809            if not self.__Token == "Auto":
2810                FfsFileObj.Alignment = self.__Token
2811
2812    ## __GetAlignment() method
2813    #
2814    #   Return the alignment value
2815    #
2816    #   @param  self        The object pointer
2817    #   @retval True        Successfully find alignment
2818    #   @retval False       Not able to find alignment
2819    #
2820    def __GetAlignment(self):
2821        if self.__IsKeyword( "Align", True):
2822            if not self.__IsToken( "="):
2823                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2824
2825            if not self.__GetNextToken():
2826                raise Warning("expected alignment value", self.FileName, self.CurrentLineNumber)
2827            return True
2828
2829        return False
2830
2831    ## __GetFilePart() method
2832    #
2833    #   Get section data for FILE statement
2834    #
2835    #   @param  self        The object pointer
2836    #   @param  FfsFileObj   for whom section is got
2837    #   @param  MacroDict   dictionary used to replace macro
2838    #
2839    def __GetSectionData(self, FfsFileObj, MacroDict = {}):
2840        Dict = {}
2841        Dict.update(MacroDict)
2842
2843        self.__GetDefineStatements(FfsFileObj)
2844
2845        Dict.update(FfsFileObj.DefineVarDict)
2846        self.__GetAprioriSection(FfsFileObj, Dict.copy())
2847        self.__GetAprioriSection(FfsFileObj, Dict.copy())
2848
2849        while True:
2850            IsLeafSection = self.__GetLeafSection(FfsFileObj, Dict)
2851            IsEncapSection = self.__GetEncapsulationSec(FfsFileObj)
2852            if not IsLeafSection and not IsEncapSection:
2853                break
2854
2855    ## __GetLeafSection() method
2856    #
2857    #   Get leaf section for Obj
2858    #
2859    #   @param  self        The object pointer
2860    #   @param  Obj         for whom leaf section is got
2861    #   @param  MacroDict   dictionary used to replace macro
2862    #   @retval True        Successfully find section statement
2863    #   @retval False       Not able to find section statement
2864    #
2865    def __GetLeafSection(self, Obj, MacroDict = {}):
2866
2867        OldPos = self.GetFileBufferPos()
2868
2869        if not self.__IsKeyword( "SECTION"):
2870            if len(Obj.SectionList) == 0:
2871                raise Warning("expected SECTION", self.FileName, self.CurrentLineNumber)
2872            else:
2873                return False
2874
2875        AlignValue = None
2876        if self.__GetAlignment():
2877            if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
2878                raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2879            AlignValue = self.__Token
2880
2881        BuildNum = None
2882        if self.__IsKeyword( "BUILD_NUM"):
2883            if not self.__IsToken( "="):
2884                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2885
2886            if not self.__GetNextToken():
2887                raise Warning("expected Build number value", self.FileName, self.CurrentLineNumber)
2888
2889            BuildNum = self.__Token
2890
2891        if self.__IsKeyword( "VERSION"):
2892            if AlignValue == 'Auto':
2893                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2894            if not self.__IsToken( "="):
2895                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2896            if not self.__GetNextToken():
2897                raise Warning("expected version", self.FileName, self.CurrentLineNumber)
2898            VerSectionObj = VerSection.VerSection()
2899            VerSectionObj.Alignment = AlignValue
2900            VerSectionObj.BuildNum = BuildNum
2901            if self.__GetStringData():
2902                VerSectionObj.StringData = self.__Token
2903            else:
2904                VerSectionObj.FileName = self.__Token
2905            Obj.SectionList.append(VerSectionObj)
2906
2907        elif self.__IsKeyword( "UI"):
2908            if AlignValue == 'Auto':
2909                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2910            if not self.__IsToken( "="):
2911                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2912            if not self.__GetNextToken():
2913                raise Warning("expected UI", self.FileName, self.CurrentLineNumber)
2914            UiSectionObj = UiSection.UiSection()
2915            UiSectionObj.Alignment = AlignValue
2916            if self.__GetStringData():
2917                UiSectionObj.StringData = self.__Token
2918            else:
2919                UiSectionObj.FileName = self.__Token
2920            Obj.SectionList.append(UiSectionObj)
2921
2922        elif self.__IsKeyword( "FV_IMAGE"):
2923            if AlignValue == 'Auto':
2924                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2925            if not self.__IsToken( "="):
2926                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2927            if not self.__GetNextToken():
2928                raise Warning("expected FV name or FV file path", self.FileName, self.CurrentLineNumber)
2929
2930            FvName = self.__Token
2931            FvObj = None
2932
2933            if self.__IsToken( "{"):
2934                FvObj = Fv.FV()
2935                FvObj.UiFvName = FvName.upper()
2936                self.__GetDefineStatements(FvObj)
2937                MacroDict.update(FvObj.DefineVarDict)
2938                self.__GetBlockStatement(FvObj)
2939                self.__GetSetStatements(FvObj)
2940                self.__GetFvAlignment(FvObj)
2941                self.__GetFvAttributes(FvObj)
2942                self.__GetAprioriSection(FvObj, MacroDict.copy())
2943                self.__GetAprioriSection(FvObj, MacroDict.copy())
2944
2945                while True:
2946                    IsInf = self.__GetInfStatement(FvObj, MacroDict.copy())
2947                    IsFile = self.__GetFileStatement(FvObj, MacroDict.copy())
2948                    if not IsInf and not IsFile:
2949                        break
2950
2951                if not self.__IsToken( "}"):
2952                    raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2953
2954            FvImageSectionObj = FvImageSection.FvImageSection()
2955            FvImageSectionObj.Alignment = AlignValue
2956            if FvObj != None:
2957                FvImageSectionObj.Fv = FvObj
2958                FvImageSectionObj.FvName = None
2959            else:
2960                FvImageSectionObj.FvName = FvName.upper()
2961                FvImageSectionObj.FvFileName = FvName
2962
2963            Obj.SectionList.append(FvImageSectionObj)
2964
2965        elif self.__IsKeyword("PEI_DEPEX_EXP") or self.__IsKeyword("DXE_DEPEX_EXP") or self.__IsKeyword("SMM_DEPEX_EXP"):
2966            if AlignValue == 'Auto':
2967                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2968            DepexSectionObj = DepexSection.DepexSection()
2969            DepexSectionObj.Alignment = AlignValue
2970            DepexSectionObj.DepexType = self.__Token
2971
2972            if not self.__IsToken( "="):
2973                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2974            if not self.__IsToken( "{"):
2975                raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2976            if not self.__SkipToToken( "}"):
2977                raise Warning("expected Depex expression ending '}'", self.FileName, self.CurrentLineNumber)
2978
2979            DepexSectionObj.Expression = self.__SkippedChars.rstrip('}')
2980            Obj.SectionList.append(DepexSectionObj)
2981
2982        else:
2983            if not self.__GetNextWord():
2984                raise Warning("expected section type", self.FileName, self.CurrentLineNumber)
2985
2986            # Encapsulation section appear, UndoToken and return
2987            if self.__Token == "COMPRESS" or self.__Token == "GUIDED":
2988                self.SetFileBufferPos(OldPos)
2989                return False
2990
2991            if self.__Token not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
2992                               "UI", "VERSION", "PEI_DEPEX", "SUBTYPE_GUID", "SMM_DEPEX"):
2993                raise Warning("Unknown section type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2994            if AlignValue == 'Auto'and (not self.__Token == 'PE32') and (not self.__Token == 'TE'):
2995                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2996
2997            # DataSection
2998            DataSectionObj = DataSection.DataSection()
2999            DataSectionObj.Alignment = AlignValue
3000            DataSectionObj.SecType = self.__Token
3001
3002            if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
3003                if self.__FileCouldHaveRelocFlag(Obj.FvFileType) and self.__SectionCouldHaveRelocFlag(DataSectionObj.SecType):
3004                    if self.__Token == 'RELOCS_STRIPPED':
3005                        DataSectionObj.KeepReloc = False
3006                    else:
3007                        DataSectionObj.KeepReloc = True
3008                else:
3009                    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)
3010
3011            if self.__IsToken("="):
3012                if not self.__GetNextToken():
3013                    raise Warning("expected section file path", self.FileName, self.CurrentLineNumber)
3014                DataSectionObj.SectFileName = self.__Token
3015                self.__VerifyFile(DataSectionObj.SectFileName)
3016            else:
3017                if not self.__GetCglSection(DataSectionObj):
3018                    return False
3019
3020            Obj.SectionList.append(DataSectionObj)
3021
3022        return True
3023
3024    ## __VerifyFile
3025    #
3026    #    Check if file exists or not:
3027    #      If current phase if GenFds, the file must exist;
3028    #      If current phase is AutoGen and the file is not in $(OUTPUT_DIRECTORY), the file must exist
3029    #    @param FileName: File path to be verified.
3030    #
3031    def __VerifyFile(self, FileName):
3032        if FileName.replace('$(WORKSPACE)', '').find('$') != -1:
3033            return
3034        if not GlobalData.gAutoGenPhase or not self.__GetMacroValue("OUTPUT_DIRECTORY") in FileName:
3035            ErrorCode, ErrorInfo = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
3036            if ErrorCode != 0:
3037                EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
3038
3039    ## __GetCglSection() method
3040    #
3041    #   Get compressed or GUIDed section for Obj
3042    #
3043    #   @param  self        The object pointer
3044    #   @param  Obj         for whom leaf section is got
3045    #   @param  AlignValue  alignment value for complex section
3046    #   @retval True        Successfully find section statement
3047    #   @retval False       Not able to find section statement
3048    #
3049    def __GetCglSection(self, Obj, AlignValue = None):
3050
3051        if self.__IsKeyword( "COMPRESS"):
3052            type = "PI_STD"
3053            if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"):
3054                type = self.__Token
3055
3056            if not self.__IsToken("{"):
3057                raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
3058
3059            CompressSectionObj = CompressSection.CompressSection()
3060            CompressSectionObj.Alignment = AlignValue
3061            CompressSectionObj.CompType = type
3062            # Recursive sections...
3063            while True:
3064                IsLeafSection = self.__GetLeafSection(CompressSectionObj)
3065                IsEncapSection = self.__GetEncapsulationSec(CompressSectionObj)
3066                if not IsLeafSection and not IsEncapSection:
3067                    break
3068
3069
3070            if not self.__IsToken( "}"):
3071                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
3072            Obj.SectionList.append(CompressSectionObj)
3073
3074#            else:
3075#               raise Warning("Compress type not known")
3076
3077            return True
3078
3079        elif self.__IsKeyword( "GUIDED"):
3080            GuidValue = None
3081            if self.__GetNextGuid():
3082                GuidValue = self.__Token
3083
3084            AttribDict = self.__GetGuidAttrib()
3085            if not self.__IsToken("{"):
3086                raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
3087            GuidSectionObj = GuidSection.GuidSection()
3088            GuidSectionObj.Alignment = AlignValue
3089            GuidSectionObj.NameGuid = GuidValue
3090            GuidSectionObj.SectionType = "GUIDED"
3091            GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
3092            GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
3093            GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
3094            # Recursive sections...
3095            while True:
3096                IsLeafSection = self.__GetLeafSection(GuidSectionObj)
3097                IsEncapSection = self.__GetEncapsulationSec(GuidSectionObj)
3098                if not IsLeafSection and not IsEncapSection:
3099                    break
3100
3101            if not self.__IsToken( "}"):
3102                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
3103            Obj.SectionList.append(GuidSectionObj)
3104
3105            return True
3106
3107        return False
3108
3109    ## __GetGuidAttri() method
3110    #
3111    #   Get attributes for GUID section
3112    #
3113    #   @param  self        The object pointer
3114    #   @retval AttribDict  Dictionary of key-value pair of section attributes
3115    #
3116    def __GetGuidAttrib(self):
3117
3118        AttribDict = {}
3119        AttribDict["PROCESSING_REQUIRED"] = "NONE"
3120        AttribDict["AUTH_STATUS_VALID"] = "NONE"
3121        AttribDict["EXTRA_HEADER_SIZE"] = -1
3122        while self.__IsKeyword("PROCESSING_REQUIRED") or self.__IsKeyword("AUTH_STATUS_VALID") \
3123            or self.__IsKeyword("EXTRA_HEADER_SIZE"):
3124            AttribKey = self.__Token
3125
3126            if not self.__IsToken("="):
3127                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3128
3129            if not self.__GetNextToken():
3130                raise Warning("expected TRUE(1)/FALSE(0)/Number", self.FileName, self.CurrentLineNumber)
3131            elif AttribKey == "EXTRA_HEADER_SIZE":
3132                Base = 10
3133                if self.__Token[0:2].upper() == "0X":
3134                    Base = 16
3135                try:
3136                    AttribDict[AttribKey] = int(self.__Token, Base)
3137                    continue
3138                except ValueError:
3139                    raise Warning("expected Number", self.FileName, self.CurrentLineNumber)
3140            elif self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"):
3141                raise Warning("expected TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
3142            AttribDict[AttribKey] = self.__Token
3143
3144        return AttribDict
3145
3146    ## __GetEncapsulationSec() method
3147    #
3148    #   Get encapsulation section for FILE
3149    #
3150    #   @param  self        The object pointer
3151    #   @param  FfsFile     for whom section is got
3152    #   @retval True        Successfully find section statement
3153    #   @retval False       Not able to find section statement
3154    #
3155    def __GetEncapsulationSec(self, FfsFileObj):
3156
3157        OldPos = self.GetFileBufferPos()
3158        if not self.__IsKeyword( "SECTION"):
3159            if len(FfsFileObj.SectionList) == 0:
3160                raise Warning("expected SECTION", self.FileName, self.CurrentLineNumber)
3161            else:
3162                return False
3163
3164        AlignValue = None
3165        if self.__GetAlignment():
3166            if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
3167                raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3168            AlignValue = self.__Token
3169
3170        if not self.__GetCglSection(FfsFileObj, AlignValue):
3171            self.SetFileBufferPos(OldPos)
3172            return False
3173        else:
3174            return True
3175
3176    def __GetFmp(self):
3177        if not self.__GetNextToken():
3178            return False
3179        S = self.__Token.upper()
3180        if S.startswith("[") and not S.startswith("[FMPPAYLOAD."):
3181            self.SectionParser(S)
3182            self.__UndoToken()
3183            return False
3184
3185        self.__UndoToken()
3186        self.__SkipToToken("[FMPPAYLOAD.", True)
3187        FmpUiName = self.__GetUiName().upper()
3188        if FmpUiName in self.Profile.FmpPayloadDict:
3189            raise Warning("Duplicated FMP UI name found: %s" % FmpUiName, self.FileName, self.CurrentLineNumber)
3190
3191        FmpData = CapsuleData.CapsulePayload()
3192        FmpData.UiName = FmpUiName
3193
3194        if not self.__IsToken( "]"):
3195            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
3196
3197        if not self.__GetNextToken():
3198            raise Warning("The FMP payload section is empty!", self.FileName, self.CurrentLineNumber)
3199        FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE', 'CERTIFICATE_GUID', 'MONOTONIC_COUNT']
3200        while self.__Token in FmpKeyList:
3201            Name = self.__Token
3202            FmpKeyList.remove(Name)
3203            if not self.__IsToken("="):
3204                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3205            if Name == 'IMAGE_TYPE_ID':
3206                if not self.__GetNextGuid():
3207                    raise Warning("expected GUID value for IMAGE_TYPE_ID.", self.FileName, self.CurrentLineNumber)
3208                FmpData.ImageTypeId = self.__Token
3209            elif Name == 'CERTIFICATE_GUID':
3210                if not self.__GetNextGuid():
3211                    raise Warning("expected GUID value for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
3212                FmpData.Certificate_Guid = self.__Token
3213                if uuid.UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_RSA2048_SHA256_GUID and uuid.UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_PKCS7_GUID:
3214                    raise Warning("Only support EFI_CERT_TYPE_RSA2048_SHA256_GUID or EFI_CERT_TYPE_PKCS7_GUID for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
3215            else:
3216                if not self.__GetNextToken():
3217                    raise Warning("expected value of %s" % Name, self.FileName, self.CurrentLineNumber)
3218                Value = self.__Token
3219                if Name == 'IMAGE_HEADER_INIT_VERSION':
3220                    if self.__Verify(Name, Value, 'UINT8'):
3221                        FmpData.Version = Value
3222                elif Name == 'IMAGE_INDEX':
3223                    if self.__Verify(Name, Value, 'UINT8'):
3224                        FmpData.ImageIndex = Value
3225                elif Name == 'HARDWARE_INSTANCE':
3226                    if self.__Verify(Name, Value, 'UINT8'):
3227                        FmpData.HardwareInstance = Value
3228                elif Name == 'MONOTONIC_COUNT':
3229                    if self.__Verify(Name, Value, 'UINT64'):
3230                        FmpData.MonotonicCount = Value
3231                        if FmpData.MonotonicCount.upper().startswith('0X'):
3232                            FmpData.MonotonicCount = (long)(FmpData.MonotonicCount, 16)
3233                        else:
3234                            FmpData.MonotonicCount = (long)(FmpData.MonotonicCount)
3235            if not self.__GetNextToken():
3236                break
3237        else:
3238            self.__UndoToken()
3239
3240        if (FmpData.MonotonicCount and not FmpData.Certificate_Guid) or (not FmpData.MonotonicCount and FmpData.Certificate_Guid):
3241            EdkLogger.error("FdfParser", FORMAT_INVALID, "CERTIFICATE_GUID and MONOTONIC_COUNT must be work as a pair.")
3242        # remove CERTIFICATE_GUID and MONOTONIC_COUNT from FmpKeyList, since these keys are optional
3243        if 'CERTIFICATE_GUID' in FmpKeyList:
3244            FmpKeyList.remove('CERTIFICATE_GUID')
3245        if 'MONOTONIC_COUNT' in FmpKeyList:
3246            FmpKeyList.remove('MONOTONIC_COUNT')
3247        if FmpKeyList:
3248            raise Warning("Missing keywords %s in FMP payload section." % ', '.join(FmpKeyList), self.FileName, self.CurrentLineNumber)
3249        # get the Image file and Vendor code file
3250        self.__GetFMPCapsuleData(FmpData)
3251        if not FmpData.ImageFile:
3252            raise Warning("Missing image file in FMP payload section.", self.FileName, self.CurrentLineNumber)
3253        # check whether more than one Vendor code file
3254        if len(FmpData.VendorCodeFile) > 1:
3255            raise Warning("At most one Image file and one Vendor code file are allowed in FMP payload section.", self.FileName, self.CurrentLineNumber)
3256        self.Profile.FmpPayloadDict[FmpUiName] = FmpData
3257        return True
3258
3259    ## __GetCapsule() method
3260    #
3261    #   Get capsule section contents and store its data into capsule list of self.Profile
3262    #
3263    #   @param  self        The object pointer
3264    #   @retval True        Successfully find a capsule
3265    #   @retval False       Not able to find a capsule
3266    #
3267    def __GetCapsule(self):
3268
3269        if not self.__GetNextToken():
3270            return False
3271
3272        S = self.__Token.upper()
3273        if S.startswith("[") and not S.startswith("[CAPSULE."):
3274            self.SectionParser(S)
3275            self.__UndoToken()
3276            return False
3277
3278        self.__UndoToken()
3279        if not self.__IsToken("[CAPSULE.", True):
3280            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
3281            #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
3282            #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
3283            raise Warning("expected [Capsule.]", self.FileName, self.CurrentLineNumber)
3284
3285        CapsuleObj = Capsule.Capsule()
3286
3287        CapsuleName = self.__GetUiName()
3288        if not CapsuleName:
3289            raise Warning("expected capsule name", self.FileName, self.CurrentLineNumber)
3290
3291        CapsuleObj.UiCapsuleName = CapsuleName.upper()
3292
3293        if not self.__IsToken( "]"):
3294            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
3295
3296        if self.__IsKeyword("CREATE_FILE"):
3297            if not self.__IsToken( "="):
3298                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3299
3300            if not self.__GetNextToken():
3301                raise Warning("expected file name", self.FileName, self.CurrentLineNumber)
3302
3303            CapsuleObj.CreateFile = self.__Token
3304
3305        self.__GetCapsuleStatements(CapsuleObj)
3306        self.Profile.CapsuleDict[CapsuleObj.UiCapsuleName] = CapsuleObj
3307        return True
3308
3309    ## __GetCapsuleStatements() method
3310    #
3311    #   Get statements for capsule
3312    #
3313    #   @param  self        The object pointer
3314    #   @param  Obj         for whom statements are got
3315    #
3316    def __GetCapsuleStatements(self, Obj):
3317        self.__GetCapsuleTokens(Obj)
3318        self.__GetDefineStatements(Obj)
3319        self.__GetSetStatements(Obj)
3320        self.__GetCapsuleData(Obj)
3321
3322    ## __GetCapsuleTokens() method
3323    #
3324    #   Get token statements for capsule
3325    #
3326    #   @param  self        The object pointer
3327    #   @param  Obj         for whom token statements are got
3328    #
3329    def __GetCapsuleTokens(self, Obj):
3330        if not self.__GetNextToken():
3331            return False
3332        while self.__Token in ("CAPSULE_GUID", "CAPSULE_HEADER_SIZE", "CAPSULE_FLAGS", "OEM_CAPSULE_FLAGS", "CAPSULE_HEADER_INIT_VERSION"):
3333            Name = self.__Token.strip()
3334            if not self.__IsToken("="):
3335                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3336            if not self.__GetNextToken():
3337                raise Warning("expected value", self.FileName, self.CurrentLineNumber)
3338            if Name == 'CAPSULE_FLAGS':
3339                if not self.__Token in ("PersistAcrossReset", "PopulateSystemTable", "InitiateReset"):
3340                    raise Warning("expected PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)
3341                Value = self.__Token.strip()
3342                while self.__IsToken(","):
3343                    Value += ','
3344                    if not self.__GetNextToken():
3345                        raise Warning("expected value", self.FileName, self.CurrentLineNumber)
3346                    if not self.__Token in ("PersistAcrossReset", "PopulateSystemTable", "InitiateReset"):
3347                        raise Warning("expected PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)
3348                    Value += self.__Token.strip()
3349            elif Name == 'OEM_CAPSULE_FLAGS':
3350                Value = self.__Token.strip()
3351                if not Value.upper().startswith('0X'):
3352                    raise Warning("expected hex value between 0x0000 and 0xFFFF", self.FileName, self.CurrentLineNumber)
3353                try:
3354                    Value = int(Value, 0)
3355                except ValueError:
3356                    raise Warning("expected hex value between 0x0000 and 0xFFFF", self.FileName, self.CurrentLineNumber)
3357                if not 0x0000 <= Value <= 0xFFFF:
3358                    raise Warning("expected hex value between 0x0000 and 0xFFFF", self.FileName, self.CurrentLineNumber)
3359                Value = self.__Token.strip()
3360            else:
3361                Value = self.__Token.strip()
3362            Obj.TokensDict[Name] = Value
3363            if not self.__GetNextToken():
3364                return False
3365        self.__UndoToken()
3366
3367    ## __GetCapsuleData() method
3368    #
3369    #   Get capsule data for capsule
3370    #
3371    #   @param  self        The object pointer
3372    #   @param  Obj         for whom capsule data are got
3373    #
3374    def __GetCapsuleData(self, Obj):
3375
3376        while True:
3377            IsInf = self.__GetInfStatement(Obj, True)
3378            IsFile = self.__GetFileStatement(Obj, True)
3379            IsFv = self.__GetFvStatement(Obj)
3380            IsFd = self.__GetFdStatement(Obj)
3381            IsAnyFile = self.__GetAnyFileStatement(Obj)
3382            IsAfile = self.__GetAfileStatement(Obj)
3383            IsFmp = self.__GetFmpStatement(Obj)
3384            if not (IsInf or IsFile or IsFv or IsFd or IsAnyFile or IsAfile or IsFmp):
3385                break
3386
3387    ## __GetFMPCapsuleData() method
3388    #
3389    #   Get capsule data for FMP capsule
3390    #
3391    #   @param  self        The object pointer
3392    #   @param  Obj         for whom capsule data are got
3393    #
3394    def __GetFMPCapsuleData(self, Obj):
3395
3396        while True:
3397            IsFv = self.__GetFvStatement(Obj, True)
3398            IsFd = self.__GetFdStatement(Obj, True)
3399            IsAnyFile = self.__GetAnyFileStatement(Obj, True)
3400            if not (IsFv or IsFd or IsAnyFile):
3401                break
3402
3403    ## __GetFvStatement() method
3404    #
3405    #   Get FV for capsule
3406    #
3407    #   @param  self        The object pointer
3408    #   @param  CapsuleObj  for whom FV is got
3409    #   @retval True        Successfully find a FV statement
3410    #   @retval False       Not able to find a FV statement
3411    #
3412    def __GetFvStatement(self, CapsuleObj, FMPCapsule = False):
3413
3414        if not self.__IsKeyword("FV"):
3415            return False
3416
3417        if not self.__IsToken("="):
3418            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3419
3420        if not self.__GetNextToken():
3421            raise Warning("expected FV name", self.FileName, self.CurrentLineNumber)
3422
3423        if self.__Token.upper() not in self.Profile.FvDict.keys():
3424            raise Warning("FV name does not exist", self.FileName, self.CurrentLineNumber)
3425
3426        CapsuleFv = CapsuleData.CapsuleFv()
3427        CapsuleFv.FvName = self.__Token
3428        if FMPCapsule:
3429            if not CapsuleObj.ImageFile:
3430                CapsuleObj.ImageFile.append(CapsuleFv)
3431            else:
3432                CapsuleObj.VendorCodeFile.append(CapsuleFv)
3433        else:
3434            CapsuleObj.CapsuleDataList.append(CapsuleFv)
3435        return True
3436
3437    ## __GetFdStatement() method
3438    #
3439    #   Get FD for capsule
3440    #
3441    #   @param  self        The object pointer
3442    #   @param  CapsuleObj  for whom FD is got
3443    #   @retval True        Successfully find a FD statement
3444    #   @retval False       Not able to find a FD statement
3445    #
3446    def __GetFdStatement(self, CapsuleObj, FMPCapsule = False):
3447
3448        if not self.__IsKeyword("FD"):
3449            return False
3450
3451        if not self.__IsToken("="):
3452            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3453
3454        if not self.__GetNextToken():
3455            raise Warning("expected FD name", self.FileName, self.CurrentLineNumber)
3456
3457        if self.__Token.upper() not in self.Profile.FdDict.keys():
3458            raise Warning("FD name does not exist", self.FileName, self.CurrentLineNumber)
3459
3460        CapsuleFd = CapsuleData.CapsuleFd()
3461        CapsuleFd.FdName = self.__Token
3462        if FMPCapsule:
3463            if not CapsuleObj.ImageFile:
3464                CapsuleObj.ImageFile.append(CapsuleFd)
3465            else:
3466                CapsuleObj.VendorCodeFile.append(CapsuleFd)
3467        else:
3468            CapsuleObj.CapsuleDataList.append(CapsuleFd)
3469        return True
3470
3471    def __GetFmpStatement(self, CapsuleObj):
3472        if not self.__IsKeyword("FMP_PAYLOAD"):
3473            if not self.__IsKeyword("FMP"):
3474                return False
3475
3476            if not self.__IsKeyword("PAYLOAD"):
3477                self.__UndoToken()
3478                return False
3479
3480        if not self.__IsToken("="):
3481            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3482
3483        if not self.__GetNextToken():
3484            raise Warning("expected payload name after FMP_PAYLOAD =", self.FileName, self.CurrentLineNumber)
3485        Payload = self.__Token.upper()
3486        if Payload not in self.Profile.FmpPayloadDict:
3487            raise Warning("This FMP Payload does not exist: %s" % self.__Token, self.FileName, self.CurrentLineNumber)
3488        CapsuleObj.FmpPayloadList.append(self.Profile.FmpPayloadDict[Payload])
3489        return True
3490
3491    def __ParseRawFileStatement(self):
3492        if not self.__IsKeyword("FILE"):
3493            return None
3494
3495        if not self.__IsKeyword("DATA"):
3496            self.__UndoToken()
3497            return None
3498
3499        if not self.__IsToken("="):
3500            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3501
3502        if not self.__GetNextToken():
3503            raise Warning("expected File name", self.FileName, self.CurrentLineNumber)
3504
3505        AnyFileName = self.__Token
3506        self.__VerifyFile(AnyFileName)
3507
3508        if not os.path.isabs(AnyFileName):
3509            AnyFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, AnyFileName)
3510
3511        return AnyFileName
3512
3513    ## __GetAnyFileStatement() method
3514    #
3515    #   Get AnyFile for capsule
3516    #
3517    #   @param  self        The object pointer
3518    #   @param  CapsuleObj  for whom AnyFile is got
3519    #   @retval True        Successfully find a Anyfile statement
3520    #   @retval False       Not able to find a AnyFile statement
3521    #
3522    def __GetAnyFileStatement(self, CapsuleObj, FMPCapsule = False):
3523        AnyFileName = self.__ParseRawFileStatement()
3524        if not AnyFileName:
3525            return False
3526
3527        CapsuleAnyFile = CapsuleData.CapsuleAnyFile()
3528        CapsuleAnyFile.FileName = AnyFileName
3529        if FMPCapsule:
3530            if not CapsuleObj.ImageFile:
3531                CapsuleObj.ImageFile.append(CapsuleAnyFile)
3532            else:
3533                CapsuleObj.VendorCodeFile.append(CapsuleAnyFile)
3534        else:
3535            CapsuleObj.CapsuleDataList.append(CapsuleAnyFile)
3536        return True
3537
3538    ## __GetAfileStatement() method
3539    #
3540    #   Get Afile for capsule
3541    #
3542    #   @param  self        The object pointer
3543    #   @param  CapsuleObj  for whom Afile is got
3544    #   @retval True        Successfully find a Afile statement
3545    #   @retval False       Not able to find a Afile statement
3546    #
3547    def __GetAfileStatement(self, CapsuleObj):
3548
3549        if not self.__IsKeyword("APPEND"):
3550            return False
3551
3552        if not self.__IsToken("="):
3553            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3554
3555        if not self.__GetNextToken():
3556            raise Warning("expected Afile name", self.FileName, self.CurrentLineNumber)
3557
3558        AfileName = self.__Token
3559        AfileBaseName = os.path.basename(AfileName)
3560
3561        if os.path.splitext(AfileBaseName)[1]  not in [".bin",".BIN",".Bin",".dat",".DAT",".Dat",".data",".DATA",".Data"]:
3562            raise Warning('invalid binary file type, should be one of "bin","BIN","Bin","dat","DAT","Dat","data","DATA","Data"', \
3563                          self.FileName, self.CurrentLineNumber)
3564
3565        if not os.path.isabs(AfileName):
3566            AfileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(AfileName)
3567            self.__VerifyFile(AfileName)
3568        else:
3569            if not os.path.exists(AfileName):
3570                raise Warning('%s does not exist' % AfileName, self.FileName, self.CurrentLineNumber)
3571            else:
3572                pass
3573
3574        CapsuleAfile = CapsuleData.CapsuleAfile()
3575        CapsuleAfile.FileName = AfileName
3576        CapsuleObj.CapsuleDataList.append(CapsuleAfile)
3577        return True
3578
3579    ## __GetRule() method
3580    #
3581    #   Get Rule section contents and store its data into rule list of self.Profile
3582    #
3583    #   @param  self        The object pointer
3584    #   @retval True        Successfully find a Rule
3585    #   @retval False       Not able to find a Rule
3586    #
3587    def __GetRule(self):
3588
3589        if not self.__GetNextToken():
3590            return False
3591
3592        S = self.__Token.upper()
3593        if S.startswith("[") and not S.startswith("[RULE."):
3594            self.SectionParser(S)
3595            self.__UndoToken()
3596            return False
3597        self.__UndoToken()
3598        if not self.__IsToken("[Rule.", True):
3599            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
3600            #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
3601            #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
3602            raise Warning("expected [Rule.]", self.FileName, self.CurrentLineNumber)
3603
3604        if not self.__SkipToToken("."):
3605            raise Warning("expected '.'", self.FileName, self.CurrentLineNumber)
3606
3607        Arch = self.__SkippedChars.rstrip(".")
3608        if Arch.upper() not in ("IA32", "X64", "IPF", "EBC", "ARM", "AARCH64", "COMMON"):
3609            raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber)
3610
3611        ModuleType = self.__GetModuleType()
3612
3613        TemplateName = ""
3614        if self.__IsToken("."):
3615            if not self.__GetNextWord():
3616                raise Warning("expected template name", self.FileName, self.CurrentLineNumber)
3617            TemplateName = self.__Token
3618
3619        if not self.__IsToken( "]"):
3620            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
3621
3622        RuleObj = self.__GetRuleFileStatements()
3623        RuleObj.Arch = Arch.upper()
3624        RuleObj.ModuleType = ModuleType
3625        RuleObj.TemplateName = TemplateName
3626        if TemplateName == '' :
3627            self.Profile.RuleDict['RULE'             + \
3628                              '.'                    + \
3629                              Arch.upper()           + \
3630                              '.'                    + \
3631                              ModuleType.upper()     ] = RuleObj
3632        else :
3633            self.Profile.RuleDict['RULE'             + \
3634                              '.'                    + \
3635                              Arch.upper()           + \
3636                              '.'                    + \
3637                              ModuleType.upper()     + \
3638                              '.'                    + \
3639                              TemplateName.upper() ] = RuleObj
3640#        self.Profile.RuleList.append(rule)
3641        return True
3642
3643    ## __GetModuleType() method
3644    #
3645    #   Return the module type
3646    #
3647    #   @param  self        The object pointer
3648    #   @retval string      module type
3649    #
3650    def __GetModuleType(self):
3651
3652        if not self.__GetNextWord():
3653            raise Warning("expected Module type", self.FileName, self.CurrentLineNumber)
3654        if self.__Token.upper() not in ("SEC", "PEI_CORE", "PEIM", "DXE_CORE", \
3655                             "DXE_DRIVER", "DXE_SAL_DRIVER", \
3656                             "DXE_SMM_DRIVER", "DXE_RUNTIME_DRIVER", \
3657                             "UEFI_DRIVER", "UEFI_APPLICATION", "USER_DEFINED", "DEFAULT", "BASE", \
3658                             "SECURITY_CORE", "COMBINED_PEIM_DRIVER", "PIC_PEIM", "RELOCATABLE_PEIM", \
3659                             "PE32_PEIM", "BS_DRIVER", "RT_DRIVER", "SAL_RT_DRIVER", "APPLICATION", "ACPITABLE", "SMM_CORE"):
3660            raise Warning("Unknown Module type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3661        return self.__Token
3662
3663    ## __GetFileExtension() method
3664    #
3665    #   Return the file extension
3666    #
3667    #   @param  self        The object pointer
3668    #   @retval string      file name extension
3669    #
3670    def __GetFileExtension(self):
3671        if not self.__IsToken("."):
3672            raise Warning("expected '.'", self.FileName, self.CurrentLineNumber)
3673
3674        Ext = ""
3675        if self.__GetNextToken():
3676            Pattern = re.compile(r'([a-zA-Z][a-zA-Z0-9]*)')
3677            if Pattern.match(self.__Token):
3678                Ext = self.__Token
3679                return '.' + Ext
3680            else:
3681                raise Warning("Unknown file extension '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3682
3683        else:
3684            raise Warning("expected file extension", self.FileName, self.CurrentLineNumber)
3685
3686    ## __GetRuleFileStatement() method
3687    #
3688    #   Get rule contents
3689    #
3690    #   @param  self        The object pointer
3691    #   @retval Rule        Rule object
3692    #
3693    def __GetRuleFileStatements(self):
3694
3695        if not self.__IsKeyword("FILE"):
3696            raise Warning("expected FILE", self.FileName, self.CurrentLineNumber)
3697
3698        if not self.__GetNextWord():
3699            raise Warning("expected FFS type", self.FileName, self.CurrentLineNumber)
3700
3701        Type = self.__Token.strip().upper()
3702        if Type not in ("RAW", "FREEFORM", "SEC", "PEI_CORE", "PEIM",\
3703                             "PEI_DXE_COMBO", "DRIVER", "DXE_CORE", "APPLICATION", "FV_IMAGE", "SMM", "SMM_CORE"):
3704            raise Warning("Unknown FV type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3705
3706        if not self.__IsToken("="):
3707            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3708
3709        if not self.__IsKeyword("$(NAMED_GUID)"):
3710            if not self.__GetNextWord():
3711                raise Warning("expected $(NAMED_GUID)", self.FileName, self.CurrentLineNumber)
3712            if self.__Token == 'PCD':
3713                if not self.__IsToken( "("):
3714                    raise Warning("expected '('", self.FileName, self.CurrentLineNumber)
3715                PcdPair = self.__GetNextPcdName()
3716                if not self.__IsToken( ")"):
3717                    raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
3718                self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')'
3719
3720        NameGuid = self.__Token
3721
3722        KeepReloc = None
3723        if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
3724            if self.__FileCouldHaveRelocFlag(Type):
3725                if self.__Token == 'RELOCS_STRIPPED':
3726                    KeepReloc = False
3727                else:
3728                    KeepReloc = True
3729            else:
3730                raise Warning("File type %s could not have reloc strip flag%d" % (Type, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3731
3732        KeyStringList = []
3733        if self.__GetNextToken():
3734            Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
3735            if Pattern.match(self.__Token):
3736                KeyStringList.append(self.__Token)
3737                if self.__IsToken(","):
3738                    while self.__GetNextToken():
3739                        if not Pattern.match(self.__Token):
3740                            raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
3741                        KeyStringList.append(self.__Token)
3742
3743                        if not self.__IsToken(","):
3744                            break
3745
3746            else:
3747                self.__UndoToken()
3748
3749
3750        Fixed = False
3751        if self.__IsKeyword("Fixed", True):
3752            Fixed = True
3753
3754        CheckSum = False
3755        if self.__IsKeyword("CheckSum", True):
3756            CheckSum = True
3757
3758        AlignValue = ""
3759        if self.__GetAlignment():
3760            if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
3761                raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3762            #For FFS, Auto is default option same to ""
3763            if not self.__Token == "Auto":
3764                AlignValue = self.__Token
3765
3766        if self.__IsToken("{"):
3767            # Complex file rule expected
3768            Rule = RuleComplexFile.RuleComplexFile()
3769            Rule.FvFileType = Type
3770            Rule.NameGuid = NameGuid
3771            Rule.Alignment = AlignValue
3772            Rule.CheckSum = CheckSum
3773            Rule.Fixed = Fixed
3774            Rule.KeyStringList = KeyStringList
3775            if KeepReloc != None:
3776                Rule.KeepReloc = KeepReloc
3777
3778            while True:
3779                IsEncapsulate = self.__GetRuleEncapsulationSection(Rule)
3780                IsLeaf = self.__GetEfiSection(Rule)
3781                if not IsEncapsulate and not IsLeaf:
3782                    break
3783
3784            if not self.__IsToken("}"):
3785                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
3786
3787            return Rule
3788
3789        else:
3790            # Simple file rule expected
3791            if not self.__GetNextWord():
3792                raise Warning("expected leaf section type", self.FileName, self.CurrentLineNumber)
3793
3794            SectionName = self.__Token
3795
3796            if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
3797                                    "UI", "PEI_DEPEX", "VERSION", "SUBTYPE_GUID", "SMM_DEPEX"):
3798                raise Warning("Unknown leaf section name '%s'" % SectionName, self.FileName, self.CurrentLineNumber)
3799
3800
3801            if self.__IsKeyword("Fixed", True):
3802                Fixed = True
3803
3804            if self.__IsKeyword("CheckSum", True):
3805                CheckSum = True
3806
3807            SectAlignment = ""
3808            if self.__GetAlignment():
3809                if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
3810                    raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3811                if self.__Token == 'Auto' and (not SectionName == 'PE32') and (not SectionName == 'TE'):
3812                    raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
3813                SectAlignment = self.__Token
3814
3815            Ext = None
3816            if self.__IsToken('|'):
3817                Ext = self.__GetFileExtension()
3818            elif not self.__GetNextToken():
3819                raise Warning("expected File name", self.FileName, self.CurrentLineNumber)
3820
3821            Rule = RuleSimpleFile.RuleSimpleFile()
3822            Rule.SectionType = SectionName
3823            Rule.FvFileType = Type
3824            Rule.NameGuid = NameGuid
3825            Rule.Alignment = AlignValue
3826            Rule.SectAlignment = SectAlignment
3827            Rule.CheckSum = CheckSum
3828            Rule.Fixed = Fixed
3829            Rule.KeyStringList = KeyStringList
3830            if KeepReloc != None:
3831                Rule.KeepReloc = KeepReloc
3832            Rule.FileExtension = Ext
3833            Rule.FileName = self.__Token
3834            return Rule
3835
3836    ## __GetEfiSection() method
3837    #
3838    #   Get section list for Rule
3839    #
3840    #   @param  self        The object pointer
3841    #   @param  Obj         for whom section is got
3842    #   @retval True        Successfully find section statement
3843    #   @retval False       Not able to find section statement
3844    #
3845    def __GetEfiSection(self, Obj):
3846
3847        OldPos = self.GetFileBufferPos()
3848        if not self.__GetNextWord():
3849            return False
3850        SectionName = self.__Token
3851
3852        if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
3853                               "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"):
3854            self.__UndoToken()
3855            return False
3856
3857        if SectionName == "FV_IMAGE":
3858            FvImageSectionObj = FvImageSection.FvImageSection()
3859            if self.__IsKeyword("FV_IMAGE"):
3860                pass
3861            if self.__IsToken( "{"):
3862                FvObj = Fv.FV()
3863                self.__GetDefineStatements(FvObj)
3864                self.__GetBlockStatement(FvObj)
3865                self.__GetSetStatements(FvObj)
3866                self.__GetFvAlignment(FvObj)
3867                self.__GetFvAttributes(FvObj)
3868                self.__GetAprioriSection(FvObj)
3869                self.__GetAprioriSection(FvObj)
3870
3871                while True:
3872                    IsInf = self.__GetInfStatement(FvObj)
3873                    IsFile = self.__GetFileStatement(FvObj)
3874                    if not IsInf and not IsFile:
3875                        break
3876
3877                if not self.__IsToken( "}"):
3878                    raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
3879                FvImageSectionObj.Fv = FvObj
3880                FvImageSectionObj.FvName = None
3881
3882            else:
3883                if not self.__IsKeyword("FV"):
3884                    raise Warning("expected 'FV'", self.FileName, self.CurrentLineNumber)
3885                FvImageSectionObj.FvFileType = self.__Token
3886
3887                if self.__GetAlignment():
3888                    if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
3889                        raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3890                    FvImageSectionObj.Alignment = self.__Token
3891
3892                if self.__IsToken('|'):
3893                    FvImageSectionObj.FvFileExtension = self.__GetFileExtension()
3894                elif self.__GetNextToken():
3895                    if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
3896                               "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"):
3897                        FvImageSectionObj.FvFileName = self.__Token
3898                    else:
3899                        self.__UndoToken()
3900                else:
3901                    raise Warning("expected FV file name", self.FileName, self.CurrentLineNumber)
3902
3903            Obj.SectionList.append(FvImageSectionObj)
3904            return True
3905
3906        EfiSectionObj = EfiSection.EfiSection()
3907        EfiSectionObj.SectionType = SectionName
3908
3909        if not self.__GetNextToken():
3910            raise Warning("expected file type", self.FileName, self.CurrentLineNumber)
3911
3912        if self.__Token == "STRING":
3913            if not self.__RuleSectionCouldHaveString(EfiSectionObj.SectionType):
3914                raise Warning("%s section could NOT have string data%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3915
3916            if not self.__IsToken('='):
3917                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3918
3919            if not self.__GetNextToken():
3920                raise Warning("expected Quoted String", self.FileName, self.CurrentLineNumber)
3921
3922            if self.__GetStringData():
3923                EfiSectionObj.StringData = self.__Token
3924
3925            if self.__IsKeyword("BUILD_NUM"):
3926                if not self.__RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
3927                    raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3928
3929                if not self.__IsToken("="):
3930                    raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3931                if not self.__GetNextToken():
3932                    raise Warning("expected Build number", self.FileName, self.CurrentLineNumber)
3933                EfiSectionObj.BuildNum = self.__Token
3934
3935        else:
3936            EfiSectionObj.FileType = self.__Token
3937            self.__CheckRuleSectionFileType(EfiSectionObj.SectionType, EfiSectionObj.FileType)
3938
3939        if self.__IsKeyword("Optional"):
3940            if not self.__RuleSectionCouldBeOptional(EfiSectionObj.SectionType):
3941                raise Warning("%s section could NOT be optional%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3942            EfiSectionObj.Optional = True
3943
3944            if self.__IsKeyword("BUILD_NUM"):
3945                if not self.__RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
3946                    raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3947
3948                if not self.__IsToken("="):
3949                    raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3950                if not self.__GetNextToken():
3951                    raise Warning("expected Build number", self.FileName, self.CurrentLineNumber)
3952                EfiSectionObj.BuildNum = self.__Token
3953
3954        if self.__GetAlignment():
3955            if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
3956                raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3957            if self.__Token == 'Auto' and (not SectionName == 'PE32') and (not SectionName == 'TE'):
3958                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
3959            EfiSectionObj.Alignment = self.__Token
3960
3961        if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
3962            if self.__SectionCouldHaveRelocFlag(EfiSectionObj.SectionType):
3963                if self.__Token == 'RELOCS_STRIPPED':
3964                    EfiSectionObj.KeepReloc = False
3965                else:
3966                    EfiSectionObj.KeepReloc = True
3967                if Obj.KeepReloc != None and Obj.KeepReloc != EfiSectionObj.KeepReloc:
3968                    raise Warning("Section type %s has reloc strip flag conflict with Rule" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber)
3969            else:
3970                raise Warning("Section type %s could not have reloc strip flag" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber)
3971
3972
3973        if self.__IsToken('|'):
3974            EfiSectionObj.FileExtension = self.__GetFileExtension()
3975        elif self.__GetNextToken():
3976            if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
3977                       "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"):
3978
3979                if self.__Token.startswith('PCD'):
3980                    self.__UndoToken()
3981                    self.__GetNextWord()
3982
3983                    if self.__Token == 'PCD':
3984                        if not self.__IsToken( "("):
3985                            raise Warning("expected '('", self.FileName, self.CurrentLineNumber)
3986                        PcdPair = self.__GetNextPcdName()
3987                        if not self.__IsToken( ")"):
3988                            raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
3989                        self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')'
3990
3991                EfiSectionObj.FileName = self.__Token
3992
3993            else:
3994                self.__UndoToken()
3995        else:
3996            raise Warning("expected section file name", self.FileName, self.CurrentLineNumber)
3997
3998        Obj.SectionList.append(EfiSectionObj)
3999        return True
4000
4001    ## __RuleSectionCouldBeOptional() method
4002    #
4003    #   Get whether a section could be optional
4004    #
4005    #   @param  self        The object pointer
4006    #   @param  SectionType The section type to check
4007    #   @retval True        section could be optional
4008    #   @retval False       section never optional
4009    #
4010    def __RuleSectionCouldBeOptional(self, SectionType):
4011        if SectionType in ("DXE_DEPEX", "UI", "VERSION", "PEI_DEPEX", "RAW", "SMM_DEPEX"):
4012            return True
4013        else:
4014            return False
4015
4016    ## __RuleSectionCouldHaveBuildNum() method
4017    #
4018    #   Get whether a section could have build number information
4019    #
4020    #   @param  self        The object pointer
4021    #   @param  SectionType The section type to check
4022    #   @retval True        section could have build number information
4023    #   @retval False       section never have build number information
4024    #
4025    def __RuleSectionCouldHaveBuildNum(self, SectionType):
4026        if SectionType in ("VERSION"):
4027            return True
4028        else:
4029            return False
4030
4031    ## __RuleSectionCouldHaveString() method
4032    #
4033    #   Get whether a section could have string
4034    #
4035    #   @param  self        The object pointer
4036    #   @param  SectionType The section type to check
4037    #   @retval True        section could have string
4038    #   @retval False       section never have string
4039    #
4040    def __RuleSectionCouldHaveString(self, SectionType):
4041        if SectionType in ("UI", "VERSION"):
4042            return True
4043        else:
4044            return False
4045
4046    ## __CheckRuleSectionFileType() method
4047    #
4048    #   Get whether a section matches a file type
4049    #
4050    #   @param  self        The object pointer
4051    #   @param  SectionType The section type to check
4052    #   @param  FileType    The file type to check
4053    #
4054    def __CheckRuleSectionFileType(self, SectionType, FileType):
4055        if SectionType == "COMPAT16":
4056            if FileType not in ("COMPAT16", "SEC_COMPAT16"):
4057                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4058        elif SectionType == "PE32":
4059            if FileType not in ("PE32", "SEC_PE32"):
4060                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4061        elif SectionType == "PIC":
4062            if FileType not in ("PIC", "PIC"):
4063                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4064        elif SectionType == "TE":
4065            if FileType not in ("TE", "SEC_TE"):
4066                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4067        elif SectionType == "RAW":
4068            if FileType not in ("BIN", "SEC_BIN", "RAW", "ASL", "ACPI"):
4069                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4070        elif SectionType == "DXE_DEPEX" or SectionType == "SMM_DEPEX":
4071            if FileType not in ("DXE_DEPEX", "SEC_DXE_DEPEX", "SMM_DEPEX"):
4072                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4073        elif SectionType == "UI":
4074            if FileType not in ("UI", "SEC_UI"):
4075                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4076        elif SectionType == "VERSION":
4077            if FileType not in ("VERSION", "SEC_VERSION"):
4078                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4079        elif SectionType == "PEI_DEPEX":
4080            if FileType not in ("PEI_DEPEX", "SEC_PEI_DEPEX"):
4081                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4082        elif SectionType == "GUID":
4083            if FileType not in ("PE32", "SEC_GUID"):
4084                raise Warning("Incorrect section file type '%s'" % FileType, self.FileName, self.CurrentLineNumber)
4085
4086    ## __GetRuleEncapsulationSection() method
4087    #
4088    #   Get encapsulation section for Rule
4089    #
4090    #   @param  self        The object pointer
4091    #   @param  Rule        for whom section is got
4092    #   @retval True        Successfully find section statement
4093    #   @retval False       Not able to find section statement
4094    #
4095    def __GetRuleEncapsulationSection(self, Rule):
4096
4097        if self.__IsKeyword( "COMPRESS"):
4098            Type = "PI_STD"
4099            if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"):
4100                Type = self.__Token
4101
4102            if not self.__IsToken("{"):
4103                raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
4104
4105            CompressSectionObj = CompressSection.CompressSection()
4106
4107            CompressSectionObj.CompType = Type
4108            # Recursive sections...
4109            while True:
4110                IsEncapsulate = self.__GetRuleEncapsulationSection(CompressSectionObj)
4111                IsLeaf = self.__GetEfiSection(CompressSectionObj)
4112                if not IsEncapsulate and not IsLeaf:
4113                    break
4114
4115            if not self.__IsToken( "}"):
4116                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
4117            Rule.SectionList.append(CompressSectionObj)
4118
4119            return True
4120
4121        elif self.__IsKeyword( "GUIDED"):
4122            GuidValue = None
4123            if self.__GetNextGuid():
4124                GuidValue = self.__Token
4125
4126            if self.__IsKeyword( "$(NAMED_GUID)"):
4127                GuidValue = self.__Token
4128
4129            AttribDict = self.__GetGuidAttrib()
4130
4131            if not self.__IsToken("{"):
4132                raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
4133            GuidSectionObj = GuidSection.GuidSection()
4134            GuidSectionObj.NameGuid = GuidValue
4135            GuidSectionObj.SectionType = "GUIDED"
4136            GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
4137            GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
4138            GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
4139
4140            # Efi sections...
4141            while True:
4142                IsEncapsulate = self.__GetRuleEncapsulationSection(GuidSectionObj)
4143                IsLeaf = self.__GetEfiSection(GuidSectionObj)
4144                if not IsEncapsulate and not IsLeaf:
4145                    break
4146
4147            if not self.__IsToken( "}"):
4148                raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
4149            Rule.SectionList.append(GuidSectionObj)
4150
4151            return True
4152
4153        return False
4154
4155    ## __GetVtf() method
4156    #
4157    #   Get VTF section contents and store its data into VTF list of self.Profile
4158    #
4159    #   @param  self        The object pointer
4160    #   @retval True        Successfully find a VTF
4161    #   @retval False       Not able to find a VTF
4162    #
4163    def __GetVtf(self):
4164
4165        if not self.__GetNextToken():
4166            return False
4167
4168        S = self.__Token.upper()
4169        if S.startswith("[") and not S.startswith("[VTF."):
4170            self.SectionParser(S)
4171            self.__UndoToken()
4172            return False
4173
4174        self.__UndoToken()
4175        if not self.__IsToken("[VTF.", True):
4176            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
4177            #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
4178            #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
4179            raise Warning("expected [VTF.]", self.FileName, self.CurrentLineNumber)
4180
4181        if not self.__SkipToToken("."):
4182            raise Warning("expected '.'", self.FileName, self.CurrentLineNumber)
4183
4184        Arch = self.__SkippedChars.rstrip(".").upper()
4185        if Arch not in ("IA32", "X64", "IPF", "ARM", "AARCH64"):
4186            raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber)
4187
4188        if not self.__GetNextWord():
4189            raise Warning("expected VTF name", self.FileName, self.CurrentLineNumber)
4190        Name = self.__Token.upper()
4191
4192        VtfObj = Vtf.Vtf()
4193        VtfObj.UiName = Name
4194        VtfObj.KeyArch = Arch
4195
4196        if self.__IsToken(","):
4197            if not self.__GetNextWord():
4198                raise Warning("expected Arch list", self.FileName, self.CurrentLineNumber)
4199            if self.__Token.upper() not in ("IA32", "X64", "IPF", "ARM", "AARCH64"):
4200                raise Warning("Unknown Arch '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
4201            VtfObj.ArchList = self.__Token.upper()
4202
4203        if not self.__IsToken( "]"):
4204            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
4205
4206        if self.__IsKeyword("IA32_RST_BIN"):
4207            if not self.__IsToken("="):
4208                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4209
4210            if not self.__GetNextToken():
4211                raise Warning("expected Reset file", self.FileName, self.CurrentLineNumber)
4212
4213            VtfObj.ResetBin = self.__Token
4214            if VtfObj.ResetBin.replace('$(WORKSPACE)', '').find('$') == -1:
4215                #check for file path
4216                ErrorCode, ErrorInfo = PathClass(NormPath(VtfObj.ResetBin), GenFdsGlobalVariable.WorkSpaceDir).Validate()
4217                if ErrorCode != 0:
4218                    EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
4219
4220        while self.__GetComponentStatement(VtfObj):
4221            pass
4222
4223        self.Profile.VtfList.append(VtfObj)
4224        return True
4225
4226    ## __GetComponentStatement() method
4227    #
4228    #   Get components in VTF
4229    #
4230    #   @param  self        The object pointer
4231    #   @param  VtfObj         for whom component is got
4232    #   @retval True        Successfully find a component
4233    #   @retval False       Not able to find a component
4234    #
4235    def __GetComponentStatement(self, VtfObj):
4236
4237        if not self.__IsKeyword("COMP_NAME"):
4238            return False
4239
4240        if not self.__IsToken("="):
4241            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4242
4243        if not self.__GetNextWord():
4244            raise Warning("expected Component Name", self.FileName, self.CurrentLineNumber)
4245
4246        CompStatementObj = ComponentStatement.ComponentStatement()
4247        CompStatementObj.CompName = self.__Token
4248
4249        if not self.__IsKeyword("COMP_LOC"):
4250            raise Warning("expected COMP_LOC", self.FileName, self.CurrentLineNumber)
4251
4252        if not self.__IsToken("="):
4253            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4254
4255        CompStatementObj.CompLoc = ""
4256        if self.__GetNextWord():
4257            CompStatementObj.CompLoc = self.__Token
4258            if self.__IsToken('|'):
4259                if not self.__GetNextWord():
4260                    raise Warning("Expected Region Name", self.FileName, self.CurrentLineNumber)
4261
4262                if self.__Token not in ("F", "N", "S"):    #, "H", "L", "PH", "PL"): not support
4263                    raise Warning("Unknown location type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
4264
4265                CompStatementObj.FilePos = self.__Token
4266        else:
4267            self.CurrentLineNumber += 1
4268            self.CurrentOffsetWithinLine = 0
4269
4270        if not self.__IsKeyword("COMP_TYPE"):
4271            raise Warning("expected COMP_TYPE", self.FileName, self.CurrentLineNumber)
4272
4273        if not self.__IsToken("="):
4274            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4275
4276        if not self.__GetNextToken():
4277            raise Warning("expected Component type", self.FileName, self.CurrentLineNumber)
4278        if self.__Token not in ("FIT", "PAL_B", "PAL_A", "OEM"):
4279            if not self.__Token.startswith("0x") or len(self.__Token) < 3 or len(self.__Token) > 4 or \
4280                not self.__HexDigit(self.__Token[2]) or not self.__HexDigit(self.__Token[-1]):
4281                raise Warning("Unknown location type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
4282        CompStatementObj.CompType = self.__Token
4283
4284        if not self.__IsKeyword("COMP_VER"):
4285            raise Warning("expected COMP_VER", self.FileName, self.CurrentLineNumber)
4286
4287        if not self.__IsToken("="):
4288            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4289
4290        if not self.__GetNextToken():
4291            raise Warning("expected Component version", self.FileName, self.CurrentLineNumber)
4292
4293        Pattern = re.compile('-$|[0-9a-fA-F]{1,2}\.[0-9a-fA-F]{1,2}$', re.DOTALL)
4294        if Pattern.match(self.__Token) == None:
4295            raise Warning("Unknown version format '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
4296        CompStatementObj.CompVer = self.__Token
4297
4298        if not self.__IsKeyword("COMP_CS"):
4299            raise Warning("expected COMP_CS", self.FileName, self.CurrentLineNumber)
4300
4301        if not self.__IsToken("="):
4302            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4303
4304        if not self.__GetNextToken():
4305            raise Warning("expected Component CS", self.FileName, self.CurrentLineNumber)
4306        if self.__Token not in ("1", "0"):
4307            raise Warning("Unknown  Component CS '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
4308        CompStatementObj.CompCs = self.__Token
4309
4310
4311        if not self.__IsKeyword("COMP_BIN"):
4312            raise Warning("expected COMP_BIN", self.FileName, self.CurrentLineNumber)
4313
4314        if not self.__IsToken("="):
4315            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4316
4317        if not self.__GetNextToken():
4318            raise Warning("expected Component file", self.FileName, self.CurrentLineNumber)
4319
4320        CompStatementObj.CompBin = self.__Token
4321        if CompStatementObj.CompBin != '-' and CompStatementObj.CompBin.replace('$(WORKSPACE)', '').find('$') == -1:
4322            #check for file path
4323            ErrorCode, ErrorInfo = PathClass(NormPath(CompStatementObj.CompBin), GenFdsGlobalVariable.WorkSpaceDir).Validate()
4324            if ErrorCode != 0:
4325                EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
4326
4327        if not self.__IsKeyword("COMP_SYM"):
4328            raise Warning("expected COMP_SYM", self.FileName, self.CurrentLineNumber)
4329
4330        if not self.__IsToken("="):
4331            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4332
4333        if not self.__GetNextToken():
4334            raise Warning("expected Component symbol file", self.FileName, self.CurrentLineNumber)
4335
4336        CompStatementObj.CompSym = self.__Token
4337        if CompStatementObj.CompSym != '-' and CompStatementObj.CompSym.replace('$(WORKSPACE)', '').find('$') == -1:
4338            #check for file path
4339            ErrorCode, ErrorInfo = PathClass(NormPath(CompStatementObj.CompSym), GenFdsGlobalVariable.WorkSpaceDir).Validate()
4340            if ErrorCode != 0:
4341                EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
4342
4343        if not self.__IsKeyword("COMP_SIZE"):
4344            raise Warning("expected COMP_SIZE", self.FileName, self.CurrentLineNumber)
4345
4346        if not self.__IsToken("="):
4347            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4348
4349        if self.__IsToken("-"):
4350            CompStatementObj.CompSize = self.__Token
4351        elif self.__GetNextDecimalNumber():
4352            CompStatementObj.CompSize = self.__Token
4353        elif self.__GetNextHexNumber():
4354            CompStatementObj.CompSize = self.__Token
4355        else:
4356            raise Warning("Unknown size '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
4357
4358        VtfObj.ComponentStatementList.append(CompStatementObj)
4359        return True
4360
4361    ## __GetOptionRom() method
4362    #
4363    #   Get OptionROM section contents and store its data into OptionROM list of self.Profile
4364    #
4365    #   @param  self        The object pointer
4366    #   @retval True        Successfully find a OptionROM
4367    #   @retval False       Not able to find a OptionROM
4368    #
4369    def __GetOptionRom(self):
4370
4371        if not self.__GetNextToken():
4372            return False
4373
4374        S = self.__Token.upper()
4375        if S.startswith("[") and not S.startswith("[OPTIONROM."):
4376            self.SectionParser(S)
4377            self.__UndoToken()
4378            return False
4379
4380        self.__UndoToken()
4381        if not self.__IsToken("[OptionRom.", True):
4382            raise Warning("Unknown Keyword '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
4383
4384        OptRomName = self.__GetUiName()
4385
4386        if not self.__IsToken( "]"):
4387            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
4388
4389        OptRomObj = OptionRom.OPTIONROM()
4390        OptRomObj.DriverName = OptRomName
4391        self.Profile.OptRomDict[OptRomName] = OptRomObj
4392
4393        while True:
4394            isInf = self.__GetOptRomInfStatement(OptRomObj)
4395            isFile = self.__GetOptRomFileStatement(OptRomObj)
4396            if not isInf and not isFile:
4397                break
4398
4399        return True
4400
4401    ## __GetOptRomInfStatement() method
4402    #
4403    #   Get INF statements
4404    #
4405    #   @param  self        The object pointer
4406    #   @param  Obj         for whom inf statement is got
4407    #   @retval True        Successfully find inf statement
4408    #   @retval False       Not able to find inf statement
4409    #
4410    def __GetOptRomInfStatement(self, Obj):
4411
4412        if not self.__IsKeyword( "INF"):
4413            return False
4414
4415        ffsInf = OptRomInfStatement.OptRomInfStatement()
4416        self.__GetInfOptions( ffsInf)
4417
4418        if not self.__GetNextToken():
4419            raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber)
4420        ffsInf.InfFileName = self.__Token
4421        if ffsInf.InfFileName.replace('$(WORKSPACE)', '').find('$') == -1:
4422            #check for file path
4423            ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
4424            if ErrorCode != 0:
4425                EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
4426
4427        if not ffsInf.InfFileName in self.Profile.InfList:
4428            self.Profile.InfList.append(ffsInf.InfFileName)
4429            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
4430            self.Profile.InfFileLineList.append(FileLineTuple)
4431            if ffsInf.UseArch:
4432                if ffsInf.UseArch not in self.Profile.InfDict:
4433                    self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
4434                else:
4435                    self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
4436            else:
4437                self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
4438
4439
4440        self.__GetOptRomOverrides (ffsInf)
4441
4442        Obj.FfsList.append(ffsInf)
4443        return True
4444
4445    ## __GetOptRomOverrides() method
4446    #
4447    #   Get overrides for OptROM INF & FILE
4448    #
4449    #   @param  self        The object pointer
4450    #   @param  FfsInfObj   for whom overrides is got
4451    #
4452    def __GetOptRomOverrides(self, Obj):
4453        if self.__IsToken('{'):
4454            Overrides = OptionRom.OverrideAttribs()
4455            while True:
4456                if self.__IsKeyword( "PCI_VENDOR_ID"):
4457                    if not self.__IsToken( "="):
4458                        raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4459                    if not self.__GetNextHexNumber():
4460                        raise Warning("expected Hex vendor id", self.FileName, self.CurrentLineNumber)
4461                    Overrides.PciVendorId = self.__Token
4462                    continue
4463
4464                if self.__IsKeyword( "PCI_CLASS_CODE"):
4465                    if not self.__IsToken( "="):
4466                        raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4467                    if not self.__GetNextHexNumber():
4468                        raise Warning("expected Hex class code", self.FileName, self.CurrentLineNumber)
4469                    Overrides.PciClassCode = self.__Token
4470                    continue
4471
4472                if self.__IsKeyword( "PCI_DEVICE_ID"):
4473                    if not self.__IsToken( "="):
4474                        raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4475                    if not self.__GetNextHexNumber():
4476                        raise Warning("expected Hex device id", self.FileName, self.CurrentLineNumber)
4477
4478                    Overrides.PciDeviceId = self.__Token
4479                    continue
4480
4481                if self.__IsKeyword( "PCI_REVISION"):
4482                    if not self.__IsToken( "="):
4483                        raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4484                    if not self.__GetNextHexNumber():
4485                        raise Warning("expected Hex revision", self.FileName, self.CurrentLineNumber)
4486                    Overrides.PciRevision = self.__Token
4487                    continue
4488
4489                if self.__IsKeyword( "PCI_COMPRESS"):
4490                    if not self.__IsToken( "="):
4491                        raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
4492                    if not self.__GetNextToken():
4493                        raise Warning("expected TRUE/FALSE for compress", self.FileName, self.CurrentLineNumber)
4494                    Overrides.NeedCompress = self.__Token.upper() == 'TRUE'
4495                    continue
4496
4497                if self.__IsToken( "}"):
4498                    break
4499                else:
4500                    EdkLogger.error("FdfParser", FORMAT_INVALID, File=self.FileName, Line=self.CurrentLineNumber)
4501
4502            Obj.OverrideAttribs = Overrides
4503
4504    ## __GetOptRomFileStatement() method
4505    #
4506    #   Get FILE statements
4507    #
4508    #   @param  self        The object pointer
4509    #   @param  Obj         for whom FILE statement is got
4510    #   @retval True        Successfully find FILE statement
4511    #   @retval False       Not able to find FILE statement
4512    #
4513    def __GetOptRomFileStatement(self, Obj):
4514
4515        if not self.__IsKeyword( "FILE"):
4516            return False
4517
4518        FfsFileObj = OptRomFileStatement.OptRomFileStatement()
4519
4520        if not self.__IsKeyword("EFI") and not self.__IsKeyword("BIN"):
4521            raise Warning("expected Binary type (EFI/BIN)", self.FileName, self.CurrentLineNumber)
4522        FfsFileObj.FileType = self.__Token
4523
4524        if not self.__GetNextToken():
4525            raise Warning("expected File path", self.FileName, self.CurrentLineNumber)
4526        FfsFileObj.FileName = self.__Token
4527        if FfsFileObj.FileName.replace('$(WORKSPACE)', '').find('$') == -1:
4528            #check for file path
4529            ErrorCode, ErrorInfo = PathClass(NormPath(FfsFileObj.FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
4530            if ErrorCode != 0:
4531                EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
4532
4533        if FfsFileObj.FileType == 'EFI':
4534            self.__GetOptRomOverrides(FfsFileObj)
4535
4536        Obj.FfsList.append(FfsFileObj)
4537
4538        return True
4539
4540    ## __GetCapInFd() method
4541    #
4542    #   Get Cap list contained in FD
4543    #
4544    #   @param  self        The object pointer
4545    #   @param  FdName      FD name
4546    #   @retval CapList     List of Capsule in FD
4547    #
4548    def __GetCapInFd (self, FdName):
4549
4550        CapList = []
4551        if FdName.upper() in self.Profile.FdDict.keys():
4552            FdObj = self.Profile.FdDict[FdName.upper()]
4553            for elementRegion in FdObj.RegionList:
4554                if elementRegion.RegionType == 'CAPSULE':
4555                    for elementRegionData in elementRegion.RegionDataList:
4556                        if elementRegionData.endswith(".cap"):
4557                            continue
4558                        if elementRegionData != None and elementRegionData.upper() not in CapList:
4559                            CapList.append(elementRegionData.upper())
4560        return CapList
4561
4562    ## __GetReferencedFdCapTuple() method
4563    #
4564    #   Get FV and FD list referenced by a capsule image
4565    #
4566    #   @param  self        The object pointer
4567    #   @param  CapObj      Capsule section to be searched
4568    #   @param  RefFdList   referenced FD by section
4569    #   @param  RefFvList   referenced FV by section
4570    #
4571    def __GetReferencedFdCapTuple(self, CapObj, RefFdList = [], RefFvList = []):
4572
4573        for CapsuleDataObj in CapObj.CapsuleDataList :
4574            if hasattr(CapsuleDataObj, 'FvName') and CapsuleDataObj.FvName != None and CapsuleDataObj.FvName.upper() not in RefFvList:
4575                RefFvList.append (CapsuleDataObj.FvName.upper())
4576            elif hasattr(CapsuleDataObj, 'FdName') and CapsuleDataObj.FdName != None and CapsuleDataObj.FdName.upper() not in RefFdList:
4577                RefFdList.append (CapsuleDataObj.FdName.upper())
4578            elif CapsuleDataObj.Ffs != None:
4579                if isinstance(CapsuleDataObj.Ffs, FfsFileStatement.FileStatement):
4580                    if CapsuleDataObj.Ffs.FvName != None and CapsuleDataObj.Ffs.FvName.upper() not in RefFvList:
4581                        RefFvList.append(CapsuleDataObj.Ffs.FvName.upper())
4582                    elif CapsuleDataObj.Ffs.FdName != None and CapsuleDataObj.Ffs.FdName.upper() not in RefFdList:
4583                        RefFdList.append(CapsuleDataObj.Ffs.FdName.upper())
4584                    else:
4585                        self.__GetReferencedFdFvTupleFromSection(CapsuleDataObj.Ffs, RefFdList, RefFvList)
4586
4587    ## __GetFvInFd() method
4588    #
4589    #   Get FV list contained in FD
4590    #
4591    #   @param  self        The object pointer
4592    #   @param  FdName      FD name
4593    #   @retval FvList      list of FV in FD
4594    #
4595    def __GetFvInFd (self, FdName):
4596
4597        FvList = []
4598        if FdName.upper() in self.Profile.FdDict.keys():
4599            FdObj = self.Profile.FdDict[FdName.upper()]
4600            for elementRegion in FdObj.RegionList:
4601                if elementRegion.RegionType == 'FV':
4602                    for elementRegionData in elementRegion.RegionDataList:
4603                        if elementRegionData.endswith(".fv"):
4604                            continue
4605                        if elementRegionData != None and elementRegionData.upper() not in FvList:
4606                            FvList.append(elementRegionData.upper())
4607        return FvList
4608
4609    ## __GetReferencedFdFvTuple() method
4610    #
4611    #   Get FD and FV list referenced by a FFS file
4612    #
4613    #   @param  self        The object pointer
4614    #   @param  FfsFile     contains sections to be searched
4615    #   @param  RefFdList   referenced FD by section
4616    #   @param  RefFvList   referenced FV by section
4617    #
4618    def __GetReferencedFdFvTuple(self, FvObj, RefFdList = [], RefFvList = []):
4619
4620        for FfsObj in FvObj.FfsList:
4621            if isinstance(FfsObj, FfsFileStatement.FileStatement):
4622                if FfsObj.FvName != None and FfsObj.FvName.upper() not in RefFvList:
4623                    RefFvList.append(FfsObj.FvName.upper())
4624                elif FfsObj.FdName != None and FfsObj.FdName.upper() not in RefFdList:
4625                    RefFdList.append(FfsObj.FdName.upper())
4626                else:
4627                    self.__GetReferencedFdFvTupleFromSection(FfsObj, RefFdList, RefFvList)
4628
4629    ## __GetReferencedFdFvTupleFromSection() method
4630    #
4631    #   Get FD and FV list referenced by a FFS section
4632    #
4633    #   @param  self        The object pointer
4634    #   @param  FfsFile     contains sections to be searched
4635    #   @param  FdList      referenced FD by section
4636    #   @param  FvList      referenced FV by section
4637    #
4638    def __GetReferencedFdFvTupleFromSection(self, FfsFile, FdList = [], FvList = []):
4639
4640        SectionStack = []
4641        SectionStack.extend(FfsFile.SectionList)
4642        while SectionStack != []:
4643            SectionObj = SectionStack.pop()
4644            if isinstance(SectionObj, FvImageSection.FvImageSection):
4645                if SectionObj.FvName != None and SectionObj.FvName.upper() not in FvList:
4646                    FvList.append(SectionObj.FvName.upper())
4647                if SectionObj.Fv != None and SectionObj.Fv.UiFvName != None and SectionObj.Fv.UiFvName.upper() not in FvList:
4648                    FvList.append(SectionObj.Fv.UiFvName.upper())
4649                    self.__GetReferencedFdFvTuple(SectionObj.Fv, FdList, FvList)
4650
4651            if isinstance(SectionObj, CompressSection.CompressSection) or isinstance(SectionObj, GuidSection.GuidSection):
4652                SectionStack.extend(SectionObj.SectionList)
4653
4654    ## CycleReferenceCheck() method
4655    #
4656    #   Check whether cycle reference exists in FDF
4657    #
4658    #   @param  self        The object pointer
4659    #   @retval True        cycle reference exists
4660    #   @retval False       Not exists cycle reference
4661    #
4662    def CycleReferenceCheck(self):
4663        #
4664        # Check the cycle between FV and FD image
4665        #
4666        MaxLength = len (self.Profile.FvDict)
4667        for FvName in self.Profile.FvDict.keys():
4668            LogStr = "\nCycle Reference Checking for FV: %s\n" % FvName
4669            RefFvStack = []
4670            RefFvStack.append(FvName)
4671            FdAnalyzedList = []
4672
4673            Index = 0
4674            while RefFvStack != [] and Index < MaxLength:
4675                Index = Index + 1
4676                FvNameFromStack = RefFvStack.pop()
4677                if FvNameFromStack.upper() in self.Profile.FvDict.keys():
4678                    FvObj = self.Profile.FvDict[FvNameFromStack.upper()]
4679                else:
4680                    continue
4681
4682                RefFdList = []
4683                RefFvList = []
4684                self.__GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
4685
4686                for RefFdName in RefFdList:
4687                    if RefFdName in FdAnalyzedList:
4688                        continue
4689
4690                    LogStr += "FV %s contains FD %s\n" % (FvNameFromStack, RefFdName)
4691                    FvInFdList = self.__GetFvInFd(RefFdName)
4692                    if FvInFdList != []:
4693                        for FvNameInFd in FvInFdList:
4694                            LogStr += "FD %s contains FV %s\n" % (RefFdName,FvNameInFd)
4695                            if FvNameInFd not in RefFvStack:
4696                                RefFvStack.append(FvNameInFd)
4697
4698                            if FvName in RefFvStack or FvNameFromStack in RefFvStack:
4699                                EdkLogger.info(LogStr)
4700                                return True
4701                    FdAnalyzedList.append(RefFdName)
4702
4703                for RefFvName in RefFvList:
4704                    LogStr += "FV %s contains FV %s\n" % (FvNameFromStack, RefFvName)
4705                    if RefFvName not in RefFvStack:
4706                        RefFvStack.append(RefFvName)
4707
4708                    if FvName in RefFvStack or FvNameFromStack in RefFvStack:
4709                        EdkLogger.info(LogStr)
4710                        return True
4711
4712        #
4713        # Check the cycle between Capsule and FD image
4714        #
4715        MaxLength = len (self.Profile.CapsuleDict)
4716        for CapName in self.Profile.CapsuleDict.keys():
4717            #
4718            # Capsule image to be checked.
4719            #
4720            LogStr = "\n\n\nCycle Reference Checking for Capsule: %s\n" % CapName
4721            RefCapStack = []
4722            RefCapStack.append(CapName)
4723            FdAnalyzedList = []
4724            FvAnalyzedList = []
4725
4726            Index = 0
4727            while RefCapStack != [] and Index < MaxLength:
4728                Index = Index + 1
4729                CapNameFromStack = RefCapStack.pop()
4730                if CapNameFromStack.upper() in self.Profile.CapsuleDict.keys():
4731                    CapObj = self.Profile.CapsuleDict[CapNameFromStack.upper()]
4732                else:
4733                    continue
4734
4735                RefFvList = []
4736                RefFdList = []
4737                self.__GetReferencedFdCapTuple(CapObj, RefFdList, RefFvList)
4738
4739                FvListLength = 0
4740                FdListLength = 0
4741                while FvListLength < len (RefFvList) or FdListLength < len (RefFdList):
4742                    for RefFdName in RefFdList:
4743                        if RefFdName in FdAnalyzedList:
4744                            continue
4745
4746                        LogStr += "Capsule %s contains FD %s\n" % (CapNameFromStack, RefFdName)
4747                        CapInFdList = self.__GetCapInFd(RefFdName)
4748                        if CapInFdList != []:
4749                            for CapNameInFd in CapInFdList:
4750                                LogStr += "FD %s contains Capsule %s\n" % (RefFdName,CapNameInFd)
4751                                if CapNameInFd not in RefCapStack:
4752                                    RefCapStack.append(CapNameInFd)
4753
4754                                if CapName in RefCapStack or CapNameFromStack in RefCapStack:
4755                                    EdkLogger.info(LogStr)
4756                                    return True
4757
4758                        FvInFdList = self.__GetFvInFd(RefFdName)
4759                        if FvInFdList != []:
4760                            for FvNameInFd in FvInFdList:
4761                                LogStr += "FD %s contains FV %s\n" % (RefFdName,FvNameInFd)
4762                                if FvNameInFd not in RefFvList:
4763                                    RefFvList.append(FvNameInFd)
4764
4765                        FdAnalyzedList.append(RefFdName)
4766                    #
4767                    # the number of the parsed FV and FD image
4768                    #
4769                    FvListLength = len (RefFvList)
4770                    FdListLength = len (RefFdList)
4771                    for RefFvName in RefFvList:
4772                        if RefFvName in FvAnalyzedList:
4773                            continue
4774                        LogStr += "Capsule %s contains FV %s\n" % (CapNameFromStack, RefFvName)
4775                        if RefFvName.upper() in self.Profile.FvDict.keys():
4776                            FvObj = self.Profile.FvDict[RefFvName.upper()]
4777                        else:
4778                            continue
4779                        self.__GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
4780                        FvAnalyzedList.append(RefFvName)
4781
4782        return False
4783
4784if __name__ == "__main__":
4785    import sys
4786    try:
4787        test_file = sys.argv[1]
4788    except IndexError, v:
4789        print "Usage: %s filename" % sys.argv[0]
4790        sys.exit(1)
4791
4792    parser = FdfParser(test_file)
4793    try:
4794        parser.ParseFile()
4795        parser.CycleReferenceCheck()
4796    except Warning, X:
4797        print str(X)
4798    else:
4799        print "Success!"
4800
4801