1## @file
2# parse FDF file
3#
4#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
5#
6#  This program and the accompanying materials
7#  are licensed and made available under the terms and conditions of the BSD License
8#  which accompanies this distribution.  The full text of the license may be found at
9#  http://opensource.org/licenses/bsd-license.php
10#
11#  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12#  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13#
14
15##
16# Import Modules
17#
18import re
19import Common.LongFilePathOs as os
20
21import CommonDataClass.FdfClass
22from Common.LongFilePathSupport import OpenLongFilePath as open
23
24##define T_CHAR_SPACE                ' '
25##define T_CHAR_NULL                 '\0'
26##define T_CHAR_CR                   '\r'
27##define T_CHAR_TAB                  '\t'
28##define T_CHAR_LF                   '\n'
29##define T_CHAR_SLASH                '/'
30##define T_CHAR_BACKSLASH            '\\'
31##define T_CHAR_DOUBLE_QUOTE         '\"'
32##define T_CHAR_SINGLE_QUOTE         '\''
33##define T_CHAR_STAR                 '*'
34##define T_CHAR_HASH                 '#'
35
36(T_CHAR_SPACE, T_CHAR_NULL, T_CHAR_CR, T_CHAR_TAB, T_CHAR_LF, T_CHAR_SLASH, \
37T_CHAR_BACKSLASH, T_CHAR_DOUBLE_QUOTE, T_CHAR_SINGLE_QUOTE, T_CHAR_STAR, T_CHAR_HASH) = \
38(' ', '\0', '\r', '\t', '\n', '/', '\\', '\"', '\'', '*', '#')
39
40SEPERATOR_TUPLE = ('=', '|', ',', '{', '}')
41
42IncludeFileList = []
43# Macro passed from command line, which has greatest priority and can NOT be overridden by those in FDF
44InputMacroDict = {}
45# All Macro values when parsing file, not replace existing Macro
46AllMacroList = []
47
48def GetRealFileLine (File, Line):
49
50    InsertedLines = 0
51    for Profile in IncludeFileList:
52        if Line >= Profile.InsertStartLineNumber and Line < Profile.InsertStartLineNumber + Profile.InsertAdjust + len(Profile.FileLinesList):
53            return (Profile.FileName, Line - Profile.InsertStartLineNumber + 1)
54        if Line >= Profile.InsertStartLineNumber + Profile.InsertAdjust + len(Profile.FileLinesList):
55            InsertedLines += Profile.InsertAdjust + len(Profile.FileLinesList)
56
57    return (File, Line - InsertedLines)
58
59## The exception class that used to report error messages when parsing FDF
60#
61# Currently the "ToolName" is set to be "FDF Parser".
62#
63class Warning (Exception):
64    ## The constructor
65    #
66    #   @param  self        The object pointer
67    #   @param  Str         The message to record
68    #   @param  File        The FDF name
69    #   @param  Line        The Line number that error occurs
70    #
71    def __init__(self, Str, File = None, Line = None):
72
73        FileLineTuple = GetRealFileLine(File, Line)
74        self.FileName = FileLineTuple[0]
75        self.LineNumber = FileLineTuple[1]
76        self.message = Str + str(self.LineNumber)
77        self.ToolName = 'FDF Parser'
78
79## The MACRO class that used to record macro value data when parsing include file
80#
81#
82class MacroProfile :
83    ## The constructor
84    #
85    #   @param  self        The object pointer
86    #   @param  FileName    The file that to be parsed
87    #
88    def __init__(self, FileName, Line):
89        self.FileName = FileName
90        self.DefinedAtLine  = Line
91        self.MacroName = None
92        self.MacroValue = None
93
94## The Include file content class that used to record file data when parsing include file
95#
96# May raise Exception when opening file.
97#
98class IncludeFileProfile :
99    ## The constructor
100    #
101    #   @param  self        The object pointer
102    #   @param  FileName    The file that to be parsed
103    #
104    def __init__(self, FileName):
105        self.FileName = FileName
106        self.FileLinesList = []
107        try:
108            fsock = open(FileName, "rb", 0)
109            try:
110                self.FileLinesList = fsock.readlines()
111            finally:
112                fsock.close()
113
114        except IOError:
115            raise Warning("Error when opening file %s" % FileName)
116
117        self.InsertStartLineNumber = None
118        self.InsertAdjust = 0
119
120## The FDF content class that used to record file data when parsing FDF
121#
122# May raise Exception when opening file.
123#
124class FileProfile :
125    ## The constructor
126    #
127    #   @param  self        The object pointer
128    #   @param  FileName    The file that to be parsed
129    #
130    def __init__(self, FileName):
131        self.FileLinesList = []
132        try:
133            fsock = open(FileName, "rb", 0)
134            try:
135                self.FileLinesList = fsock.readlines()
136            finally:
137                fsock.close()
138
139        except IOError:
140            raise Warning("Error when opening file %s" % FileName)
141
142        self.PcdDict = {}
143        self.InfList = []
144
145        self.PcdFileLineDict = {}
146        self.InfFileLineList = []
147
148        self.FdDict = {}
149        self.FvDict = {}
150        self.CapsuleList = []
151#        self.VtfList = []
152#        self.RuleDict = {}
153
154## The syntax parser for FDF
155#
156# PreprocessFile method should be called prior to ParseFile
157# CycleReferenceCheck method can detect cycles in FDF contents
158#
159# GetNext*** procedures mean these procedures will get next token first, then make judgement.
160# Get*** procedures mean these procedures will make judgement on current token only.
161#
162class FdfParser(object):
163    ## The constructor
164    #
165    #   @param  self        The object pointer
166    #   @param  FileName    The file that to be parsed
167    #
168    def __init__(self, FileName):
169        self.Profile = FileProfile(FileName)
170        self.FileName = FileName
171        self.CurrentLineNumber = 1
172        self.CurrentOffsetWithinLine = 0
173        self.CurrentFdName = None
174        self.CurrentFvName = None
175        self.__Token = ""
176        self.__SkippedChars = ""
177
178        self.__WipeOffArea = []
179
180    ## __IsWhiteSpace() method
181    #
182    #   Whether char at current FileBufferPos is whitespace
183    #
184    #   @param  self        The object pointer
185    #   @param  Char        The char to test
186    #   @retval True        The char is a kind of white space
187    #   @retval False       The char is NOT a kind of white space
188    #
189    def __IsWhiteSpace(self, Char):
190        if Char in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_SPACE, T_CHAR_TAB, T_CHAR_LF):
191            return True
192        else:
193            return False
194
195    ## __SkipWhiteSpace() method
196    #
197    #   Skip white spaces from current char, return number of chars skipped
198    #
199    #   @param  self        The object pointer
200    #   @retval Count       The number of chars skipped
201    #
202    def __SkipWhiteSpace(self):
203        Count = 0
204        while not self.__EndOfFile():
205            Count += 1
206            if self.__CurrentChar() in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_LF, T_CHAR_SPACE, T_CHAR_TAB):
207                self.__SkippedChars += str(self.__CurrentChar())
208                self.__GetOneChar()
209
210            else:
211                Count = Count - 1
212                return Count
213
214    ## __EndOfFile() method
215    #
216    #   Judge current buffer pos is at file end
217    #
218    #   @param  self        The object pointer
219    #   @retval True        Current File buffer position is at file end
220    #   @retval False       Current File buffer position is NOT at file end
221    #
222    def __EndOfFile(self):
223        NumberOfLines = len(self.Profile.FileLinesList)
224        SizeOfLastLine = len(self.Profile.FileLinesList[-1])
225        if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1:
226            return True
227        elif self.CurrentLineNumber > NumberOfLines:
228            return True
229        else:
230            return False
231
232    ## __EndOfLine() method
233    #
234    #   Judge current buffer pos is at line end
235    #
236    #   @param  self        The object pointer
237    #   @retval True        Current File buffer position is at line end
238    #   @retval False       Current File buffer position is NOT at line end
239    #
240    def __EndOfLine(self):
241        if self.CurrentLineNumber > len(self.Profile.FileLinesList):
242            return True
243        SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
244        if self.CurrentOffsetWithinLine >= SizeOfCurrentLine:
245            return True
246        else:
247            return False
248
249    ## Rewind() method
250    #
251    #   Reset file data buffer to the initial state
252    #
253    #   @param  self        The object pointer
254    #
255    def Rewind(self):
256        self.CurrentLineNumber = 1
257        self.CurrentOffsetWithinLine = 0
258
259    ## __UndoOneChar() method
260    #
261    #   Go back one char in the file buffer
262    #
263    #   @param  self        The object pointer
264    #   @retval True        Successfully go back one char
265    #   @retval False       Not able to go back one char as file beginning reached
266    #
267    def __UndoOneChar(self):
268
269        if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0:
270            return False
271        elif self.CurrentOffsetWithinLine == 0:
272            self.CurrentLineNumber -= 1
273            self.CurrentOffsetWithinLine = len(self.__CurrentLine()) - 1
274        else:
275            self.CurrentOffsetWithinLine -= 1
276        return True
277
278    ## __GetOneChar() method
279    #
280    #   Move forward one char in the file buffer
281    #
282    #   @param  self        The object pointer
283    #
284    def __GetOneChar(self):
285        if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
286            self.CurrentLineNumber += 1
287            self.CurrentOffsetWithinLine = 0
288        else:
289            self.CurrentOffsetWithinLine += 1
290
291    ## __CurrentChar() method
292    #
293    #   Get the char pointed to by the file buffer pointer
294    #
295    #   @param  self        The object pointer
296    #   @retval Char        Current char
297    #
298    def __CurrentChar(self):
299        return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine]
300
301    ## __NextChar() method
302    #
303    #   Get the one char pass the char pointed to by the file buffer pointer
304    #
305    #   @param  self        The object pointer
306    #   @retval Char        Next char
307    #
308    def __NextChar(self):
309        if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
310            return self.Profile.FileLinesList[self.CurrentLineNumber][0]
311        else:
312            return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1]
313
314    ## __SetCurrentCharValue() method
315    #
316    #   Modify the value of current char
317    #
318    #   @param  self        The object pointer
319    #   @param  Value       The new value of current char
320    #
321    def __SetCurrentCharValue(self, Value):
322        self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value
323
324    ## __CurrentLine() method
325    #
326    #   Get the list that contains current line contents
327    #
328    #   @param  self        The object pointer
329    #   @retval List        current line contents
330    #
331    def __CurrentLine(self):
332        return self.Profile.FileLinesList[self.CurrentLineNumber - 1]
333
334    def __StringToList(self):
335        self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList]
336        self.Profile.FileLinesList[-1].append(' ')
337
338    def __ReplaceMacros(self, Str, File, Line):
339        MacroEnd = 0
340        while Str.find('$(', MacroEnd) >= 0:
341            MacroStart = Str.find('$(', MacroEnd)
342            if Str.find(')', MacroStart) > 0:
343                MacroEnd = Str.find(')', MacroStart)
344                Name = Str[MacroStart + 2 : MacroEnd]
345                Value = None
346                if Name in InputMacroDict:
347                    Value = InputMacroDict[Name]
348
349                else:
350                    for Profile in AllMacroList:
351                        if Profile.FileName == File and Profile.MacroName == Name and Profile.DefinedAtLine <= Line:
352                            Value = Profile.MacroValue
353
354                if Value != None:
355                    Str = Str.replace('$(' + Name + ')', Value)
356                    MacroEnd = MacroStart + len(Value)
357
358            else:
359                raise Warning("Macro not complete At Line ", self.FileName, self.CurrentLineNumber)
360        return Str
361
362    def __ReplaceFragment(self, StartPos, EndPos, Value = ' '):
363        if StartPos[0] == EndPos[0]:
364            Offset = StartPos[1]
365            while Offset <= EndPos[1]:
366                self.Profile.FileLinesList[StartPos[0]][Offset] = Value
367                Offset += 1
368            return
369
370        Offset = StartPos[1]
371        while self.Profile.FileLinesList[StartPos[0]][Offset] not in ('\r', '\n'):
372            self.Profile.FileLinesList[StartPos[0]][Offset] = Value
373            Offset += 1
374
375        Line = StartPos[0]
376        while Line < EndPos[0]:
377            Offset = 0
378            while self.Profile.FileLinesList[Line][Offset] not in ('\r', '\n'):
379                self.Profile.FileLinesList[Line][Offset] = Value
380                Offset += 1
381            Line += 1
382
383        Offset = 0
384        while Offset <= EndPos[1]:
385            self.Profile.FileLinesList[EndPos[0]][Offset] = Value
386            Offset += 1
387
388
389    def __GetMacroName(self):
390        if not self.__GetNextToken():
391            raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber)
392        MacroName = self.__Token
393        NotFlag = False
394        if MacroName.startswith('!'):
395            NotFlag = True
396            MacroName = MacroName[1:].strip()
397
398        if not MacroName.startswith('$(') or not MacroName.endswith(')'):
399            raise Warning("Macro name expected(Please use '$(%(Token)s)' if '%(Token)s' is a macro.)" % {"Token" : MacroName},
400                          self.FileName, self.CurrentLineNumber)
401        MacroName = MacroName[2:-1]
402        return MacroName, NotFlag
403
404    ## PreprocessFile() method
405    #
406    #   Preprocess file contents, replace comments with spaces.
407    #   In the end, rewind the file buffer pointer to the beginning
408    #   BUGBUG: No !include statement processing contained in this procedure
409    #   !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1]
410    #
411    #   @param  self        The object pointer
412    #
413    def PreprocessFile(self):
414
415        self.Rewind()
416        InComment = False
417        DoubleSlashComment = False
418        HashComment = False
419        # HashComment in quoted string " " is ignored.
420        InString = False
421
422        while not self.__EndOfFile():
423
424            if self.__CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment:
425                InString = not InString
426            # meet new line, then no longer in a comment for // and '#'
427            if self.__CurrentChar() == T_CHAR_LF:
428                self.CurrentLineNumber += 1
429                self.CurrentOffsetWithinLine = 0
430                if InComment and DoubleSlashComment:
431                    InComment = False
432                    DoubleSlashComment = False
433                if InComment and HashComment:
434                    InComment = False
435                    HashComment = False
436            # check for */ comment end
437            elif InComment and not DoubleSlashComment and not HashComment and self.__CurrentChar() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH:
438                self.__SetCurrentCharValue(T_CHAR_SPACE)
439                self.__GetOneChar()
440                self.__SetCurrentCharValue(T_CHAR_SPACE)
441                self.__GetOneChar()
442                InComment = False
443            # set comments to spaces
444            elif InComment:
445                self.__SetCurrentCharValue(T_CHAR_SPACE)
446                self.__GetOneChar()
447            # check for // comment
448            elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH and not self.__EndOfLine():
449                InComment = True
450                DoubleSlashComment = True
451            # check for '#' comment
452            elif self.__CurrentChar() == T_CHAR_HASH and not self.__EndOfLine() and not InString:
453                InComment = True
454                HashComment = True
455            # check for /* comment start
456            elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR:
457                self.__SetCurrentCharValue( T_CHAR_SPACE)
458                self.__GetOneChar()
459                self.__SetCurrentCharValue( T_CHAR_SPACE)
460                self.__GetOneChar()
461                InComment = True
462            else:
463                self.__GetOneChar()
464
465        # restore from ListOfList to ListOfString
466        self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
467        self.Rewind()
468
469    ## PreprocessIncludeFile() method
470    #
471    #   Preprocess file contents, replace !include statements with file contents.
472    #   In the end, rewind the file buffer pointer to the beginning
473    #
474    #   @param  self        The object pointer
475    #
476    def PreprocessIncludeFile(self):
477
478        while self.__GetNextToken():
479
480            if self.__Token == '!include':
481                IncludeLine = self.CurrentLineNumber
482                IncludeOffset = self.CurrentOffsetWithinLine - len('!include')
483                if not self.__GetNextToken():
484                    raise Warning("expected include file name At Line ", self.FileName, self.CurrentLineNumber)
485                IncFileName = self.__Token
486                if not os.path.isabs(IncFileName):
487                    if IncFileName.startswith('$(WORKSPACE)'):
488                        Str = IncFileName.replace('$(WORKSPACE)', os.environ.get('WORKSPACE'))
489                        if os.path.exists(Str):
490                            if not os.path.isabs(Str):
491                                Str = os.path.abspath(Str)
492                        IncFileName = Str
493                    else:
494                        # file is in the same dir with FDF file
495                        FullFdf = self.FileName
496                        if not os.path.isabs(self.FileName):
497                            FullFdf = os.path.join(os.environ.get('WORKSPACE'), self.FileName)
498
499                        IncFileName = os.path.join(os.path.dirname(FullFdf), IncFileName)
500
501                if not os.path.exists(os.path.normpath(IncFileName)):
502                    raise Warning("Include file not exists At Line ", self.FileName, self.CurrentLineNumber)
503
504                IncFileProfile = IncludeFileProfile(os.path.normpath(IncFileName))
505
506                CurrentLine = self.CurrentLineNumber
507                CurrentOffset = self.CurrentOffsetWithinLine
508                # list index of the insertion, note that line number is 'CurrentLine + 1'
509                InsertAtLine = CurrentLine
510                IncFileProfile.InsertStartLineNumber = InsertAtLine + 1
511                # deal with remaining portions after "!include filename", if exists.
512                if self.__GetNextToken():
513                    if self.CurrentLineNumber == CurrentLine:
514                        RemainingLine = self.__CurrentLine()[CurrentOffset:]
515                        self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine)
516                        IncFileProfile.InsertAdjust += 1
517                        self.CurrentLineNumber += 1
518                        self.CurrentOffsetWithinLine = 0
519
520                for Line in IncFileProfile.FileLinesList:
521                    self.Profile.FileLinesList.insert(InsertAtLine, Line)
522                    self.CurrentLineNumber += 1
523                    InsertAtLine += 1
524
525                IncludeFileList.append(IncFileProfile)
526
527                # comment out the processed include file statement
528                TempList = list(self.Profile.FileLinesList[IncludeLine - 1])
529                TempList.insert(IncludeOffset, '#')
530                self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList)
531
532        self.Rewind()
533
534    ## PreprocessIncludeFile() method
535    #
536    #   Preprocess file contents, replace !include statements with file contents.
537    #   In the end, rewind the file buffer pointer to the beginning
538    #
539    #   @param  self        The object pointer
540    #
541    def PreprocessConditionalStatement(self):
542        # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined]
543        IfList = []
544        while self.__GetNextToken():
545            if self.__Token == 'DEFINE':
546                DefineLine = self.CurrentLineNumber - 1
547                DefineOffset = self.CurrentOffsetWithinLine - len('DEFINE')
548                if not self.__GetNextToken():
549                    raise Warning("expected Macro name At Line ", self.FileName, self.CurrentLineNumber)
550                Macro = self.__Token
551                if not self.__IsToken( "="):
552                    raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
553
554                if not self.__GetNextToken():
555                    raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber)
556
557                if self.__GetStringData():
558                    pass
559                Value = self.__Token
560                if not Macro in InputMacroDict:
561                    FileLineTuple = GetRealFileLine(self.FileName, DefineLine + 1)
562                    MacProfile = MacroProfile(FileLineTuple[0], FileLineTuple[1])
563                    MacProfile.MacroName = Macro
564                    MacProfile.MacroValue = Value
565                    AllMacroList.append(MacProfile)
566                self.__WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
567
568            elif self.__Token in ('!ifdef', '!ifndef', '!if'):
569                IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token))
570                IfList.append([IfStartPos, None, None])
571                CondLabel = self.__Token
572
573                MacroName, NotFlag = self.__GetMacroName()
574                NotDefineFlag = False
575                if CondLabel == '!ifndef':
576                    NotDefineFlag = True
577                if CondLabel == '!ifdef' or CondLabel == '!ifndef':
578                    if NotFlag:
579                        raise Warning("'NOT' operation not allowed for Macro name At Line ", self.FileName, self.CurrentLineNumber)
580
581                if CondLabel == '!if':
582
583                    if not self.__GetNextOp():
584                        raise Warning("expected !endif At Line ", self.FileName, self.CurrentLineNumber)
585
586                    if self.__Token in ('!=', '==', '>', '<', '>=', '<='):
587                        Op = self.__Token
588                        if not self.__GetNextToken():
589                            raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber)
590                        if self.__GetStringData():
591                            pass
592                        MacroValue = self.__Token
593                        ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, Op, MacroValue)
594                        if NotFlag:
595                            ConditionSatisfied = not ConditionSatisfied
596                        BranchDetermined = ConditionSatisfied
597                    else:
598                        self.CurrentOffsetWithinLine -= len(self.__Token)
599                        ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, None, 'Bool')
600                        if NotFlag:
601                            ConditionSatisfied = not ConditionSatisfied
602                        BranchDetermined = ConditionSatisfied
603                    IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined]
604                    if ConditionSatisfied:
605                        self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
606
607                else:
608                    ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1)
609                    if NotDefineFlag:
610                        ConditionSatisfied = not ConditionSatisfied
611                    BranchDetermined = ConditionSatisfied
612                    IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined]
613                    if ConditionSatisfied:
614                        self.__WipeOffArea.append((IfStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
615
616            elif self.__Token in ('!elseif', '!else'):
617                ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token))
618                if len(IfList) <= 0:
619                    raise Warning("Missing !if statement At Line ", self.FileName, self.CurrentLineNumber)
620                if IfList[-1][1]:
621                    IfList[-1] = [ElseStartPos, False, True]
622                    self.__WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
623                else:
624                    self.__WipeOffArea.append((IfList[-1][0], ElseStartPos))
625                    IfList[-1] = [ElseStartPos, True, IfList[-1][2]]
626                    if self.__Token == '!elseif':
627                        MacroName, NotFlag = self.__GetMacroName()
628                        if not self.__GetNextOp():
629                            raise Warning("expected !endif At Line ", self.FileName, self.CurrentLineNumber)
630
631                        if self.__Token in ('!=', '==', '>', '<', '>=', '<='):
632                            Op = self.__Token
633                            if not self.__GetNextToken():
634                                raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber)
635                            if self.__GetStringData():
636                                pass
637                            MacroValue = self.__Token
638                            ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, Op, MacroValue)
639                            if NotFlag:
640                                ConditionSatisfied = not ConditionSatisfied
641
642                        else:
643                            self.CurrentOffsetWithinLine -= len(self.__Token)
644                            ConditionSatisfied = self.__EvaluateConditional(MacroName, IfList[-1][0][0] + 1, None, 'Bool')
645                            if NotFlag:
646                                ConditionSatisfied = not ConditionSatisfied
647
648                        IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]]
649
650                    if IfList[-1][1]:
651                        if IfList[-1][2]:
652                            IfList[-1][1] = False
653                        else:
654                            IfList[-1][2] = True
655                            self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
656
657
658            elif self.__Token == '!endif':
659                if IfList[-1][1]:
660                    self.__WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
661                else:
662                    self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
663
664                IfList.pop()
665
666
667        if len(IfList) > 0:
668            raise Warning("Missing !endif At Line ", self.FileName, self.CurrentLineNumber)
669        self.Rewind()
670
671    def __EvaluateConditional(self, Name, Line, Op = None, Value = None):
672
673        FileLineTuple = GetRealFileLine(self.FileName, Line)
674        if Name in InputMacroDict:
675            MacroValue = InputMacroDict[Name]
676            if Op == None:
677                if Value == 'Bool' and MacroValue == None or MacroValue.upper() == 'FALSE':
678                    return False
679                return True
680            elif Op == '!=':
681                if Value != MacroValue:
682                    return True
683                else:
684                    return False
685            elif Op == '==':
686                if Value == MacroValue:
687                    return True
688                else:
689                    return False
690            else:
691                if (self.__IsHex(Value) or Value.isdigit()) and (self.__IsHex(MacroValue) or (MacroValue != None and MacroValue.isdigit())):
692                    InputVal = long(Value, 0)
693                    MacroVal = long(MacroValue, 0)
694                    if Op == '>':
695                        if MacroVal > InputVal:
696                            return True
697                        else:
698                            return False
699                    elif Op == '>=':
700                        if MacroVal >= InputVal:
701                            return True
702                        else:
703                            return False
704                    elif Op == '<':
705                        if MacroVal < InputVal:
706                            return True
707                        else:
708                            return False
709                    elif Op == '<=':
710                        if MacroVal <= InputVal:
711                            return True
712                        else:
713                            return False
714                    else:
715                        return False
716                else:
717                    raise Warning("Value %s is not a number At Line ", self.FileName, Line)
718
719        for Profile in AllMacroList:
720            if Profile.FileName == FileLineTuple[0] and Profile.MacroName == Name and Profile.DefinedAtLine <= FileLineTuple[1]:
721                if Op == None:
722                    if Value == 'Bool' and Profile.MacroValue == None or Profile.MacroValue.upper() == 'FALSE':
723                        return False
724                    return True
725                elif Op == '!=':
726                    if Value != Profile.MacroValue:
727                        return True
728                    else:
729                        return False
730                elif Op == '==':
731                    if Value == Profile.MacroValue:
732                        return True
733                    else:
734                        return False
735                else:
736                    if (self.__IsHex(Value) or Value.isdigit()) and (self.__IsHex(Profile.MacroValue) or (Profile.MacroValue != None and Profile.MacroValue.isdigit())):
737                        InputVal = long(Value, 0)
738                        MacroVal = long(Profile.MacroValue, 0)
739                        if Op == '>':
740                            if MacroVal > InputVal:
741                                return True
742                            else:
743                                return False
744                        elif Op == '>=':
745                            if MacroVal >= InputVal:
746                                return True
747                            else:
748                                return False
749                        elif Op == '<':
750                            if MacroVal < InputVal:
751                                return True
752                            else:
753                                return False
754                        elif Op == '<=':
755                            if MacroVal <= InputVal:
756                                return True
757                            else:
758                                return False
759                        else:
760                            return False
761                    else:
762                        raise Warning("Value %s is not a number At Line ", self.FileName, Line)
763
764        return False
765
766    ## __IsToken() method
767    #
768    #   Check whether input string is found from current char position along
769    #   If found, the string value is put into self.__Token
770    #
771    #   @param  self        The object pointer
772    #   @param  String      The string to search
773    #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive
774    #   @retval True        Successfully find string, file buffer pointer moved forward
775    #   @retval False       Not able to find string, file buffer pointer not changed
776    #
777    def __IsToken(self, String, IgnoreCase = False):
778        self.__SkipWhiteSpace()
779
780        # Only consider the same line, no multi-line token allowed
781        StartPos = self.CurrentOffsetWithinLine
782        index = -1
783        if IgnoreCase:
784            index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper())
785        else:
786            index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String)
787        if index == 0:
788            self.CurrentOffsetWithinLine += len(String)
789            self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
790            return True
791        return False
792
793    ## __IsKeyword() method
794    #
795    #   Check whether input keyword is found from current char position along, whole word only!
796    #   If found, the string value is put into self.__Token
797    #
798    #   @param  self        The object pointer
799    #   @param  Keyword     The string to search
800    #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive
801    #   @retval True        Successfully find string, file buffer pointer moved forward
802    #   @retval False       Not able to find string, file buffer pointer not changed
803    #
804    def __IsKeyword(self, KeyWord, IgnoreCase = False):
805        self.__SkipWhiteSpace()
806
807        # Only consider the same line, no multi-line token allowed
808        StartPos = self.CurrentOffsetWithinLine
809        index = -1
810        if IgnoreCase:
811            index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(KeyWord.upper())
812        else:
813            index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(KeyWord)
814        if index == 0:
815            followingChar = self.__CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)]
816            if not str(followingChar).isspace() and followingChar not in SEPERATOR_TUPLE:
817                return False
818            self.CurrentOffsetWithinLine += len(KeyWord)
819            self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
820            return True
821        return False
822
823    ## __GetNextWord() method
824    #
825    #   Get next C name from file lines
826    #   If found, the string value is put into self.__Token
827    #
828    #   @param  self        The object pointer
829    #   @retval True        Successfully find a C name string, file buffer pointer moved forward
830    #   @retval False       Not able to find a C name string, file buffer pointer not changed
831    #
832    def __GetNextWord(self):
833        self.__SkipWhiteSpace()
834        if self.__EndOfFile():
835            return False
836
837        TempChar = self.__CurrentChar()
838        StartPos = self.CurrentOffsetWithinLine
839        if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_':
840            self.__GetOneChar()
841            while not self.__EndOfLine():
842                TempChar = self.__CurrentChar()
843                if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
844                or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-':
845                    self.__GetOneChar()
846
847                else:
848                    break
849
850            self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
851            return True
852
853        return False
854
855    ## __GetNextToken() method
856    #
857    #   Get next token unit before a seperator
858    #   If found, the string value is put into self.__Token
859    #
860    #   @param  self        The object pointer
861    #   @retval True        Successfully find a token unit, file buffer pointer moved forward
862    #   @retval False       Not able to find a token unit, file buffer pointer not changed
863    #
864    def __GetNextToken(self):
865        # Skip leading spaces, if exist.
866        self.__SkipWhiteSpace()
867        if self.__EndOfFile():
868            return False
869        # Record the token start position, the position of the first non-space char.
870        StartPos = self.CurrentOffsetWithinLine
871        StartLine = self.CurrentLineNumber
872        while not self.__EndOfLine():
873            TempChar = self.__CurrentChar()
874            # Try to find the end char that is not a space and not in seperator tuple.
875            # That is, when we got a space or any char in the tuple, we got the end of token.
876            if not str(TempChar).isspace() and TempChar not in SEPERATOR_TUPLE:
877                self.__GetOneChar()
878            # if we happen to meet a seperator as the first char, we must proceed to get it.
879            # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
880            elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE:
881                self.__GetOneChar()
882                break
883            else:
884                break
885#        else:
886#            return False
887
888        EndPos = self.CurrentOffsetWithinLine
889        if self.CurrentLineNumber != StartLine:
890            EndPos = len(self.Profile.FileLinesList[StartLine-1])
891        self.__Token = self.Profile.FileLinesList[StartLine-1][StartPos : EndPos]
892        if StartPos != self.CurrentOffsetWithinLine:
893            return True
894        else:
895            return False
896
897    def __GetNextOp(self):
898        # Skip leading spaces, if exist.
899        self.__SkipWhiteSpace()
900        if self.__EndOfFile():
901            return False
902        # Record the token start position, the position of the first non-space char.
903        StartPos = self.CurrentOffsetWithinLine
904        while not self.__EndOfLine():
905            TempChar = self.__CurrentChar()
906            # Try to find the end char that is not a space
907            if not str(TempChar).isspace():
908                self.__GetOneChar()
909            else:
910                break
911        else:
912            return False
913
914        if StartPos != self.CurrentOffsetWithinLine:
915            self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
916            return True
917        else:
918            return False
919    ## __GetNextGuid() method
920    #
921    #   Get next token unit before a seperator
922    #   If found, the GUID string is put into self.__Token
923    #
924    #   @param  self        The object pointer
925    #   @retval True        Successfully find a registry format GUID, file buffer pointer moved forward
926    #   @retval False       Not able to find a registry format GUID, file buffer pointer not changed
927    #
928    def __GetNextGuid(self):
929
930        if not self.__GetNextToken():
931            return False
932        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}')
933        if p.match(self.__Token) != None:
934            return True
935        else:
936            self.__UndoToken()
937            return False
938
939    ## __UndoToken() method
940    #
941    #   Go back one token unit in file buffer
942    #
943    #   @param  self        The object pointer
944    #
945    def __UndoToken(self):
946        self.__UndoOneChar()
947        while self.__CurrentChar().isspace():
948            if not self.__UndoOneChar():
949                self.__GetOneChar()
950                return
951
952
953        StartPos = self.CurrentOffsetWithinLine
954        CurrentLine = self.CurrentLineNumber
955        while CurrentLine == self.CurrentLineNumber:
956
957            TempChar = self.__CurrentChar()
958            # Try to find the end char that is not a space and not in seperator tuple.
959            # That is, when we got a space or any char in the tuple, we got the end of token.
960            if not str(TempChar).isspace() and not TempChar in SEPERATOR_TUPLE:
961                if not self.__UndoOneChar():
962                    break
963            # if we happen to meet a seperator as the first char, we must proceed to get it.
964            # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
965            elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE:
966                return
967            else:
968                break
969
970        self.__GetOneChar()
971
972    ## __HexDigit() method
973    #
974    #   Whether char input is a Hex data bit
975    #
976    #   @param  self        The object pointer
977    #   @param  TempChar    The char to test
978    #   @retval True        The char is a Hex data bit
979    #   @retval False       The char is NOT a Hex data bit
980    #
981    def __HexDigit(self, TempChar):
982        if (TempChar >= 'a' and TempChar <= 'f') or (TempChar >= 'A' and TempChar <= 'F') \
983                or (TempChar >= '0' and TempChar <= '9'):
984                    return True
985        else:
986            return False
987
988    def __IsHex(self, HexStr):
989        if not HexStr.upper().startswith("0X"):
990            return False
991        if len(self.__Token) <= 2:
992            return False
993        charList = [c for c in HexStr[2 : ] if not self.__HexDigit( c)]
994        if len(charList) == 0:
995            return True
996        else:
997            return False
998    ## __GetNextHexNumber() method
999    #
1000    #   Get next HEX data before a seperator
1001    #   If found, the HEX data is put into self.__Token
1002    #
1003    #   @param  self        The object pointer
1004    #   @retval True        Successfully find a HEX data, file buffer pointer moved forward
1005    #   @retval False       Not able to find a HEX data, file buffer pointer not changed
1006    #
1007    def __GetNextHexNumber(self):
1008        if not self.__GetNextToken():
1009            return False
1010        if self.__IsHex(self.__Token):
1011            return True
1012        else:
1013            self.__UndoToken()
1014            return False
1015
1016    ## __GetNextDecimalNumber() method
1017    #
1018    #   Get next decimal data before a seperator
1019    #   If found, the decimal data is put into self.__Token
1020    #
1021    #   @param  self        The object pointer
1022    #   @retval True        Successfully find a decimal data, file buffer pointer moved forward
1023    #   @retval False       Not able to find a decimal data, file buffer pointer not changed
1024    #
1025    def __GetNextDecimalNumber(self):
1026        if not self.__GetNextToken():
1027            return False
1028        if self.__Token.isdigit():
1029            return True
1030        else:
1031            self.__UndoToken()
1032            return False
1033
1034    ## __GetNextPcdName() method
1035    #
1036    #   Get next PCD token space C name and PCD C name pair before a seperator
1037    #   If found, the decimal data is put into self.__Token
1038    #
1039    #   @param  self        The object pointer
1040    #   @retval Tuple       PCD C name and PCD token space C name pair
1041    #
1042    def __GetNextPcdName(self):
1043        if not self.__GetNextWord():
1044            raise Warning("expected PcdTokenSpaceCName.PcdCName At Line ", self.FileName, self.CurrentLineNumber)
1045        pcdTokenSpaceCName = self.__Token
1046
1047        if not self.__IsToken( "."):
1048            raise Warning("expected PcdTokenSpaceCName.PcdCName At Line ", self.FileName, self.CurrentLineNumber)
1049
1050        if not self.__GetNextWord():
1051            raise Warning("expected PcdTokenSpaceCName.PcdCName At Line ", self.FileName, self.CurrentLineNumber)
1052        pcdCName = self.__Token
1053
1054        return (pcdCName, pcdTokenSpaceCName)
1055
1056    ## __GetStringData() method
1057    #
1058    #   Get string contents quoted in ""
1059    #   If found, the decimal data is put into self.__Token
1060    #
1061    #   @param  self        The object pointer
1062    #   @retval True        Successfully find a string data, file buffer pointer moved forward
1063    #   @retval False       Not able to find a string data, file buffer pointer not changed
1064    #
1065    def __GetStringData(self):
1066        if self.__Token.startswith("\"") or self.__Token.startswith("L\""):
1067            self.__UndoToken()
1068            self.__SkipToToken("\"")
1069            currentLineNumber = self.CurrentLineNumber
1070
1071            if not self.__SkipToToken("\""):
1072                raise Warning("Missing Quote \" for String At Line ", self.FileName, self.CurrentLineNumber)
1073            if currentLineNumber != self.CurrentLineNumber:
1074                raise Warning("Missing Quote \" for String At Line ", self.FileName, self.CurrentLineNumber)
1075            self.__Token = self.__SkippedChars.rstrip('\"')
1076            return True
1077
1078        elif self.__Token.startswith("\'") or self.__Token.startswith("L\'"):
1079            self.__UndoToken()
1080            self.__SkipToToken("\'")
1081            currentLineNumber = self.CurrentLineNumber
1082
1083            if not self.__SkipToToken("\'"):
1084                raise Warning("Missing Quote \' for String At Line ", self.FileName, self.CurrentLineNumber)
1085            if currentLineNumber != self.CurrentLineNumber:
1086                raise Warning("Missing Quote \' for String At Line ", self.FileName, self.CurrentLineNumber)
1087            self.__Token = self.__SkippedChars.rstrip('\'')
1088            return True
1089
1090        else:
1091            return False
1092
1093    ## __SkipToToken() method
1094    #
1095    #   Search forward in file buffer for the string
1096    #   The skipped chars are put into self.__SkippedChars
1097    #
1098    #   @param  self        The object pointer
1099    #   @param  String      The string to search
1100    #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive
1101    #   @retval True        Successfully find the string, file buffer pointer moved forward
1102    #   @retval False       Not able to find the string, file buffer pointer not changed
1103    #
1104    def __SkipToToken(self, String, IgnoreCase = False):
1105        StartPos = self.GetFileBufferPos()
1106
1107        self.__SkippedChars = ""
1108        while not self.__EndOfFile():
1109            index = -1
1110            if IgnoreCase:
1111                index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper())
1112            else:
1113                index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String)
1114            if index == 0:
1115                self.CurrentOffsetWithinLine += len(String)
1116                self.__SkippedChars += String
1117                return True
1118            self.__SkippedChars += str(self.__CurrentChar())
1119            self.__GetOneChar()
1120
1121        self.SetFileBufferPos( StartPos)
1122        self.__SkippedChars = ""
1123        return False
1124
1125    ## GetFileBufferPos() method
1126    #
1127    #   Return the tuple of current line and offset within the line
1128    #
1129    #   @param  self        The object pointer
1130    #   @retval Tuple       Line number and offset pair
1131    #
1132    def GetFileBufferPos(self):
1133        return (self.CurrentLineNumber, self.CurrentOffsetWithinLine)
1134
1135    ## SetFileBufferPos() method
1136    #
1137    #   Restore the file buffer position
1138    #
1139    #   @param  self        The object pointer
1140    #   @param  Pos         The new file buffer position
1141    #
1142    def SetFileBufferPos(self, Pos):
1143        (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos
1144
1145    ## ParseFile() method
1146    #
1147    #   Parse the file profile buffer to extract fd, fv ... information
1148    #   Exception will be raised if syntax error found
1149    #
1150    #   @param  self        The object pointer
1151    #
1152    def ParseFile(self):
1153
1154        try:
1155            self.__StringToList()
1156            self.PreprocessFile()
1157            self.PreprocessIncludeFile()
1158            self.__StringToList()
1159            self.PreprocessFile()
1160            self.PreprocessConditionalStatement()
1161            self.__StringToList()
1162            for Pos in self.__WipeOffArea:
1163                self.__ReplaceFragment(Pos[0], Pos[1])
1164            self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
1165
1166            while self.__GetDefines():
1167                pass
1168
1169            Index = 0
1170            while Index < len(self.Profile.FileLinesList):
1171                FileLineTuple = GetRealFileLine(self.FileName, Index + 1)
1172                self.Profile.FileLinesList[Index] = self.__ReplaceMacros(self.Profile.FileLinesList[Index], FileLineTuple[0], FileLineTuple[1])
1173                Index += 1
1174
1175            while self.__GetFd():
1176                pass
1177
1178            while self.__GetFv():
1179                pass
1180
1181            while self.__GetCapsule():
1182                pass
1183
1184#            while self.__GetVtf():
1185#                pass
1186#
1187#            while self.__GetRule():
1188#                pass
1189
1190
1191        except Warning, X:
1192            self.__UndoToken()
1193            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1194            X.message += '\nGot Token: \"%s\" from File %s\n' % (self.__Token, FileLineTuple[0]) + \
1195                'Previous Token: \"%s\" At line: %d, Offset Within Line: %d\n' \
1196                    % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :].rstrip('\n').rstrip('\r'), FileLineTuple[1], self.CurrentOffsetWithinLine)
1197            raise
1198
1199    ## __GetDefines() method
1200    #
1201    #   Get Defines section contents and store its data into AllMacrosList
1202    #
1203    #   @param  self        The object pointer
1204    #   @retval True        Successfully find a Defines
1205    #   @retval False       Not able to find a Defines
1206    #
1207    def __GetDefines(self):
1208
1209        if not self.__GetNextToken():
1210            return False
1211
1212        S = self.__Token.upper()
1213        if S.startswith("[") and not S.startswith("[DEFINES"):
1214            if not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \
1215                and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
1216                raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
1217            self.__UndoToken()
1218            return False
1219
1220        self.__UndoToken()
1221        if not self.__IsToken("[DEFINES", True):
1222            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1223            #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1224            #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1225            raise Warning("expected [DEFINES", self.FileName, self.CurrentLineNumber)
1226
1227        if not self.__IsToken( "]"):
1228            raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
1229
1230        while self.__GetNextWord():
1231            Macro = self.__Token
1232
1233            if not self.__IsToken("="):
1234                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1235            if not self.__GetNextToken() or self.__Token.startswith('['):
1236                raise Warning("expected MACRO value", self.FileName, self.CurrentLineNumber)
1237            Value = self.__Token
1238            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1239            MacProfile = MacroProfile(FileLineTuple[0], FileLineTuple[1])
1240            MacProfile.MacroName = Macro
1241            MacProfile.MacroValue = Value
1242            AllMacroList.append(MacProfile)
1243
1244        return False
1245
1246    ## __GetFd() method
1247    #
1248    #   Get FD section contents and store its data into FD dictionary of self.Profile
1249    #
1250    #   @param  self        The object pointer
1251    #   @retval True        Successfully find a FD
1252    #   @retval False       Not able to find a FD
1253    #
1254    def __GetFd(self):
1255
1256        if not self.__GetNextToken():
1257            return False
1258
1259        S = self.__Token.upper()
1260        if S.startswith("[") and not S.startswith("[FD."):
1261            if not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \
1262                and not S.startswith("[VTF.") and not S.startswith("[RULE."):
1263                raise Warning("Unknown section At Line ", self.FileName, self.CurrentLineNumber)
1264            self.__UndoToken()
1265            return False
1266
1267        self.__UndoToken()
1268        if not self.__IsToken("[FD.", True):
1269            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1270            print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1271                    % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1272            raise Warning("expected [FD.] At Line ", self.FileName, self.CurrentLineNumber)
1273
1274        FdName = self.__GetUiName()
1275        self.CurrentFdName = FdName.upper()
1276
1277        if not self.__IsToken( "]"):
1278            raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber)
1279
1280        FdObj = CommonDataClass.FdfClass.FDClassObject()
1281        FdObj.FdUiName = self.CurrentFdName
1282        self.Profile.FdDict[self.CurrentFdName] = FdObj
1283        Status = self.__GetCreateFile(FdObj)
1284        if not Status:
1285            raise Warning("FD name error At Line ", self.FileName, self.CurrentLineNumber)
1286
1287        if not self.__GetTokenStatements(FdObj):
1288            return False
1289
1290        self.__GetDefineStatements(FdObj)
1291
1292        self.__GetSetStatements(FdObj)
1293
1294        if not self.__GetRegionLayout(FdObj):
1295            raise Warning("expected region layout At Line ", self.FileName, self.CurrentLineNumber)
1296
1297        while self.__GetRegionLayout(FdObj):
1298            pass
1299        return True
1300
1301    ## __GetUiName() method
1302    #
1303    #   Return the UI name of a section
1304    #
1305    #   @param  self        The object pointer
1306    #   @retval FdName      UI name
1307    #
1308    def __GetUiName(self):
1309        FdName = ""
1310        if self.__GetNextWord():
1311            FdName = self.__Token
1312
1313        return FdName
1314
1315    ## __GetCreateFile() method
1316    #
1317    #   Return the output file name of object
1318    #
1319    #   @param  self        The object pointer
1320    #   @param  Obj         object whose data will be stored in file
1321    #   @retval FdName      UI name
1322    #
1323    def __GetCreateFile(self, Obj):
1324
1325        if self.__IsKeyword( "CREATE_FILE"):
1326            if not self.__IsToken( "="):
1327                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1328
1329            if not self.__GetNextToken():
1330                raise Warning("expected file name At Line ", self.FileName, self.CurrentLineNumber)
1331
1332            FileName = self.__Token
1333            Obj.CreateFileName = FileName
1334
1335        return True
1336
1337    ## __GetTokenStatements() method
1338    #
1339    #   Get token statements
1340    #
1341    #   @param  self        The object pointer
1342    #   @param  Obj         for whom token statement is got
1343    #   @retval True        Successfully find a token statement
1344    #   @retval False       Not able to find a token statement
1345    #
1346    def __GetTokenStatements(self, Obj):
1347        if not self.__IsKeyword( "BaseAddress"):
1348            raise Warning("BaseAddress missing At Line ", self.FileName, self.CurrentLineNumber)
1349
1350        if not self.__IsToken( "="):
1351            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1352
1353        if not self.__GetNextHexNumber():
1354            raise Warning("expected Hex base address At Line ", self.FileName, self.CurrentLineNumber)
1355
1356        Obj.BaseAddress = self.__Token
1357
1358        if self.__IsToken( "|"):
1359            pcdPair = self.__GetNextPcdName()
1360            Obj.BaseAddressPcd = pcdPair
1361            self.Profile.PcdDict[pcdPair] = long(Obj.BaseAddress, 0)
1362            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1363            self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1364
1365        if not self.__IsKeyword( "Size"):
1366            raise Warning("Size missing At Line ", self.FileName, self.CurrentLineNumber)
1367
1368        if not self.__IsToken( "="):
1369            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1370
1371        if not self.__GetNextHexNumber():
1372            raise Warning("expected Hex size At Line ", self.FileName, self.CurrentLineNumber)
1373
1374
1375        Obj.Size = long(self.__Token, 0)
1376
1377        if self.__IsToken( "|"):
1378            pcdPair = self.__GetNextPcdName()
1379            Obj.SizePcd = pcdPair
1380            self.Profile.PcdDict[pcdPair] = Obj.Size
1381            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1382            self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1383
1384        if not self.__IsKeyword( "ErasePolarity"):
1385            raise Warning("ErasePolarity missing At Line ", self.FileName, self.CurrentLineNumber)
1386
1387        if not self.__IsToken( "="):
1388            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1389
1390        if not self.__GetNextToken():
1391            raise Warning("expected Erase Polarity At Line ", self.FileName, self.CurrentLineNumber)
1392
1393        if self.__Token != "1" and self.__Token != "0":
1394            raise Warning("expected 1 or 0 Erase Polarity At Line ", self.FileName, self.CurrentLineNumber)
1395
1396        Obj.ErasePolarity = self.__Token
1397
1398        Status = self.__GetBlockStatements(Obj)
1399        return Status
1400
1401    ## __GetAddressStatements() method
1402    #
1403    #   Get address statements
1404    #
1405    #   @param  self        The object pointer
1406    #   @param  Obj         for whom address statement is got
1407    #   @retval True        Successfully find
1408    #   @retval False       Not able to find
1409    #
1410    def __GetAddressStatements(self, Obj):
1411
1412        if self.__IsKeyword("BsBaseAddress"):
1413            if not self.__IsToken( "="):
1414                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1415
1416            if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1417                raise Warning("expected address At Line ", self.FileName, self.CurrentLineNumber)
1418
1419            BsAddress = long(self.__Token, 0)
1420            Obj.BsBaseAddress = BsAddress
1421
1422        if self.__IsKeyword("RtBaseAddress"):
1423            if not self.__IsToken( "="):
1424                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1425
1426            if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1427                raise Warning("expected address At Line ", self.FileName, self.CurrentLineNumber)
1428
1429            RtAddress = long(self.__Token, 0)
1430            Obj.RtBaseAddress = RtAddress
1431
1432    ## __GetBlockStatements() method
1433    #
1434    #   Get block statements
1435    #
1436    #   @param  self        The object pointer
1437    #   @param  Obj         for whom block statement is got
1438    #   @retval True        Successfully find
1439    #   @retval False       Not able to find
1440    #
1441    def __GetBlockStatements(self, Obj):
1442
1443        if not self.__GetBlockStatement(Obj):
1444            #set default block size is 1
1445            Obj.BlockSizeList.append((1, Obj.Size, None))
1446            return True
1447
1448        while self.__GetBlockStatement(Obj):
1449            pass
1450
1451        for Item in Obj.BlockSizeList:
1452            if Item[0] == None or Item[1] == None:
1453                raise Warning("expected block statement for Fd Section", self.FileName, self.CurrentLineNumber)
1454
1455        return True
1456
1457    ## __GetBlockStatement() method
1458    #
1459    #   Get block statement
1460    #
1461    #   @param  self        The object pointer
1462    #   @param  Obj         for whom block statement is got
1463    #   @retval True        Successfully find
1464    #   @retval False       Not able to find
1465    #
1466    def __GetBlockStatement(self, Obj):
1467        if not self.__IsKeyword( "BlockSize"):
1468            return False
1469
1470        if not self.__IsToken( "="):
1471            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1472
1473        if not self.__GetNextHexNumber() and not self.__GetNextDecimalNumber():
1474            raise Warning("expected Hex block size At Line ", self.FileName, self.CurrentLineNumber)
1475
1476        BlockSize = long(self.__Token, 0)
1477        BlockSizePcd = None
1478        if self.__IsToken( "|"):
1479            PcdPair = self.__GetNextPcdName()
1480            BlockSizePcd = PcdPair
1481            self.Profile.PcdDict[PcdPair] = BlockSize
1482            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1483            self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1484
1485        BlockNumber = None
1486        if self.__IsKeyword( "NumBlocks"):
1487            if not self.__IsToken( "="):
1488                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1489
1490            if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1491                raise Warning("expected block numbers At Line ", self.FileName, self.CurrentLineNumber)
1492
1493            BlockNumber = long(self.__Token, 0)
1494
1495        Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd))
1496        return True
1497
1498    ## __GetDefineStatements() method
1499    #
1500    #   Get define statements
1501    #
1502    #   @param  self        The object pointer
1503    #   @param  Obj         for whom define statement is got
1504    #   @retval True        Successfully find
1505    #   @retval False       Not able to find
1506    #
1507    def __GetDefineStatements(self, Obj):
1508        while self.__GetDefineStatement( Obj):
1509            pass
1510
1511    ## __GetDefineStatement() method
1512    #
1513    #   Get define statement
1514    #
1515    #   @param  self        The object pointer
1516    #   @param  Obj         for whom define statement is got
1517    #   @retval True        Successfully find
1518    #   @retval False       Not able to find
1519    #
1520    def __GetDefineStatement(self, Obj):
1521        if self.__IsKeyword("DEFINE"):
1522            self.__GetNextToken()
1523            Macro = self.__Token
1524            if not self.__IsToken( "="):
1525                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1526
1527            if not self.__GetNextToken():
1528                raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber)
1529
1530            Value = self.__Token
1531            Macro = '$(' + Macro + ')'
1532            Obj.DefineVarDict[Macro] = Value
1533            return True
1534
1535        return False
1536
1537    ## __GetSetStatements() method
1538    #
1539    #   Get set statements
1540    #
1541    #   @param  self        The object pointer
1542    #   @param  Obj         for whom set statement is got
1543    #   @retval True        Successfully find
1544    #   @retval False       Not able to find
1545    #
1546    def __GetSetStatements(self, Obj):
1547        while self.__GetSetStatement(Obj):
1548            pass
1549
1550    ## __GetSetStatement() method
1551    #
1552    #   Get set statement
1553    #
1554    #   @param  self        The object pointer
1555    #   @param  Obj         for whom set statement is got
1556    #   @retval True        Successfully find
1557    #   @retval False       Not able to find
1558    #
1559    def __GetSetStatement(self, Obj):
1560        if self.__IsKeyword("SET"):
1561            PcdPair = self.__GetNextPcdName()
1562
1563            if not self.__IsToken( "="):
1564                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1565
1566            if not self.__GetNextToken():
1567                raise Warning("expected value At Line ", self.FileName, self.CurrentLineNumber)
1568
1569            Value = self.__Token
1570            if Value.startswith("{"):
1571                # deal with value with {}
1572                if not self.__SkipToToken( "}"):
1573                    raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
1574                Value += self.__SkippedChars
1575
1576            Obj.SetVarDict[PcdPair] = Value
1577            self.Profile.PcdDict[PcdPair] = Value
1578            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1579            self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
1580            return True
1581
1582        return False
1583
1584    ## __GetRegionLayout() method
1585    #
1586    #   Get region layout for FD
1587    #
1588    #   @param  self        The object pointer
1589    #   @param  Fd          for whom region is got
1590    #   @retval True        Successfully find
1591    #   @retval False       Not able to find
1592    #
1593    def __GetRegionLayout(self, Fd):
1594        if not self.__GetNextHexNumber():
1595            return False
1596
1597        RegionObj = CommonDataClass.FdfClass.RegionClassObject()
1598        RegionObj.Offset = long(self.__Token, 0)
1599        Fd.RegionList.append(RegionObj)
1600
1601        if not self.__IsToken( "|"):
1602            raise Warning("expected '|' At Line ", self.FileName, self.CurrentLineNumber)
1603
1604        if not self.__GetNextHexNumber():
1605            raise Warning("expected Region Size At Line ", self.FileName, self.CurrentLineNumber)
1606        RegionObj.Size = long(self.__Token, 0)
1607
1608        if not self.__GetNextWord():
1609            return True
1610
1611        if not self.__Token in ("SET", "FV", "FILE", "DATA", "CAPSULE"):
1612            self.__UndoToken()
1613            RegionObj.PcdOffset = self.__GetNextPcdName()
1614            self.Profile.PcdDict[RegionObj.PcdOffset] = RegionObj.Offset + long(Fd.BaseAddress, 0)
1615            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1616            self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple
1617            if self.__IsToken( "|"):
1618                RegionObj.PcdSize = self.__GetNextPcdName()
1619                self.Profile.PcdDict[RegionObj.PcdSize] = RegionObj.Size
1620                FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1621                self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple
1622
1623            if not self.__GetNextWord():
1624                return True
1625
1626        if self.__Token == "SET":
1627            self.__UndoToken()
1628            self.__GetSetStatements( RegionObj)
1629            if not self.__GetNextWord():
1630                return True
1631
1632        elif self.__Token == "FV":
1633            self.__UndoToken()
1634            self.__GetRegionFvType( RegionObj)
1635
1636        elif self.__Token == "CAPSULE":
1637            self.__UndoToken()
1638            self.__GetRegionCapType( RegionObj)
1639
1640        elif self.__Token == "FILE":
1641            self.__UndoToken()
1642            self.__GetRegionFileType( RegionObj)
1643
1644        else:
1645            self.__UndoToken()
1646            self.__GetRegionDataType( RegionObj)
1647
1648        return True
1649
1650    ## __GetRegionFvType() method
1651    #
1652    #   Get region fv data for region
1653    #
1654    #   @param  self        The object pointer
1655    #   @param  RegionObj   for whom region data is got
1656    #
1657    def __GetRegionFvType(self, RegionObj):
1658
1659        if not self.__IsKeyword( "FV"):
1660            raise Warning("expected Keyword 'FV' At Line ", self.FileName, self.CurrentLineNumber)
1661
1662        if not self.__IsToken( "="):
1663            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1664
1665        if not self.__GetNextToken():
1666            raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber)
1667
1668        RegionObj.RegionType = "FV"
1669        RegionObj.RegionDataList.append(self.__Token)
1670
1671        while self.__IsKeyword( "FV"):
1672
1673            if not self.__IsToken( "="):
1674                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1675
1676            if not self.__GetNextToken():
1677                raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber)
1678
1679            RegionObj.RegionDataList.append(self.__Token)
1680
1681    ## __GetRegionCapType() method
1682    #
1683    #   Get region capsule data for region
1684    #
1685    #   @param  self        The object pointer
1686    #   @param  RegionObj   for whom region data is got
1687    #
1688    def __GetRegionCapType(self, RegionObj):
1689
1690        if not self.__IsKeyword("CAPSULE"):
1691            raise Warning("expected Keyword 'CAPSULE' at line", self.FileName, self.CurrentLineNumber)
1692
1693        if not self.__IsToken("="):
1694            raise Warning("expected '=' at line", self.FileName, self.CurrentLineNumber)
1695
1696        if not self.__GetNextToken():
1697            raise Warning("expected CAPSULE name at line", self.FileName, self.CurrentLineNumber)
1698
1699        RegionObj.RegionType = "CAPSULE"
1700        RegionObj.RegionDataList.append(self.__Token)
1701
1702        while self.__IsKeyword("CAPSULE"):
1703
1704            if not self.__IsToken("="):
1705                raise Warning("expected '=' at line", self.FileName, self.CurrentLineNumber)
1706
1707            if not self.__GetNextToken():
1708                raise Warning("expected CAPSULE name at line", self.FileName, self.CurrentLineNumber)
1709
1710            RegionObj.RegionDataList.append(self.__Token)
1711
1712    ## __GetRegionFileType() method
1713    #
1714    #   Get region file data for region
1715    #
1716    #   @param  self        The object pointer
1717    #   @param  RegionObj   for whom region data is got
1718    #
1719    def __GetRegionFileType(self, RegionObj):
1720
1721        if not self.__IsKeyword( "FILE"):
1722            raise Warning("expected Keyword 'FILE' At Line ", self.FileName, self.CurrentLineNumber)
1723
1724        if not self.__IsToken( "="):
1725            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1726
1727        if not self.__GetNextToken():
1728            raise Warning("expected File name At Line ", self.FileName, self.CurrentLineNumber)
1729
1730        RegionObj.RegionType = "FILE"
1731        RegionObj.RegionDataList.append( self.__Token)
1732
1733        while self.__IsKeyword( "FILE"):
1734
1735            if not self.__IsToken( "="):
1736                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1737
1738            if not self.__GetNextToken():
1739                raise Warning("expected FILE name At Line ", self.FileName, self.CurrentLineNumber)
1740
1741            RegionObj.RegionDataList.append(self.__Token)
1742
1743    ## __GetRegionDataType() method
1744    #
1745    #   Get region array data for region
1746    #
1747    #   @param  self        The object pointer
1748    #   @param  RegionObj   for whom region data is got
1749    #
1750    def __GetRegionDataType(self, RegionObj):
1751
1752        if not self.__IsKeyword( "DATA"):
1753            raise Warning("expected Region Data type At Line ", self.FileName, self.CurrentLineNumber)
1754
1755        if not self.__IsToken( "="):
1756            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1757
1758        if not self.__IsToken( "{"):
1759            raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
1760
1761        if not self.__GetNextHexNumber():
1762            raise Warning("expected Hex byte At Line ", self.FileName, self.CurrentLineNumber)
1763
1764        if len(self.__Token) > 18:
1765            raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
1766
1767        DataString = self.__Token
1768        DataString += ","
1769
1770        while self.__IsToken(","):
1771            if not self.__GetNextHexNumber():
1772                raise Warning("Invalid Hex number At Line ", self.FileName, self.CurrentLineNumber)
1773            if len(self.__Token) > 4:
1774                raise Warning("Hex byte(must be 2 digits) too long At Line ", self.FileName, self.CurrentLineNumber)
1775            DataString += self.__Token
1776            DataString += ","
1777
1778        if not self.__IsToken( "}"):
1779            raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
1780
1781        DataString = DataString.rstrip(",")
1782        RegionObj.RegionType = "DATA"
1783        RegionObj.RegionDataList.append( DataString)
1784
1785        while self.__IsKeyword( "DATA"):
1786
1787            if not self.__IsToken( "="):
1788                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1789
1790            if not self.__IsToken( "{"):
1791                raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
1792
1793            if not self.__GetNextHexNumber():
1794                raise Warning("expected Hex byte At Line ", self.FileName, self.CurrentLineNumber)
1795
1796            if len(self.__Token) > 18:
1797                raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
1798
1799            DataString = self.__Token
1800            DataString += ","
1801
1802            while self.__IsToken(","):
1803                self.__GetNextHexNumber()
1804                if len(self.__Token) > 4:
1805                    raise Warning("Hex byte(must be 2 digits) too long At Line ", self.FileName, self.CurrentLineNumber)
1806                DataString += self.__Token
1807                DataString += ","
1808
1809            if not self.__IsToken( "}"):
1810                raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
1811
1812            DataString = DataString.rstrip(",")
1813            RegionObj.RegionDataList.append( DataString)
1814
1815    ## __GetFv() method
1816    #
1817    #   Get FV section contents and store its data into FV dictionary of self.Profile
1818    #
1819    #   @param  self        The object pointer
1820    #   @retval True        Successfully find a FV
1821    #   @retval False       Not able to find a FV
1822    #
1823    def __GetFv(self):
1824        if not self.__GetNextToken():
1825            return False
1826
1827        S = self.__Token.upper()
1828        if S.startswith("[") and not S.startswith("[FV."):
1829            if not S.startswith("[CAPSULE.") \
1830                and not S.startswith("[VTF.") and not S.startswith("[RULE."):
1831                raise Warning("Unknown section or section appear sequence error \n(The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.]) At Line ", self.FileName, self.CurrentLineNumber)
1832            self.__UndoToken()
1833            return False
1834
1835        self.__UndoToken()
1836        if not self.__IsToken("[FV.", True):
1837            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1838            print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1839                    % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1840            raise Warning("Unknown Keyword At Line ", self.FileName, self.CurrentLineNumber)
1841
1842        FvName = self.__GetUiName()
1843        self.CurrentFvName = FvName.upper()
1844
1845        if not self.__IsToken( "]"):
1846            raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber)
1847
1848        FvObj = CommonDataClass.FdfClass.FvClassObject()
1849        FvObj.UiFvName = self.CurrentFvName
1850        self.Profile.FvDict[self.CurrentFvName] = FvObj
1851
1852        Status = self.__GetCreateFile(FvObj)
1853        if not Status:
1854            raise Warning("FV name error At Line ", self.FileName, self.CurrentLineNumber)
1855
1856        self.__GetDefineStatements(FvObj)
1857
1858        self.__GetAddressStatements(FvObj)
1859
1860        self.__GetBlockStatement(FvObj)
1861
1862        self.__GetSetStatements(FvObj)
1863
1864        self.__GetFvAlignment(FvObj)
1865
1866        self.__GetFvAttributes(FvObj)
1867
1868        self.__GetFvNameGuid(FvObj)
1869
1870        self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy())
1871        self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy())
1872
1873        while True:
1874            isInf = self.__GetInfStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy())
1875            isFile = self.__GetFileStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy())
1876            if not isInf and not isFile:
1877                break
1878
1879        return True
1880
1881    ## __GetFvAlignment() method
1882    #
1883    #   Get alignment for FV
1884    #
1885    #   @param  self        The object pointer
1886    #   @param  Obj         for whom alignment is got
1887    #   @retval True        Successfully find a alignment statement
1888    #   @retval False       Not able to find a alignment statement
1889    #
1890    def __GetFvAlignment(self, Obj):
1891
1892        if not self.__IsKeyword( "FvAlignment"):
1893            return False
1894
1895        if not self.__IsToken( "="):
1896            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1897
1898        if not self.__GetNextToken():
1899            raise Warning("expected alignment value At Line ", self.FileName, self.CurrentLineNumber)
1900
1901        if self.__Token.upper() not in ("1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \
1902                                        "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \
1903                                        "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \
1904                                        "1G", "2G"):
1905            raise Warning("Unknown alignment value At Line ", self.FileName, self.CurrentLineNumber)
1906        Obj.FvAlignment = self.__Token
1907        return True
1908
1909    ## __GetFvAttributes() method
1910    #
1911    #   Get attributes for FV
1912    #
1913    #   @param  self        The object pointer
1914    #   @param  Obj         for whom attribute is got
1915    #   @retval None
1916    #
1917    def __GetFvAttributes(self, FvObj):
1918
1919        while self.__GetNextWord():
1920            name = self.__Token
1921            if name not in ("ERASE_POLARITY", "MEMORY_MAPPED", \
1922                           "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \
1923                           "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \
1924                           "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \
1925                           "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \
1926                           "WRITE_POLICY_RELIABLE"):
1927                self.__UndoToken()
1928                return
1929
1930            if not self.__IsToken( "="):
1931                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
1932
1933            if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"):
1934                raise Warning("expected TRUE/FALSE (1/0) At Line ", self.FileName, self.CurrentLineNumber)
1935
1936            FvObj.FvAttributeDict[name] = self.__Token
1937
1938        return
1939
1940    ## __GetFvNameGuid() method
1941    #
1942    #   Get FV GUID for FV
1943    #
1944    #   @param  self        The object pointer
1945    #   @param  Obj         for whom GUID is got
1946    #   @retval None
1947    #
1948    def __GetFvNameGuid(self, FvObj):
1949
1950        if not self.__IsKeyword( "FvNameGuid"):
1951            return
1952
1953        if not self.__IsToken( "="):
1954            raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1955
1956        if not self.__GetNextGuid():
1957            raise Warning("expected FV GUID value", self.FileName, self.CurrentLineNumber)
1958
1959        FvObj.FvNameGuid = self.__Token
1960
1961        return
1962
1963    ## __GetAprioriSection() method
1964    #
1965    #   Get token statements
1966    #
1967    #   @param  self        The object pointer
1968    #   @param  FvObj       for whom apriori is got
1969    #   @param  MacroDict   dictionary used to replace macro
1970    #   @retval True        Successfully find apriori statement
1971    #   @retval False       Not able to find apriori statement
1972    #
1973    def __GetAprioriSection(self, FvObj, MacroDict = {}):
1974
1975        if not self.__IsKeyword( "APRIORI"):
1976            return False
1977
1978        if not self.__IsKeyword("PEI") and not self.__IsKeyword("DXE"):
1979            raise Warning("expected Apriori file type At Line ", self.FileName, self.CurrentLineNumber)
1980        AprType = self.__Token
1981
1982        if not self.__IsToken( "{"):
1983            raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
1984
1985        AprSectionObj = CommonDataClass.FdfClass.AprioriSectionClassObject()
1986        AprSectionObj.AprioriType = AprType
1987
1988        self.__GetDefineStatements(AprSectionObj)
1989        MacroDict.update(AprSectionObj.DefineVarDict)
1990
1991        while True:
1992            IsInf = self.__GetInfStatement( AprSectionObj, MacroDict = MacroDict)
1993            IsFile = self.__GetFileStatement( AprSectionObj)
1994            if not IsInf and not IsFile:
1995                break
1996
1997        if not self.__IsToken( "}"):
1998            raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
1999
2000        FvObj.AprioriSectionList.append(AprSectionObj)
2001        return True
2002
2003    ## __GetInfStatement() method
2004    #
2005    #   Get INF statements
2006    #
2007    #   @param  self        The object pointer
2008    #   @param  Obj         for whom inf statement is got
2009    #   @param  MacroDict   dictionary used to replace macro
2010    #   @retval True        Successfully find inf statement
2011    #   @retval False       Not able to find inf statement
2012    #
2013    def __GetInfStatement(self, Obj, ForCapsule = False, MacroDict = {}):
2014
2015        if not self.__IsKeyword( "INF"):
2016            return False
2017
2018        ffsInf = CommonDataClass.FdfClass.FfsInfStatementClassObject()
2019        self.__GetInfOptions( ffsInf)
2020
2021        if not self.__GetNextToken():
2022            raise Warning("expected INF file path At Line ", self.FileName, self.CurrentLineNumber)
2023        ffsInf.InfFileName = self.__Token
2024
2025#        if ffsInf.InfFileName.find('$') >= 0:
2026#            ffsInf.InfFileName = GenFdsGlobalVariable.GenFdsGlobalVariable.MacroExtend(ffsInf.InfFileName, MacroDict)
2027
2028        if not ffsInf.InfFileName in self.Profile.InfList:
2029            self.Profile.InfList.append(ffsInf.InfFileName)
2030            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2031            self.Profile.InfFileLineList.append(FileLineTuple)
2032
2033        if self.__IsToken('|'):
2034            if self.__IsKeyword('RELOCS_STRIPPED'):
2035                ffsInf.KeepReloc = False
2036            elif self.__IsKeyword('RELOCS_RETAINED'):
2037                ffsInf.KeepReloc = True
2038            else:
2039                raise Warning("Unknown reloc strip flag At Line ", self.FileName, self.CurrentLineNumber)
2040
2041        if ForCapsule:
2042            capsuleFfs = CapsuleData.CapsuleFfs()
2043            capsuleFfs.Ffs = ffsInf
2044            Obj.CapsuleDataList.append(capsuleFfs)
2045        else:
2046            Obj.FfsList.append(ffsInf)
2047        return True
2048
2049    ## __GetInfOptions() method
2050    #
2051    #   Get options for INF
2052    #
2053    #   @param  self        The object pointer
2054    #   @param  FfsInfObj   for whom option is got
2055    #
2056    def __GetInfOptions(self, FfsInfObj):
2057
2058        if self.__IsKeyword( "RuleOverride"):
2059            if not self.__IsToken( "="):
2060                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2061            if not self.__GetNextToken():
2062                raise Warning("expected Rule name At Line ", self.FileName, self.CurrentLineNumber)
2063            FfsInfObj.Rule = self.__Token
2064
2065        if self.__IsKeyword( "VERSION"):
2066            if not self.__IsToken( "="):
2067                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2068            if not self.__GetNextToken():
2069                raise Warning("expected Version At Line ", self.FileName, self.CurrentLineNumber)
2070
2071            if self.__GetStringData():
2072                FfsInfObj.Version = self.__Token
2073
2074        if self.__IsKeyword( "UI"):
2075            if not self.__IsToken( "="):
2076                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2077            if not self.__GetNextToken():
2078                raise Warning("expected UI name At Line ", self.FileName, self.CurrentLineNumber)
2079
2080            if self.__GetStringData():
2081                FfsInfObj.Ui = self.__Token
2082
2083        if self.__IsKeyword( "USE"):
2084            if not self.__IsToken( "="):
2085                raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2086            if not self.__GetNextToken():
2087                raise Warning("expected ARCH name", self.FileName, self.CurrentLineNumber)
2088            FfsInfObj.UseArch = self.__Token
2089
2090
2091        if self.__GetNextToken():
2092            p = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
2093            if p.match(self.__Token):
2094                FfsInfObj.KeyStringList.append(self.__Token)
2095                if not self.__IsToken(","):
2096                    return
2097            else:
2098                self.__UndoToken()
2099                return
2100
2101            while self.__GetNextToken():
2102                if not p.match(self.__Token):
2103                    raise Warning("expected KeyString \"Target_Tag_Arch\" At Line ", self.FileName, self.CurrentLineNumber)
2104                FfsInfObj.KeyStringList.append(self.__Token)
2105
2106                if not self.__IsToken(","):
2107                    break
2108
2109    ## __GetFileStatement() method
2110    #
2111    #   Get FILE statements
2112    #
2113    #   @param  self        The object pointer
2114    #   @param  Obj         for whom FILE statement is got
2115    #   @param  MacroDict   dictionary used to replace macro
2116    #   @retval True        Successfully find FILE statement
2117    #   @retval False       Not able to find FILE statement
2118    #
2119    def __GetFileStatement(self, Obj, ForCapsule = False, MacroDict = {}):
2120
2121        if not self.__IsKeyword( "FILE"):
2122            return False
2123
2124        FfsFileObj = CommonDataClass.FdfClass.FileStatementClassObject()
2125
2126        if not self.__GetNextWord():
2127            raise Warning("expected FFS type At Line ", self.FileName, self.CurrentLineNumber)
2128        FfsFileObj.FvFileType = self.__Token
2129
2130        if not self.__IsToken( "="):
2131            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2132
2133        if not self.__GetNextGuid():
2134            if not self.__GetNextWord():
2135                raise Warning("expected File GUID", self.FileName, self.CurrentLineNumber)
2136            if self.__Token == 'PCD':
2137                if not self.__IsToken( "("):
2138                    raise Warning("expected '('", self.FileName, self.CurrentLineNumber)
2139                PcdPair = self.__GetNextPcdName()
2140                if not self.__IsToken( ")"):
2141                    raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
2142                self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')'
2143
2144        FfsFileObj.NameGuid = self.__Token
2145
2146        self.__GetFilePart( FfsFileObj, MacroDict.copy())
2147
2148        if ForCapsule:
2149            capsuleFfs = CapsuleData.CapsuleFfs()
2150            capsuleFfs.Ffs = FfsFileObj
2151            Obj.CapsuleDataList.append(capsuleFfs)
2152        else:
2153            Obj.FfsList.append(FfsFileObj)
2154
2155        return True
2156
2157    ## __FileCouldHaveRelocFlag() method
2158    #
2159    #   Check whether reloc strip flag can be set for a file type.
2160    #
2161    #   @param  self        The object pointer
2162    #   @param  FileType    The file type to check with
2163    #   @retval True        This type could have relocation strip flag
2164    #   @retval False       No way to have it
2165    #
2166
2167    def __FileCouldHaveRelocFlag (self, FileType):
2168        if FileType in ('SEC', 'PEI_CORE', 'PEIM', 'PEI_DXE_COMBO'):
2169            return True
2170        else:
2171            return False
2172
2173    ## __SectionCouldHaveRelocFlag() method
2174    #
2175    #   Check whether reloc strip flag can be set for a section type.
2176    #
2177    #   @param  self        The object pointer
2178    #   @param  SectionType The section type to check with
2179    #   @retval True        This type could have relocation strip flag
2180    #   @retval False       No way to have it
2181    #
2182
2183    def __SectionCouldHaveRelocFlag (self, SectionType):
2184        if SectionType in ('TE', 'PE32'):
2185            return True
2186        else:
2187            return False
2188
2189    ## __GetFilePart() method
2190    #
2191    #   Get components for FILE statement
2192    #
2193    #   @param  self        The object pointer
2194    #   @param  FfsFileObj   for whom component is got
2195    #   @param  MacroDict   dictionary used to replace macro
2196    #
2197    def __GetFilePart(self, FfsFileObj, MacroDict = {}):
2198
2199        self.__GetFileOpts( FfsFileObj)
2200
2201        if not self.__IsToken("{"):
2202#            if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
2203#                if self.__FileCouldHaveRelocFlag(FfsFileObj.FvFileType):
2204#                    if self.__Token == 'RELOCS_STRIPPED':
2205#                        FfsFileObj.KeepReloc = False
2206#                    else:
2207#                        FfsFileObj.KeepReloc = True
2208#                else:
2209#                    raise Warning("File type %s could not have reloc strip flag At Line %d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
2210#
2211#            if not self.__IsToken("{"):
2212            raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
2213
2214        if not self.__GetNextToken():
2215            raise Warning("expected File name or section data At Line ", self.FileName, self.CurrentLineNumber)
2216
2217        if self.__Token == "FV":
2218            if not self.__IsToken( "="):
2219                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2220            if not self.__GetNextToken():
2221                raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber)
2222            FfsFileObj.FvName = self.__Token
2223
2224        elif self.__Token == "FD":
2225            if not self.__IsToken( "="):
2226                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2227            if not self.__GetNextToken():
2228                raise Warning("expected FD name At Line ", self.FileName, self.CurrentLineNumber)
2229            FfsFileObj.FdName = self.__Token
2230
2231        elif self.__Token in ("DEFINE", "APRIORI", "SECTION"):
2232            self.__UndoToken()
2233            self.__GetSectionData( FfsFileObj, MacroDict)
2234        else:
2235            FfsFileObj.FileName = self.__Token
2236
2237        if not self.__IsToken( "}"):
2238            raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
2239
2240    ## __GetFileOpts() method
2241    #
2242    #   Get options for FILE statement
2243    #
2244    #   @param  self        The object pointer
2245    #   @param  FfsFileObj   for whom options is got
2246    #
2247    def __GetFileOpts(self, FfsFileObj):
2248
2249        if self.__GetNextToken():
2250            Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
2251            if Pattern.match(self.__Token):
2252                FfsFileObj.KeyStringList.append(self.__Token)
2253                if self.__IsToken(","):
2254                    while self.__GetNextToken():
2255                        if not Pattern.match(self.__Token):
2256                            raise Warning("expected KeyString \"Target_Tag_Arch\" At Line ", self.FileName, self.CurrentLineNumber)
2257                        FfsFileObj.KeyStringList.append(self.__Token)
2258
2259                        if not self.__IsToken(","):
2260                            break
2261
2262            else:
2263                self.__UndoToken()
2264
2265        if self.__IsKeyword( "FIXED", True):
2266            FfsFileObj.Fixed = True
2267
2268        if self.__IsKeyword( "CHECKSUM", True):
2269            FfsFileObj.CheckSum = True
2270
2271        if self.__GetAlignment():
2272            FfsFileObj.Alignment = self.__Token
2273
2274
2275
2276    ## __GetAlignment() method
2277    #
2278    #   Return the alignment value
2279    #
2280    #   @param  self        The object pointer
2281    #   @retval True        Successfully find alignment
2282    #   @retval False       Not able to find alignment
2283    #
2284    def __GetAlignment(self):
2285        if self.__IsKeyword( "Align", True):
2286            if not self.__IsToken( "="):
2287                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2288
2289            if not self.__GetNextToken():
2290                raise Warning("expected alignment value At Line ", self.FileName, self.CurrentLineNumber)
2291            return True
2292
2293        return False
2294
2295    ## __GetFilePart() method
2296    #
2297    #   Get section data for FILE statement
2298    #
2299    #   @param  self        The object pointer
2300    #   @param  FfsFileObj   for whom section is got
2301    #   @param  MacroDict   dictionary used to replace macro
2302    #
2303    def __GetSectionData(self, FfsFileObj, MacroDict = {}):
2304        Dict = {}
2305        Dict.update(MacroDict)
2306
2307        self.__GetDefineStatements(FfsFileObj)
2308
2309        Dict.update(FfsFileObj.DefineVarDict)
2310        self.__GetAprioriSection(FfsFileObj, Dict.copy())
2311        self.__GetAprioriSection(FfsFileObj, Dict.copy())
2312
2313        while True:
2314            IsLeafSection = self.__GetLeafSection(FfsFileObj, Dict)
2315            IsEncapSection = self.__GetEncapsulationSec(FfsFileObj)
2316            if not IsLeafSection and not IsEncapSection:
2317                break
2318
2319    ## __GetLeafSection() method
2320    #
2321    #   Get leaf section for Obj
2322    #
2323    #   @param  self        The object pointer
2324    #   @param  Obj         for whom leaf section is got
2325    #   @param  MacroDict   dictionary used to replace macro
2326    #   @retval True        Successfully find section statement
2327    #   @retval False       Not able to find section statement
2328    #
2329    def __GetLeafSection(self, Obj, MacroDict = {}):
2330
2331        OldPos = self.GetFileBufferPos()
2332
2333        if not self.__IsKeyword( "SECTION"):
2334            if len(Obj.SectionList) == 0:
2335                raise Warning("expected SECTION At Line ", self.FileName, self.CurrentLineNumber)
2336            else:
2337                return False
2338
2339        AlignValue = None
2340        if self.__GetAlignment():
2341            if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
2342                raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2343            AlignValue = self.__Token
2344
2345        BuildNum = None
2346        if self.__IsKeyword( "BUILD_NUM"):
2347            if not self.__IsToken( "="):
2348                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2349
2350            if not self.__GetNextToken():
2351                raise Warning("expected Build number value At Line ", self.FileName, self.CurrentLineNumber)
2352
2353            BuildNum = self.__Token
2354
2355        if self.__IsKeyword( "VERSION"):
2356            if AlignValue == 'Auto':
2357                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2358            if not self.__IsToken( "="):
2359                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2360            if not self.__GetNextToken():
2361                raise Warning("expected version At Line ", self.FileName, self.CurrentLineNumber)
2362            VerSectionObj = CommonDataClass.FdfClass.VerSectionClassObject()
2363            VerSectionObj.Alignment = AlignValue
2364            VerSectionObj.BuildNum = BuildNum
2365            if self.__GetStringData():
2366                VerSectionObj.StringData = self.__Token
2367            else:
2368                VerSectionObj.FileName = self.__Token
2369            Obj.SectionList.append(VerSectionObj)
2370
2371        elif self.__IsKeyword( "UI"):
2372            if AlignValue == 'Auto':
2373                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2374            if not self.__IsToken( "="):
2375                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2376            if not self.__GetNextToken():
2377                raise Warning("expected UI At Line ", self.FileName, self.CurrentLineNumber)
2378            UiSectionObj = CommonDataClass.FdfClass.UiSectionClassObject()
2379            UiSectionObj.Alignment = AlignValue
2380            if self.__GetStringData():
2381                UiSectionObj.StringData = self.__Token
2382            else:
2383                UiSectionObj.FileName = self.__Token
2384            Obj.SectionList.append(UiSectionObj)
2385
2386        elif self.__IsKeyword( "FV_IMAGE"):
2387            if AlignValue == 'Auto':
2388                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2389            if not self.__IsToken( "="):
2390                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2391            if not self.__GetNextWord():
2392                raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber)
2393
2394            FvName = self.__Token.upper()
2395            FvObj = None
2396
2397            if self.__IsToken( "{"):
2398                FvObj = Fv.FV()
2399                FvObj.UiFvName = FvName
2400                self.__GetDefineStatements(FvObj)
2401                MacroDict.update(FvObj.DefineVarDict)
2402                self.__GetBlockStatement(FvObj)
2403                self.__GetSetStatements(FvObj)
2404                self.__GetFvAlignment(FvObj)
2405                self.__GetFvAttributes(FvObj)
2406                self.__GetAprioriSection(FvObj, MacroDict.copy())
2407                self.__GetAprioriSection(FvObj, MacroDict.copy())
2408
2409                while True:
2410                    IsInf = self.__GetInfStatement(FvObj, MacroDict.copy())
2411                    IsFile = self.__GetFileStatement(FvObj, MacroDict.copy())
2412                    if not IsInf and not IsFile:
2413                        break
2414
2415                if not self.__IsToken( "}"):
2416                    raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
2417
2418            FvImageSectionObj = CommonDataClass.FdfClass.FvImageSectionClassObject()
2419            FvImageSectionObj.Alignment = AlignValue
2420            if FvObj != None:
2421                FvImageSectionObj.Fv = FvObj
2422                FvImageSectionObj.FvName = None
2423            else:
2424                FvImageSectionObj.FvName = FvName
2425
2426            Obj.SectionList.append(FvImageSectionObj)
2427
2428        elif self.__IsKeyword("PEI_DEPEX_EXP") or self.__IsKeyword("DXE_DEPEX_EXP") or self.__IsKeyword("SMM_DEPEX_EXP"):
2429            if AlignValue == 'Auto':
2430                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2431            DepexSectionObj = CommonDataClass.FdfClass.DepexSectionClassObject()
2432            DepexSectionObj.Alignment = AlignValue
2433            DepexSectionObj.DepexType = self.__Token
2434
2435            if not self.__IsToken( "="):
2436                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2437            if not self.__IsToken( "{"):
2438                raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
2439            if not self.__SkipToToken( "}"):
2440                raise Warning("expected Depex expression ending '}' At Line ", self.FileName, self.CurrentLineNumber)
2441
2442            DepexSectionObj.Expression = self.__SkippedChars.rstrip('}')
2443            Obj.SectionList.append(DepexSectionObj)
2444
2445        else:
2446
2447            if not self.__GetNextWord():
2448                raise Warning("expected section type At Line ", self.FileName, self.CurrentLineNumber)
2449
2450            # Encapsulation section appear, UndoToken and return
2451            if self.__Token == "COMPRESS" or self.__Token == "GUIDED":
2452                self.SetFileBufferPos(OldPos)
2453                return False
2454
2455            if self.__Token not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
2456                               "UI", "VERSION", "PEI_DEPEX", "SUBTYPE_GUID", "SMM_DEPEX"):
2457                raise Warning("Unknown section type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2458            if AlignValue == 'Auto'and (not self.__Token == 'PE32') and (not self.__Token == 'TE'):
2459                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2460            # DataSection
2461            DataSectionObj = CommonDataClass.FdfClass.DataSectionClassObject()
2462            DataSectionObj.Alignment = AlignValue
2463            DataSectionObj.SecType = self.__Token
2464
2465            if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
2466                if self.__FileCouldHaveRelocFlag(Obj.FvFileType) and self.__SectionCouldHaveRelocFlag(DataSectionObj.SecType):
2467                    if self.__Token == 'RELOCS_STRIPPED':
2468                        DataSectionObj.KeepReloc = False
2469                    else:
2470                        DataSectionObj.KeepReloc = True
2471                else:
2472                    raise Warning("File type %s, section type %s, could not have reloc strip flag At Line %d" % (Obj.FvFileType, DataSectionObj.SecType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
2473
2474            if self.__IsToken("="):
2475                if not self.__GetNextToken():
2476                    raise Warning("expected section file path At Line ", self.FileName, self.CurrentLineNumber)
2477                DataSectionObj.SectFileName = self.__Token
2478            else:
2479                if not self.__GetCglSection(DataSectionObj):
2480                    return False
2481
2482            Obj.SectionList.append(DataSectionObj)
2483
2484        return True
2485
2486    ## __GetCglSection() method
2487    #
2488    #   Get compressed or GUIDed section for Obj
2489    #
2490    #   @param  self        The object pointer
2491    #   @param  Obj         for whom leaf section is got
2492    #   @param  AlignValue  alignment value for complex section
2493    #   @retval True        Successfully find section statement
2494    #   @retval False       Not able to find section statement
2495    #
2496    def __GetCglSection(self, Obj, AlignValue = None):
2497
2498        if self.__IsKeyword( "COMPRESS"):
2499            type = "PI_STD"
2500            if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"):
2501                type = self.__Token
2502
2503            if not self.__IsToken("{"):
2504                raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
2505
2506            CompressSectionObj = CommonDataClass.FdfClass.CompressSectionClassObject()
2507            CompressSectionObj.Alignment = AlignValue
2508            CompressSectionObj.CompType = type
2509            # Recursive sections...
2510            while True:
2511                IsLeafSection = self.__GetLeafSection(CompressSectionObj)
2512                IsEncapSection = self.__GetEncapsulationSec(CompressSectionObj)
2513                if not IsLeafSection and not IsEncapSection:
2514                    break
2515
2516
2517            if not self.__IsToken( "}"):
2518                raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
2519            Obj.SectionList.append(CompressSectionObj)
2520
2521#            else:
2522#               raise Warning("Compress type not known At Line ")
2523
2524            return True
2525
2526        elif self.__IsKeyword( "GUIDED"):
2527            GuidValue = None
2528            if self.__GetNextGuid():
2529                GuidValue = self.__Token
2530
2531            AttribDict = self.__GetGuidAttrib()
2532            if not self.__IsToken("{"):
2533                raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
2534            GuidSectionObj = CommonDataClass.FdfClass.GuidSectionClassObject()
2535            GuidSectionObj.Alignment = AlignValue
2536            GuidSectionObj.NameGuid = GuidValue
2537            GuidSectionObj.SectionType = "GUIDED"
2538            GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
2539            GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
2540            # Recursive sections...
2541            while True:
2542                IsLeafSection = self.__GetLeafSection(GuidSectionObj)
2543                IsEncapSection = self.__GetEncapsulationSec(GuidSectionObj)
2544                if not IsLeafSection and not IsEncapSection:
2545                    break
2546
2547            if not self.__IsToken( "}"):
2548                raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
2549            Obj.SectionList.append(GuidSectionObj)
2550
2551            return True
2552
2553        return False
2554
2555    ## __GetGuidAttri() method
2556    #
2557    #   Get attributes for GUID section
2558    #
2559    #   @param  self        The object pointer
2560    #   @retval AttribDict  Dictionary of key-value pair of section attributes
2561    #
2562    def __GetGuidAttrib(self):
2563
2564        AttribDict = {}
2565        AttribDict["PROCESSING_REQUIRED"] = False
2566        AttribDict["AUTH_STATUS_VALID"] = False
2567        if self.__IsKeyword("PROCESSING_REQUIRED") or self.__IsKeyword("AUTH_STATUS_VALID"):
2568            AttribKey = self.__Token
2569
2570            if not self.__IsToken("="):
2571                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2572
2573            if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"):
2574                raise Warning("expected TRUE/FALSE (1/0) At Line ", self.FileName, self.CurrentLineNumber)
2575            AttribDict[AttribKey] = self.__Token
2576
2577        if self.__IsKeyword("PROCESSING_REQUIRED") or self.__IsKeyword("AUTH_STATUS_VALID"):
2578            AttribKey = self.__Token
2579
2580            if not self.__IsToken("="):
2581                raise Warning("expected '=' At Line ")
2582
2583            if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"):
2584                raise Warning("expected TRUE/FALSE (1/0) At Line ", self.FileName, self.CurrentLineNumber)
2585            AttribDict[AttribKey] = self.__Token
2586
2587        return AttribDict
2588
2589    ## __GetEncapsulationSec() method
2590    #
2591    #   Get encapsulation section for FILE
2592    #
2593    #   @param  self        The object pointer
2594    #   @param  FfsFile     for whom section is got
2595    #   @retval True        Successfully find section statement
2596    #   @retval False       Not able to find section statement
2597    #
2598    def __GetEncapsulationSec(self, FfsFileObj):
2599
2600        OldPos = self.GetFileBufferPos()
2601        if not self.__IsKeyword( "SECTION"):
2602            if len(FfsFileObj.SectionList) == 0:
2603                raise Warning("expected SECTION At Line ", self.FileName, self.CurrentLineNumber)
2604            else:
2605                return False
2606
2607        AlignValue = None
2608        if self.__GetAlignment():
2609            if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
2610                raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2611            AlignValue = self.__Token
2612
2613        if not self.__GetCglSection(FfsFileObj, AlignValue):
2614            self.SetFileBufferPos(OldPos)
2615            return False
2616        else:
2617            return True
2618
2619    ## __GetCapsule() method
2620    #
2621    #   Get capsule section contents and store its data into capsule list of self.Profile
2622    #
2623    #   @param  self        The object pointer
2624    #   @retval True        Successfully find a capsule
2625    #   @retval False       Not able to find a capsule
2626    #
2627    def __GetCapsule(self):
2628
2629        if not self.__GetNextToken():
2630            return False
2631
2632        S = self.__Token.upper()
2633        if S.startswith("[") and not S.startswith("[CAPSULE."):
2634            if not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
2635                raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
2636            self.__UndoToken()
2637            return False
2638
2639        self.__UndoToken()
2640        if not self.__IsToken("[CAPSULE.", True):
2641            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2642            print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
2643                    % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
2644            raise Warning("expected [Capsule.] At Line ", self.FileName, self.CurrentLineNumber)
2645
2646        CapsuleObj = CommonDataClass.FdfClass.CapsuleClassObject()
2647
2648        CapsuleName = self.__GetUiName()
2649        if not CapsuleName:
2650            raise Warning("expected capsule name At line ", self.FileName, self.CurrentLineNumber)
2651
2652        CapsuleObj.UiCapsuleName = CapsuleName.upper()
2653
2654        if not self.__IsToken( "]"):
2655            raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber)
2656
2657        if self.__IsKeyword("CREATE_FILE"):
2658            if not self.__IsToken( "="):
2659                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2660
2661            if not self.__GetNextToken():
2662                raise Warning("expected file name At Line ", self.FileName, self.CurrentLineNumber)
2663
2664            CapsuleObj.CreateFile = self.__Token
2665
2666        self.__GetCapsuleStatements(CapsuleObj)
2667        self.Profile.CapsuleList.append(CapsuleObj)
2668        return True
2669
2670    ## __GetCapsuleStatements() method
2671    #
2672    #   Get statements for capsule
2673    #
2674    #   @param  self        The object pointer
2675    #   @param  Obj         for whom statements are got
2676    #
2677    def __GetCapsuleStatements(self, Obj):
2678        self.__GetCapsuleTokens(Obj)
2679        self.__GetDefineStatements(Obj)
2680        self.__GetSetStatements(Obj)
2681
2682        self.__GetCapsuleData(Obj)
2683
2684    ## __GetCapsuleStatements() method
2685    #
2686    #   Get token statements for capsule
2687    #
2688    #   @param  self        The object pointer
2689    #   @param  Obj         for whom token statements are got
2690    #
2691    def __GetCapsuleTokens(self, Obj):
2692
2693        if not self.__IsKeyword("CAPSULE_GUID"):
2694            raise Warning("expected 'CAPSULE_GUID' At Line ", self.FileName, self.CurrentLineNumber)
2695
2696        while self.__CurrentLine().find("=") != -1:
2697            NameValue = self.__CurrentLine().split("=")
2698            Obj.TokensDict[NameValue[0].strip()] = NameValue[1].strip()
2699            self.CurrentLineNumber += 1
2700            self.CurrentOffsetWithinLine = 0
2701
2702    ## __GetCapsuleData() method
2703    #
2704    #   Get capsule data for capsule
2705    #
2706    #   @param  self        The object pointer
2707    #   @param  Obj         for whom capsule data are got
2708    #
2709    def __GetCapsuleData(self, Obj):
2710
2711        while True:
2712            IsInf = self.__GetInfStatement(Obj, True)
2713            IsFile = self.__GetFileStatement(Obj, True)
2714            IsFv = self.__GetFvStatement(Obj)
2715            if not IsInf and not IsFile and not IsFv:
2716                break
2717
2718    ## __GetFvStatement() method
2719    #
2720    #   Get FV for capsule
2721    #
2722    #   @param  self        The object pointer
2723    #   @param  CapsuleObj  for whom FV is got
2724    #   @retval True        Successfully find a FV statement
2725    #   @retval False       Not able to find a FV statement
2726    #
2727    def __GetFvStatement(self, CapsuleObj):
2728
2729        if not self.__IsKeyword("FV"):
2730            return False
2731
2732        if not self.__IsToken("="):
2733            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2734
2735        if not self.__GetNextToken():
2736            raise Warning("expected FV name At Line ", self.FileName, self.CurrentLineNumber)
2737
2738#        CapsuleFv = CapsuleData.CapsuleFv()
2739#        CapsuleFv.FvName = self.__Token
2740#        CapsuleObj.CapsuleDataList.append(CapsuleFv)
2741        return True
2742
2743    ## __GetRule() method
2744    #
2745    #   Get Rule section contents and store its data into rule list of self.Profile
2746    #
2747    #   @param  self        The object pointer
2748    #   @retval True        Successfully find a Rule
2749    #   @retval False       Not able to find a Rule
2750    #
2751    def __GetRule(self):
2752
2753        if not self.__GetNextToken():
2754            return False
2755
2756        S = self.__Token.upper()
2757        if S.startswith("[") and not S.startswith("[RULE."):
2758            if not S.startswith("[OPTIONROM."):
2759                raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
2760            self.__UndoToken()
2761            return False
2762        self.__UndoToken()
2763        if not self.__IsToken("[Rule.", True):
2764            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2765            print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
2766                    % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
2767            raise Warning("expected [Rule.] At Line ", self.FileName, self.CurrentLineNumber)
2768
2769        if not self.__SkipToToken("."):
2770            raise Warning("expected '.' At Line ", self.FileName, self.CurrentLineNumber)
2771
2772        Arch = self.__SkippedChars.rstrip(".")
2773        if Arch.upper() not in ("IA32", "X64", "IPF", "EBC", "ARM", "AARCH64", "COMMON"):
2774            raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber)
2775
2776        ModuleType = self.__GetModuleType()
2777
2778        TemplateName = ""
2779        if self.__IsToken("."):
2780            if not self.__GetNextWord():
2781                raise Warning("expected template name At Line ", self.FileName, self.CurrentLineNumber)
2782            TemplateName = self.__Token
2783
2784        if not self.__IsToken( "]"):
2785            raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber)
2786
2787        RuleObj = self.__GetRuleFileStatements()
2788        RuleObj.Arch = Arch.upper()
2789        RuleObj.ModuleType = ModuleType
2790        RuleObj.TemplateName = TemplateName
2791        if TemplateName == '' :
2792            self.Profile.RuleDict['RULE'             + \
2793                              '.'                    + \
2794                              Arch.upper()           + \
2795                              '.'                    + \
2796                              ModuleType.upper()     ] = RuleObj
2797        else :
2798            self.Profile.RuleDict['RULE'             + \
2799                              '.'                    + \
2800                              Arch.upper()           + \
2801                              '.'                    + \
2802                              ModuleType.upper()     + \
2803                              '.'                    + \
2804                              TemplateName.upper() ] = RuleObj
2805#        self.Profile.RuleList.append(rule)
2806        return True
2807
2808    ## __GetModuleType() method
2809    #
2810    #   Return the module type
2811    #
2812    #   @param  self        The object pointer
2813    #   @retval string      module type
2814    #
2815    def __GetModuleType(self):
2816
2817        if not self.__GetNextWord():
2818            raise Warning("expected Module type At Line ", self.FileName, self.CurrentLineNumber)
2819        if self.__Token.upper() not in ("SEC", "PEI_CORE", "PEIM", "DXE_CORE", \
2820                             "DXE_DRIVER", "DXE_SAL_DRIVER", \
2821                             "DXE_SMM_DRIVER", "DXE_RUNTIME_DRIVER", \
2822                             "UEFI_DRIVER", "UEFI_APPLICATION", "USER_DEFINED", "DEFAULT", "BASE", \
2823                             "SECURITY_CORE", "COMBINED_PEIM_DRIVER", "PIC_PEIM", "RELOCATABLE_PEIM", \
2824                             "PE32_PEIM", "BS_DRIVER", "RT_DRIVER", "SAL_RT_DRIVER", "APPLICATION", "ACPITABLE", "SMM_CORE"):
2825            raise Warning("Unknown Module type At line ", self.FileName, self.CurrentLineNumber)
2826        return self.__Token
2827
2828    ## __GetFileExtension() method
2829    #
2830    #   Return the file extension
2831    #
2832    #   @param  self        The object pointer
2833    #   @retval string      file name extension
2834    #
2835    def __GetFileExtension(self):
2836        if not self.__IsToken("."):
2837                raise Warning("expected '.' At Line ", self.FileName, self.CurrentLineNumber)
2838
2839        Ext = ""
2840        if self.__GetNextToken():
2841            Pattern = re.compile(r'([a-zA-Z][a-zA-Z0-9]*)')
2842            if Pattern.match(self.__Token):
2843                Ext = self.__Token
2844                return '.' + Ext
2845            else:
2846                raise Warning("Unknown file extension At Line ", self.FileName, self.CurrentLineNumber)
2847
2848        else:
2849            raise Warning("expected file extension At Line ", self.FileName, self.CurrentLineNumber)
2850
2851    ## __GetRuleFileStatement() method
2852    #
2853    #   Get rule contents
2854    #
2855    #   @param  self        The object pointer
2856    #   @retval Rule        Rule object
2857    #
2858    def __GetRuleFileStatements(self):
2859
2860        if not self.__IsKeyword("FILE"):
2861            raise Warning("expected FILE At Line ", self.FileName, self.CurrentLineNumber)
2862
2863        if not self.__GetNextWord():
2864            raise Warning("expected FFS type At Line ", self.FileName, self.CurrentLineNumber)
2865
2866        Type = self.__Token.strip().upper()
2867        if Type not in ("RAW", "FREEFORM", "SEC", "PEI_CORE", "PEIM",\
2868                             "PEI_DXE_COMBO", "DRIVER", "DXE_CORE", "APPLICATION", "FV_IMAGE", "SMM", "SMM_CORE"):
2869            raise Warning("Unknown FV type At line ", self.FileName, self.CurrentLineNumber)
2870
2871        if not self.__IsToken("="):
2872            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
2873
2874        if not self.__IsKeyword("$(NAMED_GUID)"):
2875            if not self.__GetNextWord():
2876                raise Warning("expected $(NAMED_GUID)", self.FileName, self.CurrentLineNumber)
2877            if self.__Token == 'PCD':
2878                if not self.__IsToken( "("):
2879                    raise Warning("expected '('", self.FileName, self.CurrentLineNumber)
2880                PcdPair = self.__GetNextPcdName()
2881                if not self.__IsToken( ")"):
2882                    raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
2883                self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')'
2884
2885        NameGuid = self.__Token
2886
2887        KeepReloc = None
2888        if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
2889            if self.__FileCouldHaveRelocFlag(Type):
2890                if self.__Token == 'RELOCS_STRIPPED':
2891                    KeepReloc = False
2892                else:
2893                    KeepReloc = True
2894            else:
2895                raise Warning("File type %s could not have reloc strip flag At Line %d" % (Type, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
2896
2897        KeyStringList = []
2898        if self.__GetNextToken():
2899            Pattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
2900            if Pattern.match(self.__Token):
2901                KeyStringList.append(self.__Token)
2902                if self.__IsToken(","):
2903                    while self.__GetNextToken():
2904                        if not Pattern.match(self.__Token):
2905                            raise Warning("expected KeyString \"Target_Tag_Arch\" At Line ", self.FileName, self.CurrentLineNumber)
2906                        KeyStringList.append(self.__Token)
2907
2908                        if not self.__IsToken(","):
2909                            break
2910
2911            else:
2912                self.__UndoToken()
2913
2914
2915        Fixed = False
2916        if self.__IsKeyword("Fixed", True):
2917            Fixed = True
2918
2919        CheckSum = False
2920        if self.__IsKeyword("CheckSum", True):
2921            CheckSum = True
2922
2923        AlignValue = ""
2924        if self.__GetAlignment():
2925            if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
2926                raise Warning("Incorrect alignment At Line ", self.FileName, self.CurrentLineNumber)
2927            AlignValue = self.__Token
2928
2929        if self.__IsToken("{"):
2930            # Complex file rule expected
2931            Rule = RuleComplexFile.RuleComplexFile()
2932            Rule.FvFileType = Type
2933            Rule.NameGuid = NameGuid
2934            Rule.Alignment = AlignValue
2935            Rule.CheckSum = CheckSum
2936            Rule.Fixed = Fixed
2937            Rule.KeyStringList = KeyStringList
2938            if KeepReloc != None:
2939                Rule.KeepReloc = KeepReloc
2940
2941            while True:
2942                IsEncapsulate = self.__GetRuleEncapsulationSection(Rule)
2943                IsLeaf = self.__GetEfiSection(Rule)
2944                if not IsEncapsulate and not IsLeaf:
2945                    break
2946
2947            if not self.__IsToken("}"):
2948                raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
2949
2950            return Rule
2951
2952        elif self.__IsToken("|"):
2953            # Ext rule expected
2954            Ext = self.__GetFileExtension()
2955
2956            Rule = RuleSimpleFile.RuleSimpleFile()
2957
2958            Rule.FvFileType = Type
2959            Rule.NameGuid = NameGuid
2960            Rule.Alignment = AlignValue
2961            Rule.CheckSum = CheckSum
2962            Rule.Fixed = Fixed
2963            Rule.FileExtension = Ext
2964            Rule.KeyStringList = KeyStringList
2965            if KeepReloc != None:
2966                Rule.KeepReloc = KeepReloc
2967
2968            return Rule
2969
2970        else:
2971            # Simple file rule expected
2972            if not self.__GetNextWord():
2973                raise Warning("expected leaf section type At Line ", self.FileName, self.CurrentLineNumber)
2974
2975            SectionName = self.__Token
2976
2977            if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
2978                                    "UI", "PEI_DEPEX", "VERSION", "SUBTYPE_GUID", "SMM_DEPEX"):
2979                raise Warning("Unknown leaf section name '%s'" % SectionName, self.FileName, self.CurrentLineNumber)
2980
2981
2982            if self.__IsKeyword("Fixed", True):
2983                Fixed = True
2984
2985            if self.__IsKeyword("CheckSum", True):
2986                CheckSum = True
2987
2988            if self.__GetAlignment():
2989                if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
2990                    raise Warning("Incorrect alignment At Line ", self.FileName, self.CurrentLineNumber)
2991                if self.__Token == 'Auto' and (not SectionName == 'PE32') and (not SectionName == 'TE'):
2992                    raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2993                AlignValue = self.__Token
2994
2995            if not self.__GetNextToken():
2996                raise Warning("expected File name At Line ", self.FileName, self.CurrentLineNumber)
2997
2998            Rule = RuleSimpleFile.RuleSimpleFile()
2999            Rule.SectionType = SectionName
3000            Rule.FvFileType = Type
3001            Rule.NameGuid = NameGuid
3002            Rule.Alignment = AlignValue
3003            Rule.CheckSum = CheckSum
3004            Rule.Fixed = Fixed
3005            Rule.FileName = self.__Token
3006            Rule.KeyStringList = KeyStringList
3007            if KeepReloc != None:
3008                Rule.KeepReloc = KeepReloc
3009            return Rule
3010
3011    ## __GetEfiSection() method
3012    #
3013    #   Get section list for Rule
3014    #
3015    #   @param  self        The object pointer
3016    #   @param  Obj         for whom section is got
3017    #   @retval True        Successfully find section statement
3018    #   @retval False       Not able to find section statement
3019    #
3020    def __GetEfiSection(self, Obj):
3021
3022        OldPos = self.GetFileBufferPos()
3023        if not self.__GetNextWord():
3024            return False
3025        SectionName = self.__Token
3026
3027        if SectionName not in ("COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
3028                               "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"):
3029            self.__UndoToken()
3030            return False
3031
3032        if SectionName == "FV_IMAGE":
3033            FvImageSectionObj = FvImageSection.FvImageSection()
3034            if self.__IsKeyword("FV_IMAGE"):
3035                pass
3036            if self.__IsToken( "{"):
3037                FvObj = Fv.FV()
3038                self.__GetDefineStatements(FvObj)
3039                self.__GetBlockStatement(FvObj)
3040                self.__GetSetStatements(FvObj)
3041                self.__GetFvAlignment(FvObj)
3042                self.__GetFvAttributes(FvObj)
3043                self.__GetAprioriSection(FvObj)
3044                self.__GetAprioriSection(FvObj)
3045
3046                while True:
3047                    IsInf = self.__GetInfStatement(FvObj)
3048                    IsFile = self.__GetFileStatement(FvObj)
3049                    if not IsInf and not IsFile:
3050                        break
3051
3052                if not self.__IsToken( "}"):
3053                    raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
3054                FvImageSectionObj.Fv = FvObj
3055                FvImageSectionObj.FvName = None
3056
3057            else:
3058                if not self.__IsKeyword("FV"):
3059                    raise Warning("expected 'FV' At Line ", self.FileName, self.CurrentLineNumber)
3060                FvImageSectionObj.FvFileType = self.__Token
3061
3062                if self.__GetAlignment():
3063                    if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
3064                        raise Warning("Incorrect alignment At Line ", self.FileName, self.CurrentLineNumber)
3065                    FvImageSectionObj.Alignment = self.__Token
3066
3067                if self.__IsToken('|'):
3068                    FvImageSectionObj.FvFileExtension = self.__GetFileExtension()
3069                elif self.__GetNextToken():
3070                    if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
3071                               "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"):
3072                        FvImageSectionObj.FvFileName = self.__Token
3073                    else:
3074                        self.__UndoToken()
3075                else:
3076                    raise Warning("expected FV file name At Line ", self.FileName, self.CurrentLineNumber)
3077
3078            Obj.SectionList.append(FvImageSectionObj)
3079            return True
3080
3081        EfiSectionObj = EfiSection.EfiSection()
3082        EfiSectionObj.SectionType = SectionName
3083
3084        if not self.__GetNextToken():
3085            raise Warning("expected file type At Line ", self.FileName, self.CurrentLineNumber)
3086
3087        if self.__Token == "STRING":
3088            if not self.__RuleSectionCouldHaveString(EfiSectionObj.SectionType):
3089                raise Warning("%s section could NOT have string data At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3090
3091            if not self.__IsToken('='):
3092                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3093
3094            if not self.__GetNextToken():
3095                raise Warning("expected Quoted String At Line ", self.FileName, self.CurrentLineNumber)
3096
3097            if self.__GetStringData():
3098                EfiSectionObj.StringData = self.__Token
3099
3100            if self.__IsKeyword("BUILD_NUM"):
3101                if not self.__RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
3102                    raise Warning("%s section could NOT have BUILD_NUM At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3103
3104                if not self.__IsToken("="):
3105                    raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3106                if not self.__GetNextToken():
3107                    raise Warning("expected Build number At Line ", self.FileName, self.CurrentLineNumber)
3108                EfiSectionObj.BuildNum = self.__Token
3109
3110        else:
3111            EfiSectionObj.FileType = self.__Token
3112            self.__CheckRuleSectionFileType(EfiSectionObj.SectionType, EfiSectionObj.FileType)
3113
3114        if self.__IsKeyword("Optional"):
3115            if not self.__RuleSectionCouldBeOptional(EfiSectionObj.SectionType):
3116                raise Warning("%s section could NOT be optional At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3117            EfiSectionObj.Optional = True
3118
3119            if self.__IsKeyword("BUILD_NUM"):
3120                if not self.__RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
3121                    raise Warning("%s section could NOT have BUILD_NUM At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3122
3123                if not self.__IsToken("="):
3124                    raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3125                if not self.__GetNextToken():
3126                    raise Warning("expected Build number At Line ", self.FileName, self.CurrentLineNumber)
3127                EfiSectionObj.BuildNum = self.__Token
3128
3129        if self.__GetAlignment():
3130            if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K" ,"64K"):
3131                raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3132            if self.__Token == 'Auto' and (not SectionName == 'PE32') and (not SectionName == 'TE'):
3133                raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
3134            EfiSectionObj.Alignment = self.__Token
3135
3136        if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
3137            if self.__SectionCouldHaveRelocFlag(EfiSectionObj.SectionType):
3138                if self.__Token == 'RELOCS_STRIPPED':
3139                    EfiSectionObj.KeepReloc = False
3140                else:
3141                    EfiSectionObj.KeepReloc = True
3142                if Obj.KeepReloc != None and Obj.KeepReloc != EfiSectionObj.KeepReloc:
3143                    raise Warning("Section type %s has reloc strip flag conflict with Rule At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3144            else:
3145                raise Warning("Section type %s could not have reloc strip flag At Line %d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3146
3147
3148        if self.__IsToken('|'):
3149            EfiSectionObj.FileExtension = self.__GetFileExtension()
3150        elif self.__GetNextToken():
3151            if self.__Token not in ("}", "COMPAT16", "PE32", "PIC", "TE", "FV_IMAGE", "RAW", "DXE_DEPEX",\
3152                       "UI", "VERSION", "PEI_DEPEX", "GUID", "SMM_DEPEX"):
3153
3154                if self.__Token.startswith('PCD'):
3155                    self.__UndoToken()
3156                    self.__GetNextWord()
3157
3158                    if self.__Token == 'PCD':
3159                        if not self.__IsToken( "("):
3160                            raise Warning("expected '('", self.FileName, self.CurrentLineNumber)
3161                        PcdPair = self.__GetNextPcdName()
3162                        if not self.__IsToken( ")"):
3163                            raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
3164                        self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')'
3165
3166                EfiSectionObj.FileName = self.__Token
3167
3168            else:
3169                self.__UndoToken()
3170        else:
3171            raise Warning("expected section file name At Line ", self.FileName, self.CurrentLineNumber)
3172
3173        Obj.SectionList.append(EfiSectionObj)
3174        return True
3175
3176    ## __RuleSectionCouldBeOptional() method
3177    #
3178    #   Get whether a section could be optional
3179    #
3180    #   @param  self        The object pointer
3181    #   @param  SectionType The section type to check
3182    #   @retval True        section could be optional
3183    #   @retval False       section never optional
3184    #
3185    def __RuleSectionCouldBeOptional(self, SectionType):
3186        if SectionType in ("DXE_DEPEX", "UI", "VERSION", "PEI_DEPEX", "RAW", "SMM_DEPEX"):
3187            return True
3188        else:
3189            return False
3190
3191    ## __RuleSectionCouldHaveBuildNum() method
3192    #
3193    #   Get whether a section could have build number information
3194    #
3195    #   @param  self        The object pointer
3196    #   @param  SectionType The section type to check
3197    #   @retval True        section could have build number information
3198    #   @retval False       section never have build number information
3199    #
3200    def __RuleSectionCouldHaveBuildNum(self, SectionType):
3201        if SectionType in ("VERSION"):
3202            return True
3203        else:
3204            return False
3205
3206    ## __RuleSectionCouldHaveString() method
3207    #
3208    #   Get whether a section could have string
3209    #
3210    #   @param  self        The object pointer
3211    #   @param  SectionType The section type to check
3212    #   @retval True        section could have string
3213    #   @retval False       section never have string
3214    #
3215    def __RuleSectionCouldHaveString(self, SectionType):
3216        if SectionType in ("UI", "VERSION"):
3217            return True
3218        else:
3219            return False
3220
3221    ## __CheckRuleSectionFileType() method
3222    #
3223    #   Get whether a section matches a file type
3224    #
3225    #   @param  self        The object pointer
3226    #   @param  SectionType The section type to check
3227    #   @param  FileType    The file type to check
3228    #
3229    def __CheckRuleSectionFileType(self, SectionType, FileType):
3230        if SectionType == "COMPAT16":
3231            if FileType not in ("COMPAT16", "SEC_COMPAT16"):
3232                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3233        elif SectionType == "PE32":
3234            if FileType not in ("PE32", "SEC_PE32"):
3235                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3236        elif SectionType == "PIC":
3237            if FileType not in ("PIC", "PIC"):
3238                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3239        elif SectionType == "TE":
3240            if FileType not in ("TE", "SEC_TE"):
3241                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3242        elif SectionType == "RAW":
3243            if FileType not in ("BIN", "SEC_BIN", "RAW", "ASL", "ACPI"):
3244                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3245        elif SectionType == "DXE_DEPEX" or SectionType == "SMM_DEPEX":
3246            if FileType not in ("DXE_DEPEX", "SEC_DXE_DEPEX", "SMM_DEPEX"):
3247                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3248        elif SectionType == "UI":
3249            if FileType not in ("UI", "SEC_UI"):
3250                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3251        elif SectionType == "VERSION":
3252            if FileType not in ("VERSION", "SEC_VERSION"):
3253                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3254        elif SectionType == "PEI_DEPEX":
3255            if FileType not in ("PEI_DEPEX", "SEC_PEI_DEPEX"):
3256                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3257        elif SectionType == "GUID":
3258            if FileType not in ("PE32", "SEC_GUID"):
3259                raise Warning("Incorrect section file type At Line ", self.FileName, self.CurrentLineNumber)
3260
3261    ## __GetRuleEncapsulationSection() method
3262    #
3263    #   Get encapsulation section for Rule
3264    #
3265    #   @param  self        The object pointer
3266    #   @param  Rule        for whom section is got
3267    #   @retval True        Successfully find section statement
3268    #   @retval False       Not able to find section statement
3269    #
3270    def __GetRuleEncapsulationSection(self, Rule):
3271
3272        if self.__IsKeyword( "COMPRESS"):
3273            Type = "PI_STD"
3274            if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"):
3275                Type = self.__Token
3276
3277            if not self.__IsToken("{"):
3278                raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
3279
3280            CompressSectionObj = CompressSection.CompressSection()
3281
3282            CompressSectionObj.CompType = Type
3283            # Recursive sections...
3284            while True:
3285                IsEncapsulate = self.__GetRuleEncapsulationSection(CompressSectionObj)
3286                IsLeaf = self.__GetEfiSection(CompressSectionObj)
3287                if not IsEncapsulate and not IsLeaf:
3288                    break
3289
3290            if not self.__IsToken( "}"):
3291                raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
3292            Rule.SectionList.append(CompressSectionObj)
3293
3294            return True
3295
3296        elif self.__IsKeyword( "GUIDED"):
3297            GuidValue = None
3298            if self.__GetNextGuid():
3299                GuidValue = self.__Token
3300
3301            if self.__IsKeyword( "$(NAMED_GUID)"):
3302                GuidValue = self.__Token
3303
3304            AttribDict = self.__GetGuidAttrib()
3305
3306            if not self.__IsToken("{"):
3307                raise Warning("expected '{' At Line ", self.FileName, self.CurrentLineNumber)
3308            GuidSectionObj = GuidSection.GuidSection()
3309            GuidSectionObj.NameGuid = GuidValue
3310            GuidSectionObj.SectionType = "GUIDED"
3311            GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
3312            GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
3313
3314            # Efi sections...
3315            while True:
3316                IsEncapsulate = self.__GetRuleEncapsulationSection(GuidSectionObj)
3317                IsLeaf = self.__GetEfiSection(GuidSectionObj)
3318                if not IsEncapsulate and not IsLeaf:
3319                    break
3320
3321            if not self.__IsToken( "}"):
3322                raise Warning("expected '}' At Line ", self.FileName, self.CurrentLineNumber)
3323            Rule.SectionList.append(GuidSectionObj)
3324
3325            return True
3326
3327        return False
3328
3329    ## __GetVtf() method
3330    #
3331    #   Get VTF section contents and store its data into VTF list of self.Profile
3332    #
3333    #   @param  self        The object pointer
3334    #   @retval True        Successfully find a VTF
3335    #   @retval False       Not able to find a VTF
3336    #
3337    def __GetVtf(self):
3338
3339        if not self.__GetNextToken():
3340            return False
3341
3342        S = self.__Token.upper()
3343        if S.startswith("[") and not S.startswith("[VTF."):
3344            if not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
3345                raise Warning("Unknown section or section appear sequence error (The correct sequence should be [FD.], [FV.], [Capsule.], [VTF.], [Rule.], [OptionRom.])", self.FileName, self.CurrentLineNumber)
3346            self.__UndoToken()
3347            return False
3348
3349        self.__UndoToken()
3350        if not self.__IsToken("[VTF.", True):
3351            FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
3352            print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
3353                    % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
3354            raise Warning("expected [VTF.] At Line ", self.FileName, self.CurrentLineNumber)
3355
3356        if not self.__SkipToToken("."):
3357            raise Warning("expected '.' At Line ", self.FileName, self.CurrentLineNumber)
3358
3359        Arch = self.__SkippedChars.rstrip(".").upper()
3360        if Arch not in ("IA32", "X64", "IPF", "ARM", "AARCH64"):
3361            raise Warning("Unknown Arch At line ", self.FileName, self.CurrentLineNumber)
3362
3363        if not self.__GetNextWord():
3364            raise Warning("expected VTF name At Line ", self.FileName, self.CurrentLineNumber)
3365        Name = self.__Token.upper()
3366
3367        VtfObj = Vtf.Vtf()
3368        VtfObj.UiName = Name
3369        VtfObj.KeyArch = Arch
3370
3371        if self.__IsToken(","):
3372            if not self.__GetNextWord():
3373                raise Warning("expected Arch list At Line ", self.FileName, self.CurrentLineNumber)
3374            if self.__Token.upper() not in ("IA32", "X64", "IPF", "ARM", "AARCH64"):
3375                raise Warning("Unknown Arch At line ", self.FileName, self.CurrentLineNumber)
3376            VtfObj.ArchList = self.__Token.upper()
3377
3378        if not self.__IsToken( "]"):
3379            raise Warning("expected ']' At Line ", self.FileName, self.CurrentLineNumber)
3380
3381        if self.__IsKeyword("IA32_RST_BIN"):
3382            if not self.__IsToken("="):
3383                raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3384
3385            if not self.__GetNextToken():
3386                raise Warning("expected Reset file At Line ", self.FileName, self.CurrentLineNumber)
3387
3388            VtfObj.ResetBin = self.__Token
3389
3390        while self.__GetComponentStatement(VtfObj):
3391            pass
3392
3393        self.Profile.VtfList.append(VtfObj)
3394        return True
3395
3396    ## __GetComponentStatement() method
3397    #
3398    #   Get components in VTF
3399    #
3400    #   @param  self        The object pointer
3401    #   @param  VtfObj         for whom component is got
3402    #   @retval True        Successfully find a component
3403    #   @retval False       Not able to find a component
3404    #
3405    def __GetComponentStatement(self, VtfObj):
3406
3407        if not self.__IsKeyword("COMP_NAME"):
3408            return False
3409
3410        if not self.__IsToken("="):
3411            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3412
3413        if not self.__GetNextWord():
3414            raise Warning("expected Component Name At Line ", self.FileName, self.CurrentLineNumber)
3415
3416        CompStatementObj = ComponentStatement.ComponentStatement()
3417        CompStatementObj.CompName = self.__Token
3418
3419        if not self.__IsKeyword("COMP_LOC"):
3420            raise Warning("expected COMP_LOC At Line ", self.FileName, self.CurrentLineNumber)
3421
3422        if not self.__IsToken("="):
3423            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3424
3425        CompStatementObj.CompLoc = ""
3426        if self.__GetNextWord():
3427            CompStatementObj.CompLoc = self.__Token
3428            if self.__IsToken('|'):
3429                if not self.__GetNextWord():
3430                    raise Warning("Expected Region Name At Line ", self.FileName, self.CurrentLineNumber)
3431
3432                if self.__Token not in ("F", "N", "S"):    #, "H", "L", "PH", "PL"): not support
3433                    raise Warning("Unknown location type At line ", self.FileName, self.CurrentLineNumber)
3434
3435                CompStatementObj.FilePos = self.__Token
3436        else:
3437            self.CurrentLineNumber += 1
3438            self.CurrentOffsetWithinLine = 0
3439
3440        if not self.__IsKeyword("COMP_TYPE"):
3441            raise Warning("expected COMP_TYPE At Line ", self.FileName, self.CurrentLineNumber)
3442
3443        if not self.__IsToken("="):
3444            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3445
3446        if not self.__GetNextToken():
3447            raise Warning("expected Component type At Line ", self.FileName, self.CurrentLineNumber)
3448        if self.__Token not in ("FIT", "PAL_B", "PAL_A", "OEM"):
3449            if not self.__Token.startswith("0x") or len(self.__Token) < 3 or len(self.__Token) > 4 or \
3450                not self.__HexDigit(self.__Token[2]) or not self.__HexDigit(self.__Token[-1]):
3451                raise Warning("Unknown location type At line ", self.FileName, self.CurrentLineNumber)
3452        CompStatementObj.CompType = self.__Token
3453
3454        if not self.__IsKeyword("COMP_VER"):
3455            raise Warning("expected COMP_VER At Line ", self.FileName, self.CurrentLineNumber)
3456
3457        if not self.__IsToken("="):
3458            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3459
3460        if not self.__GetNextToken():
3461            raise Warning("expected Component version At Line ", self.FileName, self.CurrentLineNumber)
3462
3463        Pattern = re.compile('-$|[0-9]{0,1}[0-9]{1}\.[0-9]{0,1}[0-9]{1}')
3464        if Pattern.match(self.__Token) == None:
3465            raise Warning("Unknown version format At line ", self.FileName, self.CurrentLineNumber)
3466        CompStatementObj.CompVer = self.__Token
3467
3468        if not self.__IsKeyword("COMP_CS"):
3469            raise Warning("expected COMP_CS At Line ", self.FileName, self.CurrentLineNumber)
3470
3471        if not self.__IsToken("="):
3472            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3473
3474        if not self.__GetNextToken():
3475            raise Warning("expected Component CS At Line ", self.FileName, self.CurrentLineNumber)
3476        if self.__Token not in ("1", "0"):
3477            raise Warning("Unknown  Component CS At line ", self.FileName, self.CurrentLineNumber)
3478        CompStatementObj.CompCs = self.__Token
3479
3480
3481        if not self.__IsKeyword("COMP_BIN"):
3482            raise Warning("expected COMP_BIN At Line ", self.FileName, self.CurrentLineNumber)
3483
3484        if not self.__IsToken("="):
3485            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3486
3487        if not self.__GetNextToken():
3488            raise Warning("expected Component file At Line ", self.FileName, self.CurrentLineNumber)
3489
3490        CompStatementObj.CompBin = self.__Token
3491
3492        if not self.__IsKeyword("COMP_SYM"):
3493            raise Warning("expected COMP_SYM At Line ", self.FileName, self.CurrentLineNumber)
3494
3495        if not self.__IsToken("="):
3496            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3497
3498        if not self.__GetNextToken():
3499            raise Warning("expected Component symbol file At Line ", self.FileName, self.CurrentLineNumber)
3500
3501        CompStatementObj.CompSym = self.__Token
3502
3503        if not self.__IsKeyword("COMP_SIZE"):
3504            raise Warning("expected COMP_SIZE At Line ", self.FileName, self.CurrentLineNumber)
3505
3506        if not self.__IsToken("="):
3507            raise Warning("expected '=' At Line ", self.FileName, self.CurrentLineNumber)
3508
3509        if self.__IsToken("-"):
3510            CompStatementObj.CompSize = self.__Token
3511        elif self.__GetNextDecimalNumber():
3512            CompStatementObj.CompSize = self.__Token
3513        elif self.__GetNextHexNumber():
3514            CompStatementObj.CompSize = self.__Token
3515        else:
3516            raise Warning("Unknown size At line ", self.FileName, self.CurrentLineNumber)
3517
3518        VtfObj.ComponentStatementList.append(CompStatementObj)
3519        return True
3520
3521    ## __GetFvInFd() method
3522    #
3523    #   Get FV list contained in FD
3524    #
3525    #   @param  self        The object pointer
3526    #   @param  FdName      FD name
3527    #   @retval FvList      list of FV in FD
3528    #
3529    def __GetFvInFd (self, FdName):
3530
3531        FvList = []
3532        if FdName.upper() in self.Profile.FdDict.keys():
3533            FdObj = self.Profile.FdDict[FdName.upper()]
3534            for elementRegion in FdObj.RegionList:
3535                if elementRegion.RegionType == 'FV':
3536                    for elementRegionData in elementRegion.RegionDataList:
3537                        if elementRegionData != None and elementRegionData.upper() not in FvList:
3538                            FvList.append(elementRegionData.upper())
3539        return FvList
3540
3541    ## __GetReferencedFdFvTuple() method
3542    #
3543    #   Get FD and FV list referenced by a FFS file
3544    #
3545    #   @param  self        The object pointer
3546    #   @param  FfsFile     contains sections to be searched
3547    #   @param  RefFdList   referenced FD by section
3548    #   @param  RefFvList   referenced FV by section
3549    #
3550    def __GetReferencedFdFvTuple(self, FvObj, RefFdList = [], RefFvList = []):
3551
3552        for FfsObj in FvObj.FfsList:
3553            if isinstance(FfsObj, FfsFileStatement.FileStatement):
3554                if FfsObj.FvName != None and FfsObj.FvName.upper() not in RefFvList:
3555                    RefFvList.append(FfsObj.FvName.upper())
3556                elif FfsObj.FdName != None and FfsObj.FdName.upper() not in RefFdList:
3557                    RefFdList.append(FfsObj.FdName.upper())
3558                else:
3559                    self.__GetReferencedFdFvTupleFromSection(FfsObj, RefFdList, RefFvList)
3560
3561    ## __GetReferencedFdFvTupleFromSection() method
3562    #
3563    #   Get FD and FV list referenced by a FFS section
3564    #
3565    #   @param  self        The object pointer
3566    #   @param  FfsFile     contains sections to be searched
3567    #   @param  FdList      referenced FD by section
3568    #   @param  FvList      referenced FV by section
3569    #
3570    def __GetReferencedFdFvTupleFromSection(self, FfsFile, FdList = [], FvList = []):
3571
3572        SectionStack = []
3573        SectionStack.extend(FfsFile.SectionList)
3574        while SectionStack != []:
3575            SectionObj = SectionStack.pop()
3576            if isinstance(SectionObj, FvImageSection.FvImageSection):
3577                if SectionObj.FvName != None and SectionObj.FvName.upper() not in FvList:
3578                    FvList.append(SectionObj.FvName.upper())
3579                if SectionObj.Fv != None and SectionObj.Fv.UiFvName != None and SectionObj.Fv.UiFvName.upper() not in FvList:
3580                    FvList.append(SectionObj.Fv.UiFvName.upper())
3581                    self.__GetReferencedFdFvTuple(SectionObj.Fv, FdList, FvList)
3582
3583            if isinstance(SectionObj, CompressSection.CompressSection) or isinstance(SectionObj, GuidSection.GuidSection):
3584                SectionStack.extend(SectionObj.SectionList)
3585
3586    ## CycleReferenceCheck() method
3587    #
3588    #   Check whether cycle reference exists in FDF
3589    #
3590    #   @param  self        The object pointer
3591    #   @retval True        cycle reference exists
3592    #   @retval False       Not exists cycle reference
3593    #
3594    def CycleReferenceCheck(self):
3595
3596        CycleRefExists = False
3597
3598        try:
3599            for FvName in self.Profile.FvDict.keys():
3600                LogStr = "Cycle Reference Checking for FV: %s\n" % FvName
3601                RefFvStack = []
3602                RefFvStack.append(FvName)
3603                FdAnalyzedList = []
3604
3605                while RefFvStack != []:
3606                    FvNameFromStack = RefFvStack.pop()
3607                    if FvNameFromStack.upper() in self.Profile.FvDict.keys():
3608                        FvObj = self.Profile.FvDict[FvNameFromStack.upper()]
3609                    else:
3610                        continue
3611
3612                    RefFdList = []
3613                    RefFvList = []
3614                    self.__GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
3615
3616                    for RefFdName in RefFdList:
3617                        if RefFdName in FdAnalyzedList:
3618                            continue
3619
3620                        LogStr += "FD %s is referenced by FV %s\n" % (RefFdName, FvNameFromStack)
3621                        FvInFdList = self.__GetFvInFd(RefFdName)
3622                        if FvInFdList != []:
3623                            LogStr += "FD %s contains FV: " % RefFdName
3624                            for FvObj in FvInFdList:
3625                                LogStr += FvObj
3626                                LogStr += ' \n'
3627                                if FvObj not in RefFvStack:
3628                                    RefFvStack.append(FvObj)
3629
3630                                if FvName in RefFvStack:
3631                                    CycleRefExists = True
3632                                    raise Warning(LogStr)
3633                        FdAnalyzedList.append(RefFdName)
3634
3635                    for RefFvName in RefFvList:
3636                        LogStr += "FV %s is referenced by FV %s\n" % (RefFvName, FvNameFromStack)
3637                        if RefFvName not in RefFvStack:
3638                            RefFvStack.append(RefFvName)
3639
3640                        if FvName in RefFvStack:
3641                            CycleRefExists = True
3642                            raise Warning(LogStr)
3643
3644        except Warning:
3645            print LogStr
3646
3647        finally:
3648            return CycleRefExists
3649
3650if __name__ == "__main__":
3651    import sys
3652    try:
3653        test_file = sys.argv[1]
3654    except IndexError, v:
3655        print "Usage: %s filename" % sys.argv[0]
3656        sys.exit(1)
3657
3658    parser = FdfParser(test_file)
3659    try:
3660        parser.ParseFile()
3661        parser.CycleReferenceCheck()
3662    except Warning, X:
3663        print X.message
3664    else:
3665        print "Success!"
3666
3667