2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2010, 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
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.
22 import Common
.EdkLogger
as EdkLogger
23 import Common
.GlobalData
as GlobalData
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 *
33 from MetaFileTable
import MetaFileStorage
34 from GenFds
.FdfParser
import FdfParser
36 ## A decorator used to parse macro definition
37 def ParseMacro(Parser
):
38 def MacroParser(self
):
39 Match
= gMacroDefPattern
.match(self
._CurrentLine
)
41 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
45 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
48 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
49 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
50 if len(TokenList
) < 2:
54 Name
, Value
= TokenList
55 # Global macros can be only defined via environment variable
56 if Name
in GlobalData
.gGlobalDefines
:
57 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
58 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
59 # Only upper case letters, digit and '_' are allowed
60 if not gMacroNamePattern
.match(Name
):
61 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
62 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
64 Value
= ReplaceMacro(Value
, self
._Macros
)
65 self
._ItemType
= MODEL_META_DATA_DEFINE
66 # DEFINE defined macros
67 if Type
== TAB_DSC_DEFINES_DEFINE
:
68 if type(self
) == DecParser
:
69 if MODEL_META_DATA_HEADER
in self
._SectionType
:
70 self
._FileLocalMacros
[Name
] = Value
72 for Scope
in self
._Scope
:
73 self
._SectionsMacroDict
.setdefault((Scope
[2], Scope
[0], Scope
[1]), {})[Name
] = Value
74 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
75 self
._FileLocalMacros
[Name
] = Value
77 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
78 if SectionDictKey
not in self
._SectionsMacroDict
:
79 self
._SectionsMacroDict
[SectionDictKey
] = {}
80 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
81 SectionLocalMacros
[Name
] = Value
82 # EDK_GLOBAL defined macros
83 elif type(self
) != DscParser
:
84 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
85 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
86 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
87 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
88 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
89 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
90 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
91 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
93 self
._ValueList
= [Type
, Name
, Value
]
97 ## Base class of parser
99 # This class is used for derivation purpose. The specific parser for one kind
100 # type file must derive this class and implement some public interfaces.
102 # @param FilePath The path of platform description file
103 # @param FileType The raw data of DSC file
104 # @param Table Database used to retrieve module/package information
105 # @param Macros Macros used for replacement in file
106 # @param Owner Owner ID (for sub-section parsing)
107 # @param From ID from which the data comes (for !INCLUDE directive)
109 class MetaFileParser(object):
110 # data type (file content) for specific file type
113 # Parser objects used to implement singleton
118 # One file, one parser object. This factory method makes sure that there's
119 # only one object constructed for one meta file.
121 # @param Class class object of real AutoGen class
122 # (InfParser, DecParser or DscParser)
123 # @param FilePath The path of meta file
124 # @param *args The specific class related parameters
125 # @param **kwargs The specific class related dict parameters
127 def __new__(Class
, FilePath
, *args
, **kwargs
):
128 if FilePath
in Class
.MetaFiles
:
129 return Class
.MetaFiles
[FilePath
]
131 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
132 Class
.MetaFiles
[FilePath
] = ParserObject
135 ## Constructor of MetaFileParser
137 # Initialize object of MetaFileParser
139 # @param FilePath The path of platform description file
140 # @param FileType The raw data of DSC file
141 # @param Table Database used to retrieve module/package information
142 # @param Macros Macros used for replacement in file
143 # @param Owner Owner ID (for sub-section parsing)
144 # @param From ID from which the data comes (for !INCLUDE directive)
146 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
148 self
._RawTable
= Table
149 self
._FileType
= FileType
150 self
.MetaFile
= FilePath
152 self
._FileLocalMacros
= {}
153 self
._SectionsMacroDict
= {}
155 # for recursive parsing
156 self
._Owner
= [Owner
]
159 # parsr status for parsing
160 self
._ValueList
= ['', '', '', '', '']
163 self
._CurrentLine
= ''
164 self
._SectionType
= MODEL_UNKNOWN
165 self
._SectionName
= ''
166 self
._InSubsection
= False
167 self
._SubsectionType
= MODEL_UNKNOWN
168 self
._SubsectionName
= ''
169 self
._ItemType
= MODEL_UNKNOWN
172 self
._Finished
= False
173 self
._PostProcessed
= False
174 # Different version of meta-file has different way to parse.
177 ## Store the parsed data in table
178 def _Store(self
, *Args
):
179 return self
._Table
.Insert(*Args
)
181 ## Virtual method for starting parse
183 raise NotImplementedError
185 ## Notify a post-process is needed
186 def DoPostProcess(self
):
187 self
._PostProcessed
= False
189 ## Set parsing complete flag in both class and table
191 self
._Finished
= True
192 ## Do not set end flag when processing included files
194 self
._Table
.SetEndFlag()
196 def _PostProcess(self
):
197 self
._PostProcessed
= True
199 ## Get the parse complete flag
200 def _GetFinished(self
):
201 return self
._Finished
203 ## Set the complete flag
204 def _SetFinished(self
, Value
):
205 self
._Finished
= Value
207 ## Use [] style to query data in table, just for readability
209 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
211 def __getitem__(self
, DataInfo
):
212 if type(DataInfo
) != type(()):
213 DataInfo
= (DataInfo
,)
215 # Parse the file first, if necessary
216 if not self
._Finished
:
217 if self
._RawTable
.IsIntegrity():
218 self
._Finished
= True
220 self
._Table
= self
._RawTable
221 self
._PostProcessed
= False
224 # No specific ARCH or Platform given, use raw data
225 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] == None):
226 return self
._RawTable
.Query(*DataInfo
)
228 # Do post-process if necessary
229 if not self
._PostProcessed
:
232 return self
._Table
.Query(*DataInfo
)
234 ## Data parser for the common format in different type of file
236 # The common format in the meatfile is like
241 def _CommonParser(self
):
242 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
243 self
._ValueList
[0:len(TokenList
)] = TokenList
245 ## Data parser for the format in which there's path
247 # Only path can have macro used. So we need to replace them before use.
250 def _PathParser(self
):
251 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
252 self
._ValueList
[0:len(TokenList
)] = TokenList
253 # Don't do macro replacement for dsc file at this point
254 if type(self
) != DscParser
:
255 Macros
= self
._Macros
256 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
258 ## Skip unsupported data
260 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
261 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
);
262 self
._ValueList
[0:1] = [self
._CurrentLine
]
264 ## Section header parser
266 # The section header is always in following format:
268 # [section_name.arch<.platform|module_type>]
270 def _SectionHeaderParser(self
):
272 self
._SectionName
= ''
274 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
277 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
278 # different section should not mix in one section
279 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
280 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
281 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
282 self
._SectionName
= ItemList
[0].upper()
283 if self
._SectionName
in self
.DataType
:
284 self
._SectionType
= self
.DataType
[self
._SectionName
]
286 self
._SectionType
= MODEL_UNKNOWN
287 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
288 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
290 if len(ItemList
) > 1:
291 S1
= ItemList
[1].upper()
295 # S2 may be Platform or ModuleType
296 if len(ItemList
) > 2:
297 S2
= ItemList
[2].upper()
300 self
._Scope
.append([S1
, S2
])
302 # 'COMMON' must not be used with specific ARCHs at the same section
303 if 'COMMON' in ArchList
and len(ArchList
) > 1:
304 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
305 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
306 # If the section information is needed later, it should be stored in database
307 self
._ValueList
[0] = self
._SectionName
309 ## [defines] section parser
311 def _DefineParser(self
):
312 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
313 self
._ValueList
[1:len(TokenList
)] = TokenList
314 if not self
._ValueList
[1]:
315 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
316 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
317 if not self
._ValueList
[2]:
318 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
319 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
321 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
322 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
323 # Sometimes, we need to make differences between EDK and EDK2 modules
324 if Name
== 'INF_VERSION':
326 self
._Version
= int(Value
, 0)
328 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
329 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
331 if type(self
) == InfParser
and self
._Version
< 0x00010005:
332 # EDK module allows using defines as macros
333 self
._FileLocalMacros
[Name
] = Value
334 self
._Defines
[Name
] = Value
336 ## [BuildOptions] section parser
338 def _BuildOptionParser(self
):
339 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
340 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
341 if len(TokenList2
) == 2:
342 self
._ValueList
[0] = TokenList2
[0] # toolchain family
343 self
._ValueList
[1] = TokenList2
[1] # keys
345 self
._ValueList
[1] = TokenList
[0]
346 if len(TokenList
) == 2 and type(self
) != DscParser
: # value
347 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
349 if self
._ValueList
[1].count('_') != 4:
353 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
354 ExtraData
=self
._CurrentLine
,
356 Line
=self
._LineIndex
+1
359 def _GetMacros(self
):
361 Macros
.update(self
._FileLocalMacros
)
362 Macros
.update(self
._GetApplicableSectionMacro
())
366 ## Get section Macros that are applicable to current line, which may come from other sections
367 ## that share the same name while scope is wider
368 def _GetApplicableSectionMacro(self
):
370 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", self
._Scope
[0][1]),
371 (self
._Scope
[0][0], "COMMON"), (self
._Scope
[0][0], self
._Scope
[0][1])]:
372 if (self
._SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
373 Macros
.update(self
._SectionsMacroDict
[(self
._SectionType
, Scope1
, Scope2
)])
377 Finished
= property(_GetFinished
, _SetFinished
)
378 _Macros
= property(_GetMacros
)
381 ## INF file parser class
383 # @param FilePath The path of platform description file
384 # @param FileType The raw data of DSC file
385 # @param Table Database used to retrieve module/package information
386 # @param Macros Macros used for replacement in file
388 class InfParser(MetaFileParser
):
389 # INF file supported data types (one type per section)
391 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
392 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
393 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
394 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
395 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
396 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
397 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
398 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
399 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
400 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
401 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
402 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
403 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
404 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
405 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
406 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
407 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
408 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
409 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
410 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
411 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
414 ## Constructor of InfParser
416 # Initialize object of InfParser
418 # @param FilePath The path of module description file
419 # @param FileType The raw data of DSC file
420 # @param Table Database used to retrieve module/package information
421 # @param Macros Macros used for replacement in file
423 def __init__(self
, FilePath
, FileType
, Table
):
424 # prevent re-initialization
425 if hasattr(self
, "_Table"):
427 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
428 self
.TblFile
= EccGlobalData
.gDb
.TblFile
436 Content
= open(str(self
.MetaFile
), 'r').readlines()
438 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
440 # Insert a record for file
442 Filename
= NormPath(self
.MetaFile
)
443 FileID
= self
.TblFile
.GetFileId(Filename
)
447 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_INF
)
449 # parse the file line by line
450 IsFindBlockComment
= False
452 for Index
in range(0, len(Content
)):
453 # skip empty, commented, block commented lines
454 Line
= CleanString(Content
[Index
], AllowCppStyleComment
=True)
456 if Index
+ 1 < len(Content
):
457 NextLine
= CleanString(Content
[Index
+ 1])
460 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
461 IsFindBlockComment
= True
463 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
464 IsFindBlockComment
= False
466 if IsFindBlockComment
:
469 self
._LineIndex
= Index
470 self
._CurrentLine
= Line
473 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
474 self
._SectionHeaderParser
()
475 # Check invalid sections
476 if self
._Version
< 0x00010005:
477 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
478 MODEL_EFI_LIBRARY_CLASS
,
479 MODEL_META_DATA_PACKAGE
,
480 MODEL_PCD_FIXED_AT_BUILD
,
481 MODEL_PCD_PATCHABLE_IN_MODULE
,
482 MODEL_PCD_FEATURE_FLAG
,
483 MODEL_PCD_DYNAMIC_EX
,
488 MODEL_META_DATA_USER_EXTENSION
]:
489 EdkLogger
.error('Parser', FORMAT_INVALID
,
490 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
491 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
492 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
493 MODEL_EFI_LIBRARY_INSTANCE
,
494 MODEL_META_DATA_NMAKE
]:
495 EdkLogger
.error('Parser', FORMAT_INVALID
,
496 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
497 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
499 # merge two lines specified by '\' in section NMAKE
500 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
503 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
506 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
507 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
510 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
513 self
._CurrentLine
= NmakeLine
+ Line
517 self
._ValueList
= ['','','']
518 # parse current line, result will be put in self._ValueList
519 self
._SectionParser
[self
._SectionType
](self
)
520 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
524 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
525 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
527 self
._ValueList
[0] = self
._ValueList
[0].replace('/', '\\')
528 for Arch
, Platform
in self
._Scope
:
529 self
._Store
(self
._SectionType
,
543 if IsFindBlockComment
:
544 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
548 ## Data parser for the format in which there's path
550 # Only path can have macro used. So we need to replace them before use.
552 def _IncludeParser(self
):
553 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
554 self
._ValueList
[0:len(TokenList
)] = TokenList
555 Macros
= self
._Macros
557 for Index
in range(0, len(self
._ValueList
)):
558 Value
= self
._ValueList
[Index
]
562 if Value
.upper().find('$(EFI_SOURCE)\Edk'.upper()) > -1 or Value
.upper().find('$(EFI_SOURCE)/Edk'.upper()) > -1:
563 Value
= '$(EDK_SOURCE)' + Value
[17:]
564 if Value
.find('$(EFI_SOURCE)') > -1 or Value
.find('$(EDK_SOURCE)') > -1:
566 elif Value
.startswith('.'):
568 elif Value
.startswith('$('):
571 Value
= '$(EFI_SOURCE)/' + Value
573 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
575 ## Parse [Sources] section
577 # Only path can have macro used. So we need to replace them before use.
580 def _SourceFileParser(self
):
581 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
582 self
._ValueList
[0:len(TokenList
)] = TokenList
583 Macros
= self
._Macros
584 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
585 if 'COMPONENT_TYPE' in Macros
:
586 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
587 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
588 if self
._Defines
['BASE_NAME'] == 'Microcode':
590 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
592 ## Parse [Binaries] section
594 # Only path can have macro used. So we need to replace them before use.
597 def _BinaryFileParser(self
):
598 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
599 if len(TokenList
) < 2:
600 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
601 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
602 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
604 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
605 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
606 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
608 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
609 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
610 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
611 self
._ValueList
[0:len(TokenList
)] = TokenList
612 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
614 ## [nmake] section parser (Edk.x style only)
615 def _NmakeParser(self
):
616 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
617 self
._ValueList
[0:len(TokenList
)] = TokenList
619 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
620 # remove self-reference in macro setting
621 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
623 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
625 def _PcdParser(self
):
626 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
627 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
628 if len(ValueList
) != 2:
629 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
630 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
631 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
632 self
._ValueList
[0:1] = ValueList
633 if len(TokenList
) > 1:
634 self
._ValueList
[2] = TokenList
[1]
635 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
636 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
637 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
638 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
640 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
641 if self
._ValueList
[2] != '':
642 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
643 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
644 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
645 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
646 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
648 ## [depex] section parser
650 def _DepexParser(self
):
651 self
._ValueList
[0:1] = [self
._CurrentLine
]
654 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
655 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
656 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
657 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
658 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
659 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
660 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
661 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
662 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
663 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
664 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
665 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
666 MODEL_PCD_DYNAMIC
: _PcdParser
,
667 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
668 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
669 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
670 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
671 MODEL_EFI_DEPEX
: _DepexParser
,
672 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
673 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
676 ## DSC file parser class
678 # @param FilePath The path of platform description file
679 # @param FileType The raw data of DSC file
680 # @param Table Database used to retrieve module/package information
681 # @param Macros Macros used for replacement in file
682 # @param Owner Owner ID (for sub-section parsing)
683 # @param From ID from which the data comes (for !INCLUDE directive)
685 class DscParser(MetaFileParser
):
686 # DSC file supported data types (one type per section)
688 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
689 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
690 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
691 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
692 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
693 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
694 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
695 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
696 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
697 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
698 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
699 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
700 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
701 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
702 TAB_COMPONENTS_SOURCE_OVERRIDE_PATH
.upper() : MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
,
703 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
704 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
705 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
706 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
707 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
708 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
709 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
710 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
711 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
712 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
715 # Valid names in define section
722 "PCD_INFO_GENERATION",
723 "SUPPORTED_ARCHITECTURES",
732 "FIX_LOAD_TOP_MEMORY_ADDRESS"
735 SymbolPattern
= ValueExpression
.SymbolPattern
737 ## Constructor of DscParser
739 # Initialize object of DscParser
741 # @param FilePath The path of platform description file
742 # @param FileType The raw data of DSC file
743 # @param Table Database used to retrieve module/package information
744 # @param Macros Macros used for replacement in file
745 # @param Owner Owner ID (for sub-section parsing)
746 # @param From ID from which the data comes (for !INCLUDE directive)
748 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
749 # prevent re-initialization
750 if hasattr(self
, "_Table"):
752 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
753 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
754 # to store conditional directive evaluation result
755 self
._DirectiveStack
= []
756 self
._DirectiveEvalStack
= []
759 # Final valid replacable symbols
762 # Map the ID between the original table and new table to track
765 self
._IdMapping
= {-1:-1}
767 self
.TblFile
= EccGlobalData
.gDb
.TblFile
774 Content
= open(str(self
.MetaFile
.Path
), 'r').readlines()
776 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
778 # Insert a record for file
780 Filename
= NormPath(self
.MetaFile
.Path
)
781 FileID
= self
.TblFile
.GetFileId(Filename
)
785 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DSC
)
788 for Index
in range(0, len(Content
)):
789 Line
= CleanString(Content
[Index
])
794 self
._CurrentLine
= Line
795 self
._LineIndex
= Index
796 if self
._InSubsection
and self
._Owner
[-1] == -1:
797 self
._Owner
.append(self
._LastItem
)
800 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
801 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
803 elif Line
[0] == '}' and self
._InSubsection
:
804 self
._InSubsection
= False
805 self
._SubsectionType
= MODEL_UNKNOWN
806 self
._SubsectionName
= ''
810 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
811 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
814 self
._DirectiveParser
()
817 if self
._InSubsection
:
818 SectionType
= self
._SubsectionType
820 SectionType
= self
._SectionType
821 self
._ItemType
= SectionType
823 self
._ValueList
= ['', '', '']
824 self
._SectionParser
[SectionType
](self
)
825 if self
._ValueList
== None:
828 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
829 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
831 for Arch
, ModuleType
in self
._Scope
:
832 self
._LastItem
= self
._Store
(
849 if self
._DirectiveStack
:
850 Type
, Line
, Text
= self
._DirectiveStack
[-1]
851 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
852 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
855 ## <subsection_header> parser
856 def _SubsectionHeaderParser(self
):
857 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
858 if self
._SubsectionName
in self
.DataType
:
859 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
861 self
._SubsectionType
= MODEL_UNKNOWN
862 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
863 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
864 self
._ValueList
[0] = self
._SubsectionName
866 ## Directive statement parser
867 def _DirectiveParser(self
):
868 self
._ValueList
= ['','','']
869 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
870 self
._ValueList
[0:len(TokenList
)] = TokenList
873 DirectiveName
= self
._ValueList
[0].upper()
874 if DirectiveName
not in self
.DataType
:
875 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
876 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
877 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
878 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
879 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
880 ExtraData
=self
._CurrentLine
)
882 ItemType
= self
.DataType
[DirectiveName
]
883 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
884 # Remove all directives between !if and !endif, including themselves
885 while self
._DirectiveStack
:
886 # Remove any !else or !elseif
887 DirectiveInfo
= self
._DirectiveStack
.pop()
888 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
889 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
890 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
893 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
894 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
895 ExtraData
=self
._CurrentLine
)
896 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
897 # Break if there's a !else is followed by a !elseif
898 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
899 self
._DirectiveStack
and \
900 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
901 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
902 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
903 ExtraData
=self
._CurrentLine
)
904 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+1, self
._CurrentLine
))
906 EdkLogger
.error('Parser', FORMAT_INVALID
,
907 "No '!include' allowed in included file",
908 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
909 Line
=self
._LineIndex
+1)
912 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
913 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
915 self
._LastItem
= self
._Store
(
932 ## [defines] section parser
934 def _DefineParser(self
):
935 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
936 self
._ValueList
[1:len(TokenList
)] = TokenList
939 if not self
._ValueList
[1]:
940 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
941 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
942 if not self
._ValueList
[2]:
943 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
944 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
945 if not self
._ValueList
[1] in self
.DefineKeywords
:
946 EdkLogger
.error('Parser', FORMAT_INVALID
,
947 "Unknown keyword found: %s. "
948 "If this is a macro you must "
949 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
950 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
951 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
952 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
955 def _SkuIdParser(self
):
956 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
957 if len(TokenList
) != 2:
958 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
959 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
960 self
._ValueList
[0:len(TokenList
)] = TokenList
962 ## Parse Edk style of library modules
963 def _LibraryInstanceParser(self
):
964 self
._ValueList
[0] = self
._CurrentLine
966 ## PCD sections parser
969 # [PcdsPatchableInModule]
972 # [PcdsDynamicExDefault]
976 # [PcdsDynamicDefault]
981 def _PcdParser(self
):
982 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
983 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
984 if len(TokenList
) == 2:
985 self
._ValueList
[2] = TokenList
[1]
986 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
987 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
988 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
989 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
990 if self
._ValueList
[2] == '':
991 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
992 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
993 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
994 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
995 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
996 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
997 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
998 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
999 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1001 ## [components] section parser
1003 def _ComponentParser(self
):
1004 if self
._CurrentLine
[-1] == '{':
1005 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1006 self
._InSubsection
= True
1008 self
._ValueList
[0] = self
._CurrentLine
1010 ## [LibraryClasses] section
1012 def _LibraryClassParser(self
):
1013 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1014 if len(TokenList
) < 2:
1015 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1016 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1017 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1018 if TokenList
[0] == '':
1019 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1020 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1021 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1022 if TokenList
[1] == '':
1023 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1024 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1025 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1027 self
._ValueList
[0:len(TokenList
)] = TokenList
1029 def _CompponentSourceOverridePathParser(self
):
1030 self
._ValueList
[0] = self
._CurrentLine
1032 ## [BuildOptions] section parser
1034 def _BuildOptionParser(self
):
1035 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1036 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1037 if len(TokenList2
) == 2:
1038 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1039 self
._ValueList
[1] = TokenList2
[1] # keys
1041 self
._ValueList
[1] = TokenList
[0]
1042 if len(TokenList
) == 2: # value
1043 self
._ValueList
[2] = TokenList
[1]
1045 if self
._ValueList
[1].count('_') != 4:
1049 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1050 ExtraData
=self
._CurrentLine
,
1052 Line
=self
._LineIndex
+1
1055 ## Override parent's method since we'll do all macro replacements in parser
1056 def _GetMacros(self
):
1058 Macros
.update(self
._FileLocalMacros
)
1059 Macros
.update(self
._GetApplicableSectionMacro
())
1060 Macros
.update(GlobalData
.gEdkGlobal
)
1061 Macros
.update(GlobalData
.gPlatformDefines
)
1062 Macros
.update(GlobalData
.gCommandLineDefines
)
1063 # PCD cannot be referenced in macro definition
1064 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1065 Macros
.update(self
._Symbols
)
1068 def _PostProcess(self
):
1070 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1071 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1072 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1073 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1074 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1075 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1076 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1077 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1078 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1079 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1080 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1081 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1082 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1083 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1084 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1085 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1086 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1087 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1088 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1089 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1090 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1091 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1092 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1093 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1094 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1095 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: self
.__ProcessSourceOverridePath
,
1096 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1097 MODEL_UNKNOWN
: self
._Skip
,
1098 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1101 self
._RawTable
= self
._Table
1102 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1103 self
._DirectiveStack
= []
1104 self
._DirectiveEvalStack
= []
1105 self
._FileWithError
= self
.MetaFile
1106 self
._FileLocalMacros
= {}
1107 self
._SectionsMacroDict
= {}
1108 GlobalData
.gPlatformDefines
= {}
1110 # Get all macro and PCD which has straitforward value
1111 self
.__RetrievePcdValue
()
1112 self
._Content
= self
._RawTable
.GetAll()
1113 self
._ContentIndex
= 0
1114 while self
._ContentIndex
< len(self
._Content
) :
1115 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, BelongsToFile
, self
._From
, \
1116 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1119 self
._FileWithError
= self
.MetaFile
1121 self
._ContentIndex
+= 1
1123 self
._Scope
= [[S1
, S2
]]
1124 self
._LineIndex
= LineStart
- 1
1125 self
._ValueList
= [V1
, V2
, V3
]
1128 Processer
[self
._ItemType
]()
1129 except EvaluationException
, Excpt
:
1131 # Only catch expression evaluation error here. We need to report
1132 # the precise number of line on which the error occurred
1134 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid expression: %s" % str(Excpt
),
1135 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1136 Line
=self
._LineIndex
+1)
1137 except MacroException
, Excpt
:
1138 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1139 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1140 Line
=self
._LineIndex
+1)
1142 if self
._ValueList
== None:
1145 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1146 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1147 self
._LastItem
= self
._Store
(
1163 self
._IdMapping
[Id
] = self
._LastItem
1165 RecordList
= self
._Table
.GetAll()
1167 self
._RawTable
.Drop()
1169 for Record
in RecordList
:
1170 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])
1171 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1172 self
._PostProcessed
= True
1173 self
._Content
= None
1175 def __ProcessSectionHeader(self
):
1176 self
._SectionName
= self
._ValueList
[0]
1177 if self
._SectionName
in self
.DataType
:
1178 self
._SectionType
= self
.DataType
[self
._SectionName
]
1180 self
._SectionType
= MODEL_UNKNOWN
1182 def __ProcessSubsectionHeader(self
):
1183 self
._SubsectionName
= self
._ValueList
[0]
1184 if self
._SubsectionName
in self
.DataType
:
1185 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1187 self
._SubsectionType
= MODEL_UNKNOWN
1189 def __RetrievePcdValue(self
):
1190 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
=-1.0)
1191 for TokenSpaceGuid
,PcdName
,Value
,Dummy2
,Dummy3
,ID
,Line
in Records
:
1192 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1193 # Only use PCD whose value is straitforward (no macro and PCD)
1194 if self
.SymbolPattern
.findall(Value
):
1196 Name
= TokenSpaceGuid
+ '.' + PcdName
1197 # Don't use PCD with different values.
1198 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1199 self
._Symbols
.pop(Name
)
1201 self
._Symbols
[Name
] = Value
1203 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
=-1.0)
1204 for TokenSpaceGuid
,PcdName
,Value
,Dummy2
,Dummy3
,ID
,Line
in Records
:
1205 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1206 # Only use PCD whose value is straitforward (no macro and PCD)
1207 if self
.SymbolPattern
.findall(Value
):
1209 Name
= TokenSpaceGuid
+'.'+PcdName
1210 # Don't use PCD with different values.
1211 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1212 self
._Symbols
.pop(Name
)
1214 self
._Symbols
[Name
] = Value
1216 def __ProcessDefine(self
):
1217 if not self
._Enabled
:
1220 Type
, Name
, Value
= self
._ValueList
1221 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1222 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1223 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1224 self
._FileLocalMacros
[Name
] = Value
1226 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
1227 if SectionDictKey
not in self
._SectionsMacroDict
:
1228 self
._SectionsMacroDict
[SectionDictKey
] = {}
1229 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
1230 SectionLocalMacros
[Name
] = Value
1231 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1232 GlobalData
.gEdkGlobal
[Name
] = Value
1235 # Keyword in [Defines] section can be used as Macros
1237 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1238 self
._FileLocalMacros
[Name
] = Value
1240 self
._ValueList
= [Type
, Name
, Value
]
1242 def __ProcessDirective(self
):
1244 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1245 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1246 Macros
= self
._Macros
1247 Macros
.update(GlobalData
.gGlobalDefines
)
1249 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1250 except SymbolNotFound
, Exc
:
1251 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1253 except WrnExpression
, Excpt
:
1255 # Catch expression evaluation warning here. We need to report
1256 # the precise number of line and return the evaluation result
1258 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1259 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1260 Line
=self
._LineIndex
+1)
1261 Result
= Excpt
.result
1263 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1264 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1265 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1266 self
._DirectiveStack
.append(self
._ItemType
)
1267 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1268 Result
= bool(Result
)
1270 Macro
= self
._ValueList
[1]
1271 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1272 Result
= Macro
in self
._Macros
1273 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1275 self
._DirectiveEvalStack
.append(Result
)
1276 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1277 self
._DirectiveStack
.append(self
._ItemType
)
1278 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1279 self
._DirectiveEvalStack
.append(bool(Result
))
1280 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1281 self
._DirectiveStack
[-1] = self
._ItemType
1282 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1283 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1284 # Back to the nearest !if/!ifdef/!ifndef
1285 while self
._DirectiveStack
:
1286 self
._DirectiveEvalStack
.pop()
1287 Directive
= self
._DirectiveStack
.pop()
1288 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1289 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1290 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
1291 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1293 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1294 # The included file must be relative to workspace or same directory as DSC file
1295 __IncludeMacros
= {}
1297 # Allow using system environment variables in path after !include
1299 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1300 if "ECP_SOURCE" in GlobalData
.gGlobalDefines
.keys():
1301 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gGlobalDefines
['ECP_SOURCE']
1303 # During GenFds phase call DSC parser, will go into this branch.
1305 elif "ECP_SOURCE" in GlobalData
.gCommandLineDefines
.keys():
1306 __IncludeMacros
['ECP_SOURCE'] = GlobalData
.gCommandLineDefines
['ECP_SOURCE']
1308 __IncludeMacros
['EFI_SOURCE'] = GlobalData
.gGlobalDefines
['EFI_SOURCE']
1309 __IncludeMacros
['EDK_SOURCE'] = GlobalData
.gGlobalDefines
['EDK_SOURCE']
1311 # Allow using MACROs comes from [Defines] section to keep compatible.
1313 __IncludeMacros
.update(self
._Macros
)
1315 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1317 # First search the include file under the same directory as DSC file
1319 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1320 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1323 # Also search file under the WORKSPACE directory
1325 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1326 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1328 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1329 Line
=self
._LineIndex
+1, ExtraData
=ErrorInfo1
+ "\n"+ ErrorInfo2
)
1331 self
._FileWithError
= IncludedFile1
1333 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, True)
1334 Owner
= self
._Content
[self
._ContentIndex
-1][0]
1335 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1336 Owner
=Owner
, From
=Owner
)
1338 # set the parser status with current status
1339 Parser
._SectionName
= self
._SectionName
1340 Parser
._SectionType
= self
._SectionType
1341 Parser
._Scope
= self
._Scope
1342 Parser
._Enabled
= self
._Enabled
1343 # Parse the included file
1346 # update current status with sub-parser's status
1347 self
._SectionName
= Parser
._SectionName
1348 self
._SectionType
= Parser
._SectionType
1349 self
._Scope
= Parser
._Scope
1350 self
._Enabled
= Parser
._Enabled
1352 # Insert all records in the table for the included file into dsc file table
1353 Records
= IncludedFileTable
.GetAll()
1355 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1356 self
._Content
.pop(self
._ContentIndex
-1)
1357 self
._ValueList
= None
1358 self
._ContentIndex
-= 1
1360 def __ProcessSkuId(self
):
1361 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1362 for Value
in self
._ValueList
]
1364 def __ProcessLibraryInstance(self
):
1365 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1367 def __ProcessLibraryClass(self
):
1368 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1370 def __ProcessPcd(self
):
1371 ValueList
= GetSplitValueList(self
._ValueList
[2])
1373 # PCD value can be an expression
1375 if len(ValueList
) > 1 and ValueList
[1] == 'VOID*':
1376 PcdValue
= ValueList
[0]
1378 ValueList
[0] = ValueExpression(PcdValue
, self
._Macros
)(True)
1379 except WrnExpression
, Value
:
1380 ValueList
[0] = Value
.result
1382 PcdValue
= ValueList
[-1]
1384 ValueList
[-1] = ValueExpression(PcdValue
, self
._Macros
)(True)
1385 except WrnExpression
, Value
:
1386 ValueList
[-1] = Value
.result
1388 if ValueList
[-1] == 'True':
1390 if ValueList
[-1] == 'False':
1393 self
._ValueList
[2] = '|'.join(ValueList
)
1395 def __ProcessComponent(self
):
1396 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1398 def __ProcessSourceOverridePath(self
):
1399 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1401 def __ProcessBuildOption(self
):
1402 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1403 for Value
in self
._ValueList
]
1406 MODEL_META_DATA_HEADER
: _DefineParser
,
1407 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1408 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1409 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1410 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1411 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1412 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1413 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1414 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1415 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1416 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1417 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1418 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1419 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1420 MODEL_META_DATA_COMPONENT_SOURCE_OVERRIDE_PATH
: _CompponentSourceOverridePathParser
,
1421 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1422 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1423 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1424 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1425 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1428 _Macros
= property(_GetMacros
)
1430 ## DEC file parser class
1432 # @param FilePath The path of platform description file
1433 # @param FileType The raw data of DSC file
1434 # @param Table Database used to retrieve module/package information
1435 # @param Macros Macros used for replacement in file
1437 class DecParser(MetaFileParser
):
1438 # DEC file supported data types (one type per section)
1440 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1441 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1442 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1443 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1444 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1445 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1446 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1447 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1448 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1449 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1450 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1451 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1454 ## Constructor of DecParser
1456 # Initialize object of DecParser
1458 # @param FilePath The path of platform description file
1459 # @param FileType The raw data of DSC file
1460 # @param Table Database used to retrieve module/package information
1461 # @param Macros Macros used for replacement in file
1463 def __init__(self
, FilePath
, FileType
, Table
):
1464 # prevent re-initialization
1465 if hasattr(self
, "_Table"):
1467 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
1469 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1470 self
.TblFile
= EccGlobalData
.gDb
.TblFile
1477 Content
= open(str(self
.MetaFile
), 'r').readlines()
1479 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1482 # Insert a record for file
1484 Filename
= NormPath(self
.MetaFile
)
1485 FileID
= self
.TblFile
.GetFileId(Filename
)
1487 self
.FileID
= FileID
1489 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DEC
)
1491 for Index
in range(0, len(Content
)):
1492 Line
, Comment
= CleanString2(Content
[Index
])
1493 self
._CurrentLine
= Line
1494 self
._LineIndex
= Index
1496 # save comment for later use
1498 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1504 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1505 self
._SectionHeaderParser
()
1508 elif len(self
._SectionType
) == 0:
1513 self
._ValueList
= ['','','']
1514 self
._SectionParser
[self
._SectionType
[0]](self
)
1515 if self
._ValueList
== None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1521 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1522 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1524 for Arch
, ModuleType
, Type
in self
._Scope
:
1525 self
._LastItem
= self
._Store
(
1540 for Comment
, LineNo
in self
._Comments
:
1542 MODEL_META_DATA_COMMENT
,
1559 def _GetApplicableSectionMacro(self
):
1561 for S1
, S2
, SectionType
in self
._Scope
:
1562 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", S2
), (S1
, "COMMON"), (S1
, S2
)]:
1563 if (SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
1564 Macros
.update(self
._SectionsMacroDict
[(SectionType
, Scope1
, Scope2
)])
1567 ## Section header parser
1569 # The section header is always in following format:
1571 # [section_name.arch<.platform|module_type>]
1573 def _SectionHeaderParser(self
):
1575 self
._SectionName
= ''
1576 self
._SectionType
= []
1578 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1581 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1583 # different types of PCD are permissible in one section
1584 self
._SectionName
= ItemList
[0].upper()
1585 if self
._SectionName
in self
.DataType
:
1586 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1587 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1589 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1590 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1593 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1597 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1599 Line
=self
._LineIndex
+1,
1600 ExtraData
=self
._CurrentLine
1603 if len(ItemList
) > 1:
1604 S1
= ItemList
[1].upper()
1608 # S2 may be Platform or ModuleType
1609 if len(ItemList
) > 2:
1610 S2
= ItemList
[2].upper()
1613 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1614 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1616 # 'COMMON' must not be used with specific ARCHs at the same section
1617 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1618 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1619 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1621 ## [guids], [ppis] and [protocols] section parser
1623 def _GuidParser(self
):
1624 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1625 if len(TokenList
) < 2:
1626 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1627 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1628 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1629 if TokenList
[0] == '':
1630 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1631 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1632 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1633 if TokenList
[1] == '':
1634 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1635 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1636 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1637 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1638 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1639 ExtraData
=self
._CurrentLine
+ \
1640 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1641 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1642 self
._ValueList
[0] = TokenList
[0]
1643 #Parse the Guid value format
1644 GuidValueList
= TokenList
[1].strip(' {}').split(',')
1647 if len(GuidValueList
) == 11:
1648 for GuidValue
in GuidValueList
:
1649 GuidValue
= GuidValue
.strip()
1650 if GuidValue
.startswith('0x') or GuidValue
.startswith('0X'):
1651 HexList
.append('0x' + str(GuidValue
[2:]))
1655 if GuidValue
.startswith('{'):
1656 HexList
.append('0x' + str(GuidValue
[3:]))
1658 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])
1660 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1661 ExtraData
=self
._CurrentLine
+ \
1662 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1663 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1664 self
._ValueList
[0] = ''
1666 ## PCD sections parser
1668 # [PcdsFixedAtBuild]
1669 # [PcdsPatchableInModule]
1675 def _PcdParser(self
):
1676 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1677 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1678 # check PCD information
1679 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1680 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1681 ExtraData
=self
._CurrentLine
+ \
1682 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1683 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1684 # check PCD datum information
1685 if len(TokenList
) < 2 or TokenList
[1] == '':
1686 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1687 ExtraData
=self
._CurrentLine
+ \
1688 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1689 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1692 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1693 PtrValue
= ValueRe
.findall(TokenList
[1])
1695 # Has VOID* type string, may contain "|" character in the string.
1696 if len(PtrValue
) != 0:
1697 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1698 ValueList
= GetSplitValueList(ptrValueList
)
1699 ValueList
[0] = PtrValue
[0]
1701 ValueList
= GetSplitValueList(TokenList
[1])
1704 # check if there's enough datum information given
1705 if len(ValueList
) != 3:
1706 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1707 ExtraData
=self
._CurrentLine
+ \
1708 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1709 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1710 # check default value
1711 if ValueList
[0] == '':
1712 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1713 ExtraData
=self
._CurrentLine
+ \
1714 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1715 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1717 if ValueList
[1] == '':
1718 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1719 ExtraData
=self
._CurrentLine
+ \
1720 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1721 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1722 # check token of the PCD
1723 if ValueList
[2] == '':
1724 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1725 ExtraData
=self
._CurrentLine
+ \
1726 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1727 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1728 # check format of default value against the datum type
1729 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1731 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1732 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1734 if ValueList
[0] in ['True', 'true', 'TRUE']:
1736 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1739 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1742 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1743 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1744 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1745 MODEL_EFI_GUID
: _GuidParser
,
1746 MODEL_EFI_PPI
: _GuidParser
,
1747 MODEL_EFI_PROTOCOL
: _GuidParser
,
1748 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1749 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1750 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1751 MODEL_PCD_DYNAMIC
: _PcdParser
,
1752 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1753 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1754 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1760 # This class defined basic Fdf object which is used by inheriting
1762 # @param object: Inherited from object class
1764 class FdfObject(object):
1770 # This class defined the structure used in Fdf object
1772 # @param FdfObject: Inherited from FdfObject class
1773 # @param Filename: Input value for Ffilename of Fdf file, default is None
1774 # @param WorkspaceDir: Input value for current workspace directory, default is None
1776 class Fdf(FdfObject
):
1777 def __init__(self
, Filename
= None, IsToDatabase
= False, WorkspaceDir
= None, Database
= None):
1778 self
.WorkspaceDir
= WorkspaceDir
1779 self
.IsToDatabase
= IsToDatabase
1781 self
.Cur
= Database
.Cur
1782 self
.TblFile
= Database
.TblFile
1783 self
.TblFdf
= Database
.TblFdf
1788 # Load Fdf file if filename is not None
1790 if Filename
!= None:
1791 self
.LoadFdfFile(Filename
)
1794 # Insert a FDF file record into database
1796 def InsertFile(self
, Filename
):
1798 Filename
= NormPath(Filename
)
1799 if Filename
not in self
.FileList
:
1800 FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_FDF
)
1801 self
.FileList
[Filename
] = FileID
1803 return self
.FileList
[Filename
]
1808 # Load the file if it exists
1810 # @param Filename: Input value for filename of Fdf file
1812 def LoadFdfFile(self
, Filename
):
1817 Filename
= NormPath(Filename
)
1818 Fdf
= FdfParser(Filename
)
1822 # Insert inf file and pcd information
1824 if self
.IsToDatabase
:
1825 (Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
) = \
1826 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
1827 for Index
in range(0, len(Fdf
.Profile
.PcdDict
)):
1829 for Key
in Fdf
.Profile
.PcdDict
.keys():
1833 FileName
= Fdf
.Profile
.PcdFileLineDict
[Key
][0]
1834 StartLine
= Fdf
.Profile
.PcdFileLineDict
[Key
][1]
1835 BelongsToFile
= self
.InsertFile(FileName
)
1836 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1837 for Index
in range(0, len(Fdf
.Profile
.InfList
)):
1838 Model
= MODEL_META_DATA_COMPONENT
1839 Value1
= Fdf
.Profile
.InfList
[Index
]
1841 FileName
= Fdf
.Profile
.InfFileLineList
[Index
][0]
1842 StartLine
= Fdf
.Profile
.InfFileLineList
[Index
][1]
1843 BelongsToFile
= self
.InsertFile(FileName
)
1844 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1848 # This acts like the main() function for the script, unless it is 'import'ed into another
1851 if __name__
== '__main__':