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