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