]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/Workspace/MetaFileParser.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / Workspace / MetaFileParser.py
1 ## @file
2 # This file is used to parse meta files
3 #
4 # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
5 # (C) Copyright 2015-2018 Hewlett Packard Enterprise Development LP<BR>
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 ##
10 # Import Modules
11 #
12 from __future__ import print_function
13 from __future__ import absolute_import
14 import Common.LongFilePathOs as os
15 import re
16 import time
17 import copy
18 from hashlib import md5
19
20 import Common.EdkLogger as EdkLogger
21 import Common.GlobalData as GlobalData
22
23 from CommonDataClass.DataClass import *
24 from Common.DataType import *
25 from Common.StringUtils import *
26 from Common.Misc import GuidStructureStringToGuidString, CheckPcdDatum, PathClass, AnalyzePcdData, AnalyzeDscPcd, AnalyzePcdExpression, ParseFieldValue, StructPattern
27 from Common.Expression import *
28 from CommonDataClass.Exceptions import *
29 from Common.LongFilePathSupport import OpenLongFilePath as open
30 from collections import defaultdict
31 from .MetaFileTable import MetaFileStorage
32 from .MetaFileCommentParser import CheckInfComment
33 from Common.DataType import TAB_COMMENT_EDK_START, TAB_COMMENT_EDK_END
34
35 ## RegEx for finding file versions
36 hexVersionPattern = re.compile(r'0[xX][\da-f-A-F]{5,8}')
37 decVersionPattern = re.compile(r'\d+\.\d+')
38 CODEPattern = re.compile(r"{CODE\([a-fA-F0-9Xx\{\},\s]*\)}")
39
40 ## A decorator used to parse macro definition
41 def ParseMacro(Parser):
42 def MacroParser(self):
43 Match = GlobalData.gMacroDefPattern.match(self._CurrentLine)
44 if not Match:
45 # Not 'DEFINE/EDK_GLOBAL' statement, call decorated method
46 Parser(self)
47 return
48
49 TokenList = GetSplitValueList(self._CurrentLine[Match.end(1):], TAB_EQUAL_SPLIT, 1)
50 # Syntax check
51 if not TokenList[0]:
52 EdkLogger.error('Parser', FORMAT_INVALID, "No macro name given",
53 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
54 if len(TokenList) < 2:
55 TokenList.append('')
56
57 Type = Match.group(1)
58 Name, Value = TokenList
59 # Global macros can be only defined via environment variable
60 if Name in GlobalData.gGlobalDefines:
61 EdkLogger.error('Parser', FORMAT_INVALID, "%s can only be defined via environment variable" % Name,
62 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
63 # Only upper case letters, digit and '_' are allowed
64 if not GlobalData.gMacroNamePattern.match(Name):
65 EdkLogger.error('Parser', FORMAT_INVALID, "The macro name must be in the pattern [A-Z][A-Z0-9_]*",
66 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
67
68 Value = ReplaceMacro(Value, self._Macros)
69 if Type in self.DataType:
70 self._ItemType = self.DataType[Type]
71 else:
72 self._ItemType = MODEL_META_DATA_DEFINE
73 # DEFINE defined macros
74 if Type == TAB_DSC_DEFINES_DEFINE:
75 #
76 # First judge whether this DEFINE is in conditional directive statements or not.
77 #
78 if isinstance(self, DscParser) and self._InDirective > -1:
79 pass
80 else:
81 if isinstance(self, DecParser):
82 if MODEL_META_DATA_HEADER in self._SectionType:
83 self._FileLocalMacros[Name] = Value
84 else:
85 self._ConstructSectionMacroDict(Name, Value)
86 elif self._SectionType == MODEL_META_DATA_HEADER:
87 self._FileLocalMacros[Name] = Value
88 else:
89 self._ConstructSectionMacroDict(Name, Value)
90
91 # EDK_GLOBAL defined macros
92 elif not isinstance(self, DscParser):
93 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used in .dsc file",
94 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
95 elif self._SectionType != MODEL_META_DATA_HEADER:
96 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL can only be used under [Defines] section",
97 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
98 elif (Name in self._FileLocalMacros) and (self._FileLocalMacros[Name] != Value):
99 EdkLogger.error('Parser', FORMAT_INVALID, "EDK_GLOBAL defined a macro with the same name and different value as one defined by 'DEFINE'",
100 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
101
102 self._ValueList = [Type, Name, Value]
103
104 return MacroParser
105
106 ## Base class of parser
107 #
108 # This class is used for derivation purpose. The specific parser for one kind
109 # type file must derive this class and implement some public interfaces.
110 #
111 # @param FilePath The path of platform description file
112 # @param FileType The raw data of DSC file
113 # @param Table Database used to retrieve module/package information
114 # @param Macros Macros used for replacement in file
115 # @param Owner Owner ID (for sub-section parsing)
116 # @param From ID from which the data comes (for !INCLUDE directive)
117 #
118 class MetaFileParser(object):
119 # data type (file content) for specific file type
120 DataType = {}
121
122 # Parser objects used to implement singleton
123 MetaFiles = {}
124
125 ## Factory method
126 #
127 # One file, one parser object. This factory method makes sure that there's
128 # only one object constructed for one meta file.
129 #
130 # @param Class class object of real AutoGen class
131 # (InfParser, DecParser or DscParser)
132 # @param FilePath The path of meta file
133 # @param *args The specific class related parameters
134 # @param **kwargs The specific class related dict parameters
135 #
136 def __new__(Class, FilePath, *args, **kwargs):
137 if FilePath in Class.MetaFiles:
138 return Class.MetaFiles[FilePath]
139 else:
140 ParserObject = super(MetaFileParser, Class).__new__(Class)
141 Class.MetaFiles[FilePath] = ParserObject
142 return ParserObject
143
144 ## Constructor of MetaFileParser
145 #
146 # Initialize object of MetaFileParser
147 #
148 # @param FilePath The path of platform description file
149 # @param FileType The raw data of DSC file
150 # @param Arch Default Arch value for filtering sections
151 # @param Table Database used to retrieve module/package information
152 # @param Owner Owner ID (for sub-section parsing)
153 # @param From ID from which the data comes (for !INCLUDE directive)
154 #
155 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
156 self._Table = Table
157 self._RawTable = Table
158 self._Arch = Arch
159 self._FileType = FileType
160 self.MetaFile = FilePath
161 self._FileDir = self.MetaFile.Dir
162 self._Defines = {}
163 self._Packages = []
164 self._FileLocalMacros = {}
165 self._SectionsMacroDict = defaultdict(dict)
166
167 # for recursive parsing
168 self._Owner = [Owner]
169 self._From = From
170
171 # parsr status for parsing
172 self._ValueList = ['', '', '', '', '']
173 self._Scope = []
174 self._LineIndex = 0
175 self._CurrentLine = ''
176 self._SectionType = MODEL_UNKNOWN
177 self._SectionName = ''
178 self._InSubsection = False
179 self._SubsectionType = MODEL_UNKNOWN
180 self._SubsectionName = ''
181 self._ItemType = MODEL_UNKNOWN
182 self._LastItem = -1
183 self._Enabled = 0
184 self._Finished = False
185 self._PostProcessed = False
186 # Different version of meta-file has different way to parse.
187 self._Version = 0
188 self._GuidDict = {} # for Parser PCD value {GUID(gTokeSpaceGuidName)}
189
190 self._PcdCodeValue = ""
191 self._PcdDataTypeCODE = False
192 self._CurrentPcdName = ""
193
194 ## Store the parsed data in table
195 def _Store(self, *Args):
196 return self._Table.Insert(*Args)
197
198 ## Virtual method for starting parse
199 def Start(self):
200 raise NotImplementedError
201
202 ## Notify a post-process is needed
203 def DoPostProcess(self):
204 self._PostProcessed = False
205
206 ## Set parsing complete flag in both class and table
207 def _Done(self):
208 self._Finished = True
209 self._Table.SetEndFlag()
210
211 def _PostProcess(self):
212 self._PostProcessed = True
213
214 ## Get the parse complete flag
215 @property
216 def Finished(self):
217 return self._Finished
218
219 ## Set the complete flag
220 @Finished.setter
221 def Finished(self, Value):
222 self._Finished = Value
223
224 ## Remove records that do not match given Filter Arch
225 def _FilterRecordList(self, RecordList, FilterArch):
226 NewRecordList = []
227 for Record in RecordList:
228 Arch = Record[3]
229 if Arch == TAB_ARCH_COMMON or Arch == FilterArch:
230 NewRecordList.append(Record)
231 return NewRecordList
232
233 ## Use [] style to query data in table, just for readability
234 #
235 # DataInfo = [data_type, scope1(arch), scope2(platform/moduletype)]
236 #
237 def __getitem__(self, DataInfo):
238 if not isinstance(DataInfo, type(())):
239 DataInfo = (DataInfo,)
240
241 # Parse the file first, if necessary
242 self.StartParse()
243
244 # No specific ARCH or Platform given, use raw data
245 if self._RawTable and (len(DataInfo) == 1 or DataInfo[1] is None):
246 return self._FilterRecordList(self._RawTable.Query(*DataInfo), self._Arch)
247
248 # Do post-process if necessary
249 if not self._PostProcessed:
250 self._PostProcess()
251
252 return self._FilterRecordList(self._Table.Query(*DataInfo), DataInfo[1])
253
254 def StartParse(self):
255 if not self._Finished:
256 if self._RawTable.IsIntegrity():
257 self._Finished = True
258 else:
259 self._Table = self._RawTable
260 self._PostProcessed = False
261 self.Start()
262 ## Data parser for the common format in different type of file
263 #
264 # The common format in the meatfile is like
265 #
266 # xxx1 | xxx2 | xxx3
267 #
268 @ParseMacro
269 def _CommonParser(self):
270 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
271 self._ValueList[0:len(TokenList)] = TokenList
272
273 ## Data parser for the format in which there's path
274 #
275 # Only path can have macro used. So we need to replace them before use.
276 #
277 @ParseMacro
278 def _PathParser(self):
279 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
280 self._ValueList[0:len(TokenList)] = TokenList
281 # Don't do macro replacement for dsc file at this point
282 if not isinstance(self, DscParser):
283 Macros = self._Macros
284 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
285
286 ## Skip unsupported data
287 def _Skip(self):
288 EdkLogger.warn("Parser", "Unrecognized content", File=self.MetaFile,
289 Line=self._LineIndex + 1, ExtraData=self._CurrentLine);
290 self._ValueList[0:1] = [self._CurrentLine]
291
292 ## Skip unsupported data for UserExtension Section
293 def _SkipUserExtension(self):
294 self._ValueList[0:1] = [self._CurrentLine]
295
296 ## Section header parser
297 #
298 # The section header is always in following format:
299 #
300 # [section_name.arch<.platform|module_type>]
301 #
302 def _SectionHeaderParser(self):
303 self._Scope = []
304 self._SectionName = ''
305 ArchList = set()
306 for Item in GetSplitValueList(self._CurrentLine[1:-1], TAB_COMMA_SPLIT):
307 if Item == '':
308 continue
309 ItemList = GetSplitValueList(Item, TAB_SPLIT, 3)
310 # different section should not mix in one section
311 if self._SectionName != '' and self._SectionName != ItemList[0].upper():
312 EdkLogger.error('Parser', FORMAT_INVALID, "Different section names in the same section",
313 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
314 self._SectionName = ItemList[0].upper()
315 if self._SectionName in self.DataType:
316 self._SectionType = self.DataType[self._SectionName]
317 # Check if the section name is valid
318 if self._SectionName not in SECTIONS_HAVE_ITEM_AFTER_ARCH_SET and len(ItemList) > 3:
319 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
320 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
321 elif self._Version >= 0x00010005:
322 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
323 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
324 else:
325 self._SectionType = MODEL_UNKNOWN
326
327 # S1 is always Arch
328 if len(ItemList) > 1:
329 S1 = ItemList[1].upper()
330 else:
331 S1 = TAB_ARCH_COMMON
332 S1 = ReplaceMacro(S1, self._Macros)
333 ArchList.add(S1)
334
335 # S2 may be Platform or ModuleType
336 if len(ItemList) > 2:
337 if self._SectionName.upper() in SECTIONS_HAVE_ITEM_PCD_SET:
338 S2 = ItemList[2]
339 else:
340 S2 = ItemList[2].upper()
341 else:
342 S2 = TAB_COMMON
343 if len(ItemList) > 3:
344 S3 = ItemList[3]
345 else:
346 S3 = TAB_COMMON
347 self._Scope.append([S1, S2, S3])
348
349 # 'COMMON' must not be used with specific ARCHs at the same section
350 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:
351 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
352 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
353 # If the section information is needed later, it should be stored in database
354 self._ValueList[0] = self._SectionName
355
356 ## [packages] section parser
357 @ParseMacro
358 def _PackageParser(self):
359 self._CurrentLine = CleanString(self._CurrentLine)
360 self._Packages.append(self._CurrentLine)
361 self._ValueList[0] = self._CurrentLine
362
363 ## [defines] section parser
364 @ParseMacro
365 def _DefineParser(self):
366 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
367 self._ValueList[1:len(TokenList)] = TokenList
368 if not self._ValueList[1]:
369 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
370 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
371 if not self._ValueList[2]:
372 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
373 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
374
375 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
376 Name, Value = self._ValueList[1], self._ValueList[2]
377 MacroUsed = GlobalData.gMacroRefPattern.findall(Value)
378 if len(MacroUsed) != 0:
379 for Macro in MacroUsed:
380 if Macro in GlobalData.gGlobalDefines:
381 EdkLogger.error("Parser", FORMAT_INVALID, "Global macro %s is not permitted." % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
382 else:
383 EdkLogger.error("Parser", FORMAT_INVALID, "%s not defined" % (Macro), ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
384 # Sometimes, we need to make differences between EDK and EDK2 modules
385 if Name == 'INF_VERSION':
386 if hexVersionPattern.match(Value):
387 self._Version = int(Value, 0)
388 elif decVersionPattern.match(Value):
389 ValueList = Value.split('.')
390 Major = int(ValueList[0], 0)
391 Minor = int(ValueList[1], 0)
392 if Major > 0xffff or Minor > 0xffff:
393 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
394 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
395 self._Version = int('0x{0:04x}{1:04x}'.format(Major, Minor), 0)
396 else:
397 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid version number",
398 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
399
400 if isinstance(self, InfParser) and self._Version < 0x00010005:
401 # EDK module allows using defines as macros
402 self._FileLocalMacros[Name] = Value
403 self._Defines[Name] = Value
404
405 ## [BuildOptions] section parser
406 @ParseMacro
407 def _BuildOptionParser(self):
408 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
409 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
410 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
411 if len(TokenList2) == 2:
412 self._ValueList[0] = TokenList2[0] # toolchain family
413 self._ValueList[1] = TokenList2[1] # keys
414 else:
415 self._ValueList[1] = TokenList[0]
416 if len(TokenList) == 2 and not isinstance(self, DscParser): # value
417 self._ValueList[2] = ReplaceMacro(TokenList[1], self._Macros)
418
419 if self._ValueList[1].count('_') != 4:
420 EdkLogger.error(
421 'Parser',
422 FORMAT_INVALID,
423 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
424 ExtraData=self._CurrentLine,
425 File=self.MetaFile,
426 Line=self._LineIndex + 1
427 )
428 def GetValidExpression(self, TokenSpaceGuid, PcdCName):
429 return self._Table.GetValidExpression(TokenSpaceGuid, PcdCName)
430
431 @property
432 def _Macros(self):
433 Macros = {}
434 Macros.update(self._FileLocalMacros)
435 Macros.update(self._GetApplicableSectionMacro())
436 return Macros
437
438 ## Construct section Macro dict
439 def _ConstructSectionMacroDict(self, Name, Value):
440 ScopeKey = [(Scope[0], Scope[1], Scope[2]) for Scope in self._Scope]
441 ScopeKey = tuple(ScopeKey)
442 #
443 # DecParser SectionType is a list, will contain more than one item only in Pcd Section
444 # As Pcd section macro usage is not allowed, so here it is safe
445 #
446 if isinstance(self, DecParser):
447 SectionDictKey = self._SectionType[0], ScopeKey
448 else:
449 SectionDictKey = self._SectionType, ScopeKey
450
451 self._SectionsMacroDict[SectionDictKey][Name] = Value
452
453 ## Get section Macros that are applicable to current line, which may come from other sections
454 ## that share the same name while scope is wider
455 def _GetApplicableSectionMacro(self):
456 Macros = {}
457
458 ComComMacroDict = {}
459 ComSpeMacroDict = {}
460 SpeSpeMacroDict = {}
461
462 ActiveSectionType = self._SectionType
463 if isinstance(self, DecParser):
464 ActiveSectionType = self._SectionType[0]
465
466 for (SectionType, Scope) in self._SectionsMacroDict:
467 if SectionType != ActiveSectionType:
468 continue
469
470 for ActiveScope in self._Scope:
471 Scope0, Scope1, Scope2= ActiveScope[0], ActiveScope[1], ActiveScope[2]
472 if(Scope0, Scope1, Scope2) not in Scope:
473 break
474 else:
475 SpeSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
476
477 for ActiveScope in self._Scope:
478 Scope0, Scope1, Scope2 = ActiveScope[0], ActiveScope[1], ActiveScope[2]
479 if(Scope0, Scope1, Scope2) not in Scope and (Scope0, TAB_COMMON, TAB_COMMON) not in Scope and (TAB_COMMON, Scope1, TAB_COMMON) not in Scope:
480 break
481 else:
482 ComSpeMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
483
484 if (TAB_COMMON, TAB_COMMON, TAB_COMMON) in Scope:
485 ComComMacroDict.update(self._SectionsMacroDict[(SectionType, Scope)])
486
487 Macros.update(ComComMacroDict)
488 Macros.update(ComSpeMacroDict)
489 Macros.update(SpeSpeMacroDict)
490
491 return Macros
492
493 def ProcessMultipleLineCODEValue(self,Content):
494 CODEBegin = False
495 CODELine = ""
496 continuelinecount = 0
497 newContent = []
498 for Index in range(0, len(Content)):
499 Line = Content[Index]
500 if CODEBegin:
501 CODELine = CODELine + Line
502 continuelinecount +=1
503 if ")}" in Line:
504 newContent.append(CODELine)
505 for _ in range(continuelinecount):
506 newContent.append("")
507 CODEBegin = False
508 CODELine = ""
509 continuelinecount = 0
510 else:
511 if not Line:
512 newContent.append(Line)
513 continue
514 if "{CODE(" not in Line:
515 newContent.append(Line)
516 continue
517 elif CODEPattern.findall(Line):
518 newContent.append(Line)
519 continue
520 else:
521 CODEBegin = True
522 CODELine = Line
523
524 return newContent
525
526 _SectionParser = {}
527
528 ## INF file parser class
529 #
530 # @param FilePath The path of platform description file
531 # @param FileType The raw data of DSC file
532 # @param Table Database used to retrieve module/package information
533 # @param Macros Macros used for replacement in file
534 #
535 class InfParser(MetaFileParser):
536 # INF file supported data types (one type per section)
537 DataType = {
538 TAB_UNKNOWN.upper() : MODEL_UNKNOWN,
539 TAB_INF_DEFINES.upper() : MODEL_META_DATA_HEADER,
540 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
541 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
542 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
543 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
544 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
545 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
546 TAB_NMAKE.upper() : MODEL_META_DATA_NMAKE,
547 TAB_INF_FIXED_PCD.upper() : MODEL_PCD_FIXED_AT_BUILD,
548 TAB_INF_PATCH_PCD.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
549 TAB_INF_FEATURE_PCD.upper() : MODEL_PCD_FEATURE_FLAG,
550 TAB_INF_PCD_EX.upper() : MODEL_PCD_DYNAMIC_EX,
551 TAB_INF_PCD.upper() : MODEL_PCD_DYNAMIC,
552 TAB_SOURCES.upper() : MODEL_EFI_SOURCE_FILE,
553 TAB_GUIDS.upper() : MODEL_EFI_GUID,
554 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
555 TAB_PPIS.upper() : MODEL_EFI_PPI,
556 TAB_DEPEX.upper() : MODEL_EFI_DEPEX,
557 TAB_BINARIES.upper() : MODEL_EFI_BINARY_FILE,
558 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION
559 }
560
561 ## Constructor of InfParser
562 #
563 # Initialize object of InfParser
564 #
565 # @param FilePath The path of module description file
566 # @param FileType The raw data of DSC file
567 # @param Arch Default Arch value for filtering sections
568 # @param Table Database used to retrieve module/package information
569 #
570 def __init__(self, FilePath, FileType, Arch, Table):
571 # prevent re-initialization
572 if hasattr(self, "_Table"):
573 return
574 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table)
575 self.PcdsDict = {}
576
577 ## Parser starter
578 def Start(self):
579 NmakeLine = ''
580 Content = ''
581 try:
582 with open(str(self.MetaFile), 'r') as File:
583 Content = File.readlines()
584 except:
585 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
586
587 # parse the file line by line
588 IsFindBlockComment = False
589 GetHeaderComment = False
590 TailComments = []
591 SectionComments = []
592 Comments = []
593
594 for Index in range(0, len(Content)):
595 # skip empty, commented, block commented lines
596 Line, Comment = CleanString2(Content[Index], AllowCppStyleComment=True)
597 NextLine = ''
598 if Index + 1 < len(Content):
599 NextLine, NextComment = CleanString2(Content[Index + 1])
600 if Line == '':
601 if Comment:
602 Comments.append((Comment, Index + 1))
603 elif GetHeaderComment:
604 SectionComments.extend(Comments)
605 Comments = []
606 continue
607 if Line.find(TAB_COMMENT_EDK_START) > -1:
608 IsFindBlockComment = True
609 continue
610 if Line.find(TAB_COMMENT_EDK_END) > -1:
611 IsFindBlockComment = False
612 continue
613 if IsFindBlockComment:
614 continue
615
616 self._LineIndex = Index
617 self._CurrentLine = Line
618
619 # section header
620 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
621 if not GetHeaderComment:
622 for Cmt, LNo in Comments:
623 self._Store(MODEL_META_DATA_HEADER_COMMENT, Cmt, '', '', TAB_COMMON,
624 TAB_COMMON, self._Owner[-1], LNo, -1, LNo, -1, 0)
625 GetHeaderComment = True
626 else:
627 TailComments.extend(SectionComments + Comments)
628 Comments = []
629 self._SectionHeaderParser()
630 # Check invalid sections
631 if self._Version < 0x00010005:
632 if self._SectionType in [MODEL_META_DATA_BUILD_OPTION,
633 MODEL_EFI_LIBRARY_CLASS,
634 MODEL_META_DATA_PACKAGE,
635 MODEL_PCD_FIXED_AT_BUILD,
636 MODEL_PCD_PATCHABLE_IN_MODULE,
637 MODEL_PCD_FEATURE_FLAG,
638 MODEL_PCD_DYNAMIC_EX,
639 MODEL_PCD_DYNAMIC,
640 MODEL_EFI_GUID,
641 MODEL_EFI_PROTOCOL,
642 MODEL_EFI_PPI,
643 MODEL_META_DATA_USER_EXTENSION]:
644 EdkLogger.error('Parser', FORMAT_INVALID,
645 "Section [%s] is not allowed in inf file without version" % (self._SectionName),
646 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
647 elif self._SectionType in [MODEL_EFI_INCLUDE,
648 MODEL_EFI_LIBRARY_INSTANCE,
649 MODEL_META_DATA_NMAKE]:
650 EdkLogger.error('Parser', FORMAT_INVALID,
651 "Section [%s] is not allowed in inf file with version 0x%08x" % (self._SectionName, self._Version),
652 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
653 continue
654 # merge two lines specified by '\' in section NMAKE
655 elif self._SectionType == MODEL_META_DATA_NMAKE:
656 if Line[-1] == '\\':
657 if NextLine == '':
658 self._CurrentLine = NmakeLine + Line[0:-1]
659 NmakeLine = ''
660 else:
661 if NextLine[0] == TAB_SECTION_START and NextLine[-1] == TAB_SECTION_END:
662 self._CurrentLine = NmakeLine + Line[0:-1]
663 NmakeLine = ''
664 else:
665 NmakeLine = NmakeLine + ' ' + Line[0:-1]
666 continue
667 else:
668 self._CurrentLine = NmakeLine + Line
669 NmakeLine = ''
670
671 # section content
672 self._ValueList = ['', '', '']
673 # parse current line, result will be put in self._ValueList
674 self._SectionParser[self._SectionType](self)
675 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
676 self._ItemType = -1
677 Comments = []
678 continue
679 if Comment:
680 Comments.append((Comment, Index + 1))
681 if GlobalData.gOptions and GlobalData.gOptions.CheckUsage:
682 CheckInfComment(self._SectionType, Comments, str(self.MetaFile), Index + 1, self._ValueList)
683 #
684 # Model, Value1, Value2, Value3, Arch, Platform, BelongsToItem=-1,
685 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
686 #
687 for Arch, Platform, _ in self._Scope:
688 LastItem = self._Store(self._SectionType,
689 self._ValueList[0],
690 self._ValueList[1],
691 self._ValueList[2],
692 Arch,
693 Platform,
694 self._Owner[-1],
695 self._LineIndex + 1,
696 - 1,
697 self._LineIndex + 1,
698 - 1,
699 0
700 )
701 for Comment, LineNo in Comments:
702 self._Store(MODEL_META_DATA_COMMENT, Comment, '', '', Arch, Platform,
703 LastItem, LineNo, -1, LineNo, -1, 0)
704 Comments = []
705 SectionComments = []
706 TailComments.extend(SectionComments + Comments)
707 if IsFindBlockComment:
708 EdkLogger.error("Parser", FORMAT_INVALID, "Open block comments (starting with /*) are expected to end with */",
709 File=self.MetaFile)
710
711 # If there are tail comments in INF file, save to database whatever the comments are
712 for Comment in TailComments:
713 self._Store(MODEL_META_DATA_TAIL_COMMENT, Comment[0], '', '', TAB_COMMON,
714 TAB_COMMON, self._Owner[-1], -1, -1, -1, -1, 0)
715 self._Done()
716
717 ## Data parser for the format in which there's path
718 #
719 # Only path can have macro used. So we need to replace them before use.
720 #
721 def _IncludeParser(self):
722 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
723 self._ValueList[0:len(TokenList)] = TokenList
724 Macros = self._Macros
725 if Macros:
726 for Index in range(0, len(self._ValueList)):
727 Value = self._ValueList[Index]
728 if not Value:
729 continue
730 self._ValueList[Index] = ReplaceMacro(Value, Macros)
731
732 ## Parse [Sources] section
733 #
734 # Only path can have macro used. So we need to replace them before use.
735 #
736 @ParseMacro
737 def _SourceFileParser(self):
738 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
739 # Let TokenList[2] be TagName|ToolCode|FeatureFlag
740 if len(TokenList) > 3:
741 for extraToken in range(3, len(TokenList)):
742 TokenList[2] = TokenList[2] + '|' + TokenList[extraToken]
743 self._ValueList[0:len(TokenList)] = TokenList
744 Macros = self._Macros
745 # For Acpi tables, remove macro like ' TABLE_NAME=Sata1'
746 if 'COMPONENT_TYPE' in Macros:
747 if self._Defines['COMPONENT_TYPE'].upper() == 'ACPITABLE':
748 self._ValueList[0] = GetSplitValueList(self._ValueList[0], ' ', 1)[0]
749 if self._Defines['BASE_NAME'] == 'Microcode':
750 pass
751 self._ValueList = [ReplaceMacro(Value, Macros) for Value in self._ValueList]
752
753 ## Parse [Binaries] section
754 #
755 # Only path can have macro used. So we need to replace them before use.
756 #
757 @ParseMacro
758 def _BinaryFileParser(self):
759 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 2)
760 if len(TokenList) < 2:
761 EdkLogger.error('Parser', FORMAT_INVALID, "No file type or path specified",
762 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
763 File=self.MetaFile, Line=self._LineIndex + 1)
764 if not TokenList[0]:
765 EdkLogger.error('Parser', FORMAT_INVALID, "No file type specified",
766 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
767 File=self.MetaFile, Line=self._LineIndex + 1)
768 if not TokenList[1]:
769 EdkLogger.error('Parser', FORMAT_INVALID, "No file path specified",
770 ExtraData=self._CurrentLine + " (<FileType> | <FilePath> [| <Target>])",
771 File=self.MetaFile, Line=self._LineIndex + 1)
772 self._ValueList[0:len(TokenList)] = TokenList
773 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
774
775 ## [nmake] section parser (Edk.x style only)
776 def _NmakeParser(self):
777 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
778 self._ValueList[0:len(TokenList)] = TokenList
779 # remove macros
780 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros)
781 # remove self-reference in macro setting
782 #self._ValueList[1] = ReplaceMacro(self._ValueList[1], {self._ValueList[0]:''})
783
784 ## [FixedPcd], [FeaturePcd], [PatchPcd], [Pcd] and [PcdEx] sections parser
785 @ParseMacro
786 def _PcdParser(self):
787 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
788 ValueList = GetSplitValueList(TokenList[0], TAB_SPLIT)
789 if len(ValueList) != 2:
790 EdkLogger.error('Parser', FORMAT_INVALID, "Illegal token space GUID and PCD name format",
791 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
792 File=self.MetaFile, Line=self._LineIndex + 1)
793 self._ValueList[0:1] = ValueList
794 if len(TokenList) > 1:
795 self._ValueList[2] = TokenList[1]
796 if self._ValueList[0] == '' or self._ValueList[1] == '':
797 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
798 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
799 File=self.MetaFile, Line=self._LineIndex + 1)
800
801 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
802 if self._ValueList[2] != '':
803 InfPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
804 if InfPcdValueList[0] in ['True', 'true', 'TRUE']:
805 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '1', 1)
806 elif InfPcdValueList[0] in ['False', 'false', 'FALSE']:
807 self._ValueList[2] = TokenList[1].replace(InfPcdValueList[0], '0', 1)
808 elif isinstance(InfPcdValueList[0], str) and InfPcdValueList[0].find('$(') >= 0:
809 Value = ReplaceExprMacro(InfPcdValueList[0],self._Macros)
810 if Value != '0':
811 self._ValueList[2] = Value
812 if (self._ValueList[0], self._ValueList[1]) not in self.PcdsDict:
813 self.PcdsDict[self._ValueList[0], self._ValueList[1]] = self._SectionType
814 elif self.PcdsDict[self._ValueList[0], self._ValueList[1]] != self._SectionType:
815 EdkLogger.error('Parser', FORMAT_INVALID, "It is not permissible to list a specified PCD in different PCD type sections.",
816 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<PcdCName>)",
817 File=self.MetaFile, Line=self._LineIndex + 1)
818
819 ## [depex] section parser
820 @ParseMacro
821 def _DepexParser(self):
822 self._ValueList[0:1] = [self._CurrentLine]
823
824 _SectionParser = {
825 MODEL_UNKNOWN : MetaFileParser._Skip,
826 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
827 MODEL_META_DATA_BUILD_OPTION : MetaFileParser._BuildOptionParser,
828 MODEL_EFI_INCLUDE : _IncludeParser, # for Edk.x modules
829 MODEL_EFI_LIBRARY_INSTANCE : MetaFileParser._CommonParser, # for Edk.x modules
830 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
831 MODEL_META_DATA_PACKAGE : MetaFileParser._PathParser,
832 MODEL_META_DATA_NMAKE : _NmakeParser, # for Edk.x modules
833 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
834 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
835 MODEL_PCD_FEATURE_FLAG : _PcdParser,
836 MODEL_PCD_DYNAMIC_EX : _PcdParser,
837 MODEL_PCD_DYNAMIC : _PcdParser,
838 MODEL_EFI_SOURCE_FILE : _SourceFileParser,
839 MODEL_EFI_GUID : MetaFileParser._CommonParser,
840 MODEL_EFI_PROTOCOL : MetaFileParser._CommonParser,
841 MODEL_EFI_PPI : MetaFileParser._CommonParser,
842 MODEL_EFI_DEPEX : _DepexParser,
843 MODEL_EFI_BINARY_FILE : _BinaryFileParser,
844 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
845 }
846
847 ## DSC file parser class
848 #
849 # @param FilePath The path of platform description file
850 # @param FileType The raw data of DSC file
851 # @param Table Database used to retrieve module/package information
852 # @param Macros Macros used for replacement in file
853 # @param Owner Owner ID (for sub-section parsing)
854 # @param From ID from which the data comes (for !INCLUDE directive)
855 #
856 class DscParser(MetaFileParser):
857 # DSC file supported data types (one type per section)
858 DataType = {
859 TAB_SKUIDS.upper() : MODEL_EFI_SKU_ID,
860 TAB_DEFAULT_STORES.upper() : MODEL_EFI_DEFAULT_STORES,
861 TAB_LIBRARIES.upper() : MODEL_EFI_LIBRARY_INSTANCE,
862 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
863 TAB_BUILD_OPTIONS.upper() : MODEL_META_DATA_BUILD_OPTION,
864 TAB_PACKAGES.upper() : MODEL_META_DATA_PACKAGE,
865 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
866 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
867 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
868 TAB_PCDS_DYNAMIC_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_DEFAULT,
869 TAB_PCDS_DYNAMIC_HII_NULL.upper() : MODEL_PCD_DYNAMIC_HII,
870 TAB_PCDS_DYNAMIC_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_VPD,
871 TAB_PCDS_DYNAMIC_EX_DEFAULT_NULL.upper() : MODEL_PCD_DYNAMIC_EX_DEFAULT,
872 TAB_PCDS_DYNAMIC_EX_HII_NULL.upper() : MODEL_PCD_DYNAMIC_EX_HII,
873 TAB_PCDS_DYNAMIC_EX_VPD_NULL.upper() : MODEL_PCD_DYNAMIC_EX_VPD,
874 TAB_COMPONENTS.upper() : MODEL_META_DATA_COMPONENT,
875 TAB_DSC_DEFINES.upper() : MODEL_META_DATA_HEADER,
876 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
877 TAB_DSC_DEFINES_EDKGLOBAL : MODEL_META_DATA_GLOBAL_DEFINE,
878 TAB_INCLUDE.upper() : MODEL_META_DATA_INCLUDE,
879 TAB_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
880 TAB_IF_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
881 TAB_IF_N_DEF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF,
882 TAB_ELSE_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF,
883 TAB_ELSE.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE,
884 TAB_END_IF.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF,
885 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
886 TAB_ERROR.upper() : MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR,
887 }
888
889 # Valid names in define section
890 DefineKeywords = [
891 "DSC_SPECIFICATION",
892 "PLATFORM_NAME",
893 "PLATFORM_GUID",
894 "PLATFORM_VERSION",
895 "SKUID_IDENTIFIER",
896 "PCD_INFO_GENERATION",
897 "PCD_VAR_CHECK_GENERATION",
898 "SUPPORTED_ARCHITECTURES",
899 "BUILD_TARGETS",
900 "OUTPUT_DIRECTORY",
901 "FLASH_DEFINITION",
902 "BUILD_NUMBER",
903 "RFC_LANGUAGES",
904 "ISO_LANGUAGES",
905 "TIME_STAMP_FILE",
906 "VPD_TOOL_GUID",
907 "FIX_LOAD_TOP_MEMORY_ADDRESS",
908 "PREBUILD",
909 "POSTBUILD"
910 ]
911
912 SubSectionDefineKeywords = [
913 "FILE_GUID"
914 ]
915
916 SymbolPattern = ValueExpression.SymbolPattern
917
918 IncludedFiles = set()
919
920 ## Constructor of DscParser
921 #
922 # Initialize object of DscParser
923 #
924 # @param FilePath The path of platform description file
925 # @param FileType The raw data of DSC file
926 # @param Arch Default Arch value for filtering sections
927 # @param Table Database used to retrieve module/package information
928 # @param Owner Owner ID (for sub-section parsing)
929 # @param From ID from which the data comes (for !INCLUDE directive)
930 #
931 def __init__(self, FilePath, FileType, Arch, Table, Owner= -1, From= -1):
932 # prevent re-initialization
933 if hasattr(self, "_Table") and self._Table is Table:
934 return
935 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, Owner, From)
936 self._Version = 0x00010005 # Only EDK2 dsc file is supported
937 # to store conditional directive evaluation result
938 self._DirectiveStack = []
939 self._DirectiveEvalStack = []
940 self._Enabled = 1
941
942 #
943 # Specify whether current line is in uncertain condition
944 #
945 self._InDirective = -1
946
947 # Final valid replacable symbols
948 self._Symbols = {}
949 #
950 # Map the ID between the original table and new table to track
951 # the owner item
952 #
953 self._IdMapping = {-1:-1}
954
955 self._Content = None
956
957 ## Parser starter
958 def Start(self):
959 Content = ''
960 try:
961 with open(str(self.MetaFile), 'r') as File:
962 Content = File.readlines()
963 except:
964 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
965
966 OwnerId = {}
967
968 Content = self.ProcessMultipleLineCODEValue(Content)
969
970 for Index in range(0, len(Content)):
971 Line = CleanString(Content[Index])
972 # skip empty line
973 if Line == '':
974 continue
975
976 self._CurrentLine = Line
977 self._LineIndex = Index
978 if self._InSubsection and self._Owner[-1] == -1:
979 self._Owner.append(self._LastItem)
980
981 # section header
982 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
983 self._SectionType = MODEL_META_DATA_SECTION_HEADER
984 # subsection ending
985 elif Line[0] == '}' and self._InSubsection:
986 self._InSubsection = False
987 self._SubsectionType = MODEL_UNKNOWN
988 self._SubsectionName = ''
989 self._Owner[-1] = -1
990 OwnerId.clear()
991 continue
992 # subsection header
993 elif Line[0] == TAB_OPTION_START and Line[-1] == TAB_OPTION_END:
994 self._SubsectionType = MODEL_META_DATA_SUBSECTION_HEADER
995 # directive line
996 elif Line[0] == '!':
997 TokenList = GetSplitValueList(Line, ' ', 1)
998 if TokenList[0] == TAB_INCLUDE:
999 for Arch, ModuleType, DefaultStore in self._Scope:
1000 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
1001 self._Owner[-1] = OwnerId[Arch]
1002 self._DirectiveParser()
1003 else:
1004 self._DirectiveParser()
1005 continue
1006 if Line[0] == TAB_OPTION_START and not self._InSubsection:
1007 EdkLogger.error("Parser", FILE_READ_FAILURE, "Missing the '{' before %s in Line %s" % (Line, Index+1), ExtraData=self.MetaFile)
1008
1009 if self._InSubsection:
1010 SectionType = self._SubsectionType
1011 else:
1012 SectionType = self._SectionType
1013 self._ItemType = SectionType
1014
1015 self._ValueList = ['', '', '']
1016 # "SET pcd = pcd_expression" syntax is not supported in Dsc file.
1017 if self._CurrentLine.upper().strip().startswith("SET "):
1018 EdkLogger.error('Parser', FORMAT_INVALID, '''"SET pcd = pcd_expression" syntax is not support in Dsc file''',
1019 ExtraData=self._CurrentLine,
1020 File=self.MetaFile, Line=self._LineIndex + 1)
1021 self._SectionParser[SectionType](self)
1022 if self._ValueList is None:
1023 continue
1024 #
1025 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1026 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1027 #
1028 for Arch, ModuleType, DefaultStore in self._Scope:
1029 Owner = self._Owner[-1]
1030 if self._SubsectionType != MODEL_UNKNOWN and Arch in OwnerId:
1031 Owner = OwnerId[Arch]
1032 self._LastItem = self._Store(
1033 self._ItemType,
1034 self._ValueList[0],
1035 self._ValueList[1],
1036 self._ValueList[2],
1037 Arch,
1038 ModuleType,
1039 DefaultStore,
1040 Owner,
1041 self._From,
1042 self._LineIndex + 1,
1043 - 1,
1044 self._LineIndex + 1,
1045 - 1,
1046 self._Enabled
1047 )
1048 if self._SubsectionType == MODEL_UNKNOWN and self._InSubsection:
1049 OwnerId[Arch] = self._LastItem
1050
1051 if self._DirectiveStack:
1052 Type, Line, Text = self._DirectiveStack[-1]
1053 EdkLogger.error('Parser', FORMAT_INVALID, "No matching '!endif' found",
1054 ExtraData=Text, File=self.MetaFile, Line=Line)
1055 self._Done()
1056
1057 ## <subsection_header> parser
1058 def _SubsectionHeaderParser(self):
1059 self._SubsectionName = self._CurrentLine[1:-1].upper()
1060 if self._SubsectionName in self.DataType:
1061 self._SubsectionType = self.DataType[self._SubsectionName]
1062 else:
1063 self._SubsectionType = MODEL_UNKNOWN
1064 EdkLogger.warn("Parser", "Unrecognized sub-section", File=self.MetaFile,
1065 Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1066 self._ValueList[0] = self._SubsectionName
1067
1068 ## Directive statement parser
1069 def _DirectiveParser(self):
1070 self._ValueList = ['', '', '']
1071 TokenList = GetSplitValueList(self._CurrentLine, ' ', 1)
1072 self._ValueList[0:len(TokenList)] = TokenList
1073
1074 # Syntax check
1075 DirectiveName = self._ValueList[0].upper()
1076 if DirectiveName not in self.DataType:
1077 EdkLogger.error("Parser", FORMAT_INVALID, "Unknown directive [%s]" % DirectiveName,
1078 File=self.MetaFile, Line=self._LineIndex + 1)
1079
1080 if DirectiveName in ['!IF', '!IFDEF', '!IFNDEF']:
1081 self._InDirective += 1
1082
1083 if DirectiveName in ['!ENDIF']:
1084 self._InDirective -= 1
1085
1086 if DirectiveName in ['!IF', '!IFDEF', '!INCLUDE', '!IFNDEF', '!ELSEIF'] and self._ValueList[1] == '':
1087 EdkLogger.error("Parser", FORMAT_INVALID, "Missing expression",
1088 File=self.MetaFile, Line=self._LineIndex + 1,
1089 ExtraData=self._CurrentLine)
1090
1091 ItemType = self.DataType[DirectiveName]
1092 Scope = [[TAB_COMMON, TAB_COMMON, TAB_COMMON]]
1093 if ItemType == MODEL_META_DATA_INCLUDE:
1094 Scope = self._Scope
1095 elif ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR:
1096 Scope = self._Scope
1097 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1098 # Remove all directives between !if and !endif, including themselves
1099 while self._DirectiveStack:
1100 # Remove any !else or !elseif
1101 DirectiveInfo = self._DirectiveStack.pop()
1102 if DirectiveInfo[0] in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1103 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1104 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1105 break
1106 else:
1107 EdkLogger.error("Parser", FORMAT_INVALID, "Redundant '!endif'",
1108 File=self.MetaFile, Line=self._LineIndex + 1,
1109 ExtraData=self._CurrentLine)
1110 elif ItemType not in {MODEL_META_DATA_INCLUDE, MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR}:
1111 # Break if there's a !else is followed by a !elseif
1112 if ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF and \
1113 self._DirectiveStack and \
1114 self._DirectiveStack[-1][0] == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1115 EdkLogger.error("Parser", FORMAT_INVALID, "'!elseif' after '!else'",
1116 File=self.MetaFile, Line=self._LineIndex + 1,
1117 ExtraData=self._CurrentLine)
1118 self._DirectiveStack.append((ItemType, self._LineIndex + 1, self._CurrentLine))
1119
1120 #
1121 # Model, Value1, Value2, Value3, Arch, ModuleType, BelongsToItem=-1, BelongsToFile=-1,
1122 # LineBegin=-1, ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, Enabled=-1
1123 #
1124 for Arch, ModuleType, DefaultStore in Scope:
1125 self._LastItem = self._Store(
1126 ItemType,
1127 self._ValueList[0],
1128 self._ValueList[1],
1129 self._ValueList[2],
1130 Arch,
1131 ModuleType,
1132 DefaultStore,
1133 self._Owner[-1],
1134 self._From,
1135 self._LineIndex + 1,
1136 - 1,
1137 self._LineIndex + 1,
1138 - 1,
1139 0
1140 )
1141
1142 ## [defines] section parser
1143 @ParseMacro
1144 def _DefineParser(self):
1145 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1146 self._ValueList[1:len(TokenList)] = TokenList
1147
1148 # Syntax check
1149 if not self._ValueList[1]:
1150 EdkLogger.error('Parser', FORMAT_INVALID, "No name specified",
1151 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1152 if not self._ValueList[2]:
1153 EdkLogger.error('Parser', FORMAT_INVALID, "No value specified",
1154 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1155 if (not self._ValueList[1] in self.DefineKeywords and
1156 (self._InSubsection and self._ValueList[1] not in self.SubSectionDefineKeywords)):
1157 EdkLogger.error('Parser', FORMAT_INVALID,
1158 "Unknown keyword found: %s. "
1159 "If this is a macro you must "
1160 "add it as a DEFINE in the DSC" % self._ValueList[1],
1161 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1162 if not self._InSubsection:
1163 self._Defines[self._ValueList[1]] = self._ValueList[2]
1164 self._ItemType = self.DataType[TAB_DSC_DEFINES.upper()]
1165
1166 @ParseMacro
1167 def _SkuIdParser(self):
1168 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1169 if len(TokenList) not in (2, 3):
1170 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>[|<UiName>]'",
1171 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1172 self._ValueList[0:len(TokenList)] = TokenList
1173 @ParseMacro
1174 def _DefaultStoresParser(self):
1175 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1176 if len(TokenList) != 2:
1177 EdkLogger.error('Parser', FORMAT_INVALID, "Correct format is '<Number>|<UiName>'",
1178 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1179 self._ValueList[0:len(TokenList)] = TokenList
1180
1181 ## Parse Edk style of library modules
1182 @ParseMacro
1183 def _LibraryInstanceParser(self):
1184 self._ValueList[0] = self._CurrentLine
1185
1186
1187 def _DecodeCODEData(self):
1188 pass
1189 ## PCD sections parser
1190 #
1191 # [PcdsFixedAtBuild]
1192 # [PcdsPatchableInModule]
1193 # [PcdsFeatureFlag]
1194 # [PcdsDynamicEx
1195 # [PcdsDynamicExDefault]
1196 # [PcdsDynamicExVpd]
1197 # [PcdsDynamicExHii]
1198 # [PcdsDynamic]
1199 # [PcdsDynamicDefault]
1200 # [PcdsDynamicVpd]
1201 # [PcdsDynamicHii]
1202 #
1203 @ParseMacro
1204 def _PcdParser(self):
1205 if self._PcdDataTypeCODE:
1206 self._PcdCodeValue = self._PcdCodeValue + "\n " + self._CurrentLine
1207 if self._CurrentLine.endswith(")}"):
1208 self._CurrentLine = "|".join((self._CurrentPcdName, self._PcdCodeValue))
1209 self._PcdDataTypeCODE = False
1210 self._PcdCodeValue = ""
1211 else:
1212 self._ValueList = None
1213 return
1214 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
1215 self._CurrentPcdName = TokenList[0]
1216 if len(TokenList) == 2 and TokenList[1].strip().startswith("{CODE"):
1217 self._PcdDataTypeCODE = True
1218 self._PcdCodeValue = TokenList[1].strip()
1219
1220 if self._PcdDataTypeCODE:
1221 if self._CurrentLine.endswith(")}"):
1222 self._PcdDataTypeCODE = False
1223 self._PcdCodeValue = ""
1224 else:
1225 self._ValueList = None
1226 return
1227 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
1228 PcdNameTockens = GetSplitValueList(TokenList[0], TAB_SPLIT)
1229 if len(PcdNameTockens) == 2:
1230 self._ValueList[0], self._ValueList[1] = PcdNameTockens[0], PcdNameTockens[1]
1231 elif len(PcdNameTockens) == 3:
1232 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), PcdNameTockens[2]
1233 elif len(PcdNameTockens) > 3:
1234 self._ValueList[0], self._ValueList[1] = ".".join((PcdNameTockens[0], PcdNameTockens[1])), ".".join(PcdNameTockens[2:])
1235 if len(TokenList) == 2:
1236 self._ValueList[2] = TokenList[1]
1237 if self._ValueList[0] == '' or self._ValueList[1] == '':
1238 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
1239 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1240 File=self.MetaFile, Line=self._LineIndex + 1)
1241 if self._ValueList[2] == '':
1242 #
1243 # The PCD values are optional for FIXEDATBUILD, PATCHABLEINMODULE, Dynamic/DynamicEx default
1244 #
1245 if self._SectionType in (MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT):
1246 return
1247 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD value given",
1248 ExtraData=self._CurrentLine + " (<TokenSpaceGuidCName>.<TokenCName>|<PcdValue>)",
1249 File=self.MetaFile, Line=self._LineIndex + 1)
1250
1251 # Validate the datum type of Dynamic Defaul PCD and DynamicEx Default PCD
1252 ValueList = GetSplitValueList(self._ValueList[2])
1253 if len(ValueList) > 1 and ValueList[1] in [TAB_UINT8, TAB_UINT16, TAB_UINT32, TAB_UINT64] \
1254 and self._ItemType in [MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT]:
1255 EdkLogger.error('Parser', FORMAT_INVALID, "The datum type '%s' of PCD is wrong" % ValueList[1],
1256 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1257
1258 # Validate the VariableName of DynamicHii and DynamicExHii for PCD Entry must not be an empty string
1259 if self._ItemType in [MODEL_PCD_DYNAMIC_HII, MODEL_PCD_DYNAMIC_EX_HII]:
1260 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1261 if len(DscPcdValueList[0].replace('L', '').replace('"', '').strip()) == 0:
1262 EdkLogger.error('Parser', FORMAT_INVALID, "The VariableName field in the HII format PCD entry must not be an empty string",
1263 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
1264
1265 # if value are 'True', 'true', 'TRUE' or 'False', 'false', 'FALSE', replace with integer 1 or 0.
1266 DscPcdValueList = GetSplitValueList(TokenList[1], TAB_VALUE_SPLIT, 1)
1267 if DscPcdValueList[0] in ['True', 'true', 'TRUE']:
1268 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '1', 1);
1269 elif DscPcdValueList[0] in ['False', 'false', 'FALSE']:
1270 self._ValueList[2] = TokenList[1].replace(DscPcdValueList[0], '0', 1);
1271
1272
1273 ## [components] section parser
1274 @ParseMacro
1275 def _ComponentParser(self):
1276 if self._CurrentLine[-1] == '{':
1277 self._ValueList[0] = self._CurrentLine[0:-1].strip()
1278 self._InSubsection = True
1279 self._SubsectionType = MODEL_UNKNOWN
1280 else:
1281 self._ValueList[0] = self._CurrentLine
1282
1283 ## [LibraryClasses] section
1284 @ParseMacro
1285 def _LibraryClassParser(self):
1286 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT)
1287 if len(TokenList) < 2:
1288 EdkLogger.error('Parser', FORMAT_INVALID, "No library class or instance specified",
1289 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1290 File=self.MetaFile, Line=self._LineIndex + 1)
1291 if TokenList[0] == '':
1292 EdkLogger.error('Parser', FORMAT_INVALID, "No library class specified",
1293 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1294 File=self.MetaFile, Line=self._LineIndex + 1)
1295 if TokenList[1] == '':
1296 EdkLogger.error('Parser', FORMAT_INVALID, "No library instance specified",
1297 ExtraData=self._CurrentLine + " (<LibraryClassName>|<LibraryInstancePath>)",
1298 File=self.MetaFile, Line=self._LineIndex + 1)
1299
1300 self._ValueList[0:len(TokenList)] = TokenList
1301
1302
1303 ## [BuildOptions] section parser
1304 @ParseMacro
1305 def _BuildOptionParser(self):
1306 self._CurrentLine = CleanString(self._CurrentLine, BuildOption=True)
1307 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1308 TokenList2 = GetSplitValueList(TokenList[0], ':', 1)
1309 if len(TokenList2) == 2:
1310 self._ValueList[0] = TokenList2[0] # toolchain family
1311 self._ValueList[1] = TokenList2[1] # keys
1312 else:
1313 self._ValueList[1] = TokenList[0]
1314 if len(TokenList) == 2: # value
1315 self._ValueList[2] = TokenList[1]
1316
1317 if self._ValueList[1].count('_') != 4:
1318 EdkLogger.error(
1319 'Parser',
1320 FORMAT_INVALID,
1321 "'%s' must be in format of <TARGET>_<TOOLCHAIN>_<ARCH>_<TOOL>_FLAGS" % self._ValueList[1],
1322 ExtraData=self._CurrentLine,
1323 File=self.MetaFile,
1324 Line=self._LineIndex + 1
1325 )
1326
1327 ## Override parent's method since we'll do all macro replacements in parser
1328 @property
1329 def _Macros(self):
1330 Macros = {}
1331 Macros.update(self._FileLocalMacros)
1332 Macros.update(self._GetApplicableSectionMacro())
1333 Macros.update(GlobalData.gEdkGlobal)
1334 Macros.update(GlobalData.gPlatformDefines)
1335 Macros.update(GlobalData.gCommandLineDefines)
1336 # PCD cannot be referenced in macro definition
1337 if self._ItemType not in [MODEL_META_DATA_DEFINE, MODEL_META_DATA_GLOBAL_DEFINE]:
1338 Macros.update(self._Symbols)
1339 if GlobalData.BuildOptionPcd:
1340 for Item in GlobalData.BuildOptionPcd:
1341 if isinstance(Item, tuple):
1342 continue
1343 PcdName, TmpValue = Item.split("=")
1344 TmpValue = BuildOptionValue(TmpValue, self._GuidDict)
1345 Macros[PcdName.strip()] = TmpValue
1346 return Macros
1347
1348 def _PostProcess(self):
1349 Processer = {
1350 MODEL_META_DATA_SECTION_HEADER : self.__ProcessSectionHeader,
1351 MODEL_META_DATA_SUBSECTION_HEADER : self.__ProcessSubsectionHeader,
1352 MODEL_META_DATA_HEADER : self.__ProcessDefine,
1353 MODEL_META_DATA_DEFINE : self.__ProcessDefine,
1354 MODEL_META_DATA_GLOBAL_DEFINE : self.__ProcessDefine,
1355 MODEL_META_DATA_INCLUDE : self.__ProcessDirective,
1356 MODEL_META_DATA_PACKAGE : self.__ProcessPackages,
1357 MODEL_META_DATA_CONDITIONAL_STATEMENT_IF : self.__ProcessDirective,
1358 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE : self.__ProcessDirective,
1359 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF : self.__ProcessDirective,
1360 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF : self.__ProcessDirective,
1361 MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF : self.__ProcessDirective,
1362 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF : self.__ProcessDirective,
1363 MODEL_EFI_SKU_ID : self.__ProcessSkuId,
1364 MODEL_EFI_DEFAULT_STORES : self.__ProcessDefaultStores,
1365 MODEL_EFI_LIBRARY_INSTANCE : self.__ProcessLibraryInstance,
1366 MODEL_EFI_LIBRARY_CLASS : self.__ProcessLibraryClass,
1367 MODEL_PCD_FIXED_AT_BUILD : self.__ProcessPcd,
1368 MODEL_PCD_PATCHABLE_IN_MODULE : self.__ProcessPcd,
1369 MODEL_PCD_FEATURE_FLAG : self.__ProcessPcd,
1370 MODEL_PCD_DYNAMIC_DEFAULT : self.__ProcessPcd,
1371 MODEL_PCD_DYNAMIC_HII : self.__ProcessPcd,
1372 MODEL_PCD_DYNAMIC_VPD : self.__ProcessPcd,
1373 MODEL_PCD_DYNAMIC_EX_DEFAULT : self.__ProcessPcd,
1374 MODEL_PCD_DYNAMIC_EX_HII : self.__ProcessPcd,
1375 MODEL_PCD_DYNAMIC_EX_VPD : self.__ProcessPcd,
1376 MODEL_META_DATA_COMPONENT : self.__ProcessComponent,
1377 MODEL_META_DATA_BUILD_OPTION : self.__ProcessBuildOption,
1378 MODEL_UNKNOWN : self._Skip,
1379 MODEL_META_DATA_USER_EXTENSION : self._SkipUserExtension,
1380 MODEL_META_DATA_CONDITIONAL_STATEMENT_ERROR : self._ProcessError,
1381 }
1382
1383 self._Table = MetaFileStorage(self._RawTable.DB, self.MetaFile, MODEL_FILE_DSC, True)
1384 self._DirectiveStack = []
1385 self._DirectiveEvalStack = []
1386 self._FileWithError = self.MetaFile
1387 self._FileLocalMacros = {}
1388 self._SectionsMacroDict.clear()
1389 GlobalData.gPlatformDefines = {}
1390
1391 # Get all macro and PCD which has straitforward value
1392 self.__RetrievePcdValue()
1393 self._Content = self._RawTable.GetAll()
1394 self._ContentIndex = 0
1395 self._InSubsection = False
1396 while self._ContentIndex < len(self._Content) :
1397 Id, self._ItemType, V1, V2, V3, S1, S2, S3, Owner, self._From, \
1398 LineStart, ColStart, LineEnd, ColEnd, Enabled = self._Content[self._ContentIndex]
1399
1400 if self._From < 0:
1401 self._FileWithError = self.MetaFile
1402
1403 self._ContentIndex += 1
1404
1405 self._Scope = [[S1, S2, S3]]
1406 #
1407 # For !include directive, handle it specially,
1408 # merge arch and module type in case of duplicate items
1409 #
1410 while self._ItemType == MODEL_META_DATA_INCLUDE:
1411 if self._ContentIndex >= len(self._Content):
1412 break
1413 Record = self._Content[self._ContentIndex]
1414 if LineStart == Record[10] and LineEnd == Record[12]:
1415 if [Record[5], Record[6], Record[7]] not in self._Scope:
1416 self._Scope.append([Record[5], Record[6], Record[7]])
1417 self._ContentIndex += 1
1418 else:
1419 break
1420
1421 self._LineIndex = LineStart - 1
1422 self._ValueList = [V1, V2, V3]
1423
1424 if Owner > 0 and Owner in self._IdMapping:
1425 self._InSubsection = True
1426 else:
1427 self._InSubsection = False
1428 try:
1429 Processer[self._ItemType]()
1430 except EvaluationException as Excpt:
1431 #
1432 # Only catch expression evaluation error here. We need to report
1433 # the precise number of line on which the error occurred
1434 #
1435 if hasattr(Excpt, 'Pcd'):
1436 if Excpt.Pcd in GlobalData.gPlatformOtherPcds:
1437 Info = GlobalData.gPlatformOtherPcds[Excpt.Pcd]
1438 EdkLogger.error('Parser', FORMAT_INVALID, "Cannot use this PCD (%s) in an expression as"
1439 " it must be defined in a [PcdsFixedAtBuild] or [PcdsFeatureFlag] section"
1440 " of the DSC file, and it is currently defined in this section:"
1441 " %s, line #: %d." % (Excpt.Pcd, Info[0], Info[1]),
1442 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1443 Line=self._LineIndex + 1)
1444 else:
1445 EdkLogger.error('Parser', FORMAT_INVALID, "PCD (%s) is not defined in DSC file" % Excpt.Pcd,
1446 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1447 Line=self._LineIndex + 1)
1448 else:
1449 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid expression: %s" % str(Excpt),
1450 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1451 Line=self._LineIndex + 1)
1452 except MacroException as Excpt:
1453 EdkLogger.error('Parser', FORMAT_INVALID, str(Excpt),
1454 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1455 Line=self._LineIndex + 1)
1456
1457 if self._ValueList is None:
1458 continue
1459
1460 NewOwner = self._IdMapping.get(Owner, -1)
1461 self._Enabled = int((not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack))
1462 self._LastItem = self._Store(
1463 self._ItemType,
1464 self._ValueList[0],
1465 self._ValueList[1],
1466 self._ValueList[2],
1467 S1,
1468 S2,
1469 S3,
1470 NewOwner,
1471 self._From,
1472 self._LineIndex + 1,
1473 - 1,
1474 self._LineIndex + 1,
1475 - 1,
1476 self._Enabled
1477 )
1478 self._IdMapping[Id] = self._LastItem
1479
1480 GlobalData.gPlatformDefines.update(self._FileLocalMacros)
1481 self._PostProcessed = True
1482 self._Content = None
1483 def _ProcessError(self):
1484 if not self._Enabled:
1485 return
1486 EdkLogger.error('Parser', ERROR_STATEMENT, self._ValueList[1], File=self.MetaFile, Line=self._LineIndex + 1)
1487
1488 def __ProcessSectionHeader(self):
1489 self._SectionName = self._ValueList[0]
1490 if self._SectionName in self.DataType:
1491 self._SectionType = self.DataType[self._SectionName]
1492 else:
1493 self._SectionType = MODEL_UNKNOWN
1494
1495 def __ProcessSubsectionHeader(self):
1496 self._SubsectionName = self._ValueList[0]
1497 if self._SubsectionName in self.DataType:
1498 self._SubsectionType = self.DataType[self._SubsectionName]
1499 else:
1500 self._SubsectionType = MODEL_UNKNOWN
1501
1502 def __RetrievePcdValue(self):
1503 try:
1504 with open(str(self.MetaFile), 'r') as File:
1505 Content = File.readlines()
1506 except:
1507 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1508
1509 GlobalData.gPlatformOtherPcds['DSCFILE'] = str(self.MetaFile)
1510 for PcdType in (MODEL_PCD_PATCHABLE_IN_MODULE, MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_HII,
1511 MODEL_PCD_DYNAMIC_VPD, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_DYNAMIC_EX_HII,
1512 MODEL_PCD_DYNAMIC_EX_VPD):
1513 Records = self._RawTable.Query(PcdType, BelongsToItem= -1.0)
1514 for TokenSpaceGuid, PcdName, Value, Dummy2, Dummy3, Dummy4, ID, Line in Records:
1515 Name = TokenSpaceGuid + '.' + PcdName
1516 if Name not in GlobalData.gPlatformOtherPcds:
1517 PcdLine = Line
1518 while not Content[Line - 1].lstrip().startswith(TAB_SECTION_START):
1519 Line -= 1
1520 GlobalData.gPlatformOtherPcds[Name] = (CleanString(Content[Line - 1]), PcdLine, PcdType)
1521
1522 def __ProcessDefine(self):
1523 if not self._Enabled:
1524 return
1525
1526 Type, Name, Value = self._ValueList
1527 Value = ReplaceMacro(Value, self._Macros, False)
1528 #
1529 # If it is <Defines>, return
1530 #
1531 if self._InSubsection:
1532 self._ValueList = [Type, Name, Value]
1533 return
1534
1535 if self._ItemType == MODEL_META_DATA_DEFINE:
1536 if self._SectionType == MODEL_META_DATA_HEADER:
1537 self._FileLocalMacros[Name] = Value
1538 else:
1539 self._ConstructSectionMacroDict(Name, Value)
1540 elif self._ItemType == MODEL_META_DATA_GLOBAL_DEFINE:
1541 GlobalData.gEdkGlobal[Name] = Value
1542
1543 #
1544 # Keyword in [Defines] section can be used as Macros
1545 #
1546 if (self._ItemType == MODEL_META_DATA_HEADER) and (self._SectionType == MODEL_META_DATA_HEADER):
1547 self._FileLocalMacros[Name] = Value
1548
1549 self._ValueList = [Type, Name, Value]
1550
1551 def __ProcessDirective(self):
1552 Result = None
1553 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1554 MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF]:
1555 Macros = self._Macros
1556 Macros.update(GlobalData.gGlobalDefines)
1557 try:
1558 Result = ValueExpression(self._ValueList[1], Macros)()
1559 except SymbolNotFound as Exc:
1560 EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc), self._ValueList[1])
1561 Result = False
1562 except WrnExpression as Excpt:
1563 #
1564 # Catch expression evaluation warning here. We need to report
1565 # the precise number of line and return the evaluation result
1566 #
1567 EdkLogger.warn('Parser', "Suspicious expression: %s" % str(Excpt),
1568 File=self._FileWithError, ExtraData=' '.join(self._ValueList),
1569 Line=self._LineIndex + 1)
1570 Result = Excpt.result
1571
1572 if self._ItemType in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1573 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1574 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1575 self._DirectiveStack.append(self._ItemType)
1576 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IF:
1577 Result = bool(Result)
1578 else:
1579 Macro = self._ValueList[1]
1580 Macro = Macro[2:-1] if (Macro.startswith("$(") and Macro.endswith(")")) else Macro
1581 Result = Macro in self._Macros
1582 if self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF:
1583 Result = not Result
1584 self._DirectiveEvalStack.append(Result)
1585 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSEIF:
1586 self._DirectiveStack.append(self._ItemType)
1587 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1588 self._DirectiveEvalStack.append(bool(Result))
1589 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ELSE:
1590 self._DirectiveStack.append(self._ItemType)
1591 self._DirectiveEvalStack[-1] = not self._DirectiveEvalStack[-1]
1592 self._DirectiveEvalStack.append(True)
1593 elif self._ItemType == MODEL_META_DATA_CONDITIONAL_STATEMENT_ENDIF:
1594 # Back to the nearest !if/!ifdef/!ifndef
1595 while self._DirectiveStack:
1596 self._DirectiveEvalStack.pop()
1597 Directive = self._DirectiveStack.pop()
1598 if Directive in [MODEL_META_DATA_CONDITIONAL_STATEMENT_IF,
1599 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFDEF,
1600 MODEL_META_DATA_CONDITIONAL_STATEMENT_IFNDEF]:
1601 break
1602 elif self._ItemType == MODEL_META_DATA_INCLUDE:
1603 # The included file must be relative to workspace or same directory as DSC file
1604 __IncludeMacros = {}
1605 #
1606 # Allow using system environment variables in path after !include
1607 #
1608 __IncludeMacros['WORKSPACE'] = GlobalData.gGlobalDefines['WORKSPACE']
1609 #
1610 # Allow using MACROs comes from [Defines] section to keep compatible.
1611 #
1612 __IncludeMacros.update(self._Macros)
1613
1614 IncludedFile = NormPath(ReplaceMacro(self._ValueList[1], __IncludeMacros, RaiseError=True))
1615 #
1616 # First search the include file under the same directory as DSC file
1617 #
1618 IncludedFile1 = PathClass(IncludedFile, self.MetaFile.Dir)
1619 if self._Enabled:
1620 ErrorCode, ErrorInfo1 = IncludedFile1.Validate()
1621 if ErrorCode != 0:
1622 #
1623 # Also search file under the WORKSPACE directory
1624 #
1625 IncludedFile1 = PathClass(IncludedFile, GlobalData.gWorkspace)
1626 ErrorCode, ErrorInfo2 = IncludedFile1.Validate()
1627 if ErrorCode != 0:
1628 EdkLogger.error('parser', ErrorCode, File=self._FileWithError,
1629 Line=self._LineIndex + 1, ExtraData=ErrorInfo1 + "\n" + ErrorInfo2)
1630
1631 self._FileWithError = IncludedFile1
1632
1633 FromItem = self._Content[self._ContentIndex - 1][0]
1634 if self._InSubsection:
1635 Owner = self._Content[self._ContentIndex - 1][8]
1636 else:
1637 Owner = self._Content[self._ContentIndex - 1][0]
1638 IncludedFileTable = MetaFileStorage(self._RawTable.DB, IncludedFile1, MODEL_FILE_DSC, False, FromItem=FromItem)
1639 Parser = DscParser(IncludedFile1, self._FileType, self._Arch, IncludedFileTable,
1640 Owner=Owner, From=FromItem)
1641
1642 self.IncludedFiles.add (IncludedFile1)
1643
1644 # set the parser status with current status
1645 Parser._SectionName = self._SectionName
1646 Parser._SubsectionType = self._SubsectionType
1647 Parser._InSubsection = self._InSubsection
1648 Parser._SectionType = self._SectionType
1649 Parser._Scope = self._Scope
1650 Parser._Enabled = self._Enabled
1651 # Parse the included file
1652 Parser.StartParse()
1653 # Insert all records in the table for the included file into dsc file table
1654 Records = IncludedFileTable.GetAll()
1655 if Records:
1656 self._Content[self._ContentIndex:self._ContentIndex] = Records
1657 self._Content.pop(self._ContentIndex - 1)
1658 self._ValueList = None
1659 self._ContentIndex -= 1
1660
1661 def __ProcessPackages(self):
1662 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1663
1664 def __ProcessSkuId(self):
1665 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1666 for Value in self._ValueList]
1667 def __ProcessDefaultStores(self):
1668 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=True)
1669 for Value in self._ValueList]
1670
1671 def __ProcessLibraryInstance(self):
1672 self._ValueList = [ReplaceMacro(Value, self._Macros) for Value in self._ValueList]
1673
1674 def __ProcessLibraryClass(self):
1675 self._ValueList[1] = ReplaceMacro(self._ValueList[1], self._Macros, RaiseError=True)
1676
1677 def __ProcessPcd(self):
1678 if self._ItemType not in [MODEL_PCD_FEATURE_FLAG, MODEL_PCD_FIXED_AT_BUILD]:
1679 self._ValueList[2] = ReplaceMacro(self._ValueList[2], self._Macros, RaiseError=True)
1680 return
1681
1682 ValList, Valid, Index = AnalyzeDscPcd(self._ValueList[2], self._ItemType)
1683 if not Valid:
1684 if self._ItemType in (MODEL_PCD_DYNAMIC_DEFAULT, MODEL_PCD_DYNAMIC_EX_DEFAULT, MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE):
1685 if ValList[1] != TAB_VOID and StructPattern.match(ValList[1]) is None and ValList[2]:
1686 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect. The datum type info should be VOID* or a valid struct name.", File=self._FileWithError,
1687 Line=self._LineIndex + 1, ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1688 EdkLogger.error('build', FORMAT_INVALID, "Pcd format incorrect.", File=self._FileWithError, Line=self._LineIndex + 1,
1689 ExtraData="%s.%s|%s" % (self._ValueList[0], self._ValueList[1], self._ValueList[2]))
1690 PcdValue = ValList[Index]
1691 if PcdValue and "." not in self._ValueList[0]:
1692 try:
1693 ValList[Index] = ValueExpression(PcdValue, self._Macros)(True)
1694 except WrnExpression as Value:
1695 ValList[Index] = Value.result
1696 except:
1697 pass
1698
1699 if ValList[Index] == 'True':
1700 ValList[Index] = '1'
1701 if ValList[Index] == 'False':
1702 ValList[Index] = '0'
1703
1704 if (not self._DirectiveEvalStack) or (False not in self._DirectiveEvalStack):
1705 GlobalData.gPlatformPcds[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1706 self._Symbols[TAB_SPLIT.join(self._ValueList[0:2])] = PcdValue
1707 try:
1708 self._ValueList[2] = '|'.join(ValList)
1709 except Exception:
1710 print(ValList)
1711
1712 def __ProcessComponent(self):
1713 self._ValueList[0] = ReplaceMacro(self._ValueList[0], self._Macros)
1714
1715 def __ProcessBuildOption(self):
1716 self._ValueList = [ReplaceMacro(Value, self._Macros, RaiseError=False)
1717 for Value in self._ValueList]
1718
1719 def DisableOverrideComponent(self,module_id):
1720 for ori_id in self._IdMapping:
1721 if self._IdMapping[ori_id] == module_id:
1722 self._RawTable.DisableComponent(ori_id)
1723
1724 _SectionParser = {
1725 MODEL_META_DATA_HEADER : _DefineParser,
1726 MODEL_EFI_SKU_ID : _SkuIdParser,
1727 MODEL_EFI_DEFAULT_STORES : _DefaultStoresParser,
1728 MODEL_EFI_LIBRARY_INSTANCE : _LibraryInstanceParser,
1729 MODEL_EFI_LIBRARY_CLASS : _LibraryClassParser,
1730 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
1731 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
1732 MODEL_PCD_FEATURE_FLAG : _PcdParser,
1733 MODEL_PCD_DYNAMIC_DEFAULT : _PcdParser,
1734 MODEL_PCD_DYNAMIC_HII : _PcdParser,
1735 MODEL_PCD_DYNAMIC_VPD : _PcdParser,
1736 MODEL_PCD_DYNAMIC_EX_DEFAULT : _PcdParser,
1737 MODEL_PCD_DYNAMIC_EX_HII : _PcdParser,
1738 MODEL_PCD_DYNAMIC_EX_VPD : _PcdParser,
1739 MODEL_META_DATA_COMPONENT : _ComponentParser,
1740 MODEL_META_DATA_BUILD_OPTION : _BuildOptionParser,
1741 MODEL_UNKNOWN : MetaFileParser._Skip,
1742 MODEL_META_DATA_PACKAGE : MetaFileParser._PackageParser,
1743 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
1744 MODEL_META_DATA_SECTION_HEADER : MetaFileParser._SectionHeaderParser,
1745 MODEL_META_DATA_SUBSECTION_HEADER : _SubsectionHeaderParser,
1746 }
1747
1748 ## DEC file parser class
1749 #
1750 # @param FilePath The path of platform description file
1751 # @param FileType The raw data of DSC file
1752 # @param Table Database used to retrieve module/package information
1753 # @param Macros Macros used for replacement in file
1754 #
1755 class DecParser(MetaFileParser):
1756 # DEC file supported data types (one type per section)
1757 DataType = {
1758 TAB_DEC_DEFINES.upper() : MODEL_META_DATA_HEADER,
1759 TAB_DSC_DEFINES_DEFINE : MODEL_META_DATA_DEFINE,
1760 TAB_INCLUDES.upper() : MODEL_EFI_INCLUDE,
1761 TAB_LIBRARY_CLASSES.upper() : MODEL_EFI_LIBRARY_CLASS,
1762 TAB_GUIDS.upper() : MODEL_EFI_GUID,
1763 TAB_PPIS.upper() : MODEL_EFI_PPI,
1764 TAB_PROTOCOLS.upper() : MODEL_EFI_PROTOCOL,
1765 TAB_PCDS_FIXED_AT_BUILD_NULL.upper() : MODEL_PCD_FIXED_AT_BUILD,
1766 TAB_PCDS_PATCHABLE_IN_MODULE_NULL.upper() : MODEL_PCD_PATCHABLE_IN_MODULE,
1767 TAB_PCDS_FEATURE_FLAG_NULL.upper() : MODEL_PCD_FEATURE_FLAG,
1768 TAB_PCDS_DYNAMIC_NULL.upper() : MODEL_PCD_DYNAMIC,
1769 TAB_PCDS_DYNAMIC_EX_NULL.upper() : MODEL_PCD_DYNAMIC_EX,
1770 TAB_USER_EXTENSIONS.upper() : MODEL_META_DATA_USER_EXTENSION,
1771 }
1772
1773 ## Constructor of DecParser
1774 #
1775 # Initialize object of DecParser
1776 #
1777 # @param FilePath The path of platform description file
1778 # @param FileType The raw data of DSC file
1779 # @param Arch Default Arch value for filtering sections
1780 # @param Table Database used to retrieve module/package information
1781 #
1782 def __init__(self, FilePath, FileType, Arch, Table):
1783 # prevent re-initialization
1784 if hasattr(self, "_Table"):
1785 return
1786 MetaFileParser.__init__(self, FilePath, FileType, Arch, Table, -1)
1787 self._Comments = []
1788 self._Version = 0x00010005 # Only EDK2 dec file is supported
1789 self._AllPCDs = [] # Only for check duplicate PCD
1790 self._AllPcdDict = {}
1791
1792 self._CurrentStructurePcdName = ""
1793 self._include_flag = False
1794 self._package_flag = False
1795
1796 self._RestofValue = ""
1797
1798 ## Parser starter
1799 def Start(self):
1800 Content = ''
1801 try:
1802 with open(str(self.MetaFile), 'r') as File:
1803 Content = File.readlines()
1804 except:
1805 EdkLogger.error("Parser", FILE_READ_FAILURE, ExtraData=self.MetaFile)
1806
1807 Content = self.ProcessMultipleLineCODEValue(Content)
1808
1809 self._DefinesCount = 0
1810 for Index in range(0, len(Content)):
1811 Line, Comment = CleanString2(Content[Index])
1812 self._CurrentLine = Line
1813 self._LineIndex = Index
1814
1815 # save comment for later use
1816 if Comment:
1817 self._Comments.append((Comment, self._LineIndex + 1))
1818 # skip empty line
1819 if Line == '':
1820 continue
1821
1822 # section header
1823 if Line[0] == TAB_SECTION_START and Line[-1] == TAB_SECTION_END:
1824 self._SectionHeaderParser()
1825 if self._SectionName == TAB_DEC_DEFINES.upper():
1826 self._DefinesCount += 1
1827 self._Comments = []
1828 continue
1829 if self._SectionType == MODEL_UNKNOWN:
1830 EdkLogger.error("Parser", FORMAT_INVALID,
1831 ""
1832 "Not able to determine \"%s\" in which section."%self._CurrentLine,
1833 self.MetaFile, self._LineIndex + 1)
1834 elif len(self._SectionType) == 0:
1835 self._Comments = []
1836 continue
1837
1838 # section content
1839 self._ValueList = ['', '', '']
1840 self._SectionParser[self._SectionType[0]](self)
1841 if self._ValueList is None or self._ItemType == MODEL_META_DATA_DEFINE:
1842 self._ItemType = -1
1843 self._Comments = []
1844 continue
1845
1846 #
1847 # Model, Value1, Value2, Value3, Arch, BelongsToItem=-1, LineBegin=-1,
1848 # ColumnBegin=-1, LineEnd=-1, ColumnEnd=-1, FeatureFlag='', Enabled=-1
1849 #
1850 for Arch, ModuleType, Type in self._Scope:
1851 self._LastItem = self._Store(
1852 Type,
1853 self._ValueList[0],
1854 self._ValueList[1],
1855 self._ValueList[2],
1856 Arch,
1857 ModuleType,
1858 self._Owner[-1],
1859 self._LineIndex + 1,
1860 - 1,
1861 self._LineIndex + 1,
1862 - 1,
1863 0
1864 )
1865 for Comment, LineNo in self._Comments:
1866 self._Store(
1867 MODEL_META_DATA_COMMENT,
1868 Comment,
1869 self._ValueList[0],
1870 self._ValueList[1],
1871 Arch,
1872 ModuleType,
1873 self._LastItem,
1874 LineNo,
1875 - 1,
1876 LineNo,
1877 - 1,
1878 0
1879 )
1880 self._Comments = []
1881 if self._DefinesCount > 1:
1882 EdkLogger.error('Parser', FORMAT_INVALID, 'Multiple [Defines] section is exist.', self.MetaFile )
1883 if self._DefinesCount == 0:
1884 EdkLogger.error('Parser', FORMAT_INVALID, 'No [Defines] section exist.', self.MetaFile)
1885 self._Done()
1886
1887
1888 ## Section header parser
1889 #
1890 # The section header is always in following format:
1891 #
1892 # [section_name.arch<.platform|module_type>]
1893 #
1894 def _SectionHeaderParser(self):
1895 self._Scope = []
1896 self._SectionName = ''
1897 self._SectionType = []
1898 ArchList = set()
1899 PrivateList = set()
1900 Line = re.sub(',[\s]*', TAB_COMMA_SPLIT, self._CurrentLine)
1901 for Item in Line[1:-1].split(TAB_COMMA_SPLIT):
1902 if Item == '':
1903 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR,
1904 "section name can NOT be empty or incorrectly use separator comma",
1905 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1906 ItemList = Item.split(TAB_SPLIT)
1907
1908 # different types of PCD are permissible in one section
1909 self._SectionName = ItemList[0].upper()
1910 if self._SectionName == TAB_DEC_DEFINES.upper() and (len(ItemList) > 1 or len(Line.split(TAB_COMMA_SPLIT)) > 1):
1911 EdkLogger.error("Parser", FORMAT_INVALID, "Defines section format is invalid",
1912 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1913 if self._SectionName in self.DataType:
1914 if self.DataType[self._SectionName] not in self._SectionType:
1915 self._SectionType.append(self.DataType[self._SectionName])
1916 else:
1917 EdkLogger.error("Parser", FORMAT_UNKNOWN_ERROR, "%s is not a valid section name" % Item,
1918 self.MetaFile, self._LineIndex + 1, self._CurrentLine)
1919
1920 if MODEL_PCD_FEATURE_FLAG in self._SectionType and len(self._SectionType) > 1:
1921 EdkLogger.error(
1922 'Parser',
1923 FORMAT_INVALID,
1924 "%s must not be in the same section of other types of PCD" % TAB_PCDS_FEATURE_FLAG_NULL,
1925 File=self.MetaFile,
1926 Line=self._LineIndex + 1,
1927 ExtraData=self._CurrentLine
1928 )
1929 # S1 is always Arch
1930 if len(ItemList) > 1:
1931 S1 = ItemList[1].upper()
1932 else:
1933 S1 = TAB_ARCH_COMMON
1934 ArchList.add(S1)
1935 # S2 may be Platform or ModuleType
1936 if len(ItemList) > 2:
1937 S2 = ItemList[2].upper()
1938 # only Includes, GUIDs, PPIs, Protocols section have Private tag
1939 if self._SectionName in [TAB_INCLUDES.upper(), TAB_GUIDS.upper(), TAB_PROTOCOLS.upper(), TAB_PPIS.upper()]:
1940 if S2 != 'PRIVATE':
1941 EdkLogger.error("Parser", FORMAT_INVALID, 'Please use keyword "Private" as section tag modifier.',
1942 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1943 else:
1944 S2 = TAB_COMMON
1945 PrivateList.add(S2)
1946 if [S1, S2, self.DataType[self._SectionName]] not in self._Scope:
1947 self._Scope.append([S1, S2, self.DataType[self._SectionName]])
1948
1949 # 'COMMON' must not be used with specific ARCHs at the same section
1950 if TAB_ARCH_COMMON in ArchList and len(ArchList) > 1:
1951 EdkLogger.error('Parser', FORMAT_INVALID, "'common' ARCH must not be used with specific ARCHs",
1952 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1953
1954 # It is not permissible to mix section tags without the Private attribute with section tags with the Private attribute
1955 if TAB_COMMON in PrivateList and len(PrivateList) > 1:
1956 EdkLogger.error('Parser', FORMAT_INVALID, "Can't mix section tags without the Private attribute with section tags with the Private attribute",
1957 File=self.MetaFile, Line=self._LineIndex + 1, ExtraData=self._CurrentLine)
1958
1959 ## [guids], [ppis] and [protocols] section parser
1960 @ParseMacro
1961 def _GuidParser(self):
1962 TokenList = GetSplitValueList(self._CurrentLine, TAB_EQUAL_SPLIT, 1)
1963 if len(TokenList) < 2:
1964 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name or value specified",
1965 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1966 File=self.MetaFile, Line=self._LineIndex + 1)
1967 if TokenList[0] == '':
1968 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID name specified",
1969 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1970 File=self.MetaFile, Line=self._LineIndex + 1)
1971 if TokenList[1] == '':
1972 EdkLogger.error('Parser', FORMAT_INVALID, "No GUID value specified",
1973 ExtraData=self._CurrentLine + " (<CName> = <GuidValueInCFormat>)",
1974 File=self.MetaFile, Line=self._LineIndex + 1)
1975 if TokenList[1][0] != '{' or TokenList[1][-1] != '}' or GuidStructureStringToGuidString(TokenList[1]) == '':
1976 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid GUID value format",
1977 ExtraData=self._CurrentLine + \
1978 " (<CName> = <GuidValueInCFormat:{8,4,4,{2,2,2,2,2,2,2,2}}>)",
1979 File=self.MetaFile, Line=self._LineIndex + 1)
1980 self._ValueList[0] = TokenList[0]
1981 self._ValueList[1] = TokenList[1]
1982 if self._ValueList[0] not in self._GuidDict:
1983 self._GuidDict[self._ValueList[0]] = self._ValueList[1]
1984
1985 def ParsePcdName(self,namelist):
1986 if "[" in namelist[1]:
1987 pcdname = namelist[1][:namelist[1].index("[")]
1988 arrayindex = namelist[1][namelist[1].index("["):]
1989 namelist[1] = pcdname
1990 if len(namelist) == 2:
1991 namelist.append(arrayindex)
1992 else:
1993 namelist[2] = ".".join((arrayindex,namelist[2]))
1994 return namelist
1995
1996 ## PCD sections parser
1997 #
1998 # [PcdsFixedAtBuild]
1999 # [PcdsPatchableInModule]
2000 # [PcdsFeatureFlag]
2001 # [PcdsDynamicEx
2002 # [PcdsDynamic]
2003 #
2004 @ParseMacro
2005 def _PcdParser(self):
2006
2007 if self._CurrentStructurePcdName:
2008 self._ValueList[0] = self._CurrentStructurePcdName
2009
2010 if "|" not in self._CurrentLine:
2011 if "<HeaderFiles>" == self._CurrentLine:
2012 self._include_flag = True
2013 self._package_flag = False
2014 self._ValueList = None
2015 return
2016 if "<Packages>" == self._CurrentLine:
2017 self._package_flag = True
2018 self._ValueList = None
2019 self._include_flag = False
2020 return
2021
2022 if self._include_flag:
2023 self._ValueList[1] = "<HeaderFiles>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()
2024 self._ValueList[2] = self._CurrentLine
2025 if self._package_flag and "}" != self._CurrentLine:
2026 self._ValueList[1] = "<Packages>_" + md5(self._CurrentLine.encode('utf-8')).hexdigest()
2027 self._ValueList[2] = self._CurrentLine
2028 if self._CurrentLine == "}":
2029 self._package_flag = False
2030 self._include_flag = False
2031 self._ValueList = None
2032 return
2033 else:
2034 PcdTockens = self._CurrentLine.split(TAB_VALUE_SPLIT)
2035 PcdNames = self.ParsePcdName(PcdTockens[0].split(TAB_SPLIT))
2036 if len(PcdNames) == 2:
2037 if PcdNames[1].strip().endswith("]"):
2038 PcdName = PcdNames[1][:PcdNames[1].index('[')]
2039 Index = PcdNames[1][PcdNames[1].index('['):]
2040 self._ValueList[0] = TAB_SPLIT.join((PcdNames[0],PcdName))
2041 self._ValueList[1] = Index
2042 self._ValueList[2] = PcdTockens[1]
2043 else:
2044 self._CurrentStructurePcdName = ""
2045 else:
2046 if self._CurrentStructurePcdName != TAB_SPLIT.join(PcdNames[:2]):
2047 EdkLogger.error('Parser', FORMAT_INVALID, "Pcd Name does not match: %s and %s " % (self._CurrentStructurePcdName, TAB_SPLIT.join(PcdNames[:2])),
2048 File=self.MetaFile, Line=self._LineIndex + 1)
2049 self._ValueList[1] = TAB_SPLIT.join(PcdNames[2:])
2050 self._ValueList[2] = PcdTockens[1]
2051 if not self._CurrentStructurePcdName:
2052 if self._PcdDataTypeCODE:
2053 if ")}" in self._CurrentLine:
2054 ValuePart,RestofValue = self._CurrentLine.split(")}")
2055 self._PcdCodeValue = self._PcdCodeValue + "\n " + ValuePart
2056 self._CurrentLine = "|".join((self._CurrentPcdName, self._PcdCodeValue,RestofValue))
2057 self._PcdDataTypeCODE = False
2058 self._PcdCodeValue = ""
2059 else:
2060 self._PcdCodeValue = self._PcdCodeValue + "\n " + self._CurrentLine
2061 self._ValueList = None
2062 return
2063 TokenList = GetSplitValueList(self._CurrentLine, TAB_VALUE_SPLIT, 1)
2064 self._CurrentPcdName = TokenList[0]
2065 if len(TokenList) == 2 and TokenList[1].strip().startswith("{CODE"):
2066 if ")}" in self._CurrentLine:
2067 self._PcdDataTypeCODE = False
2068 self._PcdCodeValue = ""
2069 else:
2070 self._PcdDataTypeCODE = True
2071 self._PcdCodeValue = TokenList[1].strip()
2072 self._ValueList = None
2073 return
2074
2075 self._ValueList[0:1] = GetSplitValueList(TokenList[0], TAB_SPLIT)
2076 ValueRe = re.compile(r'^[a-zA-Z_][a-zA-Z0-9_]*')
2077 # check PCD information
2078 if self._ValueList[0] == '' or self._ValueList[1] == '':
2079 EdkLogger.error('Parser', FORMAT_INVALID, "No token space GUID or PCD name specified",
2080 ExtraData=self._CurrentLine + \
2081 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2082 File=self.MetaFile, Line=self._LineIndex + 1)
2083 # check format of token space GUID CName
2084 if not ValueRe.match(self._ValueList[0]):
2085 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the token space GUID CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
2086 ExtraData=self._CurrentLine + \
2087 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2088 File=self.MetaFile, Line=self._LineIndex + 1)
2089 # check format of PCD CName
2090 if not ValueRe.match(self._ValueList[1]):
2091 EdkLogger.error('Parser', FORMAT_INVALID, "The format of the PCD CName is invalid. The correct format is '(a-zA-Z_)[a-zA-Z0-9_]*'",
2092 ExtraData=self._CurrentLine + \
2093 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2094 File=self.MetaFile, Line=self._LineIndex + 1)
2095 # check PCD datum information
2096 if len(TokenList) < 2 or TokenList[1] == '':
2097 EdkLogger.error('Parser', FORMAT_INVALID, "No PCD Datum information given",
2098 ExtraData=self._CurrentLine + \
2099 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2100 File=self.MetaFile, Line=self._LineIndex + 1)
2101
2102
2103 ValueRe = re.compile(r'^\s*L?\".*\|.*\"')
2104 PtrValue = ValueRe.findall(TokenList[1])
2105
2106 # Has VOID* type string, may contain "|" character in the string.
2107 if len(PtrValue) != 0:
2108 ptrValueList = re.sub(ValueRe, '', TokenList[1])
2109 ValueList = AnalyzePcdExpression(ptrValueList)
2110 ValueList[0] = PtrValue[0]
2111 else:
2112 ValueList = AnalyzePcdExpression(TokenList[1])
2113
2114
2115 # check if there's enough datum information given
2116 if len(ValueList) != 3:
2117 EdkLogger.error('Parser', FORMAT_INVALID, "Invalid PCD Datum information given",
2118 ExtraData=self._CurrentLine + \
2119 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2120 File=self.MetaFile, Line=self._LineIndex + 1)
2121 # check default value
2122 if ValueList[0] == '':
2123 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DefaultValue in PCD Datum information",
2124 ExtraData=self._CurrentLine + \
2125 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2126 File=self.MetaFile, Line=self._LineIndex + 1)
2127 # check datum type
2128 if ValueList[1] == '':
2129 EdkLogger.error('Parser', FORMAT_INVALID, "Missing DatumType in PCD Datum information",
2130 ExtraData=self._CurrentLine + \
2131 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2132 File=self.MetaFile, Line=self._LineIndex + 1)
2133 # check token of the PCD
2134 if ValueList[2] == '':
2135 EdkLogger.error('Parser', FORMAT_INVALID, "Missing Token in PCD Datum information",
2136 ExtraData=self._CurrentLine + \
2137 " (<TokenSpaceGuidCName>.<PcdCName>|<DefaultValue>|<DatumType>|<Token>)",
2138 File=self.MetaFile, Line=self._LineIndex + 1)
2139
2140 PcdValue = ValueList[0]
2141 if PcdValue:
2142 try:
2143 self._GuidDict.update(self._AllPcdDict)
2144 ValueList[0] = ValueExpressionEx(ValueList[0], ValueList[1], self._GuidDict)(True)
2145 except BadExpression as Value:
2146 EdkLogger.error('Parser', FORMAT_INVALID, Value, ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
2147 # check format of default value against the datum type
2148 IsValid, Cause = CheckPcdDatum(ValueList[1], ValueList[0])
2149 if not IsValid:
2150 EdkLogger.error('Parser', FORMAT_INVALID, Cause, ExtraData=self._CurrentLine,
2151 File=self.MetaFile, Line=self._LineIndex + 1)
2152
2153 if Cause == "StructurePcd":
2154 self._CurrentStructurePcdName = TAB_SPLIT.join(self._ValueList[0:2])
2155 self._ValueList[0] = self._CurrentStructurePcdName
2156 self._ValueList[1] = ValueList[1].strip()
2157
2158 if ValueList[0] in ['True', 'true', 'TRUE']:
2159 ValueList[0] = '1'
2160 elif ValueList[0] in ['False', 'false', 'FALSE']:
2161 ValueList[0] = '0'
2162
2163 # check for duplicate PCD definition
2164 if (self._Scope[0], self._ValueList[0], self._ValueList[1]) in self._AllPCDs:
2165 EdkLogger.error('Parser', FORMAT_INVALID,
2166 "The same PCD name and GUID have been already defined",
2167 ExtraData=self._CurrentLine, File=self.MetaFile, Line=self._LineIndex + 1)
2168 else:
2169 self._AllPCDs.append((self._Scope[0], self._ValueList[0], self._ValueList[1]))
2170 self._AllPcdDict[TAB_SPLIT.join(self._ValueList[0:2])] = ValueList[0]
2171
2172 self._ValueList[2] = ValueList[0].strip() + '|' + ValueList[1].strip() + '|' + ValueList[2].strip()
2173
2174 _SectionParser = {
2175 MODEL_META_DATA_HEADER : MetaFileParser._DefineParser,
2176 MODEL_EFI_INCLUDE : MetaFileParser._PathParser,
2177 MODEL_EFI_LIBRARY_CLASS : MetaFileParser._PathParser,
2178 MODEL_EFI_GUID : _GuidParser,
2179 MODEL_EFI_PPI : _GuidParser,
2180 MODEL_EFI_PROTOCOL : _GuidParser,
2181 MODEL_PCD_FIXED_AT_BUILD : _PcdParser,
2182 MODEL_PCD_PATCHABLE_IN_MODULE : _PcdParser,
2183 MODEL_PCD_FEATURE_FLAG : _PcdParser,
2184 MODEL_PCD_DYNAMIC : _PcdParser,
2185 MODEL_PCD_DYNAMIC_EX : _PcdParser,
2186 MODEL_UNKNOWN : MetaFileParser._Skip,
2187 MODEL_META_DATA_USER_EXTENSION : MetaFileParser._SkipUserExtension,
2188 }
2189
2190 ##
2191 #
2192 # This acts like the main() function for the script, unless it is 'import'ed into another
2193 # script.
2194 #
2195 if __name__ == '__main__':
2196 pass
2197