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