67217c3b89e3b7f17c4c91a8fd8ff4126c979dd1
[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 import re
21
22 import Fd
23 import Region
24 import Fv
25 import AprioriSection
26 import FfsInfStatement
27 import FfsFileStatement
28 import VerSection
29 import UiSection
30 import FvImageSection
31 import DataSection
32 import DepexSection
33 import CompressSection
34 import GuidSection
35 import Capsule
36 import CapsuleData
37 import Rule
38 import RuleComplexFile
39 import RuleSimpleFile
40 import EfiSection
41 import Vtf
42 import ComponentStatement
43 import OptionRom
44 import OptRomInfStatement
45 import OptRomFileStatement
46 import string
47
48 from GenFdsGlobalVariable import GenFdsGlobalVariable
49 from Common.BuildToolError import *
50 from Common import EdkLogger
51 from Common.Misc import PathClass
52 from Common.StringUtils import NormPath
53 import Common.GlobalData as GlobalData
54 from Common.Expression import *
55 from Common import GlobalData
56 from Common.DataType import *
57 from Common.StringUtils import ReplaceMacro
58 import uuid
59 from Common.Misc import tdict
60 from Common.MultipleWorkspace import MultipleWorkspace as mws
61 import Common.LongFilePathOs as os
62 from Common.LongFilePathSupport import OpenLongFilePath as open
63 from Capsule import EFI_CERT_TYPE_PKCS7_GUID
64 from Capsule import EFI_CERT_TYPE_RSA2048_SHA256_GUID
65 from Common.RangeExpression import RangeExpression
66
67 ##define T_CHAR_SPACE ' '
68 ##define T_CHAR_NULL '\0'
69 ##define T_CHAR_CR '\r'
70 ##define T_CHAR_TAB '\t'
71 ##define T_CHAR_LF '\n'
72 ##define T_CHAR_SLASH '/'
73 ##define T_CHAR_BACKSLASH '\\'
74 ##define T_CHAR_DOUBLE_QUOTE '\"'
75 ##define T_CHAR_SINGLE_QUOTE '\''
76 ##define T_CHAR_STAR '*'
77 ##define T_CHAR_HASH '#'
78
79 (T_CHAR_SPACE, T_CHAR_NULL, T_CHAR_CR, T_CHAR_TAB, T_CHAR_LF, T_CHAR_SLASH, \
80 T_CHAR_BACKSLASH, T_CHAR_DOUBLE_QUOTE, T_CHAR_SINGLE_QUOTE, T_CHAR_STAR, T_CHAR_HASH) = \
81 (' ', '\0', '\r', '\t', '\n', '/', '\\', '\"', '\'', '*', '#')
82
83 SEPERATOR_TUPLE = ('=', '|', ',', '{', '}')
84
85 RegionSizePattern = re.compile("\s*(?P<base>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<size>(?:0x|0X)?[a-fA-F0-9]+)\s*")
86 RegionSizeGuidPattern = re.compile("\s*(?P<base>\w+\.\w+)\s*\|\s*(?P<size>\w+\.\w+)\s*")
87 RegionOffsetPcdPattern = re.compile("\s*(?P<base>\w+\.\w+)\s*$")
88 ShortcutPcdPattern = re.compile("\s*\w+\s*=\s*(?P<value>(?:0x|0X)?[a-fA-F0-9]+)\s*\|\s*(?P<name>\w+\.\w+)\s*")
89 BaseAddrValuePattern = re.compile('^0[xX][0-9a-fA-F]+')
90 FileExtensionPattern = re.compile(r'([a-zA-Z][a-zA-Z0-9]*)')
91 TokenFindPattern = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\)|\*)')
92
93 AllIncludeFileList = []
94
95 # Get the closest parent
96 def GetParentAtLine (Line):
97 for Profile in AllIncludeFileList:
98 if Profile.IsLineInFile(Line):
99 return Profile
100 return None
101
102 # Check include loop
103 def IsValidInclude (File, Line):
104 for Profile in AllIncludeFileList:
105 if Profile.IsLineInFile(Line) and Profile.FileName == File:
106 return False
107
108 return True
109
110 def GetRealFileLine (File, Line):
111
112 InsertedLines = 0
113 for Profile in AllIncludeFileList:
114 if Profile.IsLineInFile(Line):
115 return Profile.GetLineInFile(Line)
116 elif Line >= Profile.InsertStartLineNumber and Profile.Level == 1:
117 InsertedLines += Profile.GetTotalLines()
118
119 return (File, Line - InsertedLines)
120
121 ## The exception class that used to report error messages when parsing FDF
122 #
123 # Currently the "ToolName" is set to be "FDF Parser".
124 #
125 class Warning (Exception):
126 ## The constructor
127 #
128 # @param self The object pointer
129 # @param Str The message to record
130 # @param File The FDF name
131 # @param Line The Line number that error occurs
132 #
133 def __init__(self, Str, File = None, Line = None):
134
135 FileLineTuple = GetRealFileLine(File, Line)
136 self.FileName = FileLineTuple[0]
137 self.LineNumber = FileLineTuple[1]
138 self.OriginalLineNumber = Line
139 self.Message = Str
140 self.ToolName = 'FdfParser'
141
142 def __str__(self):
143 return self.Message
144
145 ## The Include file content class that used to record file data when parsing include file
146 #
147 # May raise Exception when opening file.
148 #
149 class IncludeFileProfile :
150 ## The constructor
151 #
152 # @param self The object pointer
153 # @param FileName The file that to be parsed
154 #
155 def __init__(self, FileName):
156 self.FileName = FileName
157 self.FileLinesList = []
158 try:
159 fsock = open(FileName, "rb", 0)
160 try:
161 self.FileLinesList = fsock.readlines()
162 for index, line in enumerate(self.FileLinesList):
163 if not line.endswith('\n'):
164 self.FileLinesList[index] += '\n'
165
166 finally:
167 fsock.close()
168
169 except:
170 EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
171
172 self.InsertStartLineNumber = None
173 self.InsertAdjust = 0
174 self.IncludeFileList = []
175 self.Level = 1 # first level include file
176
177 def GetTotalLines(self):
178 TotalLines = self.InsertAdjust + len(self.FileLinesList)
179
180 for Profile in self.IncludeFileList:
181 TotalLines += Profile.GetTotalLines()
182
183 return TotalLines
184
185 def IsLineInFile(self, Line):
186 if Line >= self.InsertStartLineNumber and Line < self.InsertStartLineNumber + self.GetTotalLines():
187 return True
188
189 return False
190
191 def GetLineInFile(self, Line):
192 if not self.IsLineInFile (Line):
193 return (self.FileName, -1)
194
195 InsertedLines = self.InsertStartLineNumber
196
197 for Profile in self.IncludeFileList:
198 if Profile.IsLineInFile(Line):
199 return Profile.GetLineInFile(Line)
200 elif Line >= Profile.InsertStartLineNumber:
201 InsertedLines += Profile.GetTotalLines()
202
203 return (self.FileName, Line - InsertedLines + 1)
204
205
206
207 ## The FDF content class that used to record file data when parsing FDF
208 #
209 # May raise Exception when opening file.
210 #
211 class FileProfile :
212 ## The constructor
213 #
214 # @param self The object pointer
215 # @param FileName The file that to be parsed
216 #
217 def __init__(self, FileName):
218 self.FileLinesList = []
219 try:
220 fsock = open(FileName, "rb", 0)
221 try:
222 self.FileLinesList = fsock.readlines()
223 finally:
224 fsock.close()
225
226 except:
227 EdkLogger.error("FdfParser", FILE_OPEN_FAILURE, ExtraData=FileName)
228
229
230 self.PcdDict = {}
231 self.InfList = []
232 self.InfDict = {'ArchTBD':[]}
233 # ECC will use this Dict and List information
234 self.PcdFileLineDict = {}
235 self.InfFileLineList = []
236
237 self.FdDict = {}
238 self.FdNameNotSet = False
239 self.FvDict = {}
240 self.CapsuleDict = {}
241 self.VtfList = []
242 self.RuleDict = {}
243 self.OptRomDict = {}
244 self.FmpPayloadDict = {}
245
246 ## The syntax parser for FDF
247 #
248 # PreprocessFile method should be called prior to ParseFile
249 # CycleReferenceCheck method can detect cycles in FDF contents
250 #
251 # GetNext*** procedures mean these procedures will get next token first, then make judgement.
252 # Get*** procedures mean these procedures will make judgement on current token only.
253 #
254 class FdfParser:
255 ## The constructor
256 #
257 # @param self The object pointer
258 # @param FileName The file that to be parsed
259 #
260 def __init__(self, FileName):
261 self.Profile = FileProfile(FileName)
262 self.FileName = FileName
263 self.CurrentLineNumber = 1
264 self.CurrentOffsetWithinLine = 0
265 self.CurrentFdName = None
266 self.CurrentFvName = None
267 self.__Token = ""
268 self.__SkippedChars = ""
269 GlobalData.gFdfParser = self
270
271 # Used to section info
272 self.__CurSection = []
273 # Key: [section name, UI name, arch]
274 # Value: {MACRO_NAME : MACRO_VALUE}
275 self.__MacroDict = tdict(True, 3)
276 self.__PcdDict = {}
277
278 self.__WipeOffArea = []
279 if GenFdsGlobalVariable.WorkSpaceDir == '':
280 GenFdsGlobalVariable.WorkSpaceDir = os.getenv("WORKSPACE")
281
282 ## __SkipWhiteSpace() method
283 #
284 # Skip white spaces from current char, return number of chars skipped
285 #
286 # @param self The object pointer
287 # @retval Count The number of chars skipped
288 #
289 def __SkipWhiteSpace(self):
290 Count = 0
291 while not self.__EndOfFile():
292 Count += 1
293 if self.__CurrentChar() in (T_CHAR_NULL, T_CHAR_CR, T_CHAR_LF, T_CHAR_SPACE, T_CHAR_TAB):
294 self.__SkippedChars += str(self.__CurrentChar())
295 self.__GetOneChar()
296
297 else:
298 Count = Count - 1
299 return Count
300
301 ## __EndOfFile() method
302 #
303 # Judge current buffer pos is at file end
304 #
305 # @param self The object pointer
306 # @retval True Current File buffer position is at file end
307 # @retval False Current File buffer position is NOT at file end
308 #
309 def __EndOfFile(self):
310 NumberOfLines = len(self.Profile.FileLinesList)
311 SizeOfLastLine = len(self.Profile.FileLinesList[-1])
312 if self.CurrentLineNumber == NumberOfLines and self.CurrentOffsetWithinLine >= SizeOfLastLine - 1:
313 return True
314 elif self.CurrentLineNumber > NumberOfLines:
315 return True
316 else:
317 return False
318
319 ## __EndOfLine() method
320 #
321 # Judge current buffer pos is at line end
322 #
323 # @param self The object pointer
324 # @retval True Current File buffer position is at line end
325 # @retval False Current File buffer position is NOT at line end
326 #
327 def __EndOfLine(self):
328 if self.CurrentLineNumber > len(self.Profile.FileLinesList):
329 return True
330 SizeOfCurrentLine = len(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
331 if self.CurrentOffsetWithinLine >= SizeOfCurrentLine:
332 return True
333 else:
334 return False
335
336 ## Rewind() method
337 #
338 # Reset file data buffer to the initial state
339 #
340 # @param self The object pointer
341 # @param DestLine Optional new destination line number.
342 # @param DestOffset Optional new destination offset.
343 #
344 def Rewind(self, DestLine = 1, DestOffset = 0):
345 self.CurrentLineNumber = DestLine
346 self.CurrentOffsetWithinLine = DestOffset
347
348 ## __UndoOneChar() method
349 #
350 # Go back one char in the file buffer
351 #
352 # @param self The object pointer
353 # @retval True Successfully go back one char
354 # @retval False Not able to go back one char as file beginning reached
355 #
356 def __UndoOneChar(self):
357
358 if self.CurrentLineNumber == 1 and self.CurrentOffsetWithinLine == 0:
359 return False
360 elif self.CurrentOffsetWithinLine == 0:
361 self.CurrentLineNumber -= 1
362 self.CurrentOffsetWithinLine = len(self.__CurrentLine()) - 1
363 else:
364 self.CurrentOffsetWithinLine -= 1
365 return True
366
367 ## __GetOneChar() method
368 #
369 # Move forward one char in the file buffer
370 #
371 # @param self The object pointer
372 #
373 def __GetOneChar(self):
374 if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
375 self.CurrentLineNumber += 1
376 self.CurrentOffsetWithinLine = 0
377 else:
378 self.CurrentOffsetWithinLine += 1
379
380 ## __CurrentChar() method
381 #
382 # Get the char pointed to by the file buffer pointer
383 #
384 # @param self The object pointer
385 # @retval Char Current char
386 #
387 def __CurrentChar(self):
388 return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine]
389
390 ## __NextChar() method
391 #
392 # Get the one char pass the char pointed to by the file buffer pointer
393 #
394 # @param self The object pointer
395 # @retval Char Next char
396 #
397 def __NextChar(self):
398 if self.CurrentOffsetWithinLine == len(self.Profile.FileLinesList[self.CurrentLineNumber - 1]) - 1:
399 return self.Profile.FileLinesList[self.CurrentLineNumber][0]
400 else:
401 return self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine + 1]
402
403 ## __SetCurrentCharValue() method
404 #
405 # Modify the value of current char
406 #
407 # @param self The object pointer
408 # @param Value The new value of current char
409 #
410 def __SetCurrentCharValue(self, Value):
411 self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine] = Value
412
413 ## __CurrentLine() method
414 #
415 # Get the list that contains current line contents
416 #
417 # @param self The object pointer
418 # @retval List current line contents
419 #
420 def __CurrentLine(self):
421 return self.Profile.FileLinesList[self.CurrentLineNumber - 1]
422
423 def __StringToList(self):
424 self.Profile.FileLinesList = [list(s) for s in self.Profile.FileLinesList]
425 self.Profile.FileLinesList[-1].append(' ')
426
427 def __ReplaceFragment(self, StartPos, EndPos, Value = ' '):
428 if StartPos[0] == EndPos[0]:
429 Offset = StartPos[1]
430 while Offset <= EndPos[1]:
431 self.Profile.FileLinesList[StartPos[0]][Offset] = Value
432 Offset += 1
433 return
434
435 Offset = StartPos[1]
436 while self.Profile.FileLinesList[StartPos[0]][Offset] not in ('\r', '\n'):
437 self.Profile.FileLinesList[StartPos[0]][Offset] = Value
438 Offset += 1
439
440 Line = StartPos[0]
441 while Line < EndPos[0]:
442 Offset = 0
443 while self.Profile.FileLinesList[Line][Offset] not in ('\r', '\n'):
444 self.Profile.FileLinesList[Line][Offset] = Value
445 Offset += 1
446 Line += 1
447
448 Offset = 0
449 while Offset <= EndPos[1]:
450 self.Profile.FileLinesList[EndPos[0]][Offset] = Value
451 Offset += 1
452
453
454 def __GetMacroName(self):
455 if not self.__GetNextToken():
456 raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber)
457 MacroName = self.__Token
458 NotFlag = False
459 if MacroName.startswith('!'):
460 NotFlag = True
461 MacroName = MacroName[1:].strip()
462
463 if not MacroName.startswith('$(') or not MacroName.endswith(')'):
464 raise Warning("Macro name expected(Please use '$(%(Token)s)' if '%(Token)s' is a macro.)" % {"Token" : MacroName},
465 self.FileName, self.CurrentLineNumber)
466 MacroName = MacroName[2:-1]
467 return MacroName, NotFlag
468
469 def __SetMacroValue(self, Macro, Value):
470 if not self.__CurSection:
471 return
472
473 MacroDict = {}
474 if not self.__MacroDict[self.__CurSection[0], self.__CurSection[1], self.__CurSection[2]]:
475 self.__MacroDict[self.__CurSection[0], self.__CurSection[1], self.__CurSection[2]] = MacroDict
476 else:
477 MacroDict = self.__MacroDict[self.__CurSection[0], self.__CurSection[1], self.__CurSection[2]]
478 MacroDict[Macro] = Value
479
480 def __GetMacroValue(self, Macro):
481 # Highest priority
482 if Macro in GlobalData.gCommandLineDefines:
483 return GlobalData.gCommandLineDefines[Macro]
484 if Macro in GlobalData.gGlobalDefines:
485 return GlobalData.gGlobalDefines[Macro]
486
487 if self.__CurSection:
488 MacroDict = self.__MacroDict[
489 self.__CurSection[0],
490 self.__CurSection[1],
491 self.__CurSection[2]
492 ]
493 if MacroDict and Macro in MacroDict:
494 return MacroDict[Macro]
495
496 # Lowest priority
497 if Macro in GlobalData.gPlatformDefines:
498 return GlobalData.gPlatformDefines[Macro]
499 return None
500
501 def __SectionHeaderParser(self, Section):
502 # [Defines]
503 # [FD.UiName]: use dummy instead if UI name is optional
504 # [FV.UiName]
505 # [Capsule.UiName]
506 # [Rule]: don't take rule section into account, macro is not allowed in this section
507 # [VTF.arch.UiName, arch]
508 # [OptionRom.DriverName]
509 self.__CurSection = []
510 Section = Section.strip()[1:-1].upper().replace(' ', '').strip('.')
511 ItemList = Section.split('.')
512 Item = ItemList[0]
513 if Item == '' or Item == 'RULE':
514 return
515
516 if Item == TAB_COMMON_DEFINES.upper():
517 self.__CurSection = [TAB_COMMON, TAB_COMMON, TAB_COMMON]
518 elif Item == 'VTF' and len(ItemList) == 3:
519 UiName = ItemList[2]
520 Pos = UiName.find(',')
521 if Pos != -1:
522 UiName = UiName[:Pos]
523 self.__CurSection = ['VTF', UiName, ItemList[1]]
524 elif len(ItemList) > 1:
525 self.__CurSection = [ItemList[0], ItemList[1], TAB_COMMON]
526 elif len(ItemList) > 0:
527 self.__CurSection = [ItemList[0], 'DUMMY', TAB_COMMON]
528
529 ## PreprocessFile() method
530 #
531 # Preprocess file contents, replace comments with spaces.
532 # In the end, rewind the file buffer pointer to the beginning
533 # BUGBUG: No !include statement processing contained in this procedure
534 # !include statement should be expanded at the same FileLinesList[CurrentLineNumber - 1]
535 #
536 # @param self The object pointer
537 #
538 def PreprocessFile(self):
539
540 self.Rewind()
541 InComment = False
542 DoubleSlashComment = False
543 HashComment = False
544 # HashComment in quoted string " " is ignored.
545 InString = False
546
547 while not self.__EndOfFile():
548
549 if self.__CurrentChar() == T_CHAR_DOUBLE_QUOTE and not InComment:
550 InString = not InString
551 # meet new line, then no longer in a comment for // and '#'
552 if self.__CurrentChar() == T_CHAR_LF:
553 self.CurrentLineNumber += 1
554 self.CurrentOffsetWithinLine = 0
555 if InComment and DoubleSlashComment:
556 InComment = False
557 DoubleSlashComment = False
558 if InComment and HashComment:
559 InComment = False
560 HashComment = False
561 # check for */ comment end
562 elif InComment and not DoubleSlashComment and not HashComment and self.__CurrentChar() == T_CHAR_STAR and self.__NextChar() == T_CHAR_SLASH:
563 self.__SetCurrentCharValue(T_CHAR_SPACE)
564 self.__GetOneChar()
565 self.__SetCurrentCharValue(T_CHAR_SPACE)
566 self.__GetOneChar()
567 InComment = False
568 # set comments to spaces
569 elif InComment:
570 self.__SetCurrentCharValue(T_CHAR_SPACE)
571 self.__GetOneChar()
572 # check for // comment
573 elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_SLASH and not self.__EndOfLine():
574 InComment = True
575 DoubleSlashComment = True
576 # check for '#' comment
577 elif self.__CurrentChar() == T_CHAR_HASH and not self.__EndOfLine() and not InString:
578 InComment = True
579 HashComment = True
580 # check for /* comment start
581 elif self.__CurrentChar() == T_CHAR_SLASH and self.__NextChar() == T_CHAR_STAR:
582 self.__SetCurrentCharValue( T_CHAR_SPACE)
583 self.__GetOneChar()
584 self.__SetCurrentCharValue( T_CHAR_SPACE)
585 self.__GetOneChar()
586 InComment = True
587 else:
588 self.__GetOneChar()
589
590 # restore from ListOfList to ListOfString
591 self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
592 self.Rewind()
593
594 ## PreprocessIncludeFile() method
595 #
596 # Preprocess file contents, replace !include statements with file contents.
597 # In the end, rewind the file buffer pointer to the beginning
598 #
599 # @param self The object pointer
600 #
601 def PreprocessIncludeFile(self):
602 # nested include support
603 Processed = False
604 MacroDict = {}
605 while self.__GetNextToken():
606
607 if self.__Token == 'DEFINE':
608 if not self.__GetNextToken():
609 raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber)
610 Macro = self.__Token
611 if not self.__IsToken( "="):
612 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
613 Value = self.__GetExpression()
614 MacroDict[Macro] = Value
615
616 elif self.__Token == '!include':
617 Processed = True
618 IncludeLine = self.CurrentLineNumber
619 IncludeOffset = self.CurrentOffsetWithinLine - len('!include')
620 if not self.__GetNextToken():
621 raise Warning("expected include file name", self.FileName, self.CurrentLineNumber)
622 IncFileName = self.__Token
623 PreIndex = 0
624 StartPos = IncFileName.find('$(', PreIndex)
625 EndPos = IncFileName.find(')', StartPos+2)
626 while StartPos != -1 and EndPos != -1:
627 Macro = IncFileName[StartPos+2 : EndPos]
628 MacroVal = self.__GetMacroValue(Macro)
629 if not MacroVal:
630 if Macro in MacroDict:
631 MacroVal = MacroDict[Macro]
632 if MacroVal is not None:
633 IncFileName = IncFileName.replace('$(' + Macro + ')', MacroVal, 1)
634 if MacroVal.find('$(') != -1:
635 PreIndex = StartPos
636 else:
637 PreIndex = StartPos + len(MacroVal)
638 else:
639 raise Warning("The Macro %s is not defined" %Macro, self.FileName, self.CurrentLineNumber)
640 StartPos = IncFileName.find('$(', PreIndex)
641 EndPos = IncFileName.find(')', StartPos+2)
642
643 IncludedFile = NormPath(IncFileName)
644 #
645 # First search the include file under the same directory as FDF file
646 #
647 IncludedFile1 = PathClass(IncludedFile, os.path.dirname(self.FileName))
648 ErrorCode = IncludedFile1.Validate()[0]
649 if ErrorCode != 0:
650 #
651 # Then search the include file under the same directory as DSC file
652 #
653 PlatformDir = ''
654 if GenFdsGlobalVariable.ActivePlatform:
655 PlatformDir = GenFdsGlobalVariable.ActivePlatform.Dir
656 elif GlobalData.gActivePlatform:
657 PlatformDir = GlobalData.gActivePlatform.MetaFile.Dir
658 IncludedFile1 = PathClass(IncludedFile, PlatformDir)
659 ErrorCode = IncludedFile1.Validate()[0]
660 if ErrorCode != 0:
661 #
662 # Also search file under the WORKSPACE directory
663 #
664 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
665 ErrorCode = IncludedFile1.Validate()[0]
666 if ErrorCode != 0:
667 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),
668 self.FileName, self.CurrentLineNumber)
669
670 if not IsValidInclude (IncludedFile1.Path, self.CurrentLineNumber):
671 raise Warning("The include file {0} is causing a include loop.\n".format (IncludedFile1.Path), self.FileName, self.CurrentLineNumber)
672
673 IncFileProfile = IncludeFileProfile(IncludedFile1.Path)
674
675 CurrentLine = self.CurrentLineNumber
676 CurrentOffset = self.CurrentOffsetWithinLine
677 # list index of the insertion, note that line number is 'CurrentLine + 1'
678 InsertAtLine = CurrentLine
679 ParentProfile = GetParentAtLine (CurrentLine)
680 if ParentProfile is not None:
681 ParentProfile.IncludeFileList.insert(0, IncFileProfile)
682 IncFileProfile.Level = ParentProfile.Level + 1
683 IncFileProfile.InsertStartLineNumber = InsertAtLine + 1
684 # deal with remaining portions after "!include filename", if exists.
685 if self.__GetNextToken():
686 if self.CurrentLineNumber == CurrentLine:
687 RemainingLine = self.__CurrentLine()[CurrentOffset:]
688 self.Profile.FileLinesList.insert(self.CurrentLineNumber, RemainingLine)
689 IncFileProfile.InsertAdjust += 1
690 self.CurrentLineNumber += 1
691 self.CurrentOffsetWithinLine = 0
692
693 for Line in IncFileProfile.FileLinesList:
694 self.Profile.FileLinesList.insert(InsertAtLine, Line)
695 self.CurrentLineNumber += 1
696 InsertAtLine += 1
697
698 # reversely sorted to better determine error in file
699 AllIncludeFileList.insert(0, IncFileProfile)
700
701 # comment out the processed include file statement
702 TempList = list(self.Profile.FileLinesList[IncludeLine - 1])
703 TempList.insert(IncludeOffset, '#')
704 self.Profile.FileLinesList[IncludeLine - 1] = ''.join(TempList)
705 if Processed: # Nested and back-to-back support
706 self.Rewind(DestLine = IncFileProfile.InsertStartLineNumber - 1)
707 Processed = False
708 # Preprocess done.
709 self.Rewind()
710
711 @staticmethod
712 def __GetIfListCurrentItemStat(IfList):
713 if len(IfList) == 0:
714 return True
715
716 for Item in IfList:
717 if Item[1] == False:
718 return False
719
720 return True
721
722 ## PreprocessConditionalStatement() method
723 #
724 # Preprocess conditional statement.
725 # In the end, rewind the file buffer pointer to the beginning
726 #
727 # @param self The object pointer
728 #
729 def PreprocessConditionalStatement(self):
730 # IfList is a stack of if branches with elements of list [Pos, CondSatisfied, BranchDetermined]
731 IfList = []
732 RegionLayoutLine = 0
733 ReplacedLine = -1
734 while self.__GetNextToken():
735 # Determine section name and the location dependent macro
736 if self.__GetIfListCurrentItemStat(IfList):
737 if self.__Token.startswith('['):
738 Header = self.__Token
739 if not self.__Token.endswith(']'):
740 self.__SkipToToken(']')
741 Header += self.__SkippedChars
742 if Header.find('$(') != -1:
743 raise Warning("macro cannot be used in section header", self.FileName, self.CurrentLineNumber)
744 self.__SectionHeaderParser(Header)
745 continue
746 # Replace macros except in RULE section or out of section
747 elif self.__CurSection and ReplacedLine != self.CurrentLineNumber:
748 ReplacedLine = self.CurrentLineNumber
749 self.__UndoToken()
750 CurLine = self.Profile.FileLinesList[ReplacedLine - 1]
751 PreIndex = 0
752 StartPos = CurLine.find('$(', PreIndex)
753 EndPos = CurLine.find(')', StartPos+2)
754 while StartPos != -1 and EndPos != -1 and self.__Token not in ['!ifdef', '!ifndef', '!if', '!elseif']:
755 MacroName = CurLine[StartPos+2 : EndPos]
756 MacorValue = self.__GetMacroValue(MacroName)
757 if MacorValue is not None:
758 CurLine = CurLine.replace('$(' + MacroName + ')', MacorValue, 1)
759 if MacorValue.find('$(') != -1:
760 PreIndex = StartPos
761 else:
762 PreIndex = StartPos + len(MacorValue)
763 else:
764 PreIndex = EndPos + 1
765 StartPos = CurLine.find('$(', PreIndex)
766 EndPos = CurLine.find(')', StartPos+2)
767 self.Profile.FileLinesList[ReplacedLine - 1] = CurLine
768 continue
769
770 if self.__Token == 'DEFINE':
771 if self.__GetIfListCurrentItemStat(IfList):
772 if not self.__CurSection:
773 raise Warning("macro cannot be defined in Rule section or out of section", self.FileName, self.CurrentLineNumber)
774 DefineLine = self.CurrentLineNumber - 1
775 DefineOffset = self.CurrentOffsetWithinLine - len('DEFINE')
776 if not self.__GetNextToken():
777 raise Warning("expected Macro name", self.FileName, self.CurrentLineNumber)
778 Macro = self.__Token
779 if not self.__IsToken( "="):
780 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
781
782 Value = self.__GetExpression()
783 self.__SetMacroValue(Macro, Value)
784 self.__WipeOffArea.append(((DefineLine, DefineOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
785 elif self.__Token == 'SET':
786 if not self.__GetIfListCurrentItemStat(IfList):
787 continue
788 SetLine = self.CurrentLineNumber - 1
789 SetOffset = self.CurrentOffsetWithinLine - len('SET')
790 PcdPair = self.__GetNextPcdName()
791 PcdName = "%s.%s" % (PcdPair[1], PcdPair[0])
792 if not self.__IsToken( "="):
793 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
794
795 Value = self.__GetExpression()
796 Value = self.__EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
797
798 self.__PcdDict[PcdName] = Value
799
800 self.Profile.PcdDict[PcdPair] = Value
801 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
802 self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
803
804 self.__WipeOffArea.append(((SetLine, SetOffset), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
805 elif self.__Token in ('!ifdef', '!ifndef', '!if'):
806 IfStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token))
807 IfList.append([IfStartPos, None, None])
808
809 CondLabel = self.__Token
810 Expression = self.__GetExpression()
811
812 if CondLabel == '!if':
813 ConditionSatisfied = self.__EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
814 else:
815 ConditionSatisfied = self.__EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'in')
816 if CondLabel == '!ifndef':
817 ConditionSatisfied = not ConditionSatisfied
818
819 BranchDetermined = ConditionSatisfied
820 IfList[-1] = [IfList[-1][0], ConditionSatisfied, BranchDetermined]
821 if ConditionSatisfied:
822 self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
823 elif self.__Token in ('!elseif', '!else'):
824 ElseStartPos = (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len(self.__Token))
825 if len(IfList) <= 0:
826 raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
827
828 if IfList[-1][1]:
829 IfList[-1] = [ElseStartPos, False, True]
830 self.__WipeOffArea.append((ElseStartPos, (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
831 else:
832 self.__WipeOffArea.append((IfList[-1][0], ElseStartPos))
833 IfList[-1] = [ElseStartPos, True, IfList[-1][2]]
834 if self.__Token == '!elseif':
835 Expression = self.__GetExpression()
836 ConditionSatisfied = self.__EvaluateConditional(Expression, IfList[-1][0][0] + 1, 'eval')
837 IfList[-1] = [IfList[-1][0], ConditionSatisfied, IfList[-1][2]]
838
839 if IfList[-1][1]:
840 if IfList[-1][2]:
841 IfList[-1][1] = False
842 else:
843 IfList[-1][2] = True
844 self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
845 elif self.__Token == '!endif':
846 if len(IfList) <= 0:
847 raise Warning("Missing !if statement", self.FileName, self.CurrentLineNumber)
848 if IfList[-1][1]:
849 self.__WipeOffArea.append(((self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - len('!endif')), (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
850 else:
851 self.__WipeOffArea.append((IfList[-1][0], (self.CurrentLineNumber - 1, self.CurrentOffsetWithinLine - 1)))
852
853 IfList.pop()
854 elif not IfList: # Don't use PCDs inside conditional directive
855 if self.CurrentLineNumber <= RegionLayoutLine:
856 # Don't try the same line twice
857 continue
858 SetPcd = ShortcutPcdPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
859 if SetPcd:
860 self.__PcdDict[SetPcd.group('name')] = SetPcd.group('value')
861 RegionLayoutLine = self.CurrentLineNumber
862 continue
863 RegionSize = RegionSizePattern.match(self.Profile.FileLinesList[self.CurrentLineNumber - 1])
864 if not RegionSize:
865 RegionLayoutLine = self.CurrentLineNumber
866 continue
867 RegionSizeGuid = RegionSizeGuidPattern.match(self.Profile.FileLinesList[self.CurrentLineNumber])
868 if not RegionSizeGuid:
869 RegionLayoutLine = self.CurrentLineNumber + 1
870 continue
871 self.__PcdDict[RegionSizeGuid.group('base')] = RegionSize.group('base')
872 self.__PcdDict[RegionSizeGuid.group('size')] = RegionSize.group('size')
873 RegionLayoutLine = self.CurrentLineNumber + 1
874
875 if IfList:
876 raise Warning("Missing !endif", self.FileName, self.CurrentLineNumber)
877 self.Rewind()
878
879 def __CollectMacroPcd(self):
880 MacroDict = {}
881
882 # PCD macro
883 MacroDict.update(GlobalData.gPlatformPcds)
884 MacroDict.update(self.__PcdDict)
885
886 # Lowest priority
887 MacroDict.update(GlobalData.gPlatformDefines)
888
889 if self.__CurSection:
890 # Defines macro
891 ScopeMacro = self.__MacroDict[TAB_COMMON, TAB_COMMON, TAB_COMMON]
892 if ScopeMacro:
893 MacroDict.update(ScopeMacro)
894
895 # Section macro
896 ScopeMacro = self.__MacroDict[
897 self.__CurSection[0],
898 self.__CurSection[1],
899 self.__CurSection[2]
900 ]
901 if ScopeMacro:
902 MacroDict.update(ScopeMacro)
903
904 MacroDict.update(GlobalData.gGlobalDefines)
905 MacroDict.update(GlobalData.gCommandLineDefines)
906 if GlobalData.BuildOptionPcd:
907 for Item in GlobalData.BuildOptionPcd:
908 if isinstance(Item, tuple):
909 continue
910 PcdName, TmpValue = Item.split("=")
911 TmpValue = BuildOptionValue(TmpValue, {})
912 MacroDict[PcdName.strip()] = TmpValue
913 # Highest priority
914
915 return MacroDict
916
917 def __EvaluateConditional(self, Expression, Line, Op = None, Value = None):
918 MacroPcdDict = self.__CollectMacroPcd()
919 if Op == 'eval':
920 try:
921 if Value:
922 return ValueExpression(Expression, MacroPcdDict)(True)
923 else:
924 return ValueExpression(Expression, MacroPcdDict)()
925 except WrnExpression as Excpt:
926 #
927 # Catch expression evaluation warning here. We need to report
928 # the precise number of line and return the evaluation result
929 #
930 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
931 File=self.FileName, ExtraData=self.__CurrentLine(),
932 Line=Line)
933 return Excpt.result
934 except Exception as Excpt:
935 if hasattr(Excpt, 'Pcd'):
936 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
937 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
938 raise Warning("Cannot use this PCD (%s) in an expression as"
939 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
940 " of the DSC file (%s), and it is currently defined in this section:"
941 " %s, line #: %d." % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE'], Info[0], Info[1]),
942 self.FileName, Line)
943 else:
944 raise Warning("PCD (%s) is not defined in DSC file (%s)" % (Excpt.Pcd, GlobalData.gPlatformOtherPcds['DSCFILE']),
945 self.FileName, Line)
946 else:
947 raise Warning(str(Excpt), self.FileName, Line)
948 else:
949 if Expression.startswith('$(') and Expression[-1] == ')':
950 Expression = Expression[2:-1]
951 return Expression in MacroPcdDict
952
953 ## __IsToken() method
954 #
955 # Check whether input string is found from current char position along
956 # If found, the string value is put into self.__Token
957 #
958 # @param self The object pointer
959 # @param String The string to search
960 # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
961 # @retval True Successfully find string, file buffer pointer moved forward
962 # @retval False Not able to find string, file buffer pointer not changed
963 #
964 def __IsToken(self, String, IgnoreCase = False):
965 self.__SkipWhiteSpace()
966
967 # Only consider the same line, no multi-line token allowed
968 StartPos = self.CurrentOffsetWithinLine
969 index = -1
970 if IgnoreCase:
971 index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper())
972 else:
973 index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String)
974 if index == 0:
975 self.CurrentOffsetWithinLine += len(String)
976 self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
977 return True
978 return False
979
980 ## __IsKeyword() method
981 #
982 # Check whether input keyword is found from current char position along, whole word only!
983 # If found, the string value is put into self.__Token
984 #
985 # @param self The object pointer
986 # @param Keyword The string to search
987 # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
988 # @retval True Successfully find string, file buffer pointer moved forward
989 # @retval False Not able to find string, file buffer pointer not changed
990 #
991 def __IsKeyword(self, KeyWord, IgnoreCase = False):
992 self.__SkipWhiteSpace()
993
994 # Only consider the same line, no multi-line token allowed
995 StartPos = self.CurrentOffsetWithinLine
996 index = -1
997 if IgnoreCase:
998 index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(KeyWord.upper())
999 else:
1000 index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(KeyWord)
1001 if index == 0:
1002 followingChar = self.__CurrentLine()[self.CurrentOffsetWithinLine + len(KeyWord)]
1003 if not str(followingChar).isspace() and followingChar not in SEPERATOR_TUPLE:
1004 return False
1005 self.CurrentOffsetWithinLine += len(KeyWord)
1006 self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
1007 return True
1008 return False
1009
1010 def __GetExpression(self):
1011 Line = self.Profile.FileLinesList[self.CurrentLineNumber - 1]
1012 Index = len(Line) - 1
1013 while Line[Index] in ['\r', '\n']:
1014 Index -= 1
1015 ExpressionString = self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine:Index+1]
1016 self.CurrentOffsetWithinLine += len(ExpressionString)
1017 ExpressionString = ExpressionString.strip()
1018 return ExpressionString
1019
1020 ## __GetNextWord() method
1021 #
1022 # Get next C name from file lines
1023 # If found, the string value is put into self.__Token
1024 #
1025 # @param self The object pointer
1026 # @retval True Successfully find a C name string, file buffer pointer moved forward
1027 # @retval False Not able to find a C name string, file buffer pointer not changed
1028 #
1029 def __GetNextWord(self):
1030 self.__SkipWhiteSpace()
1031 if self.__EndOfFile():
1032 return False
1033
1034 TempChar = self.__CurrentChar()
1035 StartPos = self.CurrentOffsetWithinLine
1036 if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') or TempChar == '_':
1037 self.__GetOneChar()
1038 while not self.__EndOfLine():
1039 TempChar = self.__CurrentChar()
1040 if (TempChar >= 'a' and TempChar <= 'z') or (TempChar >= 'A' and TempChar <= 'Z') \
1041 or (TempChar >= '0' and TempChar <= '9') or TempChar == '_' or TempChar == '-':
1042 self.__GetOneChar()
1043
1044 else:
1045 break
1046
1047 self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
1048 return True
1049
1050 return False
1051
1052 ## __GetNextToken() method
1053 #
1054 # Get next token unit before a seperator
1055 # If found, the string value is put into self.__Token
1056 #
1057 # @param self The object pointer
1058 # @retval True Successfully find a token unit, file buffer pointer moved forward
1059 # @retval False Not able to find a token unit, file buffer pointer not changed
1060 #
1061 def __GetNextToken(self):
1062 # Skip leading spaces, if exist.
1063 self.__SkipWhiteSpace()
1064 if self.__EndOfFile():
1065 return False
1066 # Record the token start position, the position of the first non-space char.
1067 StartPos = self.CurrentOffsetWithinLine
1068 StartLine = self.CurrentLineNumber
1069 while StartLine == self.CurrentLineNumber:
1070 TempChar = self.__CurrentChar()
1071 # Try to find the end char that is not a space and not in seperator tuple.
1072 # That is, when we got a space or any char in the tuple, we got the end of token.
1073 if not str(TempChar).isspace() and TempChar not in SEPERATOR_TUPLE:
1074 self.__GetOneChar()
1075 # if we happen to meet a seperator as the first char, we must proceed to get it.
1076 # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
1077 elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE:
1078 self.__GetOneChar()
1079 break
1080 else:
1081 break
1082 # else:
1083 # return False
1084
1085 EndPos = self.CurrentOffsetWithinLine
1086 if self.CurrentLineNumber != StartLine:
1087 EndPos = len(self.Profile.FileLinesList[StartLine-1])
1088 self.__Token = self.Profile.FileLinesList[StartLine-1][StartPos : EndPos]
1089 if StartPos != self.CurrentOffsetWithinLine:
1090 return True
1091 else:
1092 return False
1093
1094 def __GetNextOp(self):
1095 # Skip leading spaces, if exist.
1096 self.__SkipWhiteSpace()
1097 if self.__EndOfFile():
1098 return False
1099 # Record the token start position, the position of the first non-space char.
1100 StartPos = self.CurrentOffsetWithinLine
1101 while not self.__EndOfLine():
1102 TempChar = self.__CurrentChar()
1103 # Try to find the end char that is not a space
1104 if not str(TempChar).isspace():
1105 self.__GetOneChar()
1106 else:
1107 break
1108 else:
1109 return False
1110
1111 if StartPos != self.CurrentOffsetWithinLine:
1112 self.__Token = self.__CurrentLine()[StartPos : self.CurrentOffsetWithinLine]
1113 return True
1114 else:
1115 return False
1116 ## __GetNextGuid() method
1117 #
1118 # Get next token unit before a seperator
1119 # If found, the GUID string is put into self.__Token
1120 #
1121 # @param self The object pointer
1122 # @retval True Successfully find a registry format GUID, file buffer pointer moved forward
1123 # @retval False Not able to find a registry format GUID, file buffer pointer not changed
1124 #
1125 def __GetNextGuid(self):
1126
1127 if not self.__GetNextToken():
1128 return False
1129 if gGuidPattern.match(self.__Token) is not None:
1130 return True
1131 else:
1132 self.__UndoToken()
1133 return False
1134
1135 @staticmethod
1136 def __Verify(Name, Value, Scope):
1137 # value verification only applies to numeric values.
1138 if Scope not in TAB_PCD_NUMERIC_TYPES:
1139 return
1140
1141 ValueNumber = 0
1142 try:
1143 ValueNumber = int(Value, 0)
1144 except:
1145 EdkLogger.error("FdfParser", FORMAT_INVALID, "The value is not valid dec or hex number for %s." % Name)
1146 if ValueNumber < 0:
1147 EdkLogger.error("FdfParser", FORMAT_INVALID, "The value can't be set to negative value for %s." % Name)
1148 if ValueNumber > MAX_VAL_TYPE[Scope]:
1149 EdkLogger.error("FdfParser", FORMAT_INVALID, "Too large value for %s." % Name)
1150 return True
1151
1152 ## __UndoToken() method
1153 #
1154 # Go back one token unit in file buffer
1155 #
1156 # @param self The object pointer
1157 #
1158 def __UndoToken(self):
1159 self.__UndoOneChar()
1160 while self.__CurrentChar().isspace():
1161 if not self.__UndoOneChar():
1162 self.__GetOneChar()
1163 return
1164
1165
1166 StartPos = self.CurrentOffsetWithinLine
1167 CurrentLine = self.CurrentLineNumber
1168 while CurrentLine == self.CurrentLineNumber:
1169
1170 TempChar = self.__CurrentChar()
1171 # Try to find the end char that is not a space and not in seperator tuple.
1172 # That is, when we got a space or any char in the tuple, we got the end of token.
1173 if not str(TempChar).isspace() and not TempChar in SEPERATOR_TUPLE:
1174 if not self.__UndoOneChar():
1175 return
1176 # if we happen to meet a seperator as the first char, we must proceed to get it.
1177 # That is, we get a token that is a seperator char. nomally it is the boundary of other tokens.
1178 elif StartPos == self.CurrentOffsetWithinLine and TempChar in SEPERATOR_TUPLE:
1179 return
1180 else:
1181 break
1182
1183 self.__GetOneChar()
1184
1185 ## __GetNextHexNumber() method
1186 #
1187 # Get next HEX data before a seperator
1188 # If found, the HEX data is put into self.__Token
1189 #
1190 # @param self The object pointer
1191 # @retval True Successfully find a HEX data, file buffer pointer moved forward
1192 # @retval False Not able to find a HEX data, file buffer pointer not changed
1193 #
1194 def __GetNextHexNumber(self):
1195 if not self.__GetNextToken():
1196 return False
1197 if gHexPatternAll.match(self.__Token):
1198 return True
1199 else:
1200 self.__UndoToken()
1201 return False
1202
1203 ## __GetNextDecimalNumber() method
1204 #
1205 # Get next decimal data before a seperator
1206 # If found, the decimal data is put into self.__Token
1207 #
1208 # @param self The object pointer
1209 # @retval True Successfully find a decimal data, file buffer pointer moved forward
1210 # @retval False Not able to find a decimal data, file buffer pointer not changed
1211 #
1212 def __GetNextDecimalNumber(self):
1213 if not self.__GetNextToken():
1214 return False
1215 if self.__Token.isdigit():
1216 return True
1217 else:
1218 self.__UndoToken()
1219 return False
1220
1221 ## __GetNextPcdName() method
1222 #
1223 # Get next PCD token space C name and PCD C name pair before a seperator
1224 # If found, the decimal data is put into self.__Token
1225 #
1226 # @param self The object pointer
1227 # @retval Tuple PCD C name and PCD token space C name pair
1228 #
1229 def __GetNextPcdName(self):
1230 if not self.__GetNextWord():
1231 raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
1232 pcdTokenSpaceCName = self.__Token
1233
1234 if not self.__IsToken( "."):
1235 raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
1236
1237 if not self.__GetNextWord():
1238 raise Warning("expected format of <PcdTokenSpaceCName>.<PcdCName>", self.FileName, self.CurrentLineNumber)
1239 pcdCName = self.__Token
1240
1241 return (pcdCName, pcdTokenSpaceCName)
1242
1243 ## __GetStringData() method
1244 #
1245 # Get string contents quoted in ""
1246 # If found, the decimal data is put into self.__Token
1247 #
1248 # @param self The object pointer
1249 # @retval True Successfully find a string data, file buffer pointer moved forward
1250 # @retval False Not able to find a string data, file buffer pointer not changed
1251 #
1252 def __GetStringData(self):
1253 if self.__Token.startswith("\"") or self.__Token.startswith("L\""):
1254 self.__UndoToken()
1255 self.__SkipToToken("\"")
1256 currentLineNumber = self.CurrentLineNumber
1257
1258 if not self.__SkipToToken("\""):
1259 raise Warning("Missing Quote \" for String", self.FileName, self.CurrentLineNumber)
1260 if currentLineNumber != self.CurrentLineNumber:
1261 raise Warning("Missing Quote \" for String", self.FileName, self.CurrentLineNumber)
1262 self.__Token = self.__SkippedChars.rstrip('\"')
1263 return True
1264
1265 elif self.__Token.startswith("\'") or self.__Token.startswith("L\'"):
1266 self.__UndoToken()
1267 self.__SkipToToken("\'")
1268 currentLineNumber = self.CurrentLineNumber
1269
1270 if not self.__SkipToToken("\'"):
1271 raise Warning("Missing Quote \' for String", self.FileName, self.CurrentLineNumber)
1272 if currentLineNumber != self.CurrentLineNumber:
1273 raise Warning("Missing Quote \' for String", self.FileName, self.CurrentLineNumber)
1274 self.__Token = self.__SkippedChars.rstrip('\'')
1275 return True
1276
1277 else:
1278 return False
1279
1280 ## __SkipToToken() method
1281 #
1282 # Search forward in file buffer for the string
1283 # The skipped chars are put into self.__SkippedChars
1284 #
1285 # @param self The object pointer
1286 # @param String The string to search
1287 # @param IgnoreCase Indicate case sensitive/non-sensitive search, default is case sensitive
1288 # @retval True Successfully find the string, file buffer pointer moved forward
1289 # @retval False Not able to find the string, file buffer pointer not changed
1290 #
1291 def __SkipToToken(self, String, IgnoreCase = False):
1292 StartPos = self.GetFileBufferPos()
1293
1294 self.__SkippedChars = ""
1295 while not self.__EndOfFile():
1296 index = -1
1297 if IgnoreCase:
1298 index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].upper().find(String.upper())
1299 else:
1300 index = self.__CurrentLine()[self.CurrentOffsetWithinLine : ].find(String)
1301 if index == 0:
1302 self.CurrentOffsetWithinLine += len(String)
1303 self.__SkippedChars += String
1304 return True
1305 self.__SkippedChars += str(self.__CurrentChar())
1306 self.__GetOneChar()
1307
1308 self.SetFileBufferPos( StartPos)
1309 self.__SkippedChars = ""
1310 return False
1311
1312 ## GetFileBufferPos() method
1313 #
1314 # Return the tuple of current line and offset within the line
1315 #
1316 # @param self The object pointer
1317 # @retval Tuple Line number and offset pair
1318 #
1319 def GetFileBufferPos(self):
1320 return (self.CurrentLineNumber, self.CurrentOffsetWithinLine)
1321
1322 ## SetFileBufferPos() method
1323 #
1324 # Restore the file buffer position
1325 #
1326 # @param self The object pointer
1327 # @param Pos The new file buffer position
1328 #
1329 def SetFileBufferPos(self, Pos):
1330 (self.CurrentLineNumber, self.CurrentOffsetWithinLine) = Pos
1331
1332 ## Preprocess() method
1333 #
1334 # Preprocess comment, conditional directive, include directive, replace macro.
1335 # Exception will be raised if syntax error found
1336 #
1337 # @param self The object pointer
1338 #
1339 def Preprocess(self):
1340 self.__StringToList()
1341 self.PreprocessFile()
1342 self.PreprocessIncludeFile()
1343 self.__StringToList()
1344 self.PreprocessFile()
1345 self.PreprocessConditionalStatement()
1346 self.__StringToList()
1347 for Pos in self.__WipeOffArea:
1348 self.__ReplaceFragment(Pos[0], Pos[1])
1349 self.Profile.FileLinesList = ["".join(list) for list in self.Profile.FileLinesList]
1350
1351 while self.__GetDefines():
1352 pass
1353
1354 ## ParseFile() method
1355 #
1356 # Parse the file profile buffer to extract fd, fv ... information
1357 # Exception will be raised if syntax error found
1358 #
1359 # @param self The object pointer
1360 #
1361 def ParseFile(self):
1362
1363 try:
1364 self.Preprocess()
1365 self.__GetError()
1366 #
1367 # Keep processing sections of the FDF until no new sections or a syntax error is found
1368 #
1369 while self.__GetFd() or self.__GetFv() or self.__GetFmp() or self.__GetCapsule() or self.__GetVtf() or self.__GetRule() or self.__GetOptionRom():
1370 pass
1371
1372 except Warning as X:
1373 self.__UndoToken()
1374 #'\n\tGot Token: \"%s\" from File %s\n' % (self.__Token, FileLineTuple[0]) + \
1375 # At this point, the closest parent would be the included file itself
1376 Profile = GetParentAtLine(X.OriginalLineNumber)
1377 if Profile is not None:
1378 X.Message += ' near line %d, column %d: %s' \
1379 % (X.LineNumber, 0, Profile.FileLinesList[X.LineNumber-1])
1380 else:
1381 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1382 X.Message += ' near line %d, column %d: %s' \
1383 % (FileLineTuple[1], self.CurrentOffsetWithinLine + 1, self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :].rstrip('\n').rstrip('\r'))
1384 raise
1385
1386 ## SectionParser() method
1387 #
1388 # Parse the file section info
1389 # Exception will be raised if syntax error found
1390 #
1391 # @param self The object pointer
1392 # @param section The section string
1393
1394 def SectionParser(self, section):
1395 S = section.upper()
1396 if not S.startswith("[DEFINES") and not S.startswith("[FD.") and not S.startswith("[FV.") and not S.startswith("[CAPSULE.") \
1397 and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM.") and not S.startswith('[FMPPAYLOAD.'):
1398 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)
1399
1400 ## __GetDefines() method
1401 #
1402 # Get Defines section contents and store its data into AllMacrosList
1403 #
1404 # @param self The object pointer
1405 # @retval True Successfully find a Defines
1406 # @retval False Not able to find a Defines
1407 #
1408 def __GetDefines(self):
1409
1410 if not self.__GetNextToken():
1411 return False
1412
1413 S = self.__Token.upper()
1414 if S.startswith("[") and not S.startswith("[DEFINES"):
1415 self.SectionParser(S)
1416 self.__UndoToken()
1417 return False
1418
1419 self.__UndoToken()
1420 if not self.__IsToken("[DEFINES", True):
1421 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1422 #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1423 # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1424 raise Warning("expected [DEFINES", self.FileName, self.CurrentLineNumber)
1425
1426 if not self.__IsToken( "]"):
1427 raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
1428
1429 while self.__GetNextWord():
1430 # handle the SET statement
1431 if self.__Token == 'SET':
1432 self.__UndoToken()
1433 self.__GetSetStatement(None)
1434 continue
1435
1436 Macro = self.__Token
1437
1438 if not self.__IsToken("="):
1439 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1440 if not self.__GetNextToken() or self.__Token.startswith('['):
1441 raise Warning("expected MACRO value", self.FileName, self.CurrentLineNumber)
1442 Value = self.__Token
1443
1444 return False
1445
1446 ##__GetError() method
1447 def __GetError(self):
1448 #save the Current information
1449 CurrentLine = self.CurrentLineNumber
1450 CurrentOffset = self.CurrentOffsetWithinLine
1451 while self.__GetNextToken():
1452 if self.__Token == TAB_ERROR:
1453 EdkLogger.error('FdfParser', ERROR_STATEMENT, self.__CurrentLine().replace(TAB_ERROR, '', 1), File=self.FileName, Line=self.CurrentLineNumber)
1454 self.CurrentLineNumber = CurrentLine
1455 self.CurrentOffsetWithinLine = CurrentOffset
1456
1457 ## __GetFd() method
1458 #
1459 # Get FD section contents and store its data into FD dictionary of self.Profile
1460 #
1461 # @param self The object pointer
1462 # @retval True Successfully find a FD
1463 # @retval False Not able to find a FD
1464 #
1465 def __GetFd(self):
1466
1467 if not self.__GetNextToken():
1468 return False
1469
1470 S = self.__Token.upper()
1471 if S.startswith("[") and not S.startswith("[FD."):
1472 if not S.startswith("[FV.") and not S.startswith('[FMPPAYLOAD.') and not S.startswith("[CAPSULE.") \
1473 and not S.startswith("[VTF.") and not S.startswith("[RULE.") and not S.startswith("[OPTIONROM."):
1474 raise Warning("Unknown section", self.FileName, self.CurrentLineNumber)
1475 self.__UndoToken()
1476 return False
1477
1478 self.__UndoToken()
1479 if not self.__IsToken("[FD.", True):
1480 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1481 #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
1482 # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
1483 raise Warning("expected [FD.]", self.FileName, self.CurrentLineNumber)
1484
1485 FdName = self.__GetUiName()
1486 if FdName == "":
1487 if len (self.Profile.FdDict) == 0:
1488 FdName = GenFdsGlobalVariable.PlatformName
1489 if FdName == "" and GlobalData.gActivePlatform:
1490 FdName = GlobalData.gActivePlatform.PlatformName
1491 self.Profile.FdNameNotSet = True
1492 else:
1493 raise Warning("expected FdName in [FD.] section", self.FileName, self.CurrentLineNumber)
1494 self.CurrentFdName = FdName.upper()
1495
1496 if self.CurrentFdName in self.Profile.FdDict:
1497 raise Warning("Unexpected the same FD name", self.FileName, self.CurrentLineNumber)
1498
1499 if not self.__IsToken( "]"):
1500 raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
1501
1502 FdObj = Fd.FD()
1503 FdObj.FdUiName = self.CurrentFdName
1504 self.Profile.FdDict[self.CurrentFdName] = FdObj
1505
1506 if len (self.Profile.FdDict) > 1 and self.Profile.FdNameNotSet:
1507 raise Warning("expected all FDs have their name", self.FileName, self.CurrentLineNumber)
1508
1509 Status = self.__GetCreateFile(FdObj)
1510 if not Status:
1511 raise Warning("FD name error", self.FileName, self.CurrentLineNumber)
1512
1513 while self.__GetTokenStatements(FdObj):
1514 pass
1515 for Attr in ("BaseAddress", "Size", "ErasePolarity"):
1516 if getattr(FdObj, Attr) is None:
1517 self.__GetNextToken()
1518 raise Warning("Keyword %s missing" % Attr, self.FileName, self.CurrentLineNumber)
1519
1520 if not FdObj.BlockSizeList:
1521 FdObj.BlockSizeList.append((1, FdObj.Size, None))
1522
1523 self.__GetDefineStatements(FdObj)
1524
1525 self.__GetSetStatements(FdObj)
1526
1527 if not self.__GetRegionLayout(FdObj):
1528 raise Warning("expected region layout", self.FileName, self.CurrentLineNumber)
1529
1530 while self.__GetRegionLayout(FdObj):
1531 pass
1532 return True
1533
1534 ## __GetUiName() method
1535 #
1536 # Return the UI name of a section
1537 #
1538 # @param self The object pointer
1539 # @retval FdName UI name
1540 #
1541 def __GetUiName(self):
1542 Name = ""
1543 if self.__GetNextWord():
1544 Name = self.__Token
1545
1546 return Name
1547
1548 ## __GetCreateFile() method
1549 #
1550 # Return the output file name of object
1551 #
1552 # @param self The object pointer
1553 # @param Obj object whose data will be stored in file
1554 # @retval FdName UI name
1555 #
1556 def __GetCreateFile(self, Obj):
1557
1558 if self.__IsKeyword( "CREATE_FILE"):
1559 if not self.__IsToken( "="):
1560 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1561
1562 if not self.__GetNextToken():
1563 raise Warning("expected file name", self.FileName, self.CurrentLineNumber)
1564
1565 FileName = self.__Token
1566 Obj.CreateFileName = FileName
1567
1568 return True
1569
1570 ## __GetTokenStatements() method
1571 #
1572 # Get token statements
1573 #
1574 # @param self The object pointer
1575 # @param Obj for whom token statement is got
1576 #
1577 def __GetTokenStatements(self, Obj):
1578 if self.__IsKeyword( "BaseAddress"):
1579 if not self.__IsToken( "="):
1580 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1581
1582 if not self.__GetNextHexNumber():
1583 raise Warning("expected Hex base address", self.FileName, self.CurrentLineNumber)
1584
1585 Obj.BaseAddress = self.__Token
1586
1587 if self.__IsToken( "|"):
1588 pcdPair = self.__GetNextPcdName()
1589 Obj.BaseAddressPcd = pcdPair
1590 self.Profile.PcdDict[pcdPair] = Obj.BaseAddress
1591 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1592 self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1593 return True
1594
1595 if self.__IsKeyword( "Size"):
1596 if not self.__IsToken( "="):
1597 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1598
1599 if not self.__GetNextHexNumber():
1600 raise Warning("expected Hex size", self.FileName, self.CurrentLineNumber)
1601
1602 Size = self.__Token
1603 if self.__IsToken( "|"):
1604 pcdPair = self.__GetNextPcdName()
1605 Obj.SizePcd = pcdPair
1606 self.Profile.PcdDict[pcdPair] = Size
1607 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1608 self.Profile.PcdFileLineDict[pcdPair] = FileLineTuple
1609 Obj.Size = long(Size, 0)
1610 return True
1611
1612 if self.__IsKeyword( "ErasePolarity"):
1613 if not self.__IsToken( "="):
1614 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1615
1616 if not self.__GetNextToken():
1617 raise Warning("expected Erase Polarity", self.FileName, self.CurrentLineNumber)
1618
1619 if self.__Token != "1" and self.__Token != "0":
1620 raise Warning("expected 1 or 0 Erase Polarity", self.FileName, self.CurrentLineNumber)
1621
1622 Obj.ErasePolarity = self.__Token
1623 return True
1624
1625 return self.__GetBlockStatements(Obj)
1626
1627 ## __GetAddressStatements() method
1628 #
1629 # Get address statements
1630 #
1631 # @param self The object pointer
1632 # @param Obj for whom address statement is got
1633 # @retval True Successfully find
1634 # @retval False Not able to find
1635 #
1636 def __GetAddressStatements(self, Obj):
1637
1638 if self.__IsKeyword("BsBaseAddress"):
1639 if not self.__IsToken( "="):
1640 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1641
1642 if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1643 raise Warning("expected address", self.FileName, self.CurrentLineNumber)
1644
1645 BsAddress = long(self.__Token, 0)
1646 Obj.BsBaseAddress = BsAddress
1647
1648 if self.__IsKeyword("RtBaseAddress"):
1649 if not self.__IsToken( "="):
1650 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1651
1652 if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1653 raise Warning("expected address", self.FileName, self.CurrentLineNumber)
1654
1655 RtAddress = long(self.__Token, 0)
1656 Obj.RtBaseAddress = RtAddress
1657
1658 ## __GetBlockStatements() method
1659 #
1660 # Get block statements
1661 #
1662 # @param self The object pointer
1663 # @param Obj for whom block statement is got
1664 #
1665 def __GetBlockStatements(self, Obj):
1666 IsBlock = False
1667 while self.__GetBlockStatement(Obj):
1668 IsBlock = True
1669
1670 Item = Obj.BlockSizeList[-1]
1671 if Item[0] is None or Item[1] is None:
1672 raise Warning("expected block statement", self.FileName, self.CurrentLineNumber)
1673 return IsBlock
1674
1675 ## __GetBlockStatement() method
1676 #
1677 # Get block statement
1678 #
1679 # @param self The object pointer
1680 # @param Obj for whom block statement is got
1681 # @retval True Successfully find
1682 # @retval False Not able to find
1683 #
1684 def __GetBlockStatement(self, Obj):
1685 if not self.__IsKeyword( "BlockSize"):
1686 return False
1687
1688 if not self.__IsToken( "="):
1689 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1690
1691 if not self.__GetNextHexNumber() and not self.__GetNextDecimalNumber():
1692 raise Warning("expected Hex or Integer block size", self.FileName, self.CurrentLineNumber)
1693
1694 BlockSize = self.__Token
1695 BlockSizePcd = None
1696 if self.__IsToken( "|"):
1697 PcdPair = self.__GetNextPcdName()
1698 BlockSizePcd = PcdPair
1699 self.Profile.PcdDict[PcdPair] = BlockSize
1700 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1701 self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
1702 BlockSize = long(BlockSize, 0)
1703
1704 BlockNumber = None
1705 if self.__IsKeyword( "NumBlocks"):
1706 if not self.__IsToken( "="):
1707 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1708
1709 if not self.__GetNextDecimalNumber() and not self.__GetNextHexNumber():
1710 raise Warning("expected block numbers", self.FileName, self.CurrentLineNumber)
1711
1712 BlockNumber = long(self.__Token, 0)
1713
1714 Obj.BlockSizeList.append((BlockSize, BlockNumber, BlockSizePcd))
1715 return True
1716
1717 ## __GetDefineStatements() method
1718 #
1719 # Get define statements
1720 #
1721 # @param self The object pointer
1722 # @param Obj for whom define statement is got
1723 # @retval True Successfully find
1724 # @retval False Not able to find
1725 #
1726 def __GetDefineStatements(self, Obj):
1727 while self.__GetDefineStatement( Obj):
1728 pass
1729
1730 ## __GetDefineStatement() method
1731 #
1732 # Get define statement
1733 #
1734 # @param self The object pointer
1735 # @param Obj for whom define statement is got
1736 # @retval True Successfully find
1737 # @retval False Not able to find
1738 #
1739 def __GetDefineStatement(self, Obj):
1740 if self.__IsKeyword("DEFINE"):
1741 self.__GetNextToken()
1742 Macro = self.__Token
1743 if not self.__IsToken( "="):
1744 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1745
1746 if not self.__GetNextToken():
1747 raise Warning("expected value", self.FileName, self.CurrentLineNumber)
1748
1749 Value = self.__Token
1750 Macro = '$(' + Macro + ')'
1751 Obj.DefineVarDict[Macro] = Value
1752 return True
1753
1754 return False
1755
1756 ## __GetSetStatements() method
1757 #
1758 # Get set statements
1759 #
1760 # @param self The object pointer
1761 # @param Obj for whom set statement is got
1762 # @retval True Successfully find
1763 # @retval False Not able to find
1764 #
1765 def __GetSetStatements(self, Obj):
1766 while self.__GetSetStatement(Obj):
1767 pass
1768
1769 ## __GetSetStatement() method
1770 #
1771 # Get set statement
1772 #
1773 # @param self The object pointer
1774 # @param Obj for whom set statement is got
1775 # @retval True Successfully find
1776 # @retval False Not able to find
1777 #
1778 def __GetSetStatement(self, Obj):
1779 if self.__IsKeyword("SET"):
1780 PcdPair = self.__GetNextPcdName()
1781
1782 if not self.__IsToken( "="):
1783 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1784
1785 Value = self.__GetExpression()
1786 Value = self.__EvaluateConditional(Value, self.CurrentLineNumber, 'eval', True)
1787
1788 if Obj:
1789 Obj.SetVarDict[PcdPair] = Value
1790 self.Profile.PcdDict[PcdPair] = Value
1791 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1792 self.Profile.PcdFileLineDict[PcdPair] = FileLineTuple
1793 return True
1794
1795 return False
1796
1797 ## __CalcRegionExpr(self)
1798 #
1799 # Calculate expression for offset or size of a region
1800 #
1801 # @return: None if invalid expression
1802 # Calculated number if successfully
1803 #
1804 def __CalcRegionExpr(self):
1805 StartPos = self.GetFileBufferPos()
1806 Expr = ''
1807 PairCount = 0
1808 while not self.__EndOfFile():
1809 CurCh = self.__CurrentChar()
1810 if CurCh == '(':
1811 PairCount += 1
1812 elif CurCh == ')':
1813 PairCount -= 1
1814
1815 if CurCh in '|\r\n' and PairCount == 0:
1816 break
1817 Expr += CurCh
1818 self.__GetOneChar()
1819 try:
1820 return long(
1821 ValueExpression(Expr,
1822 self.__CollectMacroPcd()
1823 )(True), 0)
1824 except Exception:
1825 self.SetFileBufferPos(StartPos)
1826 return None
1827
1828 ## __GetRegionLayout() method
1829 #
1830 # Get region layout for FD
1831 #
1832 # @param self The object pointer
1833 # @param Fd for whom region is got
1834 # @retval True Successfully find
1835 # @retval False Not able to find
1836 #
1837 def __GetRegionLayout(self, Fd):
1838 Offset = self.__CalcRegionExpr()
1839 if Offset is None:
1840 return False
1841
1842 RegionObj = Region.Region()
1843 RegionObj.Offset = Offset
1844 Fd.RegionList.append(RegionObj)
1845
1846 if not self.__IsToken( "|"):
1847 raise Warning("expected '|'", self.FileName, self.CurrentLineNumber)
1848
1849 Size = self.__CalcRegionExpr()
1850 if Size is None:
1851 raise Warning("expected Region Size", self.FileName, self.CurrentLineNumber)
1852 RegionObj.Size = Size
1853
1854 if not self.__GetNextWord():
1855 return True
1856
1857 if not self.__Token in ("SET", BINARY_FILE_TYPE_FV, "FILE", "DATA", "CAPSULE", "INF"):
1858 #
1859 # If next token is a word which is not a valid FV type, it might be part of [PcdOffset[|PcdSize]]
1860 # Or it might be next region's offset described by an expression which starts with a PCD.
1861 # PcdOffset[|PcdSize] or OffsetPcdExpression|Size
1862 #
1863 self.__UndoToken()
1864 IsRegionPcd = (RegionSizeGuidPattern.match(self.__CurrentLine()[self.CurrentOffsetWithinLine:]) or
1865 RegionOffsetPcdPattern.match(self.__CurrentLine()[self.CurrentOffsetWithinLine:]))
1866 if IsRegionPcd:
1867 RegionObj.PcdOffset = self.__GetNextPcdName()
1868 self.Profile.PcdDict[RegionObj.PcdOffset] = "0x%08X" % (RegionObj.Offset + long(Fd.BaseAddress, 0))
1869 self.__PcdDict['%s.%s' % (RegionObj.PcdOffset[1], RegionObj.PcdOffset[0])] = "0x%x" % RegionObj.Offset
1870 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1871 self.Profile.PcdFileLineDict[RegionObj.PcdOffset] = FileLineTuple
1872 if self.__IsToken( "|"):
1873 RegionObj.PcdSize = self.__GetNextPcdName()
1874 self.Profile.PcdDict[RegionObj.PcdSize] = "0x%08X" % RegionObj.Size
1875 self.__PcdDict['%s.%s' % (RegionObj.PcdSize[1], RegionObj.PcdSize[0])] = "0x%x" % RegionObj.Size
1876 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
1877 self.Profile.PcdFileLineDict[RegionObj.PcdSize] = FileLineTuple
1878
1879 if not self.__GetNextWord():
1880 return True
1881
1882 if self.__Token == "SET":
1883 self.__UndoToken()
1884 self.__GetSetStatements( RegionObj)
1885 if not self.__GetNextWord():
1886 return True
1887
1888 elif self.__Token == BINARY_FILE_TYPE_FV:
1889 self.__UndoToken()
1890 self.__GetRegionFvType( RegionObj)
1891
1892 elif self.__Token == "CAPSULE":
1893 self.__UndoToken()
1894 self.__GetRegionCapType( RegionObj)
1895
1896 elif self.__Token == "FILE":
1897 self.__UndoToken()
1898 self.__GetRegionFileType(RegionObj)
1899
1900 elif self.__Token == "INF":
1901 self.__UndoToken()
1902 RegionObj.RegionType = "INF"
1903 while self.__IsKeyword("INF"):
1904 self.__UndoToken()
1905 ffsInf = self.__ParseInfStatement()
1906 if not ffsInf:
1907 break
1908 RegionObj.RegionDataList.append(ffsInf)
1909
1910 elif self.__Token == "DATA":
1911 self.__UndoToken()
1912 self.__GetRegionDataType(RegionObj)
1913 else:
1914 self.__UndoToken()
1915 if self.__GetRegionLayout(Fd):
1916 return True
1917 raise Warning("A valid region type was not found. "
1918 "Valid types are [SET, FV, CAPSULE, FILE, DATA, INF]. This error occurred",
1919 self.FileName, self.CurrentLineNumber)
1920
1921 return True
1922
1923 ## __GetRegionFvType() method
1924 #
1925 # Get region fv data for region
1926 #
1927 # @param self The object pointer
1928 # @param RegionObj for whom region data is got
1929 #
1930 def __GetRegionFvType(self, RegionObj):
1931
1932 if not self.__IsKeyword( BINARY_FILE_TYPE_FV):
1933 raise Warning("expected Keyword BINARY_FILE_TYPE_FV", self.FileName, self.CurrentLineNumber)
1934
1935 if not self.__IsToken( "="):
1936 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1937
1938 if not self.__GetNextToken():
1939 raise Warning("expected FV name", self.FileName, self.CurrentLineNumber)
1940
1941 RegionObj.RegionType = BINARY_FILE_TYPE_FV
1942 RegionObj.RegionDataList.append((self.__Token).upper())
1943
1944 while self.__IsKeyword( BINARY_FILE_TYPE_FV):
1945
1946 if not self.__IsToken( "="):
1947 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1948
1949 if not self.__GetNextToken():
1950 raise Warning("expected FV name", self.FileName, self.CurrentLineNumber)
1951
1952 RegionObj.RegionDataList.append((self.__Token).upper())
1953
1954 ## __GetRegionCapType() method
1955 #
1956 # Get region capsule data for region
1957 #
1958 # @param self The object pointer
1959 # @param RegionObj for whom region data is got
1960 #
1961 def __GetRegionCapType(self, RegionObj):
1962
1963 if not self.__IsKeyword("CAPSULE"):
1964 raise Warning("expected Keyword 'CAPSULE'", self.FileName, self.CurrentLineNumber)
1965
1966 if not self.__IsToken("="):
1967 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1968
1969 if not self.__GetNextToken():
1970 raise Warning("expected CAPSULE name", self.FileName, self.CurrentLineNumber)
1971
1972 RegionObj.RegionType = "CAPSULE"
1973 RegionObj.RegionDataList.append(self.__Token)
1974
1975 while self.__IsKeyword("CAPSULE"):
1976
1977 if not self.__IsToken("="):
1978 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1979
1980 if not self.__GetNextToken():
1981 raise Warning("expected CAPSULE name", self.FileName, self.CurrentLineNumber)
1982
1983 RegionObj.RegionDataList.append(self.__Token)
1984
1985 ## __GetRegionFileType() method
1986 #
1987 # Get region file data for region
1988 #
1989 # @param self The object pointer
1990 # @param RegionObj for whom region data is got
1991 #
1992 def __GetRegionFileType(self, RegionObj):
1993
1994 if not self.__IsKeyword( "FILE"):
1995 raise Warning("expected Keyword 'FILE'", self.FileName, self.CurrentLineNumber)
1996
1997 if not self.__IsToken( "="):
1998 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
1999
2000 if not self.__GetNextToken():
2001 raise Warning("expected File name", self.FileName, self.CurrentLineNumber)
2002
2003 RegionObj.RegionType = "FILE"
2004 RegionObj.RegionDataList.append( self.__Token)
2005
2006 while self.__IsKeyword( "FILE"):
2007
2008 if not self.__IsToken( "="):
2009 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2010
2011 if not self.__GetNextToken():
2012 raise Warning("expected FILE name", self.FileName, self.CurrentLineNumber)
2013
2014 RegionObj.RegionDataList.append(self.__Token)
2015
2016 ## __GetRegionDataType() method
2017 #
2018 # Get region array data for region
2019 #
2020 # @param self The object pointer
2021 # @param RegionObj for whom region data is got
2022 #
2023 def __GetRegionDataType(self, RegionObj):
2024
2025 if not self.__IsKeyword( "DATA"):
2026 raise Warning("expected Region Data type", self.FileName, self.CurrentLineNumber)
2027
2028 if not self.__IsToken( "="):
2029 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2030
2031 if not self.__IsToken( "{"):
2032 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2033
2034 if not self.__GetNextHexNumber():
2035 raise Warning("expected Hex byte", self.FileName, self.CurrentLineNumber)
2036
2037 if len(self.__Token) > 18:
2038 raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
2039
2040 # convert hex string value to byte hex string array
2041 AllString = self.__Token
2042 AllStrLen = len (AllString)
2043 DataString = ""
2044 while AllStrLen > 4:
2045 DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + ","
2046 AllStrLen = AllStrLen - 2
2047 DataString = DataString + AllString[:AllStrLen] + ","
2048
2049 # byte value array
2050 if len (self.__Token) <= 4:
2051 while self.__IsToken(","):
2052 if not self.__GetNextHexNumber():
2053 raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2054 if len(self.__Token) > 4:
2055 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2056 DataString += self.__Token
2057 DataString += ","
2058
2059 if not self.__IsToken( "}"):
2060 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2061
2062 DataString = DataString.rstrip(",")
2063 RegionObj.RegionType = "DATA"
2064 RegionObj.RegionDataList.append( DataString)
2065
2066 while self.__IsKeyword( "DATA"):
2067
2068 if not self.__IsToken( "="):
2069 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2070
2071 if not self.__IsToken( "{"):
2072 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2073
2074 if not self.__GetNextHexNumber():
2075 raise Warning("expected Hex byte", self.FileName, self.CurrentLineNumber)
2076
2077 if len(self.__Token) > 18:
2078 raise Warning("Hex string can't be converted to a valid UINT64 value", self.FileName, self.CurrentLineNumber)
2079
2080 # convert hex string value to byte hex string array
2081 AllString = self.__Token
2082 AllStrLen = len (AllString)
2083 DataString = ""
2084 while AllStrLen > 4:
2085 DataString = DataString + "0x" + AllString[AllStrLen - 2: AllStrLen] + ","
2086 AllStrLen = AllStrLen - 2
2087 DataString = DataString + AllString[:AllStrLen] + ","
2088
2089 # byte value array
2090 if len (self.__Token) <= 4:
2091 while self.__IsToken(","):
2092 if not self.__GetNextHexNumber():
2093 raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2094 if len(self.__Token) > 4:
2095 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2096 DataString += self.__Token
2097 DataString += ","
2098
2099 if not self.__IsToken( "}"):
2100 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2101
2102 DataString = DataString.rstrip(",")
2103 RegionObj.RegionDataList.append( DataString)
2104
2105 ## __GetFv() method
2106 #
2107 # Get FV section contents and store its data into FV dictionary of self.Profile
2108 #
2109 # @param self The object pointer
2110 # @retval True Successfully find a FV
2111 # @retval False Not able to find a FV
2112 #
2113 def __GetFv(self):
2114 if not self.__GetNextToken():
2115 return False
2116
2117 S = self.__Token.upper()
2118 if S.startswith("[") and not S.startswith("[FV."):
2119 self.SectionParser(S)
2120 self.__UndoToken()
2121 return False
2122
2123 self.__UndoToken()
2124 if not self.__IsToken("[FV.", True):
2125 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2126 #print 'Parsing String: %s in File %s, At line: %d, Offset Within Line: %d' \
2127 # % (self.Profile.FileLinesList[self.CurrentLineNumber - 1][self.CurrentOffsetWithinLine :], FileLineTuple[0], FileLineTuple[1], self.CurrentOffsetWithinLine)
2128 raise Warning("Unknown Keyword '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2129
2130 FvName = self.__GetUiName()
2131 self.CurrentFvName = FvName.upper()
2132
2133 if not self.__IsToken( "]"):
2134 raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
2135
2136 FvObj = Fv.FV()
2137 FvObj.UiFvName = self.CurrentFvName
2138 self.Profile.FvDict[self.CurrentFvName] = FvObj
2139
2140 Status = self.__GetCreateFile(FvObj)
2141 if not Status:
2142 raise Warning("FV name error", self.FileName, self.CurrentLineNumber)
2143
2144 self.__GetDefineStatements(FvObj)
2145
2146 self.__GetAddressStatements(FvObj)
2147
2148 FvObj.FvExtEntryTypeValue = []
2149 FvObj.FvExtEntryType = []
2150 FvObj.FvExtEntryData = []
2151 while True:
2152 self.__GetSetStatements(FvObj)
2153
2154 if not (self.__GetBlockStatement(FvObj) or self.__GetFvBaseAddress(FvObj) or
2155 self.__GetFvForceRebase(FvObj) or self.__GetFvAlignment(FvObj) or
2156 self.__GetFvAttributes(FvObj) or self.__GetFvNameGuid(FvObj) or
2157 self.__GetFvExtEntryStatement(FvObj) or self.__GetFvNameString(FvObj)):
2158 break
2159
2160 if FvObj.FvNameString == 'TRUE' and not FvObj.FvNameGuid:
2161 raise Warning("FvNameString found but FvNameGuid was not found", self.FileName, self.CurrentLineNumber)
2162
2163 self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy())
2164 self.__GetAprioriSection(FvObj, FvObj.DefineVarDict.copy())
2165
2166 while True:
2167 isInf = self.__GetInfStatement(FvObj)
2168 isFile = self.__GetFileStatement(FvObj, MacroDict = FvObj.DefineVarDict.copy())
2169 if not isInf and not isFile:
2170 break
2171
2172 return True
2173
2174 ## __GetFvAlignment() method
2175 #
2176 # Get alignment for FV
2177 #
2178 # @param self The object pointer
2179 # @param Obj for whom alignment is got
2180 # @retval True Successfully find a alignment statement
2181 # @retval False Not able to find a alignment statement
2182 #
2183 def __GetFvAlignment(self, Obj):
2184
2185 if not self.__IsKeyword( "FvAlignment"):
2186 return False
2187
2188 if not self.__IsToken( "="):
2189 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2190
2191 if not self.__GetNextToken():
2192 raise Warning("expected alignment value", self.FileName, self.CurrentLineNumber)
2193
2194 if self.__Token.upper() not in ("1", "2", "4", "8", "16", "32", "64", "128", "256", "512", \
2195 "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", "512K", \
2196 "1M", "2M", "4M", "8M", "16M", "32M", "64M", "128M", "256M", "512M", \
2197 "1G", "2G"):
2198 raise Warning("Unknown alignment value '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2199 Obj.FvAlignment = self.__Token
2200 return True
2201
2202 ## __GetFvBaseAddress() method
2203 #
2204 # Get BaseAddress for FV
2205 #
2206 # @param self The object pointer
2207 # @param Obj for whom FvBaseAddress is got
2208 # @retval True Successfully find a FvBaseAddress statement
2209 # @retval False Not able to find a FvBaseAddress statement
2210 #
2211 def __GetFvBaseAddress(self, Obj):
2212
2213 if not self.__IsKeyword("FvBaseAddress"):
2214 return False
2215
2216 if not self.__IsToken( "="):
2217 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2218
2219 if not self.__GetNextToken():
2220 raise Warning("expected FV base address value", self.FileName, self.CurrentLineNumber)
2221
2222 if not BaseAddrValuePattern.match(self.__Token.upper()):
2223 raise Warning("Unknown FV base address value '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2224 Obj.FvBaseAddress = self.__Token
2225 return True
2226
2227 ## __GetFvForceRebase() method
2228 #
2229 # Get FvForceRebase for FV
2230 #
2231 # @param self The object pointer
2232 # @param Obj for whom FvForceRebase is got
2233 # @retval True Successfully find a FvForceRebase statement
2234 # @retval False Not able to find a FvForceRebase statement
2235 #
2236 def __GetFvForceRebase(self, Obj):
2237
2238 if not self.__IsKeyword("FvForceRebase"):
2239 return False
2240
2241 if not self.__IsToken( "="):
2242 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2243
2244 if not self.__GetNextToken():
2245 raise Warning("expected FvForceRebase value", self.FileName, self.CurrentLineNumber)
2246
2247 if self.__Token.upper() not in ["TRUE", "FALSE", "0", "0X0", "0X00", "1", "0X1", "0X01"]:
2248 raise Warning("Unknown FvForceRebase value '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2249
2250 if self.__Token.upper() in ["TRUE", "1", "0X1", "0X01"]:
2251 Obj.FvForceRebase = True
2252 elif self.__Token.upper() in ["FALSE", "0", "0X0", "0X00"]:
2253 Obj.FvForceRebase = False
2254 else:
2255 Obj.FvForceRebase = None
2256
2257 return True
2258
2259
2260 ## __GetFvAttributes() method
2261 #
2262 # Get attributes for FV
2263 #
2264 # @param self The object pointer
2265 # @param Obj for whom attribute is got
2266 # @retval None
2267 #
2268 def __GetFvAttributes(self, FvObj):
2269 IsWordToken = False
2270 while self.__GetNextWord():
2271 IsWordToken = True
2272 name = self.__Token
2273 if name not in ("ERASE_POLARITY", "MEMORY_MAPPED", \
2274 "STICKY_WRITE", "LOCK_CAP", "LOCK_STATUS", "WRITE_ENABLED_CAP", \
2275 "WRITE_DISABLED_CAP", "WRITE_STATUS", "READ_ENABLED_CAP", \
2276 "READ_DISABLED_CAP", "READ_STATUS", "READ_LOCK_CAP", \
2277 "READ_LOCK_STATUS", "WRITE_LOCK_CAP", "WRITE_LOCK_STATUS", \
2278 "WRITE_POLICY_RELIABLE", "WEAK_ALIGNMENT", "FvUsedSizeEnable"):
2279 self.__UndoToken()
2280 return False
2281
2282 if not self.__IsToken( "="):
2283 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2284
2285 if not self.__GetNextToken() or self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"):
2286 raise Warning("expected TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
2287
2288 FvObj.FvAttributeDict[name] = self.__Token
2289
2290 return IsWordToken
2291
2292 ## __GetFvNameGuid() method
2293 #
2294 # Get FV GUID for FV
2295 #
2296 # @param self The object pointer
2297 # @param Obj for whom GUID is got
2298 # @retval None
2299 #
2300 def __GetFvNameGuid(self, FvObj):
2301
2302 if not self.__IsKeyword( "FvNameGuid"):
2303 return False
2304
2305 if not self.__IsToken( "="):
2306 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2307
2308 if not self.__GetNextGuid():
2309 raise Warning("expected FV GUID value", self.FileName, self.CurrentLineNumber)
2310
2311 FvObj.FvNameGuid = self.__Token
2312
2313 return True
2314
2315 def __GetFvNameString(self, FvObj):
2316
2317 if not self.__IsKeyword( "FvNameString"):
2318 return False
2319
2320 if not self.__IsToken( "="):
2321 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2322
2323 if not self.__GetNextToken() or self.__Token not in ('TRUE', 'FALSE'):
2324 raise Warning("expected TRUE or FALSE for FvNameString", self.FileName, self.CurrentLineNumber)
2325
2326 FvObj.FvNameString = self.__Token
2327
2328 return True
2329
2330 def __GetFvExtEntryStatement(self, FvObj):
2331
2332 if not (self.__IsKeyword( "FV_EXT_ENTRY") or self.__IsKeyword( "FV_EXT_ENTRY_TYPE")):
2333 return False
2334
2335 if not self.__IsKeyword ("TYPE"):
2336 raise Warning("expected 'TYPE'", self.FileName, self.CurrentLineNumber)
2337
2338 if not self.__IsToken( "="):
2339 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2340
2341 if not self.__GetNextHexNumber() and not self.__GetNextDecimalNumber():
2342 raise Warning("expected Hex FV extension entry type value At Line ", self.FileName, self.CurrentLineNumber)
2343
2344 FvObj.FvExtEntryTypeValue.append(self.__Token)
2345
2346 if not self.__IsToken( "{"):
2347 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2348
2349 if not self.__IsKeyword ("FILE") and not self.__IsKeyword ("DATA"):
2350 raise Warning("expected 'FILE' or 'DATA'", self.FileName, self.CurrentLineNumber)
2351
2352 FvObj.FvExtEntryType.append(self.__Token)
2353
2354 if self.__Token == 'DATA':
2355
2356 if not self.__IsToken( "="):
2357 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2358
2359 if not self.__IsToken( "{"):
2360 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2361
2362 if not self.__GetNextHexNumber():
2363 raise Warning("expected Hex byte", self.FileName, self.CurrentLineNumber)
2364
2365 if len(self.__Token) > 4:
2366 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2367
2368 DataString = self.__Token
2369 DataString += ","
2370
2371 while self.__IsToken(","):
2372 if not self.__GetNextHexNumber():
2373 raise Warning("Invalid Hex number", self.FileName, self.CurrentLineNumber)
2374 if len(self.__Token) > 4:
2375 raise Warning("Hex byte(must be 2 digits) too long", self.FileName, self.CurrentLineNumber)
2376 DataString += self.__Token
2377 DataString += ","
2378
2379 if not self.__IsToken( "}"):
2380 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2381
2382 if not self.__IsToken( "}"):
2383 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2384
2385 DataString = DataString.rstrip(",")
2386 FvObj.FvExtEntryData.append(DataString)
2387
2388 if self.__Token == 'FILE':
2389
2390 if not self.__IsToken( "="):
2391 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2392
2393 if not self.__GetNextToken():
2394 raise Warning("expected FV Extension Entry file path At Line ", self.FileName, self.CurrentLineNumber)
2395
2396 FvObj.FvExtEntryData.append(self.__Token)
2397
2398 if not self.__IsToken( "}"):
2399 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2400
2401 return True
2402
2403 ## __GetAprioriSection() method
2404 #
2405 # Get token statements
2406 #
2407 # @param self The object pointer
2408 # @param FvObj for whom apriori is got
2409 # @param MacroDict dictionary used to replace macro
2410 # @retval True Successfully find apriori statement
2411 # @retval False Not able to find apriori statement
2412 #
2413 def __GetAprioriSection(self, FvObj, MacroDict = {}):
2414
2415 if not self.__IsKeyword( "APRIORI"):
2416 return False
2417
2418 if not self.__IsKeyword("PEI") and not self.__IsKeyword("DXE"):
2419 raise Warning("expected Apriori file type", self.FileName, self.CurrentLineNumber)
2420 AprType = self.__Token
2421
2422 if not self.__IsToken( "{"):
2423 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2424
2425 AprSectionObj = AprioriSection.AprioriSection()
2426 AprSectionObj.AprioriType = AprType
2427
2428 self.__GetDefineStatements(AprSectionObj)
2429 MacroDict.update(AprSectionObj.DefineVarDict)
2430
2431 while True:
2432 IsInf = self.__GetInfStatement(AprSectionObj)
2433 IsFile = self.__GetFileStatement( AprSectionObj)
2434 if not IsInf and not IsFile:
2435 break
2436
2437 if not self.__IsToken( "}"):
2438 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2439
2440 FvObj.AprioriSectionList.append(AprSectionObj)
2441 return True
2442
2443 def __ParseInfStatement(self):
2444 if not self.__IsKeyword("INF"):
2445 return None
2446
2447 ffsInf = FfsInfStatement.FfsInfStatement()
2448 self.__GetInfOptions(ffsInf)
2449
2450 if not self.__GetNextToken():
2451 raise Warning("expected INF file path", self.FileName, self.CurrentLineNumber)
2452 ffsInf.InfFileName = self.__Token
2453 if not ffsInf.InfFileName.endswith('.inf'):
2454 raise Warning("expected .inf file path", self.FileName, self.CurrentLineNumber)
2455
2456 ffsInf.CurrentLineNum = self.CurrentLineNumber
2457 ffsInf.CurrentLineContent = self.__CurrentLine()
2458
2459 #Replace $(SAPCE) with real space
2460 ffsInf.InfFileName = ffsInf.InfFileName.replace('$(SPACE)', ' ')
2461
2462 if ffsInf.InfFileName.replace('$(WORKSPACE)', '').find('$') == -1:
2463 #do case sensitive check for file path
2464 ErrorCode, ErrorInfo = PathClass(NormPath(ffsInf.InfFileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
2465 if ErrorCode != 0:
2466 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
2467
2468 if not ffsInf.InfFileName in self.Profile.InfList:
2469 self.Profile.InfList.append(ffsInf.InfFileName)
2470 FileLineTuple = GetRealFileLine(self.FileName, self.CurrentLineNumber)
2471 self.Profile.InfFileLineList.append(FileLineTuple)
2472 if ffsInf.UseArch:
2473 if ffsInf.UseArch not in self.Profile.InfDict:
2474 self.Profile.InfDict[ffsInf.UseArch] = [ffsInf.InfFileName]
2475 else:
2476 self.Profile.InfDict[ffsInf.UseArch].append(ffsInf.InfFileName)
2477 else:
2478 self.Profile.InfDict['ArchTBD'].append(ffsInf.InfFileName)
2479
2480 if self.__IsToken('|'):
2481 if self.__IsKeyword('RELOCS_STRIPPED'):
2482 ffsInf.KeepReloc = False
2483 elif self.__IsKeyword('RELOCS_RETAINED'):
2484 ffsInf.KeepReloc = True
2485 else:
2486 raise Warning("Unknown reloc strip flag '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2487 return ffsInf
2488
2489 ## __GetInfStatement() method
2490 #
2491 # Get INF statements
2492 #
2493 # @param self The object pointer
2494 # @param Obj for whom inf statement is got
2495 # @retval True Successfully find inf statement
2496 # @retval False Not able to find inf statement
2497 #
2498 def __GetInfStatement(self, Obj, ForCapsule=False):
2499 ffsInf = self.__ParseInfStatement()
2500 if not ffsInf:
2501 return False
2502
2503 if ForCapsule:
2504 capsuleFfs = CapsuleData.CapsuleFfs()
2505 capsuleFfs.Ffs = ffsInf
2506 Obj.CapsuleDataList.append(capsuleFfs)
2507 else:
2508 Obj.FfsList.append(ffsInf)
2509 return True
2510
2511 ## __GetInfOptions() method
2512 #
2513 # Get options for INF
2514 #
2515 # @param self The object pointer
2516 # @param FfsInfObj for whom option is got
2517 #
2518 def __GetInfOptions(self, FfsInfObj):
2519 if self.__IsKeyword("FILE_GUID"):
2520 if not self.__IsToken("="):
2521 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2522 if not self.__GetNextGuid():
2523 raise Warning("expected GUID value", self.FileName, self.CurrentLineNumber)
2524 FfsInfObj.OverrideGuid = self.__Token
2525
2526 if self.__IsKeyword( "RuleOverride"):
2527 if not self.__IsToken( "="):
2528 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2529 if not self.__GetNextToken():
2530 raise Warning("expected Rule name", self.FileName, self.CurrentLineNumber)
2531 FfsInfObj.Rule = self.__Token
2532
2533 if self.__IsKeyword( "VERSION"):
2534 if not self.__IsToken( "="):
2535 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2536 if not self.__GetNextToken():
2537 raise Warning("expected Version", self.FileName, self.CurrentLineNumber)
2538
2539 if self.__GetStringData():
2540 FfsInfObj.Version = self.__Token
2541
2542 if self.__IsKeyword( BINARY_FILE_TYPE_UI):
2543 if not self.__IsToken( "="):
2544 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2545 if not self.__GetNextToken():
2546 raise Warning("expected UI name", self.FileName, self.CurrentLineNumber)
2547
2548 if self.__GetStringData():
2549 FfsInfObj.Ui = self.__Token
2550
2551 if self.__IsKeyword( "USE"):
2552 if not self.__IsToken( "="):
2553 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2554 if not self.__GetNextToken():
2555 raise Warning("expected ARCH name", self.FileName, self.CurrentLineNumber)
2556 FfsInfObj.UseArch = self.__Token
2557
2558
2559 if self.__GetNextToken():
2560 p = re.compile(r'([a-zA-Z0-9\-]+|\$\(TARGET\)|\*)_([a-zA-Z0-9\-]+|\$\(TOOL_CHAIN_TAG\)|\*)_([a-zA-Z0-9\-]+|\$\(ARCH\))')
2561 if p.match(self.__Token) and p.match(self.__Token).span()[1] == len(self.__Token):
2562 FfsInfObj.KeyStringList.append(self.__Token)
2563 if not self.__IsToken(","):
2564 return
2565 else:
2566 self.__UndoToken()
2567 return
2568
2569 while self.__GetNextToken():
2570 if not p.match(self.__Token):
2571 raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
2572 FfsInfObj.KeyStringList.append(self.__Token)
2573
2574 if not self.__IsToken(","):
2575 break
2576
2577 ## __GetFileStatement() method
2578 #
2579 # Get FILE statements
2580 #
2581 # @param self The object pointer
2582 # @param Obj for whom FILE statement is got
2583 # @param MacroDict dictionary used to replace macro
2584 # @retval True Successfully find FILE statement
2585 # @retval False Not able to find FILE statement
2586 #
2587 def __GetFileStatement(self, Obj, ForCapsule = False, MacroDict = {}):
2588
2589 if not self.__IsKeyword( "FILE"):
2590 return False
2591
2592 if not self.__GetNextWord():
2593 raise Warning("expected FFS type", self.FileName, self.CurrentLineNumber)
2594
2595 if ForCapsule and self.__Token == 'DATA':
2596 self.__UndoToken()
2597 self.__UndoToken()
2598 return False
2599
2600 FfsFileObj = FfsFileStatement.FileStatement()
2601 FfsFileObj.FvFileType = self.__Token
2602
2603 if not self.__IsToken( "="):
2604 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2605
2606 if not self.__GetNextGuid():
2607 if not self.__GetNextWord():
2608 raise Warning("expected File GUID", self.FileName, self.CurrentLineNumber)
2609 if self.__Token == 'PCD':
2610 if not self.__IsToken( "("):
2611 raise Warning("expected '('", self.FileName, self.CurrentLineNumber)
2612 PcdPair = self.__GetNextPcdName()
2613 if not self.__IsToken( ")"):
2614 raise Warning("expected ')'", self.FileName, self.CurrentLineNumber)
2615 self.__Token = 'PCD('+PcdPair[1]+'.'+PcdPair[0]+')'
2616
2617 FfsFileObj.NameGuid = self.__Token
2618
2619 self.__GetFilePart( FfsFileObj, MacroDict.copy())
2620
2621 if ForCapsule:
2622 capsuleFfs = CapsuleData.CapsuleFfs()
2623 capsuleFfs.Ffs = FfsFileObj
2624 Obj.CapsuleDataList.append(capsuleFfs)
2625 else:
2626 Obj.FfsList.append(FfsFileObj)
2627
2628 return True
2629
2630 ## __FileCouldHaveRelocFlag() method
2631 #
2632 # Check whether reloc strip flag can be set for a file type.
2633 #
2634 # @param FileType The file type to check with
2635 # @retval True This type could have relocation strip flag
2636 # @retval False No way to have it
2637 #
2638 @staticmethod
2639 def __FileCouldHaveRelocFlag (FileType):
2640 if FileType in (SUP_MODULE_SEC, SUP_MODULE_PEI_CORE, SUP_MODULE_PEIM, 'PEI_DXE_COMBO'):
2641 return True
2642 else:
2643 return False
2644
2645 ## __SectionCouldHaveRelocFlag() method
2646 #
2647 # Check whether reloc strip flag can be set for a section type.
2648 #
2649 # @param SectionType The section type to check with
2650 # @retval True This type could have relocation strip flag
2651 # @retval False No way to have it
2652 #
2653 @staticmethod
2654 def __SectionCouldHaveRelocFlag (SectionType):
2655 if SectionType in (BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32):
2656 return True
2657 else:
2658 return False
2659
2660 ## __GetFilePart() method
2661 #
2662 # Get components for FILE statement
2663 #
2664 # @param self The object pointer
2665 # @param FfsFileObj for whom component is got
2666 # @param MacroDict dictionary used to replace macro
2667 #
2668 def __GetFilePart(self, FfsFileObj, MacroDict = {}):
2669
2670 self.__GetFileOpts( FfsFileObj)
2671
2672 if not self.__IsToken("{"):
2673 if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
2674 if self.__FileCouldHaveRelocFlag(FfsFileObj.FvFileType):
2675 if self.__Token == 'RELOCS_STRIPPED':
2676 FfsFileObj.KeepReloc = False
2677 else:
2678 FfsFileObj.KeepReloc = True
2679 else:
2680 raise Warning("File type %s could not have reloc strip flag%d" % (FfsFileObj.FvFileType, self.CurrentLineNumber), self.FileName, self.CurrentLineNumber)
2681
2682 if not self.__IsToken("{"):
2683 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2684
2685 if not self.__GetNextToken():
2686 raise Warning("expected File name or section data", self.FileName, self.CurrentLineNumber)
2687
2688 if self.__Token == BINARY_FILE_TYPE_FV:
2689 if not self.__IsToken( "="):
2690 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2691 if not self.__GetNextToken():
2692 raise Warning("expected FV name", self.FileName, self.CurrentLineNumber)
2693 FfsFileObj.FvName = self.__Token
2694
2695 elif self.__Token == "FD":
2696 if not self.__IsToken( "="):
2697 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2698 if not self.__GetNextToken():
2699 raise Warning("expected FD name", self.FileName, self.CurrentLineNumber)
2700 FfsFileObj.FdName = self.__Token
2701
2702 elif self.__Token in ("DEFINE", "APRIORI", "SECTION"):
2703 self.__UndoToken()
2704 self.__GetSectionData( FfsFileObj, MacroDict)
2705
2706 elif hasattr(FfsFileObj, 'FvFileType') and FfsFileObj.FvFileType == 'RAW':
2707 self.__UndoToken()
2708 self.__GetRAWData(FfsFileObj, MacroDict)
2709
2710 else:
2711 FfsFileObj.CurrentLineNum = self.CurrentLineNumber
2712 FfsFileObj.CurrentLineContent = self.__CurrentLine()
2713 FfsFileObj.FileName = self.__Token.replace('$(SPACE)', ' ')
2714 self.__VerifyFile(FfsFileObj.FileName)
2715
2716 if not self.__IsToken( "}"):
2717 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2718
2719 ## __GetRAWData() method
2720 #
2721 # Get RAW data for FILE statement
2722 #
2723 # @param self The object pointer
2724 # @param FfsFileObj for whom section is got
2725 # @param MacroDict dictionary used to replace macro
2726 #
2727 def __GetRAWData(self, FfsFileObj, MacroDict = {}):
2728 FfsFileObj.FileName = []
2729 FfsFileObj.SubAlignment = []
2730 while True:
2731 AlignValue = None
2732 if self.__GetAlignment():
2733 if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K", "64K", "128K",
2734 "256K", "512K", "1M", "2M", "4M", "8M", "16M"):
2735 raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2736 #For FFS, Auto is default option same to ""
2737 if not self.__Token == "Auto":
2738 AlignValue = self.__Token
2739 if not self.__GetNextToken():
2740 raise Warning("expected Filename value", self.FileName, self.CurrentLineNumber)
2741
2742 FileName = self.__Token.replace('$(SPACE)', ' ')
2743 if FileName == '}':
2744 self.__UndoToken()
2745 raise Warning("expected Filename value", self.FileName, self.CurrentLineNumber)
2746
2747 self.__VerifyFile(FileName)
2748 File = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir)
2749 FfsFileObj.FileName.append(File.Path)
2750 FfsFileObj.SubAlignment.append(AlignValue)
2751
2752 if self.__IsToken( "}"):
2753 self.__UndoToken()
2754 break
2755
2756 if len(FfsFileObj.SubAlignment) == 1:
2757 FfsFileObj.SubAlignment = FfsFileObj.SubAlignment[0]
2758 if len(FfsFileObj.FileName) == 1:
2759 FfsFileObj.FileName = FfsFileObj.FileName[0]
2760
2761 ## __GetFileOpts() method
2762 #
2763 # Get options for FILE statement
2764 #
2765 # @param self The object pointer
2766 # @param FfsFileObj for whom options is got
2767 #
2768 def __GetFileOpts(self, FfsFileObj):
2769
2770 if self.__GetNextToken():
2771 if TokenFindPattern.match(self.__Token):
2772 FfsFileObj.KeyStringList.append(self.__Token)
2773 if self.__IsToken(","):
2774 while self.__GetNextToken():
2775 if not TokenFindPattern.match(self.__Token):
2776 raise Warning("expected KeyString \"Target_Tag_Arch\"", self.FileName, self.CurrentLineNumber)
2777 FfsFileObj.KeyStringList.append(self.__Token)
2778
2779 if not self.__IsToken(","):
2780 break
2781
2782 else:
2783 self.__UndoToken()
2784
2785 if self.__IsKeyword( "FIXED", True):
2786 FfsFileObj.Fixed = True
2787
2788 if self.__IsKeyword( "CHECKSUM", True):
2789 FfsFileObj.CheckSum = True
2790
2791 if self.__GetAlignment():
2792 if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K", "64K", "128K",
2793 "256K", "512K", "1M", "2M", "4M", "8M", "16M"):
2794 raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2795 #For FFS, Auto is default option same to ""
2796 if not self.__Token == "Auto":
2797 FfsFileObj.Alignment = self.__Token
2798
2799 ## __GetAlignment() method
2800 #
2801 # Return the alignment value
2802 #
2803 # @param self The object pointer
2804 # @retval True Successfully find alignment
2805 # @retval False Not able to find alignment
2806 #
2807 def __GetAlignment(self):
2808 if self.__IsKeyword( "Align", True):
2809 if not self.__IsToken( "="):
2810 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2811
2812 if not self.__GetNextToken():
2813 raise Warning("expected alignment value", self.FileName, self.CurrentLineNumber)
2814 return True
2815
2816 return False
2817
2818 ## __GetFilePart() method
2819 #
2820 # Get section data for FILE statement
2821 #
2822 # @param self The object pointer
2823 # @param FfsFileObj for whom section is got
2824 # @param MacroDict dictionary used to replace macro
2825 #
2826 def __GetSectionData(self, FfsFileObj, MacroDict = {}):
2827 Dict = {}
2828 Dict.update(MacroDict)
2829
2830 self.__GetDefineStatements(FfsFileObj)
2831
2832 Dict.update(FfsFileObj.DefineVarDict)
2833 self.__GetAprioriSection(FfsFileObj, Dict.copy())
2834 self.__GetAprioriSection(FfsFileObj, Dict.copy())
2835
2836 while True:
2837 IsLeafSection = self.__GetLeafSection(FfsFileObj, Dict)
2838 IsEncapSection = self.__GetEncapsulationSec(FfsFileObj)
2839 if not IsLeafSection and not IsEncapSection:
2840 break
2841
2842 ## __GetLeafSection() method
2843 #
2844 # Get leaf section for Obj
2845 #
2846 # @param self The object pointer
2847 # @param Obj for whom leaf section is got
2848 # @param MacroDict dictionary used to replace macro
2849 # @retval True Successfully find section statement
2850 # @retval False Not able to find section statement
2851 #
2852 def __GetLeafSection(self, Obj, MacroDict = {}):
2853
2854 OldPos = self.GetFileBufferPos()
2855
2856 if not self.__IsKeyword( "SECTION"):
2857 if len(Obj.SectionList) == 0:
2858 raise Warning("expected SECTION", self.FileName, self.CurrentLineNumber)
2859 else:
2860 return False
2861
2862 AlignValue = None
2863 if self.__GetAlignment():
2864 if self.__Token not in ("Auto", "8", "16", "32", "64", "128", "512", "1K", "4K", "32K", "64K", "128K",
2865 "256K", "512K", "1M", "2M", "4M", "8M", "16M"):
2866 raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2867 AlignValue = self.__Token
2868
2869 BuildNum = None
2870 if self.__IsKeyword( "BUILD_NUM"):
2871 if not self.__IsToken( "="):
2872 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2873
2874 if not self.__GetNextToken():
2875 raise Warning("expected Build number value", self.FileName, self.CurrentLineNumber)
2876
2877 BuildNum = self.__Token
2878
2879 if self.__IsKeyword( "VERSION"):
2880 if AlignValue == 'Auto':
2881 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2882 if not self.__IsToken( "="):
2883 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2884 if not self.__GetNextToken():
2885 raise Warning("expected version", self.FileName, self.CurrentLineNumber)
2886 VerSectionObj = VerSection.VerSection()
2887 VerSectionObj.Alignment = AlignValue
2888 VerSectionObj.BuildNum = BuildNum
2889 if self.__GetStringData():
2890 VerSectionObj.StringData = self.__Token
2891 else:
2892 VerSectionObj.FileName = self.__Token
2893 Obj.SectionList.append(VerSectionObj)
2894
2895 elif self.__IsKeyword( BINARY_FILE_TYPE_UI):
2896 if AlignValue == 'Auto':
2897 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2898 if not self.__IsToken( "="):
2899 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2900 if not self.__GetNextToken():
2901 raise Warning("expected UI", self.FileName, self.CurrentLineNumber)
2902 UiSectionObj = UiSection.UiSection()
2903 UiSectionObj.Alignment = AlignValue
2904 if self.__GetStringData():
2905 UiSectionObj.StringData = self.__Token
2906 else:
2907 UiSectionObj.FileName = self.__Token
2908 Obj.SectionList.append(UiSectionObj)
2909
2910 elif self.__IsKeyword( "FV_IMAGE"):
2911 if AlignValue == 'Auto':
2912 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2913 if not self.__IsToken( "="):
2914 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2915 if not self.__GetNextToken():
2916 raise Warning("expected FV name or FV file path", self.FileName, self.CurrentLineNumber)
2917
2918 FvName = self.__Token
2919 FvObj = None
2920
2921 if self.__IsToken( "{"):
2922 FvObj = Fv.FV()
2923 FvObj.UiFvName = FvName.upper()
2924 self.__GetDefineStatements(FvObj)
2925 MacroDict.update(FvObj.DefineVarDict)
2926 self.__GetBlockStatement(FvObj)
2927 self.__GetSetStatements(FvObj)
2928 self.__GetFvAlignment(FvObj)
2929 self.__GetFvAttributes(FvObj)
2930 self.__GetAprioriSection(FvObj, MacroDict.copy())
2931 self.__GetAprioriSection(FvObj, MacroDict.copy())
2932
2933 while True:
2934 IsInf = self.__GetInfStatement(FvObj)
2935 IsFile = self.__GetFileStatement(FvObj, MacroDict.copy())
2936 if not IsInf and not IsFile:
2937 break
2938
2939 if not self.__IsToken( "}"):
2940 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
2941
2942 FvImageSectionObj = FvImageSection.FvImageSection()
2943 FvImageSectionObj.Alignment = AlignValue
2944 if FvObj is not None:
2945 FvImageSectionObj.Fv = FvObj
2946 FvImageSectionObj.FvName = None
2947 else:
2948 FvImageSectionObj.FvName = FvName.upper()
2949 FvImageSectionObj.FvFileName = FvName
2950
2951 Obj.SectionList.append(FvImageSectionObj)
2952
2953 elif self.__IsKeyword("PEI_DEPEX_EXP") or self.__IsKeyword("DXE_DEPEX_EXP") or self.__IsKeyword("SMM_DEPEX_EXP"):
2954 if AlignValue == 'Auto':
2955 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2956 DepexSectionObj = DepexSection.DepexSection()
2957 DepexSectionObj.Alignment = AlignValue
2958 DepexSectionObj.DepexType = self.__Token
2959
2960 if not self.__IsToken( "="):
2961 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
2962 if not self.__IsToken( "{"):
2963 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
2964 if not self.__SkipToToken( "}"):
2965 raise Warning("expected Depex expression ending '}'", self.FileName, self.CurrentLineNumber)
2966
2967 DepexSectionObj.Expression = self.__SkippedChars.rstrip('}')
2968 Obj.SectionList.append(DepexSectionObj)
2969
2970 else:
2971 if not self.__GetNextWord():
2972 raise Warning("expected section type", self.FileName, self.CurrentLineNumber)
2973
2974 # Encapsulation section appear, UndoToken and return
2975 if self.__Token == "COMPRESS" or self.__Token == "GUIDED":
2976 self.SetFileBufferPos(OldPos)
2977 return False
2978
2979 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,\
2980 BINARY_FILE_TYPE_UI, "VERSION", BINARY_FILE_TYPE_PEI_DEPEX, "SUBTYPE_GUID", BINARY_FILE_TYPE_SMM_DEPEX):
2981 raise Warning("Unknown section type '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
2982 if AlignValue == 'Auto'and (not self.__Token == BINARY_FILE_TYPE_PE32) and (not self.__Token == BINARY_FILE_TYPE_TE):
2983 raise Warning("Auto alignment can only be used in PE32 or TE section ", self.FileName, self.CurrentLineNumber)
2984
2985 # DataSection
2986 DataSectionObj = DataSection.DataSection()
2987 DataSectionObj.Alignment = AlignValue
2988 DataSectionObj.SecType = self.__Token
2989
2990 if self.__IsKeyword('RELOCS_STRIPPED') or self.__IsKeyword('RELOCS_RETAINED'):
2991 if self.__FileCouldHaveRelocFlag(Obj.FvFileType) and self.__SectionCouldHaveRelocFlag(DataSectionObj.SecType):
2992 if self.__Token == 'RELOCS_STRIPPED':
2993 DataSectionObj.KeepReloc = False
2994 else:
2995 DataSectionObj.KeepReloc = True
2996 else:
2997 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)
2998
2999 if self.__IsToken("="):
3000 if not self.__GetNextToken():
3001 raise Warning("expected section file path", self.FileName, self.CurrentLineNumber)
3002 DataSectionObj.SectFileName = self.__Token
3003 self.__VerifyFile(DataSectionObj.SectFileName)
3004 else:
3005 if not self.__GetCglSection(DataSectionObj):
3006 return False
3007
3008 Obj.SectionList.append(DataSectionObj)
3009
3010 return True
3011
3012 ## __VerifyFile
3013 #
3014 # Check if file exists or not:
3015 # If current phase if GenFds, the file must exist;
3016 # If current phase is AutoGen and the file is not in $(OUTPUT_DIRECTORY), the file must exist
3017 # @param FileName: File path to be verified.
3018 #
3019 def __VerifyFile(self, FileName):
3020 if FileName.replace('$(WORKSPACE)', '').find('$') != -1:
3021 return
3022 if not GlobalData.gAutoGenPhase or not self.__GetMacroValue("OUTPUT_DIRECTORY") in FileName:
3023 ErrorCode, ErrorInfo = PathClass(NormPath(FileName), GenFdsGlobalVariable.WorkSpaceDir).Validate()
3024 if ErrorCode != 0:
3025 EdkLogger.error("GenFds", ErrorCode, ExtraData=ErrorInfo)
3026
3027 ## __GetCglSection() method
3028 #
3029 # Get compressed or GUIDed section for Obj
3030 #
3031 # @param self The object pointer
3032 # @param Obj for whom leaf section is got
3033 # @param AlignValue alignment value for complex section
3034 # @retval True Successfully find section statement
3035 # @retval False Not able to find section statement
3036 #
3037 def __GetCglSection(self, Obj, AlignValue = None):
3038
3039 if self.__IsKeyword( "COMPRESS"):
3040 type = "PI_STD"
3041 if self.__IsKeyword("PI_STD") or self.__IsKeyword("PI_NONE"):
3042 type = self.__Token
3043
3044 if not self.__IsToken("{"):
3045 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
3046
3047 CompressSectionObj = CompressSection.CompressSection()
3048 CompressSectionObj.Alignment = AlignValue
3049 CompressSectionObj.CompType = type
3050 # Recursive sections...
3051 while True:
3052 IsLeafSection = self.__GetLeafSection(CompressSectionObj)
3053 IsEncapSection = self.__GetEncapsulationSec(CompressSectionObj)
3054 if not IsLeafSection and not IsEncapSection:
3055 break
3056
3057
3058 if not self.__IsToken( "}"):
3059 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
3060 Obj.SectionList.append(CompressSectionObj)
3061
3062 # else:
3063 # raise Warning("Compress type not known")
3064
3065 return True
3066
3067 elif self.__IsKeyword( "GUIDED"):
3068 GuidValue = None
3069 if self.__GetNextGuid():
3070 GuidValue = self.__Token
3071
3072 AttribDict = self.__GetGuidAttrib()
3073 if not self.__IsToken("{"):
3074 raise Warning("expected '{'", self.FileName, self.CurrentLineNumber)
3075 GuidSectionObj = GuidSection.GuidSection()
3076 GuidSectionObj.Alignment = AlignValue
3077 GuidSectionObj.NameGuid = GuidValue
3078 GuidSectionObj.SectionType = "GUIDED"
3079 GuidSectionObj.ProcessRequired = AttribDict["PROCESSING_REQUIRED"]
3080 GuidSectionObj.AuthStatusValid = AttribDict["AUTH_STATUS_VALID"]
3081 GuidSectionObj.ExtraHeaderSize = AttribDict["EXTRA_HEADER_SIZE"]
3082 # Recursive sections...
3083 while True:
3084 IsLeafSection = self.__GetLeafSection(GuidSectionObj)
3085 IsEncapSection = self.__GetEncapsulationSec(GuidSectionObj)
3086 if not IsLeafSection and not IsEncapSection:
3087 break
3088
3089 if not self.__IsToken( "}"):
3090 raise Warning("expected '}'", self.FileName, self.CurrentLineNumber)
3091 Obj.SectionList.append(GuidSectionObj)
3092
3093 return True
3094
3095 return False
3096
3097 ## __GetGuidAttri() method
3098 #
3099 # Get attributes for GUID section
3100 #
3101 # @param self The object pointer
3102 # @retval AttribDict Dictionary of key-value pair of section attributes
3103 #
3104 def __GetGuidAttrib(self):
3105
3106 AttribDict = {}
3107 AttribDict["PROCESSING_REQUIRED"] = "NONE"
3108 AttribDict["AUTH_STATUS_VALID"] = "NONE"
3109 AttribDict["EXTRA_HEADER_SIZE"] = -1
3110 while self.__IsKeyword("PROCESSING_REQUIRED") or self.__IsKeyword("AUTH_STATUS_VALID") \
3111 or self.__IsKeyword("EXTRA_HEADER_SIZE"):
3112 AttribKey = self.__Token
3113
3114 if not self.__IsToken("="):
3115 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3116
3117 if not self.__GetNextToken():
3118 raise Warning("expected TRUE(1)/FALSE(0)/Number", self.FileName, self.CurrentLineNumber)
3119 elif AttribKey == "EXTRA_HEADER_SIZE":
3120 Base = 10
3121 if self.__Token[0:2].upper() == "0X":
3122 Base = 16
3123 try:
3124 AttribDict[AttribKey] = int(self.__Token, Base)
3125 continue
3126 except ValueError:
3127 raise Warning("expected Number", self.FileName, self.CurrentLineNumber)
3128 elif self.__Token.upper() not in ("TRUE", "FALSE", "1", "0"):
3129 raise Warning("expected TRUE/FALSE (1/0)", self.FileName, self.CurrentLineNumber)
3130 AttribDict[AttribKey] = self.__Token
3131
3132 return AttribDict
3133
3134 ## __GetEncapsulationSec() method
3135 #
3136 # Get encapsulation section for FILE
3137 #
3138 # @param self The object pointer
3139 # @param FfsFile for whom section is got
3140 # @retval True Successfully find section statement
3141 # @retval False Not able to find section statement
3142 #
3143 def __GetEncapsulationSec(self, FfsFileObj):
3144
3145 OldPos = self.GetFileBufferPos()
3146 if not self.__IsKeyword( "SECTION"):
3147 if len(FfsFileObj.SectionList) == 0:
3148 raise Warning("expected SECTION", self.FileName, self.CurrentLineNumber)
3149 else:
3150 return False
3151
3152 AlignValue = None
3153 if self.__GetAlignment():
3154 if self.__Token not in ("8", "16", "32", "64", "128", "512", "1K", "4K", "32K", "64K", "128K",
3155 "256K", "512K", "1M", "2M", "4M", "8M", "16M"):
3156 raise Warning("Incorrect alignment '%s'" % self.__Token, self.FileName, self.CurrentLineNumber)
3157 AlignValue = self.__Token
3158
3159 if not self.__GetCglSection(FfsFileObj, AlignValue):
3160 self.SetFileBufferPos(OldPos)
3161 return False
3162 else:
3163 return True
3164
3165 def __GetFmp(self):
3166 if not self.__GetNextToken():
3167 return False
3168 S = self.__Token.upper()
3169 if S.startswith("[") and not S.startswith("[FMPPAYLOAD."):
3170 self.SectionParser(S)
3171 self.__UndoToken()
3172 return False
3173
3174 self.__UndoToken()
3175 self.__SkipToToken("[FMPPAYLOAD.", True)
3176 FmpUiName = self.__GetUiName().upper()
3177 if FmpUiName in self.Profile.FmpPayloadDict:
3178 raise Warning("Duplicated FMP UI name found: %s" % FmpUiName, self.FileName, self.CurrentLineNumber)
3179
3180 FmpData = CapsuleData.CapsulePayload()
3181 FmpData.UiName = FmpUiName
3182
3183 if not self.__IsToken( "]"):
3184 raise Warning("expected ']'", self.FileName, self.CurrentLineNumber)
3185
3186 if not self.__GetNextToken():
3187 raise Warning("The FMP payload section is empty!", self.FileName, self.CurrentLineNumber)
3188 FmpKeyList = ['IMAGE_HEADER_INIT_VERSION', 'IMAGE_TYPE_ID', 'IMAGE_INDEX', 'HARDWARE_INSTANCE', 'CERTIFICATE_GUID', 'MONOTONIC_COUNT']
3189 while self.__Token in FmpKeyList:
3190 Name = self.__Token
3191 FmpKeyList.remove(Name)
3192 if not self.__IsToken("="):
3193 raise Warning("expected '='", self.FileName, self.CurrentLineNumber)
3194 if Name == 'IMAGE_TYPE_ID':
3195 if not self.__GetNextGuid():
3196 raise Warning("expected GUID value for IMAGE_TYPE_ID.", self.FileName, self.CurrentLineNumber)
3197 FmpData.ImageTypeId = self.__Token
3198 elif Name == 'CERTIFICATE_GUID':
3199 if not self.__GetNextGuid():
3200 raise Warning("expected GUID value for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)
3201 FmpData.Certificate_Guid = self.__Token
3202 if uuid.UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_RSA2048_SHA256_GUID and uuid.UUID(FmpData.Certificate_Guid) != EFI_CERT_TYPE_PKCS7_GUID:
3203 raise Warning("Only support EFI_CERT_TYPE_RSA2048_SHA256_GUID or EFI_CERT_TYPE_PKCS7_GUID for CERTIFICATE_GUID.", self.FileName, self.CurrentLineNumber)