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