]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Ecc/MetaFileWorkspace/MetaFileParser.py
Checking if gSmmCorePrivate->CommunicationBuffer is in supported physical address...
[mirror_edk2.git] / BaseTools / Source / Python / Ecc / MetaFileWorkspace / MetaFileParser.py
1 ## @file
2 # This file is used to parse meta files
3 #
4 # Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
5 # This program and the accompanying materials
6 # are licensed and made available under the terms and conditions of the BSD License
7 # which accompanies this distribution. The full text of the license may be found at
8 # http://opensource.org/licenses/bsd-license.php
9 #
10 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 #
13
14 ##
15 # Import Modules
16 #
17 import Common.LongFilePathOs as os
18 import re
19 import time
20 import copy
21
22 import Common.EdkLogger as EdkLogger
23 import Common.GlobalData as GlobalData
24 import EccGlobalData
25
26 from CommonDataClass.DataClass import *
27 from Common.DataType import *
28 from Common.String import *
29 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData
30 from Common.Expression import *
31 from CommonDataClass.Exceptions import *
32
33 from MetaFileTable import MetaFileStorage
34 from GenFds.FdfParser import FdfParser
35 from Common.LongFilePathSupport import OpenLongFilePath as open
36
37 ## A decorator used to parse macro definition
38 def ParseMacro(Parser):
39 def MacroParser(self):
40 Match = gMacroDefPattern.match(self._CurrentLine)
41 if not Match:
42 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
43 Parser(self)
44 return
45
46 TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)
47 # Syntax check
48 if not TokenList[0]:
49 EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
50 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
51 if len(TokenList) < 2:
52 TokenList.append('')
53
54 Type = Match.group(1)
55 Name, Value = TokenList
56 # Global macros can be only defined via environment variable
57 if Name in GlobalData.gGlobalDefines:
58 EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
59 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
60 # Only upper case letters, digit and '_' are allowed
61 if not gMacroNamePattern.match(Name):
62 EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
63 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
64
65 Value = ReplaceMacro(Value, self._Macros)
66 self._ItemType = MODEL_META_DATA_DEFINE
67 # DEFINE defined macros
68 if Type == TAB_DSC_DEFINES_DEFINE:
69 if type(self) == DecParser:
70 if MODEL_META_DATA_HEADER in self._SectionType:
71 self._FileLocalMacros[Name] = Value
72 else:
73 for Scope in self._Scope:
74 self._SectionsMacroDict.setdefault((Scope[2], Scope[0], Scope[1]), {})[Name] = Value
75 elif self._SectionType == MODEL_META_DATA_HEADER:
76 self._FileLocalMacros[Name] = Value
77 else:
78 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
79 if SectionDictKey not in self._SectionsMacroDict:
80 self._SectionsMacroDict[SectionDictKey] = {}
81 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
82 SectionLocalMacros[Name] = Value
83 # EDK_GLOBAL defined macros
84 elif type(self) != DscParser:
85 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
86 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
87 elif self._SectionType != MODEL_META_DATA_HEADER:
88 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
89 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
90 elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
91 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
92 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
93
94 self._ValueList = [Type, Name, Value]
95
96 return MacroParser
97
98 ## Base class of parser
99 #
100 # This class is used for derivation purpose. The specific parser for one kind
101 # type file must derive this class and implement some public interfaces.
102 #
103 # @param FilePath The path of platform description file
104 # @param FileType The raw data of DSC file
105 # @param Table Database used to retrieve module/package information
106 # @param Macros Macros used for replacement in file
107 # @param Owner Owner ID (for sub-section parsing)
108 # @param From ID from which the data comes (for !INCLUDE directive)
109 #
110 class MetaFileParser(object):
111 # data type (file content) for specific file type
112 DataType = {}
113
114 # Parser objects used to implement singleton
115 MetaFiles = {}
116
117 ## Factory method
118 #
119 # One file, one parser object. This factory method makes sure that there's
120 # only one object constructed for one meta file.
121 #
122 # @param Class class object of real AutoGen class
123 # (InfParser, DecParser or DscParser)
124 # @param FilePath The path of meta file
125 # @param *args The specific class related parameters
126 # @param **kwargs The specific class related dict parameters
127 #
128 def __new__(Class, FilePath, *args, **kwargs):
129 if FilePath in Class.MetaFiles:
130 return Class.MetaFiles[FilePath]
131 else:
132 ParserObject = super(MetaFileParser, Class).__new__(Class)
133 Class.MetaFiles[FilePath] = ParserObject
134 return ParserObject
135
136 ## Constructor of MetaFileParser
137 #
138 # Initialize object of MetaFileParser
139 #
140 # @param FilePath The path of platform description file
141 # @param FileType The raw data of DSC file
142 # @param Table Database used to retrieve module/package information
143 # @param Macros Macros used for replacement in file
144 # @param Owner Owner ID (for sub-section parsing)
145 # @param From ID from which the data comes (for !INCLUDE directive)
146 #
147 def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):
148 self._Table = Table
149 self._RawTable = Table
150 self._FileType = FileType
151 self.MetaFile = FilePath
152 self._Defines = {}
153 self._FileLocalMacros = {}
154 self._SectionsMacroDict = {}
155
156 # for recursive parsing
157 self._Owner = [Owner]
158 self._From = From
159
160 # parsr status for parsing
161 self._ValueList = ['', '', '', '', '']
162 self._Scope = []
163 self._LineIndex = 0
164 self._CurrentLine = ''
165 self._SectionType = MODEL_UNKNOWN
166 self._SectionName = ''
167 self._InSubsection = False
168 self._SubsectionType = MODEL_UNKNOWN
169 self._SubsectionName = ''
170 self._ItemType = MODEL_UNKNOWN
171 self._LastItem = -1
172 self._Enabled = 0
173 self._Finished = False
174 self._PostProcessed = False
175 # Different version of meta-file has different way to parse.
176 self._Version = 0
177
178 ## Store the parsed data in table
179 def _Store(self, *Args):
180 return self._Table.Insert(*Args)
181
182 ## Virtual method for starting parse
183 def Start(self):
184 raise NotImplementedError
185
186 ## Notify a post-process is needed
187 def DoPostProcess(self):
188 self._PostProcessed = False
189
190 ## Set parsing complete flag in both class and table
191 def _Done(self):
192 self._Finished = True
193 ## Do not set end flag when processing included files
194 if self._From == -1:
195 self._Table.SetEndFlag()
196
197 def _PostProcess(self):
198 self._PostProcessed = True
199
200 ## Get the parse complete flag
201 def _GetFinished(self):
202 return self._Finished
203
204 ## Set the complete flag
205 def _SetFinished(self, Value):
206 self._Finished = Value
207
208 ## Use [] style to query data in table, just for readability
209 #
210 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
211 #
212 def __getitem__(self, DataInfo):
213 if type(DataInfo) != type(()):
214 DataInfo = (DataInfo,)
215
216 # Parse the file first, if necessary
217 if not self._Finished:
218 if self._RawTable.IsIntegrity():
219 self._Finished = True
220 else:
221 self._Table = self._RawTable
222 self._PostProcessed = False
223 self.Start()
224
225 # No specific ARCH or Platform given, use raw data
226 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] == None):
227 return self._RawTable.Query(*DataInfo)
228
229 # Do post-process if necessary
230 if not self._PostProcessed:
231 self._PostProcess()
232
233 return self._Table.Query(*DataInfo)
234
235 ## Data parser for the common format in different type of file
236 #
237 # The common format in the meatfile is like
238 #
239 # xxx1 | xxx2 | xxx3
240 #
241 @ParseMacro
242 def _CommonParser(self):
243 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
244 self._ValueList[0:len(TokenList)] = TokenList
245
246 ## Data parser for the format in which there's path
247 #
248 # Only path can have macro used. So we need to replace them before use.
249 #
250 @ParseMacro
251 def _PathParser(self):
252 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
253 self._ValueList[0:len(TokenList)] = TokenList
254 # Don't do macro replacement for dsc file at this point
255 if type(self) != DscParser:
256 Macros = self._Macros
257 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
258
259 ## Skip unsupported data
260 def _Skip(self):
261 EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
262 Line=self._LineIndex+1, ExtraData=self._CurrentLine);
263 self._ValueList[0:1] = [self._CurrentLine]
264
265 ## Section header parser
266 #
267 # The section header is always in following format:
268 #
269 # [section_name.arch<.platform|module_type>]
270 #
271 def _SectionHeaderParser(self):
272 self._Scope = []
273 self._SectionName = ''
274 ArchList = set()
275 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
276 if Item == '':
277 continue
278 ItemList = GetSplitValueList(Item, TAB_SPLIT)
279 # different section should not mix in one section
280 if self._SectionName != '' and self._SectionName != ItemList[0].upper():
281 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
282 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
283 self._SectionName = ItemList[0].upper()
284 if self._SectionName in self.DataType:
285 self._SectionType = self.DataType[self._SectionName]
286 else:
287 self._SectionType = MODEL_UNKNOWN
288 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
289 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
290 # S1 is always Arch
291 if len(ItemList) > 1:
292 S1 = ItemList[1].upper()
293 else:
294 S1 = 'COMMON'
295 ArchList.add(S1)
296 # S2 may be Platform or ModuleType
297 if len(ItemList) > 2:
298 S2 = ItemList[2].upper()
299 else:
300 S2 = 'COMMON'
301 self._Scope.append([S1, S2])
302
303 # 'COMMON' must not be used with specific ARCHs at the same section
304 if 'COMMON' in ArchList and len(ArchList) > 1:
305 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
306 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
307 # If the section information is needed later, it should be stored in database
308 self._ValueList[0] = self._SectionName
309
310 ## [defines] section parser
311 @ParseMacro
312 def _DefineParser(self):
313 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
314 self._ValueList[1:len(TokenList)] = TokenList
315 if not self._ValueList[1]:
316 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
317 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
318 if not self._ValueList[2]:
319 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
320 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
321
322 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
323 Name, Value = self._ValueList[1], self._ValueList[2]
324 # Sometimes, we need to make differences between EDK and EDK2 modules
325 if Name == 'INF_VERSION':
326 try:
327 self._Version = int(Value, 0)
328 except:
329 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
330 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
331
332 if type(self) == InfParser and self._Version < 0x00010005:
333 # EDK module allows using defines as macros
334 self._FileLocalMacros[Name] = Value
335 self._Defines[Name] = Value
336
337 ## [BuildOptions] section parser
338 @ParseMacro
339 def _BuildOptionParser(self):
340 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
341 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
342 if len(TokenList2) == 2:
343 self._ValueList[0] = TokenList2[0] # toolchain family
344 self._ValueList[1] = TokenList2[1] # keys
345 else:
346 self._ValueList[1] = TokenList[0]
347 if len(TokenList) == 2 and type(self) != DscParser: # value
348 self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
349
350 if self._ValueList[1].count('_') != 4:
351 EdkLogger.error(
352 'Parser',
353 FORMAT_INVALID,
354 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
355 ExtraData=self._CurrentLine,
356 File=self.MetaFile,
357 Line=self._LineIndex+1
358 )
359
360 def _GetMacros(self):
361 Macros = {}
362 Macros.update(self._FileLocalMacros)
363 Macros.update(self._GetApplicableSectionMacro())
364 return Macros
365
366
367 ## Get section Macros that are applicable to current line, which may come from other sections
368 ## that share the same name while scope is wider
369 def _GetApplicableSectionMacro(self):
370 Macros = {}
371 for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", self._Scope[0][1]),
372 (self._Scope[0][0], "COMMON"), (self._Scope[0][0], self._Scope[0][1])]:
373 if (self._SectionType, Scope1, Scope2) in self._SectionsMacroDict:
374 Macros.update(self._SectionsMacroDict[(self._SectionType, Scope1, Scope2)])
375 return Macros
376
377 _SectionParser = {}
378 Finished = property(_GetFinished, _SetFinished)
379 _Macros = property(_GetMacros)
380
381
382 ## INF file parser class
383 #
384 # @param FilePath The path of platform description file
385 # @param FileType The raw data of DSC file
386 # @param Table Database used to retrieve module/package information
387 # @param Macros Macros used for replacement in file
388 #
389 class InfParser(MetaFileParser):
390 # INF file supported data types (one type per section)
391 DataType = {
392 TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
393 TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
394 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
395 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
396 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
397 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
398 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
399 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
400 TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
401 TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
402 TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
403 TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
404 TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
405 TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
406 TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
407 TAB_GUIDS.upper() : MODEL_EFI_GUID,
408 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
409 TAB_PPIS.upper() : MODEL_EFI_PPI,
410 TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
411 TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
412 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
413 }
414
415 ## Constructor of InfParser
416 #
417 # Initialize object of InfParser
418 #
419 # @param FilePath The path of module description file
420 # @param FileType The raw data of DSC file
421 # @param Table Database used to retrieve module/package information
422 # @param Macros Macros used for replacement in file
423 #
424 def __init__(self, FilePath, FileType, Table):
425 # prevent re-initialization
426 if hasattr(self, "_Table"):
427 return
428 MetaFileParser.__init__(self, FilePath, FileType, Table)
429 self.TblFile = EccGlobalData.gDb.TblFile
430 self.FileID = -1
431
432 ## Parser starter
433 def Start(self):
434 NmakeLine = ''
435 Content = ''
436 Usage = ''
437 try:
438 Content = open(str(self.MetaFile), 'r').readlines()
439 except:
440 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
441 #
442 # Insert a record for file
443 #
444 Filename = NormPath(self.MetaFile)
445 FileID = self.TblFile.GetFileId(Filename)
446 if FileID:
447 self.FileID = FileID
448 else:
449 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_INF)
450
451 # parse the file line by line
452 IsFindBlockComment = False
453
454 for Index in range(0, len(Content)):
455 if self._SectionType in [MODEL_EFI_GUID,
456 MODEL_EFI_PROTOCOL,
457 MODEL_EFI_PPI,
458 MODEL_PCD_FIXED_AT_BUILD,
459 MODEL_PCD_PATCHABLE_IN_MODULE,
460 MODEL_PCD_FEATURE_FLAG,
461 MODEL_PCD_DYNAMIC_EX,
462 MODEL_PCD_DYNAMIC]:
463 Line = Content[Index].strip()
464 if Line.startswith(TAB_COMMENT_SPLIT):
465 continue
466 elif Line.find(TAB_COMMENT_SPLIT) > 0:
467 Usage = Line[Line.find(TAB_COMMENT_SPLIT):]
468 Line = Line[:Line.find(TAB_COMMENT_SPLIT)]
469 else:
470 Usage = ''
471 else:
472 # skip empty, commented, block commented lines
473 Line = CleanString(Content[Index], AllowCppStyleComment=True)
474 Usage = ''
475 NextLine = ''
476 if Index + 1 < len(Content):
477 NextLine = CleanString(Content[Index + 1])
478 if Line == '':
479 continue
480 if Line.find(DataType.TAB_COMMENT_EDK_START) > -1:
481 IsFindBlockComment = True
482 continue
483 if Line.find(DataType.TAB_COMMENT_EDK_END) > -1:
484 IsFindBlockComment = False
485 continue
486 if IsFindBlockComment:
487 continue
488
489 self._LineIndex = Index
490 self._CurrentLine = Line
491
492 # section header
493 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
494 self._SectionHeaderParser()
495 # Check invalid sections
496 if self._Version < 0x00010005:
497 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
498 MODEL_EFI_LIBRARY_CLASS,
499 MODEL_META_DATA_PACKAGE,
500 MODEL_PCD_FIXED_AT_BUILD,
501 MODEL_PCD_PATCHABLE_IN_MODULE,
502 MODEL_PCD_FEATURE_FLAG,
503 MODEL_PCD_DYNAMIC_EX,
504 MODEL_PCD_DYNAMIC,
505 MODEL_EFI_GUID,
506 MODEL_EFI_PROTOCOL,
507 MODEL_EFI_PPI,
508 MODEL_META_DATA_USER_EXTENSION]:
509 EdkLogger.error('Parser', FORMAT_INVALID,
510 "Section [%s] is not allowed in inf file without version" % (self._SectionName),
511 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
512 elif self._SectionType in [MODEL_EFI_INCLUDE,
513 MODEL_EFI_LIBRARY_INSTANCE,
514 MODEL_META_DATA_NMAKE]:
515 EdkLogger.error('Parser', FORMAT_INVALID,
516 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
517 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
518 continue
519 # merge two lines specified by '\' in section NMAKE
520 elif self._SectionType == MODEL_META_DATA_NMAKE:
521 if Line[-1] == '\\':
522 if NextLine == '':
523 self._CurrentLine = NmakeLine + Line[0:-1]
524 NmakeLine = ''
525 else:
526 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
527 self._CurrentLine = NmakeLine + Line[0:-1]
528 NmakeLine = ''
529 else:
530 NmakeLine = NmakeLine + ' ' + Line[0:-1]
531 continue
532 else:
533 self._CurrentLine = NmakeLine + Line
534 NmakeLine = ''
535
536 # section content
537 self._ValueList = ['','','']
538 # parse current line, result will be put in self._ValueList
539 self._SectionParser[self._SectionType](self)
540 if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
541 self._ItemType = -1
542 continue
543 #
544 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
545 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
546 #
547 self._ValueList[0] = self._ValueList[0].replace('/', '\\')
548 for Arch, Platform in self._Scope:
549 self._Store(self._SectionType,
550 self._ValueList[0],
551 self._ValueList[1],
552 self._ValueList[2],
553 Arch,
554 Platform,
555 self._Owner[-1],
556 self.FileID,
557 self._LineIndex+1,
558 -1,
559 self._LineIndex+1,
560 -1,
561 0,
562 Usage
563 )
564 if IsFindBlockComment:
565 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
566 File=self.MetaFile)
567 self._Done()
568
569 ## Data parser for the format in which there's path
570 #
571 # Only path can have macro used. So we need to replace them before use.
572 #
573 def _IncludeParser(self):
574 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
575 self._ValueList[0:len(TokenList)] = TokenList
576 Macros = self._Macros
577 if Macros:
578 for Index in range(0, len(self._ValueList)):
579 Value = self._ValueList[Index]
580 if not Value:
581 continue
582
583 if Value.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
584 Value = '$(EDK_SOURCE)' + Value[17:]
585 if Value.find('$(EFI_SOURCE)') > -1 or Value.find('$(EDK_SOURCE)') > -1:
586 pass
587 elif Value.startswith('.'):
588 pass
589 elif Value.startswith('$('):
590 pass
591 else:
592 Value = '$(EFI_SOURCE)/' + Value
593
594 self._ValueList[Index] = ReplaceMacro(Value, Macros)
595
596 ## Parse [Sources] section
597 #
598 # Only path can have macro used. So we need to replace them before use.
599 #
600 @ParseMacro
601 def _SourceFileParser(self):
602 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
603 self._ValueList[0:len(TokenList)] = TokenList
604 Macros = self._Macros
605 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
606 if 'COMPONENT_TYPE' in Macros:
607 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
608 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
609 if self._Defines['BASE_NAME'] == 'Microcode':
610 pass
611 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
612
613 ## Parse [Binaries] section
614 #
615 # Only path can have macro used. So we need to replace them before use.
616 #
617 @ParseMacro
618 def _BinaryFileParser(self):
619 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
620 if len(TokenList) < 2:
621 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
622 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
623 File=self.MetaFile, Line=self._LineIndex+1)
624 if not TokenList[0]:
625 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
626 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
627 File=self.MetaFile, Line=self._LineIndex+1)
628 if not TokenList[1]:
629 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
630 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
631 File=self.MetaFile, Line=self._LineIndex+1)
632 self._ValueList[0:len(TokenList)] = TokenList
633 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
634
635 ## [nmake] section parser (Edk.x style only)
636 def _NmakeParser(self):
637 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
638 self._ValueList[0:len(TokenList)] = TokenList
639 # remove macros
640 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
641 # remove self-reference in macro setting
642 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
643
644 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
645 @ParseMacro
646 def _PcdParser(self):
647 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
648 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
649 if len(ValueList) != 2:
650 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
651 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
652 File=self.MetaFile, Line=self._LineIndex+1)
653 self._ValueList[0:1] = ValueList
654 if len(TokenList) > 1:
655 self._ValueList[2] = TokenList[1]
656 if self._ValueList[0] == '' or self._ValueList[1] == '':
657 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
658 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
659 File=self.MetaFile, Line=self._LineIndex+1)
660
661 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
662 if self._ValueList[2] != '':
663 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
664 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
665 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1);
666 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
667 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1);
668
669 ## [depex] section parser
670 @ParseMacro
671 def _DepexParser(self):
672 self._ValueList[0:1] = [self._CurrentLine]
673
674 _SectionParser = {
675 MODEL_UNKNOWN : MetaFileParser._Skip,
676 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
677 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
678 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules
679 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules
680 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
681 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
682 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules
683 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
684 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
685 MODEL_PCD_FEATURE_FLAG : _PcdParser,
686 MODEL_PCD_DYNAMIC_EX : _PcdParser,
687 MODEL_PCD_DYNAMIC : _PcdParser,
688 MODEL_EFI_SOURCE_FILE : _SourceFileParser,
689 MODEL_EFI_GUID : MetaFileParser._CommonParser,
690 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
691 MODEL_EFI_PPI : MetaFileParser._CommonParser,
692 MODEL_EFI_DEPEX : _DepexParser,
693 MODEL_EFI_BINARY_FILE : _BinaryFileParser,
694 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
695 }
696
697 ## DSC file parser class
698 #
699 # @param FilePath The path of platform description file
700 # @param FileType The raw data of DSC file
701 # @param Table Database used to retrieve module/package information
702 # @param Macros Macros used for replacement in file
703 # @param Owner Owner ID (for sub-section parsing)
704 # @param From ID from which the data comes (for !INCLUDE directive)
705 #
706 class DscParser(MetaFileParser):
707 # DSC file supported data types (one type per section)
708 DataType = {
709 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
710 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
711 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
712 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
713 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
714 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
715 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
716 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
717 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
718 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
719 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
720 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
721 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
722 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
723 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH,
724 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,
725 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
726 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,
727 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,
728 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
729 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
730 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
731 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
732 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
733 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
734 }
735
736 # Valid names in define section
737 DefineKeywords = [
738 "DSC_SPECIFICATION",
739 "PLATFORM_NAME",
740 "PLATFORM_GUID",
741 "PLATFORM_VERSION",
742 "SKUID_IDENTIFIER",
743 "PCD_INFO_GENERATION",
744 "SUPPORTED_ARCHITECTURES",
745 "BUILD_TARGETS",
746 "OUTPUT_DIRECTORY",
747 "FLASH_DEFINITION",
748 "BUILD_NUMBER",
749 "RFC_LANGUAGES",
750 "ISO_LANGUAGES",
751 "TIME_STAMP_FILE",
752 "VPD_TOOL_GUID",
753 "FIX_LOAD_TOP_MEMORY_ADDRESS"
754 ]
755
756 SymbolPattern = ValueExpression.SymbolPattern
757
758 ## Constructor of DscParser
759 #
760 # Initialize object of DscParser
761 #
762 # @param FilePath The path of platform description file
763 # @param FileType The raw data of DSC file
764 # @param Table Database used to retrieve module/package information
765 # @param Macros Macros used for replacement in file
766 # @param Owner Owner ID (for sub-section parsing)
767 # @param From ID from which the data comes (for !INCLUDE directive)
768 #
769 def __init__(self, FilePath, FileType, Table, Owner=-1, From=-1):
770 # prevent re-initialization
771 if hasattr(self, "_Table"):
772 return
773 MetaFileParser.__init__(self, FilePath, FileType, Table, Owner, From)
774 self._Version = 0x00010005 # Only EDK2 dsc file is supported
775 # to store conditional directive evaluation result
776 self._DirectiveStack = []
777 self._DirectiveEvalStack = []
778 self._Enabled = 1
779
780 # Final valid replacable symbols
781 self._Symbols = {}
782 #
783 # Map the ID between the original table and new table to track
784 # the owner item
785 #
786 self._IdMapping = {-1:-1}
787
788 self.TblFile = EccGlobalData.gDb.TblFile
789 self.FileID = -1
790
791 ## Parser starter
792 def Start(self):
793 Content = ''
794 try:
795 Content = open(str(self.MetaFile.Path), 'r').readlines()
796 except:
797 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
798 #
799 # Insert a record for file
800 #
801 Filename = NormPath(self.MetaFile.Path)
802 FileID = self.TblFile.GetFileId(Filename)
803 if FileID:
804 self.FileID = FileID
805 else:
806 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DSC)
807
808
809 for Index in range(0, len(Content)):
810 Line = CleanString(Content[Index])
811 # skip empty line
812 if Line == '':
813 continue
814
815 self._CurrentLine = Line
816 self._LineIndex = Index
817 if self._InSubsection and self._Owner[-1] == -1:
818 self._Owner.append(self._LastItem)
819
820 # section header
821 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
822 self._SectionType = MODEL_META_DATA_SECTION_HEADER
823 # subsection ending
824 elif Line[0] == '}' and self._InSubsection:
825 self._InSubsection = False
826 self._SubsectionType = MODEL_UNKNOWN
827 self._SubsectionName = ''
828 self._Owner[-1] = -1
829 continue
830 # subsection header
831 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
832 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
833 # directive line
834 elif Line[0] == '!':
835 self._DirectiveParser()
836 continue
837
838 if self._InSubsection:
839 SectionType = self._SubsectionType
840 else:
841 SectionType = self._SectionType
842 self._ItemType = SectionType
843
844 self._ValueList = ['', '', '']
845 self._SectionParser[SectionType](self)
846 if self._ValueList == None:
847 continue
848 #
849 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
850 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
851 #
852 for Arch, ModuleType in self._Scope:
853 self._LastItem = self._Store(
854 self._ItemType,
855 self._ValueList[0],
856 self._ValueList[1],
857 self._ValueList[2],
858 Arch,
859 ModuleType,
860 self._Owner[-1],
861 self.FileID,
862 self._From,
863 self._LineIndex+1,
864 -1,
865 self._LineIndex+1,
866 -1,
867 self._Enabled
868 )
869
870 if self._DirectiveStack:
871 Type, Line, Text = self._DirectiveStack[-1]
872 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
873 ExtraData=Text, File=self.MetaFile, Line=Line)
874 self._Done()
875
876 ## <subsection_header> parser
877 def _SubsectionHeaderParser(self):
878 self._SubsectionName = self._CurrentLine[1:-1].upper()
879 if self._SubsectionName in self.DataType:
880 self._SubsectionType = self.DataType[self._SubsectionName]
881 else:
882 self._SubsectionType = MODEL_UNKNOWN
883 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
884 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
885 self._ValueList[0] = self._SubsectionName
886
887 ## Directive statement parser
888 def _DirectiveParser(self):
889 self._ValueList = ['','','']
890 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
891 self._ValueList[0:len(TokenList)] = TokenList
892
893 # Syntax check
894 DirectiveName = self._ValueList[0].upper()
895 if DirectiveName not in self.DataType:
896 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
897 File=self.MetaFile, Line=self._LineIndex+1)
898 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
899 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
900 File=self.MetaFile, Line=self._LineIndex+1,
901 ExtraData=self._CurrentLine)
902
903 ItemType = self.DataType[DirectiveName]
904 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
905 # Remove all directives between !if and !endif, including themselves
906 while self._DirectiveStack:
907 # Remove any !else or !elseif
908 DirectiveInfo = self._DirectiveStack.pop()
909 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
910 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
911 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
912 break
913 else:
914 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
915 File=self.MetaFile, Line=self._LineIndex+1,
916 ExtraData=self._CurrentLine)
917 elif ItemType != MODEL_META_DATA_INCLUDE:
918 # Break if there's a !else is followed by a !elseif
919 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
920 self._DirectiveStack and \
921 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
922 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
923 File=self.MetaFile, Line=self._LineIndex+1,
924 ExtraData=self._CurrentLine)
925 self._DirectiveStack.append((ItemType, self._LineIndex+1, self._CurrentLine))
926 elif self._From > 0:
927 EdkLogger.error('Parser', FORMAT_INVALID,
928 "No '!include' allowed in included file",
929 ExtraData=self._CurrentLine, File=self.MetaFile,
930 Line=self._LineIndex+1)
931
932 #
933 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
934 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
935 #
936 self._LastItem = self._Store(
937 ItemType,
938 self._ValueList[0],
939 self._ValueList[1],
940 self._ValueList[2],
941 'COMMON',
942 'COMMON',
943 self._Owner[-1],
944 self.FileID,
945 self._From,
946 self._LineIndex+1,
947 -1,
948 self._LineIndex+1,
949 -1,
950 0
951 )
952
953 ## [defines] section parser
954 @ParseMacro
955 def _DefineParser(self):
956 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
957 self._ValueList[1:len(TokenList)] = TokenList
958
959 # Syntax check
960 if not self._ValueList[1]:
961 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
962 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
963 if not self._ValueList[2]:
964 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
965 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
966 if not self._ValueList[1] in self.DefineKeywords:
967 EdkLogger.error('Parser', FORMAT_INVALID,
968 "Unknown keyword found: %s. "
969 "If this is a macro you must "
970 "add it as a DEFINE in the DSC" % self._ValueList[1],
971 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
972 self._Defines[self._ValueList[1]] = self._ValueList[2]
973 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
974
975 @ParseMacro
976 def _SkuIdParser(self):
977 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
978 if len(TokenList) != 2:
979 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Integer>|<UiName>'",
980 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex+1)
981 self._ValueList[0:len(TokenList)] = TokenList
982
983 ## Parse Edk style of library modules
984 def _LibraryInstanceParser(self):
985 self._ValueList[0] = self._CurrentLine
986
987 ## PCD sections parser
988 #
989 # [PcdsFixedAtBuild]
990 # [PcdsPatchableInModule]
991 # [PcdsFeatureFlag]
992 # [PcdsDynamicEx
993 # [PcdsDynamicExDefault]
994 # [PcdsDynamicExVpd]
995 # [PcdsDynamicExHii]
996 # [PcdsDynamic]
997 # [PcdsDynamicDefault]
998 # [PcdsDynamicVpd]
999 # [PcdsDynamicHii]
1000 #
1001 @ParseMacro
1002 def _PcdParser(self):
1003 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1004 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1005 if len(TokenList) == 2:
1006 self._ValueList[2] = TokenList[1]
1007 if self._ValueList[0] == '' or self._ValueList[1] == '':
1008 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1009 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1010 File=self.MetaFile, Line=self._LineIndex+1)
1011 if self._ValueList[2] == '':
1012 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
1013 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1014 File=self.MetaFile, Line=self._LineIndex+1)
1015 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1016 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1017 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
1018 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
1019 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
1020 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
1021
1022 ## [components] section parser
1023 @ParseMacro
1024 def _ComponentParser(self):
1025 if self._CurrentLine[-1] == '{':
1026 self._ValueList[0] = self._CurrentLine[0:-1].strip()
1027 self._InSubsection = True
1028 else:
1029 self._ValueList[0] = self._CurrentLine
1030
1031 ## [LibraryClasses] section
1032 @ParseMacro
1033 def _LibraryClassParser(self):
1034 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1035 if len(TokenList) < 2:
1036 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
1037 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1038 File=self.MetaFile, Line=self._LineIndex+1)
1039 if TokenList[0] == '':
1040 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
1041 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1042 File=self.MetaFile, Line=self._LineIndex+1)
1043 if TokenList[1] == '':
1044 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
1045 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1046 File=self.MetaFile, Line=self._LineIndex+1)
1047
1048 self._ValueList[0:len(TokenList)] = TokenList
1049
1050 def _CompponentSourceOverridePathParser(self):
1051 self._ValueList[0] = self._CurrentLine
1052
1053 ## [BuildOptions] section parser
1054 @ParseMacro
1055 def _BuildOptionParser(self):
1056 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1057 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
1058 if len(TokenList2) == 2:
1059 self._ValueList[0] = TokenList2[0] # toolchain family
1060 self._ValueList[1] = TokenList2[1] # keys
1061 else:
1062 self._ValueList[1] = TokenList[0]
1063 if len(TokenList) == 2: # value
1064 self._ValueList[2] = TokenList[1]
1065
1066 if self._ValueList[1].count('_') != 4:
1067 EdkLogger.error(
1068 'Parser',
1069 FORMAT_INVALID,
1070 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
1071 ExtraData=self._CurrentLine,
1072 File=self.MetaFile,
1073 Line=self._LineIndex+1
1074 )
1075
1076 ## Override parent's method since we'll do all macro replacements in parser
1077 def _GetMacros(self):
1078 Macros = dict( [('ARCH','IA32'), ('FAMILY','MSFT'),('TOOL_CHAIN_TAG','VS2008x86'),('TARGET','DEBUG')])
1079 Macros.update(self._FileLocalMacros)
1080 Macros.update(self._GetApplicableSectionMacro())
1081 Macros.update(GlobalData.gEdkGlobal)
1082 Macros.update(GlobalData.gPlatformDefines)
1083 Macros.update(GlobalData.gCommandLineDefines)
1084 # PCD cannot be referenced in macro definition
1085 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
1086 Macros.update(self._Symbols)
1087 return Macros
1088
1089 def _PostProcess(self):
1090 Processer = {
1091 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,
1092 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,
1093 MODEL_META_DATA_HEADER : self.__ProcessDefine,
1094 MODEL_META_DATA_DEFINE : self.__ProcessDefine,
1095 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,
1096 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,
1097 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,
1098 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,
1099 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,
1100 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,
1101 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,
1102 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,
1103 MODEL_EFI_SKU_ID : self.__ProcessSkuId,
1104 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,
1105 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,
1106 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,
1107 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,
1108 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,
1109 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,
1110 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,
1111 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,
1112 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,
1113 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,
1114 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,
1115 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,
1116 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : self.__ProcessSourceOverridePath,
1117 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,
1118 MODEL_UNKNOWN : self._Skip,
1119 MODEL_META_DATA_USER_EXTENSION : self._Skip,
1120 }
1121
1122 self._RawTable = self._Table
1123 self._Table = MetaFileStorage(self._RawTable.Cur, self.MetaFile, MODEL_FILE_DSC, True)
1124 self._DirectiveStack = []
1125 self._DirectiveEvalStack = []
1126 self._FileWithError = self.MetaFile
1127 self._FileLocalMacros = {}
1128 self._SectionsMacroDict = {}
1129 GlobalData.gPlatformDefines = {}
1130
1131 # Get all macro and PCD which has straitforward value
1132 self.__RetrievePcdValue()
1133 self._Content = self._RawTable.GetAll()
1134 self._ContentIndex = 0
1135 while self._ContentIndex < len(self._Content) :
1136 Id, self._ItemType, V1, V2, V3, S1, S2, Owner, BelongsToFile, self._From, \
1137 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
1138
1139 if self._From < 0:
1140 self._FileWithError = self.MetaFile
1141
1142 self._ContentIndex += 1
1143
1144 self._Scope = [[S1, S2]]
1145 self._LineIndex = LineStart - 1
1146 self._ValueList = [V1, V2, V3]
1147
1148 try:
1149 Processer[self._ItemType]()
1150 except EvaluationException, Excpt:
1151 #
1152 # Only catch expression evaluation error here. We need to report
1153 # the precise number of line on which the error occurred
1154 #
1155 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1156 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1157 Line=self._LineIndex+1)
1158 except MacroException, Excpt:
1159 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
1160 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1161 Line=self._LineIndex+1)
1162
1163 if self._ValueList == None:
1164 continue
1165
1166 NewOwner = self._IdMapping.get(Owner, -1)
1167 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
1168 self._LastItem = self._Store(
1169 self._ItemType,
1170 self._ValueList[0],
1171 self._ValueList[1],
1172 self._ValueList[2],
1173 S1,
1174 S2,
1175 NewOwner,
1176 BelongsToFile,
1177 self._From,
1178 self._LineIndex+1,
1179 -1,
1180 self._LineIndex+1,
1181 -1,
1182 self._Enabled
1183 )
1184 self._IdMapping[Id] = self._LastItem
1185
1186 RecordList = self._Table.GetAll()
1187
1188 self._RawTable.Drop()
1189 self._Table.Drop()
1190 for Record in RecordList:
1191 EccGlobalData.gDb.TblDsc.Insert(Record[1],Record[2],Record[3],Record[4],Record[5],Record[6],Record[7],Record[8],Record[9],Record[10],Record[11],Record[12],Record[13],Record[14])
1192 GlobalData.gPlatformDefines.update(self._FileLocalMacros)
1193 self._PostProcessed = True
1194 self._Content = None
1195
1196 def __ProcessSectionHeader(self):
1197 self._SectionName = self._ValueList[0]
1198 if self._SectionName in self.DataType:
1199 self._SectionType = self.DataType[self._SectionName]
1200 else:
1201 self._SectionType = MODEL_UNKNOWN
1202
1203 def __ProcessSubsectionHeader(self):
1204 self._SubsectionName = self._ValueList[0]
1205 if self._SubsectionName in self.DataType:
1206 self._SubsectionType = self.DataType[self._SubsectionName]
1207 else:
1208 self._SubsectionType = MODEL_UNKNOWN
1209
1210 def __RetrievePcdValue(self):
1211 Records = self._RawTable.Query(MODEL_PCD_FEATURE_FLAG, BelongsToItem=-1.0)
1212 for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:
1213 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
1214 # Only use PCD whose value is straitforward (no macro and PCD)
1215 if self.SymbolPattern.findall(Value):
1216 continue
1217 Name = TokenSpaceGuid + '.' + PcdName
1218 # Don't use PCD with different values.
1219 if Name in self._Symbols and self._Symbols[Name] != Value:
1220 self._Symbols.pop(Name)
1221 continue
1222 self._Symbols[Name] = Value
1223
1224 Records = self._RawTable.Query(MODEL_PCD_FIXED_AT_BUILD, BelongsToItem=-1.0)
1225 for TokenSpaceGuid,PcdName,Value,Dummy2,Dummy3,ID,Line in Records:
1226 Value, DatumType, MaxDatumSize = AnalyzePcdData(Value)
1227 # Only use PCD whose value is straitforward (no macro and PCD)
1228 if self.SymbolPattern.findall(Value):
1229 continue
1230 Name = TokenSpaceGuid+'.'+PcdName
1231 # Don't use PCD with different values.
1232 if Name in self._Symbols and self._Symbols[Name] != Value:
1233 self._Symbols.pop(Name)
1234 continue
1235 self._Symbols[Name] = Value
1236
1237 def __ProcessDefine(self):
1238 if not self._Enabled:
1239 return
1240
1241 Type, Name, Value = self._ValueList
1242 Value = ReplaceMacro(Value, self._Macros, False)
1243 if self._ItemType == MODEL_META_DATA_DEFINE:
1244 if self._SectionType == MODEL_META_DATA_HEADER:
1245 self._FileLocalMacros[Name] = Value
1246 else:
1247 SectionDictKey = self._SectionType, self._Scope[0][0], self._Scope[0][1]
1248 if SectionDictKey not in self._SectionsMacroDict:
1249 self._SectionsMacroDict[SectionDictKey] = {}
1250 SectionLocalMacros = self._SectionsMacroDict[SectionDictKey]
1251 SectionLocalMacros[Name] = Value
1252 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
1253 GlobalData.gEdkGlobal[Name] = Value
1254
1255 #
1256 # Keyword in [Defines] section can be used as Macros
1257 #
1258 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
1259 self._FileLocalMacros[Name] = Value
1260
1261 self._ValueList = [Type, Name, Value]
1262
1263 def __ProcessDirective(self):
1264 Result = None
1265 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1266 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
1267 Macros = self._Macros
1268 Macros.update(GlobalData.gGlobalDefines)
1269 try:
1270 Result = ValueExpression(self._ValueList[1], Macros)()
1271 except SymbolNotFound, Exc:
1272 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1273 Result = False
1274 except WrnExpression, Excpt:
1275 #
1276 # Catch expression evaluation warning here. We need to report
1277 # the precise number of line and return the evaluation result
1278 #
1279 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
1280 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1281 Line=self._LineIndex+1)
1282 Result = Excpt.result
1283
1284 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1285 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1286 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1287 self._DirectiveStack.append(self._ItemType)
1288 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
1289 Result = bool(Result)
1290 else:
1291 Macro = self._ValueList[1]
1292 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
1293 Result = Macro in self._Macros
1294 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
1295 Result = not Result
1296 self._DirectiveEvalStack.append(Result)
1297 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
1298 self._DirectiveStack.append(self._ItemType)
1299 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1300 self._DirectiveEvalStack.append(bool(Result))
1301 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1302 self._DirectiveStack[-1] = self._ItemType
1303 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1304 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1305 # Back to the nearest !if/!ifdef/!ifndef
1306 while self._DirectiveStack:
1307 self._DirectiveEvalStack.pop()
1308 Directive = self._DirectiveStack.pop()
1309 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1310 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1311 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
1312 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1313 break
1314 elif self._ItemType == MODEL_META_DATA_INCLUDE:
1315 # The included file must be relative to workspace or same directory as DSC file
1316 __IncludeMacros = {}
1317 #
1318 # Allow using system environment variables in path after !include
1319 #
1320 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
1321 if "ECP_SOURCE" in GlobalData.gGlobalDefines.keys():
1322 __IncludeMacros['ECP_SOURCE'] = GlobalData.gGlobalDefines['ECP_SOURCE']
1323 #
1324 # During GenFds phase call DSC parser, will go into this branch.
1325 #
1326 elif "ECP_SOURCE" in GlobalData.gCommandLineDefines.keys():
1327 __IncludeMacros['ECP_SOURCE'] = GlobalData.gCommandLineDefines['ECP_SOURCE']
1328
1329 __IncludeMacros['EFI_SOURCE'] = GlobalData.gGlobalDefines['EFI_SOURCE']
1330 __IncludeMacros['EDK_SOURCE'] = GlobalData.gGlobalDefines['EDK_SOURCE']
1331 #
1332 # Allow using MACROs comes from [Defines] section to keep compatible.
1333 #
1334 __IncludeMacros.update(self._Macros)
1335
1336 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
1337 #
1338 # First search the include file under the same directory as DSC file
1339 #
1340 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
1341 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
1342 if ErrorCode != 0:
1343 #
1344 # Also search file under the WORKSPACE directory
1345 #
1346 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
1347 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
1348 if ErrorCode != 0:
1349 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
1350 Line=self._LineIndex+1, ExtraData=ErrorInfo1 + "\n"+ ErrorInfo2)
1351
1352 self._FileWithError = IncludedFile1
1353
1354 IncludedFileTable = MetaFileStorage(self._Table.Cur, IncludedFile1, MODEL_FILE_DSC, True)
1355 Owner = self._Content[self._ContentIndex-1][0]
1356 Parser = DscParser(IncludedFile1, self._FileType, IncludedFileTable,
1357 Owner=Owner, From=Owner)
1358
1359 # set the parser status with current status
1360 Parser._SectionName = self._SectionName
1361 Parser._SectionType = self._SectionType
1362 Parser._Scope = self._Scope
1363 Parser._Enabled = self._Enabled
1364 # Parse the included file
1365 Parser.Start()
1366
1367 # update current status with sub-parser's status
1368 self._SectionName = Parser._SectionName
1369 self._SectionType = Parser._SectionType
1370 self._Scope = Parser._Scope
1371 self._Enabled = Parser._Enabled
1372
1373 # Insert all records in the table for the included file into dsc file table
1374 Records = IncludedFileTable.GetAll()
1375 if Records:
1376 self._Content[self._ContentIndex:self._ContentIndex] = Records
1377 self._Content.pop(self._ContentIndex-1)
1378 self._ValueList = None
1379 self._ContentIndex -= 1
1380
1381 def __ProcessSkuId(self):
1382 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1383 for Value in self._ValueList]
1384
1385 def __ProcessLibraryInstance(self):
1386 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
1387
1388 def __ProcessLibraryClass(self):
1389 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
1390
1391 def __ProcessPcd(self):
1392 ValueList = GetSplitValueList(self._ValueList[2])
1393 #
1394 # PCD value can be an expression
1395 #
1396 if len(ValueList) > 1 and ValueList[1] == 'VOID*':
1397 PcdValue = ValueList[0]
1398 try:
1399 ValueList[0] = ValueExpression(PcdValue, self._Macros)(True)
1400 except WrnExpression, Value:
1401 ValueList[0] = Value.result
1402 else:
1403 PcdValue = ValueList[-1]
1404 try:
1405 ValueList[-1] = ValueExpression(PcdValue, self._Macros)(True)
1406 except WrnExpression, Value:
1407 ValueList[-1] = Value.result
1408
1409 if ValueList[-1] == 'True':
1410 ValueList[-1] = '1'
1411 if ValueList[-1] == 'False':
1412 ValueList[-1] = '0'
1413
1414 self._ValueList[2] = '|'.join(ValueList)
1415
1416 def __ProcessComponent(self):
1417 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1418
1419 def __ProcessSourceOverridePath(self):
1420 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1421
1422 def __ProcessBuildOption(self):
1423 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
1424 for Value in self._ValueList]
1425
1426 _SectionParser = {
1427 MODEL_META_DATA_HEADER : _DefineParser,
1428 MODEL_EFI_SKU_ID : _SkuIdParser,
1429 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
1430 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
1431 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1432 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1433 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1434 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
1435 MODEL_PCD_DYNAMIC_HII : _PcdParser,
1436 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
1437 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
1438 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
1439 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
1440 MODEL_META_DATA_COMPONENT : _ComponentParser,
1441 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH : _CompponentSourceOverridePathParser,
1442 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1443 MODEL_UNKNOWN : MetaFileParser._Skip,
1444 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1445 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1446 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1447 }
1448
1449 _Macros = property(_GetMacros)
1450
1451 ## DEC file parser class
1452 #
1453 # @param FilePath The path of platform description file
1454 # @param FileType The raw data of DSC file
1455 # @param Table Database used to retrieve module/package information
1456 # @param Macros Macros used for replacement in file
1457 #
1458 class DecParser(MetaFileParser):
1459 # DEC file supported data types (one type per section)
1460 DataType = {
1461 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1462 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1463 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1464 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1465 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1466 TAB_PPIS.upper() : MODEL_EFI_PPI,
1467 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1468 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1469 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1470 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1471 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1472 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1473 }
1474
1475 ## Constructor of DecParser
1476 #
1477 # Initialize object of DecParser
1478 #
1479 # @param FilePath The path of platform description file
1480 # @param FileType The raw data of DSC file
1481 # @param Table Database used to retrieve module/package information
1482 # @param Macros Macros used for replacement in file
1483 #
1484 def __init__(self, FilePath, FileType, Table):
1485 # prevent re-initialization
1486 if hasattr(self, "_Table"):
1487 return
1488 MetaFileParser.__init__(self, FilePath, FileType, Table)
1489 self._Comments = []
1490 self._Version = 0x00010005 # Only EDK2 dec file is supported
1491 self.TblFile = EccGlobalData.gDb.TblFile
1492 self.FileID = -1
1493
1494 ## Parser starter
1495 def Start(self):
1496 Content = ''
1497 try:
1498 Content = open(str(self.MetaFile), 'r').readlines()
1499 except:
1500 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1501
1502 #
1503 # Insert a record for file
1504 #
1505 Filename = NormPath(self.MetaFile)
1506 FileID = self.TblFile.GetFileId(Filename)
1507 if FileID:
1508 self.FileID = FileID
1509 else:
1510 self.FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_DEC)
1511
1512 for Index in range(0, len(Content)):
1513 Line, Comment = CleanString2(Content[Index])
1514 self._CurrentLine = Line
1515 self._LineIndex = Index
1516
1517 # save comment for later use
1518 if Comment:
1519 self._Comments.append((Comment, self._LineIndex+1))
1520 # skip empty line
1521 if Line == '':
1522 continue
1523
1524 # section header
1525 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
1526 self._SectionHeaderParser()
1527 self._Comments = []
1528 continue
1529 elif len(self._SectionType) == 0:
1530 self._Comments = []
1531 continue
1532
1533 # section content
1534 self._ValueList = ['','','']
1535 self._SectionParser[self._SectionType[0]](self)
1536 if self._ValueList == None or self._ItemType == MODEL_META_DATA_DEFINE:
1537 self._ItemType = -1
1538 self._Comments = []
1539 continue
1540
1541 #
1542 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1543 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1544 #
1545 for Arch, ModuleType, Type in self._Scope:
1546 self._LastItem = self._Store(
1547 Type,
1548 self._ValueList[0],
1549 self._ValueList[1],
1550 self._ValueList[2],
1551 Arch,
1552 ModuleType,
1553 self._Owner[-1],
1554 self.FileID,
1555 self._LineIndex+1,
1556 -1,
1557 self._LineIndex+1,
1558 -1,
1559 0
1560 )
1561 for Comment, LineNo in self._Comments:
1562 self._Store(
1563 MODEL_META_DATA_COMMENT,
1564 Comment,
1565 self._ValueList[0],
1566 self._ValueList[1],
1567 Arch,
1568 ModuleType,
1569 self._LastItem,
1570 self.FileID,
1571 LineNo,
1572 -1,
1573 LineNo,
1574 -1,
1575 0
1576 )
1577 self._Comments = []
1578 self._Done()
1579
1580 def _GetApplicableSectionMacro(self):
1581 Macros = {}
1582 for S1, S2, SectionType in self._Scope:
1583 for Scope1, Scope2 in [("COMMON", "COMMON"), ("COMMON", S2), (S1, "COMMON"), (S1, S2)]:
1584 if (SectionType, Scope1, Scope2) in self._SectionsMacroDict:
1585 Macros.update(self._SectionsMacroDict[(SectionType, Scope1, Scope2)])
1586 return Macros
1587
1588 ## Section header parser
1589 #
1590 # The section header is always in following format:
1591 #
1592 # [section_name.arch<.platform|module_type>]
1593 #
1594 def _SectionHeaderParser(self):
1595 self._Scope = []
1596 self._SectionName = ''
1597 self._SectionType = []
1598 ArchList = set()
1599 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
1600 if Item == '':
1601 continue
1602 ItemList = GetSplitValueList(Item, TAB_SPLIT)
1603
1604 # different types of PCD are permissible in one section
1605 self._SectionName = ItemList[0].upper()
1606 if self._SectionName in self.DataType:
1607 if self.DataType[self._SectionName] not in self._SectionType:
1608 self._SectionType.append(self.DataType[self._SectionName])
1609 else:
1610 EdkLogger.warn("Parser", "Unrecognized section", File=self.MetaFile,
1611 Line=self._LineIndex+1, ExtraData=self._CurrentLine)
1612 continue
1613
1614 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1615 EdkLogger.error(
1616 'Parser',
1617 FORMAT_INVALID,
1618 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1619 File=self.MetaFile,
1620 Line=self._LineIndex+1,
1621 ExtraData=self._CurrentLine
1622 )
1623 # S1 is always Arch
1624 if len(ItemList) > 1:
1625 S1 = ItemList[1].upper()
1626 else:
1627 S1 = 'COMMON'
1628 ArchList.add(S1)
1629 # S2 may be Platform or ModuleType
1630 if len(ItemList) > 2:
1631 S2 = ItemList[2].upper()
1632 else:
1633 S2 = 'COMMON'
1634 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1635 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1636
1637 # 'COMMON' must not be used with specific ARCHs at the same section
1638 if 'COMMON' in ArchList and len(ArchList) > 1:
1639 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1640 File=self.MetaFile, Line=self._LineIndex+1, ExtraData=self._CurrentLine)
1641
1642 ## [guids], [ppis] and [protocols] section parser
1643 @ParseMacro
1644 def _GuidParser(self):
1645 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1646 if len(TokenList) < 2:
1647 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1648 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1649 File=self.MetaFile, Line=self._LineIndex+1)
1650 if TokenList[0] == '':
1651 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1652 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1653 File=self.MetaFile, Line=self._LineIndex+1)
1654 if TokenList[1] == '':
1655 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1656 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1657 File=self.MetaFile, Line=self._LineIndex+1)
1658 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1659 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1660 ExtraData=self._CurrentLine + \
1661 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1662 File=self.MetaFile, Line=self._LineIndex+1)
1663 self._ValueList[0] = TokenList[0]
1664 #Parse the Guid value format
1665 GuidValueList = TokenList[1].strip(' {}').split(',')
1666 Index = 0
1667 HexList = []
1668 if len(GuidValueList) == 11:
1669 for GuidValue in GuidValueList:
1670 GuidValue = GuidValue.strip()
1671 if GuidValue.startswith('0x') or GuidValue.startswith('0X'):
1672 HexList.append('0x' + str(GuidValue[2:]))
1673 Index += 1
1674 continue
1675 else:
1676 if GuidValue.startswith('{'):
1677 HexList.append('0x' + str(GuidValue[3:]))
1678 Index += 1
1679 self._ValueList[1] = "{ %s, %s, %s, { %s, %s, %s, %s, %s, %s, %s, %s }}" % (HexList[0], HexList[1], HexList[2],HexList[3],HexList[4],HexList[5],HexList[6],HexList[7],HexList[8],HexList[9],HexList[10])
1680 else:
1681 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1682 ExtraData=self._CurrentLine + \
1683 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1684 File=self.MetaFile, Line=self._LineIndex+1)
1685 self._ValueList[0] = ''
1686
1687 ## PCD sections parser
1688 #
1689 # [PcdsFixedAtBuild]
1690 # [PcdsPatchableInModule]
1691 # [PcdsFeatureFlag]
1692 # [PcdsDynamicEx
1693 # [PcdsDynamic]
1694 #
1695 @ParseMacro
1696 def _PcdParser(self):
1697 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1698 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1699 # check PCD information
1700 if self._ValueList[0] == '' or self._ValueList[1] == '':
1701 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1702 ExtraData=self._CurrentLine + \
1703 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1704 File=self.MetaFile, Line=self._LineIndex+1)
1705 # check PCD datum information
1706 if len(TokenList) < 2 or TokenList[1] == '':
1707 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
1708 ExtraData=self._CurrentLine + \
1709 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1710 File=self.MetaFile, Line=self._LineIndex+1)
1711
1712
1713 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
1714 PtrValue = ValueRe.findall(TokenList[1])
1715
1716 # Has VOID* type string, may contain "|" character in the string.
1717 if len(PtrValue) != 0:
1718 ptrValueList = re.sub(ValueRe, '', TokenList[1])
1719 ValueList = GetSplitValueList(ptrValueList)
1720 ValueList[0] = PtrValue[0]
1721 else:
1722 ValueList = GetSplitValueList(TokenList[1])
1723
1724
1725 # check if there's enough datum information given
1726 if len(ValueList) != 3:
1727 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
1728 ExtraData=self._CurrentLine + \
1729 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1730 File=self.MetaFile, Line=self._LineIndex+1)
1731 # check default value
1732 if ValueList[0] == '':
1733 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
1734 ExtraData=self._CurrentLine + \
1735 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1736 File=self.MetaFile, Line=self._LineIndex+1)
1737 # check datum type
1738 if ValueList[1] == '':
1739 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
1740 ExtraData=self._CurrentLine + \
1741 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1742 File=self.MetaFile, Line=self._LineIndex+1)
1743 # check token of the PCD
1744 if ValueList[2] == '':
1745 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
1746 ExtraData=self._CurrentLine + \
1747 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1748 File=self.MetaFile, Line=self._LineIndex+1)
1749 # check format of default value against the datum type
1750 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
1751 if not IsValid:
1752 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
1753 File=self.MetaFile, Line=self._LineIndex+1)
1754
1755 if ValueList[0] in ['True', 'true', 'TRUE']:
1756 ValueList[0] = '1'
1757 elif ValueList[0] in ['False', 'false', 'FALSE']:
1758 ValueList[0] = '0'
1759
1760 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
1761
1762 _SectionParser = {
1763 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
1764 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
1765 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
1766 MODEL_EFI_GUID : _GuidParser,
1767 MODEL_EFI_PPI : _GuidParser,
1768 MODEL_EFI_PROTOCOL : _GuidParser,
1769 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1770 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1771 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1772 MODEL_PCD_DYNAMIC : _PcdParser,
1773 MODEL_PCD_DYNAMIC_EX : _PcdParser,
1774 MODEL_UNKNOWN : MetaFileParser._Skip,
1775 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._Skip,
1776 }
1777
1778
1779 ## FdfObject
1780 #
1781 # This class defined basic Fdf object which is used by inheriting
1782 #
1783 # @param object: Inherited from object class
1784 #
1785 class FdfObject(object):
1786 def __init__(self):
1787 object.__init__()
1788
1789 ## Fdf
1790 #
1791 # This class defined the structure used in Fdf object
1792 #
1793 # @param FdfObject: Inherited from FdfObject class
1794 # @param Filename: Input value for Ffilename of Fdf file, default is None
1795 # @param WorkspaceDir: Input value for current workspace directory, default is None
1796 #
1797 class Fdf(FdfObject):
1798 def __init__(self, Filename = None, IsToDatabase = False, WorkspaceDir = None, Database = None):
1799 self.WorkspaceDir = WorkspaceDir
1800 self.IsToDatabase = IsToDatabase
1801
1802 self.Cur = Database.Cur
1803 self.TblFile = Database.TblFile
1804 self.TblFdf = Database.TblFdf
1805 self.FileID = -1
1806 self.FileList = {}
1807
1808 #
1809 # Load Fdf file if filename is not None
1810 #
1811 if Filename != None:
1812 self.LoadFdfFile(Filename)
1813
1814 #
1815 # Insert a FDF file record into database
1816 #
1817 def InsertFile(self, Filename):
1818 FileID = -1
1819 Filename = NormPath(Filename)
1820 if Filename not in self.FileList:
1821 FileID = self.TblFile.InsertFile(Filename, MODEL_FILE_FDF)
1822 self.FileList[Filename] = FileID
1823
1824 return self.FileList[Filename]
1825
1826
1827 ## Load Fdf file
1828 #
1829 # Load the file if it exists
1830 #
1831 # @param Filename: Input value for filename of Fdf file
1832 #
1833 def LoadFdfFile(self, Filename):
1834 FileList = []
1835 #
1836 # Parse Fdf file
1837 #
1838 Filename = NormPath(Filename)
1839 Fdf = FdfParser(Filename)
1840 Fdf.ParseFile()
1841
1842 #
1843 # Insert inf file and pcd information
1844 #
1845 if self.IsToDatabase:
1846 (Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled) = \
1847 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
1848 for Index in range(0, len(Fdf.Profile.PcdDict)):
1849 pass
1850 for Key in Fdf.Profile.PcdDict.keys():
1851 Model = MODEL_PCD
1852 Value1 = Key[1]
1853 Value2 = Key[0]
1854 FileName = Fdf.Profile.PcdFileLineDict[Key][0]
1855 StartLine = Fdf.Profile.PcdFileLineDict[Key][1]
1856 BelongsToFile = self.InsertFile(FileName)
1857 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
1858 for Index in range(0, len(Fdf.Profile.InfList)):
1859 Model = MODEL_META_DATA_COMPONENT
1860 Value1 = Fdf.Profile.InfList[Index]
1861 Value2 = ''
1862 FileName = Fdf.Profile.InfFileLineList[Index][0]
1863 StartLine = Fdf.Profile.InfFileLineList[Index][1]
1864 BelongsToFile = self.InsertFile(FileName)
1865 self.TblFdf.Insert(Model, Value1, Value2, Value3, Scope1, Scope2, BelongsToItem, BelongsToFile, StartLine, StartColumn, EndLine, EndColumn, Enabled)
1866
1867 ##
1868 #
1869 # This acts like the main() function for the script, unless it is 'import'ed into another
1870 # script.
1871 #
1872 if __name__ == '__main__':
1873 pass
1874