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
.id
.ModuleIdentification
;
26 import org
.tianocore
.build
.pcd
.exception
.EntityException
;
28 /** This class is to descript a PCD token object. The information of a token mainly
29 comes from MSA, SPD and setting produced by platform developer.
33 /// Enumeration macro defintion for PCD type.
34 /// BUGBUG: Not use upcase charater is to facility for reading. It may be changed
36 public enum PCD_TYPE
{FEATURE_FLAG
, FIXED_AT_BUILD
, PATCHABLE_IN_MODULE
, DYNAMIC
,
40 /// Enumeration macro definition for datum type. All type mainly comes from ProcessBind.h.
41 /// Wizard maybe expand this type as "int, unsigned int, short, unsigned short etc" in
44 public enum DATUM_TYPE
{UINT8
, UINT16
, UINT32
, UINT64
, BOOLEAN
, POINTER
, UNKNOWN
}
47 /// Enumeration macor defintion for usage of PCD
49 public enum PCD_USAGE
{ALWAYS_PRODUCED
, ALWAYS_CONSUMED
, SOMETIMES_PRODUCED
,
50 SOMETIMES_CONSUMED
, UNKNOWN
}
53 /// cName is to identify a PCD entry and will be used for generating autogen.h/autogen.c.
54 /// cName will be defined in MSA, SPD and FPD, can be regarded as primary key with token space guid.
59 /// Token space name is the guid defined by token itself in package or module level. This
60 /// name mainly for DynamicEx type. For other PCD type token, his token space name is the
61 /// assignedtokenSpaceName as follows.
62 /// tokenSpaceName is defined in MSA, SPD, FPD, can be regarded as primary key with cName.
64 public String tokenSpaceName
;
67 /// tokenNumber is allocated by platform. tokenNumber indicate an index for this token in
68 /// platform token space. For Dynamic, dynamicEx type, this number will be re-adjust by
69 /// PCD run-time database autogen tools.
71 public long tokenNumber
;
74 /// This token number is retrieved from FPD file for DynamicEx type.
76 public long dynamicExTokenNumber
;
79 /// All supported PCD type, this value can be retrieved from SPD
80 /// Currently, only record all PCD type for this token in FPD file.
82 public List
<PCD_TYPE
> supportedPcdType
;
85 /// If the token's item type is Dynamic or DynamicEx type, isDynamicPCD
88 public boolean isDynamicPCD
;
91 /// datumSize is to descript the fix size or max size for this token.
92 /// datumSize is defined in SPD.
97 /// datum type is to descript what type can be expressed by a PCD token.
98 /// For same PCD used in different module, the datum type should be unique.
99 /// So it belong memeber to Token class.
101 public DATUM_TYPE datumType
;
104 /// skuData contains all value for SkuNumber of token.
105 /// This field is for Dynamic or DynamicEx type PCD,
107 public List
<SkuInstance
> skuData
;
110 /// consumers array record all module private information who consume this PCD token.
112 public Map
<String
, UsageInstance
> consumers
;
115 Constructure function for Token class
117 @param cName The name of token
118 @param tokenSpaceName The name of token space, it is a guid string
120 public Token(String cName
, String tokenSpaceName
) {
121 UUID nullUUID
= new UUID(0, 0);
124 this.tokenSpaceName
= tokenSpaceName
;
125 this.tokenNumber
= 0;
126 this.datumType
= DATUM_TYPE
.UNKNOWN
;
128 this.skuData
= new ArrayList
<SkuInstance
>();
130 this.consumers
= new HashMap
<String
, UsageInstance
>();
131 this.supportedPcdType
= new ArrayList
<PCD_TYPE
>();
137 SupportPcdType should be gotten from SPD file actually, but now it just
138 record all PCD type for this token in FPD file.
140 @param pcdType new PCD type found in FPD file for this token.
142 public void updateSupportPcdType(PCD_TYPE pcdType
) {
143 for (int index
= 0; index
< this.supportedPcdType
.size(); index
++) {
144 if (supportedPcdType
.get(index
) == pcdType
) {
150 // If not found, add the pcd type to member variable supportedPcdType
152 supportedPcdType
.add(pcdType
);
156 Judge whether pcdType is belong to dynamic type. Dynamic type includes
157 DYNAMIC and DYNAMIC_EX.
159 @param pcdType the judged pcd type
163 public static boolean isDynamic(PCD_TYPE pcdType
) {
164 if ((pcdType
== PCD_TYPE
.DYNAMIC
) ||
165 (pcdType
== PCD_TYPE
.DYNAMIC_EX
)) {
172 public boolean isDynamicEx() {
173 for (int i
= 0; i
< supportedPcdType
.size(); i
++) {
174 if (supportedPcdType
.get(i
) == PCD_TYPE
.DYNAMIC_EX
) {
183 Use "TokencName + "-" + SpaceTokenName" as primary key when adding token into database
185 @param cName Token name.
186 @param tokenSpaceName The token space guid string defined in MSA or SPD
188 @retval primary key for this token in token database.
190 public static String
getPrimaryKeyString(String cName
, String tokenSpaceName
) {
191 if (tokenSpaceName
== null) {
192 return cName
+ "_nullTokenSpaceGuid";
194 return cName
+ "_" + tokenSpaceName
.toString().replace('-', '_');
199 If skudata list contains more than one data, then Sku mechanism is enable.
201 @retval boolean if the number of sku data exceed to 1
203 public boolean isSkuEnable() {
204 if (this.skuData
.size() > 1) {
211 If Hii type for value of token
215 public boolean isHiiEnable() {
216 if (getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
223 If Vpd type for value of token
227 public boolean isVpdEnable() {
228 if (getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
235 Get the token primary key in token database.
239 public String
getPrimaryKeyString () {
240 return Token
.getPrimaryKeyString(cName
, tokenSpaceName
);
244 Judge datumType is valid
246 @param type The datumType want to be judged.
248 @retval TRUE - The type is valid.
249 @retval FALSE - The type is invalid.
251 public static boolean isValiddatumType(DATUM_TYPE type
) {
252 if ((type
.ordinal() < DATUM_TYPE
.UINT8
.ordinal() ) ||
253 (type
.ordinal() > DATUM_TYPE
.POINTER
.ordinal())) {
260 Judge pcdType is valid
262 @param type The PCdType want to be judged.
264 @retval TRUE - The type is valid.
265 @retval FALSE - The type is invalid.
267 public static boolean isValidpcdType(PCD_TYPE type
) {
268 if ((type
.ordinal() < PCD_TYPE
.FEATURE_FLAG
.ordinal() ) ||
269 (type
.ordinal() > PCD_TYPE
.DYNAMIC_EX
.ordinal())) {
276 Add an usage instance for token
278 @param usageInstance The usage instance
280 @retval TRUE - Success to add usage instance.
281 @retval FALSE - Fail to add usage instance
283 public boolean addUsageInstance(UsageInstance usageInstance
) throws EntityException
{
286 if (isUsageInstanceExist(usageInstance
.moduleId
, usageInstance
.arch
)) {
287 exceptionStr
= String
.format("[PCD Collection Tool Exception] PCD %s for module %s has already exist in database, Please check all PCD build entries "+
288 "in modules %s in <ModuleSA> to make sure no duplicated definitions in FPD file!",
289 usageInstance
.parentToken
.cName
,
290 usageInstance
.moduleId
.getName(),
291 usageInstance
.moduleId
.getName());
292 throw new EntityException(exceptionStr
);
296 // Put usage instance into usage instance database of this PCD token.
298 consumers
.put(usageInstance
.getPrimaryKey(), usageInstance
);
304 Judge whether exist an usage instance for this token
306 @param moduleId The module identification for usage instance
307 @param arch the architecture string
309 @return boolean whether exist an usage instance for this token.
311 public boolean isUsageInstanceExist(ModuleIdentification moduleId
,
313 String keyStr
= UsageInstance
.getPrimaryKey(moduleId
, arch
);
315 return (consumers
.get(keyStr
) != null);
319 Get the PCD_TYPE according to the string of PCD_TYPE
321 @param pcdTypeStr The string of PCD_TYPE
325 public static PCD_TYPE
getpcdTypeFromString(String pcdTypeStr
) {
326 if (pcdTypeStr
== null) {
327 return PCD_TYPE
.UNKNOWN
;
330 if (pcdTypeStr
.equalsIgnoreCase("FEATURE_FLAG")) {
331 return PCD_TYPE
.FEATURE_FLAG
;
332 } else if (pcdTypeStr
.equalsIgnoreCase("FIXED_AT_BUILD")) {
333 return PCD_TYPE
.FIXED_AT_BUILD
;
334 } else if (pcdTypeStr
.equalsIgnoreCase("PATCHABLE_IN_MODULE")) {
335 return PCD_TYPE
.PATCHABLE_IN_MODULE
;
336 } else if (pcdTypeStr
.equalsIgnoreCase("DYNAMIC")) {
337 return PCD_TYPE
.DYNAMIC
;
338 } else if (pcdTypeStr
.equalsIgnoreCase("DYNAMIC_EX")) {
339 return PCD_TYPE
.DYNAMIC_EX
;
341 return PCD_TYPE
.UNKNOWN
;
346 Get the string of given datumType. This string will be used for generating autogen files
348 @param datumType Given datumType
350 @return The string of datum type.
352 public static String
getStringOfdatumType(DATUM_TYPE datumType
) {
371 Get the datumType according to a string.
373 @param datumTypeStr The string of datumType
377 public static DATUM_TYPE
getdatumTypeFromString(String datumTypeStr
) {
378 if (datumTypeStr
.equalsIgnoreCase("UINT8")) {
379 return DATUM_TYPE
.UINT8
;
380 } else if (datumTypeStr
.equalsIgnoreCase("UINT16")) {
381 return DATUM_TYPE
.UINT16
;
382 } else if (datumTypeStr
.equalsIgnoreCase("UINT32")) {
383 return DATUM_TYPE
.UINT32
;
384 } else if (datumTypeStr
.equalsIgnoreCase("UINT64")) {
385 return DATUM_TYPE
.UINT64
;
386 } else if (datumTypeStr
.equalsIgnoreCase("VOID*")) {
387 return DATUM_TYPE
.POINTER
;
388 } else if (datumTypeStr
.equalsIgnoreCase("BOOLEAN")) {
389 return DATUM_TYPE
.BOOLEAN
;
391 return DATUM_TYPE
.UNKNOWN
;
395 Get string of given pcdType
397 @param pcdType The given PcdType
399 @return The string of PCD_TYPE.
401 public static String
getStringOfpcdType(PCD_TYPE pcdType
) {
404 return "FEATURE_FLAG";
406 return "FIXED_AT_BUILD";
407 case PATCHABLE_IN_MODULE
:
408 return "PATCHABLE_IN_MODULE";
418 Get the PCD_USAGE according to a string
420 @param usageStr The string of PCD_USAGE
422 @return The PCD_USAGE
424 public static PCD_USAGE
getUsageFromString(String usageStr
) {
425 if (usageStr
== null) {
426 return PCD_USAGE
.UNKNOWN
;
429 if (usageStr
.equalsIgnoreCase("ALWAYS_PRODUCED")) {
430 return PCD_USAGE
.ALWAYS_PRODUCED
;
431 } else if (usageStr
.equalsIgnoreCase("SOMETIMES_PRODUCED")) {
432 return PCD_USAGE
.SOMETIMES_PRODUCED
;
433 } else if (usageStr
.equalsIgnoreCase("ALWAYS_CONSUMED")) {
434 return PCD_USAGE
.ALWAYS_CONSUMED
;
435 } else if (usageStr
.equalsIgnoreCase("SOMETIMES_CONSUMED")) {
436 return PCD_USAGE
.SOMETIMES_CONSUMED
;
439 return PCD_USAGE
.UNKNOWN
;
443 Get the string of given PCD_USAGE
445 @param usage The given PCD_USAGE
447 @return The string of PDC_USAGE.
449 public static String
getStringOfUsage(PCD_USAGE usage
) {
451 case ALWAYS_PRODUCED
:
452 return "ALWAYS_PRODUCED";
453 case ALWAYS_CONSUMED
:
454 return "ALWAYS_CONSUMED";
455 case SOMETIMES_PRODUCED
:
456 return "SOMETIMES_PRODUCED";
457 case SOMETIMES_CONSUMED
:
458 return "SOMETIMES_CONSUMED";
464 Get the Defined datumType string for autogen. The string is for generating some MACROs in Autogen.h
466 @param datumType The given datumType
468 @return string of datum type for autogen.
470 public static String
GetAutogenDefinedatumTypeString(DATUM_TYPE datumType
) {
491 Get the datumType String for Autogen. This string will be used for generating defintions of PCD token in autogen
493 @param datumType The given datumType
495 @return string of datum type.
498 public static String
getAutogendatumTypeString(DATUM_TYPE datumType
) {
517 Get the datumType string for generating some MACROs in autogen file of Library
519 @param datumType The given datumType
521 @return String of datum for genrating bit charater.
523 public static String
getAutogenLibrarydatumTypeString(DATUM_TYPE datumType
) {
543 Get the sku data who id is 0.
545 @retval DynamicTokenValue the value of this dyanmic token.
547 public DynamicTokenValue
getDefaultSku() {
548 DynamicTokenValue dynamicData
;
551 for (index
= 0; index
< this.skuData
.size(); index
++) {
552 if (skuData
.get(index
).id
== 0) {
553 return skuData
.get(index
).value
;
561 Get the number of Sku data for this token
563 @retval int the number of sku data
565 public int getSkuIdCount () {
566 return this.skuData
.size();
570 Get the size of PCD value, this PCD is POINTER type.
572 @param str the string of the value
575 private void getCurrentSizeFromDefaultValue (String str
, ArrayList
<Integer
> al
) {
576 if (isValidNullValue(str
)) {
577 al
.add(new Integer(0));
580 // isValidNullValue has already make sure that str here
581 // always contain a valid default value of the following 3
583 // 1) "Hello world" //Assci string
584 // 2) L"Hello" //Unicode string
585 // 3) {0x01, 0x02, 0x03} //Byte stream
587 if (str
.startsWith("\"")) {
588 al
.add(new Integer(str
.length() - 2));
589 } else if (str
.startsWith("L\"")){
591 // Unicode is 2 bytes each.
593 al
.add(new Integer((str
.length() - 3) * 2));
594 } else if (str
.startsWith("{")) {
596 // We count the number of "," in the string.
597 // The number of byte is one plus the number of
604 pos
= str2
.indexOf(",", 0);
608 pos
= str2
.indexOf(",", pos
);
611 al
.add(new Integer(cnt
));
617 This method can be used to get the MAX and current size
618 for pointer type dynamic(ex) PCD entry
620 public ArrayList
<Integer
> getPointerTypeSize () {
621 ArrayList
<Integer
> al
= new ArrayList
<Integer
>();
624 // For VPD_enabled and HII_enabled, we can only return the MAX size.
625 // For the default DATA type dynamic PCD entry, we will return
626 // the MAX size and current size for each SKU_ID.
628 al
.add(new Integer(this.datumSize
));
630 if (!this.isVpdEnable()) {
632 if (this.isHiiEnable()){
633 for (idx
= 0; idx
< this.skuData
.size(); idx
++) {
634 String str
= this.skuData
.get(idx
).value
.hiiDefaultValue
;
635 getCurrentSizeFromDefaultValue(str
, al
);
638 for (idx
= 0; idx
< this.skuData
.size(); idx
++) {
639 String str
= this.skuData
.get(idx
).value
.value
;
640 getCurrentSizeFromDefaultValue(str
, al
);
649 Get default value for a token, For HII type, HiiDefaultValue of default
650 SKU 0 will be returned; For Default type, the defaultvalue of default SKU
655 public String
getDynamicDefaultValue() {
656 DynamicTokenValue dynamicData
= getDefaultSku();
657 if (hasDefaultValue()) {
658 switch (dynamicData
.type
) {
660 return dynamicData
.value
;
668 // BugBug: We need change this algorithm accordingly when schema is updated
669 // to support no default value.
671 public boolean hasDefaultValue () {
673 boolean isInteger
= true;
674 DynamicTokenValue dynamicValue
= null;
680 if (this.isDynamicPCD
) {
681 dynamicValue
= getDefaultSku();
682 switch (dynamicValue
.type
) {
688 return !isValidNullValue(dynamicValue
.value
);
696 Judge the value is NULL value. NULL value means the value is uninitialized value
702 public boolean isValidNullValue(String judgedValue
) {
704 BigInteger bigIntValue
;
710 if (judgedValue
.length() > 2) {
711 if ((judgedValue
.charAt(0) == '0') &&
712 ((judgedValue
.charAt(1) == 'x') || (judgedValue
.charAt(1) == 'X'))){
713 subStr
= judgedValue
.substring(2, judgedValue
.length());
714 bigIntValue
= new BigInteger(subStr
, 16);
716 bigIntValue
= new BigInteger(judgedValue
);
719 bigIntValue
= new BigInteger(judgedValue
);
721 if (bigIntValue
.bitCount() == 0) {
726 if (judgedValue
.length() > 2){
727 if ((judgedValue
.charAt(0) == '0') &&
728 ((judgedValue
.charAt(1) == 'x') ||
729 (judgedValue
.charAt(1) == 'X'))) {
730 bigIntValue
= new BigInteger(judgedValue
.substring(2, judgedValue
.length()), 16);
731 if (bigIntValue
.bitCount() == 0) {
735 bigIntValue
= new BigInteger(judgedValue
);
736 if (bigIntValue
.bitCount() == 0) {
741 bigIntValue
= new BigInteger(judgedValue
);
742 if (bigIntValue
.bitCount() == 0) {
748 if (judgedValue
.equalsIgnoreCase("false")) {
753 if (judgedValue
.equalsIgnoreCase("") ||
754 judgedValue
.equalsIgnoreCase("\"\"") ||
755 judgedValue
.equalsIgnoreCase("L\"\"") ||
756 (judgedValue
.length() == 0) ||
757 judgedValue
.equalsIgnoreCase("{0}")) {
765 Is the string value in Unicode
769 public boolean isHiiDefaultValueUnicodeStringType() {
770 DynamicTokenValue dynamicData
= getDefaultSku();
772 if (dynamicData
== null)
775 return dynamicData
.hiiDefaultValue
.startsWith("L\"")
776 && dynamicData
.hiiDefaultValue
.endsWith("\"");
780 Is the string value in ANSCI
784 public boolean isHiiDefaultValueASCIIStringType() {
785 DynamicTokenValue dynamicData
= getDefaultSku();
787 if (dynamicData
== null)
790 return dynamicData
.hiiDefaultValue
.startsWith("\"")
791 && dynamicData
.hiiDefaultValue
.endsWith("\"");
795 Judege whether current value is UNICODE string type.
798 public boolean isUnicodeStringType () {
799 String str
= getDynamicDefaultValue();
805 if (datumType
== Token
.DATUM_TYPE
.POINTER
&&
806 str
.startsWith("L\"") &&
807 str
.endsWith("\"")) {
814 public boolean isASCIIStringType () {
815 String str
= getDynamicDefaultValue();
821 if (datumType
== Token
.DATUM_TYPE
.POINTER
&&
822 str
.startsWith("\"") &&
823 str
.endsWith("\"")) {
830 public boolean isByteStreamType () {
831 String str
= getDynamicDefaultValue();
837 if (datumType
== Token
.DATUM_TYPE
.POINTER
&&
838 str
.startsWith("{") &&
847 public String
getStringTypeString () {
848 return getDefaultSku().value
.substring(2, getDefaultSku().value
.length() - 1);