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