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