]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/Parser/InfSectionParser.py
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / BaseTools / Source / Python / UPT / Parser / InfSectionParser.py
1 ## @file
2 # This file contained the parser for sections in INF file
3 #
4 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 #
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 '''
10 InfSectionParser
11 '''
12 ##
13 # Import Modules
14 #
15 from copy import deepcopy
16 import re
17
18 from Library.StringUtils import GetSplitValueList
19 from Library.CommentParsing import ParseHeaderCommentSection
20 from Library.CommentParsing import ParseComment
21
22 from Library import DataType as DT
23
24 import Logger.Log as Logger
25 from Logger import StringTable as ST
26 from Logger.ToolError import FORMAT_INVALID
27
28 from Object.Parser.InfDefineObject import InfDefObject
29 from Object.Parser.InfBuildOptionObject import InfBuildOptionsObject
30 from Object.Parser.InfLibraryClassesObject import InfLibraryClassObject
31 from Object.Parser.InfPackagesObject import InfPackageObject
32 from Object.Parser.InfPcdObject import InfPcdObject
33 from Object.Parser.InfSoucesObject import InfSourcesObject
34 from Object.Parser.InfUserExtensionObject import InfUserExtensionObject
35 from Object.Parser.InfProtocolObject import InfProtocolObject
36 from Object.Parser.InfPpiObject import InfPpiObject
37 from Object.Parser.InfGuidObject import InfGuidObject
38 from Object.Parser.InfDepexObject import InfDepexObject
39 from Object.Parser.InfBinaryObject import InfBinariesObject
40 from Object.Parser.InfHeaderObject import InfHeaderObject
41 from Object.Parser.InfMisc import InfSpecialCommentObject
42 from Object.Parser.InfMisc import InfHobObject
43 from Object.Parser.InfMisc import InfBootModeObject
44 from Object.Parser.InfMisc import InfEventObject
45 from Parser.InfParserMisc import gINF_SECTION_DEF
46 from Parser.InfDefineSectionParser import InfDefinSectionParser
47 from Parser.InfBuildOptionSectionParser import InfBuildOptionSectionParser
48 from Parser.InfSourceSectionParser import InfSourceSectionParser
49 from Parser.InfLibrarySectionParser import InfLibrarySectionParser
50 from Parser.InfPackageSectionParser import InfPackageSectionParser
51 from Parser.InfGuidPpiProtocolSectionParser import InfGuidPpiProtocolSectionParser
52 from Parser.InfBinarySectionParser import InfBinarySectionParser
53 from Parser.InfPcdSectionParser import InfPcdSectionParser
54 from Parser.InfDepexSectionParser import InfDepexSectionParser
55
56 ## GetSpecialStr2
57 #
58 # GetSpecialStr2
59 #
60 def GetSpecialStr2(ItemList, FileName, LineNo, SectionString):
61 Str2 = ''
62 #
63 # S2 may be Platform or ModuleType
64 #
65 if len(ItemList) == 3:
66 #
67 # Except [LibraryClass], [Depex]
68 # section can has more than 2 items in section header string,
69 # others should report error.
70 #
71 if not (ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() or \
72 ItemList[0].upper() == DT.TAB_DEPEX.upper() or \
73 ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper()):
74 if ItemList[2] != '':
75 Logger.Error('Parser',
76 FORMAT_INVALID,
77 ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID % (SectionString),
78 File=FileName,
79 Line=LineNo,
80 ExtraData=SectionString)
81 Str2 = ItemList[2]
82 elif len(ItemList) == 4:
83 #
84 # Except [UserExtension]
85 # section can has 4 items in section header string,
86 # others should report error.
87 #
88 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper() or ItemList[0].upper() == DT.TAB_DEPEX.upper():
89 if ItemList[3] != '':
90 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
91 % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
92
93 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
94 Str2 = ItemList[2] + ' | ' + ItemList[3]
95 else:
96 Str2 = ItemList[2]
97
98 elif len(ItemList) > 4:
99 Logger.Error('Parser', FORMAT_INVALID, ST.ERR_INF_PARSER_SOURCE_SECTION_SECTIONNAME_INVALID \
100 % (SectionString), File=FileName, Line=LineNo, ExtraData=SectionString)
101
102 return Str2
103
104 ## ProcessUseExtHeader
105 #
106 #
107 def ProcessUseExtHeader(ItemList):
108 NewItemList = []
109 AppendContent = ''
110 CompleteFlag = False
111 for Item in ItemList:
112 if Item.startswith('\"') and not Item.endswith('\"'):
113 AppendContent = Item
114 CompleteFlag = True
115 elif Item.endswith('\"') and not Item.startswith('\"'):
116 #
117 # Should not have an userId or IdString not starts with " before but ends with ".
118 #
119 if not CompleteFlag:
120 return False, []
121 AppendContent = AppendContent + "." + Item
122 NewItemList.append(AppendContent)
123 CompleteFlag = False
124 AppendContent = ''
125 elif Item.endswith('\"') and Item.startswith('\"'):
126 #
127 # Common item, not need to combine the information
128 #
129 NewItemList.append(Item)
130 else:
131 if not CompleteFlag:
132 NewItemList.append(Item)
133 else:
134 AppendContent = AppendContent + "." + Item
135
136 if len(NewItemList) > 4:
137 return False, []
138
139 return True, NewItemList
140
141 ## GetArch
142 #
143 # GetArch
144 #
145 def GetArch(ItemList, ArchList, FileName, LineNo, SectionString):
146 #
147 # S1 is always Arch
148 #
149 if len(ItemList) > 1:
150 Arch = ItemList[1]
151 else:
152 Arch = 'COMMON'
153 ArchList.add(Arch)
154
155 #
156 # 'COMMON' must not be used with specific ARCHs at the same section
157 #
158 if 'COMMON' in ArchList and len(ArchList) > 1:
159 Logger.Error('Parser',
160 FORMAT_INVALID,
161 ST.ERR_INF_PARSER_SECTION_ARCH_CONFLICT,
162 File=FileName,
163 Line=LineNo,
164 ExtraData=SectionString)
165
166 return Arch, ArchList
167
168 ## InfSectionParser
169 #
170 # Inherit from object
171 #
172 class InfSectionParser(InfDefinSectionParser,
173 InfBuildOptionSectionParser,
174 InfSourceSectionParser,
175 InfLibrarySectionParser,
176 InfPackageSectionParser,
177 InfGuidPpiProtocolSectionParser,
178 InfBinarySectionParser,
179 InfPcdSectionParser,
180 InfDepexSectionParser):
181 #
182 # Parser objects used to implement singleton
183 #
184 MetaFiles = {}
185
186 ## Factory method
187 #
188 # One file, one parser object. This factory method makes sure that there's
189 # only one object constructed for one meta file.
190 #
191 # @param Class class object of real AutoGen class
192 # (InfParser, DecParser or DscParser)
193 # @param FilePath The path of meta file
194 #
195 def __new__(cls, FilePath, *args, **kwargs):
196 if args:
197 pass
198 if kwargs:
199 pass
200 if FilePath in cls.MetaFiles:
201 return cls.MetaFiles[FilePath]
202 else:
203 ParserObject = super(InfSectionParser, cls).__new__(cls)
204 cls.MetaFiles[FilePath] = ParserObject
205 return ParserObject
206
207 def __init__(self):
208 InfDefinSectionParser.__init__(self)
209 InfBuildOptionSectionParser.__init__(self)
210 InfSourceSectionParser.__init__(self)
211 InfLibrarySectionParser.__init__(self)
212 InfPackageSectionParser.__init__(self)
213 InfGuidPpiProtocolSectionParser.__init__(self)
214 InfBinarySectionParser.__init__(self)
215 InfPcdSectionParser.__init__(self)
216 InfDepexSectionParser.__init__(self)
217 #
218 # Initialize all objects that an INF file will generated.
219 #
220 self.InfDefSection = InfDefObject()
221 self.InfBuildOptionSection = InfBuildOptionsObject()
222 self.InfLibraryClassSection = InfLibraryClassObject()
223 self.InfPackageSection = InfPackageObject()
224 self.InfPcdSection = InfPcdObject(list(self.MetaFiles.keys())[0])
225 self.InfSourcesSection = InfSourcesObject()
226 self.InfUserExtensionSection = InfUserExtensionObject()
227 self.InfProtocolSection = InfProtocolObject()
228 self.InfPpiSection = InfPpiObject()
229 self.InfGuidSection = InfGuidObject()
230 self.InfDepexSection = InfDepexObject()
231 self.InfPeiDepexSection = InfDepexObject()
232 self.InfDxeDepexSection = InfDepexObject()
233 self.InfSmmDepexSection = InfDepexObject()
234 self.InfBinariesSection = InfBinariesObject()
235 self.InfHeader = InfHeaderObject()
236 self.InfBinaryHeader = InfHeaderObject()
237 self.InfSpecialCommentSection = InfSpecialCommentObject()
238
239 #
240 # A List for store define section content.
241 #
242 self._PcdNameList = []
243 self._SectionName = ''
244 self._SectionType = 0
245 self.RelaPath = ''
246 self.FileName = ''
247
248 #
249 # File Header content parser
250 #
251 def InfHeaderParser(self, Content, InfHeaderObject2, FileName, IsBinaryHeader = False):
252 if IsBinaryHeader:
253 (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName, True)
254 if not Abstract or not Description or not Copyright or not License:
255 Logger.Error('Parser',
256 FORMAT_INVALID,
257 ST.ERR_INVALID_BINARYHEADER_FORMAT,
258 File=FileName)
259 else:
260 (Abstract, Description, Copyright, License) = ParseHeaderCommentSection(Content, FileName)
261 #
262 # Not process file name now, for later usage.
263 #
264 if self.FileName:
265 pass
266
267 #
268 # Insert Abstract, Description, CopyRight, License into header object
269 #
270 InfHeaderObject2.SetAbstract(Abstract)
271 InfHeaderObject2.SetDescription(Description)
272 InfHeaderObject2.SetCopyright(Copyright)
273 InfHeaderObject2.SetLicense(License)
274
275
276
277
278 ## Section header parser
279 #
280 # The section header is always in following format:
281 #
282 # [section_name.arch<.platform|module_type>]
283 #
284 # @param String A string contained the content need to be parsed.
285 #
286 def SectionHeaderParser(self, SectionString, FileName, LineNo):
287 _Scope = []
288 _SectionName = ''
289 ArchList = set()
290 _ValueList = []
291 _PcdNameList = [DT.TAB_INF_FIXED_PCD.upper(),
292 DT.TAB_INF_FEATURE_PCD.upper(),
293 DT.TAB_INF_PATCH_PCD.upper(),
294 DT.TAB_INF_PCD.upper(),
295 DT.TAB_INF_PCD_EX.upper()
296 ]
297 SectionString = SectionString.strip()
298 for Item in GetSplitValueList(SectionString[1:-1], DT.TAB_COMMA_SPLIT):
299 if Item == '':
300 Logger.Error('Parser',
301 FORMAT_INVALID,
302 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
303 File=FileName,
304 Line=LineNo,
305 ExtraData=SectionString)
306 ItemList = GetSplitValueList(Item, DT.TAB_SPLIT)
307 #
308 # different section should not mix in one section
309 # Allow different PCD type sections mixed together
310 #
311 if _SectionName.upper() not in _PcdNameList:
312 if _SectionName != '' and _SectionName.upper() != ItemList[0].upper():
313 Logger.Error('Parser',
314 FORMAT_INVALID,
315 ST.ERR_INF_PARSER_SECTION_NAME_DUPLICATE,
316 File=FileName,
317 Line=LineNo,
318 ExtraData=SectionString)
319 elif _PcdNameList[1] in [_SectionName.upper(), ItemList[0].upper()] and \
320 (_SectionName.upper()!= ItemList[0].upper()):
321 Logger.Error('Parser',
322 FORMAT_INVALID,
323 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (""),
324 File=FileName,
325 Line=LineNo,
326 ExtraData=SectionString)
327
328 _SectionName = ItemList[0]
329 if _SectionName.upper() in gINF_SECTION_DEF:
330 self._SectionType = gINF_SECTION_DEF[_SectionName.upper()]
331 else:
332 self._SectionType = DT.MODEL_UNKNOWN
333 Logger.Error("Parser",
334 FORMAT_INVALID,
335 ST.ERR_INF_PARSER_UNKNOWN_SECTION,
336 File=FileName,
337 Line=LineNo,
338 ExtraData=SectionString)
339
340 #
341 # Get Arch
342 #
343 Str1, ArchList = GetArch(ItemList, ArchList, FileName, LineNo, SectionString)
344
345 #
346 # For [Defines] section, do special check.
347 #
348 if ItemList[0].upper() == DT.TAB_COMMON_DEFINES.upper():
349 if len(ItemList) != 1:
350 Logger.Error('Parser',
351 FORMAT_INVALID,
352 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
353 File=FileName, Line=LineNo, ExtraData=SectionString)
354
355 #
356 # For [UserExtension] section, do special check.
357 #
358 if ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
359
360 RetValue = ProcessUseExtHeader(ItemList)
361
362 if not RetValue[0]:
363 Logger.Error('Parser',
364 FORMAT_INVALID,
365 ST.ERR_INF_PARSER_DEFINE_FROMAT_INVALID % (SectionString),
366 File=FileName, Line=LineNo, ExtraData=SectionString)
367 else:
368 ItemList = RetValue[1]
369
370 if len(ItemList) == 3:
371 ItemList.append('COMMON')
372
373 Str1 = ItemList[1]
374
375 #
376 # For Library classes, need to check module type.
377 #
378 if ItemList[0].upper() == DT.TAB_LIBRARY_CLASSES.upper() and len(ItemList) == 3:
379 if ItemList[2] != '':
380 ModuleTypeList = GetSplitValueList(ItemList[2], DT.TAB_VALUE_SPLIT)
381 for Item in ModuleTypeList:
382 if Item.strip() not in DT.MODULE_LIST:
383 Logger.Error('Parser',
384 FORMAT_INVALID,
385 ST.ERR_INF_PARSER_DEFINE_MODULETYPE_INVALID % (Item),
386 File=FileName,
387 Line=LineNo,
388 ExtraData=SectionString)
389 #
390 # GetSpecialStr2
391 #
392 Str2 = GetSpecialStr2(ItemList, FileName, LineNo, SectionString)
393
394 _Scope.append([Str1, Str2])
395
396 _NewValueList = []
397 _AppendFlag = True
398 if _SectionName.upper() in _PcdNameList:
399 for ValueItem in _ValueList:
400 if _SectionName.upper() == ValueItem[0].upper() and Str1.upper() not in ValueItem[1].split():
401 ValueItem[1] = ValueItem[1] + " " + Str1
402 _AppendFlag = False
403 elif _SectionName.upper() == ValueItem[0].upper() and Str1.upper() in ValueItem[1].split():
404 _AppendFlag = False
405
406 _NewValueList.append(ValueItem)
407
408 _ValueList = _NewValueList
409
410 if _AppendFlag:
411 if not ItemList[0].upper() == DT.TAB_USER_EXTENSIONS.upper():
412 _ValueList.append([_SectionName, Str1, Str2, LineNo])
413 else:
414 if len(ItemList) == 4:
415 _ValueList.append([_SectionName, Str1, Str2, ItemList[3], LineNo])
416
417 self.SectionHeaderContent = deepcopy(_ValueList)
418
419 ## GenSpecialSectionList
420 #
421 # @param SpecialSectionList: a list of list, of which item's format
422 # (Comment, LineNum)
423 # @param ContainerFile: Input value for filename of Inf file
424 #
425 def InfSpecialCommentParser (self, SpecialSectionList, InfSectionObject, ContainerFile, SectionType):
426 ReFindSpecialCommentRe = re.compile(r"""#(?:\s*)\[(.*?)\](?:.*)""", re.DOTALL)
427 ReFindHobArchRe = re.compile(r"""[Hh][Oo][Bb]\.([^,]*)""", re.DOTALL)
428 if self.FileName:
429 pass
430 SpecialObjectList = []
431 ArchList = []
432 if SectionType == DT.TYPE_EVENT_SECTION:
433 TokenDict = DT.EVENT_TOKENS
434 elif SectionType == DT.TYPE_HOB_SECTION:
435 TokenDict = DT.HOB_TOKENS
436 else:
437 TokenDict = DT.BOOTMODE_TOKENS
438
439 for List in SpecialSectionList:
440 #
441 # Hob has Arch attribute, need to be handled specially here
442 #
443 if SectionType == DT.TYPE_HOB_SECTION:
444
445 MatchObject = ReFindSpecialCommentRe.search(List[0][0])
446 HobSectionStr = MatchObject.group(1)
447 ArchList = []
448 for Match in ReFindHobArchRe.finditer(HobSectionStr):
449 Arch = Match.groups(1)[0].upper()
450 ArchList.append(Arch)
451 CommentSoFar = ''
452 for Index in range(1, len(List)):
453 Result = ParseComment(List[Index], DT.ALL_USAGE_TOKENS, TokenDict, [], False)
454 Usage = Result[0]
455 Type = Result[1]
456 HelpText = Result[3]
457
458 if Usage == DT.ITEM_UNDEFINED and Type == DT.ITEM_UNDEFINED:
459 if HelpText is None:
460 HelpText = ''
461 if not HelpText.endswith('\n'):
462 HelpText += '\n'
463 CommentSoFar += HelpText
464 else:
465 if HelpText:
466 CommentSoFar += HelpText
467 if SectionType == DT.TYPE_EVENT_SECTION:
468 SpecialObject = InfEventObject()
469 SpecialObject.SetEventType(Type)
470 SpecialObject.SetUsage(Usage)
471 SpecialObject.SetHelpString(CommentSoFar)
472 elif SectionType == DT.TYPE_HOB_SECTION:
473 SpecialObject = InfHobObject()
474 SpecialObject.SetHobType(Type)
475 SpecialObject.SetUsage(Usage)
476 SpecialObject.SetHelpString(CommentSoFar)
477 if len(ArchList) >= 1:
478 SpecialObject.SetSupArchList(ArchList)
479 else:
480 SpecialObject = InfBootModeObject()
481 SpecialObject.SetSupportedBootModes(Type)
482 SpecialObject.SetUsage(Usage)
483 SpecialObject.SetHelpString(CommentSoFar)
484
485 SpecialObjectList.append(SpecialObject)
486 CommentSoFar = ''
487 if not InfSectionObject.SetSpecialComments(SpecialObjectList,
488 SectionType):
489 Logger.Error('InfParser',
490 FORMAT_INVALID,
491 ST.ERR_INF_PARSER_MODULE_SECTION_TYPE_ERROR % (SectionType),
492 ContainerFile
493 )