ea1c3eeb3047363f5ff6f30f81b73d46617a1b7c
[mirror_edk2.git] / BaseTools / Source / Python / GenFds / FdfParser.py
1 ## @file\r
2 # parse FDF file\r
3 #\r
4 #  Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>\r
5 #  Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>\r
6 #\r
7 #  SPDX-License-Identifier: BSD-2-Clause-Patent\r
8 #\r
9 \r
10 ##\r
11 # Import Modules\r
12 #\r
13 from __future__ import print_function\r
14 from __future__ import absolute_import\r
15 from re import compile, DOTALL\r
16 from string import hexdigits\r
17 from uuid import UUID\r
18 \r
19 from Common.BuildToolError import *\r
20 from Common import EdkLogger\r
21 from Common.Misc import PathClass, tdict, ProcessDuplicatedInf\r
22 from Common.StringUtils import NormPath, ReplaceMacro\r
23 from Common import GlobalData\r
24 from Common.Expression import *\r
25 from Common.DataType import *\r
26 from Common.MultipleWorkspace import MultipleWorkspace as mws\r
27 import Common.LongFilePathOs as os\r
28 from Common.LongFilePathSupport import OpenLongFilePath as open\r
29 from Common.RangeExpression import RangeExpression\r
30 from collections import OrderedDict\r
31 \r
32 from .Fd import FD\r
33 from .Region import Region\r
34 from .Fv import FV\r
35 from .AprioriSection import AprioriSection\r
36 from .FfsInfStatement import FfsInfStatement\r
37 from .FfsFileStatement import FileStatement\r
38 from .VerSection import VerSection\r
39 from .UiSection import UiSection\r
40 from .FvImageSection import FvImageSection\r
41 from .DataSection import DataSection\r
42 from .DepexSection import DepexSection\r
43 from .CompressSection import CompressSection\r
44 from .GuidSection import GuidSection\r
45 from .Capsule import EFI_CERT_TYPE_PKCS7_GUID, EFI_CERT_TYPE_RSA2048_SHA256_GUID, Capsule\r
46 from .CapsuleData import CapsuleFfs, CapsulePayload, CapsuleFv, CapsuleFd, CapsuleAnyFile, CapsuleAfile\r
47 from .RuleComplexFile import RuleComplexFile\r
48 from .RuleSimpleFile import RuleSimpleFile\r
49 from .EfiSection import EfiSection\r
50 from .OptionRom import OPTIONROM\r
51 from .OptRomInfStatement import OptRomInfStatement, OverrideAttribs\r
52 from .OptRomFileStatement import OptRomFileStatement\r
53 from .GenFdsGlobalVariable import GenFdsGlobalVariable\r
54 \r
55 T_CHAR_CR = '\r'\r
56 T_CHAR_TAB = '\t'\r
57 T_CHAR_DOUBLE_QUOTE = '\"'\r
58 T_CHAR_SINGLE_QUOTE = '\''\r
59 T_CHAR_BRACE_R = '}'\r
60 \r
61 SEPARATORS = {TAB_EQUAL_SPLIT, TAB_VALUE_SPLIT, TAB_COMMA_SPLIT, '{', T_CHAR_BRACE_R}\r
62 ALIGNMENTS = {"Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K", "64K", "128K",\r
63                                     "256K", "512K", "1M", "2M", "4M", "8M", "16M"}\r
64 ALIGNMENT_NOAUTO = ALIGNMENTS - {"Auto"}\r
65 CR_LB_SET = {T_CHAR_CR, TAB_LINE_BREAK}\r
66 \r
67 RegionSizePattern = compile("\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*")\r
68 RegionSizeGuidPattern = compile("\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*\|\s*(?P<size>\w+\.\w+[\.\w\[\]]*)\s*")\r
69 RegionOffsetPcdPattern = compile("\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*$")\r
70 ShortcutPcdPattern = compile("\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*")\r
71 BaseAddrValuePattern = compile('^0[xX][0-9a-fA-F]+')\r
72 FileExtensionPattern = compile(r'([a-zA-Z][a-zA-Z0-9]*)')\r
73 TokenFindPattern = compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')\r
74 AllIncludeFileList = []\r
75 \r
76 # Get the closest parent\r
77 def GetParentAtLine (Line):\r
78     for Profile in AllIncludeFileList:\r
79         if Profile.IsLineInFile(Line):\r
80             return Profile\r
81     return None\r
82 \r
83 # Check include loop\r
84 def IsValidInclude (File, Line):\r
85     for Profile in AllIncludeFileList:\r
86         if Profile.IsLineInFile(Line) and Profile.FileName == File:\r
87             return False\r
88 \r
89     return True\r
90 \r
91 def GetRealFileLine (File, Line):\r
92     InsertedLines = 0\r
93     for Profile in AllIncludeFileList:\r
94         if Profile.IsLineInFile(Line):\r
95             return Profile.GetLineInFile(Line)\r
96         elif Line >= Profile.InsertStartLineNumber and Profile.Level == 1:\r
97             InsertedLines += Profile.GetTotalLines()\r
98 \r
99     return (File, Line - InsertedLines)\r
100 \r
101 ## The exception class that used to report error messages when parsing FDF\r
102 #\r
103 # Currently the "ToolName" is set to be "FdfParser".\r
104 #\r
105 class Warning (Exception):\r
106     ## The constructor\r
107     #\r
108     #   @param  self        The object pointer\r
109     #   @param  Str         The message to record\r
110     #   @param  File        The FDF name\r
111     #   @param  Line        The Line number that error occurs\r
112     #\r
113     def __init__(self, Str, File = None, Line = None):\r
114         FileLineTuple = GetRealFileLine(File, Line)\r
115         self.FileName = FileLineTuple[0]\r
116         self.LineNumber = FileLineTuple[1]\r
117         self.OriginalLineNumber = Line\r
118         self.Message = Str\r
119         self.ToolName = 'FdfParser'\r
120 \r
121     def __str__(self):\r
122         return self.Message\r
123 \r
124     # helper functions to facilitate consistency in warnings\r
125     # each function is for a different common warning\r
126     @staticmethod\r
127     def Expected(Str, File, Line):\r
128         return Warning("expected {}".format(Str), File, Line)\r
129     @staticmethod\r
130     def ExpectedEquals(File, Line):\r
131         return Warning.Expected("'='", File, Line)\r
132     @staticmethod\r
133     def ExpectedCurlyOpen(File, Line):\r
134         return Warning.Expected("'{'", File, Line)\r
135     @staticmethod\r
136     def ExpectedCurlyClose(File, Line):\r
137         return Warning.Expected("'}'", File, Line)\r
138     @staticmethod\r
139     def ExpectedBracketClose(File, Line):\r
140         return Warning.Expected("']'", File, Line)\r
141 \r
142 ## The Include file content class that used to record file data when parsing include file\r
143 #\r
144 # May raise Exception when opening file.\r
145 #\r
146 class IncludeFileProfile:\r
147     ## The constructor\r
148     #\r
149     #   @param  self        The object pointer\r
150     #   @param  FileName    The file that to be parsed\r
151     #\r
152     def __init__(self, FileName):\r
153         self.FileName = FileName\r
154         self.FileLinesList = []\r
155         try:\r
156             with open(FileName, "r") as fsock:\r
157                 self.FileLinesList = fsock.readlines()\r
158                 for index, line in enumerate(self.FileLinesList):\r
159                     if not line.endswith(TAB_LINE_BREAK):\r
160                         self.FileLinesList[index] += TAB_LINE_BREAK\r
161         except:\r
162             EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)\r
163 \r
164         self.InsertStartLineNumber = None\r
165         self.InsertAdjust = 0\r
166         self.IncludeFileList = []\r
167         self.Level = 1 # first level include file\r
168 \r
169     def GetTotalLines(self):\r
170         TotalLines = self.InsertAdjust + len(self.FileLinesList)\r
171 \r
172         for Profile in self.IncludeFileList:\r
173             TotalLines += Profile.GetTotalLines()\r
174 \r
175         return TotalLines\r
176 \r
177     def IsLineInFile(self, Line):\r
178         if Line >= self.InsertStartLineNumber and Line < self.InsertStartLineNumber + self.GetTotalLines():\r
179             return True\r
180 \r
181         return False\r
182 \r
183     def GetLineInFile(self, Line):\r
184         if not self.IsLineInFile (Line):\r
185             return (self.FileName, -1)\r
186 \r
187         InsertedLines = self.InsertStartLineNumber\r
188 \r
189         for Profile in self.IncludeFileList:\r
190             if Profile.IsLineInFile(Line):\r
191                 return Profile.GetLineInFile(Line)\r
192             elif Line >= Profile.InsertStartLineNumber:\r
193                 InsertedLines += Profile.GetTotalLines()\r
194 \r
195         return (self.FileName, Line - InsertedLines + 1)\r
196 \r
197 ## The FDF content class that used to record file data when parsing FDF\r
198 #\r
199 # May raise Exception when opening file.\r
200 #\r
201 class FileProfile:\r
202     ## The constructor\r
203     #\r
204     #   @param  self        The object pointer\r
205     #   @param  FileName    The file that to be parsed\r
206     #\r
207     def __init__(self, FileName):\r
208         self.FileLinesList = []\r
209         try:\r
210             with open(FileName, "r") as fsock:\r
211                 self.FileLinesList = fsock.readlines()\r
212 \r
213         except:\r
214             EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)\r
215 \r
216         self.FileName = FileName\r
217         self.PcdDict = OrderedDict()\r
218         self.PcdLocalDict = OrderedDict()\r
219         self.InfList = []\r
220         self.InfDict = {'ArchTBD':[]}\r
221         # ECC will use this Dict and List information\r
222         self.PcdFileLineDict = {}\r
223         self.InfFileLineList = []\r
224 \r
225         self.FdDict = {}\r
226         self.FdNameNotSet = False\r
227         self.FvDict = {}\r
228         self.CapsuleDict = {}\r
229         self.RuleDict = {}\r
230         self.OptRomDict = {}\r
231         self.FmpPayloadDict = {}\r
232 \r
233 ## The syntax parser for FDF\r
234 #\r
235 # PreprocessFile method should be called prior to ParseFile\r
236 # CycleReferenceCheck method can detect cycles in FDF contents\r
237 #\r
238 # GetNext*** procedures mean these procedures will get next token first, then make judgement.\r
239 # Get*** procedures mean these procedures will make judgement on current token only.\r
240 #\r
241 class FdfParser:\r
242     ## The constructor\r
243     #\r
244     #   @param  self        The object pointer\r
245     #   @param  FileName    The file that to be parsed\r
246     #\r
247     def __init__(self, FileName):\r
248         self.Profile = FileProfile(FileName)\r
249         self.FileName = FileName\r
250         self.CurrentLineNumber = 1\r
251         self.CurrentOffsetWithinLine = 0\r
252         self.CurrentFdName = None\r
253         self.CurrentFvName = None\r
254         self._Token = ""\r
255         self._SkippedChars = ""\r
256         GlobalData.gFdfParser = self\r
257 \r
258         # Used to section info\r
259         self._CurSection = []\r
260         # Key: [section name, UI name, arch]\r
261         # Value: {MACRO_NAME: MACRO_VALUE}\r
262         self._MacroDict = tdict(True, 3)\r
263         self._PcdDict = OrderedDict()\r
264 \r
265         self._WipeOffArea = []\r
266         if GenFdsGlobalVariable.WorkSpaceDir == '':\r
267             GenFdsGlobalVariable.WorkSpaceDir = os.getenv("WORKSPACE")\r
268 \r
269     ## _SkipWhiteSpace() method\r
270     #\r
271     #   Skip white spaces from current char.\r
272     #\r
273     #   @param  self        The object pointer\r
274     #\r
275     def _SkipWhiteSpace(self):\r
276         while not self._EndOfFile():\r
277             if self._CurrentChar() in {TAB_PRINTCHAR_NUL, T_CHAR_CR, TAB_LINE_BREAK, TAB_SPACE_SPLIT, T_CHAR_TAB}:\r
278                 self._SkippedChars += str(self._CurrentChar())\r
279                 self._GetOneChar()\r
280             else:\r
281                 return\r
282         return\r
283 \r
284     ## _EndOfFile() method\r
285     #\r
286     #   Judge current buffer pos is at file end\r
287     #\r
288     #   @param  self        The object pointer\r
289     #   @retval True        Current File buffer position is at file end\r
290     #   @retval False       Current File buffer position is NOT at file end\r
291     #\r
292     def _EndOfFile(self):\r
293         NumberOfLines = len(self.Profile.FileLinesList)\r
294         SizeOfLastLine = len(self.Profile.FileLinesList[-1])\r
295         if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1:\r
296             return True\r
297         if self.CurrentLineNumber > NumberOfLines:\r
298             return True\r
299         return False\r
300 \r
301     ## _EndOfLine() method\r
302     #\r
303     #   Judge current buffer pos is at line end\r
304     #\r
305     #   @param  self        The object pointer\r
306     #   @retval True        Current File buffer position is at line end\r
307     #   @retval False       Current File buffer position is NOT at line end\r
308     #\r
309     def _EndOfLine(self):\r
310         if self.CurrentLineNumber > len(self.Profile.FileLinesList):\r
311             return True\r
312         SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1])\r
313         if self.CurrentOffsetWithinLine >= SizeOfCurrentLine:\r
314             return True\r
315         return False\r
316 \r
317     ## Rewind() method\r
318     #\r
319     #   Reset file data buffer to the initial state\r
320     #\r
321     #   @param  self        The object pointer\r
322     #   @param  DestLine    Optional new destination line number.\r
323     #   @param  DestOffset  Optional new destination offset.\r
324     #\r
325     def Rewind(self, DestLine = 1, DestOffset = 0):\r
326         self.CurrentLineNumber = DestLine\r
327         self.CurrentOffsetWithinLine = DestOffset\r
328 \r
329     ## _UndoOneChar() method\r
330     #\r
331     #   Go back one char in the file buffer\r
332     #\r
333     #   @param  self        The object pointer\r
334     #   @retval True        Successfully go back one char\r
335     #   @retval False       Not able to go back one char as file beginning reached\r
336     #\r
337     def _UndoOneChar(self):\r
338         if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0:\r
339             return False\r
340         elif self.CurrentOffsetWithinLine == 0:\r
341             self.CurrentLineNumber -= 1\r
342             self.CurrentOffsetWithinLine = len(self._CurrentLine()) - 1\r
343         else:\r
344             self.CurrentOffsetWithinLine -= 1\r
345         return True\r
346 \r
347     ## _GetOneChar() method\r
348     #\r
349     #   Move forward one char in the file buffer\r
350     #\r
351     #   @param  self        The object pointer\r
352     #\r
353     def _GetOneChar(self):\r
354         if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:\r
355             self.CurrentLineNumber += 1\r
356             self.CurrentOffsetWithinLine = 0\r
357         else:\r
358             self.CurrentOffsetWithinLine += 1\r
359 \r
360     ## _CurrentChar() method\r
361     #\r
362     #   Get the char pointed to by the file buffer pointer\r
363     #\r
364     #   @param  self        The object pointer\r
365     #   @retval Char        Current char\r
366     #\r
367     def _CurrentChar(self):\r
368         return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine]\r
369 \r
370     ## _NextChar() method\r
371     #\r
372     #   Get the one char pass the char pointed to by the file buffer pointer\r
373     #\r
374     #   @param  self        The object pointer\r
375     #   @retval Char        Next char\r
376     #\r
377     def _NextChar(self):\r
378         if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:\r
379             return self.Profile.FileLinesList[self.CurrentLineNumber][0]\r
380         return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1]\r
381 \r
382     ## _SetCurrentCharValue() method\r
383     #\r
384     #   Modify the value of current char\r
385     #\r
386     #   @param  self        The object pointer\r
387     #   @param  Value       The new value of current char\r
388     #\r
389     def _SetCurrentCharValue(self, Value):\r
390         self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value\r
391 \r
392     ## _CurrentLine() method\r
393     #\r
394     #   Get the list that contains current line contents\r
395     #\r
396     #   @param  self        The object pointer\r
397     #   @retval List        current line contents\r
398     #\r
399     def _CurrentLine(self):\r
400         return self.Profile.FileLinesList[self.CurrentLineNumber - 1]\r
401 \r
402     def _StringToList(self):\r
403         self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList]\r
404         if not self.Profile.FileLinesList:\r
405             EdkLogger.error('FdfParser', FILE_READ_FAILURE, 'The file is empty!', File=self.FileName)\r
406         self.Profile.FileLinesList[-1].append(' ')\r
407 \r
408     def _ReplaceFragment(self, StartPos, EndPos, Value = ' '):\r
409         if StartPos[0] == EndPos[0]:\r
410             Offset = StartPos[1]\r
411             while Offset <= EndPos[1]:\r
412                 self.Profile.FileLinesList[StartPos[0]][Offset] = Value\r
413                 Offset += 1\r
414             return\r
415 \r
416         Offset = StartPos[1]\r
417         while self.Profile.FileLinesList[StartPos[0]][Offset] not in CR_LB_SET:\r
418             self.Profile.FileLinesList[StartPos[0]][Offset] = Value\r
419             Offset += 1\r
420 \r
421         Line = StartPos[0]\r
422         while Line < EndPos[0]:\r
423             Offset = 0\r
424             while self.Profile.FileLinesList[Line][Offset] not in CR_LB_SET:\r
425                 self.Profile.FileLinesList[Line][Offset] = Value\r
426                 Offset += 1\r
427             Line += 1\r
428 \r
429         Offset = 0\r
430         while Offset <= EndPos[1]:\r
431             self.Profile.FileLinesList[EndPos[0]][Offset] = Value\r
432             Offset += 1\r
433 \r
434     def _SetMacroValue(self, Macro, Value):\r
435         if not self._CurSection:\r
436             return\r
437 \r
438         MacroDict = {}\r
439         if not self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]]:\r
440             self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]] = MacroDict\r
441         else:\r
442             MacroDict = self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]]\r
443         MacroDict[Macro] = Value\r
444 \r
445     def _GetMacroValue(self, Macro):\r
446         # Highest priority\r
447         if Macro in GlobalData.gCommandLineDefines:\r
448             return GlobalData.gCommandLineDefines[Macro]\r
449         if Macro in GlobalData.gGlobalDefines:\r
450             return GlobalData.gGlobalDefines[Macro]\r
451 \r
452         if self._CurSection:\r
453             MacroDict = self._MacroDict[\r
454                         self._CurSection[0],\r
455                         self._CurSection[1],\r
456                         self._CurSection[2]\r
457             ]\r
458             if MacroDict and Macro in MacroDict:\r
459                 return MacroDict[Macro]\r
460 \r
461         # Lowest priority\r
462         if Macro in GlobalData.gPlatformDefines:\r
463             return GlobalData.gPlatformDefines[Macro]\r
464         return None\r
465 \r
466     def _SectionHeaderParser(self, Section):\r
467         # [Defines]\r
468         # [FD.UiName]: use dummy instead if UI name is optional\r
469         # [FV.UiName]\r
470         # [Capsule.UiName]\r
471         # [Rule]: don't take rule section into account, macro is not allowed in this section\r
472         # [OptionRom.DriverName]\r
473         self._CurSection = []\r
474         Section = Section.strip()[1:-1].upper().replace(' ', '').strip(TAB_SPLIT)\r
475         ItemList = Section.split(TAB_SPLIT)\r
476         Item = ItemList[0]\r
477         if Item == '' or Item == 'RULE':\r
478             return\r
479 \r
480         if Item == TAB_COMMON_DEFINES.upper():\r
481             self._CurSection = [TAB_COMMON, TAB_COMMON, TAB_COMMON]\r
482         elif len(ItemList) > 1:\r
483             self._CurSection = [ItemList[0], ItemList[1], TAB_COMMON]\r
484         elif len(ItemList) > 0:\r
485             self._CurSection = [ItemList[0], 'DUMMY', TAB_COMMON]\r
486 \r
487     ## PreprocessFile() method\r
488     #\r
489     #   Preprocess file contents, replace comments with spaces.\r
490     #   In the end, rewind the file buffer pointer to the beginning\r
491     #   BUGBUG: No !include statement processing contained in this procedure\r
492     #   !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1]\r
493     #\r
494     #   @param  self        The object pointer\r
495     #\r
496     def PreprocessFile(self):\r
497         self.Rewind()\r
498         InComment = False\r
499         DoubleSlashComment = False\r
500         HashComment = False\r
501         # HashComment in quoted string " " is ignored.\r
502         InString = False\r
503 \r
504         while not self._EndOfFile():\r
505 \r
506             if self._CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment:\r
507                 InString = not InString\r
508             # meet new line, then no longer in a comment for // and '#'\r
509             if self._CurrentChar() == TAB_LINE_BREAK:\r
510                 self.CurrentLineNumber += 1\r
511                 self.CurrentOffsetWithinLine = 0\r
512                 if InComment and DoubleSlashComment:\r
513                     InComment = False\r
514                     DoubleSlashComment = False\r
515                 if InComment and HashComment:\r
516                     InComment = False\r
517                     HashComment = False\r
518             # check for */ comment end\r
519             elif InComment and not DoubleSlashComment and not HashComment and self._CurrentChar() == TAB_STAR and self._NextChar() == TAB_BACK_SLASH:\r
520                 self._SetCurrentCharValue(TAB_SPACE_SPLIT)\r
521                 self._GetOneChar()\r
522                 self._SetCurrentCharValue(TAB_SPACE_SPLIT)\r
523                 self._GetOneChar()\r
524                 InComment = False\r
525             # set comments to spaces\r
526             elif InComment:\r
527                 self._SetCurrentCharValue(TAB_SPACE_SPLIT)\r
528                 self._GetOneChar()\r
529             # check for // comment\r
530             elif self._CurrentChar() == TAB_BACK_SLASH and self._NextChar() == TAB_BACK_SLASH and not self._EndOfLine():\r
531                 InComment = True\r
532                 DoubleSlashComment = True\r
533             # check for '#' comment\r
534             elif self._CurrentChar() == TAB_COMMENT_SPLIT and not self._EndOfLine() and not InString:\r
535                 InComment = True\r
536                 HashComment = True\r
537             # check for /* comment start\r
538             elif self._CurrentChar() == TAB_BACK_SLASH and self._NextChar() == TAB_STAR:\r
539                 self._SetCurrentCharValue(TAB_SPACE_SPLIT)\r
540                 self._GetOneChar()\r
541                 self._SetCurrentCharValue(TAB_SPACE_SPLIT)\r
542                 self._GetOneChar()\r
543                 InComment = True\r
544             else:\r
545                 self._GetOneChar()\r
546 \r
547         # restore from ListOfList to ListOfString\r
548         self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]\r
549         self.Rewind()\r
550 \r
551     ## PreprocessIncludeFile() method\r
552     #\r
553     #   Preprocess file contents, replace !include statements with file contents.\r
554     #   In the end, rewind the file buffer pointer to the beginning\r
555     #\r
556     #   @param  self        The object pointer\r
557     #\r
558     def PreprocessIncludeFile(self):\r
559       # nested include support\r
560         Processed = False\r
561         MacroDict = {}\r
562         while self._GetNextToken():\r
563 \r
564             if self._Token == TAB_DEFINE:\r
565                 if not self._GetNextToken():\r
566                     raise Warning.Expected("Macro name", self.FileName, self.CurrentLineNumber)\r
567                 Macro = self._Token\r
568                 if not self._IsToken(TAB_EQUAL_SPLIT):\r
569                     raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
570                 Value = self._GetExpression()\r
571                 MacroDict[Macro] = Value\r
572 \r
573             elif self._Token == TAB_INCLUDE:\r
574                 Processed = True\r
575                 IncludeLine = self.CurrentLineNumber\r
576                 IncludeOffset = self.CurrentOffsetWithinLine - len(TAB_INCLUDE)\r
577                 if not self._GetNextToken():\r
578                     raise Warning.Expected("include file name", self.FileName, self.CurrentLineNumber)\r
579                 IncFileName = self._Token\r
580                 PreIndex = 0\r
581                 StartPos = IncFileName.find('$(', PreIndex)\r
582                 EndPos = IncFileName.find(')', StartPos+2)\r
583                 while StartPos != -1 and EndPos != -1:\r
584                     Macro = IncFileName[StartPos+2: EndPos]\r
585                     MacroVal = self._GetMacroValue(Macro)\r
586                     if not MacroVal:\r
587                         if Macro in MacroDict:\r
588                             MacroVal = MacroDict[Macro]\r
589                     if MacroVal is not None:\r
590                         IncFileName = IncFileName.replace('$(' + Macro + ')', MacroVal, 1)\r
591                         if MacroVal.find('$(') != -1:\r
592                             PreIndex = StartPos\r
593                         else:\r
594                             PreIndex = StartPos + len(MacroVal)\r
595                     else:\r
596                         raise Warning("The Macro %s is not defined" %Macro, self.FileName, self.CurrentLineNumber)\r
597                     StartPos = IncFileName.find('$(', PreIndex)\r
598                     EndPos = IncFileName.find(')', StartPos+2)\r
599 \r
600                 IncludedFile = NormPath(IncFileName)\r
601                 #\r
602                 # First search the include file under the same directory as FDF file\r
603                 #\r
604                 IncludedFile1 = PathClass(IncludedFile, os.path.dirname(self.FileName))\r
605                 ErrorCode = IncludedFile1.Validate()[0]\r
606                 if ErrorCode != 0:\r
607                     #\r
608                     # Then search the include file under the same directory as DSC file\r
609                     #\r
610                     PlatformDir = ''\r
611                     if GenFdsGlobalVariable.ActivePlatform:\r
612                         PlatformDir = GenFdsGlobalVariable.ActivePlatform.Dir\r
613                     elif GlobalData.gActivePlatform:\r
614                         PlatformDir = GlobalData.gActivePlatform.MetaFile.Dir\r
615                     IncludedFile1 = PathClass(IncludedFile, PlatformDir)\r
616                     ErrorCode = IncludedFile1.Validate()[0]\r
617                     if ErrorCode != 0:\r
618                         #\r
619                         # Also search file under the WORKSPACE directory\r
620                         #\r
621                         IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)\r
622                         ErrorCode = IncludedFile1.Validate()[0]\r
623                         if ErrorCode != 0:\r
624                             raise Warning("The include file does not exist under below directories: \n%s\n%s\n%s\n"%(os.path.dirname(self.FileName), PlatformDir, GlobalData.gWorkspace),\r
625                                           self.FileName, self.CurrentLineNumber)\r
626 \r
627                 if not IsValidInclude (IncludedFile1.Path, self.CurrentLineNumber):\r
628                     raise Warning("The include file {0} is causing a include loop.\n".format (IncludedFile1.Path), self.FileName, self.CurrentLineNumber)\r
629 \r
630                 IncFileProfile = IncludeFileProfile(IncludedFile1.Path)\r
631 \r
632                 CurrentLine = self.CurrentLineNumber\r
633                 CurrentOffset = self.CurrentOffsetWithinLine\r
634                 # list index of the insertion, note that line number is 'CurrentLine + 1'\r
635                 InsertAtLine = CurrentLine\r
636                 ParentProfile = GetParentAtLine (CurrentLine)\r
637                 if ParentProfile is not None:\r
638                     ParentProfile.IncludeFileList.insert(0, IncFileProfile)\r
639                     IncFileProfile.Level = ParentProfile.Level + 1\r
640                 IncFileProfile.InsertStartLineNumber = InsertAtLine + 1\r
641                 # deal with remaining portions after "!include filename", if exists.\r
642                 if self._GetNextToken():\r
643                     if self.CurrentLineNumber == CurrentLine:\r
644                         RemainingLine = self._CurrentLine()[CurrentOffset:]\r
645                         self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine)\r
646                         IncFileProfile.InsertAdjust += 1\r
647                         self.CurrentLineNumber += 1\r
648                         self.CurrentOffsetWithinLine = 0\r
649 \r
650                 for Line in IncFileProfile.FileLinesList:\r
651                     self.Profile.FileLinesList.insert(InsertAtLine, Line)\r
652                     self.CurrentLineNumber += 1\r
653                     InsertAtLine += 1\r
654 \r
655                 # reversely sorted to better determine error in file\r
656                 AllIncludeFileList.insert(0, IncFileProfile)\r
657 \r
658                 # comment out the processed include file statement\r
659                 TempList = list(self.Profile.FileLinesList[IncludeLine - 1])\r
660                 TempList.insert(IncludeOffset, TAB_COMMENT_SPLIT)\r
661                 self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList)\r
662             if Processed: # Nested and back-to-back support\r
663                 self.Rewind(DestLine = IncFileProfile.InsertStartLineNumber - 1)\r
664                 Processed = False\r
665         # Preprocess done.\r
666         self.Rewind()\r
667 \r
668     @staticmethod\r
669     def _GetIfListCurrentItemStat(IfList):\r
670         if len(IfList) == 0:\r
671             return True\r
672 \r
673         for Item in IfList:\r
674             if Item[1] == False:\r
675                 return False\r
676 \r
677         return True\r
678 \r
679     ## PreprocessConditionalStatement() method\r
680     #\r
681     #   Preprocess conditional statement.\r
682     #   In the end, rewind the file buffer pointer to the beginning\r
683     #\r
684     #   @param  self        The object pointer\r
685     #\r
686     def PreprocessConditionalStatement(self):\r
687         # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined]\r
688         IfList = []\r
689         RegionLayoutLine = 0\r
690         ReplacedLine = -1\r
691         while self._GetNextToken():\r
692             # Determine section name and the location dependent macro\r
693             if self._GetIfListCurrentItemStat(IfList):\r
694                 if self._Token.startswith(TAB_SECTION_START):\r
695                     Header = self._Token\r
696                     if not self._Token.endswith(TAB_SECTION_END):\r
697                         self._SkipToToken(TAB_SECTION_END)\r
698                         Header += self._SkippedChars\r
699                     if Header.find('$(') != -1:\r
700                         raise Warning("macro cannot be used in section header", self.FileName, self.CurrentLineNumber)\r
701                     self._SectionHeaderParser(Header)\r
702                     continue\r
703                 # Replace macros except in RULE section or out of section\r
704                 elif self._CurSection and ReplacedLine != self.CurrentLineNumber:\r
705                     ReplacedLine = self.CurrentLineNumber\r
706                     self._UndoToken()\r
707                     CurLine = self.Profile.FileLinesList[ReplacedLine - 1]\r
708                     PreIndex = 0\r
709                     StartPos = CurLine.find('$(', PreIndex)\r
710                     EndPos = CurLine.find(')', StartPos+2)\r
711                     while StartPos != -1 and EndPos != -1 and self._Token not in {TAB_IF_DEF, TAB_IF_N_DEF, TAB_IF, TAB_ELSE_IF}:\r
712                         MacroName = CurLine[StartPos+2: EndPos]\r
713                         MacroValue = self._GetMacroValue(MacroName)\r
714                         if MacroValue is not None:\r
715                             CurLine = CurLine.replace('$(' + MacroName + ')', MacroValue, 1)\r
716                             if MacroValue.find('$(') != -1:\r
717                                 PreIndex = StartPos\r
718                             else:\r
719                                 PreIndex = StartPos + len(MacroValue)\r
720                         else:\r
721                             PreIndex = EndPos + 1\r
722                         StartPos = CurLine.find('$(', PreIndex)\r
723                         EndPos = CurLine.find(')', StartPos+2)\r
724                     self.Profile.FileLinesList[ReplacedLine - 1] = CurLine\r
725                     continue\r
726 \r
727             if self._Token == TAB_DEFINE:\r
728                 if self._GetIfListCurrentItemStat(IfList):\r
729                     if not self._CurSection:\r
730                         raise Warning("macro cannot be defined in Rule section or out of section", self.FileName, self.CurrentLineNumber)\r
731                     DefineLine = self.CurrentLineNumber - 1\r
732                     DefineOffset = self.CurrentOffsetWithinLine - len(TAB_DEFINE)\r
733                     if not self._GetNextToken():\r
734                         raise Warning.Expected("Macro name", self.FileName, self.CurrentLineNumber)\r
735                     Macro = self._Token\r
736                     if not self._IsToken(TAB_EQUAL_SPLIT):\r
737                         raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
738 \r
739                     Value = self._GetExpression()\r
740                     self._SetMacroValue(Macro, Value)\r
741                     self._WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))\r
742             elif self._Token == 'SET':\r
743                 if not self._GetIfListCurrentItemStat(IfList):\r
744                     continue\r
745                 SetLine = self.CurrentLineNumber - 1\r
746                 SetOffset = self.CurrentOffsetWithinLine - len('SET')\r
747                 PcdPair = self._GetNextPcdSettings()\r
748                 PcdName = "%s.%s" % (PcdPair[1], PcdPair[0])\r
749                 if not self._IsToken(TAB_EQUAL_SPLIT):\r
750                     raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
751 \r
752                 Value = self._GetExpression()\r
753                 Value = self._EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)\r
754 \r
755                 self._PcdDict[PcdName] = Value\r
756 \r
757                 self.Profile.PcdDict[PcdPair] = Value\r
758                 self.SetPcdLocalation(PcdPair)\r
759                 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
760                 self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple\r
761 \r
762                 self._WipeOffArea.append(((SetLine, SetOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))\r
763             elif self._Token in {TAB_IF_DEF, TAB_IF_N_DEF, TAB_IF}:\r
764                 IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self._Token))\r
765                 IfList.append([IfStartPos, None, None])\r
766 \r
767                 CondLabel = self._Token\r
768                 Expression = self._GetExpression()\r
769 \r
770                 if CondLabel == TAB_IF:\r
771                     ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')\r
772                 else:\r
773                     ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'in')\r
774                     if CondLabel == TAB_IF_N_DEF:\r
775                         ConditionSatisfied = not ConditionSatisfied\r
776 \r
777                 BranchDetermined = ConditionSatisfied\r
778                 IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined]\r
779                 if ConditionSatisfied:\r
780                     self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))\r
781             elif self._Token in {TAB_ELSE_IF, TAB_ELSE}:\r
782                 ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self._Token))\r
783                 if len(IfList) <= 0:\r
784                     raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)\r
785 \r
786                 if IfList[-1][1]:\r
787                     IfList[-1] = [ElseStartPos, False, True]\r
788                     self._WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))\r
789                 else:\r
790                     self._WipeOffArea.append((IfList[-1][0], ElseStartPos))\r
791                     IfList[-1] = [ElseStartPos, True, IfList[-1][2]]\r
792                     if self._Token == TAB_ELSE_IF:\r
793                         Expression = self._GetExpression()\r
794                         ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')\r
795                         IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]]\r
796 \r
797                     if IfList[-1][1]:\r
798                         if IfList[-1][2]:\r
799                             IfList[-1][1] = False\r
800                         else:\r
801                             IfList[-1][2] = True\r
802                             self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))\r
803             elif self._Token == '!endif':\r
804                 if len(IfList) <= 0:\r
805                     raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)\r
806                 if IfList[-1][1]:\r
807                     self._WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))\r
808                 else:\r
809                     self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))\r
810 \r
811                 IfList.pop()\r
812             elif not IfList:    # Don't use PCDs inside conditional directive\r
813                 if self.CurrentLineNumber <= RegionLayoutLine:\r
814                     # Don't try the same line twice\r
815                     continue\r
816                 SetPcd = ShortcutPcdPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])\r
817                 if SetPcd:\r
818                     self._PcdDict[SetPcd.group('name')] = SetPcd.group('value')\r
819                     RegionLayoutLine = self.CurrentLineNumber\r
820                     continue\r
821                 RegionSize = RegionSizePattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])\r
822                 if not RegionSize:\r
823                     RegionLayoutLine = self.CurrentLineNumber\r
824                     continue\r
825                 RegionSizeGuid = RegionSizeGuidPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber])\r
826                 if not RegionSizeGuid:\r
827                     RegionLayoutLine = self.CurrentLineNumber + 1\r
828                     continue\r
829                 self._PcdDict[RegionSizeGuid.group('base')] = RegionSize.group('base')\r
830                 self._PcdDict[RegionSizeGuid.group('size')] = RegionSize.group('size')\r
831                 RegionLayoutLine = self.CurrentLineNumber + 1\r
832 \r
833         if IfList:\r
834             raise Warning("Missing !endif", self.FileName, self.CurrentLineNumber)\r
835         self.Rewind()\r
836 \r
837     def _CollectMacroPcd(self):\r
838         MacroDict = {}\r
839 \r
840         # PCD macro\r
841         MacroDict.update(GlobalData.gPlatformPcds)\r
842         MacroDict.update(self._PcdDict)\r
843 \r
844         # Lowest priority\r
845         MacroDict.update(GlobalData.gPlatformDefines)\r
846 \r
847         if self._CurSection:\r
848             # Defines macro\r
849             ScopeMacro = self._MacroDict[TAB_COMMON, TAB_COMMON, TAB_COMMON]\r
850             if ScopeMacro:\r
851                 MacroDict.update(ScopeMacro)\r
852 \r
853             # Section macro\r
854             ScopeMacro = self._MacroDict[\r
855                         self._CurSection[0],\r
856                         self._CurSection[1],\r
857                         self._CurSection[2]\r
858             ]\r
859             if ScopeMacro:\r
860                 MacroDict.update(ScopeMacro)\r
861 \r
862         MacroDict.update(GlobalData.gGlobalDefines)\r
863         MacroDict.update(GlobalData.gCommandLineDefines)\r
864         for Item in GlobalData.BuildOptionPcd:\r
865             if isinstance(Item, tuple):\r
866                 continue\r
867             PcdName, TmpValue = Item.split(TAB_EQUAL_SPLIT)\r
868             TmpValue = BuildOptionValue(TmpValue, {})\r
869             MacroDict[PcdName.strip()] = TmpValue\r
870         # Highest priority\r
871 \r
872         return MacroDict\r
873 \r
874     def _EvaluateConditional(self, Expression, Line, Op = None, Value = None):\r
875         MacroPcdDict = self._CollectMacroPcd()\r
876         if Op == 'eval':\r
877             try:\r
878                 if Value:\r
879                     return ValueExpression(Expression, MacroPcdDict)(True)\r
880                 else:\r
881                     return ValueExpression(Expression, MacroPcdDict)()\r
882             except WrnExpression as Excpt:\r
883                 #\r
884                 # Catch expression evaluation warning here. We need to report\r
885                 # the precise number of line and return the evaluation result\r
886                 #\r
887                 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),\r
888                                 File=self.FileName, ExtraData=self._CurrentLine(),\r
889                                 Line=Line)\r
890                 return Excpt.result\r
891             except Exception as Excpt:\r
892                 if hasattr(Excpt, 'Pcd'):\r
893                     if Excpt.Pcd in GlobalData.gPlatformOtherPcds:\r
894                         Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]\r
895                         raise Warning("Cannot use this PCD (%s) in an expression as"\r
896                                       " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"\r
897                                       " of the DSC file (%s), and it is currently defined in this section:"\r
898                                       " %s, line #: %d." % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE'], Info[0], Info[1]),\r
899                                       self.FileName, Line)\r
900                     else:\r
901                         raise Warning("PCD (%s) is not defined in DSC file (%s)" % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE']),\r
902                                       self.FileName, Line)\r
903                 else:\r
904                     raise Warning(str(Excpt), self.FileName, Line)\r
905         else:\r
906             if Expression.startswith('$(') and Expression[-1] == ')':\r
907                 Expression = Expression[2:-1]\r
908             return Expression in MacroPcdDict\r
909 \r
910     ## _IsToken() method\r
911     #\r
912     #   Check whether input string is found from current char position along\r
913     #   If found, the string value is put into self._Token\r
914     #\r
915     #   @param  self        The object pointer\r
916     #   @param  String      The string to search\r
917     #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive\r
918     #   @retval True        Successfully find string, file buffer pointer moved forward\r
919     #   @retval False       Not able to find string, file buffer pointer not changed\r
920     #\r
921     def _IsToken(self, String, IgnoreCase = False):\r
922         self._SkipWhiteSpace()\r
923 \r
924         # Only consider the same line, no multi-line token allowed\r
925         StartPos = self.CurrentOffsetWithinLine\r
926         index = -1\r
927         if IgnoreCase:\r
928             index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(String.upper())\r
929         else:\r
930             index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(String)\r
931         if index == 0:\r
932             self.CurrentOffsetWithinLine += len(String)\r
933             self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]\r
934             return True\r
935         return False\r
936 \r
937     ## _IsKeyword() method\r
938     #\r
939     #   Check whether input keyword is found from current char position along, whole word only!\r
940     #   If found, the string value is put into self._Token\r
941     #\r
942     #   @param  self        The object pointer\r
943     #   @param  Keyword     The string to search\r
944     #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive\r
945     #   @retval True        Successfully find string, file buffer pointer moved forward\r
946     #   @retval False       Not able to find string, file buffer pointer not changed\r
947     #\r
948     def _IsKeyword(self, KeyWord, IgnoreCase = False):\r
949         self._SkipWhiteSpace()\r
950 \r
951         # Only consider the same line, no multi-line token allowed\r
952         StartPos = self.CurrentOffsetWithinLine\r
953         index = -1\r
954         if IgnoreCase:\r
955             index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(KeyWord.upper())\r
956         else:\r
957             index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(KeyWord)\r
958         if index == 0:\r
959             followingChar = self._CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)]\r
960             if not str(followingChar).isspace() and followingChar not in SEPARATORS:\r
961                 return False\r
962             self.CurrentOffsetWithinLine += len(KeyWord)\r
963             self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]\r
964             return True\r
965         return False\r
966 \r
967     def _GetExpression(self):\r
968         Line = self.Profile.FileLinesList[self.CurrentLineNumber - 1]\r
969         Index = len(Line) - 1\r
970         while Line[Index] in CR_LB_SET:\r
971             Index -= 1\r
972         ExpressionString = self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:Index+1]\r
973         self.CurrentOffsetWithinLine += len(ExpressionString)\r
974         ExpressionString = ExpressionString.strip()\r
975         return ExpressionString\r
976 \r
977     ## _GetNextWord() method\r
978     #\r
979     #   Get next C name from file lines\r
980     #   If found, the string value is put into self._Token\r
981     #\r
982     #   @param  self        The object pointer\r
983     #   @retval True        Successfully find a C name string, file buffer pointer moved forward\r
984     #   @retval False       Not able to find a C name string, file buffer pointer not changed\r
985     #\r
986     def _GetNextWord(self):\r
987         self._SkipWhiteSpace()\r
988         if self._EndOfFile():\r
989             return False\r
990 \r
991         TempChar = self._CurrentChar()\r
992         StartPos = self.CurrentOffsetWithinLine\r
993         if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_':\r
994             self._GetOneChar()\r
995             while not self._EndOfLine():\r
996                 TempChar = self._CurrentChar()\r
997                 if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \\r
998                 or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-':\r
999                     self._GetOneChar()\r
1000 \r
1001                 else:\r
1002                     break\r
1003 \r
1004             self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]\r
1005             return True\r
1006 \r
1007         return False\r
1008 \r
1009     def _GetNextPcdWord(self):\r
1010         self._SkipWhiteSpace()\r
1011         if self._EndOfFile():\r
1012             return False\r
1013 \r
1014         TempChar = self._CurrentChar()\r
1015         StartPos = self.CurrentOffsetWithinLine\r
1016         if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_' or TempChar == TAB_SECTION_START or TempChar == TAB_SECTION_END:\r
1017             self._GetOneChar()\r
1018             while not self._EndOfLine():\r
1019                 TempChar = self._CurrentChar()\r
1020                 if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \\r
1021                 or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-' or TempChar == TAB_SECTION_START or TempChar == TAB_SECTION_END:\r
1022                     self._GetOneChar()\r
1023 \r
1024                 else:\r
1025                     break\r
1026 \r
1027             self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]\r
1028             return True\r
1029 \r
1030         return False\r
1031 \r
1032     ## _GetNextToken() method\r
1033     #\r
1034     #   Get next token unit before a separator\r
1035     #   If found, the string value is put into self._Token\r
1036     #\r
1037     #   @param  self        The object pointer\r
1038     #   @retval True        Successfully find a token unit, file buffer pointer moved forward\r
1039     #   @retval False       Not able to find a token unit, file buffer pointer not changed\r
1040     #\r
1041     def _GetNextToken(self):\r
1042         # Skip leading spaces, if exist.\r
1043         self._SkipWhiteSpace()\r
1044         if self._EndOfFile():\r
1045             return False\r
1046         # Record the token start position, the position of the first non-space char.\r
1047         StartPos = self.CurrentOffsetWithinLine\r
1048         StartLine = self.CurrentLineNumber\r
1049         while StartLine == self.CurrentLineNumber:\r
1050             TempChar = self._CurrentChar()\r
1051             # Try to find the end char that is not a space and not in separator tuple.\r
1052             # That is, when we got a space or any char in the tuple, we got the end of token.\r
1053             if not str(TempChar).isspace() and TempChar not in SEPARATORS:\r
1054                 self._GetOneChar()\r
1055             # if we happen to meet a separator as the first char, we must proceed to get it.\r
1056             # That is, we get a token that is a separator char. normally it is the boundary of other tokens.\r
1057             elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPARATORS:\r
1058                 self._GetOneChar()\r
1059                 break\r
1060             else:\r
1061                 break\r
1062 #        else:\r
1063 #            return False\r
1064 \r
1065         EndPos = self.CurrentOffsetWithinLine\r
1066         if self.CurrentLineNumber != StartLine:\r
1067             EndPos = len(self.Profile.FileLinesList[StartLine-1])\r
1068         self._Token = self.Profile.FileLinesList[StartLine-1][StartPos: EndPos]\r
1069         if self._Token.lower() in {TAB_IF, TAB_END_IF, TAB_ELSE_IF, TAB_ELSE, TAB_IF_DEF, TAB_IF_N_DEF, TAB_ERROR, TAB_INCLUDE}:\r
1070             self._Token = self._Token.lower()\r
1071         if StartPos != self.CurrentOffsetWithinLine:\r
1072             return True\r
1073         else:\r
1074             return False\r
1075 \r
1076     ## _GetNextGuid() method\r
1077     #\r
1078     #   Get next token unit before a separator\r
1079     #   If found, the GUID string is put into self._Token\r
1080     #\r
1081     #   @param  self        The object pointer\r
1082     #   @retval True        Successfully find a registry format GUID, file buffer pointer moved forward\r
1083     #   @retval False       Not able to find a registry format GUID, file buffer pointer not changed\r
1084     #\r
1085     def _GetNextGuid(self):\r
1086         if not self._GetNextToken():\r
1087             return False\r
1088         if GlobalData.gGuidPattern.match(self._Token) is not None:\r
1089             return True\r
1090         else:\r
1091             self._UndoToken()\r
1092             return False\r
1093 \r
1094     @staticmethod\r
1095     def _Verify(Name, Value, Scope):\r
1096         # value verification only applies to numeric values.\r
1097         if Scope not in TAB_PCD_NUMERIC_TYPES:\r
1098             return\r
1099 \r
1100         ValueNumber = 0\r
1101         try:\r
1102             ValueNumber = int(Value, 0)\r
1103         except:\r
1104             EdkLogger.error("FdfParser", FORMAT_INVALID, "The value is not valid dec or hex number for %s." % Name)\r
1105         if ValueNumber < 0:\r
1106             EdkLogger.error("FdfParser", FORMAT_INVALID, "The value can't be set to negative value for %s." % Name)\r
1107         if ValueNumber > MAX_VAL_TYPE[Scope]:\r
1108             EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)\r
1109         return True\r
1110 \r
1111     ## _UndoToken() method\r
1112     #\r
1113     #   Go back one token unit in file buffer\r
1114     #\r
1115     #   @param  self        The object pointer\r
1116     #\r
1117     def _UndoToken(self):\r
1118         self._UndoOneChar()\r
1119         while self._CurrentChar().isspace():\r
1120             if not self._UndoOneChar():\r
1121                 self._GetOneChar()\r
1122                 return\r
1123 \r
1124 \r
1125         StartPos = self.CurrentOffsetWithinLine\r
1126         CurrentLine = self.CurrentLineNumber\r
1127         while CurrentLine == self.CurrentLineNumber:\r
1128 \r
1129             TempChar = self._CurrentChar()\r
1130             # Try to find the end char that is not a space and not in separator tuple.\r
1131             # That is, when we got a space or any char in the tuple, we got the end of token.\r
1132             if not str(TempChar).isspace() and not TempChar in SEPARATORS:\r
1133                 if not self._UndoOneChar():\r
1134                     return\r
1135             # if we happen to meet a separator as the first char, we must proceed to get it.\r
1136             # That is, we get a token that is a separator char. normally it is the boundary of other tokens.\r
1137             elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPARATORS:\r
1138                 return\r
1139             else:\r
1140                 break\r
1141 \r
1142         self._GetOneChar()\r
1143 \r
1144     ## _GetNextHexNumber() method\r
1145     #\r
1146     #   Get next HEX data before a separator\r
1147     #   If found, the HEX data is put into self._Token\r
1148     #\r
1149     #   @param  self        The object pointer\r
1150     #   @retval True        Successfully find a HEX data, file buffer pointer moved forward\r
1151     #   @retval False       Not able to find a HEX data, file buffer pointer not changed\r
1152     #\r
1153     def _GetNextHexNumber(self):\r
1154         if not self._GetNextToken():\r
1155             return False\r
1156         if GlobalData.gHexPatternAll.match(self._Token):\r
1157             return True\r
1158         else:\r
1159             self._UndoToken()\r
1160             return False\r
1161 \r
1162     ## _GetNextDecimalNumber() method\r
1163     #\r
1164     #   Get next decimal data before a separator\r
1165     #   If found, the decimal data is put into self._Token\r
1166     #\r
1167     #   @param  self        The object pointer\r
1168     #   @retval True        Successfully find a decimal data, file buffer pointer moved forward\r
1169     #   @retval False       Not able to find a decimal data, file buffer pointer not changed\r
1170     #\r
1171     def _GetNextDecimalNumber(self):\r
1172         if not self._GetNextToken():\r
1173             return False\r
1174         if self._Token.isdigit():\r
1175             return True\r
1176         else:\r
1177             self._UndoToken()\r
1178             return False\r
1179 \r
1180     def _GetNextPcdSettings(self):\r
1181         if not self._GetNextWord():\r
1182             raise Warning.Expected("<PcdTokenSpaceCName>", self.FileName, self.CurrentLineNumber)\r
1183         pcdTokenSpaceCName = self._Token\r
1184 \r
1185         if not self._IsToken(TAB_SPLIT):\r
1186             raise Warning.Expected(".", self.FileName, self.CurrentLineNumber)\r
1187 \r
1188         if not self._GetNextWord():\r
1189             raise Warning.Expected("<PcdCName>", self.FileName, self.CurrentLineNumber)\r
1190         pcdCName = self._Token\r
1191 \r
1192         Fields = []\r
1193         while self._IsToken(TAB_SPLIT):\r
1194             if not self._GetNextPcdWord():\r
1195                 raise Warning.Expected("Pcd Fields", self.FileName, self.CurrentLineNumber)\r
1196             Fields.append(self._Token)\r
1197 \r
1198         return (pcdCName, pcdTokenSpaceCName,TAB_SPLIT.join(Fields))\r
1199 \r
1200     ## _GetStringData() method\r
1201     #\r
1202     #   Get string contents quoted in ""\r
1203     #   If found, the decimal data is put into self._Token\r
1204     #\r
1205     #   @param  self        The object pointer\r
1206     #   @retval True        Successfully find a string data, file buffer pointer moved forward\r
1207     #   @retval False       Not able to find a string data, file buffer pointer not changed\r
1208     #\r
1209     def _GetStringData(self):\r
1210         QuoteToUse = None\r
1211         if self._Token.startswith(T_CHAR_DOUBLE_QUOTE) or self._Token.startswith("L\""):\r
1212             QuoteToUse = T_CHAR_DOUBLE_QUOTE\r
1213         elif self._Token.startswith(T_CHAR_SINGLE_QUOTE) or self._Token.startswith("L\'"):\r
1214             QuoteToUse = T_CHAR_SINGLE_QUOTE\r
1215         else:\r
1216             return False\r
1217 \r
1218         self._UndoToken()\r
1219         self._SkipToToken(QuoteToUse)\r
1220         currentLineNumber = self.CurrentLineNumber\r
1221 \r
1222         if not self._SkipToToken(QuoteToUse):\r
1223             raise Warning(QuoteToUse, self.FileName, self.CurrentLineNumber)\r
1224         if currentLineNumber != self.CurrentLineNumber:\r
1225             raise Warning(QuoteToUse, self.FileName, self.CurrentLineNumber)\r
1226         self._Token = self._SkippedChars.rstrip(QuoteToUse)\r
1227         return True\r
1228 \r
1229     ## _SkipToToken() method\r
1230     #\r
1231     #   Search forward in file buffer for the string\r
1232     #   The skipped chars are put into self._SkippedChars\r
1233     #\r
1234     #   @param  self        The object pointer\r
1235     #   @param  String      The string to search\r
1236     #   @param  IgnoreCase  Indicate case sensitive/non-sensitive search, default is case sensitive\r
1237     #   @retval True        Successfully find the string, file buffer pointer moved forward\r
1238     #   @retval False       Not able to find the string, file buffer pointer not changed\r
1239     #\r
1240     def _SkipToToken(self, String, IgnoreCase = False):\r
1241         StartPos = self.GetFileBufferPos()\r
1242 \r
1243         self._SkippedChars = ""\r
1244         while not self._EndOfFile():\r
1245             index = -1\r
1246             if IgnoreCase:\r
1247                 index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(String.upper())\r
1248             else:\r
1249                 index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(String)\r
1250             if index == 0:\r
1251                 self.CurrentOffsetWithinLine += len(String)\r
1252                 self._SkippedChars += String\r
1253                 return True\r
1254             self._SkippedChars += str(self._CurrentChar())\r
1255             self._GetOneChar()\r
1256 \r
1257         self.SetFileBufferPos(StartPos)\r
1258         self._SkippedChars = ""\r
1259         return False\r
1260 \r
1261     ## GetFileBufferPos() method\r
1262     #\r
1263     #   Return the tuple of current line and offset within the line\r
1264     #\r
1265     #   @param  self        The object pointer\r
1266     #   @retval Tuple       Line number and offset pair\r
1267     #\r
1268     def GetFileBufferPos(self):\r
1269         return (self.CurrentLineNumber, self.CurrentOffsetWithinLine)\r
1270 \r
1271     ## SetFileBufferPos() method\r
1272     #\r
1273     #   Restore the file buffer position\r
1274     #\r
1275     #   @param  self        The object pointer\r
1276     #   @param  Pos         The new file buffer position\r
1277     #\r
1278     def SetFileBufferPos(self, Pos):\r
1279         (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos\r
1280 \r
1281     ## Preprocess() method\r
1282     #\r
1283     #   Preprocess comment, conditional directive, include directive, replace macro.\r
1284     #   Exception will be raised if syntax error found\r
1285     #\r
1286     #   @param  self        The object pointer\r
1287     #\r
1288     def Preprocess(self):\r
1289         self._StringToList()\r
1290         self.PreprocessFile()\r
1291         self.PreprocessIncludeFile()\r
1292         self._StringToList()\r
1293         self.PreprocessFile()\r
1294         self.PreprocessConditionalStatement()\r
1295         self._StringToList()\r
1296         for Pos in self._WipeOffArea:\r
1297             self._ReplaceFragment(Pos[0], Pos[1])\r
1298         self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]\r
1299 \r
1300         while self._GetDefines():\r
1301             pass\r
1302 \r
1303     ## ParseFile() method\r
1304     #\r
1305     #   Parse the file profile buffer to extract fd, fv ... information\r
1306     #   Exception will be raised if syntax error found\r
1307     #\r
1308     #   @param  self        The object pointer\r
1309     #\r
1310     def ParseFile(self):\r
1311         try:\r
1312             self.Preprocess()\r
1313             self._GetError()\r
1314             #\r
1315             # Keep processing sections of the FDF until no new sections or a syntax error is found\r
1316             #\r
1317             while self._GetFd() or self._GetFv() or self._GetFmp() or self._GetCapsule() or self._GetRule() or self._GetOptionRom():\r
1318                 pass\r
1319 \r
1320         except Warning as X:\r
1321             self._UndoToken()\r
1322             #'\n\tGot Token: \"%s\" from File %s\n' % (self._Token, FileLineTuple[0]) + \\r
1323             # At this point, the closest parent would be the included file itself\r
1324             Profile = GetParentAtLine(X.OriginalLineNumber)\r
1325             if Profile is not None:\r
1326                 X.Message += ' near line %d, column %d: %s' \\r
1327                 % (X.LineNumber, 0, Profile.FileLinesList[X.LineNumber-1])\r
1328             else:\r
1329                 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1330                 X.Message += ' near line %d, column %d: %s' \\r
1331                 % (FileLineTuple[1], self.CurrentOffsetWithinLine + 1, self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:].rstrip(TAB_LINE_BREAK).rstrip(T_CHAR_CR))\r
1332             raise\r
1333 \r
1334     ## SectionParser() method\r
1335     #\r
1336     #   Parse the file section info\r
1337     #   Exception will be raised if syntax error found\r
1338     #\r
1339     #   @param  self          The object pointer\r
1340     #   @param  section       The section string\r
1341 \r
1342     def SectionParser(self, section):\r
1343         S = section.upper()\r
1344         if not S.startswith("[DEFINES") and not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \\r
1345              and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM.") and not S.startswith('[FMPPAYLOAD.'):\r
1346             raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [Rule.], [OptionRom.], [FMPPAYLOAD.])", self.FileName, self.CurrentLineNumber)\r
1347 \r
1348     ## _GetDefines() method\r
1349     #\r
1350     #   Get Defines section contents and store its data into AllMacrosList\r
1351     #\r
1352     #   @param  self        The object pointer\r
1353     #   @retval True        Successfully find a Defines\r
1354     #   @retval False       Not able to find a Defines\r
1355     #\r
1356     def _GetDefines(self):\r
1357         if not self._GetNextToken():\r
1358             return False\r
1359 \r
1360         S = self._Token.upper()\r
1361         if S.startswith(TAB_SECTION_START) and not S.startswith("[DEFINES"):\r
1362             self.SectionParser(S)\r
1363             self._UndoToken()\r
1364             return False\r
1365 \r
1366         self._UndoToken()\r
1367         if not self._IsToken("[DEFINES", True):\r
1368             FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1369             #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \\r
1370             #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)\r
1371             raise Warning.Expected("[DEFINES", self.FileName, self.CurrentLineNumber)\r
1372 \r
1373         if not self._IsToken(TAB_SECTION_END):\r
1374             raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)\r
1375 \r
1376         while self._GetNextWord():\r
1377             # handle the SET statement\r
1378             if self._Token == 'SET':\r
1379                 self._UndoToken()\r
1380                 self._GetSetStatement(None)\r
1381                 continue\r
1382 \r
1383             Macro = self._Token\r
1384 \r
1385             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1386                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1387             if not self._GetNextToken() or self._Token.startswith(TAB_SECTION_START):\r
1388                 raise Warning.Expected("MACRO value", self.FileName, self.CurrentLineNumber)\r
1389             Value = self._Token\r
1390 \r
1391         return False\r
1392 \r
1393     ##_GetError() method\r
1394     def _GetError(self):\r
1395         #save the Current information\r
1396         CurrentLine = self.CurrentLineNumber\r
1397         CurrentOffset = self.CurrentOffsetWithinLine\r
1398         while self._GetNextToken():\r
1399             if self._Token == TAB_ERROR:\r
1400                 EdkLogger.error('FdfParser', ERROR_STATEMENT, self._CurrentLine().replace(TAB_ERROR, '', 1), File=self.FileName, Line=self.CurrentLineNumber)\r
1401         self.CurrentLineNumber = CurrentLine\r
1402         self.CurrentOffsetWithinLine = CurrentOffset\r
1403 \r
1404     ## _GetFd() method\r
1405     #\r
1406     #   Get FD section contents and store its data into FD dictionary of self.Profile\r
1407     #\r
1408     #   @param  self        The object pointer\r
1409     #   @retval True        Successfully find a FD\r
1410     #   @retval False       Not able to find a FD\r
1411     #\r
1412     def _GetFd(self):\r
1413         if not self._GetNextToken():\r
1414             return False\r
1415 \r
1416         S = self._Token.upper()\r
1417         if S.startswith(TAB_SECTION_START) and not S.startswith("[FD."):\r
1418             if not S.startswith("[FV.") and not S.startswith('[FMPPAYLOAD.') and not S.startswith("[CAPSULE.") \\r
1419                 and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):\r
1420                 raise Warning("Unknown section", self.FileName, self.CurrentLineNumber)\r
1421             self._UndoToken()\r
1422             return False\r
1423 \r
1424         self._UndoToken()\r
1425         if not self._IsToken("[FD.", True):\r
1426             FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1427             #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \\r
1428             #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)\r
1429             raise Warning.Expected("[FD.]", self.FileName, self.CurrentLineNumber)\r
1430 \r
1431         FdName = self._GetUiName()\r
1432         if FdName == "":\r
1433             if len (self.Profile.FdDict) == 0:\r
1434                 FdName = GenFdsGlobalVariable.PlatformName\r
1435                 if FdName == "" and GlobalData.gActivePlatform:\r
1436                     FdName = GlobalData.gActivePlatform.PlatformName\r
1437                 self.Profile.FdNameNotSet = True\r
1438             else:\r
1439                 raise Warning.Expected("FdName in [FD.] section", self.FileName, self.CurrentLineNumber)\r
1440         self.CurrentFdName = FdName.upper()\r
1441 \r
1442         if self.CurrentFdName in self.Profile.FdDict:\r
1443             raise Warning("Unexpected the same FD name", self.FileName, self.CurrentLineNumber)\r
1444 \r
1445         if not self._IsToken(TAB_SECTION_END):\r
1446             raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)\r
1447 \r
1448         FdObj = FD()\r
1449         FdObj.FdUiName = self.CurrentFdName\r
1450         self.Profile.FdDict[self.CurrentFdName] = FdObj\r
1451 \r
1452         if len (self.Profile.FdDict) > 1 and self.Profile.FdNameNotSet:\r
1453             raise Warning.Expected("all FDs have their name", self.FileName, self.CurrentLineNumber)\r
1454 \r
1455         Status = self._GetCreateFile(FdObj)\r
1456         if not Status:\r
1457             raise Warning("FD name error", self.FileName, self.CurrentLineNumber)\r
1458 \r
1459         while self._GetTokenStatements(FdObj):\r
1460             pass\r
1461         for Attr in ("BaseAddress", "Size", "ErasePolarity"):\r
1462             if getattr(FdObj, Attr) is None:\r
1463                 self._GetNextToken()\r
1464                 raise Warning("Keyword %s missing" % Attr, self.FileName, self.CurrentLineNumber)\r
1465 \r
1466         if not FdObj.BlockSizeList:\r
1467             FdObj.BlockSizeList.append((1, FdObj.Size, None))\r
1468 \r
1469         self._GetDefineStatements(FdObj)\r
1470 \r
1471         self._GetSetStatements(FdObj)\r
1472 \r
1473         if not self._GetRegionLayout(FdObj):\r
1474             raise Warning.Expected("region layout", self.FileName, self.CurrentLineNumber)\r
1475 \r
1476         while self._GetRegionLayout(FdObj):\r
1477             pass\r
1478         return True\r
1479 \r
1480     ## _GetUiName() method\r
1481     #\r
1482     #   Return the UI name of a section\r
1483     #\r
1484     #   @param  self        The object pointer\r
1485     #   @retval FdName      UI name\r
1486     #\r
1487     def _GetUiName(self):\r
1488         Name = ""\r
1489         if self._GetNextWord():\r
1490             Name = self._Token\r
1491 \r
1492         return Name\r
1493 \r
1494     ## _GetCreateFile() method\r
1495     #\r
1496     #   Return the output file name of object\r
1497     #\r
1498     #   @param  self        The object pointer\r
1499     #   @param  Obj         object whose data will be stored in file\r
1500     #   @retval FdName      UI name\r
1501     #\r
1502     def _GetCreateFile(self, Obj):\r
1503         if self._IsKeyword("CREATE_FILE"):\r
1504             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1505                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1506 \r
1507             if not self._GetNextToken():\r
1508                 raise Warning.Expected("file name", self.FileName, self.CurrentLineNumber)\r
1509 \r
1510             FileName = self._Token\r
1511             Obj.CreateFileName = FileName\r
1512 \r
1513         return True\r
1514 \r
1515     def SetPcdLocalation(self,pcdpair):\r
1516         self.Profile.PcdLocalDict[pcdpair] = (self.Profile.FileName,self.CurrentLineNumber)\r
1517 \r
1518     ## _GetTokenStatements() method\r
1519     #\r
1520     #   Get token statements\r
1521     #\r
1522     #   @param  self        The object pointer\r
1523     #   @param  Obj         for whom token statement is got\r
1524     #\r
1525     def _GetTokenStatements(self, Obj):\r
1526         if self._IsKeyword("BaseAddress"):\r
1527             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1528                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1529 \r
1530             if not self._GetNextHexNumber():\r
1531                 raise Warning.Expected("Hex base address", self.FileName, self.CurrentLineNumber)\r
1532 \r
1533             Obj.BaseAddress = self._Token\r
1534 \r
1535             if self._IsToken(TAB_VALUE_SPLIT):\r
1536                 pcdPair = self._GetNextPcdSettings()\r
1537                 Obj.BaseAddressPcd = pcdPair\r
1538                 self.Profile.PcdDict[pcdPair] = Obj.BaseAddress\r
1539                 self.SetPcdLocalation(pcdPair)\r
1540                 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1541                 self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple\r
1542             return True\r
1543 \r
1544         if self._IsKeyword("Size"):\r
1545             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1546                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1547 \r
1548             if not self._GetNextHexNumber():\r
1549                 raise Warning.Expected("Hex size", self.FileName, self.CurrentLineNumber)\r
1550 \r
1551             Size = self._Token\r
1552             if self._IsToken(TAB_VALUE_SPLIT):\r
1553                 pcdPair = self._GetNextPcdSettings()\r
1554                 Obj.SizePcd = pcdPair\r
1555                 self.Profile.PcdDict[pcdPair] = Size\r
1556                 self.SetPcdLocalation(pcdPair)\r
1557                 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1558                 self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple\r
1559             Obj.Size = int(Size, 0)\r
1560             return True\r
1561 \r
1562         if self._IsKeyword("ErasePolarity"):\r
1563             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1564                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1565 \r
1566             if not self._GetNextToken():\r
1567                 raise Warning.Expected("Erase Polarity", self.FileName, self.CurrentLineNumber)\r
1568 \r
1569             if not self._Token in {"1", "0"}:\r
1570                 raise Warning.Expected("1 or 0 Erase Polarity", self.FileName, self.CurrentLineNumber)\r
1571 \r
1572             Obj.ErasePolarity = self._Token\r
1573             return True\r
1574 \r
1575         return self._GetBlockStatements(Obj)\r
1576 \r
1577     ## _GetAddressStatements() method\r
1578     #\r
1579     #   Get address statements\r
1580     #\r
1581     #   @param  self        The object pointer\r
1582     #   @param  Obj         for whom address statement is got\r
1583     #   @retval True        Successfully find\r
1584     #   @retval False       Not able to find\r
1585     #\r
1586     def _GetAddressStatements(self, Obj):\r
1587         if self._IsKeyword("BsBaseAddress"):\r
1588             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1589                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1590 \r
1591             if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():\r
1592                 raise Warning.Expected("address", self.FileName, self.CurrentLineNumber)\r
1593 \r
1594             BsAddress = int(self._Token, 0)\r
1595             Obj.BsBaseAddress = BsAddress\r
1596 \r
1597         if self._IsKeyword("RtBaseAddress"):\r
1598             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1599                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1600 \r
1601             if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():\r
1602                 raise Warning.Expected("address", self.FileName, self.CurrentLineNumber)\r
1603 \r
1604             RtAddress = int(self._Token, 0)\r
1605             Obj.RtBaseAddress = RtAddress\r
1606 \r
1607     ## _GetBlockStatements() method\r
1608     #\r
1609     #   Get block statements\r
1610     #\r
1611     #   @param  self        The object pointer\r
1612     #   @param  Obj         for whom block statement is got\r
1613     #\r
1614     def _GetBlockStatements(self, Obj):\r
1615         IsBlock = False\r
1616         while self._GetBlockStatement(Obj):\r
1617             IsBlock = True\r
1618 \r
1619             Item = Obj.BlockSizeList[-1]\r
1620             if Item[0] is None or Item[1] is None:\r
1621                 raise Warning.Expected("block statement", self.FileName, self.CurrentLineNumber)\r
1622         return IsBlock\r
1623 \r
1624     ## _GetBlockStatement() method\r
1625     #\r
1626     #   Get block statement\r
1627     #\r
1628     #   @param  self        The object pointer\r
1629     #   @param  Obj         for whom block statement is got\r
1630     #   @retval True        Successfully find\r
1631     #   @retval False       Not able to find\r
1632     #\r
1633     def _GetBlockStatement(self, Obj):\r
1634         if not self._IsKeyword("BlockSize"):\r
1635             return False\r
1636 \r
1637         if not self._IsToken(TAB_EQUAL_SPLIT):\r
1638             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1639 \r
1640         if not self._GetNextHexNumber() and not self._GetNextDecimalNumber():\r
1641             raise Warning.Expected("Hex or Integer block size", self.FileName, self.CurrentLineNumber)\r
1642 \r
1643         BlockSize = self._Token\r
1644         BlockSizePcd = None\r
1645         if self._IsToken(TAB_VALUE_SPLIT):\r
1646             PcdPair = self._GetNextPcdSettings()\r
1647             BlockSizePcd = PcdPair\r
1648             self.Profile.PcdDict[PcdPair] = BlockSize\r
1649             self.SetPcdLocalation(PcdPair)\r
1650             FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1651             self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple\r
1652         BlockSize = int(BlockSize, 0)\r
1653 \r
1654         BlockNumber = None\r
1655         if self._IsKeyword("NumBlocks"):\r
1656             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1657                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1658 \r
1659             if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():\r
1660                 raise Warning.Expected("block numbers", self.FileName, self.CurrentLineNumber)\r
1661 \r
1662             BlockNumber = int(self._Token, 0)\r
1663 \r
1664         Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd))\r
1665         return True\r
1666 \r
1667     ## _GetDefineStatements() method\r
1668     #\r
1669     #   Get define statements\r
1670     #\r
1671     #   @param  self        The object pointer\r
1672     #   @param  Obj         for whom define statement is got\r
1673     #   @retval True        Successfully find\r
1674     #   @retval False       Not able to find\r
1675     #\r
1676     def _GetDefineStatements(self, Obj):\r
1677         while self._GetDefineStatement(Obj):\r
1678             pass\r
1679 \r
1680     ## _GetDefineStatement() method\r
1681     #\r
1682     #   Get define statement\r
1683     #\r
1684     #   @param  self        The object pointer\r
1685     #   @param  Obj         for whom define statement is got\r
1686     #   @retval True        Successfully find\r
1687     #   @retval False       Not able to find\r
1688     #\r
1689     def _GetDefineStatement(self, Obj):\r
1690         if self._IsKeyword(TAB_DEFINE):\r
1691             self._GetNextToken()\r
1692             Macro = self._Token\r
1693             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1694                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1695 \r
1696             if not self._GetNextToken():\r
1697                 raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)\r
1698 \r
1699             Value = self._Token\r
1700             Macro = '$(' + Macro + ')'\r
1701             Obj.DefineVarDict[Macro] = Value\r
1702             return True\r
1703 \r
1704         return False\r
1705 \r
1706     ## _GetSetStatements() method\r
1707     #\r
1708     #   Get set statements\r
1709     #\r
1710     #   @param  self        The object pointer\r
1711     #   @param  Obj         for whom set statement is got\r
1712     #   @retval True        Successfully find\r
1713     #   @retval False       Not able to find\r
1714     #\r
1715     def _GetSetStatements(self, Obj):\r
1716         while self._GetSetStatement(Obj):\r
1717             pass\r
1718 \r
1719     ## _GetSetStatement() method\r
1720     #\r
1721     #   Get set statement\r
1722     #\r
1723     #   @param  self        The object pointer\r
1724     #   @param  Obj         for whom set statement is got\r
1725     #   @retval True        Successfully find\r
1726     #   @retval False       Not able to find\r
1727     #\r
1728     def _GetSetStatement(self, Obj):\r
1729         if self._IsKeyword("SET"):\r
1730             PcdPair = self._GetNextPcdSettings()\r
1731 \r
1732             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1733                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1734 \r
1735             Value = self._GetExpression()\r
1736             Value = self._EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)\r
1737 \r
1738             if Obj:\r
1739                 Obj.SetVarDict[PcdPair] = Value\r
1740             self.Profile.PcdDict[PcdPair] = Value\r
1741             self.SetPcdLocalation(PcdPair)\r
1742             FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1743             self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple\r
1744             return True\r
1745 \r
1746         return False\r
1747 \r
1748     ## _CalcRegionExpr(self)\r
1749     #\r
1750     #   Calculate expression for offset or size of a region\r
1751     #\r
1752     #   @return: None if invalid expression\r
1753     #            Calculated number if successfully\r
1754     #\r
1755     def _CalcRegionExpr(self):\r
1756         StartPos = self.GetFileBufferPos()\r
1757         Expr = ''\r
1758         PairCount = 0\r
1759         while not self._EndOfFile():\r
1760             CurCh = self._CurrentChar()\r
1761             if CurCh == '(':\r
1762                 PairCount += 1\r
1763             elif CurCh == ')':\r
1764                 PairCount -= 1\r
1765 \r
1766             if CurCh in '|\r\n' and PairCount == 0:\r
1767                 break\r
1768             Expr += CurCh\r
1769             self._GetOneChar()\r
1770         try:\r
1771             return int(\r
1772                 ValueExpression(Expr,\r
1773                                 self._CollectMacroPcd()\r
1774                                 )(True), 0)\r
1775         except Exception:\r
1776             self.SetFileBufferPos(StartPos)\r
1777             return None\r
1778 \r
1779     ## _GetRegionLayout() method\r
1780     #\r
1781     #   Get region layout for FD\r
1782     #\r
1783     #   @param  self        The object pointer\r
1784     #   @param  theFd       for whom region is got\r
1785     #   @retval True        Successfully find\r
1786     #   @retval False       Not able to find\r
1787     #\r
1788     def _GetRegionLayout(self, theFd):\r
1789         Offset = self._CalcRegionExpr()\r
1790         if Offset is None:\r
1791             return False\r
1792 \r
1793         RegionObj = Region()\r
1794         RegionObj.Offset = Offset\r
1795         theFd.RegionList.append(RegionObj)\r
1796 \r
1797         if not self._IsToken(TAB_VALUE_SPLIT):\r
1798             raise Warning.Expected("'|'", self.FileName, self.CurrentLineNumber)\r
1799 \r
1800         Size = self._CalcRegionExpr()\r
1801         if Size is None:\r
1802             raise Warning.Expected("Region Size", self.FileName, self.CurrentLineNumber)\r
1803         RegionObj.Size = Size\r
1804 \r
1805         if not self._GetNextWord():\r
1806             return True\r
1807 \r
1808         if not self._Token in {"SET", BINARY_FILE_TYPE_FV, "FILE", "DATA", "CAPSULE", "INF"}:\r
1809             #\r
1810             # If next token is a word which is not a valid FV type, it might be part of [PcdOffset[|PcdSize]]\r
1811             # Or it might be next region's offset described by an expression which starts with a PCD.\r
1812             #    PcdOffset[|PcdSize] or OffsetPcdExpression|Size\r
1813             #\r
1814             self._UndoToken()\r
1815             IsRegionPcd = (RegionSizeGuidPattern.match(self._CurrentLine()[self.CurrentOffsetWithinLine:]) or\r
1816                            RegionOffsetPcdPattern.match(self._CurrentLine()[self.CurrentOffsetWithinLine:]))\r
1817             if IsRegionPcd:\r
1818                 RegionObj.PcdOffset = self._GetNextPcdSettings()\r
1819                 self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + int(theFd.BaseAddress, 0))\r
1820                 self.SetPcdLocalation(RegionObj.PcdOffset)\r
1821                 self._PcdDict['%s.%s' % (RegionObj.PcdOffset[1], RegionObj.PcdOffset[0])] = "0x%x" % RegionObj.Offset\r
1822                 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1823                 self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple\r
1824                 if self._IsToken(TAB_VALUE_SPLIT):\r
1825                     RegionObj.PcdSize = self._GetNextPcdSettings()\r
1826                     self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size\r
1827                     self.SetPcdLocalation(RegionObj.PcdSize)\r
1828                     self._PcdDict['%s.%s' % (RegionObj.PcdSize[1], RegionObj.PcdSize[0])] = "0x%x" % RegionObj.Size\r
1829                     FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
1830                     self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple\r
1831 \r
1832             if not self._GetNextWord():\r
1833                 return True\r
1834 \r
1835         if self._Token == "SET":\r
1836             self._UndoToken()\r
1837             self._GetSetStatements(RegionObj)\r
1838             if not self._GetNextWord():\r
1839                 return True\r
1840 \r
1841         elif self._Token == BINARY_FILE_TYPE_FV:\r
1842             self._UndoToken()\r
1843             self._GetRegionFvType(RegionObj)\r
1844 \r
1845         elif self._Token == "CAPSULE":\r
1846             self._UndoToken()\r
1847             self._GetRegionCapType(RegionObj)\r
1848 \r
1849         elif self._Token == "FILE":\r
1850             self._UndoToken()\r
1851             self._GetRegionFileType(RegionObj)\r
1852 \r
1853         elif self._Token == "INF":\r
1854             self._UndoToken()\r
1855             RegionObj.RegionType = "INF"\r
1856             while self._IsKeyword("INF"):\r
1857                 self._UndoToken()\r
1858                 ffsInf = self._ParseInfStatement()\r
1859                 if not ffsInf:\r
1860                     break\r
1861                 RegionObj.RegionDataList.append(ffsInf)\r
1862 \r
1863         elif self._Token == "DATA":\r
1864             self._UndoToken()\r
1865             self._GetRegionDataType(RegionObj)\r
1866         else:\r
1867             self._UndoToken()\r
1868             if self._GetRegionLayout(theFd):\r
1869                 return True\r
1870             raise Warning("A valid region type was not found. "\r
1871                           "Valid types are [SET, FV, CAPSULE, FILE, DATA, INF]. This error occurred",\r
1872                           self.FileName, self.CurrentLineNumber)\r
1873 \r
1874         return True\r
1875 \r
1876     ## _GetRegionFvType() method\r
1877     #\r
1878     #   Get region fv data for region\r
1879     #\r
1880     #   @param  self        The object pointer\r
1881     #   @param  RegionObj   for whom region data is got\r
1882     #\r
1883     def _GetRegionFvType(self, RegionObj):\r
1884         if not self._IsKeyword(BINARY_FILE_TYPE_FV):\r
1885             raise Warning.Expected("'FV'", self.FileName, self.CurrentLineNumber)\r
1886 \r
1887         if not self._IsToken(TAB_EQUAL_SPLIT):\r
1888             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1889 \r
1890         if not self._GetNextToken():\r
1891             raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)\r
1892 \r
1893         RegionObj.RegionType = BINARY_FILE_TYPE_FV\r
1894         RegionObj.RegionDataList.append((self._Token).upper())\r
1895 \r
1896         while self._IsKeyword(BINARY_FILE_TYPE_FV):\r
1897 \r
1898             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1899                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1900 \r
1901             if not self._GetNextToken():\r
1902                 raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)\r
1903 \r
1904             RegionObj.RegionDataList.append((self._Token).upper())\r
1905 \r
1906     ## _GetRegionCapType() method\r
1907     #\r
1908     #   Get region capsule data for region\r
1909     #\r
1910     #   @param  self        The object pointer\r
1911     #   @param  RegionObj   for whom region data is got\r
1912     #\r
1913     def _GetRegionCapType(self, RegionObj):\r
1914         if not self._IsKeyword("CAPSULE"):\r
1915             raise Warning.Expected("'CAPSULE'", self.FileName, self.CurrentLineNumber)\r
1916 \r
1917         if not self._IsToken(TAB_EQUAL_SPLIT):\r
1918             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1919 \r
1920         if not self._GetNextToken():\r
1921             raise Warning.Expected("CAPSULE name", self.FileName, self.CurrentLineNumber)\r
1922 \r
1923         RegionObj.RegionType = "CAPSULE"\r
1924         RegionObj.RegionDataList.append(self._Token)\r
1925 \r
1926         while self._IsKeyword("CAPSULE"):\r
1927 \r
1928             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1929                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1930 \r
1931             if not self._GetNextToken():\r
1932                 raise Warning.Expected("CAPSULE name", self.FileName, self.CurrentLineNumber)\r
1933 \r
1934             RegionObj.RegionDataList.append(self._Token)\r
1935 \r
1936     ## _GetRegionFileType() method\r
1937     #\r
1938     #   Get region file data for region\r
1939     #\r
1940     #   @param  self        The object pointer\r
1941     #   @param  RegionObj   for whom region data is got\r
1942     #\r
1943     def _GetRegionFileType(self, RegionObj):\r
1944         if not self._IsKeyword("FILE"):\r
1945             raise Warning.Expected("'FILE'", self.FileName, self.CurrentLineNumber)\r
1946 \r
1947         if not self._IsToken(TAB_EQUAL_SPLIT):\r
1948             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1949 \r
1950         if not self._GetNextToken():\r
1951             raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)\r
1952 \r
1953         RegionObj.RegionType = "FILE"\r
1954         RegionObj.RegionDataList.append(self._Token)\r
1955 \r
1956         while self._IsKeyword("FILE"):\r
1957 \r
1958             if not self._IsToken(TAB_EQUAL_SPLIT):\r
1959                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1960 \r
1961             if not self._GetNextToken():\r
1962                 raise Warning.Expected("FILE name", self.FileName, self.CurrentLineNumber)\r
1963 \r
1964             RegionObj.RegionDataList.append(self._Token)\r
1965 \r
1966     ## _GetRegionDataType() method\r
1967     #\r
1968     #   Get region array data for region\r
1969     #\r
1970     #   @param  self        The object pointer\r
1971     #   @param  RegionObj   for whom region data is got\r
1972     #\r
1973     def _GetRegionDataType(self, RegionObj):\r
1974         if not self._IsKeyword("DATA"):\r
1975             raise Warning.Expected("Region Data type", self.FileName, self.CurrentLineNumber)\r
1976 \r
1977         if not self._IsToken(TAB_EQUAL_SPLIT):\r
1978             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
1979 \r
1980         if not self._IsToken("{"):\r
1981             raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
1982 \r
1983         if not self._GetNextHexNumber():\r
1984             raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)\r
1985 \r
1986         if len(self._Token) > 18:\r
1987             raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)\r
1988 \r
1989         # convert hex string value to byte hex string array\r
1990         AllString = self._Token\r
1991         AllStrLen = len (AllString)\r
1992         DataString = ""\r
1993         while AllStrLen > 4:\r
1994             DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + TAB_COMMA_SPLIT\r
1995             AllStrLen  = AllStrLen - 2\r
1996         DataString = DataString + AllString[:AllStrLen] + TAB_COMMA_SPLIT\r
1997 \r
1998         # byte value array\r
1999         if len (self._Token) <= 4:\r
2000             while self._IsToken(TAB_COMMA_SPLIT):\r
2001                 if not self._GetNextHexNumber():\r
2002                     raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)\r
2003                 if len(self._Token) > 4:\r
2004                     raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)\r
2005                 DataString += self._Token\r
2006                 DataString += TAB_COMMA_SPLIT\r
2007 \r
2008         if not self._IsToken(T_CHAR_BRACE_R):\r
2009             raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2010 \r
2011         DataString = DataString.rstrip(TAB_COMMA_SPLIT)\r
2012         RegionObj.RegionType = "DATA"\r
2013         RegionObj.RegionDataList.append(DataString)\r
2014 \r
2015         while self._IsKeyword("DATA"):\r
2016 \r
2017             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2018                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2019 \r
2020             if not self._IsToken("{"):\r
2021                 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
2022 \r
2023             if not self._GetNextHexNumber():\r
2024                 raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)\r
2025 \r
2026             if len(self._Token) > 18:\r
2027                 raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)\r
2028 \r
2029             # convert hex string value to byte hex string array\r
2030             AllString = self._Token\r
2031             AllStrLen = len (AllString)\r
2032             DataString = ""\r
2033             while AllStrLen > 4:\r
2034                 DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + TAB_COMMA_SPLIT\r
2035                 AllStrLen  = AllStrLen - 2\r
2036             DataString = DataString + AllString[:AllStrLen] + TAB_COMMA_SPLIT\r
2037 \r
2038             # byte value array\r
2039             if len (self._Token) <= 4:\r
2040                 while self._IsToken(TAB_COMMA_SPLIT):\r
2041                     if not self._GetNextHexNumber():\r
2042                         raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)\r
2043                     if len(self._Token) > 4:\r
2044                         raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)\r
2045                     DataString += self._Token\r
2046                     DataString += TAB_COMMA_SPLIT\r
2047 \r
2048             if not self._IsToken(T_CHAR_BRACE_R):\r
2049                 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2050 \r
2051             DataString = DataString.rstrip(TAB_COMMA_SPLIT)\r
2052             RegionObj.RegionDataList.append(DataString)\r
2053 \r
2054     ## _GetFv() method\r
2055     #\r
2056     #   Get FV section contents and store its data into FV dictionary of self.Profile\r
2057     #\r
2058     #   @param  self        The object pointer\r
2059     #   @retval True        Successfully find a FV\r
2060     #   @retval False       Not able to find a FV\r
2061     #\r
2062     def _GetFv(self):\r
2063         if not self._GetNextToken():\r
2064             return False\r
2065 \r
2066         S = self._Token.upper()\r
2067         if S.startswith(TAB_SECTION_START) and not S.startswith("[FV."):\r
2068             self.SectionParser(S)\r
2069             self._UndoToken()\r
2070             return False\r
2071 \r
2072         self._UndoToken()\r
2073         if not self._IsToken("[FV.", True):\r
2074             FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
2075             #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \\r
2076             #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)\r
2077             raise Warning("Unknown Keyword '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2078 \r
2079         FvName = self._GetUiName()\r
2080         self.CurrentFvName = FvName.upper()\r
2081 \r
2082         if not self._IsToken(TAB_SECTION_END):\r
2083             raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)\r
2084 \r
2085         FvObj = FV(Name=self.CurrentFvName)\r
2086         self.Profile.FvDict[self.CurrentFvName] = FvObj\r
2087 \r
2088         Status = self._GetCreateFile(FvObj)\r
2089         if not Status:\r
2090             raise Warning("FV name error", self.FileName, self.CurrentLineNumber)\r
2091 \r
2092         self._GetDefineStatements(FvObj)\r
2093 \r
2094         self._GetAddressStatements(FvObj)\r
2095 \r
2096         while True:\r
2097             self._GetSetStatements(FvObj)\r
2098 \r
2099             if not (self._GetBlockStatement(FvObj) or self._GetFvBaseAddress(FvObj) or\r
2100                 self._GetFvForceRebase(FvObj) or self._GetFvAlignment(FvObj) or\r
2101                 self._GetFvAttributes(FvObj) or self._GetFvNameGuid(FvObj) or\r
2102                 self._GetFvExtEntryStatement(FvObj) or self._GetFvNameString(FvObj)):\r
2103                 break\r
2104 \r
2105         if FvObj.FvNameString == 'TRUE' and not FvObj.FvNameGuid:\r
2106             raise Warning("FvNameString found but FvNameGuid was not found", self.FileName, self.CurrentLineNumber)\r
2107 \r
2108         self._GetAprioriSection(FvObj)\r
2109         self._GetAprioriSection(FvObj)\r
2110 \r
2111         while True:\r
2112             isInf = self._GetInfStatement(FvObj)\r
2113             isFile = self._GetFileStatement(FvObj)\r
2114             if not isInf and not isFile:\r
2115                 break\r
2116 \r
2117         return True\r
2118 \r
2119     ## _GetFvAlignment() method\r
2120     #\r
2121     #   Get alignment for FV\r
2122     #\r
2123     #   @param  self        The object pointer\r
2124     #   @param  Obj         for whom alignment is got\r
2125     #   @retval True        Successfully find a alignment statement\r
2126     #   @retval False       Not able to find a alignment statement\r
2127     #\r
2128     def _GetFvAlignment(self, Obj):\r
2129         if not self._IsKeyword("FvAlignment"):\r
2130             return False\r
2131 \r
2132         if not self._IsToken(TAB_EQUAL_SPLIT):\r
2133             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2134 \r
2135         if not self._GetNextToken():\r
2136             raise Warning.Expected("alignment value", self.FileName, self.CurrentLineNumber)\r
2137 \r
2138         if self._Token.upper() not in {"1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \\r
2139                                         "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \\r
2140                                         "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \\r
2141                                         "1G", "2G"}:\r
2142             raise Warning("Unknown alignment value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2143         Obj.FvAlignment = self._Token\r
2144         return True\r
2145 \r
2146     ## _GetFvBaseAddress() method\r
2147     #\r
2148     #   Get BaseAddress for FV\r
2149     #\r
2150     #   @param  self        The object pointer\r
2151     #   @param  Obj         for whom FvBaseAddress is got\r
2152     #   @retval True        Successfully find a FvBaseAddress statement\r
2153     #   @retval False       Not able to find a FvBaseAddress statement\r
2154     #\r
2155     def _GetFvBaseAddress(self, Obj):\r
2156         if not self._IsKeyword("FvBaseAddress"):\r
2157             return False\r
2158 \r
2159         if not self._IsToken(TAB_EQUAL_SPLIT):\r
2160             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2161 \r
2162         if not self._GetNextToken():\r
2163             raise Warning.Expected("FV base address value", self.FileName, self.CurrentLineNumber)\r
2164 \r
2165         if not BaseAddrValuePattern.match(self._Token.upper()):\r
2166             raise Warning("Unknown FV base address value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2167         Obj.FvBaseAddress = self._Token\r
2168         return True\r
2169 \r
2170     ## _GetFvForceRebase() method\r
2171     #\r
2172     #   Get FvForceRebase for FV\r
2173     #\r
2174     #   @param  self        The object pointer\r
2175     #   @param  Obj         for whom FvForceRebase is got\r
2176     #   @retval True        Successfully find a FvForceRebase statement\r
2177     #   @retval False       Not able to find a FvForceRebase statement\r
2178     #\r
2179     def _GetFvForceRebase(self, Obj):\r
2180         if not self._IsKeyword("FvForceRebase"):\r
2181             return False\r
2182 \r
2183         if not self._IsToken(TAB_EQUAL_SPLIT):\r
2184             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2185 \r
2186         if not self._GetNextToken():\r
2187             raise Warning.Expected("FvForceRebase value", self.FileName, self.CurrentLineNumber)\r
2188 \r
2189         if self._Token.upper() not in {"TRUE", "FALSE", "0", "0X0", "0X00", "1", "0X1", "0X01"}:\r
2190             raise Warning("Unknown FvForceRebase value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2191 \r
2192         if self._Token.upper() in {"TRUE", "1", "0X1", "0X01"}:\r
2193             Obj.FvForceRebase = True\r
2194         elif self._Token.upper() in {"FALSE", "0", "0X0", "0X00"}:\r
2195             Obj.FvForceRebase = False\r
2196         else:\r
2197             Obj.FvForceRebase = None\r
2198 \r
2199         return True\r
2200 \r
2201 \r
2202     ## _GetFvAttributes() method\r
2203     #\r
2204     #   Get attributes for FV\r
2205     #\r
2206     #   @param  self        The object pointer\r
2207     #   @param  Obj         for whom attribute is got\r
2208     #   @retval None\r
2209     #\r
2210     def _GetFvAttributes(self, FvObj):\r
2211         IsWordToken = False\r
2212         while self._GetNextWord():\r
2213             IsWordToken = True\r
2214             name = self._Token\r
2215             if name not in {"ERASE_POLARITY", "MEMORY_MAPPED", \\r
2216                            "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \\r
2217                            "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \\r
2218                            "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \\r
2219                            "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \\r
2220                            "WRITE_POLICY_RELIABLE", "WEAK_ALIGNMENT", "FvUsedSizeEnable"}:\r
2221                 self._UndoToken()\r
2222                 return False\r
2223 \r
2224             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2225                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2226 \r
2227             if not self._GetNextToken() or self._Token.upper() not in {"TRUE", "FALSE", "1", "0"}:\r
2228                 raise Warning.Expected("TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)\r
2229 \r
2230             FvObj.FvAttributeDict[name] = self._Token\r
2231 \r
2232         return IsWordToken\r
2233 \r
2234     ## _GetFvNameGuid() method\r
2235     #\r
2236     #   Get FV GUID for FV\r
2237     #\r
2238     #   @param  self        The object pointer\r
2239     #   @param  Obj         for whom GUID is got\r
2240     #   @retval None\r
2241     #\r
2242     def _GetFvNameGuid(self, FvObj):\r
2243         if not self._IsKeyword("FvNameGuid"):\r
2244             return False\r
2245 \r
2246         if not self._IsToken(TAB_EQUAL_SPLIT):\r
2247             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2248 \r
2249         if not self._GetNextGuid():\r
2250             raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)\r
2251 \r
2252         FvObj.FvNameGuid = self._Token\r
2253 \r
2254         return True\r
2255 \r
2256     def _GetFvNameString(self, FvObj):\r
2257         if not self._IsKeyword("FvNameString"):\r
2258             return False\r
2259 \r
2260         if not self._IsToken(TAB_EQUAL_SPLIT):\r
2261             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2262 \r
2263         if not self._GetNextToken() or self._Token.upper() not in {'TRUE', 'FALSE'}:\r
2264             raise Warning.Expected("TRUE or FALSE for FvNameString", self.FileName, self.CurrentLineNumber)\r
2265 \r
2266         FvObj.FvNameString = self._Token\r
2267 \r
2268         return True\r
2269 \r
2270     def _GetFvExtEntryStatement(self, FvObj):\r
2271         if not (self._IsKeyword("FV_EXT_ENTRY") or self._IsKeyword("FV_EXT_ENTRY_TYPE")):\r
2272             return False\r
2273 \r
2274         if not self._IsKeyword ("TYPE"):\r
2275             raise Warning.Expected("'TYPE'", self.FileName, self.CurrentLineNumber)\r
2276 \r
2277         if not self._IsToken(TAB_EQUAL_SPLIT):\r
2278             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2279 \r
2280         if not self._GetNextHexNumber() and not self._GetNextDecimalNumber():\r
2281             raise Warning.Expected("Hex FV extension entry type value At Line ", self.FileName, self.CurrentLineNumber)\r
2282 \r
2283         FvObj.FvExtEntryTypeValue.append(self._Token)\r
2284 \r
2285         if not self._IsToken("{"):\r
2286             raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
2287 \r
2288         if not self._IsKeyword("FILE") and not self._IsKeyword("DATA"):\r
2289             raise Warning.Expected("'FILE' or 'DATA'", self.FileName, self.CurrentLineNumber)\r
2290 \r
2291         FvObj.FvExtEntryType.append(self._Token)\r
2292 \r
2293         if self._Token == 'DATA':\r
2294             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2295                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2296 \r
2297             if not self._IsToken("{"):\r
2298                 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
2299 \r
2300             if not self._GetNextHexNumber():\r
2301                 raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)\r
2302 \r
2303             if len(self._Token) > 4:\r
2304                 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)\r
2305 \r
2306             DataString = self._Token\r
2307             DataString += TAB_COMMA_SPLIT\r
2308 \r
2309             while self._IsToken(TAB_COMMA_SPLIT):\r
2310                 if not self._GetNextHexNumber():\r
2311                     raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)\r
2312                 if len(self._Token) > 4:\r
2313                     raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)\r
2314                 DataString += self._Token\r
2315                 DataString += TAB_COMMA_SPLIT\r
2316 \r
2317             if not self._IsToken(T_CHAR_BRACE_R):\r
2318                 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2319 \r
2320             if not self._IsToken(T_CHAR_BRACE_R):\r
2321                 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2322 \r
2323             DataString = DataString.rstrip(TAB_COMMA_SPLIT)\r
2324             FvObj.FvExtEntryData.append(DataString)\r
2325 \r
2326         if self._Token == 'FILE':\r
2327             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2328                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2329 \r
2330             if not self._GetNextToken():\r
2331                 raise Warning.Expected("FV Extension Entry file path At Line ", self.FileName, self.CurrentLineNumber)\r
2332 \r
2333             FvObj.FvExtEntryData.append(self._Token)\r
2334 \r
2335             if not self._IsToken(T_CHAR_BRACE_R):\r
2336                 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2337 \r
2338         return True\r
2339 \r
2340     ## _GetAprioriSection() method\r
2341     #\r
2342     #   Get token statements\r
2343     #\r
2344     #   @param  self        The object pointer\r
2345     #   @param  FvObj       for whom apriori is got\r
2346     #   @retval True        Successfully find apriori statement\r
2347     #   @retval False       Not able to find apriori statement\r
2348     #\r
2349     def _GetAprioriSection(self, FvObj):\r
2350         if not self._IsKeyword("APRIORI"):\r
2351             return False\r
2352 \r
2353         if not self._IsKeyword("PEI") and not self._IsKeyword("DXE"):\r
2354             raise Warning.Expected("Apriori file type", self.FileName, self.CurrentLineNumber)\r
2355         AprType = self._Token\r
2356 \r
2357         if not self._IsToken("{"):\r
2358             raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
2359 \r
2360         AprSectionObj = AprioriSection()\r
2361         AprSectionObj.AprioriType = AprType\r
2362 \r
2363         self._GetDefineStatements(AprSectionObj)\r
2364 \r
2365         while True:\r
2366             IsInf = self._GetInfStatement(AprSectionObj)\r
2367             IsFile = self._GetFileStatement(AprSectionObj)\r
2368             if not IsInf and not IsFile:\r
2369                 break\r
2370 \r
2371         if not self._IsToken(T_CHAR_BRACE_R):\r
2372             raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2373 \r
2374         FvObj.AprioriSectionList.append(AprSectionObj)\r
2375         return True\r
2376 \r
2377     def _ParseInfStatement(self):\r
2378         if not self._IsKeyword("INF"):\r
2379             return None\r
2380 \r
2381         ffsInf = FfsInfStatement()\r
2382         self._GetInfOptions(ffsInf)\r
2383 \r
2384         if not self._GetNextToken():\r
2385             raise Warning.Expected("INF file path", self.FileName, self.CurrentLineNumber)\r
2386         ffsInf.InfFileName = self._Token\r
2387         if not ffsInf.InfFileName.endswith('.inf'):\r
2388             raise Warning.Expected(".inf file path", self.FileName, self.CurrentLineNumber)\r
2389 \r
2390         ffsInf.CurrentLineNum = self.CurrentLineNumber\r
2391         ffsInf.CurrentLineContent = self._CurrentLine()\r
2392 \r
2393         #Replace $(SAPCE) with real space\r
2394         ffsInf.InfFileName = ffsInf.InfFileName.replace('$(SPACE)', ' ')\r
2395 \r
2396         if ffsInf.InfFileName.replace(TAB_WORKSPACE, '').find('$') == -1:\r
2397             #do case sensitive check for file path\r
2398             ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()\r
2399             if ErrorCode != 0:\r
2400                 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
2401 \r
2402         NewFileName = ffsInf.InfFileName\r
2403         if ffsInf.OverrideGuid:\r
2404             NewFileName = ProcessDuplicatedInf(PathClass(ffsInf.InfFileName,GenFdsGlobalVariable.WorkSpaceDir), ffsInf.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir).Path\r
2405 \r
2406         if not NewFileName in self.Profile.InfList:\r
2407             self.Profile.InfList.append(NewFileName)\r
2408             FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
2409             self.Profile.InfFileLineList.append(FileLineTuple)\r
2410             if ffsInf.UseArch:\r
2411                 if ffsInf.UseArch not in self.Profile.InfDict:\r
2412                     self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]\r
2413                 else:\r
2414                     self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)\r
2415             else:\r
2416                 self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)\r
2417 \r
2418         if self._IsToken(TAB_VALUE_SPLIT):\r
2419             if self._IsKeyword('RELOCS_STRIPPED'):\r
2420                 ffsInf.KeepReloc = False\r
2421             elif self._IsKeyword('RELOCS_RETAINED'):\r
2422                 ffsInf.KeepReloc = True\r
2423             else:\r
2424                 raise Warning("Unknown reloc strip flag '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2425         return ffsInf\r
2426 \r
2427     ## _GetInfStatement() method\r
2428     #\r
2429     #   Get INF statements\r
2430     #\r
2431     #   @param  self        The object pointer\r
2432     #   @param  Obj         for whom inf statement is got\r
2433     #   @retval True        Successfully find inf statement\r
2434     #   @retval False       Not able to find inf statement\r
2435     #\r
2436     def _GetInfStatement(self, Obj, ForCapsule=False):\r
2437         ffsInf = self._ParseInfStatement()\r
2438         if not ffsInf:\r
2439             return False\r
2440 \r
2441         if ForCapsule:\r
2442             myCapsuleFfs = CapsuleFfs()\r
2443             myCapsuleFfs.Ffs = ffsInf\r
2444             Obj.CapsuleDataList.append(myCapsuleFfs)\r
2445         else:\r
2446             Obj.FfsList.append(ffsInf)\r
2447         return True\r
2448 \r
2449     ## _GetInfOptions() method\r
2450     #\r
2451     #   Get options for INF\r
2452     #\r
2453     #   @param  self        The object pointer\r
2454     #   @param  FfsInfObj   for whom option is got\r
2455     #\r
2456     def _GetInfOptions(self, FfsInfObj):\r
2457         if self._IsKeyword("FILE_GUID"):\r
2458             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2459                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2460             if not self._GetNextGuid():\r
2461                 raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)\r
2462             FfsInfObj.OverrideGuid = self._Token\r
2463 \r
2464         if self._IsKeyword("RuleOverride"):\r
2465             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2466                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2467             if not self._GetNextToken():\r
2468                 raise Warning.Expected("Rule name", self.FileName, self.CurrentLineNumber)\r
2469             FfsInfObj.Rule = self._Token\r
2470 \r
2471         if self._IsKeyword("VERSION"):\r
2472             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2473                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2474             if not self._GetNextToken():\r
2475                 raise Warning.Expected("Version", self.FileName, self.CurrentLineNumber)\r
2476 \r
2477             if self._GetStringData():\r
2478                 FfsInfObj.Version = self._Token\r
2479 \r
2480         if self._IsKeyword(BINARY_FILE_TYPE_UI):\r
2481             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2482                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2483             if not self._GetNextToken():\r
2484                 raise Warning.Expected("UI name", self.FileName, self.CurrentLineNumber)\r
2485 \r
2486             if self._GetStringData():\r
2487                 FfsInfObj.Ui = self._Token\r
2488 \r
2489         if self._IsKeyword("USE"):\r
2490             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2491                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2492             if not self._GetNextToken():\r
2493                 raise Warning.Expected("ARCH name", self.FileName, self.CurrentLineNumber)\r
2494             FfsInfObj.UseArch = self._Token\r
2495 \r
2496 \r
2497         if self._GetNextToken():\r
2498             p = compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\))')\r
2499             if p.match(self._Token) and p.match(self._Token).span()[1] == len(self._Token):\r
2500                 FfsInfObj.KeyStringList.append(self._Token)\r
2501                 if not self._IsToken(TAB_COMMA_SPLIT):\r
2502                     return\r
2503             else:\r
2504                 self._UndoToken()\r
2505                 return\r
2506 \r
2507             while self._GetNextToken():\r
2508                 if not p.match(self._Token):\r
2509                     raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)\r
2510                 FfsInfObj.KeyStringList.append(self._Token)\r
2511 \r
2512                 if not self._IsToken(TAB_COMMA_SPLIT):\r
2513                     break\r
2514 \r
2515     ## _GetFileStatement() method\r
2516     #\r
2517     #   Get FILE statements\r
2518     #\r
2519     #   @param  self        The object pointer\r
2520     #   @param  Obj         for whom FILE statement is got\r
2521     #   @retval True        Successfully find FILE statement\r
2522     #   @retval False       Not able to find FILE statement\r
2523     #\r
2524     def _GetFileStatement(self, Obj, ForCapsule = False):\r
2525         if not self._IsKeyword("FILE"):\r
2526             return False\r
2527 \r
2528         if not self._GetNextWord():\r
2529             raise Warning.Expected("FFS type", self.FileName, self.CurrentLineNumber)\r
2530 \r
2531         if ForCapsule and self._Token == 'DATA':\r
2532             self._UndoToken()\r
2533             self._UndoToken()\r
2534             return False\r
2535 \r
2536         FfsFileObj = FileStatement()\r
2537         FfsFileObj.FvFileType = self._Token\r
2538 \r
2539         if not self._IsToken(TAB_EQUAL_SPLIT):\r
2540             raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2541 \r
2542         if not self._GetNextGuid():\r
2543             if not self._GetNextWord():\r
2544                 raise Warning.Expected("File GUID", self.FileName, self.CurrentLineNumber)\r
2545             if self._Token == 'PCD':\r
2546                 if not self._IsToken("("):\r
2547                     raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)\r
2548                 PcdPair = self._GetNextPcdSettings()\r
2549                 if not self._IsToken(")"):\r
2550                     raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)\r
2551                 self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'\r
2552 \r
2553         FfsFileObj.NameGuid = self._Token\r
2554 \r
2555         self._GetFilePart(FfsFileObj)\r
2556 \r
2557         if ForCapsule:\r
2558             capsuleFfs = CapsuleFfs()\r
2559             capsuleFfs.Ffs = FfsFileObj\r
2560             Obj.CapsuleDataList.append(capsuleFfs)\r
2561         else:\r
2562             Obj.FfsList.append(FfsFileObj)\r
2563 \r
2564         return True\r
2565 \r
2566     ## _FileCouldHaveRelocFlag() method\r
2567     #\r
2568     #   Check whether reloc strip flag can be set for a file type.\r
2569     #\r
2570     #   @param  FileType    The file type to check with\r
2571     #   @retval True        This type could have relocation strip flag\r
2572     #   @retval False       No way to have it\r
2573     #\r
2574     @staticmethod\r
2575     def _FileCouldHaveRelocFlag (FileType):\r
2576         if FileType in {SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE, 'PEI_DXE_COMBO'}:\r
2577             return True\r
2578         else:\r
2579             return False\r
2580 \r
2581     ## _SectionCouldHaveRelocFlag() method\r
2582     #\r
2583     #   Check whether reloc strip flag can be set for a section type.\r
2584     #\r
2585     #   @param  SectionType The section type to check with\r
2586     #   @retval True        This type could have relocation strip flag\r
2587     #   @retval False       No way to have it\r
2588     #\r
2589     @staticmethod\r
2590     def _SectionCouldHaveRelocFlag (SectionType):\r
2591         if SectionType in {BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32}:\r
2592             return True\r
2593         else:\r
2594             return False\r
2595 \r
2596     ## _GetFilePart() method\r
2597     #\r
2598     #   Get components for FILE statement\r
2599     #\r
2600     #   @param  self        The object pointer\r
2601     #   @param  FfsFileObj   for whom component is got\r
2602     #\r
2603     def _GetFilePart(self, FfsFileObj):\r
2604         self._GetFileOpts(FfsFileObj)\r
2605 \r
2606         if not self._IsToken("{"):\r
2607             if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):\r
2608                 if self._FileCouldHaveRelocFlag(FfsFileObj.FvFileType):\r
2609                     if self._Token == 'RELOCS_STRIPPED':\r
2610                         FfsFileObj.KeepReloc = False\r
2611                     else:\r
2612                         FfsFileObj.KeepReloc = True\r
2613                 else:\r
2614                     raise Warning("File type %s could not have reloc strip flag%d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)\r
2615 \r
2616             if not self._IsToken("{"):\r
2617                 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
2618 \r
2619         if not self._GetNextToken():\r
2620             raise Warning.Expected("File name or section data", self.FileName, self.CurrentLineNumber)\r
2621 \r
2622         if self._Token == BINARY_FILE_TYPE_FV:\r
2623             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2624                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2625             if not self._GetNextToken():\r
2626                 raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)\r
2627             FfsFileObj.FvName = self._Token\r
2628 \r
2629         elif self._Token == "FD":\r
2630             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2631                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2632             if not self._GetNextToken():\r
2633                 raise Warning.Expected("FD name", self.FileName, self.CurrentLineNumber)\r
2634             FfsFileObj.FdName = self._Token\r
2635 \r
2636         elif self._Token in {TAB_DEFINE, "APRIORI", "SECTION"}:\r
2637             self._UndoToken()\r
2638             self._GetSectionData(FfsFileObj)\r
2639 \r
2640         elif hasattr(FfsFileObj, 'FvFileType') and FfsFileObj.FvFileType == 'RAW':\r
2641             self._UndoToken()\r
2642             self._GetRAWData(FfsFileObj)\r
2643 \r
2644         else:\r
2645             FfsFileObj.CurrentLineNum = self.CurrentLineNumber\r
2646             FfsFileObj.CurrentLineContent = self._CurrentLine()\r
2647             FfsFileObj.FileName = self._Token.replace('$(SPACE)', ' ')\r
2648             self._VerifyFile(FfsFileObj.FileName)\r
2649 \r
2650         if not self._IsToken(T_CHAR_BRACE_R):\r
2651             raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2652 \r
2653     ## _GetRAWData() method\r
2654     #\r
2655     #   Get RAW data for FILE statement\r
2656     #\r
2657     #   @param  self         The object pointer\r
2658     #   @param  FfsFileObj   for whom section is got\r
2659     #\r
2660     def _GetRAWData(self, FfsFileObj):\r
2661         FfsFileObj.FileName = []\r
2662         FfsFileObj.SubAlignment = []\r
2663         while True:\r
2664             AlignValue = None\r
2665             if self._GetAlignment():\r
2666                 if self._Token not in ALIGNMENTS:\r
2667                     raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2668                 #For FFS, Auto is default option same to ""\r
2669                 if not self._Token == "Auto":\r
2670                     AlignValue = self._Token\r
2671             if not self._GetNextToken():\r
2672                 raise Warning.Expected("Filename value", self.FileName, self.CurrentLineNumber)\r
2673 \r
2674             FileName = self._Token.replace('$(SPACE)', ' ')\r
2675             if FileName == T_CHAR_BRACE_R:\r
2676                 self._UndoToken()\r
2677                 raise Warning.Expected("Filename value", self.FileName, self.CurrentLineNumber)\r
2678 \r
2679             self._VerifyFile(FileName)\r
2680             File = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir)\r
2681             FfsFileObj.FileName.append(File.Path)\r
2682             FfsFileObj.SubAlignment.append(AlignValue)\r
2683 \r
2684             if self._IsToken(T_CHAR_BRACE_R):\r
2685                 self._UndoToken()\r
2686                 break\r
2687 \r
2688         if len(FfsFileObj.SubAlignment) == 1:\r
2689             FfsFileObj.SubAlignment = FfsFileObj.SubAlignment[0]\r
2690         if len(FfsFileObj.FileName) == 1:\r
2691             FfsFileObj.FileName = FfsFileObj.FileName[0]\r
2692 \r
2693     ## _GetFileOpts() method\r
2694     #\r
2695     #   Get options for FILE statement\r
2696     #\r
2697     #   @param  self        The object pointer\r
2698     #   @param  FfsFileObj   for whom options is got\r
2699     #\r
2700     def _GetFileOpts(self, FfsFileObj):\r
2701         if self._GetNextToken():\r
2702             if TokenFindPattern.match(self._Token):\r
2703                 FfsFileObj.KeyStringList.append(self._Token)\r
2704                 if self._IsToken(TAB_COMMA_SPLIT):\r
2705                     while self._GetNextToken():\r
2706                         if not TokenFindPattern.match(self._Token):\r
2707                             raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)\r
2708                         FfsFileObj.KeyStringList.append(self._Token)\r
2709 \r
2710                         if not self._IsToken(TAB_COMMA_SPLIT):\r
2711                             break\r
2712 \r
2713             else:\r
2714                 self._UndoToken()\r
2715 \r
2716         if self._IsKeyword("FIXED", True):\r
2717             FfsFileObj.Fixed = True\r
2718 \r
2719         if self._IsKeyword("CHECKSUM", True):\r
2720             FfsFileObj.CheckSum = True\r
2721 \r
2722         if self._GetAlignment():\r
2723             if self._Token not in ALIGNMENTS:\r
2724                 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2725             #For FFS, Auto is default option same to ""\r
2726             if not self._Token == "Auto":\r
2727                 FfsFileObj.Alignment = self._Token\r
2728 \r
2729     ## _GetAlignment() method\r
2730     #\r
2731     #   Return the alignment value\r
2732     #\r
2733     #   @param  self        The object pointer\r
2734     #   @retval True        Successfully find alignment\r
2735     #   @retval False       Not able to find alignment\r
2736     #\r
2737     def _GetAlignment(self):\r
2738         if self._IsKeyword("Align", True):\r
2739             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2740                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2741 \r
2742             if not self._GetNextToken():\r
2743                 raise Warning.Expected("alignment value", self.FileName, self.CurrentLineNumber)\r
2744             return True\r
2745 \r
2746         return False\r
2747 \r
2748     ## _GetSectionData() method\r
2749     #\r
2750     #   Get section data for FILE statement\r
2751     #\r
2752     #   @param  self        The object pointer\r
2753     #   @param  FfsFileObj   for whom section is got\r
2754     #\r
2755     def _GetSectionData(self, FfsFileObj):\r
2756         self._GetDefineStatements(FfsFileObj)\r
2757 \r
2758         while True:\r
2759             IsLeafSection = self._GetLeafSection(FfsFileObj)\r
2760             IsEncapSection = self._GetEncapsulationSec(FfsFileObj)\r
2761             if not IsLeafSection and not IsEncapSection:\r
2762                 break\r
2763 \r
2764     ## _GetLeafSection() method\r
2765     #\r
2766     #   Get leaf section for Obj\r
2767     #\r
2768     #   @param  self        The object pointer\r
2769     #   @param  Obj         for whom leaf section is got\r
2770     #   @retval True        Successfully find section statement\r
2771     #   @retval False       Not able to find section statement\r
2772     #\r
2773     def _GetLeafSection(self, Obj):\r
2774         OldPos = self.GetFileBufferPos()\r
2775 \r
2776         if not self._IsKeyword("SECTION"):\r
2777             if len(Obj.SectionList) == 0:\r
2778                 raise Warning.Expected("SECTION", self.FileName, self.CurrentLineNumber)\r
2779             else:\r
2780                 return False\r
2781 \r
2782         AlignValue = None\r
2783         if self._GetAlignment():\r
2784             if self._Token not in ALIGNMENTS:\r
2785                 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2786             AlignValue = self._Token\r
2787 \r
2788         BuildNum = None\r
2789         if self._IsKeyword("BUILD_NUM"):\r
2790             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2791                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2792 \r
2793             if not self._GetNextToken():\r
2794                 raise Warning.Expected("Build number value", self.FileName, self.CurrentLineNumber)\r
2795 \r
2796             BuildNum = self._Token\r
2797 \r
2798         if self._IsKeyword("VERSION"):\r
2799             if AlignValue == 'Auto':\r
2800                 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)\r
2801             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2802                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2803             if not self._GetNextToken():\r
2804                 raise Warning.Expected("version", self.FileName, self.CurrentLineNumber)\r
2805             VerSectionObj = VerSection()\r
2806             VerSectionObj.Alignment = AlignValue\r
2807             VerSectionObj.BuildNum = BuildNum\r
2808             if self._GetStringData():\r
2809                 VerSectionObj.StringData = self._Token\r
2810             else:\r
2811                 VerSectionObj.FileName = self._Token\r
2812             Obj.SectionList.append(VerSectionObj)\r
2813 \r
2814         elif self._IsKeyword(BINARY_FILE_TYPE_UI):\r
2815             if AlignValue == 'Auto':\r
2816                 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)\r
2817             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2818                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2819             if not self._GetNextToken():\r
2820                 raise Warning.Expected("UI", self.FileName, self.CurrentLineNumber)\r
2821             UiSectionObj = UiSection()\r
2822             UiSectionObj.Alignment = AlignValue\r
2823             if self._GetStringData():\r
2824                 UiSectionObj.StringData = self._Token\r
2825             else:\r
2826                 UiSectionObj.FileName = self._Token\r
2827             Obj.SectionList.append(UiSectionObj)\r
2828 \r
2829         elif self._IsKeyword("FV_IMAGE"):\r
2830             if AlignValue == 'Auto':\r
2831                 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)\r
2832             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2833                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2834             if not self._GetNextToken():\r
2835                 raise Warning.Expected("FV name or FV file path", self.FileName, self.CurrentLineNumber)\r
2836 \r
2837             FvName = self._Token\r
2838             FvObj = None\r
2839 \r
2840             if self._IsToken("{"):\r
2841                 FvObj = FV()\r
2842                 FvObj.UiFvName = FvName.upper()\r
2843                 self._GetDefineStatements(FvObj)\r
2844 \r
2845                 self._GetBlockStatement(FvObj)\r
2846                 self._GetSetStatements(FvObj)\r
2847                 self._GetFvAlignment(FvObj)\r
2848                 self._GetFvAttributes(FvObj)\r
2849 \r
2850                 while True:\r
2851                     IsInf = self._GetInfStatement(FvObj)\r
2852                     IsFile = self._GetFileStatement(FvObj)\r
2853                     if not IsInf and not IsFile:\r
2854                         break\r
2855 \r
2856                 if not self._IsToken(T_CHAR_BRACE_R):\r
2857                     raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2858 \r
2859             FvImageSectionObj = FvImageSection()\r
2860             FvImageSectionObj.Alignment = AlignValue\r
2861             if FvObj is not None:\r
2862                 FvImageSectionObj.Fv = FvObj\r
2863                 FvImageSectionObj.FvName = None\r
2864             else:\r
2865                 FvImageSectionObj.FvName = FvName.upper()\r
2866                 FvImageSectionObj.FvFileName = FvName\r
2867 \r
2868             Obj.SectionList.append(FvImageSectionObj)\r
2869 \r
2870         elif self._IsKeyword("PEI_DEPEX_EXP") or self._IsKeyword("DXE_DEPEX_EXP") or self._IsKeyword("SMM_DEPEX_EXP"):\r
2871             if AlignValue == 'Auto':\r
2872                 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)\r
2873             DepexSectionObj = DepexSection()\r
2874             DepexSectionObj.Alignment = AlignValue\r
2875             DepexSectionObj.DepexType = self._Token\r
2876 \r
2877             if not self._IsToken(TAB_EQUAL_SPLIT):\r
2878                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
2879             if not self._IsToken("{"):\r
2880                 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
2881             if not self._SkipToToken(T_CHAR_BRACE_R):\r
2882                 raise Warning.Expected("Depex expression ending '}'", self.FileName, self.CurrentLineNumber)\r
2883 \r
2884             DepexSectionObj.Expression = self._SkippedChars.rstrip(T_CHAR_BRACE_R)\r
2885             Obj.SectionList.append(DepexSectionObj)\r
2886 \r
2887         else:\r
2888             if not self._GetNextWord():\r
2889                 raise Warning.Expected("section type", self.FileName, self.CurrentLineNumber)\r
2890 \r
2891             # Encapsulation section appear, UndoToken and return\r
2892             if self._Token == "COMPRESS" or self._Token == "GUIDED":\r
2893                 self.SetFileBufferPos(OldPos)\r
2894                 return False\r
2895 \r
2896             if self._Token not in {"COMPAT16", BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,\\r
2897                                BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "SUBTYPE_GUID", BINARY_FILE_TYPE_SMM_DEPEX}:\r
2898                 raise Warning("Unknown section type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
2899             if AlignValue == 'Auto'and (not self._Token == BINARY_FILE_TYPE_PE32) and (not self._Token == BINARY_FILE_TYPE_TE):\r
2900                 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)\r
2901 \r
2902             # DataSection\r
2903             DataSectionObj = DataSection()\r
2904             DataSectionObj.Alignment = AlignValue\r
2905             DataSectionObj.SecType = self._Token\r
2906 \r
2907             if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):\r
2908                 if self._FileCouldHaveRelocFlag(Obj.FvFileType) and self._SectionCouldHaveRelocFlag(DataSectionObj.SecType):\r
2909                     if self._Token == 'RELOCS_STRIPPED':\r
2910                         DataSectionObj.KeepReloc = False\r
2911                     else:\r
2912                         DataSectionObj.KeepReloc = True\r
2913                 else:\r
2914                     raise Warning("File type %s, section type %s, could not have reloc strip flag%d" % (Obj.FvFileType, DataSectionObj.SecType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)\r
2915 \r
2916             if self._IsToken(TAB_EQUAL_SPLIT):\r
2917                 if not self._GetNextToken():\r
2918                     raise Warning.Expected("section file path", self.FileName, self.CurrentLineNumber)\r
2919                 DataSectionObj.SectFileName = self._Token\r
2920                 self._VerifyFile(DataSectionObj.SectFileName)\r
2921             else:\r
2922                 if not self._GetCglSection(DataSectionObj):\r
2923                     return False\r
2924 \r
2925             Obj.SectionList.append(DataSectionObj)\r
2926 \r
2927         return True\r
2928 \r
2929     ## _VerifyFile\r
2930     #\r
2931     #    Check if file exists or not:\r
2932     #      If current phase if GenFds, the file must exist;\r
2933     #      If current phase is AutoGen and the file is not in $(OUTPUT_DIRECTORY), the file must exist\r
2934     #    @param FileName: File path to be verified.\r
2935     #\r
2936     def _VerifyFile(self, FileName):\r
2937         if FileName.replace(TAB_WORKSPACE, '').find('$') != -1:\r
2938             return\r
2939         if not GlobalData.gAutoGenPhase or not self._GetMacroValue(TAB_DSC_DEFINES_OUTPUT_DIRECTORY) in FileName:\r
2940             ErrorCode, ErrorInfo = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()\r
2941             if ErrorCode != 0:\r
2942                 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)\r
2943 \r
2944     ## _GetCglSection() method\r
2945     #\r
2946     #   Get compressed or GUIDed section for Obj\r
2947     #\r
2948     #   @param  self        The object pointer\r
2949     #   @param  Obj         for whom leaf section is got\r
2950     #   @param  AlignValue  alignment value for complex section\r
2951     #   @retval True        Successfully find section statement\r
2952     #   @retval False       Not able to find section statement\r
2953     #\r
2954     def _GetCglSection(self, Obj, AlignValue = None):\r
2955 \r
2956         if self._IsKeyword("COMPRESS"):\r
2957             type = "PI_STD"\r
2958             if self._IsKeyword("PI_STD") or self._IsKeyword("PI_NONE"):\r
2959                 type = self._Token\r
2960 \r
2961             if not self._IsToken("{"):\r
2962                 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
2963 \r
2964             CompressSectionObj = CompressSection()\r
2965             CompressSectionObj.Alignment = AlignValue\r
2966             CompressSectionObj.CompType = type\r
2967             # Recursive sections...\r
2968             while True:\r
2969                 IsLeafSection = self._GetLeafSection(CompressSectionObj)\r
2970                 IsEncapSection = self._GetEncapsulationSec(CompressSectionObj)\r
2971                 if not IsLeafSection and not IsEncapSection:\r
2972                     break\r
2973 \r
2974 \r
2975             if not self._IsToken(T_CHAR_BRACE_R):\r
2976                 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
2977             Obj.SectionList.append(CompressSectionObj)\r
2978             return True\r
2979 \r
2980         elif self._IsKeyword("GUIDED"):\r
2981             GuidValue = None\r
2982             if self._GetNextGuid():\r
2983                 GuidValue = self._Token\r
2984 \r
2985             AttribDict = self._GetGuidAttrib()\r
2986             if not self._IsToken("{"):\r
2987                 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)\r
2988             GuidSectionObj = GuidSection()\r
2989             GuidSectionObj.Alignment = AlignValue\r
2990             GuidSectionObj.NameGuid = GuidValue\r
2991             GuidSectionObj.SectionType = "GUIDED"\r
2992             GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]\r
2993             GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]\r
2994             GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]\r
2995             # Recursive sections...\r
2996             while True:\r
2997                 IsLeafSection = self._GetLeafSection(GuidSectionObj)\r
2998                 IsEncapSection = self._GetEncapsulationSec(GuidSectionObj)\r
2999                 if not IsLeafSection and not IsEncapSection:\r
3000                     break\r
3001 \r
3002             if not self._IsToken(T_CHAR_BRACE_R):\r
3003                 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)\r
3004             Obj.SectionList.append(GuidSectionObj)\r
3005 \r
3006             return True\r
3007 \r
3008         return False\r
3009 \r
3010     ## _GetGuidAttri() method\r
3011     #\r
3012     #   Get attributes for GUID section\r
3013     #\r
3014     #   @param  self        The object pointer\r
3015     #   @retval AttribDict  Dictionary of key-value pair of section attributes\r
3016     #\r
3017     def _GetGuidAttrib(self):\r
3018         AttribDict = {}\r
3019         AttribDict["PROCESSING_REQUIRED"] = "NONE"\r
3020         AttribDict["AUTH_STATUS_VALID"] = "NONE"\r
3021         AttribDict["EXTRA_HEADER_SIZE"] = -1\r
3022         while self._IsKeyword("PROCESSING_REQUIRED") or self._IsKeyword("AUTH_STATUS_VALID") \\r
3023             or self._IsKeyword("EXTRA_HEADER_SIZE"):\r
3024             AttribKey = self._Token\r
3025 \r
3026             if not self._IsToken(TAB_EQUAL_SPLIT):\r
3027                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
3028 \r
3029             if not self._GetNextToken():\r
3030                 raise Warning.Expected("TRUE(1)/FALSE(0)/Number", self.FileName, self.CurrentLineNumber)\r
3031             elif AttribKey == "EXTRA_HEADER_SIZE":\r
3032                 Base = 10\r
3033                 if self._Token[0:2].upper() == "0X":\r
3034                     Base = 16\r
3035                 try:\r
3036                     AttribDict[AttribKey] = int(self._Token, Base)\r
3037                     continue\r
3038                 except ValueError:\r
3039                     raise Warning.Expected("Number", self.FileName, self.CurrentLineNumber)\r
3040             elif self._Token.upper() not in {"TRUE", "FALSE", "1", "0"}:\r
3041                 raise Warning.Expected("TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)\r
3042             AttribDict[AttribKey] = self._Token\r
3043 \r
3044         return AttribDict\r
3045 \r
3046     ## _GetEncapsulationSec() method\r
3047     #\r
3048     #   Get encapsulation section for FILE\r
3049     #\r
3050     #   @param  self        The object pointer\r
3051     #   @param  FfsFile     for whom section is got\r
3052     #   @retval True        Successfully find section statement\r
3053     #   @retval False       Not able to find section statement\r
3054     #\r
3055     def _GetEncapsulationSec(self, FfsFileObj):\r
3056         OldPos = self.GetFileBufferPos()\r
3057         if not self._IsKeyword("SECTION"):\r
3058             if len(FfsFileObj.SectionList) == 0:\r
3059                 raise Warning.Expected("SECTION", self.FileName, self.CurrentLineNumber)\r
3060             else:\r
3061                 return False\r
3062 \r
3063         AlignValue = None\r
3064         if self._GetAlignment():\r
3065             if self._Token not in ALIGNMENT_NOAUTO:\r
3066                 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)\r
3067             AlignValue = self._Token\r
3068 \r
3069         if not self._GetCglSection(FfsFileObj, AlignValue):\r
3070             self.SetFileBufferPos(OldPos)\r
3071             return False\r
3072         else:\r
3073             return True\r
3074 \r
3075     def _GetFmp(self):\r
3076         if not self._GetNextToken():\r
3077             return False\r
3078         S = self._Token.upper()\r
3079         if S.startswith(TAB_SECTION_START) and not S.startswith("[FMPPAYLOAD."):\r
3080             self.SectionParser(S)\r
3081             self._UndoToken()\r
3082             return False\r
3083 \r
3084         self._UndoToken()\r
3085         self._SkipToToken("[FMPPAYLOAD.", True)\r
3086         FmpUiName = self._GetUiName().upper()\r
3087         if FmpUiName in self.Profile.FmpPayloadDict:\r
3088             raise Warning("Duplicated FMP UI name found: %s" % FmpUiName, self.FileName, self.CurrentLineNumber)\r
3089 \r
3090         FmpData = CapsulePayload()\r
3091         FmpData.UiName = FmpUiName\r
3092 \r
3093         if not self._IsToken(TAB_SECTION_END):\r
3094             raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)\r
3095 \r
3096         if not self._GetNextToken():\r
3097             raise Warning("The FMP payload section is empty!", self.FileName, self.CurrentLineNumber)\r
3098         FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE', 'CERTIFICATE_GUID', 'MONOTONIC_COUNT']\r
3099         while self._Token in FmpKeyList:\r
3100             Name = self._Token\r
3101             FmpKeyList.remove(Name)\r
3102             if not self._IsToken(TAB_EQUAL_SPLIT):\r
3103                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
3104             if Name == 'IMAGE_TYPE_ID':\r
3105                 if not self._GetNextGuid():\r
3106                     raise Warning.Expected("GUID value for IMAGE_TYPE_ID.", self.FileName, self.CurrentLineNumber)\r
3107                 FmpData.ImageTypeId = self._Token\r
3108             elif Name == 'CERTIFICATE_GUID':\r
3109                 if not self._GetNextGuid():\r
3110                     raise Warning.Expected("GUID value for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)\r
3111                 FmpData.Certificate_Guid = self._Token\r
3112                 if UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_RSA2048_SHA256_GUID and UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_PKCS7_GUID:\r
3113                     raise Warning("Only support EFI_CERT_TYPE_RSA2048_SHA256_GUID or EFI_CERT_TYPE_PKCS7_GUID for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)\r
3114             else:\r
3115                 if not self._GetNextToken():\r
3116                     raise Warning.Expected("value of %s" % Name, self.FileName, self.CurrentLineNumber)\r
3117                 Value = self._Token\r
3118                 if Name == 'IMAGE_HEADER_INIT_VERSION':\r
3119                     if FdfParser._Verify(Name, Value, 'UINT8'):\r
3120                         FmpData.Version = Value\r
3121                 elif Name == 'IMAGE_INDEX':\r
3122                     if FdfParser._Verify(Name, Value, 'UINT8'):\r
3123                         FmpData.ImageIndex = Value\r
3124                 elif Name == 'HARDWARE_INSTANCE':\r
3125                     if FdfParser._Verify(Name, Value, 'UINT8'):\r
3126                         FmpData.HardwareInstance = Value\r
3127                 elif Name == 'MONOTONIC_COUNT':\r
3128                     if FdfParser._Verify(Name, Value, 'UINT64'):\r
3129                         FmpData.MonotonicCount = Value\r
3130                         if FmpData.MonotonicCount.upper().startswith('0X'):\r
3131                             FmpData.MonotonicCount = int(FmpData.MonotonicCount, 16)\r
3132                         else:\r
3133                             FmpData.MonotonicCount = int(FmpData.MonotonicCount)\r
3134             if not self._GetNextToken():\r
3135                 break\r
3136         else:\r
3137             self._UndoToken()\r
3138 \r
3139         if (FmpData.MonotonicCount and not FmpData.Certificate_Guid) or (not FmpData.MonotonicCount and FmpData.Certificate_Guid):\r
3140             EdkLogger.error("FdfParser", FORMAT_INVALID, "CERTIFICATE_GUID and MONOTONIC_COUNT must be work as a pair.")\r
3141 \r
3142         # Only the IMAGE_TYPE_ID is required item\r
3143         if FmpKeyList and 'IMAGE_TYPE_ID' in FmpKeyList:\r
3144             raise Warning("'IMAGE_TYPE_ID' in FMP payload section.", self.FileName, self.CurrentLineNumber)\r
3145         # get the Image file and Vendor code file\r
3146         self._GetFMPCapsuleData(FmpData)\r
3147         if not FmpData.ImageFile:\r
3148             raise Warning("Missing image file in FMP payload section.", self.FileName, self.CurrentLineNumber)\r
3149         # check whether more than one Vendor code file\r
3150         if len(FmpData.VendorCodeFile) > 1:\r
3151             raise Warning("Vendor code file max of 1 per FMP payload section.", self.FileName, self.CurrentLineNumber)\r
3152         self.Profile.FmpPayloadDict[FmpUiName] = FmpData\r
3153         return True\r
3154 \r
3155     ## _GetCapsule() method\r
3156     #\r
3157     #   Get capsule section contents and store its data into capsule list of self.Profile\r
3158     #\r
3159     #   @param  self        The object pointer\r
3160     #   @retval True        Successfully find a capsule\r
3161     #   @retval False       Not able to find a capsule\r
3162     #\r
3163     def _GetCapsule(self):\r
3164         if not self._GetNextToken():\r
3165             return False\r
3166 \r
3167         S = self._Token.upper()\r
3168         if S.startswith(TAB_SECTION_START) and not S.startswith("[CAPSULE."):\r
3169             self.SectionParser(S)\r
3170             self._UndoToken()\r
3171             return False\r
3172 \r
3173         self._UndoToken()\r
3174         if not self._IsToken("[CAPSULE.", True):\r
3175             FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)\r
3176             #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \\r
3177             #        % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)\r
3178             raise Warning.Expected("[Capsule.]", self.FileName, self.CurrentLineNumber)\r
3179 \r
3180         CapsuleObj = Capsule()\r
3181 \r
3182         CapsuleName = self._GetUiName()\r
3183         if not CapsuleName:\r
3184             raise Warning.Expected("capsule name", self.FileName, self.CurrentLineNumber)\r
3185 \r
3186         CapsuleObj.UiCapsuleName = CapsuleName.upper()\r
3187 \r
3188         if not self._IsToken(TAB_SECTION_END):\r
3189             raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)\r
3190 \r
3191         if self._IsKeyword("CREATE_FILE"):\r
3192             if not self._IsToken(TAB_EQUAL_SPLIT):\r
3193                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
3194 \r
3195             if not self._GetNextToken():\r
3196                 raise Warning.Expected("file name", self.FileName, self.CurrentLineNumber)\r
3197 \r
3198             CapsuleObj.CreateFile = self._Token\r
3199 \r
3200         self._GetCapsuleStatements(CapsuleObj)\r
3201         self.Profile.CapsuleDict[CapsuleObj.UiCapsuleName] = CapsuleObj\r
3202         return True\r
3203 \r
3204     ## _GetCapsuleStatements() method\r
3205     #\r
3206     #   Get statements for capsule\r
3207     #\r
3208     #   @param  self        The object pointer\r
3209     #   @param  Obj         for whom statements are got\r
3210     #\r
3211     def _GetCapsuleStatements(self, Obj):\r
3212         self._GetCapsuleTokens(Obj)\r
3213         self._GetDefineStatements(Obj)\r
3214         self._GetSetStatements(Obj)\r
3215         self._GetCapsuleData(Obj)\r
3216 \r
3217     ## _GetCapsuleTokens() method\r
3218     #\r
3219     #   Get token statements for capsule\r
3220     #\r
3221     #   @param  self        The object pointer\r
3222     #   @param  Obj         for whom token statements are got\r
3223     #\r
3224     def _GetCapsuleTokens(self, Obj):\r
3225         if not self._GetNextToken():\r
3226             return False\r
3227         while self._Token in {"CAPSULE_GUID", "CAPSULE_HEADER_SIZE", "CAPSULE_FLAGS", "OEM_CAPSULE_FLAGS", "CAPSULE_HEADER_INIT_VERSION"}:\r
3228             Name = self._Token.strip()\r
3229             if not self._IsToken(TAB_EQUAL_SPLIT):\r
3230                 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)\r
3231             if not self._GetNextToken():\r
3232                 raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)\r
3233             if Name == 'CAPSULE_FLAGS':\r
3234                 if not self._Token in {"PersistAcrossReset", "PopulateSystemTable", "InitiateReset"}:\r
3235                     raise Warning.Expected("PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)\r
3236                 Value = self._Token.strip()\r
3237                 while self._IsToken(TAB_COMMA_SPLIT):\r
3238                     Value += TAB_COMMA_SPLIT\r
3239                     if not self._GetNextToken():\r
3240                         raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)\r
3241                     if not self._Token in {"PersistAcrossReset", "PopulateSystemTable", "InitiateReset"}:\r
3242                         raise Warning.Expected("PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)\r
3243                     Value += self._Token.strip()\r
3244             elif Name == 'OEM_CAPSULE_FLAGS':\r
3245                 Value = self._Token.strip()\r
3246                 if not Value.upper().startswith('0X'):\r
3247                     raise Warning.Expected("hex value starting with 0x", self.FileName, self.CurrentLineNumber)\r
3248                 try:\r
3249                     Value = int(Value, 0)\r
3250                 except ValueError:\r
3251                     raise Warning.Expected("hex string failed to convert to value", self.FileName, self.CurrentLineNumber)\r
3252                 if not 0x0000 <= Value <= 0xFFFF:\r
3253                     raise Warning.Expected("hex value between 0x0000 and 0xFFFF", self.FileName, self.CurrentLineNumber)\r
3254             &nbs