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