2 CollectPCDAction class.
4 This action class is to collect PCD information from MSA, SPD, FPD xml file.
5 This class will be used for wizard and build tools, So it can *not* inherit
6 from buildAction or wizardAction.
8 Copyright (c) 2006, Intel Corporation
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 package org
.tianocore
.build
.pcd
.action
;
20 import java
.io
.BufferedReader
;
22 import java
.io
.FileReader
;
23 import java
.io
.IOException
;
24 import java
.math
.BigInteger
;
25 import java
.util
.ArrayList
;
26 import java
.util
.Comparator
;
27 import java
.util
.HashMap
;
28 import java
.util
.Iterator
;
29 import java
.util
.List
;
32 import java
.util
.UUID
;
33 import java
.util
.regex
.Matcher
;
34 import java
.util
.regex
.Pattern
;
36 import org
.apache
.xmlbeans
.XmlException
;
37 import org
.apache
.xmlbeans
.XmlObject
;
38 import org
.tianocore
.DynamicPcdBuildDefinitionsDocument
.DynamicPcdBuildDefinitions
;
39 import org
.tianocore
.FrameworkModulesDocument
;
40 import org
.tianocore
.PlatformSurfaceAreaDocument
;
41 import org
.tianocore
.PcdBuildDefinitionDocument
;
42 import org
.tianocore
.ModuleSADocument
;
43 import org
.tianocore
.PcdBuildDefinitionDocument
.PcdBuildDefinition
;
44 import org
.tianocore
.build
.autogen
.CommonDefinition
;
45 import org
.tianocore
.build
.global
.GlobalData
;
46 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
47 import org
.tianocore
.build
.pcd
.action
.ActionMessage
;
48 import org
.tianocore
.build
.pcd
.entity
.DynamicTokenValue
;
49 import org
.tianocore
.build
.pcd
.entity
.MemoryDatabaseManager
;
50 import org
.tianocore
.build
.pcd
.entity
.SkuInstance
;
51 import org
.tianocore
.build
.pcd
.entity
.Token
;
52 import org
.tianocore
.build
.pcd
.entity
.UsageInstance
;
53 import org
.tianocore
.build
.pcd
.exception
.EntityException
;
56 CStructTypeDeclaration
58 This class is used to store the declaration string, such as
59 "UINT32 PcdPlatformFlashBaseAddress", of
60 each memember in the C structure, which is a standard C language
61 feature used to implement a simple and efficient database for
62 dynamic(ex) type PCD entry.
65 class CStructTypeDeclaration
{
71 public CStructTypeDeclaration (String key
, int alignmentSize
, String cCode
, boolean initTable
) {
73 this.alignmentSize
= alignmentSize
;
75 this.initTable
= initTable
;
82 This class is used to store the String in a PCD database.
86 private ArrayList
<String
> al
;
87 private ArrayList
<String
> alComments
;
91 public StringTable (String phase
) {
93 al
= new ArrayList
<String
>();
94 alComments
= new ArrayList
<String
>();
98 public String
getSizeMacro () {
99 return String
.format(PcdDatabase
.StringTableSizeMacro
, phase
, getSize());
102 private int getSize () {
104 // We have at least one Unicode Character in the table.
106 return len
== 0 ?
1 : len
;
109 public String
getExistanceMacro () {
110 return String
.format(PcdDatabase
.StringTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
113 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
) {
114 final String stringTable
= "StringTable";
115 final String tab
= "\t";
116 final String newLine
= "\r\n";
117 final String commaNewLine
= ",\r\n";
119 CStructTypeDeclaration decl
;
121 String cDeclCode
= "";
122 String cInstCode
= "";
125 // If we have a empty StringTable
127 if (al
.size() == 0) {
128 cDeclCode
+= String
.format("%-20s%s[1]; /* StringTable is empty */", "UINT16", stringTable
) + newLine
;
129 decl
= new CStructTypeDeclaration (
137 cInstCode
= String
.format("/* %s */", stringTable
) + newLine
+ tab
+ "{ 0 }";
138 instTable
.put(stringTable
, cInstCode
);
142 // If there is any String in the StringTable
144 for (int i
= 0; i
< al
.size(); i
++) {
145 String str
= al
.get(i
);
146 String stringTableName
;
150 // StringTable is a well-known name in the PCD DXE driver
152 stringTableName
= stringTable
;
155 stringTableName
= String
.format("%s_%d", stringTable
, i
);
158 cDeclCode
+= String
.format("%-20s%s[%d]; /* %s */", "UINT16",
159 stringTableName
, str
.length() + 1,
164 cInstCode
= "/* StringTable */" + newLine
;
167 cInstCode
+= tab
+ String
.format("L\"%s\" /* %s */", al
.get(i
), alComments
.get(i
));
168 if (i
!= al
.size() - 1) {
169 cInstCode
+= commaNewLine
;
173 decl
= new CStructTypeDeclaration (
181 instTable
.put(stringTable
, cInstCode
);
185 public int add (String inputStr
, Token token
) {
189 String str
= inputStr
;
192 // The input can be two types:
193 // "L\"Bootmode\"" or "Bootmode".
194 // We drop the L\" and \" for the first type.
195 if (str
.startsWith("L\"") && str
.endsWith("\"")) {
196 str
= str
.substring(2, str
.length() - 1);
199 // Check if StringTable has this String already.
200 // If so, return the current pos.
202 for (i
= 0, pos
= 0; i
< al
.size(); i
++) {
203 String s
= al
.get(i
);;
208 pos
= s
.length() + 1;
213 // Include the NULL character at the end of String
215 len
+= str
.length() + 1;
217 alComments
.add(token
.getPrimaryKeyString());
226 This class is used to store the Size information for
227 POINTER TYPE PCD entry in a PCD database.
231 private ArrayList
<Integer
> al
;
232 private ArrayList
<String
> alComments
;
233 private String phase
;
236 public SizeTable (String phase
) {
238 al
= new ArrayList
<Integer
>();
239 alComments
= new ArrayList
<String
>();
243 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
244 final String name
= "SizeTable";
246 CStructTypeDeclaration decl
;
249 cCode
= String
.format(PcdDatabase
.SizeTableDeclaration
, phase
);
250 decl
= new CStructTypeDeclaration (
259 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
260 instTable
.put(name
, cCode
);
263 private ArrayList
<String
> getInstantiation () {
264 ArrayList
<String
> Output
= new ArrayList
<String
>();
266 Output
.add("/* SizeTable */");
268 if (al
.size() == 0) {
271 for (int index
= 0; index
< al
.size(); index
++) {
272 Integer n
= al
.get(index
);
273 String str
= "\t" + n
.toString();
275 if (index
!= (al
.size() - 1)) {
279 str
+= " /* " + alComments
.get(index
) + " */";
289 public int add (Token token
) {
293 al
.add(token
.datumSize
);
294 alComments
.add(token
.getPrimaryKeyString());
299 public int getTableLen () {
300 return al
.size() == 0 ?
1 : al
.size();
308 This class is used to store the GUIDs in a PCD database.
311 private ArrayList
<UUID
> al
;
312 private ArrayList
<String
> alComments
;
313 private String phase
;
315 private int bodyLineNum
;
317 public GuidTable (String phase
) {
319 al
= new ArrayList
<UUID
>();
320 alComments
= new ArrayList
<String
>();
325 public String
getSizeMacro () {
326 return String
.format(PcdDatabase
.GuidTableSizeMacro
, phase
, getSize());
329 private int getSize () {
330 return (al
.size() == 0)?
1 : al
.size();
333 public String
getExistanceMacro () {
334 return String
.format(PcdDatabase
.GuidTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
337 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
338 final String name
= "GuidTable";
340 CStructTypeDeclaration decl
;
343 cCode
+= String
.format(PcdDatabase
.GuidTableDeclaration
, phase
);
344 decl
= new CStructTypeDeclaration (
353 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
354 instTable
.put(name
, cCode
);
357 private String
getUuidCString (UUID uuid
) {
358 String
[] guidStrArray
;
360 guidStrArray
=(uuid
.toString()).split("-");
362 return String
.format("{0x%s, 0x%s, 0x%s, {0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s}}",
366 (guidStrArray
[3].substring(0, 2)),
367 (guidStrArray
[3].substring(2, 4)),
368 (guidStrArray
[4].substring(0, 2)),
369 (guidStrArray
[4].substring(2, 4)),
370 (guidStrArray
[4].substring(4, 6)),
371 (guidStrArray
[4].substring(6, 8)),
372 (guidStrArray
[4].substring(8, 10)),
373 (guidStrArray
[4].substring(10, 12))
377 private ArrayList
<String
> getInstantiation () {
378 ArrayList
<String
> Output
= new ArrayList
<String
>();
380 Output
.add("/* GuidTable */");
383 if (al
.size() == 0) {
384 Output
.add("\t" + getUuidCString(new UUID(0, 0)));
387 for (int i
= 0; i
< al
.size(); i
++) {
388 String str
= "\t" + getUuidCString(al
.get(i
));
390 str
+= "/* " + alComments
.get(i
) + " */";
391 if (i
!= (al
.size() - 1)) {
403 public int add (UUID uuid
, String name
) {
405 // Check if GuidTable has this entry already.
406 // If so, return the GuidTable index.
408 for (int i
= 0; i
< al
.size(); i
++) {
409 if (al
.get(i
).equals(uuid
)) {
416 alComments
.add(name
);
419 // Return the previous Table Index
429 This class is used to store the SKU IDs in a PCD database.
433 private ArrayList
<Integer
[]> al
;
434 private ArrayList
<String
> alComment
;
435 private String phase
;
438 public SkuIdTable (String phase
) {
440 al
= new ArrayList
<Integer
[]>();
441 alComment
= new ArrayList
<String
>();
445 public String
getSizeMacro () {
446 return String
.format(PcdDatabase
.SkuIdTableSizeMacro
, phase
, getSize());
449 private int getSize () {
450 return (len
== 0)?
1 : len
;
453 public String
getExistanceMacro () {
454 return String
.format(PcdDatabase
.SkuTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
457 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
458 final String name
= "SkuIdTable";
460 CStructTypeDeclaration decl
;
463 cCode
+= String
.format(PcdDatabase
.SkuIdTableDeclaration
, phase
);
464 decl
= new CStructTypeDeclaration (
473 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
474 instTable
.put(name
, cCode
);
477 // SystemSkuId is in PEI phase PCD Database
479 if (phase
.equalsIgnoreCase("PEI")) {
480 decl
= new CStructTypeDeclaration (
483 String
.format("%-20sSystemSkuId;\r\n", "SKU_ID"),
488 instTable
.put("SystemSkuId", "0");
493 private ArrayList
<String
> getInstantiation () {
494 ArrayList
<String
> Output
= new ArrayList
<String
> ();
496 Output
.add("/* SkuIdTable */");
499 if (al
.size() == 0) {
503 for (int index
= 0; index
< al
.size(); index
++) {
506 str
= "/* " + alComment
.get(index
) + "*/ ";
507 str
+= "/* MaxSku */ ";
510 Integer
[] ia
= al
.get(index
);
512 str
+= "\t" + ia
[0].toString() + ", ";
513 for (int index2
= 1; index2
< ia
.length
; index2
++) {
514 str
+= ia
[index2
].toString();
515 if (!((index2
== ia
.length
- 1) && (index
== al
.size() - 1))) {
529 public int add (Token token
) {
535 // Check if this SKU_ID Array is already in the table
539 Integer
[] s
= (Integer
[]) o
;
540 boolean different
= false;
541 if (s
[0] == token
.getSkuIdCount()) {
542 for (index
= 1; index
< s
.length
; index
++) {
543 if (s
[index
] != token
.skuData
.get(index
-1).id
) {
558 Integer
[] skuIds
= new Integer
[token
.skuData
.size() + 1];
559 skuIds
[0] = new Integer(token
.skuData
.size());
560 for (index
= 1; index
< skuIds
.length
; index
++) {
561 skuIds
[index
] = new Integer(token
.skuData
.get(index
- 1).id
);
566 len
+= skuIds
.length
;
568 alComment
.add(token
.getPrimaryKeyString());
575 class LocalTokenNumberTable
{
576 private ArrayList
<String
> al
;
577 private ArrayList
<String
> alComment
;
578 private String phase
;
581 public LocalTokenNumberTable (String phase
) {
583 al
= new ArrayList
<String
>();
584 alComment
= new ArrayList
<String
>();
589 public String
getSizeMacro () {
590 return String
.format(PcdDatabase
.LocalTokenNumberTableSizeMacro
, phase
, getSize())
591 + String
.format(PcdDatabase
.LocalTokenNumberSizeMacro
, phase
, al
.size());
594 public int getSize () {
595 return (al
.size() == 0)?
1 : al
.size();
598 public String
getExistanceMacro () {
599 return String
.format(PcdDatabase
.DatabaseExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
602 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
603 final String name
= "LocalTokenNumberTable";
605 CStructTypeDeclaration decl
;
608 cCode
+= String
.format(PcdDatabase
.LocalTokenNumberTableDeclaration
, phase
);
609 decl
= new CStructTypeDeclaration (
617 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
618 instTable
.put(name
, cCode
);
621 private ArrayList
<String
> getInstantiation () {
622 ArrayList
<String
> output
= new ArrayList
<String
>();
624 output
.add("/* LocalTokenNumberTable */");
627 if (al
.size() == 0) {
631 for (int index
= 0; index
< al
.size(); index
++) {
634 str
= "\t" + (String
)al
.get(index
);
636 str
+= " /* " + alComment
.get(index
) + " */ ";
639 if (index
!= (al
.size() - 1)) {
652 public int add (Token token
) {
658 str
= String
.format(PcdDatabase
.offsetOfStrTemplate
, phase
, token
.hasDefaultValue() ?
"Init" : "Uninit", token
.getPrimaryKeyString());
660 if (token
.isUnicodeStringType()) {
661 str
+= " | PCD_TYPE_STRING";
664 if (token
.isSkuEnable()) {
665 str
+= " | PCD_TYPE_SKU_ENABLED";
668 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
669 str
+= " | PCD_TYPE_HII";
672 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
673 str
+= " | PCD_TYPE_VPD";
677 alComment
.add(token
.getPrimaryKeyString());
686 This class is used to store the table of mapping information
687 between DynamicEX ID pair(Guid, TokenNumber) and
688 the local token number assigned by PcdDatabase class.
695 This class is used to store the mapping information
696 between DynamicEX ID pair(Guid, TokenNumber) and
697 the local token number assigned by PcdDatabase class.
700 public Integer guidTableIdx
;
701 public Long exTokenNumber
;
702 public Long localTokenIdx
;
704 public ExTriplet (int guidTableIdx
, long exTokenNumber
, long localTokenIdx
) {
705 this.guidTableIdx
= new Integer(guidTableIdx
);
706 this.exTokenNumber
= new Long(exTokenNumber
);
707 this.localTokenIdx
= new Long(localTokenIdx
);
711 private ArrayList
<ExTriplet
> al
;
712 private ArrayList
<String
> alComment
;
713 private String phase
;
715 private int bodyLineNum
;
717 public ExMapTable (String phase
) {
719 al
= new ArrayList
<ExTriplet
>();
720 alComment
= new ArrayList
<String
>();
725 public String
getSizeMacro () {
726 return String
.format(PcdDatabase
.ExMapTableSizeMacro
, phase
, getTableLen())
727 + String
.format(PcdDatabase
.ExTokenNumber
, phase
, al
.size());
730 public String
getExistanceMacro () {
731 return String
.format(PcdDatabase
.ExMapTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
734 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
735 final String exMapTableName
= "ExMapTable";
739 CStructTypeDeclaration decl
;
742 cCode
+= String
.format(PcdDatabase
.ExMapTableDeclaration
, phase
);
743 decl
= new CStructTypeDeclaration (
752 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
753 instTable
.put(exMapTableName
, cCode
);
756 private ArrayList
<String
> getInstantiation () {
757 ArrayList
<String
> Output
= new ArrayList
<String
>();
759 Output
.add("/* ExMapTable */");
761 if (al
.size() == 0) {
762 Output
.add("\t{0, 0, 0}");
766 for (index
= 0; index
< al
.size(); index
++) {
769 ExTriplet e
= (ExTriplet
)al
.get(index
);
771 str
= "\t" + "{ " + String
.format("0x%08X", e
.exTokenNumber
) + ", ";
772 str
+= e
.localTokenIdx
.toString() + ", ";
773 str
+= e
.guidTableIdx
.toString();
775 str
+= "}" + " /* " + alComment
.get(index
) + " */" ;
777 if (index
!= al
.size() - 1) {
791 public int add (int localTokenIdx
, long exTokenNum
, int guidTableIdx
, String name
) {
795 al
.add(new ExTriplet(guidTableIdx
, exTokenNum
, localTokenIdx
));
801 private int getTableLen () {
802 return al
.size() == 0 ?
1 : al
.size();
806 // To simplify the algorithm for GetNextToken and GetNextTokenSpace in
807 // PCD PEIM/Driver, we need to sort the ExMapTable according to the
812 class ExTripletComp
implements Comparator
<ExTriplet
> {
813 public int compare (ExTriplet a
, ExTriplet b
) {
814 if (a
.guidTableIdx
== b
.guidTableIdx
) {
816 // exTokenNumber is long, we can't use simple substraction.
818 if (a
.exTokenNumber
> b
.exTokenNumber
) {
820 } else if (a
.exTokenNumber
== b
.exTokenNumber
) {
827 return a
.guidTableIdx
- b
.guidTableIdx
;
831 private void sortTable () {
832 java
.util
.Comparator
<ExTriplet
> comparator
= new ExTripletComp();
833 java
.util
.Collections
.sort(al
, comparator
);
840 This class is used to generate C code for Autogen.h and Autogen.c of
841 a PCD service DXE driver and PCD service PEIM.
845 private final static int SkuHeadAlignmentSize
= 4;
846 private final String newLine
= "\r\n";
847 private final String commaNewLine
= ",\r\n";
848 private final String tab
= "\t";
849 public final static String ExMapTableDeclaration
= "DYNAMICEX_MAPPING ExMapTable[%s_EXMAPPING_TABLE_SIZE];\r\n";
850 public final static String GuidTableDeclaration
= "EFI_GUID GuidTable[%s_GUID_TABLE_SIZE];\r\n";
851 public final static String LocalTokenNumberTableDeclaration
= "UINT32 LocalTokenNumberTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";
852 public final static String StringTableDeclaration
= "UINT16 StringTable[%s_STRING_TABLE_SIZE];\r\n";
853 public final static String SizeTableDeclaration
= "UINT16 SizeTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";
854 public final static String SkuIdTableDeclaration
= "UINT8 SkuIdTable[%s_SKUID_TABLE_SIZE];\r\n";
857 public final static String ExMapTableSizeMacro
= "#define %s_EXMAPPING_TABLE_SIZE %d\r\n";
858 public final static String ExTokenNumber
= "#define %s_EX_TOKEN_NUMBER %d\r\n";
859 public final static String GuidTableSizeMacro
= "#define %s_GUID_TABLE_SIZE %d\r\n";
860 public final static String LocalTokenNumberTableSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER_TABLE_SIZE %d\r\n";
861 public final static String LocalTokenNumberSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER %d\r\n";
862 public final static String StringTableSizeMacro
= "#define %s_STRING_TABLE_SIZE %d\r\n";
863 public final static String SkuIdTableSizeMacro
= "#define %s_SKUID_TABLE_SIZE %d\r\n";
866 public final static String ExMapTableExistenceMacro
= "#define %s_EXMAP_TABLE_EMPTY %s\r\n";
867 public final static String GuidTableExistenceMacro
= "#define %s_GUID_TABLE_EMPTY %s\r\n";
868 public final static String DatabaseExistenceMacro
= "#define %s_DATABASE_EMPTY %s\r\n";
869 public final static String StringTableExistenceMacro
= "#define %s_STRING_TABLE_EMPTY %s\r\n";
870 public final static String SkuTableExistenceMacro
= "#define %s_SKUID_TABLE_EMPTY %s\r\n";
872 public final static String offsetOfSkuHeadStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)";
873 public final static String offsetOfVariableEnabledDefault
= "offsetof(%s_PCD_DATABASE, %s.%s_VariableDefault_%d)";
874 public final static String offsetOfStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s)";
876 private final static String skuDataTableTemplate
= "SkuDataTable";
879 private StringTable stringTable
;
880 private GuidTable guidTable
;
881 private LocalTokenNumberTable localTokenNumberTable
;
882 private SkuIdTable skuIdTable
;
883 private SizeTable sizeTable
;
884 private ExMapTable exMapTable
;
886 private ArrayList
<Token
> alTokens
;
887 private String phase
;
888 private int assignedTokenNumber
;
891 // Use two class global variable to store
894 private String privateGlobalName
;
895 private String privateGlobalCCode
;
897 // After Major changes done to the PCD
898 // database generation class PcdDatabase
899 // Please increment the version and please
900 // also update the version number in PCD
901 // service PEIM and DXE driver accordingly.
903 private final int version
= 2;
905 private String hString
;
906 private String cString
;
909 Constructor for PcdDatabase class.
911 <p>We have two PCD dynamic(ex) database for the Framework implementation. One
912 for PEI phase and the other for DXE phase. </p>
914 @param alTokens A ArrayList of Dynamic(EX) PCD entry.
915 @param exePhase The phase to generate PCD database for: valid input
917 @param startLen The starting Local Token Number for the PCD database. For
918 PEI phase, the starting Local Token Number starts from 0.
919 For DXE phase, the starting Local Token Number starts
920 from the total number of PCD entry of PEI phase.
923 public PcdDatabase (ArrayList
<Token
> alTokens
, String exePhase
, int startLen
) {
926 stringTable
= new StringTable(phase
);
927 guidTable
= new GuidTable(phase
);
928 localTokenNumberTable
= new LocalTokenNumberTable(phase
);
929 skuIdTable
= new SkuIdTable(phase
);
930 sizeTable
= new SizeTable(phase
);
931 exMapTable
= new ExMapTable(phase
);
934 // Local token number 0 is reserved for INVALID_TOKEN_NUMBER.
935 // So we will increment 1 for the startLen passed from the
938 assignedTokenNumber
= startLen
+ 1;
939 this.alTokens
= alTokens
;
942 private void getNonExAndExTokens (ArrayList
<Token
> alTokens
, List
<Token
> nexTokens
, List
<Token
> exTokens
) {
943 for (int i
= 0; i
< alTokens
.size(); i
++) {
944 Token t
= (Token
)alTokens
.get(i
);
945 if (t
.isDynamicEx()) {
955 private int getDataTypeAlignmentSize (Token token
) {
956 switch (token
.datumType
) {
974 private int getHiiPtrTypeAlignmentSize(Token token
) {
975 switch (token
.datumType
) {
985 if (token
.isHiiEnable()) {
986 if (token
.isHiiDefaultValueUnicodeStringType()) {
998 private int getAlignmentSize (Token token
) {
999 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
1003 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
1007 if (token
.isUnicodeStringType()) {
1011 return getDataTypeAlignmentSize(token
);
1014 public String
getCString () {
1018 public String
getHString () {
1022 private void genCodeWorker(Token t
,
1023 ArrayList
<CStructTypeDeclaration
> declaList
,
1024 HashMap
<String
, String
> instTable
, String phase
)
1025 throws EntityException
{
1027 CStructTypeDeclaration decl
;
1030 // Insert SKU_HEAD if isSkuEnable is true
1032 if (t
.isSkuEnable()) {
1034 tableIdx
= skuIdTable
.add(t
);
1035 decl
= new CStructTypeDeclaration(t
.getPrimaryKeyString(),
1036 SkuHeadAlignmentSize
, getSkuEnabledTypeDeclaration(t
), true);
1037 declaList
.add(decl
);
1038 instTable
.put(t
.getPrimaryKeyString(),
1039 getSkuEnabledTypeInstantiaion(t
, tableIdx
));
1043 // Insert PCD_ENTRY declaration and instantiation
1045 getCDeclarationString(t
);
1047 decl
= new CStructTypeDeclaration(privateGlobalName
,
1048 getAlignmentSize(t
), privateGlobalCCode
, t
.hasDefaultValue());
1049 declaList
.add(decl
);
1051 if (t
.hasDefaultValue()) {
1052 instTable
.put(privateGlobalName
,
1053 getTypeInstantiation(t
, declaList
, instTable
, phase
)
1059 private void ProcessTokens (List
<Token
> tokens
,
1060 ArrayList
<CStructTypeDeclaration
> cStructDeclList
,
1061 HashMap
<String
, String
> cStructInstTable
,
1064 throws EntityException
{
1066 for (int idx
= 0; idx
< tokens
.size(); idx
++) {
1067 Token t
= tokens
.get(idx
);
1069 genCodeWorker (t
, cStructDeclList
, cStructInstTable
, phase
);
1072 localTokenNumberTable
.add(t
);
1073 t
.tokenNumber
= assignedTokenNumber
++;
1076 // Add a mapping if this dynamic PCD entry is a EX type
1078 if (t
.isDynamicEx()) {
1079 exMapTable
.add((int)t
.tokenNumber
,
1080 t
.dynamicExTokenNumber
,
1081 guidTable
.add(t
.tokenSpaceName
, t
.getPrimaryKeyString()),
1082 t
.getPrimaryKeyString()
1089 public void genCode () throws EntityException
{
1091 ArrayList
<CStructTypeDeclaration
> cStructDeclList
= new ArrayList
<CStructTypeDeclaration
>();
1092 HashMap
<String
, String
> cStructInstTable
= new HashMap
<String
, String
>();
1094 List
<Token
> nexTokens
= new ArrayList
<Token
> ();
1095 List
<Token
> exTokens
= new ArrayList
<Token
> ();
1097 getNonExAndExTokens (alTokens
, nexTokens
, exTokens
);
1100 // We have to process Non-Ex type PCD entry first. The reason is
1101 // that our optimization assumes that the Token Number of Non-Ex
1102 // PCD entry start from 1 (for PEI phase) and grows continously upwards.
1104 // EX type token number starts from the last Non-EX PCD entry and
1105 // grows continously upwards.
1107 ProcessTokens (nexTokens
, cStructDeclList
, cStructInstTable
, phase
);
1108 ProcessTokens (exTokens
, cStructDeclList
, cStructInstTable
, phase
);
1110 stringTable
.genCode(cStructDeclList
, cStructInstTable
);
1111 skuIdTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1112 exMapTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1113 localTokenNumberTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1114 sizeTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1115 guidTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1117 hString
= genCMacroCode ();
1119 HashMap
<String
, String
> result
;
1121 result
= genCStructCode(cStructDeclList
,
1126 hString
+= result
.get("initDeclStr");
1127 hString
+= result
.get("uninitDeclStr");
1129 hString
+= String
.format("#define PCD_%s_SERVICE_DRIVER_VERSION %d", phase
, version
);
1131 cString
= newLine
+ newLine
+ result
.get("initInstStr");
1135 private String
genCMacroCode () {
1136 String macroStr
= "";
1139 // Generate size info Macro for all Tables
1141 macroStr
+= guidTable
.getSizeMacro();
1142 macroStr
+= stringTable
.getSizeMacro();
1143 macroStr
+= skuIdTable
.getSizeMacro();
1144 macroStr
+= localTokenNumberTable
.getSizeMacro();
1145 macroStr
+= exMapTable
.getSizeMacro();
1148 // Generate existance info Macro for all Tables
1150 macroStr
+= guidTable
.getExistanceMacro();
1151 macroStr
+= stringTable
.getExistanceMacro();
1152 macroStr
+= skuIdTable
.getExistanceMacro();
1153 macroStr
+= localTokenNumberTable
.getExistanceMacro();
1154 macroStr
+= exMapTable
.getExistanceMacro();
1156 macroStr
+= newLine
;
1161 private HashMap
<String
, String
> genCStructCode(
1162 ArrayList
<CStructTypeDeclaration
> declaList
,
1163 HashMap
<String
, String
> instTable
,
1168 HashMap
<String
, String
> result
= new HashMap
<String
, String
>();
1169 HashMap
<Integer
, ArrayList
<String
>> alignmentInitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1170 HashMap
<Integer
, ArrayList
<String
>> alignmentUninitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1171 HashMap
<Integer
, ArrayList
<String
>> alignmentInitInst
= new HashMap
<Integer
, ArrayList
<String
>>();
1174 // Initialize the storage for each alignment
1176 for (i
= 8; i
> 0; i
>>=1) {
1177 alignmentInitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1178 alignmentInitInst
.put(new Integer(i
), new ArrayList
<String
>());
1179 alignmentUninitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1182 String initDeclStr
= "typedef struct {" + newLine
;
1183 String initInstStr
= String
.format("%s_PCD_DATABASE_INIT g%sPcdDbInit = { ", phase
.toUpperCase(), phase
.toUpperCase()) + newLine
;
1184 String uninitDeclStr
= "typedef struct {" + newLine
;
1187 // Sort all C declaration and instantiation base on Alignment Size
1189 for (Object d
: declaList
) {
1190 CStructTypeDeclaration decl
= (CStructTypeDeclaration
) d
;
1192 if (decl
.initTable
) {
1193 alignmentInitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1194 alignmentInitInst
.get(new Integer(decl
.alignmentSize
)).add(instTable
.get(decl
.key
));
1196 alignmentUninitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1201 // Generate code for every alignment size
1203 boolean uinitDatabaseEmpty
= true;
1204 for (int align
= 8; align
> 0; align
>>= 1) {
1205 ArrayList
<String
> declaListBasedOnAlignment
= alignmentInitDecl
.get(new Integer(align
));
1206 ArrayList
<String
> instListBasedOnAlignment
= alignmentInitInst
.get(new Integer(align
));
1207 for (i
= 0; i
< declaListBasedOnAlignment
.size(); i
++) {
1208 initDeclStr
+= tab
+ declaListBasedOnAlignment
.get(i
);
1209 initInstStr
+= tab
+ instListBasedOnAlignment
.get(i
);
1212 // We made a assumption that both PEI_PCD_DATABASE and DXE_PCD_DATABASE
1213 // has a least one data memember with alignment size of 1. So we can
1214 // remove the last "," in the C structure instantiation string. Luckily,
1215 // this is true as both data structure has SKUID_TABLE anyway.
1217 if ((align
== 1) && (i
== declaListBasedOnAlignment
.size() - 1)) {
1218 initInstStr
+= newLine
;
1220 initInstStr
+= commaNewLine
;
1224 declaListBasedOnAlignment
= alignmentUninitDecl
.get(new Integer(align
));
1226 if (declaListBasedOnAlignment
.size() != 0) {
1227 uinitDatabaseEmpty
= false;
1230 for (Object d
: declaListBasedOnAlignment
) {
1231 String s
= (String
)d
;
1232 uninitDeclStr
+= tab
+ s
;
1236 if (uinitDatabaseEmpty
) {
1237 uninitDeclStr
+= tab
+ String
.format("%-20sdummy; /* PCD_DATABASE_UNINIT is emptry */\r\n", "UINT8");
1240 initDeclStr
+= String
.format("} %s_PCD_DATABASE_INIT;", phase
) + newLine
+ newLine
;
1241 initInstStr
+= "};" + newLine
;
1242 uninitDeclStr
+= String
.format("} %s_PCD_DATABASE_UNINIT;", phase
) + newLine
+ newLine
;
1244 result
.put("initDeclStr", initDeclStr
);
1245 result
.put("initInstStr", initInstStr
);
1246 result
.put("uninitDeclStr", uninitDeclStr
);
1251 public static String
genInstantiationStr (ArrayList
<String
> alStr
) {
1253 for (int i
= 0; i
< alStr
.size(); i
++) {
1257 str
+= alStr
.get(i
);
1258 if (i
!= alStr
.size() - 1) {
1266 private String
getSkuEnabledTypeDeclaration (Token token
) {
1267 return String
.format("%-20s%s;\r\n", "SKU_HEAD", token
.getPrimaryKeyString());
1270 private String
getSkuEnabledTypeInstantiaion (Token token
, int SkuTableIdx
) {
1272 String offsetof
= String
.format(PcdDatabase
.offsetOfSkuHeadStrTemplate
, phase
, token
.hasDefaultValue()?
"Init" : "Uninit", token
.getPrimaryKeyString());
1273 return String
.format("{ %s, %d } /* SKU_ENABLED: %s */", offsetof
, SkuTableIdx
, token
.getPrimaryKeyString());
1276 private String
getDataTypeInstantiationForVariableDefault (Token token
, String cName
, int skuId
) {
1277 return String
.format("%s /* %s */", token
.skuData
.get(skuId
).value
.hiiDefaultValue
, cName
);
1280 private String
getCType (Token t
)
1281 throws EntityException
{
1283 if (t
.isHiiEnable()) {
1284 return "VARIABLE_HEAD";
1287 if (t
.isVpdEnable()) {
1291 if (t
.isUnicodeStringType()) {
1292 return "STRING_HEAD";
1295 switch (t
.datumType
) {
1309 throw new EntityException("Unknown type in getDataTypeCDeclaration");
1313 private void getCDeclarationString(Token t
)
1314 throws EntityException
{
1316 if (t
.isSkuEnable()) {
1317 privateGlobalName
= String
.format("%s_%s", t
.getPrimaryKeyString(), skuDataTableTemplate
);
1319 privateGlobalName
= t
.getPrimaryKeyString();
1322 String type
= getCType(t
);
1323 if ((t
.datumType
== Token
.DATUM_TYPE
.POINTER
) && (!t
.isHiiEnable())) {
1325 if (t
.isASCIIStringType()) {
1327 // Build tool will add a NULL string at the end of the ASCII string
1329 bufferSize
= t
.datumSize
+ 1;
1331 bufferSize
= t
.datumSize
;
1333 privateGlobalCCode
= String
.format("%-20s%s[%d][%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount(), bufferSize
);
1335 privateGlobalCCode
= String
.format("%-20s%s[%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount());
1339 private String
getDataTypeDeclarationForVariableDefault (Token token
, String cName
, int skuId
)
1340 throws EntityException
{
1344 if (token
.datumType
== Token
.DATUM_TYPE
.UINT8
) {
1346 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT16
) {
1348 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT32
) {
1350 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT64
) {
1352 } else if (token
.datumType
== Token
.DATUM_TYPE
.BOOLEAN
) {
1353 typeStr
= "BOOLEAN";
1354 } else if (token
.datumType
== Token
.DATUM_TYPE
.POINTER
) {
1356 if (token
.isHiiDefaultValueUnicodeStringType()) {
1359 // Include the NULL charactor
1361 size
= token
.datumSize
/ 2 + 1;
1364 if (token
.isHiiDefaultValueASCIIStringType()) {
1366 // Include the NULL charactor
1368 size
= token
.datumSize
+ 1;
1370 size
= token
.datumSize
;
1373 return String
.format("%-20s%s[%d];\r\n", typeStr
, cName
, size
);
1375 throw new EntityException("Unknown DATUM_TYPE type in when generating code for VARIABLE_ENABLED PCD entry");
1378 return String
.format("%-20s%s;\r\n", typeStr
, cName
);
1381 private String
getTypeInstantiation (Token t
, ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) throws EntityException
{
1386 s
= String
.format("/* %s */", t
.getPrimaryKeyString()) + newLine
;
1387 s
+= tab
+ "{" + newLine
;
1389 for (i
= 0; i
< t
.skuData
.size(); i
++) {
1390 if (t
.isUnicodeStringType()) {
1391 s
+= tab
+ tab
+ String
.format("{ %d }", stringTable
.add(t
.skuData
.get(i
).value
.value
, t
));
1392 } else if (t
.isHiiEnable()) {
1393 /* VPD_HEAD definition
1395 UINT16 GuidTableIndex; // Offset in Guid Table in units of GUID.
1396 UINT16 StringIndex; // Offset in String Table in units of UINT16.
1397 UINT16 Offset; // Offset in Variable
1398 UINT16 DefaultValueOffset; // Offset of the Default Value
1401 String variableDefaultName
= String
.format("%s_VariableDefault_%d", t
.getPrimaryKeyString(), i
);
1403 s
+= tab
+ tab
+ String
.format("{ %d, %d, %s, %s }", guidTable
.add(t
.skuData
.get(i
).value
.variableGuid
, t
.getPrimaryKeyString()),
1404 stringTable
.add(t
.skuData
.get(i
).value
.getStringOfVariableName(), t
),
1405 t
.skuData
.get(i
).value
.variableOffset
,
1406 String
.format("offsetof(%s_PCD_DATABASE, Init.%s)", phase
, variableDefaultName
)
1409 // We need to support the default value, so we add the declaration and
1410 // the instantiation for the default value.
1412 CStructTypeDeclaration decl
= new CStructTypeDeclaration (variableDefaultName
,
1413 getHiiPtrTypeAlignmentSize(t
),
1414 getDataTypeDeclarationForVariableDefault(t
, variableDefaultName
, i
),
1417 declaList
.add(decl
);
1418 instTable
.put(variableDefaultName
, getDataTypeInstantiationForVariableDefault (t
, variableDefaultName
, i
));
1419 } else if (t
.isVpdEnable()) {
1424 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.vpdOffset
);
1426 if (t
.isByteStreamType()) {
1428 // Byte stream type input has their own "{" "}", so we won't help to insert.
1430 s
+= tab
+ tab
+ String
.format(" %s ", t
.skuData
.get(i
).value
.value
);
1432 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.value
);
1436 if (i
!= t
.skuData
.size() - 1) {
1449 public static String
getPcdDatabaseCommonDefinitions ()
1450 throws EntityException
{
1454 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1455 "Tools" + File
.separator
+
1456 "Conf" + File
.separator
+
1457 "Pcd" + File
.separator
+
1458 "PcdDatabaseCommonDefinitions.sample");
1459 FileReader reader
= new FileReader(file
);
1460 BufferedReader in
= new BufferedReader(reader
);
1462 while ((str
= in
.readLine()) != null) {
1463 retStr
= retStr
+"\r\n" + str
;
1465 } catch (Exception ex
) {
1466 throw new EntityException("Fatal error when generating PcdDatabase Common Definitions");
1472 public static String
getPcdDxeDatabaseDefinitions ()
1473 throws EntityException
{
1477 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1478 "Tools" + File
.separator
+
1479 "Conf" + File
.separator
+
1480 "Pcd" + File
.separator
+
1481 "PcdDatabaseDxeDefinitions.sample");
1482 FileReader reader
= new FileReader(file
);
1483 BufferedReader in
= new BufferedReader(reader
);
1485 while ((str
= in
.readLine()) != null) {
1486 retStr
= retStr
+"\r\n" + str
;
1488 } catch (Exception ex
) {
1489 throw new EntityException("Fatal error when generating PcdDatabase Dxe Definitions");
1495 public static String
getPcdPeiDatabaseDefinitions ()
1496 throws EntityException
{
1500 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1501 "Tools" + File
.separator
+
1502 "Conf" + File
.separator
+
1503 "Pcd" + File
.separator
+
1504 "PcdDatabasePeiDefinitions.sample");
1505 FileReader reader
= new FileReader(file
);
1506 BufferedReader in
= new BufferedReader(reader
);
1508 while ((str
= in
.readLine()) != null) {
1509 retStr
= retStr
+"\r\n" + str
;
1511 } catch (Exception ex
) {
1512 throw new EntityException("Fatal error when generating PcdDatabase Pei Definitions");
1521 private String type
;
1522 private FpdModuleIdentification moduleId
;
1523 private PcdBuildDefinitionDocument
.PcdBuildDefinition pcdBuildDef
;
1527 public ModuleInfo (FpdModuleIdentification moduleId
, String type
, XmlObject pcdDef
) {
1528 this.moduleId
= moduleId
;
1530 this.pcdBuildDef
= ((PcdBuildDefinitionDocument
)pcdDef
).getPcdBuildDefinition();
1532 public String
getModuleType (){
1535 public FpdModuleIdentification
getModuleId (){
1536 return this.moduleId
;
1538 public PcdBuildDefinitionDocument
.PcdBuildDefinition
getPcdBuildDef(){
1539 return this.pcdBuildDef
;
1543 /** This action class is to collect PCD information from MSA, SPD, FPD xml file.
1544 This class will be used for wizard and build tools, So it can *not* inherit
1545 from buildAction or UIAction.
1547 public class CollectPCDAction
{
1548 /// memoryDatabase hold all PCD information collected from SPD, MSA, FPD.
1549 private MemoryDatabaseManager dbManager
;
1551 /// Workspacepath hold the workspace information.
1552 private String workspacePath
;
1554 /// FPD file is the root file.
1555 private String fpdFilePath
;
1557 /// Message level for CollectPCDAction.
1558 private int originalMessageLevel
;
1560 /// Cache the fpd docment instance for private usage.
1561 private PlatformSurfaceAreaDocument fpdDocInstance
;
1564 private static String xmlObjectName
= "PcdBuildDefinition";
1567 Set WorkspacePath parameter for this action class.
1569 @param workspacePath parameter for this action
1571 public void setWorkspacePath(String workspacePath
) {
1572 this.workspacePath
= workspacePath
;
1576 Set action message level for CollectPcdAction tool.
1578 The message should be restored when this action exit.
1580 @param actionMessageLevel parameter for this action
1582 public void setActionMessageLevel(int actionMessageLevel
) {
1583 originalMessageLevel
= ActionMessage
.messageLevel
;
1584 ActionMessage
.messageLevel
= actionMessageLevel
;
1588 Set FPDFileName parameter for this action class.
1590 @param fpdFilePath fpd file path
1592 public void setFPDFilePath(String fpdFilePath
) {
1593 this.fpdFilePath
= fpdFilePath
;
1597 Common function interface for outer.
1599 @param workspacePath The path of workspace of current build or analysis.
1600 @param fpdFilePath The fpd file path of current build or analysis.
1601 @param messageLevel The message level for this Action.
1603 @throws Exception The exception of this function. Because it can *not* be predict
1604 where the action class will be used. So only Exception can be throw.
1607 public void perform(String workspacePath
, String fpdFilePath
,
1608 int messageLevel
) throws Exception
{
1609 setWorkspacePath(workspacePath
);
1610 setFPDFilePath(fpdFilePath
);
1611 setActionMessageLevel(messageLevel
);
1614 ActionMessage
.messageLevel
= originalMessageLevel
;
1618 Core execution function for this action class.
1620 This function work flows will be:
1621 1) Collect and prepocess PCD information from FPD file, all PCD
1622 information will be stored into memory database.
1623 2) Generate 3 strings for
1624 a) All modules using Dynamic(Ex) PCD entry.(Token Number)
1625 b) PEI PCDDatabase (C Structure) for PCD Service PEIM.
1626 c) DXE PCD Database (C structure) for PCD Service DXE.
1629 @throws EntityException Exception indicate failed to execute this action.
1632 public void execute() throws EntityException
{
1634 // Get memoryDatabaseManager instance from GlobalData.
1635 // The memoryDatabaseManager should be initialized for whatever build
1636 // tools or wizard tools
1638 if((dbManager
= GlobalData
.getPCDMemoryDBManager()) == null) {
1639 throw new EntityException("The instance of PCD memory database manager is null");
1643 // Collect all PCD information defined in FPD file.
1644 // Evenry token defind in FPD will be created as an token into
1647 createTokenInDBFromFPD();
1650 // Call Private function genPcdDatabaseSourceCode (void); ComponentTypeBsDriver
1651 // 1) Generate for PEI, DXE PCD DATABASE's definition and initialization.
1653 genPcdDatabaseSourceCode ();
1658 This function generates source code for PCD Database.
1661 @throws EntityException If the token does *not* exist in memory database.
1664 private void genPcdDatabaseSourceCode()
1665 throws EntityException
{
1666 String PcdCommonHeaderString
= PcdDatabase
.getPcdDatabaseCommonDefinitions ();
1668 ArrayList
<Token
> alPei
= new ArrayList
<Token
> ();
1669 ArrayList
<Token
> alDxe
= new ArrayList
<Token
> ();
1671 dbManager
.getTwoPhaseDynamicRecordArray(alPei
, alDxe
);
1672 PcdDatabase pcdPeiDatabase
= new PcdDatabase (alPei
, "PEI", 0);
1673 pcdPeiDatabase
.genCode();
1674 MemoryDatabaseManager
.PcdPeimHString
= PcdCommonHeaderString
+ pcdPeiDatabase
.getHString()
1675 + PcdDatabase
.getPcdPeiDatabaseDefinitions();
1676 MemoryDatabaseManager
.PcdPeimCString
= pcdPeiDatabase
.getCString();
1678 PcdDatabase pcdDxeDatabase
= new PcdDatabase (alDxe
,
1682 pcdDxeDatabase
.genCode();
1683 MemoryDatabaseManager
.PcdDxeHString
= MemoryDatabaseManager
.PcdPeimHString
+ pcdDxeDatabase
.getHString()
1684 + PcdDatabase
.getPcdDxeDatabaseDefinitions();
1685 MemoryDatabaseManager
.PcdDxeCString
= pcdDxeDatabase
.getCString();
1689 Get component array from FPD.
1691 This function maybe provided by some Global class.
1693 @return List<ModuleInfo> the component array.
1696 private List
<ModuleInfo
> getComponentsFromFPD()
1697 throws EntityException
{
1698 List
<ModuleInfo
> allModules
= new ArrayList
<ModuleInfo
>();
1699 ModuleInfo current
= null;
1701 FrameworkModulesDocument
.FrameworkModules fModules
= null;
1702 ModuleSADocument
.ModuleSA
[] modules
= null;
1703 HashMap
<String
, XmlObject
> map
= new HashMap
<String
, XmlObject
>();
1705 if (fpdDocInstance
== null) {
1707 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
1708 } catch(IOException ioE
) {
1709 throw new EntityException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
1710 } catch(XmlException xmlE
) {
1711 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
1716 Map
<FpdModuleIdentification
,XmlObject
>pcdBuildDef
= GlobalData
.getFpdModuleSaXmlObject(CollectPCDAction
.xmlObjectName
);
1717 Set
<FpdModuleIdentification
> pcdBuildKeySet
= pcdBuildDef
.keySet();
1718 Iterator item
= pcdBuildKeySet
.iterator();
1719 while (item
.hasNext()){
1720 FpdModuleIdentification id
= (FpdModuleIdentification
)item
.next();
1721 allModules
.add(new ModuleInfo(id
, id
.getModule().getModuleType(),pcdBuildDef
.get(id
)));
1728 Create token instance object into memory database, the token information
1729 comes for FPD file. Normally, FPD file will contain all token platform
1732 @return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage.
1734 @throws EntityException Failed to parse FPD xml file.
1737 private void createTokenInDBFromFPD()
1738 throws EntityException
{
1742 List
<PcdBuildDefinition
.PcdData
> pcdBuildDataArray
= new ArrayList
<PcdBuildDefinition
.PcdData
>();
1743 PcdBuildDefinition
.PcdData pcdBuildData
= null;
1745 List
<ModuleInfo
> modules
= null;
1746 String primaryKey
= null;
1747 String exceptionString
= null;
1748 UsageInstance usageInstance
= null;
1749 String primaryKey1
= null;
1750 String primaryKey2
= null;
1751 boolean isDuplicate
= false;
1752 Token
.PCD_TYPE pcdType
= Token
.PCD_TYPE
.UNKNOWN
;
1753 Token
.DATUM_TYPE datumType
= Token
.DATUM_TYPE
.UNKNOWN
;
1754 long tokenNumber
= 0;
1755 String moduleName
= null;
1756 String datum
= null;
1757 int maxDatumSize
= 0;
1758 String
[] tokenSpaceStrRet
= null;
1761 // ----------------------------------------------
1762 // 1), Get all <ModuleSA> from FPD file.
1763 // ----------------------------------------------
1765 modules
= getComponentsFromFPD();
1767 if (modules
== null) {
1768 throw new EntityException("[FPD file error] No modules in FPD file, Please check whether there are elements in <FrameworkModules> in FPD file!");
1772 // -------------------------------------------------------------------
1773 // 2), Loop all modules to process <PcdBuildDeclarations> for each module.
1774 // -------------------------------------------------------------------
1776 for (index
= 0; index
< modules
.size(); index
++) {
1777 isDuplicate
= false;
1778 for (index2
= 0; index2
< index
; index2
++) {
1780 // BUGBUG: For transition schema, we can *not* get module's version from
1781 // <ModuleSAs>, It is work around code.
1783 primaryKey1
= UsageInstance
.getPrimaryKey(modules
.get(index
).getModuleId().getModule().getName(),
1787 modules
.get(index
).getModuleId().getArch(),
1789 primaryKey2
= UsageInstance
.getPrimaryKey(modules
.get(index2
).getModuleId().getModule().getName(),
1793 modules
.get(index2
).getModuleId().getArch(),
1795 if (primaryKey1
.equalsIgnoreCase(primaryKey2
)) {
1806 // It is legal for a module does not contains ANY pcd build definitions.
1808 if (modules
.get(index
).getPcdBuildDef() == null) {
1812 pcdBuildDataArray
= modules
.get(index
).getPcdBuildDef().getPcdDataList();
1814 moduleName
= modules
.get(index
).getModuleId().getModule().getName();
1817 // ----------------------------------------------------------------------
1818 // 2.1), Loop all Pcd entry for a module and add it into memory database.
1819 // ----------------------------------------------------------------------
1821 for (pcdIndex
= 0; pcdIndex
< pcdBuildDataArray
.size(); pcdIndex
++) {
1822 pcdBuildData
= pcdBuildDataArray
.get(pcdIndex
);
1825 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(pcdBuildData
.getTokenSpaceGuidCName());
1826 } catch ( Exception e
) {
1827 throw new EntityException ("Faile get Guid for token " + pcdBuildData
.getCName() + ":" + e
.getMessage());
1830 if (tokenSpaceStrRet
== null) {
1831 throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData
.getCName());
1834 primaryKey
= Token
.getPrimaryKeyString(pcdBuildData
.getCName(),
1835 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
1836 pcdType
= Token
.getpcdTypeFromString(pcdBuildData
.getItemType().toString());
1837 datumType
= Token
.getdatumTypeFromString(pcdBuildData
.getDatumType().toString());
1838 tokenNumber
= Long
.decode(pcdBuildData
.getToken().toString());
1839 if (pcdBuildData
.getValue() != null) {
1840 datum
= pcdBuildData
.getValue().toString();
1844 maxDatumSize
= pcdBuildData
.getMaxDatumSize();
1846 if ((pcdType
== Token
.PCD_TYPE
.FEATURE_FLAG
) &&
1847 (datumType
!= Token
.DATUM_TYPE
.BOOLEAN
)){
1848 exceptionString
= String
.format("[FPD file error] For PCD %s in module %s, the PCD type is FEATRUE_FLAG but "+
1849 "datum type of this PCD entry is not BOOLEAN!",
1850 pcdBuildData
.getCName(),
1852 throw new EntityException(exceptionString
);
1856 // -------------------------------------------------------------------------------------------
1857 // 2.1.1), Do some necessary checking work for FixedAtBuild, FeatureFlag and PatchableInModule
1858 // -------------------------------------------------------------------------------------------
1860 if (!Token
.isDynamic(pcdType
)) {
1862 // Value is required.
1864 if (datum
== null) {
1865 exceptionString
= String
.format("[FPD file error] There is no value for PCD entry %s in module %s!",
1866 pcdBuildData
.getCName(),
1868 throw new EntityException(exceptionString
);
1872 // Check whether the datum size is matched datum type.
1874 if ((exceptionString
= verifyDatum(pcdBuildData
.getCName(),
1878 maxDatumSize
)) != null) {
1879 throw new EntityException(exceptionString
);
1884 // ---------------------------------------------------------------------------------
1885 // 2.1.2), Create token or update token information for current anaylized PCD data.
1886 // ---------------------------------------------------------------------------------
1888 if (dbManager
.isTokenInDatabase(primaryKey
)) {
1890 // If the token is already exist in database, do some necessary checking
1891 // and add a usage instance into this token in database
1893 token
= dbManager
.getTokenByKey(primaryKey
);
1896 // checking for DatumType, DatumType should be unique for one PCD used in different
1899 if (token
.datumType
!= datumType
) {
1900 exceptionString
= String
.format("[FPD file error] The datum type of PCD entry %s is %s, which is different with %s defined in before!",
1901 pcdBuildData
.getCName(),
1902 pcdBuildData
.getDatumType().toString(),
1903 Token
.getStringOfdatumType(token
.datumType
));
1904 throw new EntityException(exceptionString
);
1908 // Check token number is valid
1910 if (tokenNumber
!= token
.tokenNumber
) {
1911 exceptionString
= String
.format("[FPD file error] The token number of PCD entry %s in module %s is different with same PCD entry in other modules!",
1912 pcdBuildData
.getCName(),
1914 throw new EntityException(exceptionString
);
1918 // For same PCD used in different modules, the PCD type should all be dynamic or non-dynamic.
1920 if (token
.isDynamicPCD
!= Token
.isDynamic(pcdType
)) {
1921 exceptionString
= String
.format("[FPD file error] For PCD entry %s in module %s, you define dynamic or non-dynamic PCD type which"+
1922 "is different with others module's",
1925 throw new EntityException(exceptionString
);
1928 if (token
.isDynamicPCD
) {
1930 // Check datum is equal the datum in dynamic information.
1931 // For dynamic PCD, you can do not write <Value> in sperated every <PcdBuildDefinition> in different <ModuleSA>,
1932 // But if you write, the <Value> must be same as the value in <DynamicPcdBuildDefinitions>.
1934 if (!token
.isSkuEnable() &&
1935 (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.DEFAULT_TYPE
) &&
1937 if (!datum
.equalsIgnoreCase(token
.getDefaultSku().value
)) {
1938 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in module %s, the datum in <ModuleSA> is "+
1939 "not equal to the datum in <DynamicPcdBuildDefinitions>, it is "+
1940 "illega! You could no set <Value> in <ModuleSA> for a dynamic PCD!",
1943 throw new EntityException(exceptionString
);
1947 if ((maxDatumSize
!= 0) &&
1948 (maxDatumSize
!= token
.datumSize
)){
1949 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in module %s, the max datum size is %d which "+
1950 "is different with <MaxDatumSize> %d defined in <DynamicPcdBuildDefinitions>!",
1955 throw new EntityException(exceptionString
);
1961 // If the token is not in database, create a new token instance and add
1962 // a usage instance into this token in database.
1965 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(pcdBuildData
.getTokenSpaceGuidCName());
1966 } catch (Exception e
) {
1967 throw new EntityException("Fail to get token space guid for token " + token
.cName
);
1970 if (tokenSpaceStrRet
== null) {
1971 throw new EntityException("Fail to get token space guid for token " + token
.cName
);
1974 token
= new Token(pcdBuildData
.getCName(),
1975 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
1977 token
.datumType
= datumType
;
1978 token
.tokenNumber
= tokenNumber
;
1979 token
.isDynamicPCD
= Token
.isDynamic(pcdType
);
1980 token
.datumSize
= maxDatumSize
;
1982 if (token
.isDynamicPCD
) {
1984 // For Dynamic and Dynamic Ex type, need find the dynamic information
1985 // in <DynamicPcdBuildDefinition> section in FPD file.
1987 updateDynamicInformation(moduleName
,
1993 dbManager
.addTokenToDatabase(primaryKey
, token
);
1997 // -----------------------------------------------------------------------------------
1998 // 2.1.3), Add the PcdType in current module into this Pcd token's supported PCD type.
1999 // -----------------------------------------------------------------------------------
2001 token
.updateSupportPcdType(pcdType
);
2004 // ------------------------------------------------
2005 // 2.1.4), Create an usage instance for this token.
2006 // ------------------------------------------------
2008 usageInstance
= new UsageInstance(token
,
2013 CommonDefinition
.getModuleType(modules
.get(index
).getModuleType()),
2015 modules
.get(index
).getModuleId().getArch(),
2019 token
.addUsageInstance(usageInstance
);
2025 Verify the datum value according its datum size and datum type, this
2026 function maybe moved to FPD verification tools in future.
2037 public String
verifyDatum(String cName
,
2040 Token
.DATUM_TYPE datumType
,
2042 String exceptionString
= null;
2048 if (moduleName
== null) {
2049 moduleName
= "section <DynamicPcdBuildDefinitions>";
2051 moduleName
= "module " + moduleName
;
2054 if (maxDatumSize
== 0) {
2055 exceptionString
= String
.format("[FPD file error] You maybe miss <MaxDatumSize> for PCD %s in %s",
2058 return exceptionString
;
2061 switch (datumType
) {
2063 if (maxDatumSize
!= 1) {
2064 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2065 "is UINT8, but datum size is %d, they are not matched!",
2069 return exceptionString
;
2072 if (datum
!= null) {
2074 value
= Integer
.decode(datum
);
2075 } catch (NumberFormatException nfeExp
) {
2076 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid "+
2077 "digital format of UINT8",
2080 return exceptionString
;
2083 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s exceed"+
2084 " the max size of UINT8 - 0xFF",
2088 return exceptionString
;
2093 if (maxDatumSize
!= 2) {
2094 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2095 "is UINT16, but datum size is %d, they are not matched!",
2099 return exceptionString
;
2101 if (datum
!= null) {
2103 value
= Integer
.decode(datum
);
2104 } catch (NumberFormatException nfeExp
) {
2105 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is "+
2106 "not valid digital of UINT16",
2109 return exceptionString
;
2111 if (value
> 0xFFFF) {
2112 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
2113 "which exceed the range of UINT16 - 0xFFFF",
2117 return exceptionString
;
2122 if (maxDatumSize
!= 4) {
2123 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2124 "is UINT32, but datum size is %d, they are not matched!",
2128 return exceptionString
;
2131 if (datum
!= null) {
2133 if (datum
.length() > 2) {
2134 if ((datum
.charAt(0) == '0') &&
2135 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
2136 subStr
= datum
.substring(2, datum
.length());
2137 value64
= new BigInteger(subStr
, 16);
2139 value64
= new BigInteger(datum
);
2142 value64
= new BigInteger(datum
);
2144 } catch (NumberFormatException nfeExp
) {
2145 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not "+
2146 "valid digital of UINT32",
2149 return exceptionString
;
2152 if (value64
.bitLength() > 32) {
2153 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s which "+
2154 "exceed the range of UINT32 - 0xFFFFFFFF",
2158 return exceptionString
;
2163 if (maxDatumSize
!= 8) {
2164 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2165 "is UINT64, but datum size is %d, they are not matched!",
2169 return exceptionString
;
2172 if (datum
!= null) {
2174 if (datum
.length() > 2) {
2175 if ((datum
.charAt(0) == '0') &&
2176 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
2177 subStr
= datum
.substring(2, datum
.length());
2178 value64
= new BigInteger(subStr
, 16);
2180 value64
= new BigInteger(datum
);
2183 value64
= new BigInteger(datum
);
2185 } catch (NumberFormatException nfeExp
) {
2186 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid"+
2187 " digital of UINT64",
2190 return exceptionString
;
2193 if (value64
.bitLength() > 64) {
2194 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
2195 "exceed the range of UINT64 - 0xFFFFFFFFFFFFFFFF",
2199 return exceptionString
;
2204 if (maxDatumSize
!= 1) {
2205 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2206 "is BOOLEAN, but datum size is %d, they are not matched!",
2210 return exceptionString
;
2213 if (datum
!= null) {
2214 if (!(datum
.equalsIgnoreCase("TRUE") ||
2215 datum
.equalsIgnoreCase("FALSE"))) {
2216 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2217 "is BOOELAN, but value is not 'true'/'TRUE' or 'FALSE'/'false'",
2220 return exceptionString
;
2226 if (datum
== null) {
2230 char ch
= datum
.charAt(0);
2234 // For void* type PCD, only three datum is support:
2235 // 1) Unicode: string with start char is "L"
2236 // 2) Ansci: String start char is ""
2237 // 3) byte array: String start char "{"
2240 start
= datum
.indexOf('\"');
2241 end
= datum
.lastIndexOf('\"');
2242 if ((start
> end
) ||
2243 (end
> datum
.length())||
2244 ((start
== end
) && (datum
.length() > 0))) {
2245 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
2246 "a UNICODE string because start with L\", but format maybe"+
2247 "is not right, correct UNICODE string is L\"...\"!",
2250 return exceptionString
;
2253 strValue
= datum
.substring(start
+ 1, end
);
2254 if ((strValue
.length() * 2) > maxDatumSize
) {
2255 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
2256 "a UNICODE string, but the datum size is %d exceed to <MaxDatumSize> : %d",
2259 strValue
.length() * 2,
2261 return exceptionString
;
2263 } else if (ch
== '\"'){
2264 start
= datum
.indexOf('\"');
2265 end
= datum
.lastIndexOf('\"');
2266 if ((start
> end
) ||
2267 (end
> datum
.length())||
2268 ((start
== end
) && (datum
.length() > 0))) {
2269 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
2270 "a ANSCII string because start with \", but format maybe"+
2271 "is not right, correct ANSIC string is \"...\"!",
2274 return exceptionString
;
2276 strValue
= datum
.substring(start
+ 1, end
);
2277 if ((strValue
.length()) > maxDatumSize
) {
2278 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
2279 "a ANSCI string, but the datum size is %d which exceed to <MaxDatumSize> : %d",
2284 return exceptionString
;
2286 } else if (ch
=='{') {
2287 String
[] strValueArray
;
2289 start
= datum
.indexOf('{');
2290 end
= datum
.lastIndexOf('}');
2291 strValue
= datum
.substring(start
+ 1, end
);
2292 strValue
= strValue
.trim();
2293 if (strValue
.length() == 0) {
2296 strValueArray
= strValue
.split(",");
2297 for (index
= 0; index
< strValueArray
.length
; index
++) {
2299 value
= Integer
.decode(strValueArray
[index
].trim());
2300 } catch (NumberFormatException nfeEx
) {
2301 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
2302 "it is byte array in fact. For every byte in array should be a valid"+
2303 "byte digital, but element %s is not a valid byte digital!",
2306 strValueArray
[index
]);
2307 return exceptionString
;
2310 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, "+
2311 "it is byte array in fact. But the element of %s exceed the byte range",
2314 strValueArray
[index
]);
2315 return exceptionString
;
2319 if (strValueArray
.length
> maxDatumSize
) {
2320 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is byte"+
2321 "array, but the number of bytes is %d which exceed to <MaxDatumSzie> : %d!",
2324 strValueArray
.length
,
2326 return exceptionString
;
2329 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*. For VOID* type, you have three format choise:\n "+
2330 "1) UNICODE string: like L\"xxxx\";\r\n"+
2331 "2) ANSIC string: like \"xxx\";\r\n"+
2332 "3) Byte array: like {0x2, 0x45, 0x23}\r\n"+
2333 "But the datum in seems does not following above format!",
2336 return exceptionString
;
2340 exceptionString
= String
.format("[FPD file error] For PCD entry %s in %s, datum type is unknown, it should be one of "+
2341 "UINT8, UINT16, UINT32, UINT64, VOID*, BOOLEAN",
2344 return exceptionString
;
2350 Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.
2352 This function should be implemented in GlobalData in future.
2354 @param token The token instance which has hold module's PCD information
2355 @param moduleName The name of module who will use this Dynamic PCD.
2357 @return DynamicPcdBuildDefinitions.PcdBuildData
2360 private DynamicPcdBuildDefinitions
.PcdBuildData
getDynamicInfoFromFPD(Token token
,
2362 throws EntityException
{
2364 String exceptionString
= null;
2365 String dynamicPrimaryKey
= null;
2366 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
2367 List
<DynamicPcdBuildDefinitions
.PcdBuildData
> dynamicPcdBuildDataArray
= null;
2368 String
[] tokenSpaceStrRet
= null;
2371 // If FPD document is not be opened, open and initialize it.
2373 if (fpdDocInstance
== null) {
2375 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
2376 } catch(IOException ioE
) {
2377 throw new EntityException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
2378 } catch(XmlException xmlE
) {
2379 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
2383 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
2384 if (dynamicPcdBuildDefinitions
== null) {
2385 exceptionString
= String
.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+
2386 "PCD entry %s in module %s!",
2389 throw new EntityException(exceptionString
);
2392 dynamicPcdBuildDataArray
= dynamicPcdBuildDefinitions
.getPcdBuildDataList();
2393 for (index
= 0; index
< dynamicPcdBuildDataArray
.size(); index
++) {
2394 //String tokenSpaceGuidString = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName())[1];
2395 String tokenSpaceGuidString
= null;
2397 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(dynamicPcdBuildDataArray
.get(index
).getTokenSpaceGuidCName());
2398 } catch (Exception e
) {
2399 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName());
2402 if (tokenSpaceStrRet
== null) {
2403 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName());
2406 dynamicPrimaryKey
= Token
.getPrimaryKeyString(dynamicPcdBuildDataArray
.get(index
).getCName(),
2407 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
2408 if (dynamicPrimaryKey
.equalsIgnoreCase(token
.getPrimaryKeyString())) {
2409 return dynamicPcdBuildDataArray
.get(index
);
2417 Update dynamic information for PCD entry.
2419 Dynamic information is retrieved from <PcdDynamicBuildDeclarations> in
2422 @param moduleName The name of the module who use this PCD
2423 @param token The token instance
2424 @param datum The <datum> in module's PCD information
2425 @param maxDatumSize The <maxDatumSize> in module's PCD information
2429 private Token
updateDynamicInformation(String moduleName
,
2433 throws EntityException
{
2436 String exceptionString
= null;
2437 DynamicTokenValue dynamicValue
;
2438 SkuInstance skuInstance
= null;
2440 boolean hasSkuId0
= false;
2441 Token
.PCD_TYPE pcdType
= Token
.PCD_TYPE
.UNKNOWN
;
2442 long tokenNumber
= 0;
2443 String hiiDefaultValue
= null;
2444 String
[] variableGuidString
= null;
2446 List
<DynamicPcdBuildDefinitions
.PcdBuildData
.SkuInfo
> skuInfoList
= null;
2447 DynamicPcdBuildDefinitions
.PcdBuildData dynamicInfo
= null;
2449 dynamicInfo
= getDynamicInfoFromFPD(token
, moduleName
);
2450 if (dynamicInfo
== null) {
2451 exceptionString
= String
.format("[FPD file error] For Dynamic PCD %s used by module %s, "+
2452 "there is no dynamic information in <DynamicPcdBuildDefinitions> "+
2453 "in FPD file, but it is required!",
2456 throw new EntityException(exceptionString
);
2459 token
.datumSize
= dynamicInfo
.getMaxDatumSize();
2461 exceptionString
= verifyDatum(token
.cName
,
2466 if (exceptionString
!= null) {
2467 throw new EntityException(exceptionString
);
2470 if ((maxDatumSize
!= 0) &&
2471 (maxDatumSize
!= token
.datumSize
)) {
2472 exceptionString
= String
.format("FPD file error] For dynamic PCD %s, the datum size in module %s is %d, but "+
2473 "the datum size in <DynamicPcdBuildDefinitions> is %d, they are not match!",
2477 dynamicInfo
.getMaxDatumSize());
2478 throw new EntityException(exceptionString
);
2480 tokenNumber
= Long
.decode(dynamicInfo
.getToken().toString());
2481 if (tokenNumber
!= token
.tokenNumber
) {
2482 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s, the token number in module %s is 0x%x, but"+
2483 "in <DynamicPcdBuildDefinictions>, the token number is 0x%x, they are not match!",
2488 throw new EntityException(exceptionString
);
2491 pcdType
= Token
.getpcdTypeFromString(dynamicInfo
.getItemType().toString());
2492 if (pcdType
== Token
.PCD_TYPE
.DYNAMIC_EX
) {
2493 token
.dynamicExTokenNumber
= tokenNumber
;
2496 skuInfoList
= dynamicInfo
.getSkuInfoList();
2499 // Loop all sku data
2501 for (index
= 0; index
< skuInfoList
.size(); index
++) {
2502 skuInstance
= new SkuInstance();
2504 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.
2506 temp
= skuInfoList
.get(index
).getSkuId().toString();
2507 skuInstance
.id
= Integer
.decode(temp
);
2508 if (skuInstance
.id
== 0) {
2512 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.
2514 if (skuInfoList
.get(index
).getValue() != null) {
2515 skuInstance
.value
.setValue(skuInfoList
.get(index
).getValue().toString());
2516 if ((exceptionString
= verifyDatum(token
.cName
,
2518 skuInfoList
.get(index
).getValue().toString(),
2520 token
.datumSize
)) != null) {
2521 throw new EntityException(exceptionString
);
2524 token
.skuData
.add(skuInstance
);
2527 // Judege wether is same of datum between module's information
2528 // and dynamic information.
2530 if (datum
!= null) {
2531 if ((skuInstance
.id
== 0) &&
2532 !datum
.toString().equalsIgnoreCase(skuInfoList
.get(index
).getValue().toString())) {
2533 exceptionString
= "[FPD file error] For dynamic PCD " + token
.cName
+ ", the value in module " + moduleName
+ " is " + datum
.toString() + " but the "+
2534 "value of sku 0 data in <DynamicPcdBuildDefinition> is " + skuInstance
.value
.value
+ ". They are must be same!"+
2535 " or you could not define value for a dynamic PCD in every <ModuleSA>!";
2536 throw new EntityException(exceptionString
);
2543 // Judge whether is HII group case.
2545 if (skuInfoList
.get(index
).getVariableName() != null) {
2546 exceptionString
= null;
2547 if (skuInfoList
.get(index
).getVariableGuid() == null) {
2548 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2549 "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",
2552 if (exceptionString
!= null) {
2553 throw new EntityException(exceptionString
);
2557 if (skuInfoList
.get(index
).getVariableOffset() == null) {
2558 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2559 "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",
2562 if (exceptionString
!= null) {
2563 throw new EntityException(exceptionString
);
2567 if (skuInfoList
.get(index
).getHiiDefaultValue() == null) {
2568 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2569 "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",
2572 if (exceptionString
!= null) {
2573 throw new EntityException(exceptionString
);
2577 if (skuInfoList
.get(index
).getHiiDefaultValue() != null) {
2578 hiiDefaultValue
= skuInfoList
.get(index
).getHiiDefaultValue().toString();
2580 hiiDefaultValue
= null;
2583 if ((exceptionString
= verifyDatum(token
.cName
,
2587 token
.datumSize
)) != null) {
2588 throw new EntityException(exceptionString
);
2591 offset
= Integer
.decode(skuInfoList
.get(index
).getVariableOffset());
2592 if (offset
> 0xFFFF) {
2593 throw new EntityException(String
.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+
2594 "exceed 64K, it is not allowed!",
2600 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.
2602 variableGuidString
= GlobalData
.getGuidInfoFromCname(skuInfoList
.get(index
).getVariableGuid().toString());
2603 if (variableGuidString
== null) {
2604 throw new EntityException(String
.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",
2606 skuInfoList
.get(index
).getVariableGuid().toString()));
2608 String variableStr
= skuInfoList
.get(index
).getVariableName();
2609 Pattern pattern
= Pattern
.compile("0x([a-fA-F0-9]){4}");
2610 Matcher matcher
= pattern
.matcher(variableStr
);
2611 List
<String
> varNameList
= new ArrayList
<String
>();
2612 while (matcher
.find()){
2613 String str
= variableStr
.substring(matcher
.start(),matcher
.end());
2614 varNameList
.add(str
);
2617 skuInstance
.value
.setHiiData(varNameList
,
2618 translateSchemaStringToUUID(variableGuidString
[1]),
2619 skuInfoList
.get(index
).getVariableOffset(),
2620 skuInfoList
.get(index
).getHiiDefaultValue().toString());
2621 token
.skuData
.add(skuInstance
);
2625 if (skuInfoList
.get(index
).getVpdOffset() != null) {
2626 skuInstance
.value
.setVpdData(skuInfoList
.get(index
).getVpdOffset());
2627 token
.skuData
.add(skuInstance
);
2631 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+
2632 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",
2634 throw new EntityException(exceptionString
);
2638 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+
2639 "no sku id = 0 data, which is required for every dynamic PCD",
2641 throw new EntityException(exceptionString
);
2648 Translate the schema string to UUID instance.
2650 In schema, the string of UUID is defined as following two types string:
2651 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(
2652 )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?
2654 2) GuidNamingConvention: pattern =
2655 [a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}
2657 This function will convert string and create uuid instance.
2659 @param uuidString UUID string in XML file
2661 @return UUID UUID instance
2663 private UUID
translateSchemaStringToUUID(String uuidString
)
2664 throws EntityException
{
2666 String
[] splitStringArray
;
2671 if (uuidString
== null) {
2675 if (uuidString
.length() == 0) {
2679 if (uuidString
.equals("0") ||
2680 uuidString
.equalsIgnoreCase("0x0")) {
2681 return new UUID(0, 0);
2684 uuidString
= uuidString
.replaceAll("\\{", "");
2685 uuidString
= uuidString
.replaceAll("\\}", "");
2688 // If the UUID schema string is GuidArrayType type then need translate
2689 // to GuidNamingConvention type at first.
2691 if ((uuidString
.charAt(0) == '0') && ((uuidString
.charAt(1) == 'x') || (uuidString
.charAt(1) == 'X'))) {
2692 splitStringArray
= uuidString
.split("," );
2693 if (splitStringArray
.length
!= 11) {
2694 throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString
);
2698 // Remove blank space from these string and remove header string "0x"
2700 for (index
= 0; index
< 11; index
++) {
2701 splitStringArray
[index
] = splitStringArray
[index
].trim();
2702 splitStringArray
[index
] = splitStringArray
[index
].substring(2, splitStringArray
[index
].length());
2706 // Add heading '0' to normalize the string length
2708 for (index
= 3; index
< 11; index
++) {
2709 chLen
= splitStringArray
[index
].length();
2710 for (chIndex
= 0; chIndex
< 2 - chLen
; chIndex
++) {
2711 splitStringArray
[index
] = "0" + splitStringArray
[index
];
2716 // construct the final GuidNamingConvention string
2718 temp
= String
.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",
2719 splitStringArray
[0],
2720 splitStringArray
[1],
2721 splitStringArray
[2],
2722 splitStringArray
[3],
2723 splitStringArray
[4],
2724 splitStringArray
[5],
2725 splitStringArray
[6],
2726 splitStringArray
[7],
2727 splitStringArray
[8],
2728 splitStringArray
[9],
2729 splitStringArray
[10]);
2733 return UUID
.fromString(uuidString
);
2737 check parameter for this action.
2739 @throws EntityException Bad parameter.
2741 private void checkParameter() throws EntityException
{
2744 if((fpdFilePath
== null) ||(workspacePath
== null)) {
2745 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
2748 if(fpdFilePath
.length() == 0 || workspacePath
.length() == 0) {
2749 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
2752 file
= new File(workspacePath
);
2753 if(!file
.exists()) {
2754 throw new EntityException("WorkpacePath " + workspacePath
+ " does not exist!");
2757 file
= new File(fpdFilePath
);
2759 if(!file
.exists()) {
2760 throw new EntityException("FPD File " + fpdFilePath
+ " does not exist!");
2767 @param argv parameter from command line
2769 public static void main(String argv
[]) throws EntityException
{
2770 CollectPCDAction ca
= new CollectPCDAction();
2771 ca
.setWorkspacePath("m:/tianocore/edk2");
2772 ca
.setFPDFilePath("m:/tianocore/edk2/EdkNt32Pkg/Nt32.fpd");
2773 ca
.setActionMessageLevel(ActionMessage
.MAX_MESSAGE_LEVEL
);
2774 // GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db",
2775 // "m:/tianocore/edk2");