2 # This file is used to parse meta files
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # SPDX-License-Identifier: BSD-2-Clause-Patent
11 from __future__
import absolute_import
12 import Common
.LongFilePathOs
as os
17 import Common
.EdkLogger
as EdkLogger
18 import Common
.GlobalData
as GlobalData
19 import Ecc
.EccGlobalData
as EccGlobalData
20 import Ecc
.EccToolError
as EccToolError
22 from CommonDataClass
.DataClass
import *
23 from Common
.DataType
import *
24 from Common
.StringUtils
import *
25 from Common
.Misc
import GuidStructureStringToGuidString
, CheckPcdDatum
, PathClass
, AnalyzePcdData
26 from Common
.Expression
import *
27 from CommonDataClass
.Exceptions
import *
29 from Ecc
.MetaFileWorkspace
.MetaFileTable
import MetaFileStorage
30 from GenFds
.FdfParser
import FdfParser
31 from Common
.LongFilePathSupport
import OpenLongFilePath
as open
32 from Common
.LongFilePathSupport
import CodecOpenLongFilePath
34 ## A decorator used to parse macro definition
35 def ParseMacro(Parser
):
36 def MacroParser(self
):
37 Match
= GlobalData
.gMacroDefPattern
.match(self
._CurrentLine
)
39 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
43 TokenList
= GetSplitValueList(self
._CurrentLine
[Match
.end(1):], TAB_EQUAL_SPLIT
, 1)
46 EdkLogger
.error('Parser', FORMAT_INVALID
, "No macro name given",
47 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
48 if len(TokenList
) < 2:
52 Name
, Value
= TokenList
53 # Global macros can be only defined via environment variable
54 if Name
in GlobalData
.gGlobalDefines
:
55 EdkLogger
.error('Parser', FORMAT_INVALID
, "%s can only be defined via environment variable" % Name
,
56 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
57 # Only upper case letters, digit and '_' are allowed
58 if not GlobalData
.gMacroNamePattern
.match(Name
):
59 EdkLogger
.error('Parser', FORMAT_INVALID
, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
60 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
62 Value
= ReplaceMacro(Value
, self
._Macros
)
63 self
._ItemType
= MODEL_META_DATA_DEFINE
64 # DEFINE defined macros
65 if Type
== TAB_DSC_DEFINES_DEFINE
:
66 if isinstance(self
, DecParser
):
67 if MODEL_META_DATA_HEADER
in self
._SectionType
:
68 self
._FileLocalMacros
[Name
] = Value
70 for Scope
in self
._Scope
:
71 self
._SectionsMacroDict
.setdefault((Scope
[2], Scope
[0], Scope
[1]), {})[Name
] = Value
72 elif self
._SectionType
== MODEL_META_DATA_HEADER
:
73 self
._FileLocalMacros
[Name
] = Value
75 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
76 if SectionDictKey
not in self
._SectionsMacroDict
:
77 self
._SectionsMacroDict
[SectionDictKey
] = {}
78 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
79 SectionLocalMacros
[Name
] = Value
80 # EDK_GLOBAL defined macros
81 elif not isinstance(self
, DscParser
):
82 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used in .dsc file",
83 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
84 elif self
._SectionType
!= MODEL_META_DATA_HEADER
:
85 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL can only be used under [Defines] section",
86 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
87 elif (Name
in self
._FileLocalMacros
) and (self
._FileLocalMacros
[Name
] != Value
):
88 EdkLogger
.error('Parser', FORMAT_INVALID
, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
89 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
91 self
._ValueList
= [Type
, Name
, Value
]
95 ## Base class of parser
97 # This class is used for derivation purpose. The specific parser for one kind
98 # type file must derive this class and implement some public interfaces.
100 # @param FilePath The path of platform description file
101 # @param FileType The raw data of DSC file
102 # @param Table Database used to retrieve module/package information
103 # @param Macros Macros used for replacement in file
104 # @param Owner Owner ID (for sub-section parsing)
105 # @param From ID from which the data comes (for !INCLUDE directive)
107 class MetaFileParser(object):
108 # data type (file content) for specific file type
111 # Parser objects used to implement singleton
116 # One file, one parser object. This factory method makes sure that there's
117 # only one object constructed for one meta file.
119 # @param Class class object of real AutoGen class
120 # (InfParser, DecParser or DscParser)
121 # @param FilePath The path of meta file
122 # @param *args The specific class related parameters
123 # @param **kwargs The specific class related dict parameters
125 def __new__(Class
, FilePath
, *args
, **kwargs
):
126 if FilePath
in Class
.MetaFiles
:
127 return Class
.MetaFiles
[FilePath
]
129 ParserObject
= super(MetaFileParser
, Class
).__new
__(Class
)
130 Class
.MetaFiles
[FilePath
] = ParserObject
133 ## Constructor of MetaFileParser
135 # Initialize object of MetaFileParser
137 # @param FilePath The path of platform description file
138 # @param FileType The raw data of DSC file
139 # @param Table Database used to retrieve module/package information
140 # @param Macros Macros used for replacement in file
141 # @param Owner Owner ID (for sub-section parsing)
142 # @param From ID from which the data comes (for !INCLUDE directive)
144 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
146 self
._RawTable
= Table
147 self
._FileType
= FileType
148 self
.MetaFile
= FilePath
150 self
._FileLocalMacros
= {}
151 self
._SectionsMacroDict
= {}
153 # for recursive parsing
154 self
._Owner
= [Owner
]
157 # parsr status for parsing
158 self
._ValueList
= ['', '', '', '', '']
161 self
._CurrentLine
= ''
162 self
._SectionType
= MODEL_UNKNOWN
163 self
._SectionName
= ''
164 self
._InSubsection
= False
165 self
._SubsectionType
= MODEL_UNKNOWN
166 self
._SubsectionName
= ''
167 self
._ItemType
= MODEL_UNKNOWN
170 self
._Finished
= False
171 self
._PostProcessed
= False
172 # Different version of meta-file has different way to parse.
174 # UNI object and extra UNI object
176 self
._UniExtraObj
= None
178 ## Store the parsed data in table
179 def _Store(self
, *Args
):
180 return self
._Table
.Insert(*Args
)
182 ## Virtual method for starting parse
184 raise NotImplementedError
186 ## Notify a post-process is needed
187 def DoPostProcess(self
):
188 self
._PostProcessed
= False
190 ## Set parsing complete flag in both class and table
192 self
._Finished
= True
193 ## Do not set end flag when processing included files
195 self
._Table
.SetEndFlag()
197 def _PostProcess(self
):
198 self
._PostProcessed
= True
200 ## Get the parse complete flag
201 def _GetFinished(self
):
202 return self
._Finished
204 ## Set the complete flag
205 def _SetFinished(self
, Value
):
206 self
._Finished
= Value
208 ## Use [] style to query data in table, just for readability
210 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
212 def __getitem__(self
, DataInfo
):
213 if not isinstance(DataInfo
, type(())):
214 DataInfo
= (DataInfo
,)
216 # Parse the file first, if necessary
217 if not self
._Finished
:
218 if self
._RawTable
.IsIntegrity():
219 self
._Finished
= True
221 self
._Table
= self
._RawTable
222 self
._PostProcessed
= False
225 # No specific ARCH or Platform given, use raw data
226 if self
._RawTable
and (len(DataInfo
) == 1 or DataInfo
[1] is None):
227 return self
._RawTable
.Query(*DataInfo
)
229 # Do post-process if necessary
230 if not self
._PostProcessed
:
233 return self
._Table
.Query(*DataInfo
)
235 ## Data parser for the common format in different type of file
237 # The common format in the meatfile is like
242 def _CommonParser(self
):
243 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
244 self
._ValueList
[0:len(TokenList
)] = TokenList
246 ## Data parser for the format in which there's path
248 # Only path can have macro used. So we need to replace them before use.
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 not isinstance(self
, DscParser
):
256 Macros
= self
._Macros
257 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
259 ## Skip unsupported data
261 if self
._SectionName
== TAB_USER_EXTENSIONS
.upper() and self
._CurrentLine
.upper().endswith('.UNI'):
262 if EccGlobalData
.gConfig
.UniCheckHelpInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
263 ExtraUni
= self
._CurrentLine
.strip()
264 ExtraUniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), ExtraUni
)
265 IsModuleUni
= self
.MetaFile
.upper().endswith('.INF')
266 self
._UniExtraObj
= UniParser(ExtraUniFile
, IsExtraUni
=True, IsModuleUni
=IsModuleUni
)
267 self
._UniExtraObj
.Start()
269 EdkLogger
.warn("Parser", "Unrecognized content", File
=self
.MetaFile
,
270 Line
=self
._LineIndex
+ 1, ExtraData
=self
._CurrentLine
);
271 self
._ValueList
[0:1] = [self
._CurrentLine
]
273 ## Section header parser
275 # The section header is always in following format:
277 # [section_name.arch<.platform|module_type>]
279 def _SectionHeaderParser(self
):
281 self
._SectionName
= ''
283 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
286 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
287 # different section should not mix in one section
288 if self
._SectionName
!= '' and self
._SectionName
!= ItemList
[0].upper():
289 EdkLogger
.error('Parser', FORMAT_INVALID
, "Different section names in the same section",
290 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
291 self
._SectionName
= ItemList
[0].upper()
292 if self
._SectionName
in self
.DataType
:
293 self
._SectionType
= self
.DataType
[self
._SectionName
]
295 self
._SectionType
= MODEL_UNKNOWN
296 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
297 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
299 if len(ItemList
) > 1:
300 S1
= ItemList
[1].upper()
304 # S2 may be Platform or ModuleType
305 if len(ItemList
) > 2:
306 S2
= ItemList
[2].upper()
309 self
._Scope
.append([S1
, S2
])
311 # 'COMMON' must not be used with specific ARCHs at the same section
312 if 'COMMON' in ArchList
and len(ArchList
) > 1:
313 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
314 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
315 # If the section information is needed later, it should be stored in database
316 self
._ValueList
[0] = self
._SectionName
318 ## [defines] section parser
320 def _DefineParser(self
):
321 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
322 self
._ValueList
[1:len(TokenList
)] = TokenList
323 if not self
._ValueList
[1]:
324 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
325 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
326 if not self
._ValueList
[2]:
327 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
328 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
330 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
331 Name
, Value
= self
._ValueList
[1], self
._ValueList
[2]
332 # Sometimes, we need to make differences between EDK and EDK2 modules
333 if Name
== 'INF_VERSION':
335 self
._Version
= int(Value
, 0)
337 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid version number",
338 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
339 elif Name
== 'MODULE_UNI_FILE':
340 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
341 if os
.path
.exists(UniFile
):
342 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=True)
345 EdkLogger
.error('Parser', FILE_NOT_FOUND
, "Module UNI file %s is missing." % Value
,
346 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
348 elif Name
== 'PACKAGE_UNI_FILE':
349 UniFile
= os
.path
.join(os
.path
.dirname(self
.MetaFile
), Value
)
350 if os
.path
.exists(UniFile
):
351 self
._UniObj
= UniParser(UniFile
, IsExtraUni
=False, IsModuleUni
=False)
353 if isinstance(self
, InfParser
) and self
._Version
< 0x00010005:
354 # EDK module allows using defines as macros
355 self
._FileLocalMacros
[Name
] = Value
356 self
._Defines
[Name
] = Value
358 ## [BuildOptions] section parser
360 def _BuildOptionParser(self
):
361 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
362 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
363 if len(TokenList2
) == 2:
364 self
._ValueList
[0] = TokenList2
[0] # toolchain family
365 self
._ValueList
[1] = TokenList2
[1] # keys
367 self
._ValueList
[1] = TokenList
[0]
368 if len(TokenList
) == 2 and not isinstance(self
, DscParser
): # value
369 self
._ValueList
[2] = ReplaceMacro(TokenList
[1], self
._Macros
)
371 if self
._ValueList
[1].count('_') != 4:
375 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
376 ExtraData
=self
._CurrentLine
,
378 Line
=self
._LineIndex
+1
381 def _GetMacros(self
):
383 Macros
.update(self
._FileLocalMacros
)
384 Macros
.update(self
._GetApplicableSectionMacro
())
388 ## Get section Macros that are applicable to current line, which may come from other sections
389 ## that share the same name while scope is wider
390 def _GetApplicableSectionMacro(self
):
392 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", self
._Scope
[0][1]),
393 (self
._Scope
[0][0], "COMMON"), (self
._Scope
[0][0], self
._Scope
[0][1])]:
394 if (self
._SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
395 Macros
.update(self
._SectionsMacroDict
[(self
._SectionType
, Scope1
, Scope2
)])
399 Finished
= property(_GetFinished
, _SetFinished
)
400 _Macros
= property(_GetMacros
)
403 ## INF file parser class
405 # @param FilePath The path of platform description file
406 # @param FileType The raw data of DSC file
407 # @param Table Database used to retrieve module/package information
408 # @param Macros Macros used for replacement in file
410 class InfParser(MetaFileParser
):
411 # INF file supported data types (one type per section)
413 TAB_UNKNOWN
.upper() : MODEL_UNKNOWN
,
414 TAB_INF_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
415 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
416 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
417 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
418 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
419 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
420 TAB_PACKAGES
.upper() : MODEL_META_DATA_PACKAGE
,
421 TAB_NMAKE
.upper() : MODEL_META_DATA_NMAKE
,
422 TAB_INF_FIXED_PCD
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
423 TAB_INF_PATCH_PCD
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
424 TAB_INF_FEATURE_PCD
.upper() : MODEL_PCD_FEATURE_FLAG
,
425 TAB_INF_PCD_EX
.upper() : MODEL_PCD_DYNAMIC_EX
,
426 TAB_INF_PCD
.upper() : MODEL_PCD_DYNAMIC
,
427 TAB_SOURCES
.upper() : MODEL_EFI_SOURCE_FILE
,
428 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
429 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
430 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
431 TAB_DEPEX
.upper() : MODEL_EFI_DEPEX
,
432 TAB_BINARIES
.upper() : MODEL_EFI_BINARY_FILE
,
433 TAB_USER_EXTENSIONS
.upper() : MODEL_META_DATA_USER_EXTENSION
436 ## Constructor of InfParser
438 # Initialize object of InfParser
440 # @param FilePath The path of module description file
441 # @param FileType The raw data of DSC file
442 # @param Table Database used to retrieve module/package information
443 # @param Macros Macros used for replacement in file
445 def __init__(self
, FilePath
, FileType
, Table
):
446 # prevent re-initialization
447 if hasattr(self
, "_Table"):
449 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
450 self
.TblFile
= EccGlobalData
.gDb
.TblFile
459 Content
= open(str(self
.MetaFile
), 'r').readlines()
461 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
463 # Insert a record for file
465 Filename
= NormPath(self
.MetaFile
)
466 FileID
= self
.TblFile
.GetFileId(Filename
)
470 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_INF
)
472 # parse the file line by line
473 IsFindBlockComment
= False
475 for Index
in range(0, len(Content
)):
476 if self
._SectionType
in [MODEL_EFI_GUID
,
479 MODEL_PCD_FIXED_AT_BUILD
,
480 MODEL_PCD_PATCHABLE_IN_MODULE
,
481 MODEL_PCD_FEATURE_FLAG
,
482 MODEL_PCD_DYNAMIC_EX
,
484 Line
= Content
[Index
].strip()
485 if Line
.startswith(TAB_SPECIAL_COMMENT
):
486 Usage
+= ' ' + Line
[Line
.find(TAB_SPECIAL_COMMENT
):]
488 elif Line
.startswith(TAB_COMMENT_SPLIT
):
490 elif Line
.find(TAB_COMMENT_SPLIT
) > 0:
491 Usage
+= ' ' + Line
[Line
.find(TAB_COMMENT_SPLIT
):]
492 Line
= Line
[:Line
.find(TAB_COMMENT_SPLIT
)]
494 # skip empty, commented, block commented lines
495 Line
= CleanString(Content
[Index
], AllowCppStyleComment
=True)
498 if Index
+ 1 < len(Content
):
499 NextLine
= CleanString(Content
[Index
+ 1])
502 if Line
.find(DataType
.TAB_COMMENT_EDK_START
) > -1:
503 IsFindBlockComment
= True
505 if Line
.find(DataType
.TAB_COMMENT_EDK_END
) > -1:
506 IsFindBlockComment
= False
508 if IsFindBlockComment
:
511 self
._LineIndex
= Index
512 self
._CurrentLine
= Line
515 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
516 self
._SectionHeaderParser
()
517 # Check invalid sections
518 if self
._Version
< 0x00010005:
519 if self
._SectionType
in [MODEL_META_DATA_BUILD_OPTION
,
520 MODEL_EFI_LIBRARY_CLASS
,
521 MODEL_META_DATA_PACKAGE
,
522 MODEL_PCD_FIXED_AT_BUILD
,
523 MODEL_PCD_PATCHABLE_IN_MODULE
,
524 MODEL_PCD_FEATURE_FLAG
,
525 MODEL_PCD_DYNAMIC_EX
,
530 MODEL_META_DATA_USER_EXTENSION
]:
531 EdkLogger
.error('Parser', FORMAT_INVALID
,
532 "Section [%s] is not allowed in inf file without version" % (self
._SectionName
),
533 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
534 elif self
._SectionType
in [MODEL_EFI_INCLUDE
,
535 MODEL_EFI_LIBRARY_INSTANCE
,
536 MODEL_META_DATA_NMAKE
]:
537 EdkLogger
.error('Parser', FORMAT_INVALID
,
538 "Section [%s] is not allowed in inf file with version 0x%08x" % (self
._SectionName
, self
._Version
),
539 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
541 # merge two lines specified by '\' in section NMAKE
542 elif self
._SectionType
== MODEL_META_DATA_NMAKE
:
545 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
548 if NextLine
[0] == TAB_SECTION_START
and NextLine
[-1] == TAB_SECTION_END
:
549 self
._CurrentLine
= NmakeLine
+ Line
[0:-1]
552 NmakeLine
= NmakeLine
+ ' ' + Line
[0:-1]
555 self
._CurrentLine
= NmakeLine
+ Line
559 self
._ValueList
= ['', '', '']
560 # parse current line, result will be put in self._ValueList
561 self
._SectionParser
[self
._SectionType
](self
)
562 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
566 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
567 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
569 self
._ValueList
[0] = self
._ValueList
[0].replace('/', '\\')
570 Usage
= Usage
.strip()
571 for Arch
, Platform
in self
._Scope
:
572 self
._Store
(self
._SectionType
,
588 if IsFindBlockComment
:
589 EdkLogger
.error("Parser", FORMAT_INVALID
, "Open block comments (starting with /*) are expected to end with */",
593 ## Data parser for the format in which there's path
595 # Only path can have macro used. So we need to replace them before use.
597 def _IncludeParser(self
):
598 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
599 self
._ValueList
[0:len(TokenList
)] = TokenList
600 Macros
= self
._Macros
602 for Index
in range(0, len(self
._ValueList
)):
603 Value
= self
._ValueList
[Index
]
607 self
._ValueList
[Index
] = ReplaceMacro(Value
, Macros
)
609 ## Parse [Sources] section
611 # Only path can have macro used. So we need to replace them before use.
614 def _SourceFileParser(self
):
615 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
616 self
._ValueList
[0:len(TokenList
)] = TokenList
617 Macros
= self
._Macros
618 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
619 if 'COMPONENT_TYPE' in Macros
:
620 if self
._Defines
['COMPONENT_TYPE'].upper() == 'ACPITABLE':
621 self
._ValueList
[0] = GetSplitValueList(self
._ValueList
[0], ' ', 1)[0]
622 if self
._Defines
['BASE_NAME'] == 'Microcode':
624 self
._ValueList
= [ReplaceMacro(Value
, Macros
) for Value
in self
._ValueList
]
626 ## Parse [Binaries] section
628 # Only path can have macro used. So we need to replace them before use.
631 def _BinaryFileParser(self
):
632 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 2)
633 if len(TokenList
) < 2:
634 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type or path specified",
635 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
636 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
638 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file type specified",
639 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
640 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
642 EdkLogger
.error('Parser', FORMAT_INVALID
, "No file path specified",
643 ExtraData
=self
._CurrentLine
+ " (<FileType> | <FilePath> [| <Target>])",
644 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
645 self
._ValueList
[0:len(TokenList
)] = TokenList
646 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
648 ## [nmake] section parser (Edk.x style only)
649 def _NmakeParser(self
):
650 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
651 self
._ValueList
[0:len(TokenList
)] = TokenList
653 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
)
654 # remove self-reference in macro setting
655 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
657 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
659 def _PcdParser(self
):
660 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
661 ValueList
= GetSplitValueList(TokenList
[0], TAB_SPLIT
)
662 if len(ValueList
) != 2:
663 EdkLogger
.error('Parser', FORMAT_INVALID
, "Illegal token space GUID and PCD name format",
664 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
665 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
666 self
._ValueList
[0:1] = ValueList
667 if len(TokenList
) > 1:
668 self
._ValueList
[2] = TokenList
[1]
669 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
670 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
671 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<PcdCName>)",
672 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
674 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
675 if self
._ValueList
[2] != '':
676 InfPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
677 if InfPcdValueList
[0] in ['True', 'true', 'TRUE']:
678 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '1', 1);
679 elif InfPcdValueList
[0] in ['False', 'false', 'FALSE']:
680 self
._ValueList
[2] = TokenList
[1].replace(InfPcdValueList
[0], '0', 1);
682 ## [depex] section parser
684 def _DepexParser(self
):
685 self
._ValueList
[0:1] = [self
._CurrentLine
]
688 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
689 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
690 MODEL_META_DATA_BUILD_OPTION
: MetaFileParser
._BuildOptionParser
,
691 MODEL_EFI_INCLUDE
: _IncludeParser
, # for Edk.x modules
692 MODEL_EFI_LIBRARY_INSTANCE
: MetaFileParser
._CommonParser
, # for Edk.x modules
693 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
694 MODEL_META_DATA_PACKAGE
: MetaFileParser
._PathParser
,
695 MODEL_META_DATA_NMAKE
: _NmakeParser
, # for Edk.x modules
696 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
697 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
698 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
699 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
700 MODEL_PCD_DYNAMIC
: _PcdParser
,
701 MODEL_EFI_SOURCE_FILE
: _SourceFileParser
,
702 MODEL_EFI_GUID
: MetaFileParser
._CommonParser
,
703 MODEL_EFI_PROTOCOL
: MetaFileParser
._CommonParser
,
704 MODEL_EFI_PPI
: MetaFileParser
._CommonParser
,
705 MODEL_EFI_DEPEX
: _DepexParser
,
706 MODEL_EFI_BINARY_FILE
: _BinaryFileParser
,
707 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
710 ## DSC file parser class
712 # @param FilePath The path of platform description file
713 # @param FileType The raw data of DSC file
714 # @param Table Database used to retrieve module/package information
715 # @param Macros Macros used for replacement in file
716 # @param Owner Owner ID (for sub-section parsing)
717 # @param From ID from which the data comes (for !INCLUDE directive)
719 class DscParser(MetaFileParser
):
720 # DSC file supported data types (one type per section)
722 TAB_SKUIDS
.upper() : MODEL_EFI_SKU_ID
,
723 TAB_LIBRARIES
.upper() : MODEL_EFI_LIBRARY_INSTANCE
,
724 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
725 TAB_BUILD_OPTIONS
.upper() : MODEL_META_DATA_BUILD_OPTION
,
726 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
727 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
728 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
729 TAB_PCDS_DYNAMIC_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_DEFAULT
,
730 TAB_PCDS_DYNAMIC_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_HII
,
731 TAB_PCDS_DYNAMIC_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_VPD
,
732 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT
,
733 TAB_PCDS_DYNAMIC_EX_HII_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_HII
,
734 TAB_PCDS_DYNAMIC_EX_VPD_NULL
.upper() : MODEL_PCD_DYNAMIC_EX_VPD
,
735 TAB_COMPONENTS
.upper() : MODEL_META_DATA_COMPONENT
,
736 TAB_DSC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
737 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
738 TAB_DSC_DEFINES_EDKGLOBAL
: MODEL_META_DATA_GLOBAL_DEFINE
,
739 TAB_INCLUDE
.upper() : MODEL_META_DATA_INCLUDE
,
740 TAB_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
741 TAB_IF_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
742 TAB_IF_N_DEF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
,
743 TAB_ELSE_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
,
744 TAB_ELSE
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
745 TAB_END_IF
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
,
746 TAB_ERROR
.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
,
749 # Valid names in define section
756 "PCD_INFO_GENERATION",
757 "SUPPORTED_ARCHITECTURES",
766 "FIX_LOAD_TOP_MEMORY_ADDRESS"
769 SubSectionDefineKeywords
= [
773 SymbolPattern
= ValueExpression
.SymbolPattern
775 ## Constructor of DscParser
777 # Initialize object of DscParser
779 # @param FilePath The path of platform description file
780 # @param FileType The raw data of DSC file
781 # @param Table Database used to retrieve module/package information
782 # @param Macros Macros used for replacement in file
783 # @param Owner Owner ID (for sub-section parsing)
784 # @param From ID from which the data comes (for !INCLUDE directive)
786 def __init__(self
, FilePath
, FileType
, Table
, Owner
=-1, From
=-1):
787 # prevent re-initialization
788 if hasattr(self
, "_Table"):
790 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
, Owner
, From
)
791 self
._Version
= 0x00010005 # Only EDK2 dsc file is supported
792 # to store conditional directive evaluation result
793 self
._DirectiveStack
= []
794 self
._DirectiveEvalStack
= []
797 # Final valid replacable symbols
800 # Map the ID between the original table and new table to track
803 self
._IdMapping
= {-1:-1}
805 self
.TblFile
= EccGlobalData
.gDb
.TblFile
812 Content
= open(str(self
.MetaFile
.Path
), 'r').readlines()
814 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
816 # Insert a record for file
818 Filename
= NormPath(self
.MetaFile
.Path
)
819 FileID
= self
.TblFile
.GetFileId(Filename
)
823 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DSC
)
826 for Index
in range(0, len(Content
)):
827 Line
= CleanString(Content
[Index
])
832 self
._CurrentLine
= Line
833 self
._LineIndex
= Index
834 if self
._InSubsection
and self
._Owner
[-1] == -1:
835 self
._Owner
.append(self
._LastItem
)
838 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
839 self
._SectionType
= MODEL_META_DATA_SECTION_HEADER
841 elif Line
[0] == '}' and self
._InSubsection
:
842 self
._InSubsection
= False
843 self
._SubsectionType
= MODEL_UNKNOWN
844 self
._SubsectionName
= ''
848 elif Line
[0] == TAB_OPTION_START
and Line
[-1] == TAB_OPTION_END
:
849 self
._SubsectionType
= MODEL_META_DATA_SUBSECTION_HEADER
852 self
._DirectiveParser
()
855 if self
._InSubsection
:
856 SectionType
= self
._SubsectionType
858 SectionType
= self
._SectionType
859 self
._ItemType
= SectionType
861 self
._ValueList
= ['', '', '']
862 self
._SectionParser
[SectionType
](self
)
863 if self
._ValueList
is None:
866 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
867 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
869 for Arch
, ModuleType
in self
._Scope
:
870 self
._LastItem
= self
._Store
(
887 if self
._DirectiveStack
:
888 Type
, Line
, Text
= self
._DirectiveStack
[-1]
889 EdkLogger
.error('Parser', FORMAT_INVALID
, "No matching '!endif' found",
890 ExtraData
=Text
, File
=self
.MetaFile
, Line
=Line
)
893 ## <subsection_header> parser
894 def _SubsectionHeaderParser(self
):
895 self
._SubsectionName
= self
._CurrentLine
[1:-1].upper()
896 if self
._SubsectionName
in self
.DataType
:
897 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
899 self
._SubsectionType
= MODEL_UNKNOWN
900 EdkLogger
.warn("Parser", "Unrecognized sub-section", File
=self
.MetaFile
,
901 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
902 self
._ValueList
[0] = self
._SubsectionName
904 ## Directive statement parser
905 def _DirectiveParser(self
):
906 self
._ValueList
= ['', '', '']
907 TokenList
= GetSplitValueList(self
._CurrentLine
, ' ', 1)
908 self
._ValueList
[0:len(TokenList
)] = TokenList
911 DirectiveName
= self
._ValueList
[0].upper()
912 if DirectiveName
not in self
.DataType
:
913 EdkLogger
.error("Parser", FORMAT_INVALID
, "Unknown directive [%s]" % DirectiveName
,
914 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
915 if DirectiveName
in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self
._ValueList
[1] == '':
916 EdkLogger
.error("Parser", FORMAT_INVALID
, "Missing expression",
917 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
918 ExtraData
=self
._CurrentLine
)
920 ItemType
= self
.DataType
[DirectiveName
]
921 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
922 # Remove all directives between !if and !endif, including themselves
923 while self
._DirectiveStack
:
924 # Remove any !else or !elseif
925 DirectiveInfo
= self
._DirectiveStack
.pop()
926 if DirectiveInfo
[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
927 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
928 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
931 EdkLogger
.error("Parser", FORMAT_INVALID
, "Redundant '!endif'",
932 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
933 ExtraData
=self
._CurrentLine
)
934 elif ItemType
!= MODEL_META_DATA_INCLUDE
:
935 # Break if there's a !else is followed by a !elseif
936 if ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
and \
937 self
._DirectiveStack
and \
938 self
._DirectiveStack
[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
939 EdkLogger
.error("Parser", FORMAT_INVALID
, "'!elseif' after '!else'",
940 File
=self
.MetaFile
, Line
=self
._LineIndex
+1,
941 ExtraData
=self
._CurrentLine
)
942 self
._DirectiveStack
.append((ItemType
, self
._LineIndex
+1, self
._CurrentLine
))
944 EdkLogger
.error('Parser', FORMAT_INVALID
,
945 "No '!include' allowed in included file",
946 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
,
947 Line
=self
._LineIndex
+1)
950 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
951 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
953 self
._LastItem
= self
._Store
(
970 ## [defines] section parser
972 def _DefineParser(self
):
973 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
974 self
._ValueList
[1:len(TokenList
)] = TokenList
977 if not self
._ValueList
[1]:
978 EdkLogger
.error('Parser', FORMAT_INVALID
, "No name specified",
979 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
980 if not self
._ValueList
[2]:
981 EdkLogger
.error('Parser', FORMAT_INVALID
, "No value specified",
982 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
983 if (not self
._ValueList
[1] in self
.DefineKeywords
and
984 (self
._InSubsection
and self
._ValueList
[1] not in self
.SubSectionDefineKeywords
)):
985 EdkLogger
.error('Parser', FORMAT_INVALID
,
986 "Unknown keyword found: %s. "
987 "If this is a macro you must "
988 "add it as a DEFINE in the DSC" % self
._ValueList
[1],
989 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
990 self
._Defines
[self
._ValueList
[1]] = self
._ValueList
[2]
991 self
._ItemType
= self
.DataType
[TAB_DSC_DEFINES
.upper()]
994 def _SkuIdParser(self
):
995 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
996 if len(TokenList
) != 2:
997 EdkLogger
.error('Parser', FORMAT_INVALID
, "Correct format is '<Integer>|<UiName>'",
998 ExtraData
=self
._CurrentLine
, File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
999 self
._ValueList
[0:len(TokenList
)] = TokenList
1001 ## Parse Edk style of library modules
1002 def _LibraryInstanceParser(self
):
1003 self
._ValueList
[0] = self
._CurrentLine
1005 ## PCD sections parser
1007 # [PcdsFixedAtBuild]
1008 # [PcdsPatchableInModule]
1011 # [PcdsDynamicExDefault]
1012 # [PcdsDynamicExVpd]
1013 # [PcdsDynamicExHii]
1015 # [PcdsDynamicDefault]
1020 def _PcdParser(self
):
1021 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1022 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1023 if len(TokenList
) == 2:
1024 self
._ValueList
[2] = TokenList
[1]
1025 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1026 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1027 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1028 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1029 if self
._ValueList
[2] == '':
1030 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD value given",
1031 ExtraData
=self
._CurrentLine
+ " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1032 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1033 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1034 DscPcdValueList
= GetSplitValueList(TokenList
[1], TAB_VALUE_SPLIT
, 1)
1035 if DscPcdValueList
[0] in ['True', 'true', 'TRUE']:
1036 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '1', 1);
1037 elif DscPcdValueList
[0] in ['False', 'false', 'FALSE']:
1038 self
._ValueList
[2] = TokenList
[1].replace(DscPcdValueList
[0], '0', 1);
1040 ## [components] section parser
1042 def _ComponentParser(self
):
1043 if self
._CurrentLine
[-1] == '{':
1044 self
._ValueList
[0] = self
._CurrentLine
[0:-1].strip()
1045 self
._InSubsection
= True
1047 self
._ValueList
[0] = self
._CurrentLine
1049 ## [LibraryClasses] section
1051 def _LibraryClassParser(self
):
1052 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
)
1053 if len(TokenList
) < 2:
1054 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class or instance specified",
1055 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1056 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1057 if TokenList
[0] == '':
1058 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library class specified",
1059 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1060 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1061 if TokenList
[1] == '':
1062 EdkLogger
.error('Parser', FORMAT_INVALID
, "No library instance specified",
1063 ExtraData
=self
._CurrentLine
+ " (<LibraryClassName>|<LibraryInstancePath>)",
1064 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1066 self
._ValueList
[0:len(TokenList
)] = TokenList
1069 ## [BuildOptions] section parser
1071 def _BuildOptionParser(self
):
1072 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1073 TokenList2
= GetSplitValueList(TokenList
[0], ':', 1)
1074 if len(TokenList2
) == 2:
1075 self
._ValueList
[0] = TokenList2
[0] # toolchain family
1076 self
._ValueList
[1] = TokenList2
[1] # keys
1078 self
._ValueList
[1] = TokenList
[0]
1079 if len(TokenList
) == 2: # value
1080 self
._ValueList
[2] = TokenList
[1]
1082 if self
._ValueList
[1].count('_') != 4:
1086 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self
._ValueList
[1],
1087 ExtraData
=self
._CurrentLine
,
1089 Line
=self
._LineIndex
+1
1092 ## Override parent's method since we'll do all macro replacements in parser
1093 def _GetMacros(self
):
1094 Macros
= dict( [('ARCH', 'IA32'), ('FAMILY', TAB_COMPILER_MSFT
), ('TOOL_CHAIN_TAG', 'VS2008x86'), ('TARGET', 'DEBUG')])
1095 Macros
.update(self
._FileLocalMacros
)
1096 Macros
.update(self
._GetApplicableSectionMacro
())
1097 Macros
.update(GlobalData
.gEdkGlobal
)
1098 Macros
.update(GlobalData
.gPlatformDefines
)
1099 Macros
.update(GlobalData
.gCommandLineDefines
)
1100 # PCD cannot be referenced in macro definition
1101 if self
._ItemType
not in [MODEL_META_DATA_DEFINE
, MODEL_META_DATA_GLOBAL_DEFINE
]:
1102 Macros
.update(self
._Symbols
)
1105 def _PostProcess(self
):
1107 MODEL_META_DATA_SECTION_HEADER
: self
.__ProcessSectionHeader
,
1108 MODEL_META_DATA_SUBSECTION_HEADER
: self
.__ProcessSubsectionHeader
,
1109 MODEL_META_DATA_HEADER
: self
.__ProcessDefine
,
1110 MODEL_META_DATA_DEFINE
: self
.__ProcessDefine
,
1111 MODEL_META_DATA_GLOBAL_DEFINE
: self
.__ProcessDefine
,
1112 MODEL_META_DATA_INCLUDE
: self
.__ProcessDirective
,
1113 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
: self
.__ProcessDirective
,
1114 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
: self
.__ProcessDirective
,
1115 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
: self
.__ProcessDirective
,
1116 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
: self
.__ProcessDirective
,
1117 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
: self
.__ProcessDirective
,
1118 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
: self
.__ProcessDirective
,
1119 MODEL_EFI_SKU_ID
: self
.__ProcessSkuId
,
1120 MODEL_EFI_LIBRARY_INSTANCE
: self
.__ProcessLibraryInstance
,
1121 MODEL_EFI_LIBRARY_CLASS
: self
.__ProcessLibraryClass
,
1122 MODEL_PCD_FIXED_AT_BUILD
: self
.__ProcessPcd
,
1123 MODEL_PCD_PATCHABLE_IN_MODULE
: self
.__ProcessPcd
,
1124 MODEL_PCD_FEATURE_FLAG
: self
.__ProcessPcd
,
1125 MODEL_PCD_DYNAMIC_DEFAULT
: self
.__ProcessPcd
,
1126 MODEL_PCD_DYNAMIC_HII
: self
.__ProcessPcd
,
1127 MODEL_PCD_DYNAMIC_VPD
: self
.__ProcessPcd
,
1128 MODEL_PCD_DYNAMIC_EX_DEFAULT
: self
.__ProcessPcd
,
1129 MODEL_PCD_DYNAMIC_EX_HII
: self
.__ProcessPcd
,
1130 MODEL_PCD_DYNAMIC_EX_VPD
: self
.__ProcessPcd
,
1131 MODEL_META_DATA_COMPONENT
: self
.__ProcessComponent
,
1132 MODEL_META_DATA_BUILD_OPTION
: self
.__ProcessBuildOption
,
1133 MODEL_UNKNOWN
: self
._Skip
,
1134 MODEL_META_DATA_USER_EXTENSION
: self
._Skip
,
1135 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR
: self
._Skip
,
1138 self
._RawTable
= self
._Table
1139 self
._Table
= MetaFileStorage(self
._RawTable
.Cur
, self
.MetaFile
, MODEL_FILE_DSC
, True)
1140 self
._DirectiveStack
= []
1141 self
._DirectiveEvalStack
= []
1142 self
._FileWithError
= self
.MetaFile
1143 self
._FileLocalMacros
= {}
1144 self
._SectionsMacroDict
= {}
1145 GlobalData
.gPlatformDefines
= {}
1147 # Get all macro and PCD which has straitforward value
1148 self
.__RetrievePcdValue
()
1149 self
._Content
= self
._RawTable
.GetAll()
1150 self
._ContentIndex
= 0
1151 while self
._ContentIndex
< len(self
._Content
) :
1152 Id
, self
._ItemType
, V1
, V2
, V3
, S1
, S2
, Owner
, BelongsToFile
, self
._From
, \
1153 LineStart
, ColStart
, LineEnd
, ColEnd
, Enabled
= self
._Content
[self
._ContentIndex
]
1156 self
._FileWithError
= self
.MetaFile
1158 self
._ContentIndex
+= 1
1160 self
._Scope
= [[S1
, S2
]]
1161 self
._LineIndex
= LineStart
- 1
1162 self
._ValueList
= [V1
, V2
, V3
]
1165 Processer
[self
._ItemType
]()
1166 except EvaluationException
as Excpt
:
1168 # Only catch expression evaluation error here. We need to report
1169 # the precise number of line on which the error occurred
1172 # EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1173 # File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1174 # Line=self._LineIndex+1)
1175 except MacroException
as Excpt
:
1176 EdkLogger
.error('Parser', FORMAT_INVALID
, str(Excpt
),
1177 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1178 Line
=self
._LineIndex
+1)
1180 if self
._ValueList
is None:
1183 NewOwner
= self
._IdMapping
.get(Owner
, -1)
1184 self
._Enabled
= int((not self
._DirectiveEvalStack
) or (False not in self
._DirectiveEvalStack
))
1185 self
._LastItem
= self
._Store
(
1201 self
._IdMapping
[Id
] = self
._LastItem
1203 RecordList
= self
._Table
.GetAll()
1205 self
._RawTable
.Drop()
1207 for Record
in RecordList
:
1208 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])
1209 GlobalData
.gPlatformDefines
.update(self
._FileLocalMacros
)
1210 self
._PostProcessed
= True
1211 self
._Content
= None
1213 def __ProcessSectionHeader(self
):
1214 self
._SectionName
= self
._ValueList
[0]
1215 if self
._SectionName
in self
.DataType
:
1216 self
._SectionType
= self
.DataType
[self
._SectionName
]
1218 self
._SectionType
= MODEL_UNKNOWN
1220 def __ProcessSubsectionHeader(self
):
1221 self
._SubsectionName
= self
._ValueList
[0]
1222 if self
._SubsectionName
in self
.DataType
:
1223 self
._SubsectionType
= self
.DataType
[self
._SubsectionName
]
1225 self
._SubsectionType
= MODEL_UNKNOWN
1227 def __RetrievePcdValue(self
):
1228 Records
= self
._RawTable
.Query(MODEL_PCD_FEATURE_FLAG
, BelongsToItem
=-1.0)
1229 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1230 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1231 # Only use PCD whose value is straitforward (no macro and PCD)
1232 if self
.SymbolPattern
.findall(Value
):
1234 Name
= TokenSpaceGuid
+ '.' + PcdName
1235 # Don't use PCD with different values.
1236 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1237 self
._Symbols
.pop(Name
)
1239 self
._Symbols
[Name
] = Value
1241 Records
= self
._RawTable
.Query(MODEL_PCD_FIXED_AT_BUILD
, BelongsToItem
=-1.0)
1242 for TokenSpaceGuid
, PcdName
, Value
, Dummy2
, Dummy3
, ID
, Line
in Records
:
1243 Value
, DatumType
, MaxDatumSize
= AnalyzePcdData(Value
)
1244 # Only use PCD whose value is straitforward (no macro and PCD)
1245 if self
.SymbolPattern
.findall(Value
):
1247 Name
= TokenSpaceGuid
+'.'+PcdName
1248 # Don't use PCD with different values.
1249 if Name
in self
._Symbols
and self
._Symbols
[Name
] != Value
:
1250 self
._Symbols
.pop(Name
)
1252 self
._Symbols
[Name
] = Value
1254 def __ProcessDefine(self
):
1255 if not self
._Enabled
:
1258 Type
, Name
, Value
= self
._ValueList
1259 Value
= ReplaceMacro(Value
, self
._Macros
, False)
1260 if self
._ItemType
== MODEL_META_DATA_DEFINE
:
1261 if self
._SectionType
== MODEL_META_DATA_HEADER
:
1262 self
._FileLocalMacros
[Name
] = Value
1264 SectionDictKey
= self
._SectionType
, self
._Scope
[0][0], self
._Scope
[0][1]
1265 if SectionDictKey
not in self
._SectionsMacroDict
:
1266 self
._SectionsMacroDict
[SectionDictKey
] = {}
1267 SectionLocalMacros
= self
._SectionsMacroDict
[SectionDictKey
]
1268 SectionLocalMacros
[Name
] = Value
1269 elif self
._ItemType
== MODEL_META_DATA_GLOBAL_DEFINE
:
1270 GlobalData
.gEdkGlobal
[Name
] = Value
1273 # Keyword in [Defines] section can be used as Macros
1275 if (self
._ItemType
== MODEL_META_DATA_HEADER
) and (self
._SectionType
== MODEL_META_DATA_HEADER
):
1276 self
._FileLocalMacros
[Name
] = Value
1278 self
._ValueList
= [Type
, Name
, Value
]
1280 def __ProcessDirective(self
):
1282 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1283 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
]:
1284 Macros
= self
._Macros
1285 Macros
.update(GlobalData
.gGlobalDefines
)
1287 Result
= ValueExpression(self
._ValueList
[1], Macros
)()
1288 except SymbolNotFound
as Exc
:
1289 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1291 except WrnExpression
as Excpt
:
1293 # Catch expression evaluation warning here. We need to report
1294 # the precise number of line and return the evaluation result
1296 EdkLogger
.warn('Parser', "Suspicious expression: %s" % str(Excpt
),
1297 File
=self
._FileWithError
, ExtraData
=' '.join(self
._ValueList
),
1298 Line
=self
._LineIndex
+1)
1299 Result
= Excpt
.result
1300 except BadExpression
as Exc
:
1301 EdkLogger
.debug(EdkLogger
.DEBUG_5
, str(Exc
), self
._ValueList
[1])
1304 if self
._ItemType
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1305 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1306 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1307 self
._DirectiveStack
.append(self
._ItemType
)
1308 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
:
1309 Result
= bool(Result
)
1311 Macro
= self
._ValueList
[1]
1312 Macro
= Macro
[2:-1] if (Macro
.startswith("$(") and Macro
.endswith(")")) else Macro
1313 Result
= Macro
in self
._Macros
1314 if self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
:
1316 self
._DirectiveEvalStack
.append(Result
)
1317 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF
:
1318 self
._DirectiveStack
.append(self
._ItemType
)
1319 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1320 self
._DirectiveEvalStack
.append(bool(Result
))
1321 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
:
1322 self
._DirectiveStack
[-1] = self
._ItemType
1323 self
._DirectiveEvalStack
[-1] = not self
._DirectiveEvalStack
[-1]
1324 elif self
._ItemType
== MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF
:
1325 # Back to the nearest !if/!ifdef/!ifndef
1326 while self
._DirectiveStack
:
1327 self
._DirectiveEvalStack
.pop()
1328 Directive
= self
._DirectiveStack
.pop()
1329 if Directive
in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF
,
1330 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF
,
1331 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE
,
1332 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF
]:
1334 elif self
._ItemType
== MODEL_META_DATA_INCLUDE
:
1335 # The included file must be relative to workspace or same directory as DSC file
1336 __IncludeMacros
= {}
1338 # Allow using system environment variables in path after !include
1340 __IncludeMacros
['WORKSPACE'] = GlobalData
.gGlobalDefines
['WORKSPACE']
1343 # Allow using MACROs comes from [Defines] section to keep compatible.
1345 __IncludeMacros
.update(self
._Macros
)
1347 IncludedFile
= NormPath(ReplaceMacro(self
._ValueList
[1], __IncludeMacros
, RaiseError
=True))
1349 # First search the include file under the same directory as DSC file
1351 IncludedFile1
= PathClass(IncludedFile
, self
.MetaFile
.Dir
)
1352 ErrorCode
, ErrorInfo1
= IncludedFile1
.Validate()
1355 # Also search file under the WORKSPACE directory
1357 IncludedFile1
= PathClass(IncludedFile
, GlobalData
.gWorkspace
)
1358 ErrorCode
, ErrorInfo2
= IncludedFile1
.Validate()
1360 EdkLogger
.error('parser', ErrorCode
, File
=self
._FileWithError
,
1361 Line
=self
._LineIndex
+1, ExtraData
=ErrorInfo1
+ "\n"+ ErrorInfo2
)
1363 self
._FileWithError
= IncludedFile1
1365 IncludedFileTable
= MetaFileStorage(self
._Table
.Cur
, IncludedFile1
, MODEL_FILE_DSC
, True)
1366 Owner
= self
._Content
[self
._ContentIndex
-1][0]
1367 Parser
= DscParser(IncludedFile1
, self
._FileType
, IncludedFileTable
,
1368 Owner
=Owner
, From
=Owner
)
1370 # set the parser status with current status
1371 Parser
._SectionName
= self
._SectionName
1372 Parser
._SectionType
= self
._SectionType
1373 Parser
._Scope
= self
._Scope
1374 Parser
._Enabled
= self
._Enabled
1375 # Parse the included file
1378 # update current status with sub-parser's status
1379 self
._SectionName
= Parser
._SectionName
1380 self
._SectionType
= Parser
._SectionType
1381 self
._Scope
= Parser
._Scope
1382 self
._Enabled
= Parser
._Enabled
1384 # Insert all records in the table for the included file into dsc file table
1385 Records
= IncludedFileTable
.GetAll()
1387 self
._Content
[self
._ContentIndex
:self
._ContentIndex
] = Records
1388 self
._Content
.pop(self
._ContentIndex
-1)
1389 self
._ValueList
= None
1390 self
._ContentIndex
-= 1
1392 def __ProcessSkuId(self
):
1393 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=True)
1394 for Value
in self
._ValueList
]
1396 def __ProcessLibraryInstance(self
):
1397 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
) for Value
in self
._ValueList
]
1399 def __ProcessLibraryClass(self
):
1400 self
._ValueList
[1] = ReplaceMacro(self
._ValueList
[1], self
._Macros
, RaiseError
=True)
1402 def __ProcessPcd(self
):
1403 ValueList
= GetSplitValueList(self
._ValueList
[2])
1405 # PCD value can be an expression
1407 if len(ValueList
) > 1 and ValueList
[1] == TAB_VOID
:
1408 PcdValue
= ValueList
[0]
1410 ValueList
[0] = ValueExpression(PcdValue
, self
._Macros
)(True)
1411 except WrnExpression
as Value
:
1412 ValueList
[0] = Value
.result
1414 PcdValue
= ValueList
[-1]
1416 ValueList
[-1] = ValueExpression(PcdValue
, self
._Macros
)(True)
1417 except WrnExpression
as Value
:
1418 ValueList
[-1] = Value
.result
1420 if ValueList
[-1] == 'True':
1422 if ValueList
[-1] == 'False':
1425 self
._ValueList
[2] = '|'.join(ValueList
)
1427 def __ProcessComponent(self
):
1428 self
._ValueList
[0] = ReplaceMacro(self
._ValueList
[0], self
._Macros
)
1430 def __ProcessBuildOption(self
):
1431 self
._ValueList
= [ReplaceMacro(Value
, self
._Macros
, RaiseError
=False)
1432 for Value
in self
._ValueList
]
1435 MODEL_META_DATA_HEADER
: _DefineParser
,
1436 MODEL_EFI_SKU_ID
: _SkuIdParser
,
1437 MODEL_EFI_LIBRARY_INSTANCE
: _LibraryInstanceParser
,
1438 MODEL_EFI_LIBRARY_CLASS
: _LibraryClassParser
,
1439 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1440 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1441 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1442 MODEL_PCD_DYNAMIC_DEFAULT
: _PcdParser
,
1443 MODEL_PCD_DYNAMIC_HII
: _PcdParser
,
1444 MODEL_PCD_DYNAMIC_VPD
: _PcdParser
,
1445 MODEL_PCD_DYNAMIC_EX_DEFAULT
: _PcdParser
,
1446 MODEL_PCD_DYNAMIC_EX_HII
: _PcdParser
,
1447 MODEL_PCD_DYNAMIC_EX_VPD
: _PcdParser
,
1448 MODEL_META_DATA_COMPONENT
: _ComponentParser
,
1449 MODEL_META_DATA_BUILD_OPTION
: _BuildOptionParser
,
1450 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1451 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1452 MODEL_META_DATA_SECTION_HEADER
: MetaFileParser
._SectionHeaderParser
,
1453 MODEL_META_DATA_SUBSECTION_HEADER
: _SubsectionHeaderParser
,
1456 _Macros
= property(_GetMacros
)
1458 ## DEC file parser class
1460 # @param FilePath The path of platform description file
1461 # @param FileType The raw data of DSC file
1462 # @param Table Database used to retrieve module/package information
1463 # @param Macros Macros used for replacement in file
1465 class DecParser(MetaFileParser
):
1466 # DEC file supported data types (one type per section)
1468 TAB_DEC_DEFINES
.upper() : MODEL_META_DATA_HEADER
,
1469 TAB_DSC_DEFINES_DEFINE
: MODEL_META_DATA_DEFINE
,
1470 TAB_INCLUDES
.upper() : MODEL_EFI_INCLUDE
,
1471 TAB_LIBRARY_CLASSES
.upper() : MODEL_EFI_LIBRARY_CLASS
,
1472 TAB_GUIDS
.upper() : MODEL_EFI_GUID
,
1473 TAB_PPIS
.upper() : MODEL_EFI_PPI
,
1474 TAB_PROTOCOLS
.upper() : MODEL_EFI_PROTOCOL
,
1475 TAB_PCDS_FIXED_AT_BUILD_NULL
.upper() : MODEL_PCD_FIXED_AT_BUILD
,
1476 TAB_PCDS_PATCHABLE_IN_MODULE_NULL
.upper() : MODEL_PCD_PATCHABLE_IN_MODULE
,
1477 TAB_PCDS_FEATURE_FLAG_NULL
.upper() : MODEL_PCD_FEATURE_FLAG
,
1478 TAB_PCDS_DYNAMIC_NULL
.upper() : MODEL_PCD_DYNAMIC
,
1479 TAB_PCDS_DYNAMIC_EX_NULL
.upper() : MODEL_PCD_DYNAMIC_EX
,
1482 ## Constructor of DecParser
1484 # Initialize object of DecParser
1486 # @param FilePath The path of platform description file
1487 # @param FileType The raw data of DSC file
1488 # @param Table Database used to retrieve module/package information
1489 # @param Macros Macros used for replacement in file
1491 def __init__(self
, FilePath
, FileType
, Table
):
1492 # prevent re-initialization
1493 if hasattr(self
, "_Table"):
1495 MetaFileParser
.__init
__(self
, FilePath
, FileType
, Table
)
1497 self
._Version
= 0x00010005 # Only EDK2 dec file is supported
1498 self
.TblFile
= EccGlobalData
.gDb
.TblFile
1505 Content
= open(str(self
.MetaFile
), 'r').readlines()
1507 EdkLogger
.error("Parser", FILE_READ_FAILURE
, ExtraData
=self
.MetaFile
)
1510 # Insert a record for file
1512 Filename
= NormPath(self
.MetaFile
)
1513 FileID
= self
.TblFile
.GetFileId(Filename
)
1515 self
.FileID
= FileID
1517 self
.FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_DEC
)
1519 for Index
in range(0, len(Content
)):
1520 Line
, Comment
= CleanString2(Content
[Index
])
1521 self
._CurrentLine
= Line
1522 self
._LineIndex
= Index
1524 # save comment for later use
1526 self
._Comments
.append((Comment
, self
._LineIndex
+1))
1532 if Line
[0] == TAB_SECTION_START
and Line
[-1] == TAB_SECTION_END
:
1533 self
._SectionHeaderParser
()
1536 elif len(self
._SectionType
) == 0:
1541 self
._ValueList
= ['', '', '']
1542 self
._SectionParser
[self
._SectionType
[0]](self
)
1543 if self
._ValueList
is None or self
._ItemType
== MODEL_META_DATA_DEFINE
:
1549 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1550 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1552 for Arch
, ModuleType
, Type
in self
._Scope
:
1553 self
._LastItem
= self
._Store
(
1568 for Comment
, LineNo
in self
._Comments
:
1570 MODEL_META_DATA_COMMENT
,
1587 def _GetApplicableSectionMacro(self
):
1589 for S1
, S2
, SectionType
in self
._Scope
:
1590 for Scope1
, Scope2
in [("COMMON", "COMMON"), ("COMMON", S2
), (S1
, "COMMON"), (S1
, S2
)]:
1591 if (SectionType
, Scope1
, Scope2
) in self
._SectionsMacroDict
:
1592 Macros
.update(self
._SectionsMacroDict
[(SectionType
, Scope1
, Scope2
)])
1595 ## Section header parser
1597 # The section header is always in following format:
1599 # [section_name.arch<.platform|module_type>]
1601 def _SectionHeaderParser(self
):
1603 self
._SectionName
= ''
1604 self
._SectionType
= []
1606 for Item
in GetSplitValueList(self
._CurrentLine
[1:-1], TAB_COMMA_SPLIT
):
1609 ItemList
= GetSplitValueList(Item
, TAB_SPLIT
)
1611 # different types of PCD are permissible in one section
1612 self
._SectionName
= ItemList
[0].upper()
1613 if self
._SectionName
in self
.DataType
:
1614 if self
.DataType
[self
._SectionName
] not in self
._SectionType
:
1615 self
._SectionType
.append(self
.DataType
[self
._SectionName
])
1617 EdkLogger
.warn("Parser", "Unrecognized section", File
=self
.MetaFile
,
1618 Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1621 if MODEL_PCD_FEATURE_FLAG
in self
._SectionType
and len(self
._SectionType
) > 1:
1625 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL
,
1627 Line
=self
._LineIndex
+1,
1628 ExtraData
=self
._CurrentLine
1631 if len(ItemList
) > 1:
1632 S1
= ItemList
[1].upper()
1636 # S2 may be Platform or ModuleType
1637 if len(ItemList
) > 2:
1638 S2
= ItemList
[2].upper()
1641 if [S1
, S2
, self
.DataType
[self
._SectionName
]] not in self
._Scope
:
1642 self
._Scope
.append([S1
, S2
, self
.DataType
[self
._SectionName
]])
1644 # 'COMMON' must not be used with specific ARCHs at the same section
1645 if 'COMMON' in ArchList
and len(ArchList
) > 1:
1646 EdkLogger
.error('Parser', FORMAT_INVALID
, "'common' ARCH must not be used with specific ARCHs",
1647 File
=self
.MetaFile
, Line
=self
._LineIndex
+1, ExtraData
=self
._CurrentLine
)
1649 ## [guids], [ppis] and [protocols] section parser
1651 def _GuidParser(self
):
1652 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_EQUAL_SPLIT
, 1)
1653 if len(TokenList
) < 2:
1654 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name or value specified",
1655 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1656 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1657 if TokenList
[0] == '':
1658 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID name specified",
1659 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1660 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1661 if TokenList
[1] == '':
1662 EdkLogger
.error('Parser', FORMAT_INVALID
, "No GUID value specified",
1663 ExtraData
=self
._CurrentLine
+ " (<CName> = <GuidValueInCFormat>)",
1664 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1665 if TokenList
[1][0] != '{' or TokenList
[1][-1] != '}' or GuidStructureStringToGuidString(TokenList
[1]) == '':
1666 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1667 ExtraData
=self
._CurrentLine
+ \
1668 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1669 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1670 self
._ValueList
[0] = TokenList
[0]
1671 #Parse the Guid value format
1672 GuidValueList
= TokenList
[1].strip(' {}').split(',')
1675 if len(GuidValueList
) == 11:
1676 for GuidValue
in GuidValueList
:
1677 GuidValue
= GuidValue
.strip()
1678 if GuidValue
.startswith('0x') or GuidValue
.startswith('0X'):
1679 HexList
.append('0x' + str(GuidValue
[2:]))
1683 if GuidValue
.startswith('{'):
1684 GuidValue
= GuidValue
.lstrip(' {')
1685 HexList
.append('0x' + str(GuidValue
[2:]))
1687 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])
1689 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid GUID value format",
1690 ExtraData
=self
._CurrentLine
+ \
1691 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1692 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1693 self
._ValueList
[0] = ''
1695 ## PCD sections parser
1697 # [PcdsFixedAtBuild]
1698 # [PcdsPatchableInModule]
1704 def _PcdParser(self
):
1705 TokenList
= GetSplitValueList(self
._CurrentLine
, TAB_VALUE_SPLIT
, 1)
1706 self
._ValueList
[0:1] = GetSplitValueList(TokenList
[0], TAB_SPLIT
)
1707 # check PCD information
1708 if self
._ValueList
[0] == '' or self
._ValueList
[1] == '':
1709 EdkLogger
.error('Parser', FORMAT_INVALID
, "No token space GUID or PCD name specified",
1710 ExtraData
=self
._CurrentLine
+ \
1711 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1712 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1713 # check PCD datum information
1714 if len(TokenList
) < 2 or TokenList
[1] == '':
1715 EdkLogger
.error('Parser', FORMAT_INVALID
, "No PCD Datum information given",
1716 ExtraData
=self
._CurrentLine
+ \
1717 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1718 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1721 ValueRe
= re
.compile(r
'^\s*L?\".*\|.*\"')
1722 PtrValue
= ValueRe
.findall(TokenList
[1])
1724 # Has VOID* type string, may contain "|" character in the string.
1725 if len(PtrValue
) != 0:
1726 ptrValueList
= re
.sub(ValueRe
, '', TokenList
[1])
1727 ValueList
= GetSplitValueList(ptrValueList
)
1728 ValueList
[0] = PtrValue
[0]
1730 ValueList
= GetSplitValueList(TokenList
[1])
1733 # check if there's enough datum information given
1734 if len(ValueList
) != 3:
1735 EdkLogger
.error('Parser', FORMAT_INVALID
, "Invalid PCD Datum information given",
1736 ExtraData
=self
._CurrentLine
+ \
1737 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1738 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1739 # check default value
1740 if ValueList
[0] == '':
1741 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DefaultValue in PCD Datum information",
1742 ExtraData
=self
._CurrentLine
+ \
1743 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1744 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1746 if ValueList
[1] == '':
1747 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing DatumType in PCD Datum information",
1748 ExtraData
=self
._CurrentLine
+ \
1749 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1750 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1751 # check token of the PCD
1752 if ValueList
[2] == '':
1753 EdkLogger
.error('Parser', FORMAT_INVALID
, "Missing Token in PCD Datum information",
1754 ExtraData
=self
._CurrentLine
+ \
1755 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
1756 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1757 # check format of default value against the datum type
1758 IsValid
, Cause
= CheckPcdDatum(ValueList
[1], ValueList
[0])
1760 EdkLogger
.error('Parser', FORMAT_INVALID
, Cause
, ExtraData
=self
._CurrentLine
,
1761 File
=self
.MetaFile
, Line
=self
._LineIndex
+1)
1763 if EccGlobalData
.gConfig
.UniCheckPCDInfo
== '1' or EccGlobalData
.gConfig
.UniCheckAll
== '1' or EccGlobalData
.gConfig
.CheckAll
== '1':
1764 # check Description, Prompt information
1765 PatternDesc
= re
.compile('##\s*([\x21-\x7E\s]*)', re
.S
)
1766 PatternPrompt
= re
.compile('#\s+@Prompt\s+([\x21-\x7E\s]*)', re
.S
)
1769 # check @ValidRange, @ValidList and @Expression format valid
1770 ErrorCodeValid
= '0x0 <= %s <= 0xFFFFFFFF'
1771 PatternValidRangeIn
= '(NOT)?\s*(\d+\s*-\s*\d+|0[xX][a-fA-F0-9]+\s*-\s*0[xX][a-fA-F0-9]+|LT\s*\d+|LT\s*0[xX][a-fA-F0-9]+|GT\s*\d+|GT\s*0[xX][a-fA-F0-9]+|LE\s*\d+|LE\s*0[xX][a-fA-F0-9]+|GE\s*\d+|GE\s*0[xX][a-fA-F0-9]+|XOR\s*\d+|XOR\s*0[xX][a-fA-F0-9]+|EQ\s*\d+|EQ\s*0[xX][a-fA-F0-9]+)'
1772 PatternValidRng
= re
.compile('^' + '(NOT)?\s*' + PatternValidRangeIn
+ '$')
1773 for Comment
in self
._Comments
:
1774 Comm
= Comment
[0].strip()
1778 Description
= PatternDesc
.findall(Comm
)
1780 Prompt
= PatternPrompt
.findall(Comm
)
1782 ValidFormt
= Comm
.lstrip('#')
1783 ValidFormt
= ValidFormt
.lstrip()
1784 if ValidFormt
[0:11] == '@ValidRange':
1785 ValidFormt
= ValidFormt
[11:]
1786 ValidFormt
= ValidFormt
.lstrip()
1788 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1791 Expression
= ValidFormt
1792 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1794 if not eval(ErrorCodeValid
% ErrorCode
):
1795 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1797 EdkLogger
.warn('Parser', '@ValidRange ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1798 if not PatternValidRng
.search(Expression
):
1799 EdkLogger
.warn('Parser', '@ValidRange Expression(%s) of PCD %s is incorrect format.' % (Expression
, TokenList
[0]))
1800 if ValidFormt
[0:10] == '@ValidList':
1801 ValidFormt
= ValidFormt
[10:]
1802 ValidFormt
= ValidFormt
.lstrip()
1804 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1807 Expression
= ValidFormt
1808 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1810 if not eval(ErrorCodeValid
% ErrorCode
):
1811 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1813 EdkLogger
.warn('Parser', '@ValidList ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1814 Values
= Expression
.split(',')
1815 for Value
in Values
:
1816 Value
= Value
.strip()
1820 EdkLogger
.warn('Parser', '@ValidList Expression of PCD %s include a invalid value(%s).' % (TokenList
[0], Value
))
1822 if ValidFormt
[0:11] == '@Expression':
1823 ValidFormt
= ValidFormt
[11:]
1824 ValidFormt
= ValidFormt
.lstrip()
1826 ErrorCode
, Expression
= ValidFormt
.split('|', 1)
1829 Expression
= ValidFormt
1830 ErrorCode
, Expression
= ErrorCode
.strip(), Expression
.strip()
1832 if not eval(ErrorCodeValid
% ErrorCode
):
1833 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1835 EdkLogger
.warn('Parser', '@Expression ErrorCode(%s) of PCD %s is not valid UINT32 value.' % (ErrorCode
, TokenList
[0]))
1837 EdkLogger
.warn('Parser', '@Expression Expression of PCD %s is incorrect format.' % TokenList
[0])
1839 EdkLogger
.warn('Parser', 'PCD %s Description information is not provided.' % TokenList
[0])
1841 EdkLogger
.warn('Parser', 'PCD %s Prompt information is not provided.' % TokenList
[0])
1842 # check Description, Prompt localization information
1844 self
._UniObj
.CheckPcdInfo(TokenList
[0])
1846 if ValueList
[0] in ['True', 'true', 'TRUE']:
1848 elif ValueList
[0] in ['False', 'false', 'FALSE']:
1851 self
._ValueList
[2] = ValueList
[0].strip() + '|' + ValueList
[1].strip() + '|' + ValueList
[2].strip()
1854 MODEL_META_DATA_HEADER
: MetaFileParser
._DefineParser
,
1855 MODEL_EFI_INCLUDE
: MetaFileParser
._PathParser
,
1856 MODEL_EFI_LIBRARY_CLASS
: MetaFileParser
._PathParser
,
1857 MODEL_EFI_GUID
: _GuidParser
,
1858 MODEL_EFI_PPI
: _GuidParser
,
1859 MODEL_EFI_PROTOCOL
: _GuidParser
,
1860 MODEL_PCD_FIXED_AT_BUILD
: _PcdParser
,
1861 MODEL_PCD_PATCHABLE_IN_MODULE
: _PcdParser
,
1862 MODEL_PCD_FEATURE_FLAG
: _PcdParser
,
1863 MODEL_PCD_DYNAMIC
: _PcdParser
,
1864 MODEL_PCD_DYNAMIC_EX
: _PcdParser
,
1865 MODEL_UNKNOWN
: MetaFileParser
._Skip
,
1866 MODEL_META_DATA_USER_EXTENSION
: MetaFileParser
._Skip
,
1872 # This class defined the structure used in Fdf object
1874 # @param Filename: Input value for Ffilename of Fdf file, default is None
1875 # @param WorkspaceDir: Input value for current workspace directory, default is None
1878 def __init__(self
, Filename
= None, IsToDatabase
= False, WorkspaceDir
= None, Database
= None):
1879 self
.WorkspaceDir
= WorkspaceDir
1880 self
.IsToDatabase
= IsToDatabase
1882 self
.Cur
= Database
.Cur
1883 self
.TblFile
= Database
.TblFile
1884 self
.TblFdf
= Database
.TblFdf
1889 # Load Fdf file if filename is not None
1891 if Filename
is not None:
1893 self
.LoadFdfFile(Filename
)
1898 # Insert a FDF file record into database
1900 def InsertFile(self
, Filename
):
1902 Filename
= NormPath(Filename
)
1903 if Filename
not in self
.FileList
:
1904 FileID
= self
.TblFile
.InsertFile(Filename
, MODEL_FILE_FDF
)
1905 self
.FileList
[Filename
] = FileID
1907 return self
.FileList
[Filename
]
1912 # Load the file if it exists
1914 # @param Filename: Input value for filename of Fdf file
1916 def LoadFdfFile(self
, Filename
):
1921 Filename
= NormPath(Filename
)
1922 Fdf
= FdfParser(Filename
)
1926 # Insert inf file and pcd information
1928 if self
.IsToDatabase
:
1929 (Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
) = \
1930 (0, '', '', '', 'COMMON', 'COMMON', -1, -1, -1, -1, -1, -1, 0)
1931 for Index
in range(0, len(Fdf
.Profile
.PcdDict
)):
1933 for Key
in Fdf
.Profile
.PcdDict
.keys():
1937 FileName
= Fdf
.Profile
.PcdFileLineDict
[Key
][0]
1938 StartLine
= Fdf
.Profile
.PcdFileLineDict
[Key
][1]
1939 BelongsToFile
= self
.InsertFile(FileName
)
1940 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1941 for Index
in range(0, len(Fdf
.Profile
.InfList
)):
1942 Model
= MODEL_META_DATA_COMPONENT
1943 Value1
= Fdf
.Profile
.InfList
[Index
]
1945 FileName
= Fdf
.Profile
.InfFileLineList
[Index
][0]
1946 StartLine
= Fdf
.Profile
.InfFileLineList
[Index
][1]
1947 BelongsToFile
= self
.InsertFile(FileName
)
1948 self
.TblFdf
.Insert(Model
, Value1
, Value2
, Value3
, Scope1
, Scope2
, BelongsToItem
, BelongsToFile
, StartLine
, StartColumn
, EndLine
, EndColumn
, Enabled
)
1950 class UniParser(object):
1951 # IsExtraUni defined the UNI file is Module UNI or extra Module UNI
1952 # IsModuleUni defined the UNI file is Module UNI or Package UNI
1953 def __init__(self
, FilePath
, IsExtraUni
=False, IsModuleUni
=True):
1954 self
.FilePath
= FilePath
1955 self
.FileName
= os
.path
.basename(FilePath
)
1956 self
.IsExtraUni
= IsExtraUni
1957 self
.IsModuleUni
= IsModuleUni
1964 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_8').read()
1965 except UnicodeError:
1966 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16').read()
1967 except UnicodeError:
1968 self
.FileIn
= CodecOpenLongFilePath(self
.FilePath
, Mode
='rb', Encoding
='utf_16_le').read()
1973 if self
.IsModuleUni
:
1975 ModuleName
= self
.CheckKeyValid('STR_PROPERTIES_MODULE_NAME')
1976 self
.PrintLog('STR_PROPERTIES_MODULE_NAME', ModuleName
)
1978 ModuleAbstract
= self
.CheckKeyValid('STR_MODULE_ABSTRACT')
1979 self
.PrintLog('STR_MODULE_ABSTRACT', ModuleAbstract
)
1980 ModuleDescription
= self
.CheckKeyValid('STR_MODULE_DESCRIPTION')
1981 self
.PrintLog('STR_MODULE_DESCRIPTION', ModuleDescription
)
1984 PackageName
= self
.CheckKeyValid('STR_PROPERTIES_PACKAGE_NAME')
1985 self
.PrintLog('STR_PROPERTIES_PACKAGE_NAME', PackageName
)
1987 PackageAbstract
= self
.CheckKeyValid('STR_PACKAGE_ABSTRACT')
1988 self
.PrintLog('STR_PACKAGE_ABSTRACT', PackageAbstract
)
1989 PackageDescription
= self
.CheckKeyValid('STR_PACKAGE_DESCRIPTION')
1990 self
.PrintLog('STR_PACKAGE_DESCRIPTION', PackageDescription
)
1992 def CheckKeyValid(self
, Key
, Contents
=None):
1994 Contents
= self
.FileIn
1995 KeyPattern
= re
.compile('#string\s+%s\s+.*?#language.*?".*?"' % Key
, re
.S
)
1996 if KeyPattern
.search(Contents
):
2000 def CheckPcdInfo(self
, PcdCName
):
2001 PromptKey
= 'STR_%s_PROMPT' % PcdCName
.replace('.', '_')
2002 PcdPrompt
= self
.CheckKeyValid(PromptKey
)
2003 self
.PrintLog(PromptKey
, PcdPrompt
)
2004 HelpKey
= 'STR_%s_HELP' % PcdCName
.replace('.', '_')
2005 PcdHelp
= self
.CheckKeyValid(HelpKey
)
2006 self
.PrintLog(HelpKey
, PcdHelp
)
2008 def PrintLog(self
, Key
, Value
):
2009 if not Value
and Key
not in self
.Missing
:
2010 Msg
= '%s is missing in the %s file.' % (Key
, self
.FileName
)
2011 EdkLogger
.warn('Parser', Msg
)
2012 EccGlobalData
.gDb
.TblReport
.Insert(EccToolError
.ERROR_GENERAL_CHECK_UNI_HELP_INFO
, OtherMsg
=Msg
, BelongsToTable
='File', BelongsToItem
=-2)
2013 self
.Missing
.append(Key
)
2017 # This acts like the main() function for the script, unless it is 'import'ed into another
2020 if __name__
== '__main__':