]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/GenFds/FdfParser.py
63edf816ecfc8e48088f762dc1757583ccb1dabd
[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 from re import compile, DOTALL
22 from string import hexdigits
23 from uuid import UUID
24
25 from Common.BuildToolError import *
26 from Common import EdkLogger
27 from Common.Misc import PathClass, tdict, ProcessDuplicatedInf
28 from Common.StringUtils import NormPath, ReplaceMacro
29 from Common import GlobalData
30 from Common.Expression import *
31 from Common.DataType import *
32 from Common.MultipleWorkspace import MultipleWorkspace as mws
33 import Common.LongFilePathOs as os
34 from Common.LongFilePathSupport import OpenLongFilePath as open
35 from Common.RangeExpression import RangeExpression
36 from collections import OrderedDict
37
38 from .Fd import FD
39 from .Region import Region
40 from .Fv import FV
41 from .AprioriSection import AprioriSection
42 from .FfsInfStatement import FfsInfStatement
43 from .FfsFileStatement import FileStatement
44 from .VerSection import VerSection
45 from .UiSection import UiSection
46 from .FvImageSection import FvImageSection
47 from .DataSection import DataSection
48 from .DepexSection import DepexSection
49 from .CompressSection import CompressSection
50 from .GuidSection import GuidSection
51 from .Capsule import EFI_CERT_TYPE_PKCS7_GUID, EFI_CERT_TYPE_RSA2048_SHA256_GUID, Capsule
52 from .CapsuleData import CapsuleFfs, CapsulePayload, CapsuleFv, CapsuleFd, CapsuleAnyFile, CapsuleAfile
53 from .RuleComplexFile import RuleComplexFile
54 from .RuleSimpleFile import RuleSimpleFile
55 from .EfiSection import EfiSection
56 from .OptionRom import OPTIONROM
57 from .OptRomInfStatement import OptRomInfStatement, OverrideAttribs
58 from .OptRomFileStatement import OptRomFileStatement
59 from .GenFdsGlobalVariable import GenFdsGlobalVariable
60
61 T_CHAR_CR = '\r'
62 T_CHAR_TAB = '\t'
63 T_CHAR_DOUBLE_QUOTE = '\"'
64 T_CHAR_SINGLE_QUOTE = '\''
65 T_CHAR_BRACE_R = '}'
66
67 SEPARATORS = {TAB_EQUAL_SPLIT, TAB_VALUE_SPLIT, TAB_COMMA_SPLIT, '{', T_CHAR_BRACE_R}
68 ALIGNMENTS = {"Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K", "64K", "128K",
69 "256K", "512K", "1M", "2M", "4M", "8M", "16M"}
70 ALIGNMENT_NOAUTO = ALIGNMENTS - {"Auto"}
71 CR_LB_SET = {T_CHAR_CR, TAB_LINE_BREAK}
72
73 RegionSizePattern = compile("\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*")
74 RegionSizeGuidPattern = compile("\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*\|\s*(?P<size>\w+\.\w+[\.\w\[\]]*)\s*")
75 RegionOffsetPcdPattern = compile("\s*(?P<base>\w+\.\w+[\.\w\[\]]*)\s*$")
76 ShortcutPcdPattern = compile("\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*")
77 BaseAddrValuePattern = compile('^0[xX][0-9a-fA-F]+')
78 FileExtensionPattern = compile(r'([a-zA-Z][a-zA-Z0-9]*)')
79 TokenFindPattern = compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
80 AllIncludeFileList = []
81
82 # Get the closest parent
83 def GetParentAtLine (Line):
84 for Profile in AllIncludeFileList:
85 if Profile.IsLineInFile(Line):
86 return Profile
87 return None
88
89 # Check include loop
90 def IsValidInclude (File, Line):
91 for Profile in AllIncludeFileList:
92 if Profile.IsLineInFile(Line) and Profile.FileName == File:
93 return False
94
95 return True
96
97 def GetRealFileLine (File, Line):
98 InsertedLines = 0
99 for Profile in AllIncludeFileList:
100 if Profile.IsLineInFile(Line):
101 return Profile.GetLineInFile(Line)
102 elif Line >= Profile.InsertStartLineNumber and Profile.Level == 1:
103 InsertedLines += Profile.GetTotalLines()
104
105 return (File, Line - InsertedLines)
106
107 ## The exception class that used to report error messages when parsing FDF
108 #
109 # Currently the "ToolName" is set to be "FdfParser".
110 #
111 class Warning (Exception):
112 ## The constructor
113 #
114 # @param self The object pointer
115 # @param Str The message to record
116 # @param File The FDF name
117 # @param Line The Line number that error occurs
118 #
119 def __init__(self, Str, File = None, Line = None):
120 FileLineTuple = GetRealFileLine(File, Line)
121 self.FileName = FileLineTuple[0]
122 self.LineNumber = FileLineTuple[1]
123 self.OriginalLineNumber = Line
124 self.Message = Str
125 self.ToolName = 'FdfParser'
126
127 def __str__(self):
128 return self.Message
129
130 # helper functions to facilitate consistency in warnings
131 # each function is for a different common warning
132 @staticmethod
133 def Expected(Str, File, Line):
134 return Warning("expected {}".format(Str), File, Line)
135 @staticmethod
136 def ExpectedEquals(File, Line):
137 return Warning.Expected("'='", File, Line)
138 @staticmethod
139 def ExpectedCurlyOpen(File, Line):
140 return Warning.Expected("'{'", File, Line)
141 @staticmethod
142 def ExpectedCurlyClose(File, Line):
143 return Warning.Expected("'}'", File, Line)
144 @staticmethod
145 def ExpectedBracketClose(File, Line):
146 return Warning.Expected("']'", File, Line)
147
148 ## The Include file content class that used to record file data when parsing include file
149 #
150 # May raise Exception when opening file.
151 #
152 class IncludeFileProfile:
153 ## The constructor
154 #
155 # @param self The object pointer
156 # @param FileName The file that to be parsed
157 #
158 def __init__(self, FileName):
159 self.FileName = FileName
160 self.FileLinesList = []
161 try:
162 with open(FileName, "r") as fsock:
163 self.FileLinesList = fsock.readlines()
164 for index, line in enumerate(self.FileLinesList):
165 if not line.endswith(TAB_LINE_BREAK):
166 self.FileLinesList[index] += TAB_LINE_BREAK
167 except:
168 EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
169
170 self.InsertStartLineNumber = None
171 self.InsertAdjust = 0
172 self.IncludeFileList = []
173 self.Level = 1 # first level include file
174
175 def GetTotalLines(self):
176 TotalLines = self.InsertAdjust + len(self.FileLinesList)
177
178 for Profile in self.IncludeFileList:
179 TotalLines += Profile.GetTotalLines()
180
181 return TotalLines
182
183 def IsLineInFile(self, Line):
184 if Line >= self.InsertStartLineNumber and Line < self.InsertStartLineNumber + self.GetTotalLines():
185 return True
186
187 return False
188
189 def GetLineInFile(self, Line):
190 if not self.IsLineInFile (Line):
191 return (self.FileName, -1)
192
193 InsertedLines = self.InsertStartLineNumber
194
195 for Profile in self.IncludeFileList:
196 if Profile.IsLineInFile(Line):
197 return Profile.GetLineInFile(Line)
198 elif Line >= Profile.InsertStartLineNumber:
199 InsertedLines += Profile.GetTotalLines()
200
201 return (self.FileName, Line - InsertedLines + 1)
202
203 ## The FDF content class that used to record file data when parsing FDF
204 #
205 # May raise Exception when opening file.
206 #
207 class FileProfile:
208 ## The constructor
209 #
210 # @param self The object pointer
211 # @param FileName The file that to be parsed
212 #
213 def __init__(self, FileName):
214 self.FileLinesList = []
215 try:
216 with open(FileName, "r") as fsock:
217 self.FileLinesList = fsock.readlines()
218
219 except:
220 EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
221
222 self.FileName = FileName
223 self.PcdDict = OrderedDict()
224 self.PcdLocalDict = OrderedDict()
225 self.InfList = []
226 self.InfDict = {'ArchTBD':[]}
227 # ECC will use this Dict and List information
228 self.PcdFileLineDict = {}
229 self.InfFileLineList = []
230
231 self.FdDict = {}
232 self.FdNameNotSet = False
233 self.FvDict = {}
234 self.CapsuleDict = {}
235 self.RuleDict = {}
236 self.OptRomDict = {}
237 self.FmpPayloadDict = {}
238
239 ## The syntax parser for FDF
240 #
241 # PreprocessFile method should be called prior to ParseFile
242 # CycleReferenceCheck method can detect cycles in FDF contents
243 #
244 # GetNext*** procedures mean these procedures will get next token first, then make judgement.
245 # Get*** procedures mean these procedures will make judgement on current token only.
246 #
247 class FdfParser:
248 ## The constructor
249 #
250 # @param self The object pointer
251 # @param FileName The file that to be parsed
252 #
253 def __init__(self, FileName):
254 self.Profile = FileProfile(FileName)
255 self.FileName = FileName
256 self.CurrentLineNumber = 1
257 self.CurrentOffsetWithinLine = 0
258 self.CurrentFdName = None
259 self.CurrentFvName = None
260 self._Token = ""
261 self._SkippedChars = ""
262 GlobalData.gFdfParser = self
263
264 # Used to section info
265 self._CurSection = []
266 # Key: [section name, UI name, arch]
267 # Value: {MACRO_NAME: MACRO_VALUE}
268 self._MacroDict = tdict(True, 3)
269 self._PcdDict = OrderedDict()
270
271 self._WipeOffArea = []
272 if GenFdsGlobalVariable.WorkSpaceDir == '':
273 GenFdsGlobalVariable.WorkSpaceDir = os.getenv("WORKSPACE")
274
275 ## _SkipWhiteSpace() method
276 #
277 # Skip white spaces from current char.
278 #
279 # @param self The object pointer
280 #
281 def _SkipWhiteSpace(self):
282 while not self._EndOfFile():
283 if self._CurrentChar() in {TAB_PRINTCHAR_NUL, T_CHAR_CR, TAB_LINE_BREAK, TAB_SPACE_SPLIT, T_CHAR_TAB}:
284 self._SkippedChars += str(self._CurrentChar())
285 self._GetOneChar()
286 else:
287 return
288 return
289
290 ## _EndOfFile() method
291 #
292 # Judge current buffer pos is at file end
293 #
294 # @param self The object pointer
295 # @retval True Current File buffer position is at file end
296 # @retval False Current File buffer position is NOT at file end
297 #
298 def _EndOfFile(self):
299 NumberOfLines = len(self.Profile.FileLinesList)
300 SizeOfLastLine = len(self.Profile.FileLinesList[-1])
301 if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1:
302 return True
303 if self.CurrentLineNumber > NumberOfLines:
304 return True
305 return False
306
307 ## _EndOfLine() method
308 #
309 # Judge current buffer pos is at line end
310 #
311 # @param self The object pointer
312 # @retval True Current File buffer position is at line end
313 # @retval False Current File buffer position is NOT at line end
314 #
315 def _EndOfLine(self):
316 if self.CurrentLineNumber > len(self.Profile.FileLinesList):
317 return True
318 SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
319 if self.CurrentOffsetWithinLine >= SizeOfCurrentLine:
320 return True
321 return False
322
323 ## Rewind() method
324 #
325 # Reset file data buffer to the initial state
326 #
327 # @param self The object pointer
328 # @param DestLine Optional new destination line number.
329 # @param DestOffset Optional new destination offset.
330 #
331 def Rewind(self, DestLine = 1, DestOffset = 0):
332 self.CurrentLineNumber = DestLine
333 self.CurrentOffsetWithinLine = DestOffset
334
335 ## _UndoOneChar() method
336 #
337 # Go back one char in the file buffer
338 #
339 # @param self The object pointer
340 # @retval True Successfully go back one char
341 # @retval False Not able to go back one char as file beginning reached
342 #
343 def _UndoOneChar(self):
344 if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0:
345 return False
346 elif self.CurrentOffsetWithinLine == 0:
347 self.CurrentLineNumber -= 1
348 self.CurrentOffsetWithinLine = len(self._CurrentLine()) - 1
349 else:
350 self.CurrentOffsetWithinLine -= 1
351 return True
352
353 ## _GetOneChar() method
354 #
355 # Move forward one char in the file buffer
356 #
357 # @param self The object pointer
358 #
359 def _GetOneChar(self):
360 if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
361 self.CurrentLineNumber += 1
362 self.CurrentOffsetWithinLine = 0
363 else:
364 self.CurrentOffsetWithinLine += 1
365
366 ## _CurrentChar() method
367 #
368 # Get the char pointed to by the file buffer pointer
369 #
370 # @param self The object pointer
371 # @retval Char Current char
372 #
373 def _CurrentChar(self):
374 return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine]
375
376 ## _NextChar() method
377 #
378 # Get the one char pass the char pointed to by the file buffer pointer
379 #
380 # @param self The object pointer
381 # @retval Char Next char
382 #
383 def _NextChar(self):
384 if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
385 return self.Profile.FileLinesList[self.CurrentLineNumber][0]
386 return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1]
387
388 ## _SetCurrentCharValue() method
389 #
390 # Modify the value of current char
391 #
392 # @param self The object pointer
393 # @param Value The new value of current char
394 #
395 def _SetCurrentCharValue(self, Value):
396 self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value
397
398 ## _CurrentLine() method
399 #
400 # Get the list that contains current line contents
401 #
402 # @param self The object pointer
403 # @retval List current line contents
404 #
405 def _CurrentLine(self):
406 return self.Profile.FileLinesList[self.CurrentLineNumber - 1]
407
408 def _StringToList(self):
409 self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList]
410 if not self.Profile.FileLinesList:
411 EdkLogger.error('FdfParser', FILE_READ_FAILURE, 'The file is empty!', File=self.FileName)
412 self.Profile.FileLinesList[-1].append(' ')
413
414 def _ReplaceFragment(self, StartPos, EndPos, Value = ' '):
415 if StartPos[0] == EndPos[0]:
416 Offset = StartPos[1]
417 while Offset <= EndPos[1]:
418 self.Profile.FileLinesList[StartPos[0]][Offset] = Value
419 Offset += 1
420 return
421
422 Offset = StartPos[1]
423 while self.Profile.FileLinesList[StartPos[0]][Offset] not in CR_LB_SET:
424 self.Profile.FileLinesList[StartPos[0]][Offset] = Value
425 Offset += 1
426
427 Line = StartPos[0]
428 while Line < EndPos[0]:
429 Offset = 0
430 while self.Profile.FileLinesList[Line][Offset] not in CR_LB_SET:
431 self.Profile.FileLinesList[Line][Offset] = Value
432 Offset += 1
433 Line += 1
434
435 Offset = 0
436 while Offset <= EndPos[1]:
437 self.Profile.FileLinesList[EndPos[0]][Offset] = Value
438 Offset += 1
439
440 def _SetMacroValue(self, Macro, Value):
441 if not self._CurSection:
442 return
443
444 MacroDict = {}
445 if not self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]]:
446 self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]] = MacroDict
447 else:
448 MacroDict = self._MacroDict[self._CurSection[0], self._CurSection[1], self._CurSection[2]]
449 MacroDict[Macro] = Value
450
451 def _GetMacroValue(self, Macro):
452 # Highest priority
453 if Macro in GlobalData.gCommandLineDefines:
454 return GlobalData.gCommandLineDefines[Macro]
455 if Macro in GlobalData.gGlobalDefines:
456 return GlobalData.gGlobalDefines[Macro]
457
458 if self._CurSection:
459 MacroDict = self._MacroDict[
460 self._CurSection[0],
461 self._CurSection[1],
462 self._CurSection[2]
463 ]
464 if MacroDict and Macro in MacroDict:
465 return MacroDict[Macro]
466
467 # Lowest priority
468 if Macro in GlobalData.gPlatformDefines:
469 return GlobalData.gPlatformDefines[Macro]
470 return None
471
472 def _SectionHeaderParser(self, Section):
473 # [Defines]
474 # [FD.UiName]: use dummy instead if UI name is optional
475 # [FV.UiName]
476 # [Capsule.UiName]
477 # [Rule]: don't take rule section into account, macro is not allowed in this section
478 # [OptionRom.DriverName]
479 self._CurSection = []
480 Section = Section.strip()[1:-1].upper().replace(' ', '').strip(TAB_SPLIT)
481 ItemList = Section.split(TAB_SPLIT)
482 Item = ItemList[0]
483 if Item == '' or Item == 'RULE':
484 return
485
486 if Item == TAB_COMMON_DEFINES.upper():
487 self._CurSection = [TAB_COMMON, TAB_COMMON, TAB_COMMON]
488 elif len(ItemList) > 1:
489 self._CurSection = [ItemList[0], ItemList[1], TAB_COMMON]
490 elif len(ItemList) > 0:
491 self._CurSection = [ItemList[0], 'DUMMY', TAB_COMMON]
492
493 ## PreprocessFile() method
494 #
495 # Preprocess file contents, replace comments with spaces.
496 # In the end, rewind the file buffer pointer to the beginning
497 # BUGBUG: No !include statement processing contained in this procedure
498 # !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1]
499 #
500 # @param self The object pointer
501 #
502 def PreprocessFile(self):
503 self.Rewind()
504 InComment = False
505 DoubleSlashComment = False
506 HashComment = False
507 # HashComment in quoted string " " is ignored.
508 InString = False
509
510 while not self._EndOfFile():
511
512 if self._CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment:
513 InString = not InString
514 # meet new line, then no longer in a comment for // and '#'
515 if self._CurrentChar() == TAB_LINE_BREAK:
516 self.CurrentLineNumber += 1
517 self.CurrentOffsetWithinLine = 0
518 if InComment and DoubleSlashComment:
519 InComment = False
520 DoubleSlashComment = False
521 if InComment and HashComment:
522 InComment = False
523 HashComment = False
524 # check for */ comment end
525 elif InComment and not DoubleSlashComment and not HashComment and self._CurrentChar() == TAB_STAR and self._NextChar() == TAB_BACK_SLASH:
526 self._SetCurrentCharValue(TAB_SPACE_SPLIT)
527 self._GetOneChar()
528 self._SetCurrentCharValue(TAB_SPACE_SPLIT)
529 self._GetOneChar()
530 InComment = False
531 # set comments to spaces
532 elif InComment:
533 self._SetCurrentCharValue(TAB_SPACE_SPLIT)
534 self._GetOneChar()
535 # check for // comment
536 elif self._CurrentChar() == TAB_BACK_SLASH and self._NextChar() == TAB_BACK_SLASH and not self._EndOfLine():
537 InComment = True
538 DoubleSlashComment = True
539 # check for '#' comment
540 elif self._CurrentChar() == TAB_COMMENT_SPLIT and not self._EndOfLine() and not InString:
541 InComment = True
542 HashComment = True
543 # check for /* comment start
544 elif self._CurrentChar() == TAB_BACK_SLASH and self._NextChar() == TAB_STAR:
545 self._SetCurrentCharValue(TAB_SPACE_SPLIT)
546 self._GetOneChar()
547 self._SetCurrentCharValue(TAB_SPACE_SPLIT)
548 self._GetOneChar()
549 InComment = True
550 else:
551 self._GetOneChar()
552
553 # restore from ListOfList to ListOfString
554 self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
555 self.Rewind()
556
557 ## PreprocessIncludeFile() method
558 #
559 # Preprocess file contents, replace !include statements with file contents.
560 # In the end, rewind the file buffer pointer to the beginning
561 #
562 # @param self The object pointer
563 #
564 def PreprocessIncludeFile(self):
565 # nested include support
566 Processed = False
567 MacroDict = {}
568 while self._GetNextToken():
569
570 if self._Token == TAB_DEFINE:
571 if not self._GetNextToken():
572 raise Warning.Expected("Macro name", self.FileName, self.CurrentLineNumber)
573 Macro = self._Token
574 if not self._IsToken(TAB_EQUAL_SPLIT):
575 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
576 Value = self._GetExpression()
577 MacroDict[Macro] = Value
578
579 elif self._Token == TAB_INCLUDE:
580 Processed = True
581 IncludeLine = self.CurrentLineNumber
582 IncludeOffset = self.CurrentOffsetWithinLine - len(TAB_INCLUDE)
583 if not self._GetNextToken():
584 raise Warning.Expected("include file name", self.FileName, self.CurrentLineNumber)
585 IncFileName = self._Token
586 PreIndex = 0
587 StartPos = IncFileName.find('$(', PreIndex)
588 EndPos = IncFileName.find(')', StartPos+2)
589 while StartPos != -1 and EndPos != -1:
590 Macro = IncFileName[StartPos+2: EndPos]
591 MacroVal = self._GetMacroValue(Macro)
592 if not MacroVal:
593 if Macro in MacroDict:
594 MacroVal = MacroDict[Macro]
595 if MacroVal is not None:
596 IncFileName = IncFileName.replace('$(' + Macro + ')', MacroVal, 1)
597 if MacroVal.find('$(') != -1:
598 PreIndex = StartPos
599 else:
600 PreIndex = StartPos + len(MacroVal)
601 else:
602 raise Warning("The Macro %s is not defined" %Macro, self.FileName, self.CurrentLineNumber)
603 StartPos = IncFileName.find('$(', PreIndex)
604 EndPos = IncFileName.find(')', StartPos+2)
605
606 IncludedFile = NormPath(IncFileName)
607 #
608 # First search the include file under the same directory as FDF file
609 #
610 IncludedFile1 = PathClass(IncludedFile, os.path.dirname(self.FileName))
611 ErrorCode = IncludedFile1.Validate()[0]
612 if ErrorCode != 0:
613 #
614 # Then search the include file under the same directory as DSC file
615 #
616 PlatformDir = ''
617 if GenFdsGlobalVariable.ActivePlatform:
618 PlatformDir = GenFdsGlobalVariable.ActivePlatform.Dir
619 elif GlobalData.gActivePlatform:
620 PlatformDir = GlobalData.gActivePlatform.MetaFile.Dir
621 IncludedFile1 = PathClass(IncludedFile, PlatformDir)
622 ErrorCode = IncludedFile1.Validate()[0]
623 if ErrorCode != 0:
624 #
625 # Also search file under the WORKSPACE directory
626 #
627 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
628 ErrorCode = IncludedFile1.Validate()[0]
629 if ErrorCode != 0:
630 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),
631 self.FileName, self.CurrentLineNumber)
632
633 if not IsValidInclude (IncludedFile1.Path, self.CurrentLineNumber):
634 raise Warning("The include file {0} is causing a include loop.\n".format (IncludedFile1.Path), self.FileName, self.CurrentLineNumber)
635
636 IncFileProfile = IncludeFileProfile(IncludedFile1.Path)
637
638 CurrentLine = self.CurrentLineNumber
639 CurrentOffset = self.CurrentOffsetWithinLine
640 # list index of the insertion, note that line number is 'CurrentLine + 1'
641 InsertAtLine = CurrentLine
642 ParentProfile = GetParentAtLine (CurrentLine)
643 if ParentProfile is not None:
644 ParentProfile.IncludeFileList.insert(0, IncFileProfile)
645 IncFileProfile.Level = ParentProfile.Level + 1
646 IncFileProfile.InsertStartLineNumber = InsertAtLine + 1
647 # deal with remaining portions after "!include filename", if exists.
648 if self._GetNextToken():
649 if self.CurrentLineNumber == CurrentLine:
650 RemainingLine = self._CurrentLine()[CurrentOffset:]
651 self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine)
652 IncFileProfile.InsertAdjust += 1
653 self.CurrentLineNumber += 1
654 self.CurrentOffsetWithinLine = 0
655
656 for Line in IncFileProfile.FileLinesList:
657 self.Profile.FileLinesList.insert(InsertAtLine, Line)
658 self.CurrentLineNumber += 1
659 InsertAtLine += 1
660
661 # reversely sorted to better determine error in file
662 AllIncludeFileList.insert(0, IncFileProfile)
663
664 # comment out the processed include file statement
665 TempList = list(self.Profile.FileLinesList[IncludeLine - 1])
666 TempList.insert(IncludeOffset, TAB_COMMENT_SPLIT)
667 self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList)
668 if Processed: # Nested and back-to-back support
669 self.Rewind(DestLine = IncFileProfile.InsertStartLineNumber - 1)
670 Processed = False
671 # Preprocess done.
672 self.Rewind()
673
674 @staticmethod
675 def _GetIfListCurrentItemStat(IfList):
676 if len(IfList) == 0:
677 return True
678
679 for Item in IfList:
680 if Item[1] == False:
681 return False
682
683 return True
684
685 ## PreprocessConditionalStatement() method
686 #
687 # Preprocess conditional statement.
688 # In the end, rewind the file buffer pointer to the beginning
689 #
690 # @param self The object pointer
691 #
692 def PreprocessConditionalStatement(self):
693 # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined]
694 IfList = []
695 RegionLayoutLine = 0
696 ReplacedLine = -1
697 while self._GetNextToken():
698 # Determine section name and the location dependent macro
699 if self._GetIfListCurrentItemStat(IfList):
700 if self._Token.startswith(TAB_SECTION_START):
701 Header = self._Token
702 if not self._Token.endswith(TAB_SECTION_END):
703 self._SkipToToken(TAB_SECTION_END)
704 Header += self._SkippedChars
705 if Header.find('$(') != -1:
706 raise Warning("macro cannot be used in section header", self.FileName, self.CurrentLineNumber)
707 self._SectionHeaderParser(Header)
708 continue
709 # Replace macros except in RULE section or out of section
710 elif self._CurSection and ReplacedLine != self.CurrentLineNumber:
711 ReplacedLine = self.CurrentLineNumber
712 self._UndoToken()
713 CurLine = self.Profile.FileLinesList[ReplacedLine - 1]
714 PreIndex = 0
715 StartPos = CurLine.find('$(', PreIndex)
716 EndPos = CurLine.find(')', StartPos+2)
717 while StartPos != -1 and EndPos != -1 and self._Token not in {TAB_IF_DEF, TAB_IF_N_DEF, TAB_IF, TAB_ELSE_IF}:
718 MacroName = CurLine[StartPos+2: EndPos]
719 MacorValue = self._GetMacroValue(MacroName)
720 if MacorValue is not None:
721 CurLine = CurLine.replace('$(' + MacroName + ')', MacorValue, 1)
722 if MacorValue.find('$(') != -1:
723 PreIndex = StartPos
724 else:
725 PreIndex = StartPos + len(MacorValue)
726 else:
727 PreIndex = EndPos + 1
728 StartPos = CurLine.find('$(', PreIndex)
729 EndPos = CurLine.find(')', StartPos+2)
730 self.Profile.FileLinesList[ReplacedLine - 1] = CurLine
731 continue
732
733 if self._Token == TAB_DEFINE:
734 if self._GetIfListCurrentItemStat(IfList):
735 if not self._CurSection:
736 raise Warning("macro cannot be defined in Rule section or out of section", self.FileName, self.CurrentLineNumber)
737 DefineLine = self.CurrentLineNumber - 1
738 DefineOffset = self.CurrentOffsetWithinLine - len(TAB_DEFINE)
739 if not self._GetNextToken():
740 raise Warning.Expected("Macro name", self.FileName, self.CurrentLineNumber)
741 Macro = self._Token
742 if not self._IsToken(TAB_EQUAL_SPLIT):
743 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
744
745 Value = self._GetExpression()
746 self._SetMacroValue(Macro, Value)
747 self._WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
748 elif self._Token == 'SET':
749 if not self._GetIfListCurrentItemStat(IfList):
750 continue
751 SetLine = self.CurrentLineNumber - 1
752 SetOffset = self.CurrentOffsetWithinLine - len('SET')
753 PcdPair = self._GetNextPcdSettings()
754 PcdName = "%s.%s" % (PcdPair[1], PcdPair[0])
755 if not self._IsToken(TAB_EQUAL_SPLIT):
756 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
757
758 Value = self._GetExpression()
759 Value = self._EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
760
761 self._PcdDict[PcdName] = Value
762
763 self.Profile.PcdDict[PcdPair] = Value
764 self.SetPcdLocalation(PcdPair)
765 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
766 self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
767
768 self._WipeOffArea.append(((SetLine, SetOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
769 elif self._Token in {TAB_IF_DEF, TAB_IF_N_DEF, TAB_IF}:
770 IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self._Token))
771 IfList.append([IfStartPos, None, None])
772
773 CondLabel = self._Token
774 Expression = self._GetExpression()
775
776 if CondLabel == TAB_IF:
777 ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
778 else:
779 ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'in')
780 if CondLabel == TAB_IF_N_DEF:
781 ConditionSatisfied = not ConditionSatisfied
782
783 BranchDetermined = ConditionSatisfied
784 IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined]
785 if ConditionSatisfied:
786 self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
787 elif self._Token in {TAB_ELSE_IF, TAB_ELSE}:
788 ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self._Token))
789 if len(IfList) <= 0:
790 raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
791
792 if IfList[-1][1]:
793 IfList[-1] = [ElseStartPos, False, True]
794 self._WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
795 else:
796 self._WipeOffArea.append((IfList[-1][0], ElseStartPos))
797 IfList[-1] = [ElseStartPos, True, IfList[-1][2]]
798 if self._Token == TAB_ELSE_IF:
799 Expression = self._GetExpression()
800 ConditionSatisfied = self._EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
801 IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]]
802
803 if IfList[-1][1]:
804 if IfList[-1][2]:
805 IfList[-1][1] = False
806 else:
807 IfList[-1][2] = True
808 self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
809 elif self._Token == '!endif':
810 if len(IfList) <= 0:
811 raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
812 if IfList[-1][1]:
813 self._WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
814 else:
815 self._WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
816
817 IfList.pop()
818 elif not IfList: # Don't use PCDs inside conditional directive
819 if self.CurrentLineNumber <= RegionLayoutLine:
820 # Don't try the same line twice
821 continue
822 SetPcd = ShortcutPcdPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
823 if SetPcd:
824 self._PcdDict[SetPcd.group('name')] = SetPcd.group('value')
825 RegionLayoutLine = self.CurrentLineNumber
826 continue
827 RegionSize = RegionSizePattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
828 if not RegionSize:
829 RegionLayoutLine = self.CurrentLineNumber
830 continue
831 RegionSizeGuid = RegionSizeGuidPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber])
832 if not RegionSizeGuid:
833 RegionLayoutLine = self.CurrentLineNumber + 1
834 continue
835 self._PcdDict[RegionSizeGuid.group('base')] = RegionSize.group('base')
836 self._PcdDict[RegionSizeGuid.group('size')] = RegionSize.group('size')
837 RegionLayoutLine = self.CurrentLineNumber + 1
838
839 if IfList:
840 raise Warning("Missing !endif", self.FileName, self.CurrentLineNumber)
841 self.Rewind()
842
843 def _CollectMacroPcd(self):
844 MacroDict = {}
845
846 # PCD macro
847 MacroDict.update(GlobalData.gPlatformPcds)
848 MacroDict.update(self._PcdDict)
849
850 # Lowest priority
851 MacroDict.update(GlobalData.gPlatformDefines)
852
853 if self._CurSection:
854 # Defines macro
855 ScopeMacro = self._MacroDict[TAB_COMMON, TAB_COMMON, TAB_COMMON]
856 if ScopeMacro:
857 MacroDict.update(ScopeMacro)
858
859 # Section macro
860 ScopeMacro = self._MacroDict[
861 self._CurSection[0],
862 self._CurSection[1],
863 self._CurSection[2]
864 ]
865 if ScopeMacro:
866 MacroDict.update(ScopeMacro)
867
868 MacroDict.update(GlobalData.gGlobalDefines)
869 MacroDict.update(GlobalData.gCommandLineDefines)
870 for Item in GlobalData.BuildOptionPcd:
871 if isinstance(Item, tuple):
872 continue
873 PcdName, TmpValue = Item.split(TAB_EQUAL_SPLIT)
874 TmpValue = BuildOptionValue(TmpValue, {})
875 MacroDict[PcdName.strip()] = TmpValue
876 # Highest priority
877
878 return MacroDict
879
880 def _EvaluateConditional(self, Expression, Line, Op = None, Value = None):
881 MacroPcdDict = self._CollectMacroPcd()
882 if Op == 'eval':
883 try:
884 if Value:
885 return ValueExpression(Expression, MacroPcdDict)(True)
886 else:
887 return ValueExpression(Expression, MacroPcdDict)()
888 except WrnExpression as Excpt:
889 #
890 # Catch expression evaluation warning here. We need to report
891 # the precise number of line and return the evaluation result
892 #
893 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
894 File=self.FileName, ExtraData=self._CurrentLine(),
895 Line=Line)
896 return Excpt.result
897 except Exception as Excpt:
898 if hasattr(Excpt, 'Pcd'):
899 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
900 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
901 raise Warning("Cannot use this PCD (%s) in an expression as"
902 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
903 " of the DSC file (%s), and it is currently defined in this section:"
904 " %s, line #: %d." % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE'], Info[0], Info[1]),
905 self.FileName, Line)
906 else:
907 raise Warning("PCD (%s) is not defined in DSC file (%s)" % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE']),
908 self.FileName, Line)
909 else:
910 raise Warning(str(Excpt), self.FileName, Line)
911 else:
912 if Expression.startswith('$(') and Expression[-1] == ')':
913 Expression = Expression[2:-1]
914 return Expression in MacroPcdDict
915
916 ## _IsToken() method
917 #
918 # Check whether input string is found from current char position along
919 # If found, the string value is put into self._Token
920 #
921 # @param self The object pointer
922 # @param String The string to search
923 # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
924 # @retval True Successfully find string, file buffer pointer moved forward
925 # @retval False Not able to find string, file buffer pointer not changed
926 #
927 def _IsToken(self, String, IgnoreCase = False):
928 self._SkipWhiteSpace()
929
930 # Only consider the same line, no multi-line token allowed
931 StartPos = self.CurrentOffsetWithinLine
932 index = -1
933 if IgnoreCase:
934 index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(String.upper())
935 else:
936 index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(String)
937 if index == 0:
938 self.CurrentOffsetWithinLine += len(String)
939 self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
940 return True
941 return False
942
943 ## _IsKeyword() method
944 #
945 # Check whether input keyword is found from current char position along, whole word only!
946 # If found, the string value is put into self._Token
947 #
948 # @param self The object pointer
949 # @param Keyword The string to search
950 # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
951 # @retval True Successfully find string, file buffer pointer moved forward
952 # @retval False Not able to find string, file buffer pointer not changed
953 #
954 def _IsKeyword(self, KeyWord, IgnoreCase = False):
955 self._SkipWhiteSpace()
956
957 # Only consider the same line, no multi-line token allowed
958 StartPos = self.CurrentOffsetWithinLine
959 index = -1
960 if IgnoreCase:
961 index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(KeyWord.upper())
962 else:
963 index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(KeyWord)
964 if index == 0:
965 followingChar = self._CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)]
966 if not str(followingChar).isspace() and followingChar not in SEPARATORS:
967 return False
968 self.CurrentOffsetWithinLine += len(KeyWord)
969 self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
970 return True
971 return False
972
973 def _GetExpression(self):
974 Line = self.Profile.FileLinesList[self.CurrentLineNumber - 1]
975 Index = len(Line) - 1
976 while Line[Index] in CR_LB_SET:
977 Index -= 1
978 ExpressionString = self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:Index+1]
979 self.CurrentOffsetWithinLine += len(ExpressionString)
980 ExpressionString = ExpressionString.strip()
981 return ExpressionString
982
983 ## _GetNextWord() method
984 #
985 # Get next C name from file lines
986 # If found, the string value is put into self._Token
987 #
988 # @param self The object pointer
989 # @retval True Successfully find a C name string, file buffer pointer moved forward
990 # @retval False Not able to find a C name string, file buffer pointer not changed
991 #
992 def _GetNextWord(self):
993 self._SkipWhiteSpace()
994 if self._EndOfFile():
995 return False
996
997 TempChar = self._CurrentChar()
998 StartPos = self.CurrentOffsetWithinLine
999 if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_':
1000 self._GetOneChar()
1001 while not self._EndOfLine():
1002 TempChar = self._CurrentChar()
1003 if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
1004 or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-':
1005 self._GetOneChar()
1006
1007 else:
1008 break
1009
1010 self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
1011 return True
1012
1013 return False
1014
1015 def _GetNextPcdWord(self):
1016 self._SkipWhiteSpace()
1017 if self._EndOfFile():
1018 return False
1019
1020 TempChar = self._CurrentChar()
1021 StartPos = self.CurrentOffsetWithinLine
1022 if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_' or TempChar == TAB_SECTION_START or TempChar == TAB_SECTION_END:
1023 self._GetOneChar()
1024 while not self._EndOfLine():
1025 TempChar = self._CurrentChar()
1026 if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
1027 or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-' or TempChar == TAB_SECTION_START or TempChar == TAB_SECTION_END:
1028 self._GetOneChar()
1029
1030 else:
1031 break
1032
1033 self._Token = self._CurrentLine()[StartPos: self.CurrentOffsetWithinLine]
1034 return True
1035
1036 return False
1037
1038 ## _GetNextToken() method
1039 #
1040 # Get next token unit before a seperator
1041 # If found, the string value is put into self._Token
1042 #
1043 # @param self The object pointer
1044 # @retval True Successfully find a token unit, file buffer pointer moved forward
1045 # @retval False Not able to find a token unit, file buffer pointer not changed
1046 #
1047 def _GetNextToken(self):
1048 # Skip leading spaces, if exist.
1049 self._SkipWhiteSpace()
1050 if self._EndOfFile():
1051 return False
1052 # Record the token start position, the position of the first non-space char.
1053 StartPos = self.CurrentOffsetWithinLine
1054 StartLine = self.CurrentLineNumber
1055 while StartLine == self.CurrentLineNumber:
1056 TempChar = self._CurrentChar()
1057 # Try to find the end char that is not a space and not in seperator tuple.
1058 # That is, when we got a space or any char in the tuple, we got the end of token.
1059 if not str(TempChar).isspace() and TempChar not in SEPARATORS:
1060 self._GetOneChar()
1061 # if we happen to meet a seperator as the first char, we must proceed to get it.
1062 # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
1063 elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPARATORS:
1064 self._GetOneChar()
1065 break
1066 else:
1067 break
1068 # else:
1069 # return False
1070
1071 EndPos = self.CurrentOffsetWithinLine
1072 if self.CurrentLineNumber != StartLine:
1073 EndPos = len(self.Profile.FileLinesList[StartLine-1])
1074 self._Token = self.Profile.FileLinesList[StartLine-1][StartPos: EndPos]
1075 if self._Token.lower() in {TAB_IF, TAB_END_IF, TAB_ELSE_IF, TAB_ELSE, TAB_IF_DEF, TAB_IF_N_DEF, TAB_ERROR, TAB_INCLUDE}:
1076 self._Token = self._Token.lower()
1077 if StartPos != self.CurrentOffsetWithinLine:
1078 return True
1079 else:
1080 return False
1081
1082 ## _GetNextGuid() method
1083 #
1084 # Get next token unit before a seperator
1085 # If found, the GUID string is put into self._Token
1086 #
1087 # @param self The object pointer
1088 # @retval True Successfully find a registry format GUID, file buffer pointer moved forward
1089 # @retval False Not able to find a registry format GUID, file buffer pointer not changed
1090 #
1091 def _GetNextGuid(self):
1092 if not self._GetNextToken():
1093 return False
1094 if GlobalData.gGuidPattern.match(self._Token) is not None:
1095 return True
1096 else:
1097 self._UndoToken()
1098 return False
1099
1100 @staticmethod
1101 def _Verify(Name, Value, Scope):
1102 # value verification only applies to numeric values.
1103 if Scope not in TAB_PCD_NUMERIC_TYPES:
1104 return
1105
1106 ValueNumber = 0
1107 try:
1108 ValueNumber = int(Value, 0)
1109 except:
1110 EdkLogger.error("FdfParser", FORMAT_INVALID, "The value is not valid dec or hex number for %s." % Name)
1111 if ValueNumber < 0:
1112 EdkLogger.error("FdfParser", FORMAT_INVALID, "The value can't be set to negative value for %s." % Name)
1113 if ValueNumber > MAX_VAL_TYPE[Scope]:
1114 EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)
1115 return True
1116
1117 ## _UndoToken() method
1118 #
1119 # Go back one token unit in file buffer
1120 #
1121 # @param self The object pointer
1122 #
1123 def _UndoToken(self):
1124 self._UndoOneChar()
1125 while self._CurrentChar().isspace():
1126 if not self._UndoOneChar():
1127 self._GetOneChar()
1128 return
1129
1130
1131 StartPos = self.CurrentOffsetWithinLine
1132 CurrentLine = self.CurrentLineNumber
1133 while CurrentLine == self.CurrentLineNumber:
1134
1135 TempChar = self._CurrentChar()
1136 # Try to find the end char that is not a space and not in seperator tuple.
1137 # That is, when we got a space or any char in the tuple, we got the end of token.
1138 if not str(TempChar).isspace() and not TempChar in SEPARATORS:
1139 if not self._UndoOneChar():
1140 return
1141 # if we happen to meet a seperator as the first char, we must proceed to get it.
1142 # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
1143 elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPARATORS:
1144 return
1145 else:
1146 break
1147
1148 self._GetOneChar()
1149
1150 ## _GetNextHexNumber() method
1151 #
1152 # Get next HEX data before a seperator
1153 # If found, the HEX data is put into self._Token
1154 #
1155 # @param self The object pointer
1156 # @retval True Successfully find a HEX data, file buffer pointer moved forward
1157 # @retval False Not able to find a HEX data, file buffer pointer not changed
1158 #
1159 def _GetNextHexNumber(self):
1160 if not self._GetNextToken():
1161 return False
1162 if GlobalData.gHexPatternAll.match(self._Token):
1163 return True
1164 else:
1165 self._UndoToken()
1166 return False
1167
1168 ## _GetNextDecimalNumber() method
1169 #
1170 # Get next decimal data before a seperator
1171 # If found, the decimal data is put into self._Token
1172 #
1173 # @param self The object pointer
1174 # @retval True Successfully find a decimal data, file buffer pointer moved forward
1175 # @retval False Not able to find a decimal data, file buffer pointer not changed
1176 #
1177 def _GetNextDecimalNumber(self):
1178 if not self._GetNextToken():
1179 return False
1180 if self._Token.isdigit():
1181 return True
1182 else:
1183 self._UndoToken()
1184 return False
1185
1186 def _GetNextPcdSettings(self):
1187 if not self._GetNextWord():
1188 raise Warning.Expected("<PcdTokenSpaceCName>", self.FileName, self.CurrentLineNumber)
1189 pcdTokenSpaceCName = self._Token
1190
1191 if not self._IsToken(TAB_SPLIT):
1192 raise Warning.Expected(".", self.FileName, self.CurrentLineNumber)
1193
1194 if not self._GetNextWord():
1195 raise Warning.Expected("<PcdCName>", self.FileName, self.CurrentLineNumber)
1196 pcdCName = self._Token
1197
1198 Fields = []
1199 while self._IsToken(TAB_SPLIT):
1200 if not self._GetNextPcdWord():
1201 raise Warning.Expected("Pcd Fields", self.FileName, self.CurrentLineNumber)
1202 Fields.append(self._Token)
1203
1204 return (pcdCName, pcdTokenSpaceCName,TAB_SPLIT.join(Fields))
1205
1206 ## _GetStringData() method
1207 #
1208 # Get string contents quoted in ""
1209 # If found, the decimal data is put into self._Token
1210 #
1211 # @param self The object pointer
1212 # @retval True Successfully find a string data, file buffer pointer moved forward
1213 # @retval False Not able to find a string data, file buffer pointer not changed
1214 #
1215 def _GetStringData(self):
1216 QuoteToUse = None
1217 if self._Token.startswith(T_CHAR_DOUBLE_QUOTE) or self._Token.startswith("L\""):
1218 QuoteToUse = T_CHAR_DOUBLE_QUOTE
1219 elif self._Token.startswith(T_CHAR_SINGLE_QUOTE) or self._Token.startswith("L\'"):
1220 QuoteToUse = T_CHAR_SINGLE_QUOTE
1221 else:
1222 return False
1223
1224 self._UndoToken()
1225 self._SkipToToken(QuoteToUse)
1226 currentLineNumber = self.CurrentLineNumber
1227
1228 if not self._SkipToToken(QuoteToUse):
1229 raise Warning(QuoteToUse, self.FileName, self.CurrentLineNumber)
1230 if currentLineNumber != self.CurrentLineNumber:
1231 raise Warning(QuoteToUse, self.FileName, self.CurrentLineNumber)
1232 self._Token = self._SkippedChars.rstrip(QuoteToUse)
1233 return True
1234
1235 ## _SkipToToken() method
1236 #
1237 # Search forward in file buffer for the string
1238 # The skipped chars are put into self._SkippedChars
1239 #
1240 # @param self The object pointer
1241 # @param String The string to search
1242 # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
1243 # @retval True Successfully find the string, file buffer pointer moved forward
1244 # @retval False Not able to find the string, file buffer pointer not changed
1245 #
1246 def _SkipToToken(self, String, IgnoreCase = False):
1247 StartPos = self.GetFileBufferPos()
1248
1249 self._SkippedChars = ""
1250 while not self._EndOfFile():
1251 index = -1
1252 if IgnoreCase:
1253 index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].upper().find(String.upper())
1254 else:
1255 index = self._CurrentLine()[self.CurrentOffsetWithinLine: ].find(String)
1256 if index == 0:
1257 self.CurrentOffsetWithinLine += len(String)
1258 self._SkippedChars += String
1259 return True
1260 self._SkippedChars += str(self._CurrentChar())
1261 self._GetOneChar()
1262
1263 self.SetFileBufferPos(StartPos)
1264 self._SkippedChars = ""
1265 return False
1266
1267 ## GetFileBufferPos() method
1268 #
1269 # Return the tuple of current line and offset within the line
1270 #
1271 # @param self The object pointer
1272 # @retval Tuple Line number and offset pair
1273 #
1274 def GetFileBufferPos(self):
1275 return (self.CurrentLineNumber, self.CurrentOffsetWithinLine)
1276
1277 ## SetFileBufferPos() method
1278 #
1279 # Restore the file buffer position
1280 #
1281 # @param self The object pointer
1282 # @param Pos The new file buffer position
1283 #
1284 def SetFileBufferPos(self, Pos):
1285 (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos
1286
1287 ## Preprocess() method
1288 #
1289 # Preprocess comment, conditional directive, include directive, replace macro.
1290 # Exception will be raised if syntax error found
1291 #
1292 # @param self The object pointer
1293 #
1294 def Preprocess(self):
1295 self._StringToList()
1296 self.PreprocessFile()
1297 self.PreprocessIncludeFile()
1298 self._StringToList()
1299 self.PreprocessFile()
1300 self.PreprocessConditionalStatement()
1301 self._StringToList()
1302 for Pos in self._WipeOffArea:
1303 self._ReplaceFragment(Pos[0], Pos[1])
1304 self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
1305
1306 while self._GetDefines():
1307 pass
1308
1309 ## ParseFile() method
1310 #
1311 # Parse the file profile buffer to extract fd, fv ... information
1312 # Exception will be raised if syntax error found
1313 #
1314 # @param self The object pointer
1315 #
1316 def ParseFile(self):
1317 try:
1318 self.Preprocess()
1319 self._GetError()
1320 #
1321 # Keep processing sections of the FDF until no new sections or a syntax error is found
1322 #
1323 while self._GetFd() or self._GetFv() or self._GetFmp() or self._GetCapsule() or self._GetRule() or self._GetOptionRom():
1324 pass
1325
1326 except Warning as X:
1327 self._UndoToken()
1328 #'\n\tGot Token: \"%s\" from File %s\n' % (self._Token, FileLineTuple[0]) + \
1329 # At this point, the closest parent would be the included file itself
1330 Profile = GetParentAtLine(X.OriginalLineNumber)
1331 if Profile is not None:
1332 X.Message += ' near line %d, column %d: %s' \
1333 % (X.LineNumber, 0, Profile.FileLinesList[X.LineNumber-1])
1334 else:
1335 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1336 X.Message += ' near line %d, column %d: %s' \
1337 % (FileLineTuple[1], self.CurrentOffsetWithinLine + 1, self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:].rstrip(TAB_LINE_BREAK).rstrip(T_CHAR_CR))
1338 raise
1339
1340 ## SectionParser() method
1341 #
1342 # Parse the file section info
1343 # Exception will be raised if syntax error found
1344 #
1345 # @param self The object pointer
1346 # @param section The section string
1347
1348 def SectionParser(self, section):
1349 S = section.upper()
1350 if not S.startswith("[DEFINES") and not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \
1351 and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM.") and not S.startswith('[FMPPAYLOAD.'):
1352 raise Warning("Unknown section or section appear sequence error (The correct sequence should be [DEFINES], [FD.], [FV.], [Capsule.], [Rule.], [OptionRom.], [FMPPAYLOAD.])", self.FileName, self.CurrentLineNumber)
1353
1354 ## _GetDefines() method
1355 #
1356 # Get Defines section contents and store its data into AllMacrosList
1357 #
1358 # @param self The object pointer
1359 # @retval True Successfully find a Defines
1360 # @retval False Not able to find a Defines
1361 #
1362 def _GetDefines(self):
1363 if not self._GetNextToken():
1364 return False
1365
1366 S = self._Token.upper()
1367 if S.startswith(TAB_SECTION_START) and not S.startswith("[DEFINES"):
1368 self.SectionParser(S)
1369 self._UndoToken()
1370 return False
1371
1372 self._UndoToken()
1373 if not self._IsToken("[DEFINES", True):
1374 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1375 #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1376 # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1377 raise Warning.Expected("[DEFINES", self.FileName, self.CurrentLineNumber)
1378
1379 if not self._IsToken(TAB_SECTION_END):
1380 raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
1381
1382 while self._GetNextWord():
1383 # handle the SET statement
1384 if self._Token == 'SET':
1385 self._UndoToken()
1386 self._GetSetStatement(None)
1387 continue
1388
1389 Macro = self._Token
1390
1391 if not self._IsToken(TAB_EQUAL_SPLIT):
1392 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1393 if not self._GetNextToken() or self._Token.startswith(TAB_SECTION_START):
1394 raise Warning.Expected("MACRO value", self.FileName, self.CurrentLineNumber)
1395 Value = self._Token
1396
1397 return False
1398
1399 ##_GetError() method
1400 def _GetError(self):
1401 #save the Current information
1402 CurrentLine = self.CurrentLineNumber
1403 CurrentOffset = self.CurrentOffsetWithinLine
1404 while self._GetNextToken():
1405 if self._Token == TAB_ERROR:
1406 EdkLogger.error('FdfParser', ERROR_STATEMENT, self._CurrentLine().replace(TAB_ERROR, '', 1), File=self.FileName, Line=self.CurrentLineNumber)
1407 self.CurrentLineNumber = CurrentLine
1408 self.CurrentOffsetWithinLine = CurrentOffset
1409
1410 ## _GetFd() method
1411 #
1412 # Get FD section contents and store its data into FD dictionary of self.Profile
1413 #
1414 # @param self The object pointer
1415 # @retval True Successfully find a FD
1416 # @retval False Not able to find a FD
1417 #
1418 def _GetFd(self):
1419 if not self._GetNextToken():
1420 return False
1421
1422 S = self._Token.upper()
1423 if S.startswith(TAB_SECTION_START) and not S.startswith("[FD."):
1424 if not S.startswith("[FV.") and not S.startswith('[FMPPAYLOAD.') and not S.startswith("[CAPSULE.") \
1425 and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
1426 raise Warning("Unknown section", self.FileName, self.CurrentLineNumber)
1427 self._UndoToken()
1428 return False
1429
1430 self._UndoToken()
1431 if not self._IsToken("[FD.", True):
1432 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1433 #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1434 # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1435 raise Warning.Expected("[FD.]", self.FileName, self.CurrentLineNumber)
1436
1437 FdName = self._GetUiName()
1438 if FdName == "":
1439 if len (self.Profile.FdDict) == 0:
1440 FdName = GenFdsGlobalVariable.PlatformName
1441 if FdName == "" and GlobalData.gActivePlatform:
1442 FdName = GlobalData.gActivePlatform.PlatformName
1443 self.Profile.FdNameNotSet = True
1444 else:
1445 raise Warning.Expected("FdName in [FD.] section", self.FileName, self.CurrentLineNumber)
1446 self.CurrentFdName = FdName.upper()
1447
1448 if self.CurrentFdName in self.Profile.FdDict:
1449 raise Warning("Unexpected the same FD name", self.FileName, self.CurrentLineNumber)
1450
1451 if not self._IsToken(TAB_SECTION_END):
1452 raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
1453
1454 FdObj = FD()
1455 FdObj.FdUiName = self.CurrentFdName
1456 self.Profile.FdDict[self.CurrentFdName] = FdObj
1457
1458 if len (self.Profile.FdDict) > 1 and self.Profile.FdNameNotSet:
1459 raise Warning.Expected("all FDs have their name", self.FileName, self.CurrentLineNumber)
1460
1461 Status = self._GetCreateFile(FdObj)
1462 if not Status:
1463 raise Warning("FD name error", self.FileName, self.CurrentLineNumber)
1464
1465 while self._GetTokenStatements(FdObj):
1466 pass
1467 for Attr in ("BaseAddress", "Size", "ErasePolarity"):
1468 if getattr(FdObj, Attr) is None:
1469 self._GetNextToken()
1470 raise Warning("Keyword %s missing" % Attr, self.FileName, self.CurrentLineNumber)
1471
1472 if not FdObj.BlockSizeList:
1473 FdObj.BlockSizeList.append((1, FdObj.Size, None))
1474
1475 self._GetDefineStatements(FdObj)
1476
1477 self._GetSetStatements(FdObj)
1478
1479 if not self._GetRegionLayout(FdObj):
1480 raise Warning.Expected("region layout", self.FileName, self.CurrentLineNumber)
1481
1482 while self._GetRegionLayout(FdObj):
1483 pass
1484 return True
1485
1486 ## _GetUiName() method
1487 #
1488 # Return the UI name of a section
1489 #
1490 # @param self The object pointer
1491 # @retval FdName UI name
1492 #
1493 def _GetUiName(self):
1494 Name = ""
1495 if self._GetNextWord():
1496 Name = self._Token
1497
1498 return Name
1499
1500 ## _GetCreateFile() method
1501 #
1502 # Return the output file name of object
1503 #
1504 # @param self The object pointer
1505 # @param Obj object whose data will be stored in file
1506 # @retval FdName UI name
1507 #
1508 def _GetCreateFile(self, Obj):
1509 if self._IsKeyword("CREATE_FILE"):
1510 if not self._IsToken(TAB_EQUAL_SPLIT):
1511 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1512
1513 if not self._GetNextToken():
1514 raise Warning.Expected("file name", self.FileName, self.CurrentLineNumber)
1515
1516 FileName = self._Token
1517 Obj.CreateFileName = FileName
1518
1519 return True
1520
1521 def SetPcdLocalation(self,pcdpair):
1522 self.Profile.PcdLocalDict[pcdpair] = (self.Profile.FileName,self.CurrentLineNumber)
1523
1524 ## _GetTokenStatements() method
1525 #
1526 # Get token statements
1527 #
1528 # @param self The object pointer
1529 # @param Obj for whom token statement is got
1530 #
1531 def _GetTokenStatements(self, Obj):
1532 if self._IsKeyword("BaseAddress"):
1533 if not self._IsToken(TAB_EQUAL_SPLIT):
1534 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1535
1536 if not self._GetNextHexNumber():
1537 raise Warning.Expected("Hex base address", self.FileName, self.CurrentLineNumber)
1538
1539 Obj.BaseAddress = self._Token
1540
1541 if self._IsToken(TAB_VALUE_SPLIT):
1542 pcdPair = self._GetNextPcdSettings()
1543 Obj.BaseAddressPcd = pcdPair
1544 self.Profile.PcdDict[pcdPair] = Obj.BaseAddress
1545 self.SetPcdLocalation(pcdPair)
1546 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1547 self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1548 return True
1549
1550 if self._IsKeyword("Size"):
1551 if not self._IsToken(TAB_EQUAL_SPLIT):
1552 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1553
1554 if not self._GetNextHexNumber():
1555 raise Warning.Expected("Hex size", self.FileName, self.CurrentLineNumber)
1556
1557 Size = self._Token
1558 if self._IsToken(TAB_VALUE_SPLIT):
1559 pcdPair = self._GetNextPcdSettings()
1560 Obj.SizePcd = pcdPair
1561 self.Profile.PcdDict[pcdPair] = Size
1562 self.SetPcdLocalation(pcdPair)
1563 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1564 self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1565 Obj.Size = int(Size, 0)
1566 return True
1567
1568 if self._IsKeyword("ErasePolarity"):
1569 if not self._IsToken(TAB_EQUAL_SPLIT):
1570 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1571
1572 if not self._GetNextToken():
1573 raise Warning.Expected("Erase Polarity", self.FileName, self.CurrentLineNumber)
1574
1575 if not self._Token in {"1", "0"}:
1576 raise Warning.Expected("1 or 0 Erase Polarity", self.FileName, self.CurrentLineNumber)
1577
1578 Obj.ErasePolarity = self._Token
1579 return True
1580
1581 return self._GetBlockStatements(Obj)
1582
1583 ## _GetAddressStatements() method
1584 #
1585 # Get address statements
1586 #
1587 # @param self The object pointer
1588 # @param Obj for whom address statement is got
1589 # @retval True Successfully find
1590 # @retval False Not able to find
1591 #
1592 def _GetAddressStatements(self, Obj):
1593 if self._IsKeyword("BsBaseAddress"):
1594 if not self._IsToken(TAB_EQUAL_SPLIT):
1595 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1596
1597 if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
1598 raise Warning.Expected("address", self.FileName, self.CurrentLineNumber)
1599
1600 BsAddress = int(self._Token, 0)
1601 Obj.BsBaseAddress = BsAddress
1602
1603 if self._IsKeyword("RtBaseAddress"):
1604 if not self._IsToken(TAB_EQUAL_SPLIT):
1605 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1606
1607 if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
1608 raise Warning.Expected("address", self.FileName, self.CurrentLineNumber)
1609
1610 RtAddress = int(self._Token, 0)
1611 Obj.RtBaseAddress = RtAddress
1612
1613 ## _GetBlockStatements() method
1614 #
1615 # Get block statements
1616 #
1617 # @param self The object pointer
1618 # @param Obj for whom block statement is got
1619 #
1620 def _GetBlockStatements(self, Obj):
1621 IsBlock = False
1622 while self._GetBlockStatement(Obj):
1623 IsBlock = True
1624
1625 Item = Obj.BlockSizeList[-1]
1626 if Item[0] is None or Item[1] is None:
1627 raise Warning.Expected("block statement", self.FileName, self.CurrentLineNumber)
1628 return IsBlock
1629
1630 ## _GetBlockStatement() method
1631 #
1632 # Get block statement
1633 #
1634 # @param self The object pointer
1635 # @param Obj for whom block statement is got
1636 # @retval True Successfully find
1637 # @retval False Not able to find
1638 #
1639 def _GetBlockStatement(self, Obj):
1640 if not self._IsKeyword("BlockSize"):
1641 return False
1642
1643 if not self._IsToken(TAB_EQUAL_SPLIT):
1644 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1645
1646 if not self._GetNextHexNumber() and not self._GetNextDecimalNumber():
1647 raise Warning.Expected("Hex or Integer block size", self.FileName, self.CurrentLineNumber)
1648
1649 BlockSize = self._Token
1650 BlockSizePcd = None
1651 if self._IsToken(TAB_VALUE_SPLIT):
1652 PcdPair = self._GetNextPcdSettings()
1653 BlockSizePcd = PcdPair
1654 self.Profile.PcdDict[PcdPair] = BlockSize
1655 self.SetPcdLocalation(PcdPair)
1656 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1657 self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
1658 BlockSize = int(BlockSize, 0)
1659
1660 BlockNumber = None
1661 if self._IsKeyword("NumBlocks"):
1662 if not self._IsToken(TAB_EQUAL_SPLIT):
1663 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1664
1665 if not self._GetNextDecimalNumber() and not self._GetNextHexNumber():
1666 raise Warning.Expected("block numbers", self.FileName, self.CurrentLineNumber)
1667
1668 BlockNumber = int(self._Token, 0)
1669
1670 Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd))
1671 return True
1672
1673 ## _GetDefineStatements() method
1674 #
1675 # Get define statements
1676 #
1677 # @param self The object pointer
1678 # @param Obj for whom define statement is got
1679 # @retval True Successfully find
1680 # @retval False Not able to find
1681 #
1682 def _GetDefineStatements(self, Obj):
1683 while self._GetDefineStatement(Obj):
1684 pass
1685
1686 ## _GetDefineStatement() method
1687 #
1688 # Get define statement
1689 #
1690 # @param self The object pointer
1691 # @param Obj for whom define statement is got
1692 # @retval True Successfully find
1693 # @retval False Not able to find
1694 #
1695 def _GetDefineStatement(self, Obj):
1696 if self._IsKeyword(TAB_DEFINE):
1697 self._GetNextToken()
1698 Macro = self._Token
1699 if not self._IsToken(TAB_EQUAL_SPLIT):
1700 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1701
1702 if not self._GetNextToken():
1703 raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
1704
1705 Value = self._Token
1706 Macro = '$(' + Macro + ')'
1707 Obj.DefineVarDict[Macro] = Value
1708 return True
1709
1710 return False
1711
1712 ## _GetSetStatements() method
1713 #
1714 # Get set statements
1715 #
1716 # @param self The object pointer
1717 # @param Obj for whom set statement is got
1718 # @retval True Successfully find
1719 # @retval False Not able to find
1720 #
1721 def _GetSetStatements(self, Obj):
1722 while self._GetSetStatement(Obj):
1723 pass
1724
1725 ## _GetSetStatement() method
1726 #
1727 # Get set statement
1728 #
1729 # @param self The object pointer
1730 # @param Obj for whom set statement is got
1731 # @retval True Successfully find
1732 # @retval False Not able to find
1733 #
1734 def _GetSetStatement(self, Obj):
1735 if self._IsKeyword("SET"):
1736 PcdPair = self._GetNextPcdSettings()
1737
1738 if not self._IsToken(TAB_EQUAL_SPLIT):
1739 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1740
1741 Value = self._GetExpression()
1742 Value = self._EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
1743
1744 if Obj:
1745 Obj.SetVarDict[PcdPair] = Value
1746 self.Profile.PcdDict[PcdPair] = Value
1747 self.SetPcdLocalation(PcdPair)
1748 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1749 self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
1750 return True
1751
1752 return False
1753
1754 ## _CalcRegionExpr(self)
1755 #
1756 # Calculate expression for offset or size of a region
1757 #
1758 # @return: None if invalid expression
1759 # Calculated number if successfully
1760 #
1761 def _CalcRegionExpr(self):
1762 StartPos = self.GetFileBufferPos()
1763 Expr = ''
1764 PairCount = 0
1765 while not self._EndOfFile():
1766 CurCh = self._CurrentChar()
1767 if CurCh == '(':
1768 PairCount += 1
1769 elif CurCh == ')':
1770 PairCount -= 1
1771
1772 if CurCh in '|\r\n' and PairCount == 0:
1773 break
1774 Expr += CurCh
1775 self._GetOneChar()
1776 try:
1777 return int(
1778 ValueExpression(Expr,
1779 self._CollectMacroPcd()
1780 )(True), 0)
1781 except Exception:
1782 self.SetFileBufferPos(StartPos)
1783 return None
1784
1785 ## _GetRegionLayout() method
1786 #
1787 # Get region layout for FD
1788 #
1789 # @param self The object pointer
1790 # @param theFd for whom region is got
1791 # @retval True Successfully find
1792 # @retval False Not able to find
1793 #
1794 def _GetRegionLayout(self, theFd):
1795 Offset = self._CalcRegionExpr()
1796 if Offset is None:
1797 return False
1798
1799 RegionObj = Region()
1800 RegionObj.Offset = Offset
1801 theFd.RegionList.append(RegionObj)
1802
1803 if not self._IsToken(TAB_VALUE_SPLIT):
1804 raise Warning.Expected("'|'", self.FileName, self.CurrentLineNumber)
1805
1806 Size = self._CalcRegionExpr()
1807 if Size is None:
1808 raise Warning.Expected("Region Size", self.FileName, self.CurrentLineNumber)
1809 RegionObj.Size = Size
1810
1811 if not self._GetNextWord():
1812 return True
1813
1814 if not self._Token in {"SET", BINARY_FILE_TYPE_FV, "FILE", "DATA", "CAPSULE", "INF"}:
1815 #
1816 # If next token is a word which is not a valid FV type, it might be part of [PcdOffset[|PcdSize]]
1817 # Or it might be next region's offset described by an expression which starts with a PCD.
1818 # PcdOffset[|PcdSize] or OffsetPcdExpression|Size
1819 #
1820 self._UndoToken()
1821 IsRegionPcd = (RegionSizeGuidPattern.match(self._CurrentLine()[self.CurrentOffsetWithinLine:]) or
1822 RegionOffsetPcdPattern.match(self._CurrentLine()[self.CurrentOffsetWithinLine:]))
1823 if IsRegionPcd:
1824 RegionObj.PcdOffset = self._GetNextPcdSettings()
1825 self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + int(theFd.BaseAddress, 0))
1826 self.SetPcdLocalation(RegionObj.PcdOffset)
1827 self._PcdDict['%s.%s' % (RegionObj.PcdOffset[1], RegionObj.PcdOffset[0])] = "0x%x" % RegionObj.Offset
1828 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1829 self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple
1830 if self._IsToken(TAB_VALUE_SPLIT):
1831 RegionObj.PcdSize = self._GetNextPcdSettings()
1832 self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size
1833 self.SetPcdLocalation(RegionObj.PcdSize)
1834 self._PcdDict['%s.%s' % (RegionObj.PcdSize[1], RegionObj.PcdSize[0])] = "0x%x" % RegionObj.Size
1835 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1836 self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple
1837
1838 if not self._GetNextWord():
1839 return True
1840
1841 if self._Token == "SET":
1842 self._UndoToken()
1843 self._GetSetStatements(RegionObj)
1844 if not self._GetNextWord():
1845 return True
1846
1847 elif self._Token == BINARY_FILE_TYPE_FV:
1848 self._UndoToken()
1849 self._GetRegionFvType(RegionObj)
1850
1851 elif self._Token == "CAPSULE":
1852 self._UndoToken()
1853 self._GetRegionCapType(RegionObj)
1854
1855 elif self._Token == "FILE":
1856 self._UndoToken()
1857 self._GetRegionFileType(RegionObj)
1858
1859 elif self._Token == "INF":
1860 self._UndoToken()
1861 RegionObj.RegionType = "INF"
1862 while self._IsKeyword("INF"):
1863 self._UndoToken()
1864 ffsInf = self._ParseInfStatement()
1865 if not ffsInf:
1866 break
1867 RegionObj.RegionDataList.append(ffsInf)
1868
1869 elif self._Token == "DATA":
1870 self._UndoToken()
1871 self._GetRegionDataType(RegionObj)
1872 else:
1873 self._UndoToken()
1874 if self._GetRegionLayout(theFd):
1875 return True
1876 raise Warning("A valid region type was not found. "
1877 "Valid types are [SET, FV, CAPSULE, FILE, DATA, INF]. This error occurred",
1878 self.FileName, self.CurrentLineNumber)
1879
1880 return True
1881
1882 ## _GetRegionFvType() method
1883 #
1884 # Get region fv data for region
1885 #
1886 # @param self The object pointer
1887 # @param RegionObj for whom region data is got
1888 #
1889 def _GetRegionFvType(self, RegionObj):
1890 if not self._IsKeyword(BINARY_FILE_TYPE_FV):
1891 raise Warning.Expected("'FV'", self.FileName, self.CurrentLineNumber)
1892
1893 if not self._IsToken(TAB_EQUAL_SPLIT):
1894 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1895
1896 if not self._GetNextToken():
1897 raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
1898
1899 RegionObj.RegionType = BINARY_FILE_TYPE_FV
1900 RegionObj.RegionDataList.append((self._Token).upper())
1901
1902 while self._IsKeyword(BINARY_FILE_TYPE_FV):
1903
1904 if not self._IsToken(TAB_EQUAL_SPLIT):
1905 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1906
1907 if not self._GetNextToken():
1908 raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
1909
1910 RegionObj.RegionDataList.append((self._Token).upper())
1911
1912 ## _GetRegionCapType() method
1913 #
1914 # Get region capsule data for region
1915 #
1916 # @param self The object pointer
1917 # @param RegionObj for whom region data is got
1918 #
1919 def _GetRegionCapType(self, RegionObj):
1920 if not self._IsKeyword("CAPSULE"):
1921 raise Warning.Expected("'CAPSULE'", self.FileName, self.CurrentLineNumber)
1922
1923 if not self._IsToken(TAB_EQUAL_SPLIT):
1924 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1925
1926 if not self._GetNextToken():
1927 raise Warning.Expected("CAPSULE name", self.FileName, self.CurrentLineNumber)
1928
1929 RegionObj.RegionType = "CAPSULE"
1930 RegionObj.RegionDataList.append(self._Token)
1931
1932 while self._IsKeyword("CAPSULE"):
1933
1934 if not self._IsToken(TAB_EQUAL_SPLIT):
1935 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1936
1937 if not self._GetNextToken():
1938 raise Warning.Expected("CAPSULE name", self.FileName, self.CurrentLineNumber)
1939
1940 RegionObj.RegionDataList.append(self._Token)
1941
1942 ## _GetRegionFileType() method
1943 #
1944 # Get region file data for region
1945 #
1946 # @param self The object pointer
1947 # @param RegionObj for whom region data is got
1948 #
1949 def _GetRegionFileType(self, RegionObj):
1950 if not self._IsKeyword("FILE"):
1951 raise Warning.Expected("'FILE'", self.FileName, self.CurrentLineNumber)
1952
1953 if not self._IsToken(TAB_EQUAL_SPLIT):
1954 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1955
1956 if not self._GetNextToken():
1957 raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
1958
1959 RegionObj.RegionType = "FILE"
1960 RegionObj.RegionDataList.append(self._Token)
1961
1962 while self._IsKeyword("FILE"):
1963
1964 if not self._IsToken(TAB_EQUAL_SPLIT):
1965 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1966
1967 if not self._GetNextToken():
1968 raise Warning.Expected("FILE name", self.FileName, self.CurrentLineNumber)
1969
1970 RegionObj.RegionDataList.append(self._Token)
1971
1972 ## _GetRegionDataType() method
1973 #
1974 # Get region array data for region
1975 #
1976 # @param self The object pointer
1977 # @param RegionObj for whom region data is got
1978 #
1979 def _GetRegionDataType(self, RegionObj):
1980 if not self._IsKeyword("DATA"):
1981 raise Warning.Expected("Region Data type", self.FileName, self.CurrentLineNumber)
1982
1983 if not self._IsToken(TAB_EQUAL_SPLIT):
1984 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
1985
1986 if not self._IsToken("{"):
1987 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
1988
1989 if not self._GetNextHexNumber():
1990 raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
1991
1992 if len(self._Token) > 18:
1993 raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
1994
1995 # convert hex string value to byte hex string array
1996 AllString = self._Token
1997 AllStrLen = len (AllString)
1998 DataString = ""
1999 while AllStrLen > 4:
2000 DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + TAB_COMMA_SPLIT
2001 AllStrLen = AllStrLen - 2
2002 DataString = DataString + AllString[:AllStrLen] + TAB_COMMA_SPLIT
2003
2004 # byte value array
2005 if len (self._Token) <= 4:
2006 while self._IsToken(TAB_COMMA_SPLIT):
2007 if not self._GetNextHexNumber():
2008 raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2009 if len(self._Token) > 4:
2010 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2011 DataString += self._Token
2012 DataString += TAB_COMMA_SPLIT
2013
2014 if not self._IsToken(T_CHAR_BRACE_R):
2015 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2016
2017 DataString = DataString.rstrip(TAB_COMMA_SPLIT)
2018 RegionObj.RegionType = "DATA"
2019 RegionObj.RegionDataList.append(DataString)
2020
2021 while self._IsKeyword("DATA"):
2022
2023 if not self._IsToken(TAB_EQUAL_SPLIT):
2024 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2025
2026 if not self._IsToken("{"):
2027 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
2028
2029 if not self._GetNextHexNumber():
2030 raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
2031
2032 if len(self._Token) > 18:
2033 raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
2034
2035 # convert hex string value to byte hex string array
2036 AllString = self._Token
2037 AllStrLen = len (AllString)
2038 DataString = ""
2039 while AllStrLen > 4:
2040 DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + TAB_COMMA_SPLIT
2041 AllStrLen = AllStrLen - 2
2042 DataString = DataString + AllString[:AllStrLen] + TAB_COMMA_SPLIT
2043
2044 # byte value array
2045 if len (self._Token) <= 4:
2046 while self._IsToken(TAB_COMMA_SPLIT):
2047 if not self._GetNextHexNumber():
2048 raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2049 if len(self._Token) > 4:
2050 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2051 DataString += self._Token
2052 DataString += TAB_COMMA_SPLIT
2053
2054 if not self._IsToken(T_CHAR_BRACE_R):
2055 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2056
2057 DataString = DataString.rstrip(TAB_COMMA_SPLIT)
2058 RegionObj.RegionDataList.append(DataString)
2059
2060 ## _GetFv() method
2061 #
2062 # Get FV section contents and store its data into FV dictionary of self.Profile
2063 #
2064 # @param self The object pointer
2065 # @retval True Successfully find a FV
2066 # @retval False Not able to find a FV
2067 #
2068 def _GetFv(self):
2069 if not self._GetNextToken():
2070 return False
2071
2072 S = self._Token.upper()
2073 if S.startswith(TAB_SECTION_START) and not S.startswith("[FV."):
2074 self.SectionParser(S)
2075 self._UndoToken()
2076 return False
2077
2078 self._UndoToken()
2079 if not self._IsToken("[FV.", True):
2080 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2081 #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
2082 # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
2083 raise Warning("Unknown Keyword '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2084
2085 FvName = self._GetUiName()
2086 self.CurrentFvName = FvName.upper()
2087
2088 if not self._IsToken(TAB_SECTION_END):
2089 raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
2090
2091 FvObj = FV(Name=self.CurrentFvName)
2092 self.Profile.FvDict[self.CurrentFvName] = FvObj
2093
2094 Status = self._GetCreateFile(FvObj)
2095 if not Status:
2096 raise Warning("FV name error", self.FileName, self.CurrentLineNumber)
2097
2098 self._GetDefineStatements(FvObj)
2099
2100 self._GetAddressStatements(FvObj)
2101
2102 while True:
2103 self._GetSetStatements(FvObj)
2104
2105 if not (self._GetBlockStatement(FvObj) or self._GetFvBaseAddress(FvObj) or
2106 self._GetFvForceRebase(FvObj) or self._GetFvAlignment(FvObj) or
2107 self._GetFvAttributes(FvObj) or self._GetFvNameGuid(FvObj) or
2108 self._GetFvExtEntryStatement(FvObj) or self._GetFvNameString(FvObj)):
2109 break
2110
2111 if FvObj.FvNameString == 'TRUE' and not FvObj.FvNameGuid:
2112 raise Warning("FvNameString found but FvNameGuid was not found", self.FileName, self.CurrentLineNumber)
2113
2114 self._GetAprioriSection(FvObj)
2115 self._GetAprioriSection(FvObj)
2116
2117 while True:
2118 isInf = self._GetInfStatement(FvObj)
2119 isFile = self._GetFileStatement(FvObj)
2120 if not isInf and not isFile:
2121 break
2122
2123 return True
2124
2125 ## _GetFvAlignment() method
2126 #
2127 # Get alignment for FV
2128 #
2129 # @param self The object pointer
2130 # @param Obj for whom alignment is got
2131 # @retval True Successfully find a alignment statement
2132 # @retval False Not able to find a alignment statement
2133 #
2134 def _GetFvAlignment(self, Obj):
2135 if not self._IsKeyword("FvAlignment"):
2136 return False
2137
2138 if not self._IsToken(TAB_EQUAL_SPLIT):
2139 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2140
2141 if not self._GetNextToken():
2142 raise Warning.Expected("alignment value", self.FileName, self.CurrentLineNumber)
2143
2144 if self._Token.upper() not in {"1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \
2145 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \
2146 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \
2147 "1G", "2G"}:
2148 raise Warning("Unknown alignment value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2149 Obj.FvAlignment = self._Token
2150 return True
2151
2152 ## _GetFvBaseAddress() method
2153 #
2154 # Get BaseAddress for FV
2155 #
2156 # @param self The object pointer
2157 # @param Obj for whom FvBaseAddress is got
2158 # @retval True Successfully find a FvBaseAddress statement
2159 # @retval False Not able to find a FvBaseAddress statement
2160 #
2161 def _GetFvBaseAddress(self, Obj):
2162 if not self._IsKeyword("FvBaseAddress"):
2163 return False
2164
2165 if not self._IsToken(TAB_EQUAL_SPLIT):
2166 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2167
2168 if not self._GetNextToken():
2169 raise Warning.Expected("FV base address value", self.FileName, self.CurrentLineNumber)
2170
2171 if not BaseAddrValuePattern.match(self._Token.upper()):
2172 raise Warning("Unknown FV base address value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2173 Obj.FvBaseAddress = self._Token
2174 return True
2175
2176 ## _GetFvForceRebase() method
2177 #
2178 # Get FvForceRebase for FV
2179 #
2180 # @param self The object pointer
2181 # @param Obj for whom FvForceRebase is got
2182 # @retval True Successfully find a FvForceRebase statement
2183 # @retval False Not able to find a FvForceRebase statement
2184 #
2185 def _GetFvForceRebase(self, Obj):
2186 if not self._IsKeyword("FvForceRebase"):
2187 return False
2188
2189 if not self._IsToken(TAB_EQUAL_SPLIT):
2190 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2191
2192 if not self._GetNextToken():
2193 raise Warning.Expected("FvForceRebase value", self.FileName, self.CurrentLineNumber)
2194
2195 if self._Token.upper() not in {"TRUE", "FALSE", "0", "0X0", "0X00", "1", "0X1", "0X01"}:
2196 raise Warning("Unknown FvForceRebase value '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2197
2198 if self._Token.upper() in {"TRUE", "1", "0X1", "0X01"}:
2199 Obj.FvForceRebase = True
2200 elif self._Token.upper() in {"FALSE", "0", "0X0", "0X00"}:
2201 Obj.FvForceRebase = False
2202 else:
2203 Obj.FvForceRebase = None
2204
2205 return True
2206
2207
2208 ## _GetFvAttributes() method
2209 #
2210 # Get attributes for FV
2211 #
2212 # @param self The object pointer
2213 # @param Obj for whom attribute is got
2214 # @retval None
2215 #
2216 def _GetFvAttributes(self, FvObj):
2217 IsWordToken = False
2218 while self._GetNextWord():
2219 IsWordToken = True
2220 name = self._Token
2221 if name not in {"ERASE_POLARITY", "MEMORY_MAPPED", \
2222 "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \
2223 "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \
2224 "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \
2225 "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \
2226 "WRITE_POLICY_RELIABLE", "WEAK_ALIGNMENT", "FvUsedSizeEnable"}:
2227 self._UndoToken()
2228 return False
2229
2230 if not self._IsToken(TAB_EQUAL_SPLIT):
2231 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2232
2233 if not self._GetNextToken() or self._Token.upper() not in {"TRUE", "FALSE", "1", "0"}:
2234 raise Warning.Expected("TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
2235
2236 FvObj.FvAttributeDict[name] = self._Token
2237
2238 return IsWordToken
2239
2240 ## _GetFvNameGuid() method
2241 #
2242 # Get FV GUID for FV
2243 #
2244 # @param self The object pointer
2245 # @param Obj for whom GUID is got
2246 # @retval None
2247 #
2248 def _GetFvNameGuid(self, FvObj):
2249 if not self._IsKeyword("FvNameGuid"):
2250 return False
2251
2252 if not self._IsToken(TAB_EQUAL_SPLIT):
2253 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2254
2255 if not self._GetNextGuid():
2256 raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)
2257
2258 FvObj.FvNameGuid = self._Token
2259
2260 return True
2261
2262 def _GetFvNameString(self, FvObj):
2263 if not self._IsKeyword("FvNameString"):
2264 return False
2265
2266 if not self._IsToken(TAB_EQUAL_SPLIT):
2267 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2268
2269 if not self._GetNextToken() or self._Token.upper() not in {'TRUE', 'FALSE'}:
2270 raise Warning.Expected("TRUE or FALSE for FvNameString", self.FileName, self.CurrentLineNumber)
2271
2272 FvObj.FvNameString = self._Token
2273
2274 return True
2275
2276 def _GetFvExtEntryStatement(self, FvObj):
2277 if not (self._IsKeyword("FV_EXT_ENTRY") or self._IsKeyword("FV_EXT_ENTRY_TYPE")):
2278 return False
2279
2280 if not self._IsKeyword ("TYPE"):
2281 raise Warning.Expected("'TYPE'", self.FileName, self.CurrentLineNumber)
2282
2283 if not self._IsToken(TAB_EQUAL_SPLIT):
2284 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2285
2286 if not self._GetNextHexNumber() and not self._GetNextDecimalNumber():
2287 raise Warning.Expected("Hex FV extension entry type value At Line ", self.FileName, self.CurrentLineNumber)
2288
2289 FvObj.FvExtEntryTypeValue.append(self._Token)
2290
2291 if not self._IsToken("{"):
2292 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
2293
2294 if not self._IsKeyword("FILE") and not self._IsKeyword("DATA"):
2295 raise Warning.Expected("'FILE' or 'DATA'", self.FileName, self.CurrentLineNumber)
2296
2297 FvObj.FvExtEntryType.append(self._Token)
2298
2299 if self._Token == 'DATA':
2300 if not self._IsToken(TAB_EQUAL_SPLIT):
2301 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2302
2303 if not self._IsToken("{"):
2304 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
2305
2306 if not self._GetNextHexNumber():
2307 raise Warning.Expected("Hex byte", self.FileName, self.CurrentLineNumber)
2308
2309 if len(self._Token) > 4:
2310 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2311
2312 DataString = self._Token
2313 DataString += TAB_COMMA_SPLIT
2314
2315 while self._IsToken(TAB_COMMA_SPLIT):
2316 if not self._GetNextHexNumber():
2317 raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2318 if len(self._Token) > 4:
2319 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2320 DataString += self._Token
2321 DataString += TAB_COMMA_SPLIT
2322
2323 if not self._IsToken(T_CHAR_BRACE_R):
2324 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2325
2326 if not self._IsToken(T_CHAR_BRACE_R):
2327 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2328
2329 DataString = DataString.rstrip(TAB_COMMA_SPLIT)
2330 FvObj.FvExtEntryData.append(DataString)
2331
2332 if self._Token == 'FILE':
2333 if not self._IsToken(TAB_EQUAL_SPLIT):
2334 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2335
2336 if not self._GetNextToken():
2337 raise Warning.Expected("FV Extension Entry file path At Line ", self.FileName, self.CurrentLineNumber)
2338
2339 FvObj.FvExtEntryData.append(self._Token)
2340
2341 if not self._IsToken(T_CHAR_BRACE_R):
2342 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2343
2344 return True
2345
2346 ## _GetAprioriSection() method
2347 #
2348 # Get token statements
2349 #
2350 # @param self The object pointer
2351 # @param FvObj for whom apriori is got
2352 # @retval True Successfully find apriori statement
2353 # @retval False Not able to find apriori statement
2354 #
2355 def _GetAprioriSection(self, FvObj):
2356 if not self._IsKeyword("APRIORI"):
2357 return False
2358
2359 if not self._IsKeyword("PEI") and not self._IsKeyword("DXE"):
2360 raise Warning.Expected("Apriori file type", self.FileName, self.CurrentLineNumber)
2361 AprType = self._Token
2362
2363 if not self._IsToken("{"):
2364 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
2365
2366 AprSectionObj = AprioriSection()
2367 AprSectionObj.AprioriType = AprType
2368
2369 self._GetDefineStatements(AprSectionObj)
2370
2371 while True:
2372 IsInf = self._GetInfStatement(AprSectionObj)
2373 IsFile = self._GetFileStatement(AprSectionObj)
2374 if not IsInf and not IsFile:
2375 break
2376
2377 if not self._IsToken(T_CHAR_BRACE_R):
2378 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2379
2380 FvObj.AprioriSectionList.append(AprSectionObj)
2381 return True
2382
2383 def _ParseInfStatement(self):
2384 if not self._IsKeyword("INF"):
2385 return None
2386
2387 ffsInf = FfsInfStatement()
2388 self._GetInfOptions(ffsInf)
2389
2390 if not self._GetNextToken():
2391 raise Warning.Expected("INF file path", self.FileName, self.CurrentLineNumber)
2392 ffsInf.InfFileName = self._Token
2393 if not ffsInf.InfFileName.endswith('.inf'):
2394 raise Warning.Expected(".inf file path", self.FileName, self.CurrentLineNumber)
2395
2396 ffsInf.CurrentLineNum = self.CurrentLineNumber
2397 ffsInf.CurrentLineContent = self._CurrentLine()
2398
2399 #Replace $(SAPCE) with real space
2400 ffsInf.InfFileName = ffsInf.InfFileName.replace('$(SPACE)', ' ')
2401
2402 if ffsInf.InfFileName.replace(TAB_WORKSPACE, '').find('$') == -1:
2403 #do case sensitive check for file path
2404 ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
2405 if ErrorCode != 0:
2406 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
2407
2408 NewFileName = ffsInf.InfFileName
2409 if ffsInf.OverrideGuid:
2410 NewFileName = ProcessDuplicatedInf(PathClass(ffsInf.InfFileName,GenFdsGlobalVariable.WorkSpaceDir), ffsInf.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir).Path
2411
2412 if not NewFileName in self.Profile.InfList:
2413 self.Profile.InfList.append(NewFileName)
2414 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2415 self.Profile.InfFileLineList.append(FileLineTuple)
2416 if ffsInf.UseArch:
2417 if ffsInf.UseArch not in self.Profile.InfDict:
2418 self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
2419 else:
2420 self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
2421 else:
2422 self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
2423
2424 if self._IsToken(TAB_VALUE_SPLIT):
2425 if self._IsKeyword('RELOCS_STRIPPED'):
2426 ffsInf.KeepReloc = False
2427 elif self._IsKeyword('RELOCS_RETAINED'):
2428 ffsInf.KeepReloc = True
2429 else:
2430 raise Warning("Unknown reloc strip flag '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2431 return ffsInf
2432
2433 ## _GetInfStatement() method
2434 #
2435 # Get INF statements
2436 #
2437 # @param self The object pointer
2438 # @param Obj for whom inf statement is got
2439 # @retval True Successfully find inf statement
2440 # @retval False Not able to find inf statement
2441 #
2442 def _GetInfStatement(self, Obj, ForCapsule=False):
2443 ffsInf = self._ParseInfStatement()
2444 if not ffsInf:
2445 return False
2446
2447 if ForCapsule:
2448 myCapsuleFfs = CapsuleFfs()
2449 myCapsuleFfs.Ffs = ffsInf
2450 Obj.CapsuleDataList.append(myCapsuleFfs)
2451 else:
2452 Obj.FfsList.append(ffsInf)
2453 return True
2454
2455 ## _GetInfOptions() method
2456 #
2457 # Get options for INF
2458 #
2459 # @param self The object pointer
2460 # @param FfsInfObj for whom option is got
2461 #
2462 def _GetInfOptions(self, FfsInfObj):
2463 if self._IsKeyword("FILE_GUID"):
2464 if not self._IsToken(TAB_EQUAL_SPLIT):
2465 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2466 if not self._GetNextGuid():
2467 raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)
2468 FfsInfObj.OverrideGuid = self._Token
2469
2470 if self._IsKeyword("RuleOverride"):
2471 if not self._IsToken(TAB_EQUAL_SPLIT):
2472 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2473 if not self._GetNextToken():
2474 raise Warning.Expected("Rule name", self.FileName, self.CurrentLineNumber)
2475 FfsInfObj.Rule = self._Token
2476
2477 if self._IsKeyword("VERSION"):
2478 if not self._IsToken(TAB_EQUAL_SPLIT):
2479 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2480 if not self._GetNextToken():
2481 raise Warning.Expected("Version", self.FileName, self.CurrentLineNumber)
2482
2483 if self._GetStringData():
2484 FfsInfObj.Version = self._Token
2485
2486 if self._IsKeyword(BINARY_FILE_TYPE_UI):
2487 if not self._IsToken(TAB_EQUAL_SPLIT):
2488 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2489 if not self._GetNextToken():
2490 raise Warning.Expected("UI name", self.FileName, self.CurrentLineNumber)
2491
2492 if self._GetStringData():
2493 FfsInfObj.Ui = self._Token
2494
2495 if self._IsKeyword("USE"):
2496 if not self._IsToken(TAB_EQUAL_SPLIT):
2497 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2498 if not self._GetNextToken():
2499 raise Warning.Expected("ARCH name", self.FileName, self.CurrentLineNumber)
2500 FfsInfObj.UseArch = self._Token
2501
2502
2503 if self._GetNextToken():
2504 p = compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\))')
2505 if p.match(self._Token) and p.match(self._Token).span()[1] == len(self._Token):
2506 FfsInfObj.KeyStringList.append(self._Token)
2507 if not self._IsToken(TAB_COMMA_SPLIT):
2508 return
2509 else:
2510 self._UndoToken()
2511 return
2512
2513 while self._GetNextToken():
2514 if not p.match(self._Token):
2515 raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
2516 FfsInfObj.KeyStringList.append(self._Token)
2517
2518 if not self._IsToken(TAB_COMMA_SPLIT):
2519 break
2520
2521 ## _GetFileStatement() method
2522 #
2523 # Get FILE statements
2524 #
2525 # @param self The object pointer
2526 # @param Obj for whom FILE statement is got
2527 # @retval True Successfully find FILE statement
2528 # @retval False Not able to find FILE statement
2529 #
2530 def _GetFileStatement(self, Obj, ForCapsule = False):
2531 if not self._IsKeyword("FILE"):
2532 return False
2533
2534 if not self._GetNextWord():
2535 raise Warning.Expected("FFS type", self.FileName, self.CurrentLineNumber)
2536
2537 if ForCapsule and self._Token == 'DATA':
2538 self._UndoToken()
2539 self._UndoToken()
2540 return False
2541
2542 FfsFileObj = FileStatement()
2543 FfsFileObj.FvFileType = self._Token
2544
2545 if not self._IsToken(TAB_EQUAL_SPLIT):
2546 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2547
2548 if not self._GetNextGuid():
2549 if not self._GetNextWord():
2550 raise Warning.Expected("File GUID", self.FileName, self.CurrentLineNumber)
2551 if self._Token == 'PCD':
2552 if not self._IsToken("("):
2553 raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
2554 PcdPair = self._GetNextPcdSettings()
2555 if not self._IsToken(")"):
2556 raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
2557 self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
2558
2559 FfsFileObj.NameGuid = self._Token
2560
2561 self._GetFilePart(FfsFileObj)
2562
2563 if ForCapsule:
2564 capsuleFfs = CapsuleFfs()
2565 capsuleFfs.Ffs = FfsFileObj
2566 Obj.CapsuleDataList.append(capsuleFfs)
2567 else:
2568 Obj.FfsList.append(FfsFileObj)
2569
2570 return True
2571
2572 ## _FileCouldHaveRelocFlag() method
2573 #
2574 # Check whether reloc strip flag can be set for a file type.
2575 #
2576 # @param FileType The file type to check with
2577 # @retval True This type could have relocation strip flag
2578 # @retval False No way to have it
2579 #
2580 @staticmethod
2581 def _FileCouldHaveRelocFlag (FileType):
2582 if FileType in {SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, SUP_MODULE_MM_CORE_STANDALONE, 'PEI_DXE_COMBO'}:
2583 return True
2584 else:
2585 return False
2586
2587 ## _SectionCouldHaveRelocFlag() method
2588 #
2589 # Check whether reloc strip flag can be set for a section type.
2590 #
2591 # @param SectionType The section type to check with
2592 # @retval True This type could have relocation strip flag
2593 # @retval False No way to have it
2594 #
2595 @staticmethod
2596 def _SectionCouldHaveRelocFlag (SectionType):
2597 if SectionType in {BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32}:
2598 return True
2599 else:
2600 return False
2601
2602 ## _GetFilePart() method
2603 #
2604 # Get components for FILE statement
2605 #
2606 # @param self The object pointer
2607 # @param FfsFileObj for whom component is got
2608 #
2609 def _GetFilePart(self, FfsFileObj):
2610 self._GetFileOpts(FfsFileObj)
2611
2612 if not self._IsToken("{"):
2613 if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
2614 if self._FileCouldHaveRelocFlag(FfsFileObj.FvFileType):
2615 if self._Token == 'RELOCS_STRIPPED':
2616 FfsFileObj.KeepReloc = False
2617 else:
2618 FfsFileObj.KeepReloc = True
2619 else:
2620 raise Warning("File type %s could not have reloc strip flag%d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
2621
2622 if not self._IsToken("{"):
2623 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
2624
2625 if not self._GetNextToken():
2626 raise Warning.Expected("File name or section data", self.FileName, self.CurrentLineNumber)
2627
2628 if self._Token == BINARY_FILE_TYPE_FV:
2629 if not self._IsToken(TAB_EQUAL_SPLIT):
2630 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2631 if not self._GetNextToken():
2632 raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
2633 FfsFileObj.FvName = self._Token
2634
2635 elif self._Token == "FD":
2636 if not self._IsToken(TAB_EQUAL_SPLIT):
2637 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2638 if not self._GetNextToken():
2639 raise Warning.Expected("FD name", self.FileName, self.CurrentLineNumber)
2640 FfsFileObj.FdName = self._Token
2641
2642 elif self._Token in {TAB_DEFINE, "APRIORI", "SECTION"}:
2643 self._UndoToken()
2644 self._GetSectionData(FfsFileObj)
2645
2646 elif hasattr(FfsFileObj, 'FvFileType') and FfsFileObj.FvFileType == 'RAW':
2647 self._UndoToken()
2648 self._GetRAWData(FfsFileObj)
2649
2650 else:
2651 FfsFileObj.CurrentLineNum = self.CurrentLineNumber
2652 FfsFileObj.CurrentLineContent = self._CurrentLine()
2653 FfsFileObj.FileName = self._Token.replace('$(SPACE)', ' ')
2654 self._VerifyFile(FfsFileObj.FileName)
2655
2656 if not self._IsToken(T_CHAR_BRACE_R):
2657 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2658
2659 ## _GetRAWData() method
2660 #
2661 # Get RAW data for FILE statement
2662 #
2663 # @param self The object pointer
2664 # @param FfsFileObj for whom section is got
2665 #
2666 def _GetRAWData(self, FfsFileObj):
2667 FfsFileObj.FileName = []
2668 FfsFileObj.SubAlignment = []
2669 while True:
2670 AlignValue = None
2671 if self._GetAlignment():
2672 if self._Token not in ALIGNMENTS:
2673 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2674 #For FFS, Auto is default option same to ""
2675 if not self._Token == "Auto":
2676 AlignValue = self._Token
2677 if not self._GetNextToken():
2678 raise Warning.Expected("Filename value", self.FileName, self.CurrentLineNumber)
2679
2680 FileName = self._Token.replace('$(SPACE)', ' ')
2681 if FileName == T_CHAR_BRACE_R:
2682 self._UndoToken()
2683 raise Warning.Expected("Filename value", self.FileName, self.CurrentLineNumber)
2684
2685 self._VerifyFile(FileName)
2686 File = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir)
2687 FfsFileObj.FileName.append(File.Path)
2688 FfsFileObj.SubAlignment.append(AlignValue)
2689
2690 if self._IsToken(T_CHAR_BRACE_R):
2691 self._UndoToken()
2692 break
2693
2694 if len(FfsFileObj.SubAlignment) == 1:
2695 FfsFileObj.SubAlignment = FfsFileObj.SubAlignment[0]
2696 if len(FfsFileObj.FileName) == 1:
2697 FfsFileObj.FileName = FfsFileObj.FileName[0]
2698
2699 ## _GetFileOpts() method
2700 #
2701 # Get options for FILE statement
2702 #
2703 # @param self The object pointer
2704 # @param FfsFileObj for whom options is got
2705 #
2706 def _GetFileOpts(self, FfsFileObj):
2707 if self._GetNextToken():
2708 if TokenFindPattern.match(self._Token):
2709 FfsFileObj.KeyStringList.append(self._Token)
2710 if self._IsToken(TAB_COMMA_SPLIT):
2711 while self._GetNextToken():
2712 if not TokenFindPattern.match(self._Token):
2713 raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
2714 FfsFileObj.KeyStringList.append(self._Token)
2715
2716 if not self._IsToken(TAB_COMMA_SPLIT):
2717 break
2718
2719 else:
2720 self._UndoToken()
2721
2722 if self._IsKeyword("FIXED", True):
2723 FfsFileObj.Fixed = True
2724
2725 if self._IsKeyword("CHECKSUM", True):
2726 FfsFileObj.CheckSum = True
2727
2728 if self._GetAlignment():
2729 if self._Token not in ALIGNMENTS:
2730 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2731 #For FFS, Auto is default option same to ""
2732 if not self._Token == "Auto":
2733 FfsFileObj.Alignment = self._Token
2734
2735 ## _GetAlignment() method
2736 #
2737 # Return the alignment value
2738 #
2739 # @param self The object pointer
2740 # @retval True Successfully find alignment
2741 # @retval False Not able to find alignment
2742 #
2743 def _GetAlignment(self):
2744 if self._IsKeyword("Align", True):
2745 if not self._IsToken(TAB_EQUAL_SPLIT):
2746 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2747
2748 if not self._GetNextToken():
2749 raise Warning.Expected("alignment value", self.FileName, self.CurrentLineNumber)
2750 return True
2751
2752 return False
2753
2754 ## _GetSectionData() method
2755 #
2756 # Get section data for FILE statement
2757 #
2758 # @param self The object pointer
2759 # @param FfsFileObj for whom section is got
2760 #
2761 def _GetSectionData(self, FfsFileObj):
2762 self._GetDefineStatements(FfsFileObj)
2763
2764 while True:
2765 IsLeafSection = self._GetLeafSection(FfsFileObj)
2766 IsEncapSection = self._GetEncapsulationSec(FfsFileObj)
2767 if not IsLeafSection and not IsEncapSection:
2768 break
2769
2770 ## _GetLeafSection() method
2771 #
2772 # Get leaf section for Obj
2773 #
2774 # @param self The object pointer
2775 # @param Obj for whom leaf section is got
2776 # @retval True Successfully find section statement
2777 # @retval False Not able to find section statement
2778 #
2779 def _GetLeafSection(self, Obj):
2780 OldPos = self.GetFileBufferPos()
2781
2782 if not self._IsKeyword("SECTION"):
2783 if len(Obj.SectionList) == 0:
2784 raise Warning.Expected("SECTION", self.FileName, self.CurrentLineNumber)
2785 else:
2786 return False
2787
2788 AlignValue = None
2789 if self._GetAlignment():
2790 if self._Token not in ALIGNMENTS:
2791 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2792 AlignValue = self._Token
2793
2794 BuildNum = None
2795 if self._IsKeyword("BUILD_NUM"):
2796 if not self._IsToken(TAB_EQUAL_SPLIT):
2797 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2798
2799 if not self._GetNextToken():
2800 raise Warning.Expected("Build number value", self.FileName, self.CurrentLineNumber)
2801
2802 BuildNum = self._Token
2803
2804 if self._IsKeyword("VERSION"):
2805 if AlignValue == 'Auto':
2806 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2807 if not self._IsToken(TAB_EQUAL_SPLIT):
2808 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2809 if not self._GetNextToken():
2810 raise Warning.Expected("version", self.FileName, self.CurrentLineNumber)
2811 VerSectionObj = VerSection()
2812 VerSectionObj.Alignment = AlignValue
2813 VerSectionObj.BuildNum = BuildNum
2814 if self._GetStringData():
2815 VerSectionObj.StringData = self._Token
2816 else:
2817 VerSectionObj.FileName = self._Token
2818 Obj.SectionList.append(VerSectionObj)
2819
2820 elif self._IsKeyword(BINARY_FILE_TYPE_UI):
2821 if AlignValue == 'Auto':
2822 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2823 if not self._IsToken(TAB_EQUAL_SPLIT):
2824 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2825 if not self._GetNextToken():
2826 raise Warning.Expected("UI", self.FileName, self.CurrentLineNumber)
2827 UiSectionObj = UiSection()
2828 UiSectionObj.Alignment = AlignValue
2829 if self._GetStringData():
2830 UiSectionObj.StringData = self._Token
2831 else:
2832 UiSectionObj.FileName = self._Token
2833 Obj.SectionList.append(UiSectionObj)
2834
2835 elif self._IsKeyword("FV_IMAGE"):
2836 if AlignValue == 'Auto':
2837 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2838 if not self._IsToken(TAB_EQUAL_SPLIT):
2839 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2840 if not self._GetNextToken():
2841 raise Warning.Expected("FV name or FV file path", self.FileName, self.CurrentLineNumber)
2842
2843 FvName = self._Token
2844 FvObj = None
2845
2846 if self._IsToken("{"):
2847 FvObj = FV()
2848 FvObj.UiFvName = FvName.upper()
2849 self._GetDefineStatements(FvObj)
2850
2851 self._GetBlockStatement(FvObj)
2852 self._GetSetStatements(FvObj)
2853 self._GetFvAlignment(FvObj)
2854 self._GetFvAttributes(FvObj)
2855
2856 while True:
2857 IsInf = self._GetInfStatement(FvObj)
2858 IsFile = self._GetFileStatement(FvObj)
2859 if not IsInf and not IsFile:
2860 break
2861
2862 if not self._IsToken(T_CHAR_BRACE_R):
2863 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2864
2865 FvImageSectionObj = FvImageSection()
2866 FvImageSectionObj.Alignment = AlignValue
2867 if FvObj is not None:
2868 FvImageSectionObj.Fv = FvObj
2869 FvImageSectionObj.FvName = None
2870 else:
2871 FvImageSectionObj.FvName = FvName.upper()
2872 FvImageSectionObj.FvFileName = FvName
2873
2874 Obj.SectionList.append(FvImageSectionObj)
2875
2876 elif self._IsKeyword("PEI_DEPEX_EXP") or self._IsKeyword("DXE_DEPEX_EXP") or self._IsKeyword("SMM_DEPEX_EXP"):
2877 if AlignValue == 'Auto':
2878 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2879 DepexSectionObj = DepexSection()
2880 DepexSectionObj.Alignment = AlignValue
2881 DepexSectionObj.DepexType = self._Token
2882
2883 if not self._IsToken(TAB_EQUAL_SPLIT):
2884 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
2885 if not self._IsToken("{"):
2886 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
2887 if not self._SkipToToken(T_CHAR_BRACE_R):
2888 raise Warning.Expected("Depex expression ending '}'", self.FileName, self.CurrentLineNumber)
2889
2890 DepexSectionObj.Expression = self._SkippedChars.rstrip(T_CHAR_BRACE_R)
2891 Obj.SectionList.append(DepexSectionObj)
2892
2893 else:
2894 if not self._GetNextWord():
2895 raise Warning.Expected("section type", self.FileName, self.CurrentLineNumber)
2896
2897 # Encapsulation section appear, UndoToken and return
2898 if self._Token == "COMPRESS" or self._Token == "GUIDED":
2899 self.SetFileBufferPos(OldPos)
2900 return False
2901
2902 if self._Token not in {"COMPAT16", BINARY_FILE_TYPE_PE32, BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,\
2903 BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "SUBTYPE_GUID", BINARY_FILE_TYPE_SMM_DEPEX}:
2904 raise Warning("Unknown section type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
2905 if AlignValue == 'Auto'and (not self._Token == BINARY_FILE_TYPE_PE32) and (not self._Token == BINARY_FILE_TYPE_TE):
2906 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2907
2908 # DataSection
2909 DataSectionObj = DataSection()
2910 DataSectionObj.Alignment = AlignValue
2911 DataSectionObj.SecType = self._Token
2912
2913 if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
2914 if self._FileCouldHaveRelocFlag(Obj.FvFileType) and self._SectionCouldHaveRelocFlag(DataSectionObj.SecType):
2915 if self._Token == 'RELOCS_STRIPPED':
2916 DataSectionObj.KeepReloc = False
2917 else:
2918 DataSectionObj.KeepReloc = True
2919 else:
2920 raise Warning("File type %s, section type %s, could not have reloc strip flag%d" % (Obj.FvFileType, DataSectionObj.SecType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
2921
2922 if self._IsToken(TAB_EQUAL_SPLIT):
2923 if not self._GetNextToken():
2924 raise Warning.Expected("section file path", self.FileName, self.CurrentLineNumber)
2925 DataSectionObj.SectFileName = self._Token
2926 self._VerifyFile(DataSectionObj.SectFileName)
2927 else:
2928 if not self._GetCglSection(DataSectionObj):
2929 return False
2930
2931 Obj.SectionList.append(DataSectionObj)
2932
2933 return True
2934
2935 ## _VerifyFile
2936 #
2937 # Check if file exists or not:
2938 # If current phase if GenFds, the file must exist;
2939 # If current phase is AutoGen and the file is not in $(OUTPUT_DIRECTORY), the file must exist
2940 # @param FileName: File path to be verified.
2941 #
2942 def _VerifyFile(self, FileName):
2943 if FileName.replace(TAB_WORKSPACE, '').find('$') != -1:
2944 return
2945 if not GlobalData.gAutoGenPhase or not self._GetMacroValue(TAB_DSC_DEFINES_OUTPUT_DIRECTORY) in FileName:
2946 ErrorCode, ErrorInfo = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
2947 if ErrorCode != 0:
2948 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
2949
2950 ## _GetCglSection() method
2951 #
2952 # Get compressed or GUIDed section for Obj
2953 #
2954 # @param self The object pointer
2955 # @param Obj for whom leaf section is got
2956 # @param AlignValue alignment value for complex section
2957 # @retval True Successfully find section statement
2958 # @retval False Not able to find section statement
2959 #
2960 def _GetCglSection(self, Obj, AlignValue = None):
2961
2962 if self._IsKeyword("COMPRESS"):
2963 type = "PI_STD"
2964 if self._IsKeyword("PI_STD") or self._IsKeyword("PI_NONE"):
2965 type = self._Token
2966
2967 if not self._IsToken("{"):
2968 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
2969
2970 CompressSectionObj = CompressSection()
2971 CompressSectionObj.Alignment = AlignValue
2972 CompressSectionObj.CompType = type
2973 # Recursive sections...
2974 while True:
2975 IsLeafSection = self._GetLeafSection(CompressSectionObj)
2976 IsEncapSection = self._GetEncapsulationSec(CompressSectionObj)
2977 if not IsLeafSection and not IsEncapSection:
2978 break
2979
2980
2981 if not self._IsToken(T_CHAR_BRACE_R):
2982 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
2983 Obj.SectionList.append(CompressSectionObj)
2984 return True
2985
2986 elif self._IsKeyword("GUIDED"):
2987 GuidValue = None
2988 if self._GetNextGuid():
2989 GuidValue = self._Token
2990
2991 AttribDict = self._GetGuidAttrib()
2992 if not self._IsToken("{"):
2993 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
2994 GuidSectionObj = GuidSection()
2995 GuidSectionObj.Alignment = AlignValue
2996 GuidSectionObj.NameGuid = GuidValue
2997 GuidSectionObj.SectionType = "GUIDED"
2998 GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
2999 GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
3000 GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
3001 # Recursive sections...
3002 while True:
3003 IsLeafSection = self._GetLeafSection(GuidSectionObj)
3004 IsEncapSection = self._GetEncapsulationSec(GuidSectionObj)
3005 if not IsLeafSection and not IsEncapSection:
3006 break
3007
3008 if not self._IsToken(T_CHAR_BRACE_R):
3009 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
3010 Obj.SectionList.append(GuidSectionObj)
3011
3012 return True
3013
3014 return False
3015
3016 ## _GetGuidAttri() method
3017 #
3018 # Get attributes for GUID section
3019 #
3020 # @param self The object pointer
3021 # @retval AttribDict Dictionary of key-value pair of section attributes
3022 #
3023 def _GetGuidAttrib(self):
3024 AttribDict = {}
3025 AttribDict["PROCESSING_REQUIRED"] = "NONE"
3026 AttribDict["AUTH_STATUS_VALID"] = "NONE"
3027 AttribDict["EXTRA_HEADER_SIZE"] = -1
3028 while self._IsKeyword("PROCESSING_REQUIRED") or self._IsKeyword("AUTH_STATUS_VALID") \
3029 or self._IsKeyword("EXTRA_HEADER_SIZE"):
3030 AttribKey = self._Token
3031
3032 if not self._IsToken(TAB_EQUAL_SPLIT):
3033 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3034
3035 if not self._GetNextToken():
3036 raise Warning.Expected("TRUE(1)/FALSE(0)/Number", self.FileName, self.CurrentLineNumber)
3037 elif AttribKey == "EXTRA_HEADER_SIZE":
3038 Base = 10
3039 if self._Token[0:2].upper() == "0X":
3040 Base = 16
3041 try:
3042 AttribDict[AttribKey] = int(self._Token, Base)
3043 continue
3044 except ValueError:
3045 raise Warning.Expected("Number", self.FileName, self.CurrentLineNumber)
3046 elif self._Token.upper() not in {"TRUE", "FALSE", "1", "0"}:
3047 raise Warning.Expected("TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
3048 AttribDict[AttribKey] = self._Token
3049
3050 return AttribDict
3051
3052 ## _GetEncapsulationSec() method
3053 #
3054 # Get encapsulation section for FILE
3055 #
3056 # @param self The object pointer
3057 # @param FfsFile for whom section is got
3058 # @retval True Successfully find section statement
3059 # @retval False Not able to find section statement
3060 #
3061 def _GetEncapsulationSec(self, FfsFileObj):
3062 OldPos = self.GetFileBufferPos()
3063 if not self._IsKeyword("SECTION"):
3064 if len(FfsFileObj.SectionList) == 0:
3065 raise Warning.Expected("SECTION", self.FileName, self.CurrentLineNumber)
3066 else:
3067 return False
3068
3069 AlignValue = None
3070 if self._GetAlignment():
3071 if self._Token not in ALIGNMENT_NOAUTO:
3072 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
3073 AlignValue = self._Token
3074
3075 if not self._GetCglSection(FfsFileObj, AlignValue):
3076 self.SetFileBufferPos(OldPos)
3077 return False
3078 else:
3079 return True
3080
3081 def _GetFmp(self):
3082 if not self._GetNextToken():
3083 return False
3084 S = self._Token.upper()
3085 if S.startswith(TAB_SECTION_START) and not S.startswith("[FMPPAYLOAD."):
3086 self.SectionParser(S)
3087 self._UndoToken()
3088 return False
3089
3090 self._UndoToken()
3091 self._SkipToToken("[FMPPAYLOAD.", True)
3092 FmpUiName = self._GetUiName().upper()
3093 if FmpUiName in self.Profile.FmpPayloadDict:
3094 raise Warning("Duplicated FMP UI name found: %s" % FmpUiName, self.FileName, self.CurrentLineNumber)
3095
3096 FmpData = CapsulePayload()
3097 FmpData.UiName = FmpUiName
3098
3099 if not self._IsToken(TAB_SECTION_END):
3100 raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
3101
3102 if not self._GetNextToken():
3103 raise Warning("The FMP payload section is empty!", self.FileName, self.CurrentLineNumber)
3104 FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE', 'CERTIFICATE_GUID', 'MONOTONIC_COUNT']
3105 while self._Token in FmpKeyList:
3106 Name = self._Token
3107 FmpKeyList.remove(Name)
3108 if not self._IsToken(TAB_EQUAL_SPLIT):
3109 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3110 if Name == 'IMAGE_TYPE_ID':
3111 if not self._GetNextGuid():
3112 raise Warning.Expected("GUID value for IMAGE_TYPE_ID.", self.FileName, self.CurrentLineNumber)
3113 FmpData.ImageTypeId = self._Token
3114 elif Name == 'CERTIFICATE_GUID':
3115 if not self._GetNextGuid():
3116 raise Warning.Expected("GUID value for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
3117 FmpData.Certificate_Guid = self._Token
3118 if UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_RSA2048_SHA256_GUID and UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_PKCS7_GUID:
3119 raise Warning("Only support EFI_CERT_TYPE_RSA2048_SHA256_GUID or EFI_CERT_TYPE_PKCS7_GUID for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
3120 else:
3121 if not self._GetNextToken():
3122 raise Warning.Expected("value of %s" % Name, self.FileName, self.CurrentLineNumber)
3123 Value = self._Token
3124 if Name == 'IMAGE_HEADER_INIT_VERSION':
3125 if FdfParser._Verify(Name, Value, 'UINT8'):
3126 FmpData.Version = Value
3127 elif Name == 'IMAGE_INDEX':
3128 if FdfParser._Verify(Name, Value, 'UINT8'):
3129 FmpData.ImageIndex = Value
3130 elif Name == 'HARDWARE_INSTANCE':
3131 if FdfParser._Verify(Name, Value, 'UINT8'):
3132 FmpData.HardwareInstance = Value
3133 elif Name == 'MONOTONIC_COUNT':
3134 if FdfParser._Verify(Name, Value, 'UINT64'):
3135 FmpData.MonotonicCount = Value
3136 if FmpData.MonotonicCount.upper().startswith('0X'):
3137 FmpData.MonotonicCount = int(FmpData.MonotonicCount, 16)
3138 else:
3139 FmpData.MonotonicCount = int(FmpData.MonotonicCount)
3140 if not self._GetNextToken():
3141 break
3142 else:
3143 self._UndoToken()
3144
3145 if (FmpData.MonotonicCount and not FmpData.Certificate_Guid) or (not FmpData.MonotonicCount and FmpData.Certificate_Guid):
3146 EdkLogger.error("FdfParser", FORMAT_INVALID, "CERTIFICATE_GUID and MONOTONIC_COUNT must be work as a pair.")
3147
3148 # Only the IMAGE_TYPE_ID is required item
3149 if FmpKeyList and 'IMAGE_TYPE_ID' in FmpKeyList:
3150 raise Warning("'IMAGE_TYPE_ID' in FMP payload section.", self.FileName, self.CurrentLineNumber)
3151 # get the Image file and Vendor code file
3152 self._GetFMPCapsuleData(FmpData)
3153 if not FmpData.ImageFile:
3154 raise Warning("Missing image file in FMP payload section.", self.FileName, self.CurrentLineNumber)
3155 # check whether more than one Vendor code file
3156 if len(FmpData.VendorCodeFile) > 1:
3157 raise Warning("Vendor code file max of 1 per FMP payload section.", self.FileName, self.CurrentLineNumber)
3158 self.Profile.FmpPayloadDict[FmpUiName] = FmpData
3159 return True
3160
3161 ## _GetCapsule() method
3162 #
3163 # Get capsule section contents and store its data into capsule list of self.Profile
3164 #
3165 # @param self The object pointer
3166 # @retval True Successfully find a capsule
3167 # @retval False Not able to find a capsule
3168 #
3169 def _GetCapsule(self):
3170 if not self._GetNextToken():
3171 return False
3172
3173 S = self._Token.upper()
3174 if S.startswith(TAB_SECTION_START) and not S.startswith("[CAPSULE."):
3175 self.SectionParser(S)
3176 self._UndoToken()
3177 return False
3178
3179 self._UndoToken()
3180 if not self._IsToken("[CAPSULE.", True):
3181 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
3182 #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
3183 # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
3184 raise Warning.Expected("[Capsule.]", self.FileName, self.CurrentLineNumber)
3185
3186 CapsuleObj = Capsule()
3187
3188 CapsuleName = self._GetUiName()
3189 if not CapsuleName:
3190 raise Warning.Expected("capsule name", self.FileName, self.CurrentLineNumber)
3191
3192 CapsuleObj.UiCapsuleName = CapsuleName.upper()
3193
3194 if not self._IsToken(TAB_SECTION_END):
3195 raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
3196
3197 if self._IsKeyword("CREATE_FILE"):
3198 if not self._IsToken(TAB_EQUAL_SPLIT):
3199 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3200
3201 if not self._GetNextToken():
3202 raise Warning.Expected("file name", self.FileName, self.CurrentLineNumber)
3203
3204 CapsuleObj.CreateFile = self._Token
3205
3206 self._GetCapsuleStatements(CapsuleObj)
3207 self.Profile.CapsuleDict[CapsuleObj.UiCapsuleName] = CapsuleObj
3208 return True
3209
3210 ## _GetCapsuleStatements() method
3211 #
3212 # Get statements for capsule
3213 #
3214 # @param self The object pointer
3215 # @param Obj for whom statements are got
3216 #
3217 def _GetCapsuleStatements(self, Obj):
3218 self._GetCapsuleTokens(Obj)
3219 self._GetDefineStatements(Obj)
3220 self._GetSetStatements(Obj)
3221 self._GetCapsuleData(Obj)
3222
3223 ## _GetCapsuleTokens() method
3224 #
3225 # Get token statements for capsule
3226 #
3227 # @param self The object pointer
3228 # @param Obj for whom token statements are got
3229 #
3230 def _GetCapsuleTokens(self, Obj):
3231 if not self._GetNextToken():
3232 return False
3233 while self._Token in {"CAPSULE_GUID", "CAPSULE_HEADER_SIZE", "CAPSULE_FLAGS", "OEM_CAPSULE_FLAGS", "CAPSULE_HEADER_INIT_VERSION"}:
3234 Name = self._Token.strip()
3235 if not self._IsToken(TAB_EQUAL_SPLIT):
3236 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3237 if not self._GetNextToken():
3238 raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
3239 if Name == 'CAPSULE_FLAGS':
3240 if not self._Token in {"PersistAcrossReset", "PopulateSystemTable", "InitiateReset"}:
3241 raise Warning.Expected("PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)
3242 Value = self._Token.strip()
3243 while self._IsToken(TAB_COMMA_SPLIT):
3244 Value += TAB_COMMA_SPLIT
3245 if not self._GetNextToken():
3246 raise Warning.Expected("value", self.FileName, self.CurrentLineNumber)
3247 if not self._Token in {"PersistAcrossReset", "PopulateSystemTable", "InitiateReset"}:
3248 raise Warning.Expected("PersistAcrossReset, PopulateSystemTable, or InitiateReset", self.FileName, self.CurrentLineNumber)
3249 Value += self._Token.strip()
3250 elif Name == 'OEM_CAPSULE_FLAGS':
3251 Value = self._Token.strip()
3252 if not Value.upper().startswith('0X'):
3253 raise Warning.Expected("hex value starting with 0x", self.FileName, self.CurrentLineNumber)
3254 try:
3255 Value = int(Value, 0)
3256 except ValueError:
3257 raise Warning.Expected("hex string failed to convert to value", self.FileName, self.CurrentLineNumber)
3258 if not 0x0000 <= Value <= 0xFFFF:
3259 raise Warning.Expected("hex value between 0x0000 and 0xFFFF", self.FileName, self.CurrentLineNumber)
3260 Value = self._Token.strip()
3261 else:
3262 Value = self._Token.strip()
3263 Obj.TokensDict[Name] = Value
3264 if not self._GetNextToken():
3265 return False
3266 self._UndoToken()
3267
3268 ## _GetCapsuleData() method
3269 #
3270 # Get capsule data for capsule
3271 #
3272 # @param self The object pointer
3273 # @param Obj for whom capsule data are got
3274 #
3275 def _GetCapsuleData(self, Obj):
3276 while True:
3277 IsInf = self._GetInfStatement(Obj, True)
3278 IsFile = self._GetFileStatement(Obj, True)
3279 IsFv = self._GetFvStatement(Obj)
3280 IsFd = self._GetFdStatement(Obj)
3281 IsAnyFile = self._GetAnyFileStatement(Obj)
3282 IsAfile = self._GetAfileStatement(Obj)
3283 IsFmp = self._GetFmpStatement(Obj)
3284 if not (IsInf or IsFile or IsFv or IsFd or IsAnyFile or IsAfile or IsFmp):
3285 break
3286
3287 ## _GetFMPCapsuleData() method
3288 #
3289 # Get capsule data for FMP capsule
3290 #
3291 # @param self The object pointer
3292 # @param Obj for whom capsule data are got
3293 #
3294 def _GetFMPCapsuleData(self, Obj):
3295 while True:
3296 IsFv = self._GetFvStatement(Obj, True)
3297 IsFd = self._GetFdStatement(Obj, True)
3298 IsAnyFile = self._GetAnyFileStatement(Obj, True)
3299 if not (IsFv or IsFd or IsAnyFile):
3300 break
3301
3302 ## _GetFvStatement() method
3303 #
3304 # Get FV for capsule
3305 #
3306 # @param self The object pointer
3307 # @param CapsuleObj for whom FV is got
3308 # @retval True Successfully find a FV statement
3309 # @retval False Not able to find a FV statement
3310 #
3311 def _GetFvStatement(self, CapsuleObj, FMPCapsule = False):
3312 if not self._IsKeyword(BINARY_FILE_TYPE_FV):
3313 return False
3314
3315 if not self._IsToken(TAB_EQUAL_SPLIT):
3316 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3317
3318 if not self._GetNextToken():
3319 raise Warning.Expected("FV name", self.FileName, self.CurrentLineNumber)
3320
3321 if self._Token.upper() not in self.Profile.FvDict:
3322 raise Warning("FV name does not exist", self.FileName, self.CurrentLineNumber)
3323
3324 myCapsuleFv = CapsuleFv()
3325 myCapsuleFv.FvName = self._Token
3326 if FMPCapsule:
3327 if not CapsuleObj.ImageFile:
3328 CapsuleObj.ImageFile.append(myCapsuleFv)
3329 else:
3330 CapsuleObj.VendorCodeFile.append(myCapsuleFv)
3331 else:
3332 CapsuleObj.CapsuleDataList.append(myCapsuleFv)
3333 return True
3334
3335 ## _GetFdStatement() method
3336 #
3337 # Get FD for capsule
3338 #
3339 # @param self The object pointer
3340 # @param CapsuleObj for whom FD is got
3341 # @retval True Successfully find a FD statement
3342 # @retval False Not able to find a FD statement
3343 #
3344 def _GetFdStatement(self, CapsuleObj, FMPCapsule = False):
3345 if not self._IsKeyword("FD"):
3346 return False
3347
3348 if not self._IsToken(TAB_EQUAL_SPLIT):
3349 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3350
3351 if not self._GetNextToken():
3352 raise Warning.Expected("FD name", self.FileName, self.CurrentLineNumber)
3353
3354 if self._Token.upper() not in self.Profile.FdDict:
3355 raise Warning("FD name does not exist", self.FileName, self.CurrentLineNumber)
3356
3357 myCapsuleFd = CapsuleFd()
3358 myCapsuleFd.FdName = self._Token
3359 if FMPCapsule:
3360 if not CapsuleObj.ImageFile:
3361 CapsuleObj.ImageFile.append(myCapsuleFd)
3362 else:
3363 CapsuleObj.VendorCodeFile.append(myCapsuleFd)
3364 else:
3365 CapsuleObj.CapsuleDataList.append(myCapsuleFd)
3366 return True
3367
3368 def _GetFmpStatement(self, CapsuleObj):
3369 if not self._IsKeyword("FMP_PAYLOAD"):
3370 if not self._IsKeyword("FMP"):
3371 return False
3372
3373 if not self._IsKeyword("PAYLOAD"):
3374 self._UndoToken()
3375 return False
3376
3377 if not self._IsToken(TAB_EQUAL_SPLIT):
3378 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3379
3380 if not self._GetNextToken():
3381 raise Warning.Expected("payload name after FMP_PAYLOAD =", self.FileName, self.CurrentLineNumber)
3382 Payload = self._Token.upper()
3383 if Payload not in self.Profile.FmpPayloadDict:
3384 raise Warning("This FMP Payload does not exist: %s" % self._Token, self.FileName, self.CurrentLineNumber)
3385 CapsuleObj.FmpPayloadList.append(self.Profile.FmpPayloadDict[Payload])
3386 return True
3387
3388 def _ParseRawFileStatement(self):
3389 if not self._IsKeyword("FILE"):
3390 return None
3391
3392 if not self._IsKeyword("DATA"):
3393 self._UndoToken()
3394 return None
3395
3396 if not self._IsToken(TAB_EQUAL_SPLIT):
3397 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3398
3399 if not self._GetNextToken():
3400 raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
3401
3402 AnyFileName = self._Token
3403 self._VerifyFile(AnyFileName)
3404
3405 if not os.path.isabs(AnyFileName):
3406 AnyFileName = mws.join(GenFdsGlobalVariable.WorkSpaceDir, AnyFileName)
3407
3408 return AnyFileName
3409
3410 ## _GetAnyFileStatement() method
3411 #
3412 # Get AnyFile for capsule
3413 #
3414 # @param self The object pointer
3415 # @param CapsuleObj for whom AnyFile is got
3416 # @retval True Successfully find a Anyfile statement
3417 # @retval False Not able to find a AnyFile statement
3418 #
3419 def _GetAnyFileStatement(self, CapsuleObj, FMPCapsule = False):
3420 AnyFileName = self._ParseRawFileStatement()
3421 if not AnyFileName:
3422 return False
3423
3424 myCapsuleAnyFile = CapsuleAnyFile()
3425 myCapsuleAnyFile.FileName = AnyFileName
3426 if FMPCapsule:
3427 if not CapsuleObj.ImageFile:
3428 CapsuleObj.ImageFile.append(myCapsuleAnyFile)
3429 else:
3430 CapsuleObj.VendorCodeFile.append(myCapsuleAnyFile)
3431 else:
3432 CapsuleObj.CapsuleDataList.append(myCapsuleAnyFile)
3433 return True
3434
3435 ## _GetAfileStatement() method
3436 #
3437 # Get Afile for capsule
3438 #
3439 # @param self The object pointer
3440 # @param CapsuleObj for whom Afile is got
3441 # @retval True Successfully find a Afile statement
3442 # @retval False Not able to find a Afile statement
3443 #
3444 def _GetAfileStatement(self, CapsuleObj):
3445 if not self._IsKeyword("APPEND"):
3446 return False
3447
3448 if not self._IsToken(TAB_EQUAL_SPLIT):
3449 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3450
3451 if not self._GetNextToken():
3452 raise Warning.Expected("Afile name", self.FileName, self.CurrentLineNumber)
3453
3454 AfileName = self._Token
3455 AfileBaseName = os.path.basename(AfileName)
3456
3457 if os.path.splitext(AfileBaseName)[1] not in {".bin", ".BIN", ".Bin", ".dat", ".DAT", ".Dat", ".data", ".DATA", ".Data"}:
3458 raise Warning('invalid binary file type, should be one of "bin",BINARY_FILE_TYPE_BIN,"Bin","dat","DAT","Dat","data","DATA","Data"', \
3459 self.FileName, self.CurrentLineNumber)
3460
3461 if not os.path.isabs(AfileName):
3462 AfileName = GenFdsGlobalVariable.ReplaceWorkspaceMacro(AfileName)
3463 self._VerifyFile(AfileName)
3464 else:
3465 if not os.path.exists(AfileName):
3466 raise Warning('%s does not exist' % AfileName, self.FileName, self.CurrentLineNumber)
3467 else:
3468 pass
3469
3470 myCapsuleAfile = CapsuleAfile()
3471 myCapsuleAfile.FileName = AfileName
3472 CapsuleObj.CapsuleDataList.append(myCapsuleAfile)
3473 return True
3474
3475 ## _GetRule() method
3476 #
3477 # Get Rule section contents and store its data into rule list of self.Profile
3478 #
3479 # @param self The object pointer
3480 # @retval True Successfully find a Rule
3481 # @retval False Not able to find a Rule
3482 #
3483 def _GetRule(self):
3484 if not self._GetNextToken():
3485 return False
3486
3487 S = self._Token.upper()
3488 if S.startswith(TAB_SECTION_START) and not S.startswith("[RULE."):
3489 self.SectionParser(S)
3490 self._UndoToken()
3491 return False
3492 self._UndoToken()
3493 if not self._IsToken("[Rule.", True):
3494 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
3495 #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
3496 # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
3497 raise Warning.Expected("[Rule.]", self.FileName, self.CurrentLineNumber)
3498
3499 if not self._SkipToToken(TAB_SPLIT):
3500 raise Warning.Expected("'.'", self.FileName, self.CurrentLineNumber)
3501
3502 Arch = self._SkippedChars.rstrip(TAB_SPLIT)
3503 if Arch.upper() not in ARCH_SET_FULL:
3504 raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber)
3505
3506 ModuleType = self._GetModuleType()
3507
3508 TemplateName = ""
3509 if self._IsToken(TAB_SPLIT):
3510 if not self._GetNextWord():
3511 raise Warning.Expected("template name", self.FileName, self.CurrentLineNumber)
3512 TemplateName = self._Token
3513
3514 if not self._IsToken(TAB_SECTION_END):
3515 raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
3516
3517 RuleObj = self._GetRuleFileStatements()
3518 RuleObj.Arch = Arch.upper()
3519 RuleObj.ModuleType = ModuleType
3520 RuleObj.TemplateName = TemplateName
3521 if TemplateName == '':
3522 self.Profile.RuleDict['RULE' + \
3523 TAB_SPLIT + \
3524 Arch.upper() + \
3525 TAB_SPLIT + \
3526 ModuleType.upper() ] = RuleObj
3527 else:
3528 self.Profile.RuleDict['RULE' + \
3529 TAB_SPLIT + \
3530 Arch.upper() + \
3531 TAB_SPLIT + \
3532 ModuleType.upper() + \
3533 TAB_SPLIT + \
3534 TemplateName.upper() ] = RuleObj
3535 return True
3536
3537 ## _GetModuleType() method
3538 #
3539 # Return the module type
3540 #
3541 # @param self The object pointer
3542 # @retval string module type
3543 #
3544 def _GetModuleType(self):
3545 if not self._GetNextWord():
3546 raise Warning.Expected("Module type", self.FileName, self.CurrentLineNumber)
3547 if self._Token.upper() not in {
3548 SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM,
3549 SUP_MODULE_DXE_CORE, SUP_MODULE_DXE_DRIVER,
3550 SUP_MODULE_DXE_SAL_DRIVER, SUP_MODULE_DXE_SMM_DRIVER,
3551 SUP_MODULE_DXE_RUNTIME_DRIVER, SUP_MODULE_UEFI_DRIVER,
3552 SUP_MODULE_UEFI_APPLICATION, SUP_MODULE_USER_DEFINED,
3553 TAB_DEFAULT, SUP_MODULE_BASE,
3554 EDK_COMPONENT_TYPE_SECURITY_CORE,
3555 EDK_COMPONENT_TYPE_COMBINED_PEIM_DRIVER,
3556 EDK_COMPONENT_TYPE_PIC_PEIM,
3557 EDK_COMPONENT_TYPE_RELOCATABLE_PEIM, "PE32_PEIM",
3558 EDK_COMPONENT_TYPE_BS_DRIVER, EDK_COMPONENT_TYPE_RT_DRIVER,
3559 EDK_COMPONENT_TYPE_SAL_RT_DRIVER,
3560 EDK_COMPONENT_TYPE_APPLICATION, "ACPITABLE",
3561 SUP_MODULE_SMM_CORE, SUP_MODULE_MM_STANDALONE,
3562 SUP_MODULE_MM_CORE_STANDALONE}:
3563 raise Warning("Unknown Module type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
3564 return self._Token
3565
3566 ## _GetFileExtension() method
3567 #
3568 # Return the file extension
3569 #
3570 # @param self The object pointer
3571 # @retval string file name extension
3572 #
3573 def _GetFileExtension(self):
3574 if not self._IsToken(TAB_SPLIT):
3575 raise Warning.Expected("'.'", self.FileName, self.CurrentLineNumber)
3576
3577 Ext = ""
3578 if self._GetNextToken():
3579 if FileExtensionPattern.match(self._Token):
3580 Ext = self._Token
3581 return TAB_SPLIT + Ext
3582 else:
3583 raise Warning("Unknown file extension '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
3584
3585 else:
3586 raise Warning.Expected("file extension", self.FileName, self.CurrentLineNumber)
3587
3588 ## _GetRuleFileStatement() method
3589 #
3590 # Get rule contents
3591 #
3592 # @param self The object pointer
3593 # @retval Rule Rule object
3594 #
3595 def _GetRuleFileStatements(self):
3596 if not self._IsKeyword("FILE"):
3597 raise Warning.Expected("FILE", self.FileName, self.CurrentLineNumber)
3598
3599 if not self._GetNextWord():
3600 raise Warning.Expected("FFS type", self.FileName, self.CurrentLineNumber)
3601
3602 Type = self._Token.strip().upper()
3603 if Type not in {"RAW", "FREEFORM", SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM,
3604 "PEI_DXE_COMBO", "DRIVER", SUP_MODULE_DXE_CORE, EDK_COMPONENT_TYPE_APPLICATION,
3605 "FV_IMAGE", "SMM", SUP_MODULE_SMM_CORE, SUP_MODULE_MM_STANDALONE,
3606 SUP_MODULE_MM_CORE_STANDALONE}:
3607 raise Warning("Unknown FV type '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
3608
3609 if not self._IsToken(TAB_EQUAL_SPLIT):
3610 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3611
3612 if not self._IsKeyword("$(NAMED_GUID)"):
3613 if not self._GetNextWord():
3614 raise Warning.Expected("$(NAMED_GUID)", self.FileName, self.CurrentLineNumber)
3615 if self._Token == 'PCD':
3616 if not self._IsToken("("):
3617 raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
3618 PcdPair = self._GetNextPcdSettings()
3619 if not self._IsToken(")"):
3620 raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
3621 self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
3622
3623 NameGuid = self._Token
3624
3625 KeepReloc = None
3626 if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
3627 if self._FileCouldHaveRelocFlag(Type):
3628 if self._Token == 'RELOCS_STRIPPED':
3629 KeepReloc = False
3630 else:
3631 KeepReloc = True
3632 else:
3633 raise Warning("File type %s could not have reloc strip flag%d" % (Type, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3634
3635 KeyStringList = []
3636 if self._GetNextToken():
3637 if TokenFindPattern.match(self._Token):
3638 KeyStringList.append(self._Token)
3639 if self._IsToken(TAB_COMMA_SPLIT):
3640 while self._GetNextToken():
3641 if not TokenFindPattern.match(self._Token):
3642 raise Warning.Expected("KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
3643 KeyStringList.append(self._Token)
3644
3645 if not self._IsToken(TAB_COMMA_SPLIT):
3646 break
3647
3648 else:
3649 self._UndoToken()
3650
3651
3652 Fixed = False
3653 if self._IsKeyword("Fixed", True):
3654 Fixed = True
3655
3656 CheckSum = False
3657 if self._IsKeyword("CheckSum", True):
3658 CheckSum = True
3659
3660 AlignValue = ""
3661 if self._GetAlignment():
3662 if self._Token not in ALIGNMENTS:
3663 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
3664 #For FFS, Auto is default option same to ""
3665 if not self._Token == "Auto":
3666 AlignValue = self._Token
3667
3668 if self._IsToken("{"):
3669 # Complex file rule expected
3670 NewRule = RuleComplexFile()
3671 NewRule.FvFileType = Type
3672 NewRule.NameGuid = NameGuid
3673 NewRule.Alignment = AlignValue
3674 NewRule.CheckSum = CheckSum
3675 NewRule.Fixed = Fixed
3676 NewRule.KeyStringList = KeyStringList
3677 if KeepReloc is not None:
3678 NewRule.KeepReloc = KeepReloc
3679
3680 while True:
3681 IsEncapsulate = self._GetRuleEncapsulationSection(NewRule)
3682 IsLeaf = self._GetEfiSection(NewRule)
3683 if not IsEncapsulate and not IsLeaf:
3684 break
3685
3686 if not self._IsToken(T_CHAR_BRACE_R):
3687 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
3688
3689 return NewRule
3690
3691 else:
3692 # Simple file rule expected
3693 if not self._GetNextWord():
3694 raise Warning.Expected("leaf section type", self.FileName, self.CurrentLineNumber)
3695
3696 SectionName = self._Token
3697
3698 if SectionName not in {
3699 "COMPAT16", BINARY_FILE_TYPE_PE32,
3700 BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE",
3701 "RAW",BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI,
3702 BINARY_FILE_TYPE_PEI_DEPEX, "VERSION", "SUBTYPE_GUID",
3703 BINARY_FILE_TYPE_SMM_DEPEX}:
3704 raise Warning("Unknown leaf section name '%s'" % SectionName, self.FileName, self.CurrentLineNumber)
3705
3706
3707 if self._IsKeyword("Fixed", True):
3708 Fixed = True
3709
3710 if self._IsKeyword("CheckSum", True):
3711 CheckSum = True
3712
3713 SectAlignment = ""
3714 if self._GetAlignment():
3715 if self._Token not in ALIGNMENTS:
3716 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
3717 if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32) and (not SectionName == BINARY_FILE_TYPE_TE):
3718 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
3719 SectAlignment = self._Token
3720
3721 Ext = None
3722 if self._IsToken(TAB_VALUE_SPLIT):
3723 Ext = self._GetFileExtension()
3724 elif not self._GetNextToken():
3725 raise Warning.Expected("File name", self.FileName, self.CurrentLineNumber)
3726
3727 NewRule = RuleSimpleFile()
3728 NewRule.SectionType = SectionName
3729 NewRule.FvFileType = Type
3730 NewRule.NameGuid = NameGuid
3731 NewRule.Alignment = AlignValue
3732 NewRule.SectAlignment = SectAlignment
3733 NewRule.CheckSum = CheckSum
3734 NewRule.Fixed = Fixed
3735 NewRule.KeyStringList = KeyStringList
3736 if KeepReloc is not None:
3737 NewRule.KeepReloc = KeepReloc
3738 NewRule.FileExtension = Ext
3739 NewRule.FileName = self._Token
3740 return NewRule
3741
3742 ## _GetEfiSection() method
3743 #
3744 # Get section list for Rule
3745 #
3746 # @param self The object pointer
3747 # @param Obj for whom section is got
3748 # @retval True Successfully find section statement
3749 # @retval False Not able to find section statement
3750 #
3751 def _GetEfiSection(self, Obj):
3752 OldPos = self.GetFileBufferPos()
3753 if not self._GetNextWord():
3754 return False
3755 SectionName = self._Token
3756
3757 if SectionName not in {
3758 "COMPAT16", BINARY_FILE_TYPE_PE32,
3759 BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE, "FV_IMAGE",
3760 "RAW",BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI,
3761 BINARY_FILE_TYPE_PEI_DEPEX, "VERSION", "SUBTYPE_GUID",
3762 BINARY_FILE_TYPE_SMM_DEPEX, BINARY_FILE_TYPE_GUID}:
3763 self._UndoToken()
3764 return False
3765
3766 if SectionName == "FV_IMAGE":
3767 FvImageSectionObj = FvImageSection()
3768 if self._IsKeyword("FV_IMAGE"):
3769 pass
3770 if self._IsToken("{"):
3771 FvObj = FV()
3772 self._GetDefineStatements(FvObj)
3773 self._GetBlockStatement(FvObj)
3774 self._GetSetStatements(FvObj)
3775 self._GetFvAlignment(FvObj)
3776 self._GetFvAttributes(FvObj)
3777 self._GetAprioriSection(FvObj)
3778 self._GetAprioriSection(FvObj)
3779
3780 while True:
3781 IsInf = self._GetInfStatement(FvObj)
3782 IsFile = self._GetFileStatement(FvObj)
3783 if not IsInf and not IsFile:
3784 break
3785
3786 if not self._IsToken(T_CHAR_BRACE_R):
3787 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
3788 FvImageSectionObj.Fv = FvObj
3789 FvImageSectionObj.FvName = None
3790
3791 else:
3792 if not self._IsKeyword(BINARY_FILE_TYPE_FV):
3793 raise Warning.Expected("'FV'", self.FileName, self.CurrentLineNumber)
3794 FvImageSectionObj.FvFileType = self._Token
3795
3796 if self._GetAlignment():
3797 if self._Token not in ALIGNMENT_NOAUTO:
3798 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
3799 FvImageSectionObj.Alignment = self._Token
3800
3801 if self._IsToken(TAB_VALUE_SPLIT):
3802 FvImageSectionObj.FvFileExtension = self._GetFileExtension()
3803 elif self._GetNextToken():
3804 if self._Token not in {
3805 T_CHAR_BRACE_R, "COMPAT16", BINARY_FILE_TYPE_PE32,
3806 BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE,
3807 "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,
3808 BINARY_FILE_TYPE_UI, "VERSION",
3809 BINARY_FILE_TYPE_PEI_DEPEX, BINARY_FILE_TYPE_GUID,
3810 BINARY_FILE_TYPE_SMM_DEPEX}:
3811 FvImageSectionObj.FvFileName = self._Token
3812 else:
3813 self._UndoToken()
3814 else:
3815 raise Warning.Expected("FV file name", self.FileName, self.CurrentLineNumber)
3816
3817 Obj.SectionList.append(FvImageSectionObj)
3818 return True
3819
3820 EfiSectionObj = EfiSection()
3821 EfiSectionObj.SectionType = SectionName
3822
3823 if not self._GetNextToken():
3824 raise Warning.Expected("file type", self.FileName, self.CurrentLineNumber)
3825
3826 if self._Token == "STRING":
3827 if not self._RuleSectionCouldHaveString(EfiSectionObj.SectionType):
3828 raise Warning("%s section could NOT have string data%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3829
3830 if not self._IsToken(TAB_EQUAL_SPLIT):
3831 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3832
3833 if not self._GetNextToken():
3834 raise Warning.Expected("Quoted String", self.FileName, self.CurrentLineNumber)
3835
3836 if self._GetStringData():
3837 EfiSectionObj.StringData = self._Token
3838
3839 if self._IsKeyword("BUILD_NUM"):
3840 if not self._RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
3841 raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3842
3843 if not self._IsToken(TAB_EQUAL_SPLIT):
3844 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3845 if not self._GetNextToken():
3846 raise Warning.Expected("Build number", self.FileName, self.CurrentLineNumber)
3847 EfiSectionObj.BuildNum = self._Token
3848
3849 else:
3850 EfiSectionObj.FileType = self._Token
3851 self._CheckRuleSectionFileType(EfiSectionObj.SectionType, EfiSectionObj.FileType)
3852
3853 if self._IsKeyword("Optional"):
3854 if not self._RuleSectionCouldBeOptional(EfiSectionObj.SectionType):
3855 raise Warning("%s section could NOT be optional%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3856 EfiSectionObj.Optional = True
3857
3858 if self._IsKeyword("BUILD_NUM"):
3859 if not self._RuleSectionCouldHaveBuildNum(EfiSectionObj.SectionType):
3860 raise Warning("%s section could NOT have BUILD_NUM%d" % (EfiSectionObj.SectionType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
3861
3862 if not self._IsToken(TAB_EQUAL_SPLIT):
3863 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
3864 if not self._GetNextToken():
3865 raise Warning.Expected("Build number", self.FileName, self.CurrentLineNumber)
3866 EfiSectionObj.BuildNum = self._Token
3867
3868 if self._GetAlignment():
3869 if self._Token not in ALIGNMENTS:
3870 raise Warning("Incorrect alignment '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
3871 if self._Token == 'Auto' and (not SectionName == BINARY_FILE_TYPE_PE32) and (not SectionName == BINARY_FILE_TYPE_TE):
3872 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
3873 EfiSectionObj.Alignment = self._Token
3874
3875 if self._IsKeyword('RELOCS_STRIPPED') or self._IsKeyword('RELOCS_RETAINED'):
3876 if self._SectionCouldHaveRelocFlag(EfiSectionObj.SectionType):
3877 if self._Token == 'RELOCS_STRIPPED':
3878 EfiSectionObj.KeepReloc = False
3879 else:
3880 EfiSectionObj.KeepReloc = True
3881 if Obj.KeepReloc is not None and Obj.KeepReloc != EfiSectionObj.KeepReloc:
3882 raise Warning("Section type %s has reloc strip flag conflict with Rule" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber)
3883 else:
3884 raise Warning("Section type %s could not have reloc strip flag" % EfiSectionObj.SectionType, self.FileName, self.CurrentLineNumber)
3885
3886
3887 if self._IsToken(TAB_VALUE_SPLIT):
3888 EfiSectionObj.FileExtension = self._GetFileExtension()
3889 elif self._GetNextToken():
3890 if self._Token not in {
3891 T_CHAR_BRACE_R, "COMPAT16", BINARY_FILE_TYPE_PE32,
3892 BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_TE,
3893 "FV_IMAGE", "RAW", BINARY_FILE_TYPE_DXE_DEPEX,
3894 BINARY_FILE_TYPE_UI, "VERSION",
3895 BINARY_FILE_TYPE_PEI_DEPEX, BINARY_FILE_TYPE_GUID,
3896 BINARY_FILE_TYPE_SMM_DEPEX}:
3897
3898 if self._Token.startswith('PCD'):
3899 self._UndoToken()
3900 self._GetNextWord()
3901
3902 if self._Token == 'PCD':
3903 if not self._IsToken("("):
3904 raise Warning.Expected("'('", self.FileName, self.CurrentLineNumber)
3905 PcdPair = self._GetNextPcdSettings()
3906 if not self._IsToken(")"):
3907 raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
3908 self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
3909
3910 EfiSectionObj.FileName = self._Token
3911
3912 else:
3913 self._UndoToken()
3914 else:
3915 raise Warning.Expected("section file name", self.FileName, self.CurrentLineNumber)
3916
3917 Obj.SectionList.append(EfiSectionObj)
3918 return True
3919
3920 ## _RuleSectionCouldBeOptional() method
3921 #
3922 # Get whether a section could be optional
3923 #
3924 # @param SectionType The section type to check
3925 # @retval True section could be optional
3926 # @retval False section never optional
3927 #
3928 @staticmethod
3929 def _RuleSectionCouldBeOptional(SectionType):
3930 if SectionType in {BINARY_FILE_TYPE_DXE_DEPEX, BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "RAW", BINARY_FILE_TYPE_SMM_DEPEX}:
3931 return True
3932 else:
3933 return False
3934
3935 ## _RuleSectionCouldHaveBuildNum() method
3936 #
3937 # Get whether a section could have build number information
3938 #
3939 # @param SectionType The section type to check
3940 # @retval True section could have build number information
3941 # @retval False section never have build number information
3942 #
3943 @staticmethod
3944 def _RuleSectionCouldHaveBuildNum(SectionType):
3945 if SectionType == "VERSION":
3946 return True
3947 else:
3948 return False
3949
3950 ## _RuleSectionCouldHaveString() method
3951 #
3952 # Get whether a section could have string
3953 #
3954 # @param SectionType The section type to check
3955 # @retval True section could have string
3956 # @retval False section never have string
3957 #
3958 @staticmethod
3959 def _RuleSectionCouldHaveString(SectionType):
3960 if SectionType in {BINARY_FILE_TYPE_UI, "VERSION"}:
3961 return True
3962 else:
3963 return False
3964
3965 ## _CheckRuleSectionFileType() method
3966 #
3967 # Get whether a section matches a file type
3968 #
3969 # @param self The object pointer
3970 # @param SectionType The section type to check
3971 # @param FileType The file type to check
3972 #
3973 def _CheckRuleSectionFileType(self, SectionType, FileType):
3974 WarningString = "Incorrect section file type '%s'"
3975 if SectionType == "COMPAT16":
3976 if FileType not in {"COMPAT16", "SEC_COMPAT16"}:
3977 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
3978 elif SectionType == BINARY_FILE_TYPE_PE32:
3979 if FileType not in {BINARY_FILE_TYPE_PE32, "SEC_PE32"}:
3980 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
3981 elif SectionType == BINARY_FILE_TYPE_PIC:
3982 if FileType not in {BINARY_FILE_TYPE_PIC, BINARY_FILE_TYPE_PIC}:
3983 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
3984 elif SectionType == BINARY_FILE_TYPE_TE:
3985 if FileType not in {BINARY_FILE_TYPE_TE, "SEC_TE"}:
3986 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
3987 elif SectionType == "RAW":
3988 if FileType not in {BINARY_FILE_TYPE_BIN, "SEC_BIN", "RAW", "ASL", "ACPI"}:
3989 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
3990 elif SectionType == BINARY_FILE_TYPE_DXE_DEPEX or SectionType == BINARY_FILE_TYPE_SMM_DEPEX:
3991 if FileType not in {BINARY_FILE_TYPE_DXE_DEPEX, "SEC_DXE_DEPEX", BINARY_FILE_TYPE_SMM_DEPEX}:
3992 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
3993 elif SectionType == BINARY_FILE_TYPE_UI:
3994 if FileType not in {BINARY_FILE_TYPE_UI, "SEC_UI"}:
3995 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
3996 elif SectionType == "VERSION":
3997 if FileType not in {"VERSION", "SEC_VERSION"}:
3998 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
3999 elif SectionType == BINARY_FILE_TYPE_PEI_DEPEX:
4000 if FileType not in {BINARY_FILE_TYPE_PEI_DEPEX, "SEC_PEI_DEPEX"}:
4001 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
4002 elif SectionType == BINARY_FILE_TYPE_GUID:
4003 if FileType not in {BINARY_FILE_TYPE_PE32, "SEC_GUID"}:
4004 raise Warning(WarningString % FileType, self.FileName, self.CurrentLineNumber)
4005
4006 ## _GetRuleEncapsulationSection() method
4007 #
4008 # Get encapsulation section for Rule
4009 #
4010 # @param self The object pointer
4011 # @param theRule for whom section is got
4012 # @retval True Successfully find section statement
4013 # @retval False Not able to find section statement
4014 #
4015 def _GetRuleEncapsulationSection(self, theRule):
4016 if self._IsKeyword("COMPRESS"):
4017 Type = "PI_STD"
4018 if self._IsKeyword("PI_STD") or self._IsKeyword("PI_NONE"):
4019 Type = self._Token
4020
4021 if not self._IsToken("{"):
4022 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
4023
4024 CompressSectionObj = CompressSection()
4025
4026 CompressSectionObj.CompType = Type
4027 # Recursive sections...
4028 while True:
4029 IsEncapsulate = self._GetRuleEncapsulationSection(CompressSectionObj)
4030 IsLeaf = self._GetEfiSection(CompressSectionObj)
4031 if not IsEncapsulate and not IsLeaf:
4032 break
4033
4034 if not self._IsToken(T_CHAR_BRACE_R):
4035 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
4036 theRule.SectionList.append(CompressSectionObj)
4037
4038 return True
4039
4040 elif self._IsKeyword("GUIDED"):
4041 GuidValue = None
4042 if self._GetNextGuid():
4043 GuidValue = self._Token
4044
4045 if self._IsKeyword("$(NAMED_GUID)"):
4046 GuidValue = self._Token
4047
4048 AttribDict = self._GetGuidAttrib()
4049
4050 if not self._IsToken("{"):
4051 raise Warning.ExpectedCurlyOpen(self.FileName, self.CurrentLineNumber)
4052 GuidSectionObj = GuidSection()
4053 GuidSectionObj.NameGuid = GuidValue
4054 GuidSectionObj.SectionType = "GUIDED"
4055 GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
4056 GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
4057 GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
4058
4059 # Efi sections...
4060 while True:
4061 IsEncapsulate = self._GetRuleEncapsulationSection(GuidSectionObj)
4062 IsLeaf = self._GetEfiSection(GuidSectionObj)
4063 if not IsEncapsulate and not IsLeaf:
4064 break
4065
4066 if not self._IsToken(T_CHAR_BRACE_R):
4067 raise Warning.ExpectedCurlyClose(self.FileName, self.CurrentLineNumber)
4068 theRule.SectionList.append(GuidSectionObj)
4069
4070 return True
4071
4072 return False
4073
4074 ## _GetOptionRom() method
4075 #
4076 # Get OptionROM section contents and store its data into OptionROM list of self.Profile
4077 #
4078 # @param self The object pointer
4079 # @retval True Successfully find a OptionROM
4080 # @retval False Not able to find a OptionROM
4081 #
4082 def _GetOptionRom(self):
4083 if not self._GetNextToken():
4084 return False
4085
4086 S = self._Token.upper()
4087 if S.startswith(TAB_SECTION_START) and not S.startswith("[OPTIONROM."):
4088 self.SectionParser(S)
4089 self._UndoToken()
4090 return False
4091
4092 self._UndoToken()
4093 if not self._IsToken("[OptionRom.", True):
4094 raise Warning("Unknown Keyword '%s'" % self._Token, self.FileName, self.CurrentLineNumber)
4095
4096 OptRomName = self._GetUiName()
4097
4098 if not self._IsToken(TAB_SECTION_END):
4099 raise Warning.ExpectedBracketClose(self.FileName, self.CurrentLineNumber)
4100
4101 OptRomObj = OPTIONROM(OptRomName)
4102 self.Profile.OptRomDict[OptRomName] = OptRomObj
4103
4104 while True:
4105 isInf = self._GetOptRomInfStatement(OptRomObj)
4106 isFile = self._GetOptRomFileStatement(OptRomObj)
4107 if not isInf and not isFile:
4108 break
4109
4110 return True
4111
4112 ## _GetOptRomInfStatement() method
4113 #
4114 # Get INF statements
4115 #
4116 # @param self The object pointer
4117 # @param Obj for whom inf statement is got
4118 # @retval True Successfully find inf statement
4119 # @retval False Not able to find inf statement
4120 #
4121 def _GetOptRomInfStatement(self, Obj):
4122 if not self._IsKeyword("INF"):
4123 return False
4124
4125 ffsInf = OptRomInfStatement()
4126 self._GetInfOptions(ffsInf)
4127
4128 if not self._GetNextToken():
4129 raise Warning.Expected("INF file path", self.FileName, self.CurrentLineNumber)
4130 ffsInf.InfFileName = self._Token
4131 if ffsInf.InfFileName.replace(TAB_WORKSPACE, '').find('$') == -1:
4132 #check for file path
4133 ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
4134 if ErrorCode != 0:
4135 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
4136
4137 NewFileName = ffsInf.InfFileName
4138 if ffsInf.OverrideGuid:
4139 NewFileName = ProcessDuplicatedInf(PathClass(ffsInf.InfFileName,GenFdsGlobalVariable.WorkSpaceDir), ffsInf.OverrideGuid, GenFdsGlobalVariable.WorkSpaceDir).Path
4140
4141 if not NewFileName in self.Profile.InfList:
4142 self.Profile.InfList.append(NewFileName)
4143 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
4144 self.Profile.InfFileLineList.append(FileLineTuple)
4145 if ffsInf.UseArch:
4146 if ffsInf.UseArch not in self.Profile.InfDict:
4147 self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
4148 else:
4149 self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
4150 else:
4151 self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
4152
4153
4154 self._GetOptRomOverrides (ffsInf)
4155
4156 Obj.FfsList.append(ffsInf)
4157 return True
4158
4159 ## _GetOptRomOverrides() method
4160 #
4161 # Get overrides for OptROM INF & FILE
4162 #
4163 # @param self The object pointer
4164 # @param FfsInfObj for whom overrides is got
4165 #
4166 def _GetOptRomOverrides(self, Obj):
4167 if self._IsToken('{'):
4168 Overrides = OverrideAttribs()
4169 while True:
4170 if self._IsKeyword("PCI_VENDOR_ID"):
4171 if not self._IsToken(TAB_EQUAL_SPLIT):
4172 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
4173 if not self._GetNextHexNumber():
4174 raise Warning.Expected("Hex vendor id", self.FileName, self.CurrentLineNumber)
4175 Overrides.PciVendorId = self._Token
4176 continue
4177
4178 if self._IsKeyword("PCI_CLASS_CODE"):
4179 if not self._IsToken(TAB_EQUAL_SPLIT):
4180 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
4181 if not self._GetNextHexNumber():
4182 raise Warning.Expected("Hex class code", self.FileName, self.CurrentLineNumber)
4183 Overrides.PciClassCode = self._Token
4184 continue
4185
4186 if self._IsKeyword("PCI_DEVICE_ID"):
4187 if not self._IsToken(TAB_EQUAL_SPLIT):
4188 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
4189 # Get a list of PCI IDs
4190 Overrides.PciDeviceId = ""
4191 while (self._GetNextHexNumber()):
4192 Overrides.PciDeviceId = "{} {}".format(Overrides.PciDeviceId, self._Token)
4193 if not Overrides.PciDeviceId:
4194 raise Warning.Expected("one or more Hex device ids", self.FileName, self.CurrentLineNumber)
4195 continue
4196
4197 if self._IsKeyword("PCI_REVISION"):
4198 if not self._IsToken(TAB_EQUAL_SPLIT):
4199 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
4200 if not self._GetNextHexNumber():
4201 raise Warning.Expected("Hex revision", self.FileName, self.CurrentLineNumber)
4202 Overrides.PciRevision = self._Token
4203 continue
4204
4205 if self._IsKeyword("PCI_COMPRESS"):
4206 if not self._IsToken(TAB_EQUAL_SPLIT):
4207 raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
4208 if not self._GetNextToken():
4209 raise Warning.Expected("TRUE/FALSE for compress", self.FileName, self.CurrentLineNumber)
4210 Overrides.NeedCompress = self._Token.upper() == 'TRUE'
4211 continue
4212
4213 if self._IsToken(T_CHAR_BRACE_R):
4214 break
4215 else:
4216 EdkLogger.error("FdfParser", FORMAT_INVALID, File=self.FileName, Line=self.CurrentLineNumber)
4217
4218 Obj.OverrideAttribs = Overrides
4219
4220 ## _GetOptRomFileStatement() method
4221 #
4222 # Get FILE statements
4223 #
4224 # @param self The object pointer
4225 # @param Obj for whom FILE statement is got
4226 # @retval True Successfully find FILE statement
4227 # @retval False Not able to find FILE statement
4228 #
4229 def _GetOptRomFileStatement(self, Obj):
4230 if not self._IsKeyword("FILE"):
4231 return False
4232
4233 FfsFileObj = OptRomFileStatement()
4234
4235 if not self._IsKeyword("EFI") and not self._IsKeyword(BINARY_FILE_TYPE_BIN):
4236 raise Warning.Expected("Binary type (EFI/BIN)", self.FileName, self.CurrentLineNumber)
4237 FfsFileObj.FileType = self._Token
4238
4239 if not self._GetNextToken():
4240 raise Warning.Expected("File path", self.FileName, self.CurrentLineNumber)
4241 FfsFileObj.FileName = self._Token
4242 if FfsFileObj.FileName.replace(TAB_WORKSPACE, '').find('$') == -1:
4243 #check for file path
4244 ErrorCode, ErrorInfo = PathClass(NormPath(FfsFileObj.FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
4245 if ErrorCode != 0:
4246 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
4247
4248 if FfsFileObj.FileType == 'EFI':
4249 self._GetOptRomOverrides(FfsFileObj)
4250
4251 Obj.FfsList.append(FfsFileObj)
4252
4253 return True
4254
4255 ## _GetCapInFd() method
4256 #
4257 # Get Cap list contained in FD
4258 #
4259 # @param self The object pointer
4260 # @param FdName FD name
4261 # @retval CapList List of Capsule in FD
4262 #
4263 def _GetCapInFd (self, FdName):
4264 CapList = []
4265 if FdName.upper() in self.Profile.FdDict:
4266 FdObj = self.Profile.FdDict[FdName.upper()]
4267 for elementRegion in FdObj.RegionList:
4268 if elementRegion.RegionType == 'CAPSULE':
4269 for elementRegionData in elementRegion.RegionDataList:
4270 if elementRegionData.endswith(".cap"):
4271 continue
4272 if elementRegionData is not None and elementRegionData.upper() not in CapList:
4273 CapList.append(elementRegionData.upper())
4274 return CapList
4275
4276 ## _GetReferencedFdCapTuple() method
4277 #
4278 # Get FV and FD list referenced by a capsule image
4279 #
4280 # @param self The object pointer
4281 # @param CapObj Capsule section to be searched
4282 # @param RefFdList referenced FD by section
4283 # @param RefFvList referenced FV by section
4284 #
4285 def _GetReferencedFdCapTuple(self, CapObj, RefFdList = [], RefFvList = []):
4286 for CapsuleDataObj in CapObj.CapsuleDataList:
4287 if hasattr(CapsuleDataObj, 'FvName') and CapsuleDataObj.FvName is not None and CapsuleDataObj.FvName.upper() not in RefFvList:
4288 RefFvList.append (CapsuleDataObj.FvName.upper())
4289 elif hasattr(CapsuleDataObj, 'FdName') and CapsuleDataObj.FdName is not None and CapsuleDataObj.FdName.upper() not in RefFdList:
4290 RefFdList.append (CapsuleDataObj.FdName.upper())
4291 elif CapsuleDataObj.Ffs is not None:
4292 if isinstance(CapsuleDataObj.Ffs, FileStatement):
4293 if CapsuleDataObj.Ffs.FvName is not None and CapsuleDataObj.Ffs.FvName.upper() not in RefFvList:
4294 RefFvList.append(CapsuleDataObj.Ffs.FvName.upper())
4295 elif CapsuleDataObj.Ffs.FdName is not None and CapsuleDataObj.Ffs.FdName.upper() not in RefFdList:
4296 RefFdList.append(CapsuleDataObj.Ffs.FdName.upper())
4297 else:
4298 self._GetReferencedFdFvTupleFromSection(CapsuleDataObj.Ffs, RefFdList, RefFvList)
4299
4300 ## _GetFvInFd() method
4301 #
4302 # Get FV list contained in FD
4303 #
4304 # @param self The object pointer
4305 # @param FdName FD name
4306 # @retval FvList list of FV in FD
4307 #
4308 def _GetFvInFd (self, FdName):
4309 FvList = []
4310 if FdName.upper() in self.Profile.FdDict:
4311 FdObj = self.Profile.FdDict[FdName.upper()]
4312 for elementRegion in FdObj.RegionList:
4313 if elementRegion.RegionType == BINARY_FILE_TYPE_FV:
4314 for elementRegionData in elementRegion.RegionDataList:
4315 if elementRegionData.endswith(".fv"):
4316 continue
4317 if elementRegionData is not None and elementRegionData.upper() not in FvList:
4318 FvList.append(elementRegionData.upper())
4319 return FvList
4320
4321 ## _GetReferencedFdFvTuple() method
4322 #
4323 # Get FD and FV list referenced by a FFS file
4324 #
4325 # @param self The object pointer
4326 # @param FfsFile contains sections to be searched
4327 # @param RefFdList referenced FD by section
4328 # @param RefFvList referenced FV by section
4329 #
4330 def _GetReferencedFdFvTuple(self, FvObj, RefFdList = [], RefFvList = []):
4331 for FfsObj in FvObj.FfsList:
4332 if isinstance(FfsObj, FileStatement):
4333 if FfsObj.FvName is not None and FfsObj.FvName.upper() not in RefFvList:
4334 RefFvList.append(FfsObj.FvName.upper())
4335 elif FfsObj.FdName is not None and FfsObj.FdName.upper() not in RefFdList:
4336 RefFdList.append(FfsObj.FdName.upper())
4337 else:
4338 self._GetReferencedFdFvTupleFromSection(FfsObj, RefFdList, RefFvList)
4339
4340 ## _GetReferencedFdFvTupleFromSection() method
4341 #
4342 # Get FD and FV list referenced by a FFS section
4343 #
4344 # @param self The object pointer
4345 # @param FfsFile contains sections to be searched
4346 # @param FdList referenced FD by section
4347 # @param FvList referenced FV by section
4348 #
4349 def _GetReferencedFdFvTupleFromSection(self, FfsFile, FdList = [], FvList = []):
4350 SectionStack = list(FfsFile.SectionList)
4351 while SectionStack != []:
4352 SectionObj = SectionStack.pop()
4353 if isinstance(SectionObj, FvImageSection):
4354 if SectionObj.FvName is not None and SectionObj.FvName.upper() not in FvList:
4355 FvList.append(SectionObj.FvName.upper())
4356 if SectionObj.Fv is not None and SectionObj.Fv.UiFvName is not None and SectionObj.Fv.UiFvName.upper() not in FvList:
4357 FvList.append(SectionObj.Fv.UiFvName.upper())
4358 self._GetReferencedFdFvTuple(SectionObj.Fv, FdList, FvList)
4359
4360 if isinstance(SectionObj, CompressSection) or isinstance(SectionObj, GuidSection):
4361 SectionStack.extend(SectionObj.SectionList)
4362
4363 ## CycleReferenceCheck() method
4364 #
4365 # Check whether cycle reference exists in FDF
4366 #
4367 # @param self The object pointer
4368 # @retval True cycle reference exists
4369 # @retval False Not exists cycle reference
4370 #
4371 def CycleReferenceCheck(self):
4372 #
4373 # Check the cycle between FV and FD image
4374 #
4375 MaxLength = len (self.Profile.FvDict)
4376 for FvName in self.Profile.FvDict:
4377 LogStr = "\nCycle Reference Checking for FV: %s\n" % FvName
4378 RefFvStack = set(FvName)
4379 FdAnalyzedList = set()
4380
4381 Index = 0
4382 while RefFvStack and Index < MaxLength:
4383 Index = Index + 1
4384 FvNameFromStack = RefFvStack.pop()
4385 if FvNameFromStack.upper() in self.Profile.FvDict:
4386 FvObj = self.Profile.FvDict[FvNameFromStack.upper()]
4387 else:
4388 continue
4389
4390 RefFdList = []
4391 RefFvList = []
4392 self._GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
4393
4394 for RefFdName in RefFdList:
4395 if RefFdName in FdAnalyzedList:
4396 continue
4397
4398 LogStr += "FV %s contains FD %s\n" % (FvNameFromStack, RefFdName)
4399 FvInFdList = self._GetFvInFd(RefFdName)
4400 if FvInFdList != []:
4401 for FvNameInFd in FvInFdList:
4402 LogStr += "FD %s contains FV %s\n" % (RefFdName, FvNameInFd)
4403 if FvNameInFd not in RefFvStack:
4404 RefFvStack.add(FvNameInFd)
4405
4406 if FvName in RefFvStack or FvNameFromStack in RefFvStack:
4407 EdkLogger.info(LogStr)
4408 return True
4409 FdAnalyzedList.add(RefFdName)
4410
4411 for RefFvName in RefFvList:
4412 LogStr += "FV %s contains FV %s\n" % (FvNameFromStack, RefFvName)
4413 if RefFvName not in RefFvStack:
4414 RefFvStack.add(RefFvName)
4415
4416 if FvName in RefFvStack or FvNameFromStack in RefFvStack:
4417 EdkLogger.info(LogStr)
4418 return True
4419
4420 #
4421 # Check the cycle between Capsule and FD image
4422 #
4423 MaxLength = len (self.Profile.CapsuleDict)
4424 for CapName in self.Profile.CapsuleDict:
4425 #
4426 # Capsule image to be checked.
4427 #
4428 LogStr = "\n\n\nCycle Reference Checking for Capsule: %s\n" % CapName
4429 RefCapStack = {CapName}
4430 FdAnalyzedList = set()
4431 FvAnalyzedList = set()
4432
4433 Index = 0
4434 while RefCapStack and Index < MaxLength:
4435 Index = Index + 1
4436 CapNameFromStack = RefCapStack.pop()
4437 if CapNameFromStack.upper() in self.Profile.CapsuleDict:
4438 CapObj = self.Profile.CapsuleDict[CapNameFromStack.upper()]
4439 else:
4440 continue
4441
4442 RefFvList = []
4443 RefFdList = []
4444 self._GetReferencedFdCapTuple(CapObj, RefFdList, RefFvList)
4445
4446 FvListLength = 0
4447 FdListLength = 0
4448 while FvListLength < len (RefFvList) or FdListLength < len (RefFdList):
4449 for RefFdName in RefFdList:
4450 if RefFdName in FdAnalyzedList:
4451 continue
4452
4453 LogStr += "Capsule %s contains FD %s\n" % (CapNameFromStack, RefFdName)
4454 for CapNameInFd in self._GetCapInFd(RefFdName):
4455 LogStr += "FD %s contains Capsule %s\n" % (RefFdName, CapNameInFd)
4456 if CapNameInFd not in RefCapStack:
4457 RefCapStack.append(CapNameInFd)
4458
4459 if CapName in RefCapStack or CapNameFromStack in RefCapStack:
4460 EdkLogger.info(LogStr)
4461 return True
4462
4463 for FvNameInFd in self._GetFvInFd(RefFdName):
4464 LogStr += "FD %s contains FV %s\n" % (RefFdName, FvNameInFd)
4465 if FvNameInFd not in RefFvList:
4466 RefFvList.append(FvNameInFd)
4467
4468 FdAnalyzedList.add(RefFdName)
4469 #
4470 # the number of the parsed FV and FD image
4471 #
4472 FvListLength = len (RefFvList)
4473 FdListLength = len (RefFdList)
4474 for RefFvName in RefFvList:
4475 if RefFvName in FvAnalyzedList:
4476 continue
4477 LogStr += "Capsule %s contains FV %s\n" % (CapNameFromStack, RefFvName)
4478 if RefFvName.upper() in self.Profile.FvDict:
4479 FvObj = self.Profile.FvDict[RefFvName.upper()]
4480 else:
4481 continue
4482 self._GetReferencedFdFvTuple(FvObj, RefFdList, RefFvList)
4483 FvAnalyzedList.add(RefFvName)
4484
4485 return False
4486
4487 def GetAllIncludedFile (self):
4488 global AllIncludeFileList
4489 return AllIncludeFileList
4490
4491 if __name__ == "__main__":
4492 import sys
4493 try:
4494 test_file = sys.argv[1]
4495 except IndexError as v:
4496 print("Usage: %s filename" % sys.argv[0])
4497 sys.exit(1)
4498
4499 parser = FdfParser(test_file)
4500 try:
4501 parser.ParseFile()
4502 parser.CycleReferenceCheck()
4503 except Warning as X:
4504 print(str(X))
4505 else:
4506 print("Success!")
4507