2 # This file is used to define class objects of INF file [Pcds] section.
3 # It will consumed by InfParser.
5 # Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
7 # This program and the accompanying materials are licensed and made available
8 # under the terms and conditions of the BSD License which accompanies this
9 # distribution. The full text of the license may be found at
10 # http://opensource.org/licenses/bsd-license.php
12 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 from Logger
import StringTable
as ST
22 from Logger
import ToolError
23 import Logger
.Log
as Logger
24 from Library
import GlobalData
25 from Library
import DataType
as DT
27 from Library
.Misc
import Sdict
28 from Library
.Misc
import GetHelpStringByRemoveHashKey
29 from Library
.ParserValidate
import IsValidPcdType
30 from Library
.ParserValidate
import IsValidCVariableName
31 from Library
.ParserValidate
import IsValidPcdValue
32 from Library
.ParserValidate
import IsValidArch
33 from Library
.CommentParsing
import ParseComment
34 from Library
.String
import GetSplitValueList
35 from Library
.String
import IsHexDigitUINT32
36 from Library
.ExpressionValidate
import IsValidFeatureFlagExp
37 from Parser
.InfAsBuiltProcess
import GetPackageListInfo
38 from Parser
.DecParser
import Dec
40 from Object
.Parser
.InfPackagesObject
import InfPackageItem
42 def ValidateArch(ArchItem
, PcdTypeItem1
, LineNo
, SupArchDict
, SupArchList
):
46 if (ArchItem
== '' or ArchItem
== None):
49 if PcdTypeItem1
.upper
!= DT
.TAB_INF_FEATURE_PCD
.upper():
50 ArchList
= GetSplitValueList(ArchItem
, ' ')
51 for ArchItemNew
in ArchList
:
52 if not IsValidArch(ArchItemNew
):
53 Logger
.Error("InfParser",
54 ToolError
.FORMAT_INVALID
,
55 ST
.ERR_INF_PARSER_DEFINE_FROMAT_INVALID
%(ArchItemNew),
56 File
=GlobalData
.gINF_MODULE_NAME
,
58 ExtraData
=ArchItemNew
)
59 SupArchDict
[PcdTypeItem1
] = ArchList
61 SupArchList
.append(ArchItem
)
63 return SupArchList
, SupArchDict
65 def ParsePcdComment(CommentList
, PcdTypeItem
, PcdItemObj
):
71 CommentItemHelpText
= ''
73 for CommentItem
in CommentList
:
75 CommentItemUsage
, CommentType
, CommentString
, CommentItemHelpText
= ParseComment(CommentItem
,
80 if CommentType
and CommentString
:
83 if PcdTypeItem
== 'FeaturePcd':
84 CommentItemUsage
= DT
.USAGE_ITEM_CONSUMES
85 if CommentItemHelpText
== None:
86 CommentItemHelpText
= ''
89 FFEHelpText
= CommentItemHelpText
91 FFEHelpText
= FFEHelpText
+ DT
.END_OF_LINE
+ CommentItemHelpText
93 if Count
== len(CommentList
):
94 CommentItemHelpText
= FFEHelpText
99 if CommentItemHelpText
== None:
100 CommentItemHelpText
= ''
101 if Count
== len(CommentList
) and CommentItemUsage
== DT
.ITEM_UNDEFINED
:
102 CommentItemHelpText
= DT
.END_OF_LINE
104 if Count
== len(CommentList
) and (BlockFlag
== 1 or BlockFlag
== 2):
105 if CommentItemUsage
== DT
.ITEM_UNDEFINED
:
109 elif BlockFlag
== -1 and Count
== len(CommentList
):
112 if BlockFlag
== -1 or BlockFlag
== 1 or BlockFlag
== 2:
113 if CommentItemUsage
== DT
.ITEM_UNDEFINED
:
119 if BlockFlag
== 1 or BlockFlag
== 2:
121 elif BlockFlag
== -1:
124 # Combine two comment line if they are generic comment
126 if CommentItemUsage
== PreUsage
== DT
.ITEM_UNDEFINED
:
127 CommentItemHelpText
= PreHelpText
+ DT
.END_OF_LINE
+ CommentItemHelpText
129 PreHelpText
= CommentItemHelpText
132 CommentItemIns
= InfPcdItemCommentContent()
133 CommentItemIns
.SetUsageItem(CommentItemUsage
)
134 CommentItemIns
.SetHelpStringItem(CommentItemHelpText
)
135 CommentInsList
.append(CommentItemIns
)
143 # Add previous help string
145 CommentItemIns
= InfPcdItemCommentContent()
146 CommentItemIns
.SetUsageItem(DT
.ITEM_UNDEFINED
)
147 if PreHelpText
== '' or PreHelpText
.endswith(DT
.END_OF_LINE
):
148 PreHelpText
+= DT
.END_OF_LINE
149 CommentItemIns
.SetHelpStringItem(PreHelpText
)
150 CommentInsList
.append(CommentItemIns
)
152 # Add Current help string
154 CommentItemIns
= InfPcdItemCommentContent()
155 CommentItemIns
.SetUsageItem(CommentItemUsage
)
156 CommentItemIns
.SetHelpStringItem(CommentItemHelpText
)
157 CommentInsList
.append(CommentItemIns
)
164 PreUsage
= CommentItemUsage
165 PreHelpText
= CommentItemHelpText
167 PcdItemObj
.SetHelpStringList(CommentInsList
)
171 class InfPcdItemCommentContent():
174 # ## SOMETIMES_CONSUMES ## HelpString
180 self
.HelpStringItem
= ''
182 def SetUsageItem(self
, UsageItem
):
183 self
.UsageItem
= UsageItem
184 def GetUsageItem(self
):
185 return self
.UsageItem
187 def SetHelpStringItem(self
, HelpStringItem
):
188 self
.HelpStringItem
= HelpStringItem
189 def GetHelpStringItem(self
):
190 return self
.HelpStringItem
194 # This class defined Pcd item used in Module files
196 # @param CName: Input value for CName, default is ''
197 # @param Token: Input value for Token, default is ''
198 # @param TokenSpaceGuidCName: Input value for TokenSpaceGuidCName, default
200 # @param DatumType: Input value for DatumType, default is ''
201 # @param MaxDatumSize: Input value for MaxDatumSize, default is ''
202 # @param DefaultValue: Input value for DefaultValue, default is ''
203 # @param ItemType: Input value for ItemType, default is ''
204 # @param ValidUsage: Input value for ValidUsage, default is []
205 # @param SkuInfoList: Input value for SkuInfoList, default is {}
206 # @param SupModuleList: Input value for SupModuleList, default is []
212 self
.TokenSpaceGuidCName
= ''
213 self
.TokenSpaceGuidValue
= ''
215 self
.MaxDatumSize
= ''
216 self
.DefaultValue
= ''
220 self
.SupModuleList
= []
221 self
.HelpStringList
= []
222 self
.FeatureFlagExp
= ''
223 self
.SupArchList
= []
224 self
.PcdErrorsList
= []
226 def SetCName(self
, CName
):
231 def SetToken(self
, Token
):
236 def SetTokenSpaceGuidCName(self
, TokenSpaceGuidCName
):
237 self
.TokenSpaceGuidCName
= TokenSpaceGuidCName
238 def GetTokenSpaceGuidCName(self
):
239 return self
.TokenSpaceGuidCName
241 def SetTokenSpaceGuidValue(self
, TokenSpaceGuidValue
):
242 self
.TokenSpaceGuidValue
= TokenSpaceGuidValue
243 def GetTokenSpaceGuidValue(self
):
244 return self
.TokenSpaceGuidValue
246 def SetDatumType(self
, DatumType
):
247 self
.DatumType
= DatumType
248 def GetDatumType(self
):
249 return self
.DatumType
251 def SetMaxDatumSize(self
, MaxDatumSize
):
252 self
.MaxDatumSize
= MaxDatumSize
253 def GetMaxDatumSize(self
):
254 return self
.MaxDatumSize
256 def SetDefaultValue(self
, DefaultValue
):
257 self
.DefaultValue
= DefaultValue
258 def GetDefaultValue(self
):
259 return self
.DefaultValue
261 def SetPcdErrorsList(self
, PcdErrorsList
):
262 self
.PcdErrorsList
= PcdErrorsList
263 def GetPcdErrorsList(self
):
264 return self
.PcdErrorsList
266 def SetItemType(self
, ItemType
):
267 self
.ItemType
= ItemType
268 def GetItemType(self
):
271 def SetSupModuleList(self
, SupModuleList
):
272 self
.SupModuleList
= SupModuleList
273 def GetSupModuleList(self
):
274 return self
.SupModuleList
276 def SetHelpStringList(self
, HelpStringList
):
277 self
.HelpStringList
= HelpStringList
278 def GetHelpStringList(self
):
279 return self
.HelpStringList
281 def SetFeatureFlagExp(self
, FeatureFlagExp
):
282 self
.FeatureFlagExp
= FeatureFlagExp
283 def GetFeatureFlagExp(self
):
284 return self
.FeatureFlagExp
286 def SetSupportArchList(self
, ArchList
):
287 self
.SupArchList
= ArchList
288 def GetSupportArchList(self
):
289 return self
.SupArchList
291 def SetOffset(self
, Offset
):
300 class InfPcdObject():
301 def __init__(self
, FileName
):
303 self
.FileName
= FileName
305 def SetPcds(self
, PcdContent
, KeysList
= None, PackageInfo
= None):
307 if GlobalData
.gIS_BINARY_INF
:
308 self
.SetAsBuildPcds(PcdContent
, KeysList
, PackageInfo
)
317 for (PcdTypeItem1
, ArchItem
, LineNo
) in KeysList
:
318 SupArchList
, SupArchDict
= ValidateArch(ArchItem
, PcdTypeItem1
, LineNo
, SupArchDict
, SupArchList
)
323 if (PcdTypeItem1
== '' or PcdTypeItem1
== None):
326 if not IsValidPcdType(PcdTypeItem1
):
327 Logger
.Error("InfParser",
328 ToolError
.FORMAT_INVALID
,
329 ST
.ERR_INF_PARSER_PCD_SECTION_TYPE_ERROR
%(DT
.PCD_USAGE_TYPE_LIST_OF_MODULE
),
330 File
=GlobalData
.gINF_MODULE_NAME
,
332 ExtraData
=PcdTypeItem1
)
335 PcdTypeItem
= PcdTypeItem1
337 for PcdItem
in PcdContent
:
338 PcdItemObj
= InfPcdItem()
339 CommentList
= PcdItem
[1]
340 CurrentLineOfPcdItem
= PcdItem
[2]
343 if CommentList
!= None and len(CommentList
) != 0:
344 PcdItemObj
= ParsePcdComment(CommentList
, PcdTypeItem
, PcdItemObj
)
346 CommentItemIns
= InfPcdItemCommentContent()
347 CommentItemIns
.SetUsageItem(DT
.ITEM_UNDEFINED
)
348 PcdItemObj
.SetHelpStringList([CommentItemIns
])
350 if len(PcdItem
) >= 1 and len(PcdItem
) <= 3:
351 PcdItemObj
= SetPcdName(PcdItem
, CurrentLineOfPcdItem
, PcdItemObj
)
353 if len(PcdItem
) >= 2 and len(PcdItem
) <= 3:
355 # Contain PcdName and Value, validate value.
357 if IsValidPcdValue(PcdItem
[1]) or PcdItem
[1].strip() == "":
358 PcdItemObj
.SetDefaultValue(PcdItem
[1])
360 Logger
.Error("InfParser",
361 ToolError
.FORMAT_INVALID
,
362 ST
.ERR_INF_PARSER_PCD_VALUE_INVALID
,
363 File
=CurrentLineOfPcdItem
[2],
364 Line
=CurrentLineOfPcdItem
[1],
365 ExtraData
=PcdItem
[1])
367 if len(PcdItem
) == 3:
369 # Contain PcdName, value, and FeatureFlag express
372 # Validate Feature Flag Express
374 if PcdItem
[2].strip() == '':
375 Logger
.Error("InfParser",
376 ToolError
.FORMAT_INVALID
,
377 ST
.ERR_INF_PARSER_FEATURE_FLAG_EXP_MISSING
,
378 File
=CurrentLineOfPcdItem
[2],
379 Line
=CurrentLineOfPcdItem
[1],
380 ExtraData
=CurrentLineOfPcdItem
[0])
384 FeatureFlagRtv
= IsValidFeatureFlagExp(PcdItem
[2].strip())
385 if not FeatureFlagRtv
[0]:
386 Logger
.Error("InfParser",
387 ToolError
.FORMAT_INVALID
,
388 ST
.ERR_INF_PARSER_FEATURE_FLAG_EXP_SYNTAX_INVLID
%(FeatureFlagRtv
[1]),
389 File
=CurrentLineOfPcdItem
[2],
390 Line
=CurrentLineOfPcdItem
[1],
391 ExtraData
=CurrentLineOfPcdItem
[0])
392 PcdItemObj
.SetFeatureFlagExp(PcdItem
[2])
394 if len(PcdItem
) < 1 or len(PcdItem
) > 3:
395 Logger
.Error("InfParser",
396 ToolError
.FORMAT_INVALID
,
397 ST
.ERR_INF_PARSER_PCD_SECTION_CONTENT_ERROR
,
398 File
=CurrentLineOfPcdItem
[2],
399 Line
=CurrentLineOfPcdItem
[1],
400 ExtraData
=CurrentLineOfPcdItem
[0])
403 if PcdTypeItem
.upper
!= DT
.TAB_INF_FEATURE_PCD
.upper():
404 PcdItemObj
.SetSupportArchList(SupArchDict
[PcdTypeItem
])
406 PcdItemObj
.SetSupportArchList(SupArchList
)
408 if self
.Pcds
.has_key((PcdTypeItem
, PcdItemObj
)):
409 PcdsList
= self
.Pcds
[PcdTypeItem
, PcdItemObj
]
410 PcdsList
.append(PcdItemObj
)
411 self
.Pcds
[PcdTypeItem
, PcdItemObj
] = PcdsList
414 PcdsList
.append(PcdItemObj
)
415 self
.Pcds
[PcdTypeItem
, PcdItemObj
] = PcdsList
419 def SetAsBuildPcds(self
, PcdContent
, KeysList
= None, PackageInfo
= None):
420 for PcdItem
in PcdContent
:
421 PcdItemObj
= InfPcdItem()
422 CommentList
= PcdItem
[1]
423 CurrentLineOfPcdItem
= PcdItem
[2]
426 for CommmentLine
in CommentList
:
427 CommentString
+= GetHelpStringByRemoveHashKey(CommmentLine
)
429 PcdItemObj
.SetHelpStringList(CommentString
)
430 PcdItemObj
.SetItemType(KeysList
[0][0])
432 # Set PcdTokenSpaceCName and CName
434 PcdItemObj
= SetPcdName(PcdItem
, CurrentLineOfPcdItem
, PcdItemObj
)
436 # Set Value/DatumType/MaxDatumSize/Token
438 PcdItemObj
= SetValueDatumTypeMaxSizeToken(PcdItem
,
439 CurrentLineOfPcdItem
,
444 PcdTypeItem
= KeysList
[0][0]
445 if self
.Pcds
.has_key((PcdTypeItem
, PcdItemObj
)):
446 PcdsList
= self
.Pcds
[PcdTypeItem
, PcdItemObj
]
447 PcdsList
.append(PcdItemObj
)
448 self
.Pcds
[PcdTypeItem
, PcdItemObj
] = PcdsList
451 PcdsList
.append(PcdItemObj
)
452 self
.Pcds
[PcdTypeItem
, PcdItemObj
] = PcdsList
457 def ParserPcdInfoInDec(String
):
458 ValueList
= GetSplitValueList(String
, DT
.TAB_VALUE_SPLIT
, 3)
463 return ValueList
[2], ValueList
[3]
465 def SetValueDatumTypeMaxSizeToken(PcdItem
, CurrentLineOfPcdItem
, PcdItemObj
, Arch
, PackageInfo
= None):
467 # Package information not been generated currently, we need to parser INF file to get information.
471 InfFileName
= CurrentLineOfPcdItem
[2]
472 PackageInfoList
= GetPackageListInfo(InfFileName
, GlobalData
.gWORKSPACE
, -1)
473 for PackageInfoListItem
in PackageInfoList
:
474 PackageInfoIns
= InfPackageItem()
475 PackageInfoIns
.SetPackageName(PackageInfoListItem
)
476 PackageInfo
.append(PackageInfoIns
)
478 PcdInfoInDecHasFound
= False
479 for PackageItem
in PackageInfo
:
480 if PcdInfoInDecHasFound
:
482 PackageName
= PackageItem
.PackageName
484 # Open DEC file to get information
486 FullFileName
= os
.path
.normpath(os
.path
.realpath(os
.path
.join(GlobalData
.gWORKSPACE
, PackageName
)))
488 DecParser
= Dec(FullFileName
)
490 # Find PCD information.
492 DecPcdsDict
= DecParser
.GetPcdSectionObject().ValueDict
493 for Key
in DecPcdsDict
.keys():
494 if (Key
[0] == 'PCDSDYNAMICEX' and PcdItemObj
.GetItemType() == 'PcdEx') and \
495 (Key
[1] == 'COMMON' or Key
[1] == Arch
):
496 for PcdInDec
in DecPcdsDict
[Key
]:
497 if PcdInDec
.TokenCName
== PcdItemObj
.CName
and \
498 PcdInDec
.TokenSpaceGuidCName
== PcdItemObj
.TokenSpaceGuidCName
:
499 PcdItemObj
.SetToken(PcdInDec
.TokenValue
)
500 PcdItemObj
.SetDatumType(PcdInDec
.DatumType
)
501 PcdItemObj
.SetSupportArchList([Arch
])
503 if (Key
[0] == 'PCDSPATCHABLEINMODULE' and PcdItemObj
.GetItemType() == 'PatchPcd') and \
504 (Key
[1] == 'COMMON' or Key
[1] == Arch
):
505 for PcdInDec
in DecPcdsDict
[Key
]:
506 if PcdInDec
.TokenCName
== PcdItemObj
.CName
and \
507 PcdInDec
.TokenSpaceGuidCName
== PcdItemObj
.TokenSpaceGuidCName
:
508 PcdItemObj
.SetToken(PcdInDec
.TokenValue
)
509 PcdItemObj
.SetDatumType(PcdInDec
.DatumType
)
510 PcdItemObj
.SetSupportArchList([Arch
])
512 if PcdItemObj
.GetDatumType() == 'VOID*':
513 PcdItemObj
.SetMaxDatumSize('%s'%(len(GetSplitValueList(PcdItem
[1], DT
.TAB_COMMA_SPLIT
))))
515 DecGuidsDict
= DecParser
.GetGuidSectionObject().ValueDict
516 for Key
in DecGuidsDict
.keys():
517 if Key
== 'COMMON' or Key
== Arch
:
518 for GuidInDec
in DecGuidsDict
[Key
]:
519 if GuidInDec
.GuidCName
== PcdItemObj
.TokenSpaceGuidCName
:
520 PcdItemObj
.SetTokenSpaceGuidValue(GuidInDec
.GuidString
)
525 if ValidatePcdValueOnDatumType(PcdItem
[1], PcdItemObj
.GetDatumType()):
526 PcdItemObj
.SetDefaultValue(PcdItem
[1])
528 Logger
.Error("InfParser",
529 ToolError
.FORMAT_INVALID
,
530 ST
.ERR_ASBUILD_PCD_VALUE_INVALID
%("\"" + PcdItem
[1] + "\"", "\"" +
531 PcdItemObj
.GetDatumType() + "\""),
532 File
=CurrentLineOfPcdItem
[2],
533 Line
=CurrentLineOfPcdItem
[1],
534 ExtraData
=CurrentLineOfPcdItem
[0])
538 if PcdItemObj
.GetItemType().upper() == DT
.TAB_INF_PATCH_PCD
.upper():
539 if not IsHexDigitUINT32(PcdItem
[2]):
540 Logger
.Error("InfParser",
541 ToolError
.FORMAT_INVALID
,
542 ST
.ERR_ASBUILD_PCD_OFFSET_FORMAT_INVALID
%("\"" + PcdItem
[2] + "\""),
543 File
=CurrentLineOfPcdItem
[2],
544 Line
=CurrentLineOfPcdItem
[1],
545 ExtraData
=CurrentLineOfPcdItem
[0])
546 PcdItemObj
.SetOffset(PcdItem
[2])
548 if PcdItemObj
.GetToken() == '' or PcdItemObj
.GetDatumType() == '':
549 Logger
.Error("InfParser",
550 ToolError
.FORMAT_INVALID
,
551 ST
.ERR_ASBUILD_PCD_DECLARITION_MISS
%("\"" + PcdItem
[0] + "\""),
552 File
=CurrentLineOfPcdItem
[2],
553 Line
=CurrentLineOfPcdItem
[1],
554 ExtraData
=CurrentLineOfPcdItem
[0])
558 def ValidatePcdValueOnDatumType(Value
, Type
):
560 Value
= Value
.strip()
562 # Boolean type only allow 0x00 or 0x01 as value per INF spec
564 if Type
== 'BOOLEAN':
565 if not (Value
== '0x00' or Value
== '0x01'):
567 elif Type
== 'VOID*':
568 if not Value
.startswith("{"):
570 if not Value
.endswith("}"):
573 # Strip "{" at head and "}" at tail.
576 ValueList
= GetSplitValueList(Value
, DT
.TAB_COMMA_SPLIT
)
578 ReIsValidHexByte
= re
.compile("^0x[0-9a-f]{1,2}$", re
.IGNORECASE
)
579 for ValueItem
in ValueList
:
580 if not ReIsValidHexByte
.match(ValueItem
):
583 elif Type
== 'UINT8' or Type
== 'UINT16' or Type
== 'UINT32' or Type
== 'UINT64':
585 ReIsValidUint8z
= re
.compile('^0[x|X][a-fA-F0-9]{2}$')
586 ReIsValidUint16z
= re
.compile('^0[x|X][a-fA-F0-9]{4}$')
587 ReIsValidUint32z
= re
.compile('^0[x|X][a-fA-F0-9]{8}$')
588 ReIsValidUint64z
= re
.compile('^0[x|X][a-fA-F0-9]{16}$')
590 if not ReIsValidUint8z
.match(Value
) and Type
== 'UINT8':
592 elif not ReIsValidUint16z
.match(Value
) and Type
== 'UINT16':
594 elif not ReIsValidUint32z
.match(Value
) and Type
== 'UINT32':
596 elif not ReIsValidUint64z
.match(Value
) and Type
== 'UINT64':
600 # Since we assume the DEC file always correct, should never go to here.
606 def SetPcdName(PcdItem
, CurrentLineOfPcdItem
, PcdItemObj
):
608 # Only PCD Name specified
609 # <PcdName> ::= <TokenSpaceGuidCName> "." <TokenCName>
611 PcdId
= GetSplitValueList(PcdItem
[0], DT
.TAB_SPLIT
)
613 Logger
.Error("InfParser",
614 ToolError
.FORMAT_INVALID
,
615 ST
.ERR_INF_PARSER_PCD_NAME_FORMAT_ERROR
,
616 File
=CurrentLineOfPcdItem
[2],
617 Line
=CurrentLineOfPcdItem
[1],
618 ExtraData
=CurrentLineOfPcdItem
[0])
621 # Validate PcdTokenSpaceGuidCName
623 if not IsValidCVariableName(PcdId
[0]):
624 Logger
.Error("InfParser",
625 ToolError
.FORMAT_INVALID
,
626 ST
.ERR_INF_PARSER_PCD_CVAR_GUID
,
627 File
=CurrentLineOfPcdItem
[2],
628 Line
=CurrentLineOfPcdItem
[1],
630 if not IsValidCVariableName(PcdId
[1]):
631 Logger
.Error("InfParser",
632 ToolError
.FORMAT_INVALID
,
633 ST
.ERR_INF_PARSER_PCD_CVAR_PCDCNAME
,
634 File
=CurrentLineOfPcdItem
[2],
635 Line
=CurrentLineOfPcdItem
[1],
637 PcdItemObj
.SetTokenSpaceGuidCName(PcdId
[0])
638 PcdItemObj
.SetCName(PcdId
[1])