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