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