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
.ModuleSADocument
;
41 import org
.tianocore
.PcdBuildDefinitionDocument
;
42 import org
.tianocore
.PcdBuildDefinitionDocument
.PcdBuildDefinition
;
43 import org
.tianocore
.PlatformSurfaceAreaDocument
;
44 import org
.tianocore
.build
.autogen
.CommonDefinition
;
45 import org
.tianocore
.build
.fpd
.FpdParserTask
;
46 import org
.tianocore
.build
.global
.GlobalData
;
47 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
48 import org
.tianocore
.build
.pcd
.action
.ActionMessage
;
49 import org
.tianocore
.build
.pcd
.entity
.DynamicTokenValue
;
50 import org
.tianocore
.build
.pcd
.entity
.MemoryDatabaseManager
;
51 import org
.tianocore
.build
.pcd
.entity
.SkuInstance
;
52 import org
.tianocore
.build
.pcd
.entity
.Token
;
53 import org
.tianocore
.build
.pcd
.entity
.UsageInstance
;
54 import org
.tianocore
.build
.pcd
.exception
.EntityException
;
57 CStructTypeDeclaration
59 This class is used to store the declaration string, such as
60 "UINT32 PcdPlatformFlashBaseAddress", of
61 each memember in the C structure, which is a standard C language
62 feature used to implement a simple and efficient database for
63 dynamic(ex) type PCD entry.
66 class CStructTypeDeclaration
{
72 public CStructTypeDeclaration (String key
, int alignmentSize
, String cCode
, boolean initTable
) {
74 this.alignmentSize
= alignmentSize
;
76 this.initTable
= initTable
;
83 This class is used to store the String in a PCD database.
87 private ArrayList
<String
> al
;
88 private ArrayList
<String
> alComments
;
92 public StringTable (String phase
) {
94 al
= new ArrayList
<String
>();
95 alComments
= new ArrayList
<String
>();
99 public String
getSizeMacro () {
100 return String
.format(PcdDatabase
.StringTableSizeMacro
, phase
, getSize());
103 private int getSize () {
105 // We have at least one Unicode Character in the table.
107 return len
== 0 ?
1 : len
;
110 public String
getExistanceMacro () {
111 return String
.format(PcdDatabase
.StringTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
114 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
) {
115 final String stringTable
= "StringTable";
116 final String tab
= "\t";
117 final String newLine
= "\r\n";
118 final String commaNewLine
= ",\r\n";
120 CStructTypeDeclaration decl
;
122 String cDeclCode
= "";
123 String cInstCode
= "";
126 // If we have a empty StringTable
128 if (al
.size() == 0) {
129 cDeclCode
+= String
.format("%-20s%s[1]; /* StringTable is empty */", "UINT16", stringTable
) + newLine
;
130 decl
= new CStructTypeDeclaration (
138 cInstCode
= String
.format("/* %s */", stringTable
) + newLine
+ tab
+ "{ 0 }";
139 instTable
.put(stringTable
, cInstCode
);
143 // If there is any String in the StringTable
145 for (int i
= 0; i
< al
.size(); i
++) {
146 String str
= al
.get(i
);
147 String stringTableName
;
151 // StringTable is a well-known name in the PCD DXE driver
153 stringTableName
= stringTable
;
156 stringTableName
= String
.format("%s_%d", stringTable
, i
);
159 cDeclCode
+= String
.format("%-20s%s[%d]; /* %s */", "UINT16",
160 stringTableName
, str
.length() + 1,
165 cInstCode
= "/* StringTable */" + newLine
;
168 cInstCode
+= tab
+ String
.format("L\"%s\" /* %s */", al
.get(i
), alComments
.get(i
));
169 if (i
!= al
.size() - 1) {
170 cInstCode
+= commaNewLine
;
174 decl
= new CStructTypeDeclaration (
182 instTable
.put(stringTable
, cInstCode
);
186 public int add (String inputStr
, Token token
) {
190 String str
= inputStr
;
193 // The input can be two types:
194 // "L\"Bootmode\"" or "Bootmode".
195 // We drop the L\" and \" for the first type.
196 if (str
.startsWith("L\"") && str
.endsWith("\"")) {
197 str
= str
.substring(2, str
.length() - 1);
200 // Check if StringTable has this String already.
201 // If so, return the current pos.
203 for (i
= 0, pos
= 0; i
< al
.size(); i
++) {
204 String s
= al
.get(i
);;
209 pos
= s
.length() + 1;
214 // Include the NULL character at the end of String
216 len
+= str
.length() + 1;
218 alComments
.add(token
.getPrimaryKeyString());
227 This class is used to store the Size information for
228 POINTER TYPE PCD entry in a PCD database.
232 private ArrayList
<ArrayList
<Integer
>> al
;
233 private ArrayList
<String
> alComments
;
235 private String phase
;
237 public SizeTable (String phase
) {
238 al
= new ArrayList
<ArrayList
<Integer
>>();
239 alComments
= new ArrayList
<String
>();
244 public String
getSizeMacro () {
245 return String
.format(PcdDatabase
.SizeTableSizeMacro
, phase
, getSize());
248 private int getSize() {
249 return len
== 0 ?
1 : len
;
252 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
253 final String name
= "SizeTable";
255 CStructTypeDeclaration decl
;
258 cCode
= String
.format(PcdDatabase
.SizeTableDeclaration
, phase
);
259 decl
= new CStructTypeDeclaration (
268 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
269 instTable
.put(name
, cCode
);
272 private ArrayList
<String
> getInstantiation () {
273 final String comma
= ",";
274 ArrayList
<String
> Output
= new ArrayList
<String
>();
276 Output
.add("/* SizeTable */");
278 if (al
.size() == 0) {
281 for (int index
= 0; index
< al
.size(); index
++) {
282 ArrayList
<Integer
> ial
= al
.get(index
);
286 for (int index2
= 0; index2
< ial
.size(); index2
++) {
287 str
+= " " + ial
.get(index2
).toString();
288 if (index2
!= ial
.size() - 1) {
293 str
+= " /* " + alComments
.get(index
) + " */";
295 if (index
!= (al
.size() - 1)) {
308 public void add (Token token
) {
311 // We only have size information for POINTER type PCD entry.
313 if (token
.datumType
!= Token
.DATUM_TYPE
.POINTER
) {
317 ArrayList
<Integer
> ial
= token
.getPointerTypeSize();
322 alComments
.add(token
.getPrimaryKeyString());
332 This class is used to store the GUIDs in a PCD database.
335 private ArrayList
<UUID
> al
;
336 private ArrayList
<String
> alComments
;
337 private String phase
;
339 private int bodyLineNum
;
341 public GuidTable (String phase
) {
343 al
= new ArrayList
<UUID
>();
344 alComments
= new ArrayList
<String
>();
349 public String
getSizeMacro () {
350 return String
.format(PcdDatabase
.GuidTableSizeMacro
, phase
, getSize());
353 private int getSize () {
354 return (al
.size() == 0)?
1 : al
.size();
357 public String
getExistanceMacro () {
358 return String
.format(PcdDatabase
.GuidTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
361 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
362 final String name
= "GuidTable";
364 CStructTypeDeclaration decl
;
367 cCode
+= String
.format(PcdDatabase
.GuidTableDeclaration
, phase
);
368 decl
= new CStructTypeDeclaration (
377 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
378 instTable
.put(name
, cCode
);
381 private String
getUuidCString (UUID uuid
) {
382 String
[] guidStrArray
;
384 guidStrArray
=(uuid
.toString()).split("-");
386 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}}",
390 (guidStrArray
[3].substring(0, 2)),
391 (guidStrArray
[3].substring(2, 4)),
392 (guidStrArray
[4].substring(0, 2)),
393 (guidStrArray
[4].substring(2, 4)),
394 (guidStrArray
[4].substring(4, 6)),
395 (guidStrArray
[4].substring(6, 8)),
396 (guidStrArray
[4].substring(8, 10)),
397 (guidStrArray
[4].substring(10, 12))
401 private ArrayList
<String
> getInstantiation () {
402 ArrayList
<String
> Output
= new ArrayList
<String
>();
404 Output
.add("/* GuidTable */");
407 if (al
.size() == 0) {
408 Output
.add("\t" + getUuidCString(new UUID(0, 0)));
411 for (int i
= 0; i
< al
.size(); i
++) {
412 String str
= "\t" + getUuidCString(al
.get(i
));
414 str
+= "/* " + alComments
.get(i
) + " */";
415 if (i
!= (al
.size() - 1)) {
427 public int add (UUID uuid
, String name
) {
429 // Check if GuidTable has this entry already.
430 // If so, return the GuidTable index.
432 for (int i
= 0; i
< al
.size(); i
++) {
433 if (al
.get(i
).equals(uuid
)) {
440 alComments
.add(name
);
443 // Return the previous Table Index
453 This class is used to store the SKU IDs in a PCD database.
457 private ArrayList
<Integer
[]> al
;
458 private ArrayList
<String
> alComment
;
459 private String phase
;
462 public SkuIdTable (String phase
) {
464 al
= new ArrayList
<Integer
[]>();
465 alComment
= new ArrayList
<String
>();
469 public String
getSizeMacro () {
470 return String
.format(PcdDatabase
.SkuIdTableSizeMacro
, phase
, getSize());
473 private int getSize () {
474 return (len
== 0)?
1 : len
;
477 public String
getExistanceMacro () {
478 return String
.format(PcdDatabase
.SkuTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
481 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
482 final String name
= "SkuIdTable";
484 CStructTypeDeclaration decl
;
487 cCode
+= String
.format(PcdDatabase
.SkuIdTableDeclaration
, phase
);
488 decl
= new CStructTypeDeclaration (
497 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
498 instTable
.put(name
, cCode
);
501 // SystemSkuId is in PEI phase PCD Database
503 if (phase
.equalsIgnoreCase("PEI")) {
504 decl
= new CStructTypeDeclaration (
507 String
.format("%-20sSystemSkuId;\r\n", "SKU_ID"),
512 instTable
.put("SystemSkuId", "0");
517 private ArrayList
<String
> getInstantiation () {
518 ArrayList
<String
> Output
= new ArrayList
<String
> ();
520 Output
.add("/* SkuIdTable */");
523 if (al
.size() == 0) {
527 for (int index
= 0; index
< al
.size(); index
++) {
530 str
= "/* " + alComment
.get(index
) + "*/ ";
531 str
+= "/* MaxSku */ ";
534 Integer
[] ia
= al
.get(index
);
536 str
+= "\t" + ia
[0].toString() + ", ";
537 for (int index2
= 1; index2
< ia
.length
; index2
++) {
538 str
+= ia
[index2
].toString();
539 if (!((index2
== ia
.length
- 1) && (index
== al
.size() - 1))) {
553 public int add (Token token
) {
559 // Check if this SKU_ID Array is already in the table
563 Integer
[] s
= (Integer
[]) o
;
564 boolean different
= false;
565 if (s
[0] == token
.getSkuIdCount()) {
566 for (index
= 1; index
< s
.length
; index
++) {
567 if (s
[index
] != token
.skuData
.get(index
-1).id
) {
582 Integer
[] skuIds
= new Integer
[token
.skuData
.size() + 1];
583 skuIds
[0] = new Integer(token
.skuData
.size());
584 for (index
= 1; index
< skuIds
.length
; index
++) {
585 skuIds
[index
] = new Integer(token
.skuData
.get(index
- 1).id
);
590 len
+= skuIds
.length
;
592 alComment
.add(token
.getPrimaryKeyString());
599 class LocalTokenNumberTable
{
600 private ArrayList
<String
> al
;
601 private ArrayList
<String
> alComment
;
602 private String phase
;
605 public LocalTokenNumberTable (String phase
) {
607 al
= new ArrayList
<String
>();
608 alComment
= new ArrayList
<String
>();
613 public String
getSizeMacro () {
614 return String
.format(PcdDatabase
.LocalTokenNumberTableSizeMacro
, phase
, getSize())
615 + String
.format(PcdDatabase
.LocalTokenNumberSizeMacro
, phase
, al
.size());
618 public int getSize () {
619 return (al
.size() == 0)?
1 : al
.size();
622 public String
getExistanceMacro () {
623 return String
.format(PcdDatabase
.DatabaseExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
626 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
627 final String name
= "LocalTokenNumberTable";
629 CStructTypeDeclaration decl
;
632 cCode
+= String
.format(PcdDatabase
.LocalTokenNumberTableDeclaration
, phase
);
633 decl
= new CStructTypeDeclaration (
641 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
642 instTable
.put(name
, cCode
);
645 private ArrayList
<String
> getInstantiation () {
646 ArrayList
<String
> output
= new ArrayList
<String
>();
648 output
.add("/* LocalTokenNumberTable */");
651 if (al
.size() == 0) {
655 for (int index
= 0; index
< al
.size(); index
++) {
658 str
= "\t" + (String
)al
.get(index
);
660 str
+= " /* " + alComment
.get(index
) + " */ ";
663 if (index
!= (al
.size() - 1)) {
676 public int add (Token token
) {
682 str
= String
.format(PcdDatabase
.offsetOfStrTemplate
, phase
, token
.hasDefaultValue() ?
"Init" : "Uninit", token
.getPrimaryKeyString());
684 if (token
.isUnicodeStringType()) {
685 str
+= " | PCD_TYPE_STRING";
688 if (token
.isSkuEnable()) {
689 str
+= " | PCD_TYPE_SKU_ENABLED";
692 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
693 str
+= " | PCD_TYPE_HII";
696 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
697 str
+= " | PCD_TYPE_VPD";
700 switch (token
.datumType
) {
703 str
+= " | PCD_DATUM_TYPE_UINT8";
706 str
+= " | PCD_DATUM_TYPE_UINT16";
709 str
+= " | PCD_DATUM_TYPE_UINT32";
712 str
+= " | PCD_DATUM_TYPE_UINT64";
715 str
+= " | PCD_DATUM_TYPE_POINTER";
720 alComment
.add(token
.getPrimaryKeyString());
729 This class is used to store the table of mapping information
730 between DynamicEX ID pair(Guid, TokenNumber) and
731 the local token number assigned by PcdDatabase class.
738 This class is used to store the mapping information
739 between DynamicEX ID pair(Guid, TokenNumber) and
740 the local token number assigned by PcdDatabase class.
743 public Integer guidTableIdx
;
744 public Long exTokenNumber
;
745 public Long localTokenIdx
;
747 public ExTriplet (int guidTableIdx
, long exTokenNumber
, long localTokenIdx
) {
748 this.guidTableIdx
= new Integer(guidTableIdx
);
749 this.exTokenNumber
= new Long(exTokenNumber
);
750 this.localTokenIdx
= new Long(localTokenIdx
);
754 private ArrayList
<ExTriplet
> al
;
755 private ArrayList
<String
> alComment
;
756 private String phase
;
758 private int bodyLineNum
;
760 public ExMapTable (String phase
) {
762 al
= new ArrayList
<ExTriplet
>();
763 alComment
= new ArrayList
<String
>();
768 public String
getSizeMacro () {
769 return String
.format(PcdDatabase
.ExMapTableSizeMacro
, phase
, getTableLen())
770 + String
.format(PcdDatabase
.ExTokenNumber
, phase
, al
.size());
773 public String
getExistanceMacro () {
774 return String
.format(PcdDatabase
.ExMapTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
777 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
778 final String exMapTableName
= "ExMapTable";
782 CStructTypeDeclaration decl
;
785 cCode
+= String
.format(PcdDatabase
.ExMapTableDeclaration
, phase
);
786 decl
= new CStructTypeDeclaration (
795 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
796 instTable
.put(exMapTableName
, cCode
);
799 private ArrayList
<String
> getInstantiation () {
800 ArrayList
<String
> Output
= new ArrayList
<String
>();
802 Output
.add("/* ExMapTable */");
804 if (al
.size() == 0) {
805 Output
.add("\t{0, 0, 0}");
809 for (index
= 0; index
< al
.size(); index
++) {
812 ExTriplet e
= (ExTriplet
)al
.get(index
);
814 str
= "\t" + "{ " + String
.format("0x%08X", e
.exTokenNumber
) + ", ";
815 str
+= e
.localTokenIdx
.toString() + ", ";
816 str
+= e
.guidTableIdx
.toString();
818 str
+= "}" + " /* " + alComment
.get(index
) + " */" ;
820 if (index
!= al
.size() - 1) {
834 public int add (int localTokenIdx
, long exTokenNum
, int guidTableIdx
, String name
) {
838 al
.add(new ExTriplet(guidTableIdx
, exTokenNum
, localTokenIdx
));
844 private int getTableLen () {
845 return al
.size() == 0 ?
1 : al
.size();
849 // To simplify the algorithm for GetNextToken and GetNextTokenSpace in
850 // PCD PEIM/Driver, we need to sort the ExMapTable according to the
855 class ExTripletComp
implements Comparator
<ExTriplet
> {
856 public int compare (ExTriplet a
, ExTriplet b
) {
857 if (a
.guidTableIdx
== b
.guidTableIdx
) {
859 // exTokenNumber is long, we can't use simple substraction.
861 if (a
.exTokenNumber
> b
.exTokenNumber
) {
863 } else if (a
.exTokenNumber
== b
.exTokenNumber
) {
870 return a
.guidTableIdx
- b
.guidTableIdx
;
874 private void sortTable () {
875 java
.util
.Comparator
<ExTriplet
> comparator
= new ExTripletComp();
876 java
.util
.Collections
.sort(al
, comparator
);
883 This class is used to generate C code for Autogen.h and Autogen.c of
884 a PCD service DXE driver and PCD service PEIM.
888 private final static int SkuHeadAlignmentSize
= 4;
889 private final String newLine
= "\r\n";
890 private final String commaNewLine
= ",\r\n";
891 private final String tab
= "\t";
892 public final static String ExMapTableDeclaration
= "DYNAMICEX_MAPPING ExMapTable[%s_EXMAPPING_TABLE_SIZE];\r\n";
893 public final static String GuidTableDeclaration
= "EFI_GUID GuidTable[%s_GUID_TABLE_SIZE];\r\n";
894 public final static String LocalTokenNumberTableDeclaration
= "UINT32 LocalTokenNumberTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";
895 public final static String StringTableDeclaration
= "UINT16 StringTable[%s_STRING_TABLE_SIZE];\r\n";
896 public final static String SizeTableDeclaration
= "SIZE_INFO SizeTable[%s_SIZE_TABLE_SIZE];\r\n";
897 public final static String SkuIdTableDeclaration
= "UINT8 SkuIdTable[%s_SKUID_TABLE_SIZE];\r\n";
900 public final static String ExMapTableSizeMacro
= "#define %s_EXMAPPING_TABLE_SIZE %d\r\n";
901 public final static String ExTokenNumber
= "#define %s_EX_TOKEN_NUMBER %d\r\n";
902 public final static String GuidTableSizeMacro
= "#define %s_GUID_TABLE_SIZE %d\r\n";
903 public final static String LocalTokenNumberTableSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER_TABLE_SIZE %d\r\n";
904 public final static String LocalTokenNumberSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER %d\r\n";
905 public final static String SizeTableSizeMacro
= "#define %s_SIZE_TABLE_SIZE %d\r\n";
906 public final static String StringTableSizeMacro
= "#define %s_STRING_TABLE_SIZE %d\r\n";
907 public final static String SkuIdTableSizeMacro
= "#define %s_SKUID_TABLE_SIZE %d\r\n";
910 public final static String ExMapTableExistenceMacro
= "#define %s_EXMAP_TABLE_EMPTY %s\r\n";
911 public final static String GuidTableExistenceMacro
= "#define %s_GUID_TABLE_EMPTY %s\r\n";
912 public final static String DatabaseExistenceMacro
= "#define %s_DATABASE_EMPTY %s\r\n";
913 public final static String StringTableExistenceMacro
= "#define %s_STRING_TABLE_EMPTY %s\r\n";
914 public final static String SkuTableExistenceMacro
= "#define %s_SKUID_TABLE_EMPTY %s\r\n";
916 public final static String offsetOfSkuHeadStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)";
917 public final static String offsetOfVariableEnabledDefault
= "offsetof(%s_PCD_DATABASE, %s.%s_VariableDefault_%d)";
918 public final static String offsetOfStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s)";
920 private final static String skuDataTableTemplate
= "SkuDataTable";
923 private StringTable stringTable
;
924 private GuidTable guidTable
;
925 private LocalTokenNumberTable localTokenNumberTable
;
926 private SkuIdTable skuIdTable
;
927 private SizeTable sizeTable
;
928 private ExMapTable exMapTable
;
930 private ArrayList
<Token
> alTokens
;
931 private String phase
;
932 private int assignedTokenNumber
;
935 // Use two class global variable to store
938 private String privateGlobalName
;
939 private String privateGlobalCCode
;
941 // After Major changes done to the PCD
942 // database generation class PcdDatabase
943 // Please increment the version and please
944 // also update the version number in PCD
945 // service PEIM and DXE driver accordingly.
947 private final int version
= 2;
949 private String hString
;
950 private String cString
;
953 Constructor for PcdDatabase class.
955 <p>We have two PCD dynamic(ex) database for the Framework implementation. One
956 for PEI phase and the other for DXE phase. </p>
958 @param alTokens A ArrayList of Dynamic(EX) PCD entry.
959 @param exePhase The phase to generate PCD database for: valid input
961 @param startLen The starting Local Token Number for the PCD database. For
962 PEI phase, the starting Local Token Number starts from 0.
963 For DXE phase, the starting Local Token Number starts
964 from the total number of PCD entry of PEI phase.
967 public PcdDatabase (ArrayList
<Token
> alTokens
, String exePhase
, int startLen
) {
970 stringTable
= new StringTable(phase
);
971 guidTable
= new GuidTable(phase
);
972 localTokenNumberTable
= new LocalTokenNumberTable(phase
);
973 skuIdTable
= new SkuIdTable(phase
);
974 sizeTable
= new SizeTable(phase
);
975 exMapTable
= new ExMapTable(phase
);
978 // Local token number 0 is reserved for INVALID_TOKEN_NUMBER.
979 // So we will increment 1 for the startLen passed from the
982 assignedTokenNumber
= startLen
+ 1;
983 this.alTokens
= alTokens
;
986 private void getNonExAndExTokens (ArrayList
<Token
> alTokens
, List
<Token
> nexTokens
, List
<Token
> exTokens
) {
987 for (int i
= 0; i
< alTokens
.size(); i
++) {
988 Token t
= (Token
)alTokens
.get(i
);
989 if (t
.isDynamicEx()) {
999 private int getDataTypeAlignmentSize (Token token
) {
1000 switch (token
.datumType
) {
1018 private int getHiiPtrTypeAlignmentSize(Token token
) {
1019 switch (token
.datumType
) {
1029 if (token
.isHiiEnable()) {
1030 if (token
.isHiiDefaultValueUnicodeStringType()) {
1042 private int getAlignmentSize (Token token
) {
1043 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
1047 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
1051 if (token
.isUnicodeStringType()) {
1055 return getDataTypeAlignmentSize(token
);
1058 public String
getCString () {
1062 public String
getHString () {
1066 private void genCodeWorker(Token t
,
1067 ArrayList
<CStructTypeDeclaration
> declaList
,
1068 HashMap
<String
, String
> instTable
, String phase
)
1069 throws EntityException
{
1071 CStructTypeDeclaration decl
;
1074 // Insert SKU_HEAD if isSkuEnable is true
1076 if (t
.isSkuEnable()) {
1078 tableIdx
= skuIdTable
.add(t
);
1079 decl
= new CStructTypeDeclaration(t
.getPrimaryKeyString(),
1080 SkuHeadAlignmentSize
, getSkuEnabledTypeDeclaration(t
), true);
1081 declaList
.add(decl
);
1082 instTable
.put(t
.getPrimaryKeyString(),
1083 getSkuEnabledTypeInstantiaion(t
, tableIdx
));
1087 // Insert PCD_ENTRY declaration and instantiation
1089 getCDeclarationString(t
);
1091 decl
= new CStructTypeDeclaration(privateGlobalName
,
1092 getAlignmentSize(t
), privateGlobalCCode
, t
.hasDefaultValue());
1093 declaList
.add(decl
);
1095 if (t
.hasDefaultValue()) {
1096 instTable
.put(privateGlobalName
,
1097 getTypeInstantiation(t
, declaList
, instTable
, phase
)
1103 private void ProcessTokens (List
<Token
> tokens
,
1104 ArrayList
<CStructTypeDeclaration
> cStructDeclList
,
1105 HashMap
<String
, String
> cStructInstTable
,
1108 throws EntityException
{
1110 for (int idx
= 0; idx
< tokens
.size(); idx
++) {
1111 Token t
= tokens
.get(idx
);
1113 genCodeWorker (t
, cStructDeclList
, cStructInstTable
, phase
);
1116 localTokenNumberTable
.add(t
);
1117 t
.tokenNumber
= assignedTokenNumber
++;
1120 // Add a mapping if this dynamic PCD entry is a EX type
1122 if (t
.isDynamicEx()) {
1123 exMapTable
.add((int)t
.tokenNumber
,
1124 t
.dynamicExTokenNumber
,
1125 guidTable
.add(t
.tokenSpaceName
, t
.getPrimaryKeyString()),
1126 t
.getPrimaryKeyString()
1133 public void genCode () throws EntityException
{
1135 ArrayList
<CStructTypeDeclaration
> cStructDeclList
= new ArrayList
<CStructTypeDeclaration
>();
1136 HashMap
<String
, String
> cStructInstTable
= new HashMap
<String
, String
>();
1138 List
<Token
> nexTokens
= new ArrayList
<Token
> ();
1139 List
<Token
> exTokens
= new ArrayList
<Token
> ();
1141 getNonExAndExTokens (alTokens
, nexTokens
, exTokens
);
1144 // We have to process Non-Ex type PCD entry first. The reason is
1145 // that our optimization assumes that the Token Number of Non-Ex
1146 // PCD entry start from 1 (for PEI phase) and grows continously upwards.
1148 // EX type token number starts from the last Non-EX PCD entry and
1149 // grows continously upwards.
1151 ProcessTokens (nexTokens
, cStructDeclList
, cStructInstTable
, phase
);
1152 ProcessTokens (exTokens
, cStructDeclList
, cStructInstTable
, phase
);
1154 stringTable
.genCode(cStructDeclList
, cStructInstTable
);
1155 skuIdTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1156 exMapTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1157 localTokenNumberTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1158 sizeTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1159 guidTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1161 hString
= genCMacroCode ();
1163 HashMap
<String
, String
> result
;
1165 result
= genCStructCode(cStructDeclList
,
1170 hString
+= result
.get("initDeclStr");
1171 hString
+= result
.get("uninitDeclStr");
1173 hString
+= String
.format("#define PCD_%s_SERVICE_DRIVER_VERSION %d", phase
, version
);
1175 cString
= newLine
+ newLine
+ result
.get("initInstStr");
1179 private String
genCMacroCode () {
1180 String macroStr
= "";
1183 // Generate size info Macro for all Tables
1185 macroStr
+= guidTable
.getSizeMacro();
1186 macroStr
+= stringTable
.getSizeMacro();
1187 macroStr
+= skuIdTable
.getSizeMacro();
1188 macroStr
+= localTokenNumberTable
.getSizeMacro();
1189 macroStr
+= exMapTable
.getSizeMacro();
1190 macroStr
+= sizeTable
.getSizeMacro();
1193 // Generate existance info Macro for all Tables
1195 macroStr
+= guidTable
.getExistanceMacro();
1196 macroStr
+= stringTable
.getExistanceMacro();
1197 macroStr
+= skuIdTable
.getExistanceMacro();
1198 macroStr
+= localTokenNumberTable
.getExistanceMacro();
1199 macroStr
+= exMapTable
.getExistanceMacro();
1201 macroStr
+= newLine
;
1206 private HashMap
<String
, String
> genCStructCode(
1207 ArrayList
<CStructTypeDeclaration
> declaList
,
1208 HashMap
<String
, String
> instTable
,
1213 HashMap
<String
, String
> result
= new HashMap
<String
, String
>();
1214 HashMap
<Integer
, ArrayList
<String
>> alignmentInitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1215 HashMap
<Integer
, ArrayList
<String
>> alignmentUninitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1216 HashMap
<Integer
, ArrayList
<String
>> alignmentInitInst
= new HashMap
<Integer
, ArrayList
<String
>>();
1219 // Initialize the storage for each alignment
1221 for (i
= 8; i
> 0; i
>>=1) {
1222 alignmentInitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1223 alignmentInitInst
.put(new Integer(i
), new ArrayList
<String
>());
1224 alignmentUninitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1227 String initDeclStr
= "typedef struct {" + newLine
;
1228 String initInstStr
= String
.format("%s_PCD_DATABASE_INIT g%sPcdDbInit = { ", phase
.toUpperCase(), phase
.toUpperCase()) + newLine
;
1229 String uninitDeclStr
= "typedef struct {" + newLine
;
1232 // Sort all C declaration and instantiation base on Alignment Size
1234 for (Object d
: declaList
) {
1235 CStructTypeDeclaration decl
= (CStructTypeDeclaration
) d
;
1237 if (decl
.initTable
) {
1238 alignmentInitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1239 alignmentInitInst
.get(new Integer(decl
.alignmentSize
)).add(instTable
.get(decl
.key
));
1241 alignmentUninitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1246 // Generate code for every alignment size
1248 boolean uinitDatabaseEmpty
= true;
1249 for (int align
= 8; align
> 0; align
>>= 1) {
1250 ArrayList
<String
> declaListBasedOnAlignment
= alignmentInitDecl
.get(new Integer(align
));
1251 ArrayList
<String
> instListBasedOnAlignment
= alignmentInitInst
.get(new Integer(align
));
1252 for (i
= 0; i
< declaListBasedOnAlignment
.size(); i
++) {
1253 initDeclStr
+= tab
+ declaListBasedOnAlignment
.get(i
);
1254 initInstStr
+= tab
+ instListBasedOnAlignment
.get(i
);
1257 // We made a assumption that both PEI_PCD_DATABASE and DXE_PCD_DATABASE
1258 // has a least one data memember with alignment size of 1. So we can
1259 // remove the last "," in the C structure instantiation string. Luckily,
1260 // this is true as both data structure has SKUID_TABLE anyway.
1262 if ((align
== 1) && (i
== declaListBasedOnAlignment
.size() - 1)) {
1263 initInstStr
+= newLine
;
1265 initInstStr
+= commaNewLine
;
1269 declaListBasedOnAlignment
= alignmentUninitDecl
.get(new Integer(align
));
1271 if (declaListBasedOnAlignment
.size() != 0) {
1272 uinitDatabaseEmpty
= false;
1275 for (Object d
: declaListBasedOnAlignment
) {
1276 String s
= (String
)d
;
1277 uninitDeclStr
+= tab
+ s
;
1281 if (uinitDatabaseEmpty
) {
1282 uninitDeclStr
+= tab
+ String
.format("%-20sdummy; /* PCD_DATABASE_UNINIT is emptry */\r\n", "UINT8");
1285 initDeclStr
+= String
.format("} %s_PCD_DATABASE_INIT;", phase
) + newLine
+ newLine
;
1286 initInstStr
+= "};" + newLine
;
1287 uninitDeclStr
+= String
.format("} %s_PCD_DATABASE_UNINIT;", phase
) + newLine
+ newLine
;
1289 result
.put("initDeclStr", initDeclStr
);
1290 result
.put("initInstStr", initInstStr
);
1291 result
.put("uninitDeclStr", uninitDeclStr
);
1296 public static String
genInstantiationStr (ArrayList
<String
> alStr
) {
1298 for (int i
= 0; i
< alStr
.size(); i
++) {
1302 str
+= alStr
.get(i
);
1303 if (i
!= alStr
.size() - 1) {
1311 private String
getSkuEnabledTypeDeclaration (Token token
) {
1312 return String
.format("%-20s%s;\r\n", "SKU_HEAD", token
.getPrimaryKeyString());
1315 private String
getSkuEnabledTypeInstantiaion (Token token
, int SkuTableIdx
) {
1317 String offsetof
= String
.format(PcdDatabase
.offsetOfSkuHeadStrTemplate
, phase
, token
.hasDefaultValue()?
"Init" : "Uninit", token
.getPrimaryKeyString());
1318 return String
.format("{ %s, %d } /* SKU_ENABLED: %s */", offsetof
, SkuTableIdx
, token
.getPrimaryKeyString());
1321 private String
getDataTypeInstantiationForVariableDefault (Token token
, String cName
, int skuId
) {
1322 return String
.format("%s /* %s */", token
.skuData
.get(skuId
).value
.hiiDefaultValue
, cName
);
1325 private String
getCType (Token t
)
1326 throws EntityException
{
1328 if (t
.isHiiEnable()) {
1329 return "VARIABLE_HEAD";
1332 if (t
.isVpdEnable()) {
1336 if (t
.isUnicodeStringType()) {
1337 return "STRING_HEAD";
1340 switch (t
.datumType
) {
1354 throw new EntityException("Unknown type in getDataTypeCDeclaration");
1359 // privateGlobalName and privateGlobalCCode is used to pass output to caller of getCDeclarationString
1361 private void getCDeclarationString(Token t
)
1362 throws EntityException
{
1364 if (t
.isSkuEnable()) {
1365 privateGlobalName
= String
.format("%s_%s", t
.getPrimaryKeyString(), skuDataTableTemplate
);
1367 privateGlobalName
= t
.getPrimaryKeyString();
1370 String type
= getCType(t
);
1371 if ((t
.datumType
== Token
.DATUM_TYPE
.POINTER
) && (!t
.isHiiEnable()) && (!t
.isUnicodeStringType())) {
1373 if (t
.isASCIIStringType()) {
1375 // Build tool will add a NULL string at the end of the ASCII string
1377 bufferSize
= t
.datumSize
+ 1;
1379 bufferSize
= t
.datumSize
;
1381 privateGlobalCCode
= String
.format("%-20s%s[%d][%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount(), bufferSize
);
1383 privateGlobalCCode
= String
.format("%-20s%s[%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount());
1387 private String
getDataTypeDeclarationForVariableDefault (Token token
, String cName
, int skuId
)
1388 throws EntityException
{
1392 if (token
.datumType
== Token
.DATUM_TYPE
.UINT8
) {
1394 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT16
) {
1396 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT32
) {
1398 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT64
) {
1400 } else if (token
.datumType
== Token
.DATUM_TYPE
.BOOLEAN
) {
1401 typeStr
= "BOOLEAN";
1402 } else if (token
.datumType
== Token
.DATUM_TYPE
.POINTER
) {
1404 if (token
.isHiiDefaultValueUnicodeStringType()) {
1407 // Include the NULL charactor
1409 size
= token
.datumSize
/ 2 + 1;
1412 if (token
.isHiiDefaultValueASCIIStringType()) {
1414 // Include the NULL charactor
1416 size
= token
.datumSize
+ 1;
1418 size
= token
.datumSize
;
1421 return String
.format("%-20s%s[%d];\r\n", typeStr
, cName
, size
);
1423 throw new EntityException("Unknown DATUM_TYPE type in when generating code for VARIABLE_ENABLED PCD entry");
1426 return String
.format("%-20s%s;\r\n", typeStr
, cName
);
1429 private String
getTypeInstantiation (Token t
, ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) throws EntityException
{
1434 s
= String
.format("/* %s */", t
.getPrimaryKeyString()) + newLine
;
1435 s
+= tab
+ "{" + newLine
;
1437 for (i
= 0; i
< t
.skuData
.size(); i
++) {
1438 if (t
.isUnicodeStringType()) {
1439 s
+= tab
+ tab
+ String
.format("{ %d }", stringTable
.add(t
.skuData
.get(i
).value
.value
, t
));
1440 } else if (t
.isHiiEnable()) {
1441 /* VPD_HEAD definition
1443 UINT16 GuidTableIndex; // Offset in Guid Table in units of GUID.
1444 UINT16 StringIndex; // Offset in String Table in units of UINT16.
1445 UINT16 Offset; // Offset in Variable
1446 UINT16 DefaultValueOffset; // Offset of the Default Value
1449 String variableDefaultName
= String
.format("%s_VariableDefault_%d", t
.getPrimaryKeyString(), i
);
1451 s
+= tab
+ tab
+ String
.format("{ %d, %d, %s, %s }", guidTable
.add(t
.skuData
.get(i
).value
.variableGuid
, t
.getPrimaryKeyString()),
1452 stringTable
.add(t
.skuData
.get(i
).value
.getStringOfVariableName(), t
),
1453 t
.skuData
.get(i
).value
.variableOffset
,
1454 String
.format("offsetof(%s_PCD_DATABASE, Init.%s)", phase
, variableDefaultName
)
1457 // We need to support the default value, so we add the declaration and
1458 // the instantiation for the default value.
1460 CStructTypeDeclaration decl
= new CStructTypeDeclaration (variableDefaultName
,
1461 getHiiPtrTypeAlignmentSize(t
),
1462 getDataTypeDeclarationForVariableDefault(t
, variableDefaultName
, i
),
1465 declaList
.add(decl
);
1466 instTable
.put(variableDefaultName
, getDataTypeInstantiationForVariableDefault (t
, variableDefaultName
, i
));
1467 } else if (t
.isVpdEnable()) {
1472 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.vpdOffset
);
1474 if (t
.isByteStreamType()) {
1476 // Byte stream type input has their own "{" "}", so we won't help to insert.
1478 s
+= tab
+ tab
+ String
.format(" %s ", t
.skuData
.get(i
).value
.value
);
1480 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.value
);
1484 if (i
!= t
.skuData
.size() - 1) {
1497 public static String
getPcdDatabaseCommonDefinitions ()
1498 throws EntityException
{
1502 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1503 "Tools" + File
.separator
+
1504 "Conf" + File
.separator
+
1505 "Pcd" + File
.separator
+
1506 "PcdDatabaseCommonDefinitions.sample");
1507 FileReader reader
= new FileReader(file
);
1508 BufferedReader in
= new BufferedReader(reader
);
1510 while ((str
= in
.readLine()) != null) {
1511 retStr
= retStr
+"\r\n" + str
;
1513 } catch (Exception ex
) {
1514 throw new EntityException("Fatal error when generating PcdDatabase Common Definitions");
1520 public static String
getPcdDxeDatabaseDefinitions ()
1521 throws EntityException
{
1525 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1526 "Tools" + File
.separator
+
1527 "Conf" + File
.separator
+
1528 "Pcd" + File
.separator
+
1529 "PcdDatabaseDxeDefinitions.sample");
1530 FileReader reader
= new FileReader(file
);
1531 BufferedReader in
= new BufferedReader(reader
);
1533 while ((str
= in
.readLine()) != null) {
1534 retStr
= retStr
+"\r\n" + str
;
1536 } catch (Exception ex
) {
1537 throw new EntityException("Fatal error when generating PcdDatabase Dxe Definitions");
1543 public static String
getPcdPeiDatabaseDefinitions ()
1544 throws EntityException
{
1548 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1549 "Tools" + File
.separator
+
1550 "Conf" + File
.separator
+
1551 "Pcd" + File
.separator
+
1552 "PcdDatabasePeiDefinitions.sample");
1553 FileReader reader
= new FileReader(file
);
1554 BufferedReader in
= new BufferedReader(reader
);
1556 while ((str
= in
.readLine()) != null) {
1557 retStr
= retStr
+"\r\n" + str
;
1559 } catch (Exception ex
) {
1560 throw new EntityException("Fatal error when generating PcdDatabase Pei Definitions");
1569 private String type
;
1570 private FpdModuleIdentification moduleId
;
1571 private PcdBuildDefinitionDocument
.PcdBuildDefinition pcdBuildDef
;
1575 public ModuleInfo (FpdModuleIdentification moduleId
, String type
, XmlObject pcdDef
) {
1576 this.moduleId
= moduleId
;
1578 this.pcdBuildDef
= ((PcdBuildDefinitionDocument
)pcdDef
).getPcdBuildDefinition();
1580 public String
getModuleType (){
1583 public FpdModuleIdentification
getModuleId (){
1584 return this.moduleId
;
1586 public PcdBuildDefinitionDocument
.PcdBuildDefinition
getPcdBuildDef(){
1587 return this.pcdBuildDef
;
1591 /** This action class is to collect PCD information from MSA, SPD, FPD xml file.
1592 This class will be used for wizard and build tools, So it can *not* inherit
1593 from buildAction or UIAction.
1595 public class CollectPCDAction
{
1596 /// memoryDatabase hold all PCD information collected from SPD, MSA, FPD.
1597 private MemoryDatabaseManager dbManager
;
1599 /// Workspacepath hold the workspace information.
1600 private String workspacePath
;
1602 /// FPD file is the root file.
1603 private String fpdFilePath
;
1605 /// Message level for CollectPCDAction.
1606 private int originalMessageLevel
;
1608 /// Cache the fpd docment instance for private usage.
1609 private PlatformSurfaceAreaDocument fpdDocInstance
;
1612 private static String xmlObjectName
= "PcdBuildDefinition";
1615 Set WorkspacePath parameter for this action class.
1617 @param workspacePath parameter for this action
1619 public void setWorkspacePath(String workspacePath
) {
1620 this.workspacePath
= workspacePath
;
1624 Set action message level for CollectPcdAction tool.
1626 The message should be restored when this action exit.
1628 @param actionMessageLevel parameter for this action
1630 public void setActionMessageLevel(int actionMessageLevel
) {
1631 originalMessageLevel
= ActionMessage
.messageLevel
;
1632 ActionMessage
.messageLevel
= actionMessageLevel
;
1636 Set FPDFileName parameter for this action class.
1638 @param fpdFilePath fpd file path
1640 public void setFPDFilePath(String fpdFilePath
) {
1641 this.fpdFilePath
= fpdFilePath
;
1645 Common function interface for outer.
1647 @param workspacePath The path of workspace of current build or analysis.
1648 @param fpdFilePath The fpd file path of current build or analysis.
1649 @param messageLevel The message level for this Action.
1651 @throws Exception The exception of this function. Because it can *not* be predict
1652 where the action class will be used. So only Exception can be throw.
1655 public void perform(String workspacePath
, String fpdFilePath
,
1656 int messageLevel
) throws Exception
{
1657 setWorkspacePath(workspacePath
);
1658 setFPDFilePath(fpdFilePath
);
1659 setActionMessageLevel(messageLevel
);
1662 ActionMessage
.messageLevel
= originalMessageLevel
;
1666 Core execution function for this action class.
1668 This function work flows will be:
1669 1) Collect and prepocess PCD information from FPD file, all PCD
1670 information will be stored into memory database.
1671 2) Generate 3 strings for
1672 a) All modules using Dynamic(Ex) PCD entry.(Token Number)
1673 b) PEI PCDDatabase (C Structure) for PCD Service PEIM.
1674 c) DXE PCD Database (C structure) for PCD Service DXE.
1677 @throws EntityException Exception indicate failed to execute this action.
1680 public void execute() throws EntityException
{
1682 // Get memoryDatabaseManager instance from GlobalData.
1683 // The memoryDatabaseManager should be initialized for whatever build
1684 // tools or wizard tools
1686 if((dbManager
= GlobalData
.getPCDMemoryDBManager()) == null) {
1687 throw new EntityException("The instance of PCD memory database manager is null");
1691 // Collect all PCD information defined in FPD file.
1692 // Evenry token defind in FPD will be created as an token into
1695 createTokenInDBFromFPD();
1698 // Call Private function genPcdDatabaseSourceCode (void); ComponentTypeBsDriver
1699 // 1) Generate for PEI, DXE PCD DATABASE's definition and initialization.
1701 genPcdDatabaseSourceCode ();
1706 This function generates source code for PCD Database.
1709 @throws EntityException If the token does *not* exist in memory database.
1712 private void genPcdDatabaseSourceCode()
1713 throws EntityException
{
1714 String PcdCommonHeaderString
= PcdDatabase
.getPcdDatabaseCommonDefinitions ();
1716 ArrayList
<Token
> alPei
= new ArrayList
<Token
> ();
1717 ArrayList
<Token
> alDxe
= new ArrayList
<Token
> ();
1719 dbManager
.getTwoPhaseDynamicRecordArray(alPei
, alDxe
);
1720 PcdDatabase pcdPeiDatabase
= new PcdDatabase (alPei
, "PEI", 0);
1721 pcdPeiDatabase
.genCode();
1722 MemoryDatabaseManager
.PcdPeimHString
= PcdCommonHeaderString
+ pcdPeiDatabase
.getHString()
1723 + PcdDatabase
.getPcdPeiDatabaseDefinitions();
1724 MemoryDatabaseManager
.PcdPeimCString
= pcdPeiDatabase
.getCString();
1726 PcdDatabase pcdDxeDatabase
= new PcdDatabase (alDxe
,
1730 pcdDxeDatabase
.genCode();
1731 MemoryDatabaseManager
.PcdDxeHString
= MemoryDatabaseManager
.PcdPeimHString
+ pcdDxeDatabase
.getHString()
1732 + PcdDatabase
.getPcdDxeDatabaseDefinitions();
1733 MemoryDatabaseManager
.PcdDxeCString
= pcdDxeDatabase
.getCString();
1737 Get component array from FPD.
1739 This function maybe provided by some Global class.
1741 @return List<ModuleInfo> the component array.
1744 private List
<ModuleInfo
> getComponentsFromFPD()
1745 throws EntityException
{
1746 List
<ModuleInfo
> allModules
= new ArrayList
<ModuleInfo
>();
1747 ModuleInfo current
= null;
1749 FrameworkModulesDocument
.FrameworkModules fModules
= null;
1750 ModuleSADocument
.ModuleSA
[] modules
= null;
1751 HashMap
<String
, XmlObject
> map
= new HashMap
<String
, XmlObject
>();
1753 if (fpdDocInstance
== null) {
1755 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
1756 } catch(IOException ioE
) {
1757 throw new EntityException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
1758 } catch(XmlException xmlE
) {
1759 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
1764 Map
<FpdModuleIdentification
,XmlObject
>pcdBuildDef
= GlobalData
.getFpdModuleSaXmlObject(CollectPCDAction
.xmlObjectName
);
1765 Set
<FpdModuleIdentification
> pcdBuildKeySet
= pcdBuildDef
.keySet();
1766 Iterator item
= pcdBuildKeySet
.iterator();
1767 while (item
.hasNext()){
1768 FpdModuleIdentification id
= (FpdModuleIdentification
)item
.next();
1769 allModules
.add(new ModuleInfo(id
, id
.getModule().getModuleType(),pcdBuildDef
.get(id
)));
1776 Create token instance object into memory database, the token information
1777 comes for FPD file. Normally, FPD file will contain all token platform
1780 @return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage.
1782 @throws EntityException Failed to parse FPD xml file.
1785 private void createTokenInDBFromFPD()
1786 throws EntityException
{
1790 List
<PcdBuildDefinition
.PcdData
> pcdBuildDataArray
= new ArrayList
<PcdBuildDefinition
.PcdData
>();
1791 PcdBuildDefinition
.PcdData pcdBuildData
= null;
1793 List
<ModuleInfo
> modules
= null;
1794 String primaryKey
= null;
1795 String exceptionString
= null;
1796 UsageInstance usageInstance
= null;
1797 String primaryKey1
= null;
1798 String primaryKey2
= null;
1799 boolean isDuplicate
= false;
1800 Token
.PCD_TYPE pcdType
= Token
.PCD_TYPE
.UNKNOWN
;
1801 Token
.DATUM_TYPE datumType
= Token
.DATUM_TYPE
.UNKNOWN
;
1802 long tokenNumber
= 0;
1803 String moduleName
= null;
1804 String datum
= null;
1805 int maxDatumSize
= 0;
1806 String
[] tokenSpaceStrRet
= null;
1809 // ----------------------------------------------
1810 // 1), Get all <ModuleSA> from FPD file.
1811 // ----------------------------------------------
1813 modules
= getComponentsFromFPD();
1815 if (modules
== null) {
1816 throw new EntityException("[FPD file error] No modules in FPD file, Please check whether there are elements in <FrameworkModules> in FPD file!");
1820 // -------------------------------------------------------------------
1821 // 2), Loop all modules to process <PcdBuildDeclarations> for each module.
1822 // -------------------------------------------------------------------
1824 for (index
= 0; index
< modules
.size(); index
++) {
1825 isDuplicate
= false;
1826 for (index2
= 0; index2
< index
; index2
++) {
1828 // BUGBUG: For transition schema, we can *not* get module's version from
1829 // <ModuleSAs>, It is work around code.
1831 primaryKey1
= UsageInstance
.getPrimaryKey(modules
.get(index
).getModuleId().getModule().getName(),
1835 modules
.get(index
).getModuleId().getArch(),
1837 primaryKey2
= UsageInstance
.getPrimaryKey(modules
.get(index2
).getModuleId().getModule().getName(),
1841 modules
.get(index2
).getModuleId().getArch(),
1843 if (primaryKey1
.equalsIgnoreCase(primaryKey2
)) {
1854 // It is legal for a module does not contains ANY pcd build definitions.
1856 if (modules
.get(index
).getPcdBuildDef() == null) {
1860 pcdBuildDataArray
= modules
.get(index
).getPcdBuildDef().getPcdDataList();
1862 moduleName
= modules
.get(index
).getModuleId().getModule().getName();
1865 // ----------------------------------------------------------------------
1866 // 2.1), Loop all Pcd entry for a module and add it into memory database.
1867 // ----------------------------------------------------------------------
1869 for (pcdIndex
= 0; pcdIndex
< pcdBuildDataArray
.size(); pcdIndex
++) {
1870 pcdBuildData
= pcdBuildDataArray
.get(pcdIndex
);
1873 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(pcdBuildData
.getTokenSpaceGuidCName());
1874 } catch ( Exception e
) {
1875 throw new EntityException ("Faile get Guid for token " + pcdBuildData
.getCName() + ":" + e
.getMessage());
1878 if (tokenSpaceStrRet
== null) {
1879 throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData
.getCName());
1882 primaryKey
= Token
.getPrimaryKeyString(pcdBuildData
.getCName(),
1883 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
1884 pcdType
= Token
.getpcdTypeFromString(pcdBuildData
.getItemType().toString());
1885 datumType
= Token
.getdatumTypeFromString(pcdBuildData
.getDatumType().toString());
1886 tokenNumber
= Long
.decode(pcdBuildData
.getToken().toString());
1887 if (pcdBuildData
.getValue() != null) {
1888 datum
= pcdBuildData
.getValue().toString();
1892 maxDatumSize
= pcdBuildData
.getMaxDatumSize();
1894 if ((pcdType
== Token
.PCD_TYPE
.FEATURE_FLAG
) &&
1895 (datumType
!= Token
.DATUM_TYPE
.BOOLEAN
)){
1896 exceptionString
= String
.format("[FPD file error] For PCD %s in module %s, the PCD type is FEATRUE_FLAG but "+
1897 "datum type of this PCD entry is not BOOLEAN!",
1898 pcdBuildData
.getCName(),
1900 throw new EntityException(exceptionString
);
1904 // -------------------------------------------------------------------------------------------
1905 // 2.1.1), Do some necessary checking work for FixedAtBuild, FeatureFlag and PatchableInModule
1906 // -------------------------------------------------------------------------------------------
1908 if (!Token
.isDynamic(pcdType
)) {
1910 // Value is required.
1912 if (datum
== null) {
1913 exceptionString
= String
.format("[FPD file error] There is no value for PCD entry %s in module %s!",
1914 pcdBuildData
.getCName(),
1916 throw new EntityException(exceptionString
);
1920 // Check whether the datum size is matched datum type.
1922 if ((exceptionString
= verifyDatum(pcdBuildData
.getCName(),
1926 maxDatumSize
)) != null) {
1927 throw new EntityException(exceptionString
);
1932 // ---------------------------------------------------------------------------------
1933 // 2.1.2), Create token or update token information for current anaylized PCD data.
1934 // ---------------------------------------------------------------------------------
1936 if (dbManager
.isTokenInDatabase(primaryKey
)) {
1938 // If the token is already exist in database, do some necessary checking
1939 // and add a usage instance into this token in database
1941 token
= dbManager
.getTokenByKey(primaryKey
);
1944 // checking for DatumType, DatumType should be unique for one PCD used in different
1947 if (token
.datumType
!= datumType
) {
1948 exceptionString
= String
.format("[FPD file error] The datum type of PCD entry %s is %s, which is different with %s defined in before!",
1949 pcdBuildData
.getCName(),
1950 pcdBuildData
.getDatumType().toString(),
1951 Token
.getStringOfdatumType(token
.datumType
));
1952 throw new EntityException(exceptionString
);
1956 // Check token number is valid
1958 if (tokenNumber
!= token
.tokenNumber
) {
1959 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!",
1960 pcdBuildData
.getCName(),
1962 throw new EntityException(exceptionString
);
1966 // For same PCD used in different modules, the PCD type should all be dynamic or non-dynamic.
1968 if (token
.isDynamicPCD
!= Token
.isDynamic(pcdType
)) {
1969 exceptionString
= String
.format("[FPD file error] For PCD entry %s in module %s, you define dynamic or non-dynamic PCD type which"+
1970 "is different with others module's",
1973 throw new EntityException(exceptionString
);
1976 if (token
.isDynamicPCD
) {
1978 // Check datum is equal the datum in dynamic information.
1979 // For dynamic PCD, you can do not write <Value> in sperated every <PcdBuildDefinition> in different <ModuleSA>,
1980 // But if you write, the <Value> must be same as the value in <DynamicPcdBuildDefinitions>.
1982 if (!token
.isSkuEnable() &&
1983 (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.DEFAULT_TYPE
) &&
1985 if (!datum
.equalsIgnoreCase(token
.getDefaultSku().value
)) {
1986 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in module %s, the datum in <ModuleSA> is "+
1987 "not equal to the datum in <DynamicPcdBuildDefinitions>, it is "+
1988 "illega! You could no set <Value> in <ModuleSA> for a dynamic PCD!",
1991 throw new EntityException(exceptionString
);
1995 if ((maxDatumSize
!= 0) &&
1996 (maxDatumSize
!= token
.datumSize
)){
1997 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in module %s, the max datum size is %d which "+
1998 "is different with <MaxDatumSize> %d defined in <DynamicPcdBuildDefinitions>!",
2003 throw new EntityException(exceptionString
);
2009 // If the token is not in database, create a new token instance and add
2010 // a usage instance into this token in database.
2013 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(pcdBuildData
.getTokenSpaceGuidCName());
2014 } catch (Exception e
) {
2015 throw new EntityException("Fail to get token space guid for token " + token
.cName
);
2018 if (tokenSpaceStrRet
== null) {
2019 throw new EntityException("Fail to get token space guid for token " + token
.cName
);
2022 token
= new Token(pcdBuildData
.getCName(),
2023 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
2025 token
.datumType
= datumType
;
2026 token
.tokenNumber
= tokenNumber
;
2027 token
.isDynamicPCD
= Token
.isDynamic(pcdType
);
2028 token
.datumSize
= maxDatumSize
;
2030 if (token
.isDynamicPCD
) {
2032 // For Dynamic and Dynamic Ex type, need find the dynamic information
2033 // in <DynamicPcdBuildDefinition> section in FPD file.
2035 updateDynamicInformation(moduleName
,
2041 dbManager
.addTokenToDatabase(primaryKey
, token
);
2045 // -----------------------------------------------------------------------------------
2046 // 2.1.3), Add the PcdType in current module into this Pcd token's supported PCD type.
2047 // -----------------------------------------------------------------------------------
2049 token
.updateSupportPcdType(pcdType
);
2052 // ------------------------------------------------
2053 // 2.1.4), Create an usage instance for this token.
2054 // ------------------------------------------------
2056 usageInstance
= new UsageInstance(token
,
2061 CommonDefinition
.getModuleType(modules
.get(index
).getModuleType()),
2063 modules
.get(index
).getModuleId().getArch(),
2067 token
.addUsageInstance(usageInstance
);
2072 // ------------------------------------------------
2073 // 3), Add unreference dynamic_Ex pcd token into Pcd database.
2074 // ------------------------------------------------
2076 List
<Token
> tokenArray
= getUnreferencedDynamicPcd();
2077 if (tokenArray
!= null) {
2078 for (index
= 0; index
< tokenArray
.size(); index
++) {
2079 dbManager
.addTokenToDatabase(tokenArray
.get(index
).getPrimaryKeyString(),
2080 tokenArray
.get(index
));
2085 private List
<Token
> getUnreferencedDynamicPcd () throws EntityException
{
2086 List
<Token
> tokenArray
= new ArrayList
<Token
>();
2088 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
2089 List
<DynamicPcdBuildDefinitions
.PcdBuildData
> dynamicPcdBuildDataArray
= null;
2090 DynamicPcdBuildDefinitions
.PcdBuildData pcdBuildData
= null;
2091 List
<DynamicPcdBuildDefinitions
.PcdBuildData
.SkuInfo
> skuInfoList
= null;
2092 Token
.PCD_TYPE pcdType
;
2093 SkuInstance skuInstance
= null;
2094 String primaryKey
= null;
2095 boolean hasSkuId0
= false;
2096 int index
, offset
, index2
;
2098 String exceptionString
;
2099 String hiiDefaultValue
;
2100 String tokenSpaceStrRet
[];
2101 String variableGuidString
[];
2104 // If FPD document is not be opened, open and initialize it.
2106 if (fpdDocInstance
== null) {
2108 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
2109 } catch(IOException ioE
) {
2110 throw new EntityException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
2111 } catch(XmlException xmlE
) {
2112 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
2116 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
2117 if (dynamicPcdBuildDefinitions
== null) {
2121 dynamicPcdBuildDataArray
= dynamicPcdBuildDefinitions
.getPcdBuildDataList();
2122 for (index2
= 0; index2
< dynamicPcdBuildDataArray
.size(); index2
++) {
2123 pcdBuildData
= dynamicPcdBuildDataArray
.get(index2
);
2125 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(pcdBuildData
.getTokenSpaceGuidCName());
2126 } catch ( Exception e
) {
2127 throw new EntityException ("Faile get Guid for token " + pcdBuildData
.getCName() + ":" + e
.getMessage());
2130 if (tokenSpaceStrRet
== null) {
2131 throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData
.getCName());
2134 primaryKey
= Token
.getPrimaryKeyString(pcdBuildData
.getCName(),
2135 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
2137 if (dbManager
.isTokenInDatabase(primaryKey
)) {
2141 pcdType
= Token
.getpcdTypeFromString(pcdBuildData
.getItemType().toString());
2142 if (pcdType
!= Token
.PCD_TYPE
.DYNAMIC_EX
) {
2143 throw new EntityException (String
.format("[FPD file error] It not allowed for DYNAMIC PCD %s who is no used by any module",
2144 pcdBuildData
.getCName()));
2148 // Create new token for unreference dynamic PCD token
2150 token
= new Token(pcdBuildData
.getCName(), translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
2151 token
.datumSize
= pcdBuildData
.getMaxDatumSize();
2154 token
.datumType
= Token
.getdatumTypeFromString(pcdBuildData
.getDatumType().toString());
2155 token
.tokenNumber
= Long
.decode(pcdBuildData
.getToken().toString());
2156 token
.dynamicExTokenNumber
= token
.tokenNumber
;
2157 token
.isDynamicPCD
= true;
2158 token
.updateSupportPcdType(pcdType
);
2160 exceptionString
= verifyDatum(token
.cName
,
2165 if (exceptionString
!= null) {
2166 throw new EntityException(exceptionString
);
2169 skuInfoList
= pcdBuildData
.getSkuInfoList();
2172 // Loop all sku data
2174 for (index
= 0; index
< skuInfoList
.size(); index
++) {
2175 skuInstance
= new SkuInstance();
2177 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.
2179 temp
= skuInfoList
.get(index
).getSkuId().toString();
2180 skuInstance
.id
= Integer
.decode(temp
);
2181 if (skuInstance
.id
== 0) {
2185 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.
2187 if (skuInfoList
.get(index
).getValue() != null) {
2188 skuInstance
.value
.setValue(skuInfoList
.get(index
).getValue().toString());
2189 if ((exceptionString
= verifyDatum(token
.cName
,
2191 skuInfoList
.get(index
).getValue().toString(),
2193 token
.datumSize
)) != null) {
2194 throw new EntityException(exceptionString
);
2197 token
.skuData
.add(skuInstance
);
2203 // Judge whether is HII group case.
2205 if (skuInfoList
.get(index
).getVariableName() != null) {
2206 exceptionString
= null;
2207 if (skuInfoList
.get(index
).getVariableGuid() == null) {
2208 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2209 "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",
2212 if (exceptionString
!= null) {
2213 throw new EntityException(exceptionString
);
2217 if (skuInfoList
.get(index
).getVariableOffset() == null) {
2218 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2219 "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",
2222 if (exceptionString
!= null) {
2223 throw new EntityException(exceptionString
);
2227 if (skuInfoList
.get(index
).getHiiDefaultValue() == null) {
2228 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2229 "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",
2232 if (exceptionString
!= null) {
2233 throw new EntityException(exceptionString
);
2237 if (skuInfoList
.get(index
).getHiiDefaultValue() != null) {
2238 hiiDefaultValue
= skuInfoList
.get(index
).getHiiDefaultValue().toString();
2240 hiiDefaultValue
= null;
2243 if ((exceptionString
= verifyDatum(token
.cName
,
2247 token
.datumSize
)) != null) {
2248 throw new EntityException(exceptionString
);
2251 offset
= Integer
.decode(skuInfoList
.get(index
).getVariableOffset());
2252 if (offset
> 0xFFFF) {
2253 throw new EntityException(String
.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+
2254 "exceed 64K, it is not allowed!",
2260 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.
2262 variableGuidString
= GlobalData
.getGuidInfoFromCname(skuInfoList
.get(index
).getVariableGuid().toString());
2263 if (variableGuidString
== null) {
2264 throw new EntityException(String
.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",
2266 skuInfoList
.get(index
).getVariableGuid().toString()));
2268 String variableStr
= skuInfoList
.get(index
).getVariableName();
2269 Pattern pattern
= Pattern
.compile("0x([a-fA-F0-9]){4}");
2270 Matcher matcher
= pattern
.matcher(variableStr
);
2271 List
<String
> varNameList
= new ArrayList
<String
>();
2272 while (matcher
.find()){
2273 String str
= variableStr
.substring(matcher
.start(),matcher
.end());
2274 varNameList
.add(str
);
2277 skuInstance
.value
.setHiiData(varNameList
,
2278 translateSchemaStringToUUID(variableGuidString
[1]),
2279 skuInfoList
.get(index
).getVariableOffset(),
2280 skuInfoList
.get(index
).getHiiDefaultValue().toString());
2281 token
.skuData
.add(skuInstance
);
2285 if (skuInfoList
.get(index
).getVpdOffset() != null) {
2286 skuInstance
.value
.setVpdData(skuInfoList
.get(index
).getVpdOffset());
2287 token
.skuData
.add(skuInstance
);
2291 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+
2292 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",
2294 throw new EntityException(exceptionString
);
2298 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+
2299 "no sku id = 0 data, which is required for every dynamic PCD",
2301 throw new EntityException(exceptionString
);
2304 tokenArray
.add(token
);
2311 Verify the datum value according its datum size and datum type, this
2312 function maybe moved to FPD verification tools in future.
2323 public String
verifyDatum(String cName
,
2326 Token
.DATUM_TYPE datumType
,
2328 String exceptionString
= null;
2334 if (moduleName
== null) {
2335 moduleName
= "section <DynamicPcdBuildDefinitions>";
2337 moduleName
= "module " + moduleName
;
2340 if (maxDatumSize
== 0) {
2341 exceptionString
= String
.format("[FPD file error] You maybe miss <MaxDatumSize> for PCD %s in %s",
2344 return exceptionString
;
2347 switch (datumType
) {
2349 if (maxDatumSize
!= 1) {
2350 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2351 "is UINT8, but datum size is %d, they are not matched!",
2355 return exceptionString
;
2358 if (datum
!= null) {
2360 value
= Integer
.decode(datum
);
2361 } catch (NumberFormatException nfeExp
) {
2362 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid "+
2363 "digital format of UINT8",
2366 return exceptionString
;
2369 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s exceed"+
2370 " the max size of UINT8 - 0xFF",
2374 return exceptionString
;
2379 if (maxDatumSize
!= 2) {
2380 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2381 "is UINT16, but datum size is %d, they are not matched!",
2385 return exceptionString
;
2387 if (datum
!= null) {
2389 value
= Integer
.decode(datum
);
2390 } catch (NumberFormatException nfeExp
) {
2391 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is "+
2392 "not valid digital of UINT16",
2395 return exceptionString
;
2397 if (value
> 0xFFFF) {
2398 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
2399 "which exceed the range of UINT16 - 0xFFFF",
2403 return exceptionString
;
2408 if (maxDatumSize
!= 4) {
2409 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2410 "is UINT32, but datum size is %d, they are not matched!",
2414 return exceptionString
;
2417 if (datum
!= null) {
2419 if (datum
.length() > 2) {
2420 if ((datum
.charAt(0) == '0') &&
2421 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
2422 subStr
= datum
.substring(2, datum
.length());
2423 value64
= new BigInteger(subStr
, 16);
2425 value64
= new BigInteger(datum
);
2428 value64
= new BigInteger(datum
);
2430 } catch (NumberFormatException nfeExp
) {
2431 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not "+
2432 "valid digital of UINT32",
2435 return exceptionString
;
2438 if (value64
.bitLength() > 32) {
2439 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s which "+
2440 "exceed the range of UINT32 - 0xFFFFFFFF",
2444 return exceptionString
;
2449 if (maxDatumSize
!= 8) {
2450 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2451 "is UINT64, but datum size is %d, they are not matched!",
2455 return exceptionString
;
2458 if (datum
!= null) {
2460 if (datum
.length() > 2) {
2461 if ((datum
.charAt(0) == '0') &&
2462 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
2463 subStr
= datum
.substring(2, datum
.length());
2464 value64
= new BigInteger(subStr
, 16);
2466 value64
= new BigInteger(datum
);
2469 value64
= new BigInteger(datum
);
2471 } catch (NumberFormatException nfeExp
) {
2472 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid"+
2473 " digital of UINT64",
2476 return exceptionString
;
2479 if (value64
.bitLength() > 64) {
2480 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
2481 "exceed the range of UINT64 - 0xFFFFFFFFFFFFFFFF",
2485 return exceptionString
;
2490 if (maxDatumSize
!= 1) {
2491 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2492 "is BOOLEAN, but datum size is %d, they are not matched!",
2496 return exceptionString
;
2499 if (datum
!= null) {
2500 if (!(datum
.equalsIgnoreCase("TRUE") ||
2501 datum
.equalsIgnoreCase("FALSE"))) {
2502 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2503 "is BOOELAN, but value is not 'true'/'TRUE' or 'FALSE'/'false'",
2506 return exceptionString
;
2512 if (datum
== null) {
2516 char ch
= datum
.charAt(0);
2520 // For void* type PCD, only three datum is support:
2521 // 1) Unicode: string with start char is "L"
2522 // 2) Ansci: String start char is ""
2523 // 3) byte array: String start char "{"
2526 start
= datum
.indexOf('\"');
2527 end
= datum
.lastIndexOf('\"');
2528 if ((start
> end
) ||
2529 (end
> datum
.length())||
2530 ((start
== end
) && (datum
.length() > 0))) {
2531 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
2532 "a UNICODE string because start with L\", but format maybe"+
2533 "is not right, correct UNICODE string is L\"...\"!",
2536 return exceptionString
;
2539 strValue
= datum
.substring(start
+ 1, end
);
2540 if ((strValue
.length() * 2) > maxDatumSize
) {
2541 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
2542 "a UNICODE string, but the datum size is %d exceed to <MaxDatumSize> : %d",
2545 strValue
.length() * 2,
2547 return exceptionString
;
2549 } else if (ch
== '\"'){
2550 start
= datum
.indexOf('\"');
2551 end
= datum
.lastIndexOf('\"');
2552 if ((start
> end
) ||
2553 (end
> datum
.length())||
2554 ((start
== end
) && (datum
.length() > 0))) {
2555 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
2556 "a ANSCII string because start with \", but format maybe"+
2557 "is not right, correct ANSIC string is \"...\"!",
2560 return exceptionString
;
2562 strValue
= datum
.substring(start
+ 1, end
);
2563 if ((strValue
.length()) > maxDatumSize
) {
2564 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
2565 "a ANSCI string, but the datum size is %d which exceed to <MaxDatumSize> : %d",
2570 return exceptionString
;
2572 } else if (ch
=='{') {
2573 String
[] strValueArray
;
2575 start
= datum
.indexOf('{');
2576 end
= datum
.lastIndexOf('}');
2577 strValue
= datum
.substring(start
+ 1, end
);
2578 strValue
= strValue
.trim();
2579 if (strValue
.length() == 0) {
2582 strValueArray
= strValue
.split(",");
2583 for (index
= 0; index
< strValueArray
.length
; index
++) {
2585 value
= Integer
.decode(strValueArray
[index
].trim());
2586 } catch (NumberFormatException nfeEx
) {
2587 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
2588 "it is byte array in fact. For every byte in array should be a valid"+
2589 "byte digital, but element %s is not a valid byte digital!",
2592 strValueArray
[index
]);
2593 return exceptionString
;
2596 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, "+
2597 "it is byte array in fact. But the element of %s exceed the byte range",
2600 strValueArray
[index
]);
2601 return exceptionString
;
2605 if (strValueArray
.length
> maxDatumSize
) {
2606 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is byte"+
2607 "array, but the number of bytes is %d which exceed to <MaxDatumSzie> : %d!",
2610 strValueArray
.length
,
2612 return exceptionString
;
2615 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 "+
2616 "1) UNICODE string: like L\"xxxx\";\r\n"+
2617 "2) ANSIC string: like \"xxx\";\r\n"+
2618 "3) Byte array: like {0x2, 0x45, 0x23}\r\n"+
2619 "But the datum in seems does not following above format!",
2622 return exceptionString
;
2626 exceptionString
= String
.format("[FPD file error] For PCD entry %s in %s, datum type is unknown, it should be one of "+
2627 "UINT8, UINT16, UINT32, UINT64, VOID*, BOOLEAN",
2630 return exceptionString
;
2636 Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.
2638 This function should be implemented in GlobalData in future.
2640 @param token The token instance which has hold module's PCD information
2641 @param moduleName The name of module who will use this Dynamic PCD.
2643 @return DynamicPcdBuildDefinitions.PcdBuildData
2646 private DynamicPcdBuildDefinitions
.PcdBuildData
getDynamicInfoFromFPD(Token token
,
2648 throws EntityException
{
2650 String exceptionString
= null;
2651 String dynamicPrimaryKey
= null;
2652 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
2653 List
<DynamicPcdBuildDefinitions
.PcdBuildData
> dynamicPcdBuildDataArray
= null;
2654 String
[] tokenSpaceStrRet
= null;
2657 // If FPD document is not be opened, open and initialize it.
2659 if (fpdDocInstance
== null) {
2661 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
2662 } catch(IOException ioE
) {
2663 throw new EntityException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
2664 } catch(XmlException xmlE
) {
2665 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
2669 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
2670 if (dynamicPcdBuildDefinitions
== null) {
2671 exceptionString
= String
.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+
2672 "PCD entry %s in module %s!",
2675 throw new EntityException(exceptionString
);
2678 dynamicPcdBuildDataArray
= dynamicPcdBuildDefinitions
.getPcdBuildDataList();
2679 for (index
= 0; index
< dynamicPcdBuildDataArray
.size(); index
++) {
2680 //String tokenSpaceGuidString = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName())[1];
2681 String tokenSpaceGuidString
= null;
2683 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(dynamicPcdBuildDataArray
.get(index
).getTokenSpaceGuidCName());
2684 } catch (Exception e
) {
2685 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName());
2688 if (tokenSpaceStrRet
== null) {
2689 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName());
2692 dynamicPrimaryKey
= Token
.getPrimaryKeyString(dynamicPcdBuildDataArray
.get(index
).getCName(),
2693 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
2694 if (dynamicPrimaryKey
.equalsIgnoreCase(token
.getPrimaryKeyString())) {
2695 return dynamicPcdBuildDataArray
.get(index
);
2703 Update dynamic information for PCD entry.
2705 Dynamic information is retrieved from <PcdDynamicBuildDeclarations> in
2708 @param moduleName The name of the module who use this PCD
2709 @param token The token instance
2710 @param datum The <datum> in module's PCD information
2711 @param maxDatumSize The <maxDatumSize> in module's PCD information
2715 private Token
updateDynamicInformation(String moduleName
,
2719 throws EntityException
{
2722 String exceptionString
= null;
2723 DynamicTokenValue dynamicValue
;
2724 SkuInstance skuInstance
= null;
2726 boolean hasSkuId0
= false;
2727 Token
.PCD_TYPE pcdType
= Token
.PCD_TYPE
.UNKNOWN
;
2728 long tokenNumber
= 0;
2729 String hiiDefaultValue
= null;
2730 String
[] variableGuidString
= null;
2732 List
<DynamicPcdBuildDefinitions
.PcdBuildData
.SkuInfo
> skuInfoList
= null;
2733 DynamicPcdBuildDefinitions
.PcdBuildData dynamicInfo
= null;
2735 dynamicInfo
= getDynamicInfoFromFPD(token
, moduleName
);
2736 if (dynamicInfo
== null) {
2737 exceptionString
= String
.format("[FPD file error] For Dynamic PCD %s used by module %s, "+
2738 "there is no dynamic information in <DynamicPcdBuildDefinitions> "+
2739 "in FPD file, but it is required!",
2742 throw new EntityException(exceptionString
);
2745 token
.datumSize
= dynamicInfo
.getMaxDatumSize();
2747 exceptionString
= verifyDatum(token
.cName
,
2752 if (exceptionString
!= null) {
2753 throw new EntityException(exceptionString
);
2756 if ((maxDatumSize
!= 0) &&
2757 (maxDatumSize
!= token
.datumSize
)) {
2758 exceptionString
= String
.format("FPD file error] For dynamic PCD %s, the datum size in module %s is %d, but "+
2759 "the datum size in <DynamicPcdBuildDefinitions> is %d, they are not match!",
2763 dynamicInfo
.getMaxDatumSize());
2764 throw new EntityException(exceptionString
);
2766 tokenNumber
= Long
.decode(dynamicInfo
.getToken().toString());
2767 if (tokenNumber
!= token
.tokenNumber
) {
2768 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s, the token number in module %s is 0x%x, but"+
2769 "in <DynamicPcdBuildDefinictions>, the token number is 0x%x, they are not match!",
2774 throw new EntityException(exceptionString
);
2777 pcdType
= Token
.getpcdTypeFromString(dynamicInfo
.getItemType().toString());
2778 if (pcdType
== Token
.PCD_TYPE
.DYNAMIC_EX
) {
2779 token
.dynamicExTokenNumber
= tokenNumber
;
2782 skuInfoList
= dynamicInfo
.getSkuInfoList();
2785 // Loop all sku data
2787 for (index
= 0; index
< skuInfoList
.size(); index
++) {
2788 skuInstance
= new SkuInstance();
2790 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.
2792 temp
= skuInfoList
.get(index
).getSkuId().toString();
2793 skuInstance
.id
= Integer
.decode(temp
);
2794 if (skuInstance
.id
== 0) {
2798 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.
2800 if (skuInfoList
.get(index
).getValue() != null) {
2801 skuInstance
.value
.setValue(skuInfoList
.get(index
).getValue().toString());
2802 if ((exceptionString
= verifyDatum(token
.cName
,
2804 skuInfoList
.get(index
).getValue().toString(),
2806 token
.datumSize
)) != null) {
2807 throw new EntityException(exceptionString
);
2810 token
.skuData
.add(skuInstance
);
2813 // Judege wether is same of datum between module's information
2814 // and dynamic information.
2816 if (datum
!= null) {
2817 if ((skuInstance
.id
== 0) &&
2818 !datum
.toString().equalsIgnoreCase(skuInfoList
.get(index
).getValue().toString())) {
2819 exceptionString
= "[FPD file error] For dynamic PCD " + token
.cName
+ ", the value in module " + moduleName
+ " is " + datum
.toString() + " but the "+
2820 "value of sku 0 data in <DynamicPcdBuildDefinition> is " + skuInstance
.value
.value
+ ". They are must be same!"+
2821 " or you could not define value for a dynamic PCD in every <ModuleSA>!";
2822 throw new EntityException(exceptionString
);
2829 // Judge whether is HII group case.
2831 if (skuInfoList
.get(index
).getVariableName() != null) {
2832 exceptionString
= null;
2833 if (skuInfoList
.get(index
).getVariableGuid() == null) {
2834 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2835 "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",
2838 if (exceptionString
!= null) {
2839 throw new EntityException(exceptionString
);
2843 if (skuInfoList
.get(index
).getVariableOffset() == null) {
2844 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2845 "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",
2848 if (exceptionString
!= null) {
2849 throw new EntityException(exceptionString
);
2853 if (skuInfoList
.get(index
).getHiiDefaultValue() == null) {
2854 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2855 "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",
2858 if (exceptionString
!= null) {
2859 throw new EntityException(exceptionString
);
2863 if (skuInfoList
.get(index
).getHiiDefaultValue() != null) {
2864 hiiDefaultValue
= skuInfoList
.get(index
).getHiiDefaultValue().toString();
2866 hiiDefaultValue
= null;
2869 if ((exceptionString
= verifyDatum(token
.cName
,
2873 token
.datumSize
)) != null) {
2874 throw new EntityException(exceptionString
);
2877 offset
= Integer
.decode(skuInfoList
.get(index
).getVariableOffset());
2878 if (offset
> 0xFFFF) {
2879 throw new EntityException(String
.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+
2880 "exceed 64K, it is not allowed!",
2886 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.
2888 variableGuidString
= GlobalData
.getGuidInfoFromCname(skuInfoList
.get(index
).getVariableGuid().toString());
2889 if (variableGuidString
== null) {
2890 throw new EntityException(String
.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",
2892 skuInfoList
.get(index
).getVariableGuid().toString()));
2894 String variableStr
= skuInfoList
.get(index
).getVariableName();
2895 Pattern pattern
= Pattern
.compile("0x([a-fA-F0-9]){4}");
2896 Matcher matcher
= pattern
.matcher(variableStr
);
2897 List
<String
> varNameList
= new ArrayList
<String
>();
2898 while (matcher
.find()){
2899 String str
= variableStr
.substring(matcher
.start(),matcher
.end());
2900 varNameList
.add(str
);
2903 skuInstance
.value
.setHiiData(varNameList
,
2904 translateSchemaStringToUUID(variableGuidString
[1]),
2905 skuInfoList
.get(index
).getVariableOffset(),
2906 skuInfoList
.get(index
).getHiiDefaultValue().toString());
2907 token
.skuData
.add(skuInstance
);
2911 if (skuInfoList
.get(index
).getVpdOffset() != null) {
2912 skuInstance
.value
.setVpdData(skuInfoList
.get(index
).getVpdOffset());
2913 token
.skuData
.add(skuInstance
);
2917 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+
2918 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",
2920 throw new EntityException(exceptionString
);
2924 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+
2925 "no sku id = 0 data, which is required for every dynamic PCD",
2927 throw new EntityException(exceptionString
);
2934 Translate the schema string to UUID instance.
2936 In schema, the string of UUID is defined as following two types string:
2937 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(
2938 )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?
2940 2) GuidNamingConvention: pattern =
2941 [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}
2943 This function will convert string and create uuid instance.
2945 @param uuidString UUID string in XML file
2947 @return UUID UUID instance
2949 private UUID
translateSchemaStringToUUID(String uuidString
)
2950 throws EntityException
{
2952 String
[] splitStringArray
;
2957 if (uuidString
== null) {
2961 if (uuidString
.length() == 0) {
2965 if (uuidString
.equals("0") ||
2966 uuidString
.equalsIgnoreCase("0x0")) {
2967 return new UUID(0, 0);
2970 uuidString
= uuidString
.replaceAll("\\{", "");
2971 uuidString
= uuidString
.replaceAll("\\}", "");
2974 // If the UUID schema string is GuidArrayType type then need translate
2975 // to GuidNamingConvention type at first.
2977 if ((uuidString
.charAt(0) == '0') && ((uuidString
.charAt(1) == 'x') || (uuidString
.charAt(1) == 'X'))) {
2978 splitStringArray
= uuidString
.split("," );
2979 if (splitStringArray
.length
!= 11) {
2980 throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString
);
2984 // Remove blank space from these string and remove header string "0x"
2986 for (index
= 0; index
< 11; index
++) {
2987 splitStringArray
[index
] = splitStringArray
[index
].trim();
2988 splitStringArray
[index
] = splitStringArray
[index
].substring(2, splitStringArray
[index
].length());
2992 // Add heading '0' to normalize the string length
2994 for (index
= 3; index
< 11; index
++) {
2995 chLen
= splitStringArray
[index
].length();
2996 for (chIndex
= 0; chIndex
< 2 - chLen
; chIndex
++) {
2997 splitStringArray
[index
] = "0" + splitStringArray
[index
];
3002 // construct the final GuidNamingConvention string
3004 temp
= String
.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",
3005 splitStringArray
[0],
3006 splitStringArray
[1],
3007 splitStringArray
[2],
3008 splitStringArray
[3],
3009 splitStringArray
[4],
3010 splitStringArray
[5],
3011 splitStringArray
[6],
3012 splitStringArray
[7],
3013 splitStringArray
[8],
3014 splitStringArray
[9],
3015 splitStringArray
[10]);
3019 return UUID
.fromString(uuidString
);
3023 check parameter for this action.
3025 @throws EntityException Bad parameter.
3027 private void checkParameter() throws EntityException
{
3030 if((fpdFilePath
== null) ||(workspacePath
== null)) {
3031 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
3034 if(fpdFilePath
.length() == 0 || workspacePath
.length() == 0) {
3035 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
3038 file
= new File(workspacePath
);
3039 if(!file
.exists()) {
3040 throw new EntityException("WorkpacePath " + workspacePath
+ " does not exist!");
3043 file
= new File(fpdFilePath
);
3045 if(!file
.exists()) {
3046 throw new EntityException("FPD File " + fpdFilePath
+ " does not exist!");
3053 @param argv parameter from command line
3055 public static void main(String argv
[]) throws EntityException
{
3056 CollectPCDAction ca
= new CollectPCDAction();
3057 String projectDir
= "x:/edk2";
3058 ca
.setWorkspacePath(projectDir
);
3059 ca
.setFPDFilePath(projectDir
+ "/EdkNt32Pkg/Nt32.fpd");
3060 ca
.setActionMessageLevel(ActionMessage
.MAX_MESSAGE_LEVEL
);
3061 GlobalData
.initInfo("Tools" + File
.separator
+ "Conf" + File
.separator
+ "FrameworkDatabase.db",
3064 System
.out
.println("After initInfo!");
3065 FpdParserTask fpt
= new FpdParserTask();
3066 fpt
.parseFpdFile(new File(projectDir
+ "/EdkNt32Pkg/Nt32.fpd"));