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