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