4 This module contains all classes releted to PCD token.
6 Copyright (c) 2006, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this 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.
16 package org
.tianocore
.build
.pcd
.entity
;
18 import java
.math
.BigInteger
;
19 import java
.util
.ArrayList
;
20 import java
.util
.HashMap
;
21 import java
.util
.List
;
23 import java
.util
.UUID
;
25 import org
.tianocore
.build
.pcd
.exception
.EntityException
;
27 /** This class is to descript a PCD token object. The information of a token mainly
28 comes from MSA, SPD and setting produced by platform developer.
32 /// Enumeration macro defintion for PCD type.
33 /// BUGBUG: Not use upcase charater is to facility for reading. It may be changed
35 public enum PCD_TYPE
{FEATURE_FLAG
, FIXED_AT_BUILD
, PATCHABLE_IN_MODULE
, DYNAMIC
,
39 /// Enumeration macro definition for datum type. All type mainly comes from ProcessBind.h.
40 /// Wizard maybe expand this type as "int, unsigned int, short, unsigned short etc" in
43 public enum DATUM_TYPE
{UINT8
, UINT16
, UINT32
, UINT64
, BOOLEAN
, POINTER
, UNKNOWN
}
46 /// Enumeration macor defintion for usage of PCD
48 public enum PCD_USAGE
{ALWAYS_PRODUCED
, ALWAYS_CONSUMED
, SOMETIMES_PRODUCED
,
49 SOMETIMES_CONSUMED
, UNKNOWN
}
52 /// cName is to identify a PCD entry and will be used for generating autogen.h/autogen.c.
53 /// cName will be defined in MSA, SPD and FPD, can be regarded as primary key with token space guid.
58 /// Token space name is the guid defined by token itself in package or module level. This
59 /// name mainly for DynamicEx type. For other PCD type token, his token space name is the
60 /// assignedtokenSpaceName as follows.
61 /// tokenSpaceName is defined in MSA, SPD, FPD, can be regarded as primary key with cName.
63 public UUID tokenSpaceName
;
66 /// tokenNumber is allocated by platform. tokenNumber indicate an index for this token in
67 /// platform token space. For Dynamic, dynamicEx type, this number will be re-adjust by
68 /// PCD run-time database autogen tools.
70 public long tokenNumber
;
73 /// This token number is retrieved from FPD file for DynamicEx type.
75 public long dynamicExTokenNumber
;
78 /// All supported PCD type, this value can be retrieved from SPD
79 /// Currently, only record all PCD type for this token in FPD file.
81 public List
<PCD_TYPE
> supportedPcdType
;
84 /// If the token's item type is Dynamic or DynamicEx type, isDynamicPCD
87 public boolean isDynamicPCD
;
90 /// datumSize is to descript the fix size or max size for this token.
91 /// datumSize is defined in SPD.
96 /// datum type is to descript what type can be expressed by a PCD token.
97 /// For same PCD used in different module, the datum type should be unique.
98 /// So it belong memeber to Token class.
100 public DATUM_TYPE datumType
;
103 /// skuData contains all value for SkuNumber of token.
104 /// This field is for Dynamic or DynamicEx type PCD,
106 public List
<SkuInstance
> skuData
;
109 /// consumers array record all module private information who consume this PCD token.
111 public Map
<String
, UsageInstance
> consumers
;
113 public Token(String cName
, UUID tokenSpaceName
) {
114 UUID nullUUID
= new UUID(0, 0);
117 this.tokenSpaceName
= (tokenSpaceName
== null) ? nullUUID
: tokenSpaceName
;
118 this.tokenNumber
= 0;
119 this.datumType
= DATUM_TYPE
.UNKNOWN
;
121 this.skuData
= new ArrayList
<SkuInstance
>();
123 this.consumers
= new HashMap
<String
, UsageInstance
>();
124 this.supportedPcdType
= new ArrayList
<PCD_TYPE
>();
130 SupportPcdType should be gotten from SPD file actually, but now it just
131 record all PCD type for this token in FPD file.
133 @param pcdType new PCD type found in FPD file for this token.
135 public void updateSupportPcdType(PCD_TYPE pcdType
) {
137 boolean found
= false;
138 for (index
= 0; index
< this.supportedPcdType
.size(); index
++) {
139 if (this.supportedPcdType
.get(index
) == pcdType
) {
145 this.supportedPcdType
.add(pcdType
);
150 Judge whether pcdType is belong to dynamic type. Dynamic type includes
151 DYNAMIC and DYNAMIC_EX.
157 public static boolean isDynamic(PCD_TYPE pcdType
) {
158 if ((pcdType
== PCD_TYPE
.DYNAMIC
) ||
159 (pcdType
== PCD_TYPE
.DYNAMIC_EX
)) {
166 public boolean isDynamicEx() {
168 for (int i
= 0; i
< supportedPcdType
.size(); i
++) {
169 if (supportedPcdType
.get(i
) == PCD_TYPE
.DYNAMIC_EX
) {
178 Use "TokencName + "-" + SpaceTokenName" as primary key when adding token into database
180 @param cName Token name.
181 @param tokenSpaceName The token space guid defined in MSA or SPD
182 @param platformtokenSpaceName The token space guid for current platform token space,
184 @return primary key for this token in token database.
186 public static String
getPrimaryKeyString(String cName
, UUID tokenSpaceName
) {
187 UUID nullUUID
= new UUID(0, 0);
189 if (tokenSpaceName
== null) {
190 return cName
+ "_" + nullUUID
.toString().replace('-', '_');
192 return cName
+ "_" + tokenSpaceName
.toString().replace('-', '_');
197 If skudata list contains more than one data, then Sku mechanism is enable.
201 public boolean isSkuEnable() {
202 if (this.skuData
.size() > 1) {
208 public boolean isHiiEnable() {
209 if (getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
215 public boolean isVpdEnable() {
216 if (getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
223 Get the token primary key in token database.
227 public String
getPrimaryKeyString () {
228 return Token
.getPrimaryKeyString(cName
, tokenSpaceName
);
232 Judge datumType is valid
234 @param type The datumType want to be judged.
236 @retval TRUE - The type is valid.
237 @retval FALSE - The type is invalid.
239 public static boolean isValiddatumType(DATUM_TYPE type
) {
240 if ((type
.ordinal() < DATUM_TYPE
.UINT8
.ordinal() ) ||
241 (type
.ordinal() > DATUM_TYPE
.POINTER
.ordinal())) {
248 Judge pcdType is valid
250 @param type The PCdType want to be judged.
252 @retval TRUE - The type is valid.
253 @retval FALSE - The type is invalid.
255 public static boolean isValidpcdType(PCD_TYPE type
) {
256 if ((type
.ordinal() < PCD_TYPE
.FEATURE_FLAG
.ordinal() ) ||
257 (type
.ordinal() > PCD_TYPE
.DYNAMIC_EX
.ordinal())) {
264 Add an usage instance for token
266 @param usageInstance The usage instance
268 @retval TRUE - Success to add usage instance.
269 @retval FALSE - Fail to add usage instance
271 public boolean addUsageInstance(UsageInstance usageInstance
)
272 throws EntityException
{
275 if (isUsageInstanceExist(usageInstance
.moduleName
,
276 usageInstance
.moduleGUID
,
277 usageInstance
.packageName
,
278 usageInstance
.packageGUID
,
280 usageInstance
.version
)) {
281 exceptionStr
= String
.format("PCD %s for module %s has already exist in database, Please check all PCD build entries "+
282 "in modules %s in <ModuleSA> to make sure no duplicated definitions!",
283 usageInstance
.parentToken
.cName
,
284 usageInstance
.moduleName
,
285 usageInstance
.moduleName
);
286 throw new EntityException(exceptionStr
);
289 consumers
.put(usageInstance
.getPrimaryKey(), usageInstance
);
294 Judge whether exist an usage instance for this token
296 @param moduleName the name of module
297 @param moduleGuid the GUID name of modules
298 @param packageName the name of package contains this module
299 @param packageGuid the GUID name of package contains this module
300 @param arch the architecture string
301 @param version the version string
303 @return boolean whether exist an usage instance for this token.
305 public boolean isUsageInstanceExist(String moduleName
,
311 String keyStr
= UsageInstance
.getPrimaryKey(moduleName
,
317 return (consumers
.get(keyStr
) != null);
321 Get the PCD_TYPE according to the string of PCD_TYPE
323 @param pcdTypeStr The string of PCD_TYPE
327 public static PCD_TYPE
getpcdTypeFromString(String pcdTypeStr
) {
328 if (pcdTypeStr
== null) {
329 return PCD_TYPE
.UNKNOWN
;
332 if (pcdTypeStr
.equalsIgnoreCase("FEATURE_FLAG")) {
333 return PCD_TYPE
.FEATURE_FLAG
;
334 } else if (pcdTypeStr
.equalsIgnoreCase("FIXED_AT_BUILD")) {
335 return PCD_TYPE
.FIXED_AT_BUILD
;
336 } else if (pcdTypeStr
.equalsIgnoreCase("PATCHABLE_IN_MODULE")) {
337 return PCD_TYPE
.PATCHABLE_IN_MODULE
;
338 } else if (pcdTypeStr
.equalsIgnoreCase("DYNAMIC")) {
339 return PCD_TYPE
.DYNAMIC
;
340 } else if (pcdTypeStr
.equalsIgnoreCase("DYNAMIC_EX")) {
341 return PCD_TYPE
.DYNAMIC_EX
;
343 return PCD_TYPE
.UNKNOWN
;
348 Get the string of given datumType. This string will be used for generating autogen files
350 @param datumType Given datumType
352 @return The string of datum type.
354 public static String
getStringOfdatumType(DATUM_TYPE datumType
) {
373 Get the datumType according to a string.
375 @param datumTypeStr The string of datumType
379 public static DATUM_TYPE
getdatumTypeFromString(String datumTypeStr
) {
380 if (datumTypeStr
.equalsIgnoreCase("UINT8")) {
381 return DATUM_TYPE
.UINT8
;
382 } else if (datumTypeStr
.equalsIgnoreCase("UINT16")) {
383 return DATUM_TYPE
.UINT16
;
384 } else if (datumTypeStr
.equalsIgnoreCase("UINT32")) {
385 return DATUM_TYPE
.UINT32
;
386 } else if (datumTypeStr
.equalsIgnoreCase("UINT64")) {
387 return DATUM_TYPE
.UINT64
;
388 } else if (datumTypeStr
.equalsIgnoreCase("VOID*")) {
389 return DATUM_TYPE
.POINTER
;
390 } else if (datumTypeStr
.equalsIgnoreCase("BOOLEAN")) {
391 return DATUM_TYPE
.BOOLEAN
;
393 return DATUM_TYPE
.UNKNOWN
;
397 Get string of given pcdType
399 @param pcdType The given PcdType
401 @return The string of PCD_TYPE.
403 public static String
getStringOfpcdType(PCD_TYPE pcdType
) {
406 return "FEATURE_FLAG";
408 return "FIXED_AT_BUILD";
409 case PATCHABLE_IN_MODULE
:
410 return "PATCHABLE_IN_MODULE";
420 Get the PCD_USAGE according to a string
422 @param usageStr The string of PCD_USAGE
424 @return The PCD_USAGE
426 public static PCD_USAGE
getUsageFromString(String usageStr
) {
427 if (usageStr
== null) {
428 return PCD_USAGE
.UNKNOWN
;
431 if (usageStr
.equalsIgnoreCase("ALWAYS_PRODUCED")) {
432 return PCD_USAGE
.ALWAYS_PRODUCED
;
433 } else if (usageStr
.equalsIgnoreCase("SOMETIMES_PRODUCED")) {
434 return PCD_USAGE
.SOMETIMES_PRODUCED
;
435 } else if (usageStr
.equalsIgnoreCase("ALWAYS_CONSUMED")) {
436 return PCD_USAGE
.ALWAYS_CONSUMED
;
437 } else if (usageStr
.equalsIgnoreCase("SOMETIMES_CONSUMED")) {
438 return PCD_USAGE
.SOMETIMES_CONSUMED
;
441 return PCD_USAGE
.UNKNOWN
;
445 Get the string of given PCD_USAGE
447 @param usage The given PCD_USAGE
449 @return The string of PDC_USAGE.
451 public static String
getStringOfUsage(PCD_USAGE usage
) {
453 case ALWAYS_PRODUCED
:
454 return "ALWAYS_PRODUCED";
455 case ALWAYS_CONSUMED
:
456 return "ALWAYS_CONSUMED";
457 case SOMETIMES_PRODUCED
:
458 return "SOMETIMES_PRODUCED";
459 case SOMETIMES_CONSUMED
:
460 return "SOMETIMES_CONSUMED";
466 Get the Defined datumType string for autogen. The string is for generating some MACROs in Autogen.h
468 @param datumType The given datumType
470 @return string of datum type for autogen.
472 public static String
GetAutogenDefinedatumTypeString(DATUM_TYPE datumType
) {
493 Get the datumType String for Autogen. This string will be used for generating defintions of PCD token in autogen
495 @param datumType The given datumType
497 @return string of datum type.
500 public static String
getAutogendatumTypeString(DATUM_TYPE datumType
) {
519 Get the datumType string for generating some MACROs in autogen file of Library
521 @param datumType The given datumType
523 @return String of datum for genrating bit charater.
525 public static String
getAutogenLibrarydatumTypeString(DATUM_TYPE datumType
) {
545 UUID defined in Schems is object, this function is to tranlate this object
548 @param uuidObj The object comes from schema.
550 @return The traslated UUID instance.
552 public static UUID
getGUIDFromSchemaObject(Object uuidObj
) {
554 if (uuidObj
.toString().equalsIgnoreCase("0")) {
555 uuid
= new UUID(0,0);
557 uuid
= UUID
.fromString(uuidObj
.toString());
563 public DynamicTokenValue
getDefaultSku() {
564 DynamicTokenValue dynamicData
;
566 for (index
= 0; index
< this.skuData
.size(); index
++) {
567 if (skuData
.get(index
).id
== 0) {
568 return skuData
.get(index
).value
;
575 public int getSkuIdCount () {
576 return this.skuData
.size();
579 private void getCurrentSizeFromDefaultValue (String str
, ArrayList
<Integer
> al
) {
580 if (isValidNullValue(str
)) {
581 al
.add(new Integer(0));
584 // isValidNullValue has already make sure that str here
585 // always contain a valid default value of the following 3
587 // 1) "Hello world" //Assci string
588 // 2) L"Hello" //Unicode string
589 // 3) {0x01, 0x02, 0x03} //Byte stream
591 if (str
.startsWith("\"")) {
592 al
.add(new Integer(str
.length() - 2));
593 } else if (str
.startsWith("L\"")){
595 // Unicode is 2 bytes each.
597 al
.add(new Integer((str
.length() - 3) * 2));
598 } else if (str
.startsWith("{")) {
600 // We count the number of "," in the string.
601 // The number of byte is one plus the number of
608 pos
= str2
.indexOf(",", 0);
612 pos
= str2
.indexOf(",", pos
);
615 al
.add(new Integer(cnt
));
620 // This method can be used to get the MAX and current size
621 // for pointer type dynamic(ex) PCD entry
623 public ArrayList
<Integer
> getPointerTypeSize () {
624 ArrayList
<Integer
> al
= new ArrayList
<Integer
>();
627 // For VPD_enabled and HII_enabled, we can only return the MAX size.
628 // For the default DATA type dynamic PCD entry, we will return
629 // the MAX size and current size for each SKU_ID.
631 al
.add(new Integer(this.datumSize
));
633 if (!this.isVpdEnable()) {
635 if (this.isHiiEnable()){
636 for (idx
= 0; idx
< this.skuData
.size(); idx
++) {
637 String str
= this.skuData
.get(idx
).value
.hiiDefaultValue
;
638 getCurrentSizeFromDefaultValue(str
, al
);
641 for (idx
= 0; idx
< this.skuData
.size(); idx
++) {
642 String str
= this.skuData
.get(idx
).value
.value
;
643 getCurrentSizeFromDefaultValue(str
, al
);
652 Get default value for a token, For HII type, HiiDefaultValue of default
653 SKU 0 will be returned; For Default type, the defaultvalue of default SKU
658 public String
getDynamicDefaultValue() {
659 DynamicTokenValue dynamicData
= getDefaultSku();
660 if (hasDefaultValue()) {
661 switch (dynamicData
.type
) {
663 return dynamicData
.value
;
671 // BugBug: We need change this algorithm accordingly when schema is updated
672 // to support no default value.
674 public boolean hasDefaultValue () {
676 boolean isInteger
= true;
677 DynamicTokenValue dynamicValue
= null;
683 if (this.isDynamicPCD
) {
684 dynamicValue
= getDefaultSku();
685 switch (dynamicValue
.type
) {
691 return !isValidNullValue(dynamicValue
.value
);
698 public boolean isValidNullValue(String judgedValue
) {
700 BigInteger bigIntValue
;
706 if (judgedValue
.length() > 2) {
707 if ((judgedValue
.charAt(0) == '0') &&
708 ((judgedValue
.charAt(1) == 'x') || (judgedValue
.charAt(1) == 'X'))){
709 subStr
= judgedValue
.substring(2, judgedValue
.length());
710 bigIntValue
= new BigInteger(subStr
, 16);
712 bigIntValue
= new BigInteger(judgedValue
);
715 bigIntValue
= new BigInteger(judgedValue
);
717 if (bigIntValue
.bitCount() == 0) {
722 if (judgedValue
.length() > 2){
723 if ((judgedValue
.charAt(0) == '0') &&
724 ((judgedValue
.charAt(1) == 'x') ||
725 (judgedValue
.charAt(1) == 'X'))) {
726 bigIntValue
= new BigInteger(judgedValue
.substring(2, judgedValue
.length()), 16);
727 if (bigIntValue
.bitCount() == 0) {
731 bigIntValue
= new BigInteger(judgedValue
);
732 if (bigIntValue
.bitCount() == 0) {
737 bigIntValue
= new BigInteger(judgedValue
);
738 if (bigIntValue
.bitCount() == 0) {
744 if (judgedValue
.equalsIgnoreCase("false")) {
749 if (judgedValue
.equalsIgnoreCase("") ||
750 judgedValue
.equalsIgnoreCase("\"\"") ||
751 judgedValue
.equalsIgnoreCase("L\"\"") ||
752 (judgedValue
.length() == 0) ||
753 judgedValue
.equalsIgnoreCase("{0}")) {
760 public boolean isHiiDefaultValueUnicodeStringType() {
761 DynamicTokenValue dynamicData
= getDefaultSku();
763 if (dynamicData
== null)
766 return dynamicData
.hiiDefaultValue
.startsWith("L\"")
767 && dynamicData
.hiiDefaultValue
.endsWith("\"");
770 public boolean isHiiDefaultValueASCIIStringType() {
771 DynamicTokenValue dynamicData
= getDefaultSku();
773 if (dynamicData
== null)
776 return dynamicData
.hiiDefaultValue
.startsWith("\"")
777 && dynamicData
.hiiDefaultValue
.endsWith("\"");
781 Judege whether current value is UNICODE string type.
784 public boolean isUnicodeStringType () {
785 String str
= getDynamicDefaultValue();
791 if (datumType
== Token
.DATUM_TYPE
.POINTER
&&
792 str
.startsWith("L\"") &&
793 str
.endsWith("\"")) {
800 public boolean isASCIIStringType () {
801 String str
= getDynamicDefaultValue();
807 if (datumType
== Token
.DATUM_TYPE
.POINTER
&&
808 str
.startsWith("\"") &&
809 str
.endsWith("\"")) {
816 public boolean isByteStreamType () {
817 String str
= getDynamicDefaultValue();
823 if (datumType
== Token
.DATUM_TYPE
.POINTER
&&
824 str
.startsWith("{") &&
833 public String
getStringTypeString () {
834 return getDefaultSku().value
.substring(2, getDefaultSku().value
.length() - 1);