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