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