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