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
<Integer
> al
;
233 private ArrayList
<String
> alComments
;
234 private String phase
;
237 public SizeTable (String phase
) {
239 al
= new ArrayList
<Integer
>();
240 alComments
= new ArrayList
<String
>();
244 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
245 final String name
= "SizeTable";
247 CStructTypeDeclaration decl
;
250 cCode
= String
.format(PcdDatabase
.SizeTableDeclaration
, phase
);
251 decl
= new CStructTypeDeclaration (
260 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
261 instTable
.put(name
, cCode
);
264 private ArrayList
<String
> getInstantiation () {
265 ArrayList
<String
> Output
= new ArrayList
<String
>();
267 Output
.add("/* SizeTable */");
269 if (al
.size() == 0) {
272 for (int index
= 0; index
< al
.size(); index
++) {
273 Integer n
= al
.get(index
);
274 String str
= "\t" + n
.toString();
276 if (index
!= (al
.size() - 1)) {
280 str
+= " /* " + alComments
.get(index
) + " */";
290 public int add (Token token
) {
294 al
.add(token
.datumSize
);
295 alComments
.add(token
.getPrimaryKeyString());
300 public int getTableLen () {
301 return al
.size() == 0 ?
1 : al
.size();
309 This class is used to store the GUIDs in a PCD database.
312 private ArrayList
<UUID
> al
;
313 private ArrayList
<String
> alComments
;
314 private String phase
;
316 private int bodyLineNum
;
318 public GuidTable (String phase
) {
320 al
= new ArrayList
<UUID
>();
321 alComments
= new ArrayList
<String
>();
326 public String
getSizeMacro () {
327 return String
.format(PcdDatabase
.GuidTableSizeMacro
, phase
, getSize());
330 private int getSize () {
331 return (al
.size() == 0)?
1 : al
.size();
334 public String
getExistanceMacro () {
335 return String
.format(PcdDatabase
.GuidTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
338 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
339 final String name
= "GuidTable";
341 CStructTypeDeclaration decl
;
344 cCode
+= String
.format(PcdDatabase
.GuidTableDeclaration
, phase
);
345 decl
= new CStructTypeDeclaration (
354 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
355 instTable
.put(name
, cCode
);
358 private String
getUuidCString (UUID uuid
) {
359 String
[] guidStrArray
;
361 guidStrArray
=(uuid
.toString()).split("-");
363 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}}",
367 (guidStrArray
[3].substring(0, 2)),
368 (guidStrArray
[3].substring(2, 4)),
369 (guidStrArray
[4].substring(0, 2)),
370 (guidStrArray
[4].substring(2, 4)),
371 (guidStrArray
[4].substring(4, 6)),
372 (guidStrArray
[4].substring(6, 8)),
373 (guidStrArray
[4].substring(8, 10)),
374 (guidStrArray
[4].substring(10, 12))
378 private ArrayList
<String
> getInstantiation () {
379 ArrayList
<String
> Output
= new ArrayList
<String
>();
381 Output
.add("/* GuidTable */");
384 if (al
.size() == 0) {
385 Output
.add("\t" + getUuidCString(new UUID(0, 0)));
388 for (int i
= 0; i
< al
.size(); i
++) {
389 String str
= "\t" + getUuidCString(al
.get(i
));
391 str
+= "/* " + alComments
.get(i
) + " */";
392 if (i
!= (al
.size() - 1)) {
404 public int add (UUID uuid
, String name
) {
406 // Check if GuidTable has this entry already.
407 // If so, return the GuidTable index.
409 for (int i
= 0; i
< al
.size(); i
++) {
410 if (al
.get(i
).equals(uuid
)) {
417 alComments
.add(name
);
420 // Return the previous Table Index
430 This class is used to store the SKU IDs in a PCD database.
434 private ArrayList
<Integer
[]> al
;
435 private ArrayList
<String
> alComment
;
436 private String phase
;
439 public SkuIdTable (String phase
) {
441 al
= new ArrayList
<Integer
[]>();
442 alComment
= new ArrayList
<String
>();
446 public String
getSizeMacro () {
447 return String
.format(PcdDatabase
.SkuIdTableSizeMacro
, phase
, getSize());
450 private int getSize () {
451 return (len
== 0)?
1 : len
;
454 public String
getExistanceMacro () {
455 return String
.format(PcdDatabase
.SkuTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
458 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
459 final String name
= "SkuIdTable";
461 CStructTypeDeclaration decl
;
464 cCode
+= String
.format(PcdDatabase
.SkuIdTableDeclaration
, phase
);
465 decl
= new CStructTypeDeclaration (
474 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
475 instTable
.put(name
, cCode
);
478 // SystemSkuId is in PEI phase PCD Database
480 if (phase
.equalsIgnoreCase("PEI")) {
481 decl
= new CStructTypeDeclaration (
484 String
.format("%-20sSystemSkuId;\r\n", "SKU_ID"),
489 instTable
.put("SystemSkuId", "0");
494 private ArrayList
<String
> getInstantiation () {
495 ArrayList
<String
> Output
= new ArrayList
<String
> ();
497 Output
.add("/* SkuIdTable */");
500 if (al
.size() == 0) {
504 for (int index
= 0; index
< al
.size(); index
++) {
507 str
= "/* " + alComment
.get(index
) + "*/ ";
508 str
+= "/* MaxSku */ ";
511 Integer
[] ia
= al
.get(index
);
513 str
+= "\t" + ia
[0].toString() + ", ";
514 for (int index2
= 1; index2
< ia
.length
; index2
++) {
515 str
+= ia
[index2
].toString();
516 if (!((index2
== ia
.length
- 1) && (index
== al
.size() - 1))) {
530 public int add (Token token
) {
536 // Check if this SKU_ID Array is already in the table
540 Integer
[] s
= (Integer
[]) o
;
541 boolean different
= false;
542 if (s
[0] == token
.getSkuIdCount()) {
543 for (index
= 1; index
< s
.length
; index
++) {
544 if (s
[index
] != token
.skuData
.get(index
-1).id
) {
559 Integer
[] skuIds
= new Integer
[token
.skuData
.size() + 1];
560 skuIds
[0] = new Integer(token
.skuData
.size());
561 for (index
= 1; index
< skuIds
.length
; index
++) {
562 skuIds
[index
] = new Integer(token
.skuData
.get(index
- 1).id
);
567 len
+= skuIds
.length
;
569 alComment
.add(token
.getPrimaryKeyString());
576 class LocalTokenNumberTable
{
577 private ArrayList
<String
> al
;
578 private ArrayList
<String
> alComment
;
579 private String phase
;
582 public LocalTokenNumberTable (String phase
) {
584 al
= new ArrayList
<String
>();
585 alComment
= new ArrayList
<String
>();
590 public String
getSizeMacro () {
591 return String
.format(PcdDatabase
.LocalTokenNumberTableSizeMacro
, phase
, getSize())
592 + String
.format(PcdDatabase
.LocalTokenNumberSizeMacro
, phase
, al
.size());
595 public int getSize () {
596 return (al
.size() == 0)?
1 : al
.size();
599 public String
getExistanceMacro () {
600 return String
.format(PcdDatabase
.DatabaseExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
603 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
604 final String name
= "LocalTokenNumberTable";
606 CStructTypeDeclaration decl
;
609 cCode
+= String
.format(PcdDatabase
.LocalTokenNumberTableDeclaration
, phase
);
610 decl
= new CStructTypeDeclaration (
618 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
619 instTable
.put(name
, cCode
);
622 private ArrayList
<String
> getInstantiation () {
623 ArrayList
<String
> output
= new ArrayList
<String
>();
625 output
.add("/* LocalTokenNumberTable */");
628 if (al
.size() == 0) {
632 for (int index
= 0; index
< al
.size(); index
++) {
635 str
= "\t" + (String
)al
.get(index
);
637 str
+= " /* " + alComment
.get(index
) + " */ ";
640 if (index
!= (al
.size() - 1)) {
653 public int add (Token token
) {
659 str
= String
.format(PcdDatabase
.offsetOfStrTemplate
, phase
, token
.hasDefaultValue() ?
"Init" : "Uninit", token
.getPrimaryKeyString());
661 if (token
.isUnicodeStringType()) {
662 str
+= " | PCD_TYPE_STRING";
665 if (token
.isSkuEnable()) {
666 str
+= " | PCD_TYPE_SKU_ENABLED";
669 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
670 str
+= " | PCD_TYPE_HII";
673 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
674 str
+= " | PCD_TYPE_VPD";
678 alComment
.add(token
.getPrimaryKeyString());
687 This class is used to store the table of mapping information
688 between DynamicEX ID pair(Guid, TokenNumber) and
689 the local token number assigned by PcdDatabase class.
696 This class is used to store the mapping information
697 between DynamicEX ID pair(Guid, TokenNumber) and
698 the local token number assigned by PcdDatabase class.
701 public Integer guidTableIdx
;
702 public Long exTokenNumber
;
703 public Long localTokenIdx
;
705 public ExTriplet (int guidTableIdx
, long exTokenNumber
, long localTokenIdx
) {
706 this.guidTableIdx
= new Integer(guidTableIdx
);
707 this.exTokenNumber
= new Long(exTokenNumber
);
708 this.localTokenIdx
= new Long(localTokenIdx
);
712 private ArrayList
<ExTriplet
> al
;
713 private ArrayList
<String
> alComment
;
714 private String phase
;
716 private int bodyLineNum
;
718 public ExMapTable (String phase
) {
720 al
= new ArrayList
<ExTriplet
>();
721 alComment
= new ArrayList
<String
>();
726 public String
getSizeMacro () {
727 return String
.format(PcdDatabase
.ExMapTableSizeMacro
, phase
, getTableLen())
728 + String
.format(PcdDatabase
.ExTokenNumber
, phase
, al
.size());
731 public String
getExistanceMacro () {
732 return String
.format(PcdDatabase
.ExMapTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
735 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
736 final String exMapTableName
= "ExMapTable";
740 CStructTypeDeclaration decl
;
743 cCode
+= String
.format(PcdDatabase
.ExMapTableDeclaration
, phase
);
744 decl
= new CStructTypeDeclaration (
753 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
754 instTable
.put(exMapTableName
, cCode
);
757 private ArrayList
<String
> getInstantiation () {
758 ArrayList
<String
> Output
= new ArrayList
<String
>();
760 Output
.add("/* ExMapTable */");
762 if (al
.size() == 0) {
763 Output
.add("\t{0, 0, 0}");
767 for (index
= 0; index
< al
.size(); index
++) {
770 ExTriplet e
= (ExTriplet
)al
.get(index
);
772 str
= "\t" + "{ " + String
.format("0x%08X", e
.exTokenNumber
) + ", ";
773 str
+= e
.localTokenIdx
.toString() + ", ";
774 str
+= e
.guidTableIdx
.toString();
776 str
+= "}" + " /* " + alComment
.get(index
) + " */" ;
778 if (index
!= al
.size() - 1) {
792 public int add (int localTokenIdx
, long exTokenNum
, int guidTableIdx
, String name
) {
796 al
.add(new ExTriplet(guidTableIdx
, exTokenNum
, localTokenIdx
));
802 private int getTableLen () {
803 return al
.size() == 0 ?
1 : al
.size();
807 // To simplify the algorithm for GetNextToken and GetNextTokenSpace in
808 // PCD PEIM/Driver, we need to sort the ExMapTable according to the
813 class ExTripletComp
implements Comparator
<ExTriplet
> {
814 public int compare (ExTriplet a
, ExTriplet b
) {
815 if (a
.guidTableIdx
== b
.guidTableIdx
) {
817 // exTokenNumber is long, we can't use simple substraction.
819 if (a
.exTokenNumber
> b
.exTokenNumber
) {
821 } else if (a
.exTokenNumber
== b
.exTokenNumber
) {
828 return a
.guidTableIdx
- b
.guidTableIdx
;
832 private void sortTable () {
833 java
.util
.Comparator
<ExTriplet
> comparator
= new ExTripletComp();
834 java
.util
.Collections
.sort(al
, comparator
);
841 This class is used to generate C code for Autogen.h and Autogen.c of
842 a PCD service DXE driver and PCD service PEIM.
846 private final static int SkuHeadAlignmentSize
= 4;
847 private final String newLine
= "\r\n";
848 private final String commaNewLine
= ",\r\n";
849 private final String tab
= "\t";
850 public final static String ExMapTableDeclaration
= "DYNAMICEX_MAPPING ExMapTable[%s_EXMAPPING_TABLE_SIZE];\r\n";
851 public final static String GuidTableDeclaration
= "EFI_GUID GuidTable[%s_GUID_TABLE_SIZE];\r\n";
852 public final static String LocalTokenNumberTableDeclaration
= "UINT32 LocalTokenNumberTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";
853 public final static String StringTableDeclaration
= "UINT16 StringTable[%s_STRING_TABLE_SIZE];\r\n";
854 public final static String SizeTableDeclaration
= "UINT16 SizeTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";
855 public final static String SkuIdTableDeclaration
= "UINT8 SkuIdTable[%s_SKUID_TABLE_SIZE];\r\n";
858 public final static String ExMapTableSizeMacro
= "#define %s_EXMAPPING_TABLE_SIZE %d\r\n";
859 public final static String ExTokenNumber
= "#define %s_EX_TOKEN_NUMBER %d\r\n";
860 public final static String GuidTableSizeMacro
= "#define %s_GUID_TABLE_SIZE %d\r\n";
861 public final static String LocalTokenNumberTableSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER_TABLE_SIZE %d\r\n";
862 public final static String LocalTokenNumberSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER %d\r\n";
863 public final static String StringTableSizeMacro
= "#define %s_STRING_TABLE_SIZE %d\r\n";
864 public final static String SkuIdTableSizeMacro
= "#define %s_SKUID_TABLE_SIZE %d\r\n";
867 public final static String ExMapTableExistenceMacro
= "#define %s_EXMAP_TABLE_EMPTY %s\r\n";
868 public final static String GuidTableExistenceMacro
= "#define %s_GUID_TABLE_EMPTY %s\r\n";
869 public final static String DatabaseExistenceMacro
= "#define %s_DATABASE_EMPTY %s\r\n";
870 public final static String StringTableExistenceMacro
= "#define %s_STRING_TABLE_EMPTY %s\r\n";
871 public final static String SkuTableExistenceMacro
= "#define %s_SKUID_TABLE_EMPTY %s\r\n";
873 public final static String offsetOfSkuHeadStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)";
874 public final static String offsetOfVariableEnabledDefault
= "offsetof(%s_PCD_DATABASE, %s.%s_VariableDefault_%d)";
875 public final static String offsetOfStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s)";
877 private final static String skuDataTableTemplate
= "SkuDataTable";
880 private StringTable stringTable
;
881 private GuidTable guidTable
;
882 private LocalTokenNumberTable localTokenNumberTable
;
883 private SkuIdTable skuIdTable
;
884 private SizeTable sizeTable
;
885 private ExMapTable exMapTable
;
887 private ArrayList
<Token
> alTokens
;
888 private String phase
;
889 private int assignedTokenNumber
;
892 // Use two class global variable to store
895 private String privateGlobalName
;
896 private String privateGlobalCCode
;
898 // After Major changes done to the PCD
899 // database generation class PcdDatabase
900 // Please increment the version and please
901 // also update the version number in PCD
902 // service PEIM and DXE driver accordingly.
904 private final int version
= 2;
906 private String hString
;
907 private String cString
;
910 Constructor for PcdDatabase class.
912 <p>We have two PCD dynamic(ex) database for the Framework implementation. One
913 for PEI phase and the other for DXE phase. </p>
915 @param alTokens A ArrayList of Dynamic(EX) PCD entry.
916 @param exePhase The phase to generate PCD database for: valid input
918 @param startLen The starting Local Token Number for the PCD database. For
919 PEI phase, the starting Local Token Number starts from 0.
920 For DXE phase, the starting Local Token Number starts
921 from the total number of PCD entry of PEI phase.
924 public PcdDatabase (ArrayList
<Token
> alTokens
, String exePhase
, int startLen
) {
927 stringTable
= new StringTable(phase
);
928 guidTable
= new GuidTable(phase
);
929 localTokenNumberTable
= new LocalTokenNumberTable(phase
);
930 skuIdTable
= new SkuIdTable(phase
);
931 sizeTable
= new SizeTable(phase
);
932 exMapTable
= new ExMapTable(phase
);
935 // Local token number 0 is reserved for INVALID_TOKEN_NUMBER.
936 // So we will increment 1 for the startLen passed from the
939 assignedTokenNumber
= startLen
+ 1;
940 this.alTokens
= alTokens
;
943 private void getNonExAndExTokens (ArrayList
<Token
> alTokens
, List
<Token
> nexTokens
, List
<Token
> exTokens
) {
944 for (int i
= 0; i
< alTokens
.size(); i
++) {
945 Token t
= (Token
)alTokens
.get(i
);
946 if (t
.isDynamicEx()) {
956 private int getDataTypeAlignmentSize (Token token
) {
957 switch (token
.datumType
) {
975 private int getHiiPtrTypeAlignmentSize(Token token
) {
976 switch (token
.datumType
) {
986 if (token
.isHiiEnable()) {
987 if (token
.isHiiDefaultValueUnicodeStringType()) {
999 private int getAlignmentSize (Token token
) {
1000 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
1004 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
1008 if (token
.isUnicodeStringType()) {
1012 return getDataTypeAlignmentSize(token
);
1015 public String
getCString () {
1019 public String
getHString () {
1023 private void genCodeWorker(Token t
,
1024 ArrayList
<CStructTypeDeclaration
> declaList
,
1025 HashMap
<String
, String
> instTable
, String phase
)
1026 throws EntityException
{
1028 CStructTypeDeclaration decl
;
1031 // Insert SKU_HEAD if isSkuEnable is true
1033 if (t
.isSkuEnable()) {
1035 tableIdx
= skuIdTable
.add(t
);
1036 decl
= new CStructTypeDeclaration(t
.getPrimaryKeyString(),
1037 SkuHeadAlignmentSize
, getSkuEnabledTypeDeclaration(t
), true);
1038 declaList
.add(decl
);
1039 instTable
.put(t
.getPrimaryKeyString(),
1040 getSkuEnabledTypeInstantiaion(t
, tableIdx
));
1044 // Insert PCD_ENTRY declaration and instantiation
1046 getCDeclarationString(t
);
1048 decl
= new CStructTypeDeclaration(privateGlobalName
,
1049 getAlignmentSize(t
), privateGlobalCCode
, t
.hasDefaultValue());
1050 declaList
.add(decl
);
1052 if (t
.hasDefaultValue()) {
1053 instTable
.put(privateGlobalName
,
1054 getTypeInstantiation(t
, declaList
, instTable
, phase
)
1060 private void ProcessTokens (List
<Token
> tokens
,
1061 ArrayList
<CStructTypeDeclaration
> cStructDeclList
,
1062 HashMap
<String
, String
> cStructInstTable
,
1065 throws EntityException
{
1067 for (int idx
= 0; idx
< tokens
.size(); idx
++) {
1068 Token t
= tokens
.get(idx
);
1070 genCodeWorker (t
, cStructDeclList
, cStructInstTable
, phase
);
1073 localTokenNumberTable
.add(t
);
1074 t
.tokenNumber
= assignedTokenNumber
++;
1077 // Add a mapping if this dynamic PCD entry is a EX type
1079 if (t
.isDynamicEx()) {
1080 exMapTable
.add((int)t
.tokenNumber
,
1081 t
.dynamicExTokenNumber
,
1082 guidTable
.add(t
.tokenSpaceName
, t
.getPrimaryKeyString()),
1083 t
.getPrimaryKeyString()
1090 public void genCode () throws EntityException
{
1092 ArrayList
<CStructTypeDeclaration
> cStructDeclList
= new ArrayList
<CStructTypeDeclaration
>();
1093 HashMap
<String
, String
> cStructInstTable
= new HashMap
<String
, String
>();
1095 List
<Token
> nexTokens
= new ArrayList
<Token
> ();
1096 List
<Token
> exTokens
= new ArrayList
<Token
> ();
1098 getNonExAndExTokens (alTokens
, nexTokens
, exTokens
);
1101 // We have to process Non-Ex type PCD entry first. The reason is
1102 // that our optimization assumes that the Token Number of Non-Ex
1103 // PCD entry start from 1 (for PEI phase) and grows continously upwards.
1105 // EX type token number starts from the last Non-EX PCD entry and
1106 // grows continously upwards.
1108 ProcessTokens (nexTokens
, cStructDeclList
, cStructInstTable
, phase
);
1109 ProcessTokens (exTokens
, cStructDeclList
, cStructInstTable
, phase
);
1111 stringTable
.genCode(cStructDeclList
, cStructInstTable
);
1112 skuIdTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1113 exMapTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1114 localTokenNumberTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1115 sizeTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1116 guidTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1118 hString
= genCMacroCode ();
1120 HashMap
<String
, String
> result
;
1122 result
= genCStructCode(cStructDeclList
,
1127 hString
+= result
.get("initDeclStr");
1128 hString
+= result
.get("uninitDeclStr");
1130 hString
+= String
.format("#define PCD_%s_SERVICE_DRIVER_VERSION %d", phase
, version
);
1132 cString
= newLine
+ newLine
+ result
.get("initInstStr");
1136 private String
genCMacroCode () {
1137 String macroStr
= "";
1140 // Generate size info Macro for all Tables
1142 macroStr
+= guidTable
.getSizeMacro();
1143 macroStr
+= stringTable
.getSizeMacro();
1144 macroStr
+= skuIdTable
.getSizeMacro();
1145 macroStr
+= localTokenNumberTable
.getSizeMacro();
1146 macroStr
+= exMapTable
.getSizeMacro();
1149 // Generate existance info Macro for all Tables
1151 macroStr
+= guidTable
.getExistanceMacro();
1152 macroStr
+= stringTable
.getExistanceMacro();
1153 macroStr
+= skuIdTable
.getExistanceMacro();
1154 macroStr
+= localTokenNumberTable
.getExistanceMacro();
1155 macroStr
+= exMapTable
.getExistanceMacro();
1157 macroStr
+= newLine
;
1162 private HashMap
<String
, String
> genCStructCode(
1163 ArrayList
<CStructTypeDeclaration
> declaList
,
1164 HashMap
<String
, String
> instTable
,
1169 HashMap
<String
, String
> result
= new HashMap
<String
, String
>();
1170 HashMap
<Integer
, ArrayList
<String
>> alignmentInitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1171 HashMap
<Integer
, ArrayList
<String
>> alignmentUninitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1172 HashMap
<Integer
, ArrayList
<String
>> alignmentInitInst
= new HashMap
<Integer
, ArrayList
<String
>>();
1175 // Initialize the storage for each alignment
1177 for (i
= 8; i
> 0; i
>>=1) {
1178 alignmentInitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1179 alignmentInitInst
.put(new Integer(i
), new ArrayList
<String
>());
1180 alignmentUninitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1183 String initDeclStr
= "typedef struct {" + newLine
;
1184 String initInstStr
= String
.format("%s_PCD_DATABASE_INIT g%sPcdDbInit = { ", phase
.toUpperCase(), phase
.toUpperCase()) + newLine
;
1185 String uninitDeclStr
= "typedef struct {" + newLine
;
1188 // Sort all C declaration and instantiation base on Alignment Size
1190 for (Object d
: declaList
) {
1191 CStructTypeDeclaration decl
= (CStructTypeDeclaration
) d
;
1193 if (decl
.initTable
) {
1194 alignmentInitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1195 alignmentInitInst
.get(new Integer(decl
.alignmentSize
)).add(instTable
.get(decl
.key
));
1197 alignmentUninitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1202 // Generate code for every alignment size
1204 boolean uinitDatabaseEmpty
= true;
1205 for (int align
= 8; align
> 0; align
>>= 1) {
1206 ArrayList
<String
> declaListBasedOnAlignment
= alignmentInitDecl
.get(new Integer(align
));
1207 ArrayList
<String
> instListBasedOnAlignment
= alignmentInitInst
.get(new Integer(align
));
1208 for (i
= 0; i
< declaListBasedOnAlignment
.size(); i
++) {
1209 initDeclStr
+= tab
+ declaListBasedOnAlignment
.get(i
);
1210 initInstStr
+= tab
+ instListBasedOnAlignment
.get(i
);
1213 // We made a assumption that both PEI_PCD_DATABASE and DXE_PCD_DATABASE
1214 // has a least one data memember with alignment size of 1. So we can
1215 // remove the last "," in the C structure instantiation string. Luckily,
1216 // this is true as both data structure has SKUID_TABLE anyway.
1218 if ((align
== 1) && (i
== declaListBasedOnAlignment
.size() - 1)) {
1219 initInstStr
+= newLine
;
1221 initInstStr
+= commaNewLine
;
1225 declaListBasedOnAlignment
= alignmentUninitDecl
.get(new Integer(align
));
1227 if (declaListBasedOnAlignment
.size() != 0) {
1228 uinitDatabaseEmpty
= false;
1231 for (Object d
: declaListBasedOnAlignment
) {
1232 String s
= (String
)d
;
1233 uninitDeclStr
+= tab
+ s
;
1237 if (uinitDatabaseEmpty
) {
1238 uninitDeclStr
+= tab
+ String
.format("%-20sdummy; /* PCD_DATABASE_UNINIT is emptry */\r\n", "UINT8");
1241 initDeclStr
+= String
.format("} %s_PCD_DATABASE_INIT;", phase
) + newLine
+ newLine
;
1242 initInstStr
+= "};" + newLine
;
1243 uninitDeclStr
+= String
.format("} %s_PCD_DATABASE_UNINIT;", phase
) + newLine
+ newLine
;
1245 result
.put("initDeclStr", initDeclStr
);
1246 result
.put("initInstStr", initInstStr
);
1247 result
.put("uninitDeclStr", uninitDeclStr
);
1252 public static String
genInstantiationStr (ArrayList
<String
> alStr
) {
1254 for (int i
= 0; i
< alStr
.size(); i
++) {
1258 str
+= alStr
.get(i
);
1259 if (i
!= alStr
.size() - 1) {
1267 private String
getSkuEnabledTypeDeclaration (Token token
) {
1268 return String
.format("%-20s%s;\r\n", "SKU_HEAD", token
.getPrimaryKeyString());
1271 private String
getSkuEnabledTypeInstantiaion (Token token
, int SkuTableIdx
) {
1273 String offsetof
= String
.format(PcdDatabase
.offsetOfSkuHeadStrTemplate
, phase
, token
.hasDefaultValue()?
"Init" : "Uninit", token
.getPrimaryKeyString());
1274 return String
.format("{ %s, %d } /* SKU_ENABLED: %s */", offsetof
, SkuTableIdx
, token
.getPrimaryKeyString());
1277 private String
getDataTypeInstantiationForVariableDefault (Token token
, String cName
, int skuId
) {
1278 return String
.format("%s /* %s */", token
.skuData
.get(skuId
).value
.hiiDefaultValue
, cName
);
1281 private String
getCType (Token t
)
1282 throws EntityException
{
1284 if (t
.isHiiEnable()) {
1285 return "VARIABLE_HEAD";
1288 if (t
.isVpdEnable()) {
1292 if (t
.isUnicodeStringType()) {
1293 return "STRING_HEAD";
1296 switch (t
.datumType
) {
1310 throw new EntityException("Unknown type in getDataTypeCDeclaration");
1314 private void getCDeclarationString(Token t
)
1315 throws EntityException
{
1317 if (t
.isSkuEnable()) {
1318 privateGlobalName
= String
.format("%s_%s", t
.getPrimaryKeyString(), skuDataTableTemplate
);
1320 privateGlobalName
= t
.getPrimaryKeyString();
1323 String type
= getCType(t
);
1324 if ((t
.datumType
== Token
.DATUM_TYPE
.POINTER
) && (!t
.isHiiEnable())) {
1326 if (t
.isASCIIStringType()) {
1328 // Build tool will add a NULL string at the end of the ASCII string
1330 bufferSize
= t
.datumSize
+ 1;
1332 bufferSize
= t
.datumSize
;
1334 privateGlobalCCode
= String
.format("%-20s%s[%d][%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount(), bufferSize
);
1336 privateGlobalCCode
= String
.format("%-20s%s[%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount());
1340 private String
getDataTypeDeclarationForVariableDefault (Token token
, String cName
, int skuId
)
1341 throws EntityException
{
1345 if (token
.datumType
== Token
.DATUM_TYPE
.UINT8
) {
1347 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT16
) {
1349 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT32
) {
1351 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT64
) {
1353 } else if (token
.datumType
== Token
.DATUM_TYPE
.BOOLEAN
) {
1354 typeStr
= "BOOLEAN";
1355 } else if (token
.datumType
== Token
.DATUM_TYPE
.POINTER
) {
1357 if (token
.isHiiDefaultValueUnicodeStringType()) {
1360 // Include the NULL charactor
1362 size
= token
.datumSize
/ 2 + 1;
1365 if (token
.isHiiDefaultValueASCIIStringType()) {
1367 // Include the NULL charactor
1369 size
= token
.datumSize
+ 1;
1371 size
= token
.datumSize
;
1374 return String
.format("%-20s%s[%d];\r\n", typeStr
, cName
, size
);
1376 throw new EntityException("Unknown DATUM_TYPE type in when generating code for VARIABLE_ENABLED PCD entry");
1379 return String
.format("%-20s%s;\r\n", typeStr
, cName
);
1382 private String
getTypeInstantiation (Token t
, ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) throws EntityException
{
1387 s
= String
.format("/* %s */", t
.getPrimaryKeyString()) + newLine
;
1388 s
+= tab
+ "{" + newLine
;
1390 for (i
= 0; i
< t
.skuData
.size(); i
++) {
1391 if (t
.isUnicodeStringType()) {
1392 s
+= tab
+ tab
+ String
.format("{ %d }", stringTable
.add(t
.skuData
.get(i
).value
.value
, t
));
1393 } else if (t
.isHiiEnable()) {
1394 /* VPD_HEAD definition
1396 UINT16 GuidTableIndex; // Offset in Guid Table in units of GUID.
1397 UINT16 StringIndex; // Offset in String Table in units of UINT16.
1398 UINT16 Offset; // Offset in Variable
1399 UINT16 DefaultValueOffset; // Offset of the Default Value
1402 String variableDefaultName
= String
.format("%s_VariableDefault_%d", t
.getPrimaryKeyString(), i
);
1404 s
+= tab
+ tab
+ String
.format("{ %d, %d, %s, %s }", guidTable
.add(t
.skuData
.get(i
).value
.variableGuid
, t
.getPrimaryKeyString()),
1405 stringTable
.add(t
.skuData
.get(i
).value
.getStringOfVariableName(), t
),
1406 t
.skuData
.get(i
).value
.variableOffset
,
1407 String
.format("offsetof(%s_PCD_DATABASE, Init.%s)", phase
, variableDefaultName
)
1410 // We need to support the default value, so we add the declaration and
1411 // the instantiation for the default value.
1413 CStructTypeDeclaration decl
= new CStructTypeDeclaration (variableDefaultName
,
1414 getHiiPtrTypeAlignmentSize(t
),
1415 getDataTypeDeclarationForVariableDefault(t
, variableDefaultName
, i
),
1418 declaList
.add(decl
);
1419 instTable
.put(variableDefaultName
, getDataTypeInstantiationForVariableDefault (t
, variableDefaultName
, i
));
1420 } else if (t
.isVpdEnable()) {
1425 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.vpdOffset
);
1427 if (t
.isByteStreamType()) {
1429 // Byte stream type input has their own "{" "}", so we won't help to insert.
1431 s
+= tab
+ tab
+ String
.format(" %s ", t
.skuData
.get(i
).value
.value
);
1433 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.value
);
1437 if (i
!= t
.skuData
.size() - 1) {
1450 public static String
getPcdDatabaseCommonDefinitions ()
1451 throws EntityException
{
1455 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1456 "Tools" + File
.separator
+
1457 "Conf" + File
.separator
+
1458 "Pcd" + File
.separator
+
1459 "PcdDatabaseCommonDefinitions.sample");
1460 FileReader reader
= new FileReader(file
);
1461 BufferedReader in
= new BufferedReader(reader
);
1463 while ((str
= in
.readLine()) != null) {
1464 retStr
= retStr
+"\r\n" + str
;
1466 } catch (Exception ex
) {
1467 throw new EntityException("Fatal error when generating PcdDatabase Common Definitions");
1473 public static String
getPcdDxeDatabaseDefinitions ()
1474 throws EntityException
{
1478 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1479 "Tools" + File
.separator
+
1480 "Conf" + File
.separator
+
1481 "Pcd" + File
.separator
+
1482 "PcdDatabaseDxeDefinitions.sample");
1483 FileReader reader
= new FileReader(file
);
1484 BufferedReader in
= new BufferedReader(reader
);
1486 while ((str
= in
.readLine()) != null) {
1487 retStr
= retStr
+"\r\n" + str
;
1489 } catch (Exception ex
) {
1490 throw new EntityException("Fatal error when generating PcdDatabase Dxe Definitions");
1496 public static String
getPcdPeiDatabaseDefinitions ()
1497 throws EntityException
{
1501 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1502 "Tools" + File
.separator
+
1503 "Conf" + File
.separator
+
1504 "Pcd" + File
.separator
+
1505 "PcdDatabasePeiDefinitions.sample");
1506 FileReader reader
= new FileReader(file
);
1507 BufferedReader in
= new BufferedReader(reader
);
1509 while ((str
= in
.readLine()) != null) {
1510 retStr
= retStr
+"\r\n" + str
;
1512 } catch (Exception ex
) {
1513 throw new EntityException("Fatal error when generating PcdDatabase Pei Definitions");
1522 private String type
;
1523 private FpdModuleIdentification moduleId
;
1524 private PcdBuildDefinitionDocument
.PcdBuildDefinition pcdBuildDef
;
1528 public ModuleInfo (FpdModuleIdentification moduleId
, String type
, XmlObject pcdDef
) {
1529 this.moduleId
= moduleId
;
1531 this.pcdBuildDef
= ((PcdBuildDefinitionDocument
)pcdDef
).getPcdBuildDefinition();
1533 public String
getModuleType (){
1536 public FpdModuleIdentification
getModuleId (){
1537 return this.moduleId
;
1539 public PcdBuildDefinitionDocument
.PcdBuildDefinition
getPcdBuildDef(){
1540 return this.pcdBuildDef
;
1544 /** This action class is to collect PCD information from MSA, SPD, FPD xml file.
1545 This class will be used for wizard and build tools, So it can *not* inherit
1546 from buildAction or UIAction.
1548 public class CollectPCDAction
{
1549 /// memoryDatabase hold all PCD information collected from SPD, MSA, FPD.
1550 private MemoryDatabaseManager dbManager
;
1552 /// Workspacepath hold the workspace information.
1553 private String workspacePath
;
1555 /// FPD file is the root file.
1556 private String fpdFilePath
;
1558 /// Message level for CollectPCDAction.
1559 private int originalMessageLevel
;
1561 /// Cache the fpd docment instance for private usage.
1562 private PlatformSurfaceAreaDocument fpdDocInstance
;
1565 private static String xmlObjectName
= "PcdBuildDefinition";
1568 Set WorkspacePath parameter for this action class.
1570 @param workspacePath parameter for this action
1572 public void setWorkspacePath(String workspacePath
) {
1573 this.workspacePath
= workspacePath
;
1577 Set action message level for CollectPcdAction tool.
1579 The message should be restored when this action exit.
1581 @param actionMessageLevel parameter for this action
1583 public void setActionMessageLevel(int actionMessageLevel
) {
1584 originalMessageLevel
= ActionMessage
.messageLevel
;
1585 ActionMessage
.messageLevel
= actionMessageLevel
;
1589 Set FPDFileName parameter for this action class.
1591 @param fpdFilePath fpd file path
1593 public void setFPDFilePath(String fpdFilePath
) {
1594 this.fpdFilePath
= fpdFilePath
;
1598 Common function interface for outer.
1600 @param workspacePath The path of workspace of current build or analysis.
1601 @param fpdFilePath The fpd file path of current build or analysis.
1602 @param messageLevel The message level for this Action.
1604 @throws Exception The exception of this function. Because it can *not* be predict
1605 where the action class will be used. So only Exception can be throw.
1608 public void perform(String workspacePath
, String fpdFilePath
,
1609 int messageLevel
) throws Exception
{
1610 setWorkspacePath(workspacePath
);
1611 setFPDFilePath(fpdFilePath
);
1612 setActionMessageLevel(messageLevel
);
1615 ActionMessage
.messageLevel
= originalMessageLevel
;
1619 Core execution function for this action class.
1621 This function work flows will be:
1622 1) Collect and prepocess PCD information from FPD file, all PCD
1623 information will be stored into memory database.
1624 2) Generate 3 strings for
1625 a) All modules using Dynamic(Ex) PCD entry.(Token Number)
1626 b) PEI PCDDatabase (C Structure) for PCD Service PEIM.
1627 c) DXE PCD Database (C structure) for PCD Service DXE.
1630 @throws EntityException Exception indicate failed to execute this action.
1633 public void execute() throws EntityException
{
1635 // Get memoryDatabaseManager instance from GlobalData.
1636 // The memoryDatabaseManager should be initialized for whatever build
1637 // tools or wizard tools
1639 if((dbManager
= GlobalData
.getPCDMemoryDBManager()) == null) {
1640 throw new EntityException("The instance of PCD memory database manager is null");
1644 // Collect all PCD information defined in FPD file.
1645 // Evenry token defind in FPD will be created as an token into
1648 createTokenInDBFromFPD();
1651 // Call Private function genPcdDatabaseSourceCode (void); ComponentTypeBsDriver
1652 // 1) Generate for PEI, DXE PCD DATABASE's definition and initialization.
1654 genPcdDatabaseSourceCode ();
1659 This function generates source code for PCD Database.
1662 @throws EntityException If the token does *not* exist in memory database.
1665 private void genPcdDatabaseSourceCode()
1666 throws EntityException
{
1667 String PcdCommonHeaderString
= PcdDatabase
.getPcdDatabaseCommonDefinitions ();
1669 ArrayList
<Token
> alPei
= new ArrayList
<Token
> ();
1670 ArrayList
<Token
> alDxe
= new ArrayList
<Token
> ();
1672 dbManager
.getTwoPhaseDynamicRecordArray(alPei
, alDxe
);
1673 PcdDatabase pcdPeiDatabase
= new PcdDatabase (alPei
, "PEI", 0);
1674 pcdPeiDatabase
.genCode();
1675 MemoryDatabaseManager
.PcdPeimHString
= PcdCommonHeaderString
+ pcdPeiDatabase
.getHString()
1676 + PcdDatabase
.getPcdPeiDatabaseDefinitions();
1677 MemoryDatabaseManager
.PcdPeimCString
= pcdPeiDatabase
.getCString();
1679 PcdDatabase pcdDxeDatabase
= new PcdDatabase (alDxe
,
1683 pcdDxeDatabase
.genCode();
1684 MemoryDatabaseManager
.PcdDxeHString
= MemoryDatabaseManager
.PcdPeimHString
+ pcdDxeDatabase
.getHString()
1685 + PcdDatabase
.getPcdDxeDatabaseDefinitions();
1686 MemoryDatabaseManager
.PcdDxeCString
= pcdDxeDatabase
.getCString();
1690 Get component array from FPD.
1692 This function maybe provided by some Global class.
1694 @return List<ModuleInfo> the component array.
1697 private List
<ModuleInfo
> getComponentsFromFPD()
1698 throws EntityException
{
1699 List
<ModuleInfo
> allModules
= new ArrayList
<ModuleInfo
>();
1700 ModuleInfo current
= null;
1702 FrameworkModulesDocument
.FrameworkModules fModules
= null;
1703 ModuleSADocument
.ModuleSA
[] modules
= null;
1704 HashMap
<String
, XmlObject
> map
= new HashMap
<String
, XmlObject
>();
1706 if (fpdDocInstance
== null) {
1708 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
1709 } catch(IOException ioE
) {
1710 throw new EntityException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
1711 } catch(XmlException xmlE
) {
1712 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
1717 Map
<FpdModuleIdentification
,XmlObject
>pcdBuildDef
= GlobalData
.getFpdModuleSaXmlObject(CollectPCDAction
.xmlObjectName
);
1718 Set
<FpdModuleIdentification
> pcdBuildKeySet
= pcdBuildDef
.keySet();
1719 Iterator item
= pcdBuildKeySet
.iterator();
1720 while (item
.hasNext()){
1721 FpdModuleIdentification id
= (FpdModuleIdentification
)item
.next();
1722 allModules
.add(new ModuleInfo(id
, id
.getModule().getModuleType(),pcdBuildDef
.get(id
)));
1729 Create token instance object into memory database, the token information
1730 comes for FPD file. Normally, FPD file will contain all token platform
1733 @return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage.
1735 @throws EntityException Failed to parse FPD xml file.
1738 private void createTokenInDBFromFPD()
1739 throws EntityException
{
1743 List
<PcdBuildDefinition
.PcdData
> pcdBuildDataArray
= new ArrayList
<PcdBuildDefinition
.PcdData
>();
1744 PcdBuildDefinition
.PcdData pcdBuildData
= null;
1746 List
<ModuleInfo
> modules
= null;
1747 String primaryKey
= null;
1748 String exceptionString
= null;
1749 UsageInstance usageInstance
= null;
1750 String primaryKey1
= null;
1751 String primaryKey2
= null;
1752 boolean isDuplicate
= false;
1753 Token
.PCD_TYPE pcdType
= Token
.PCD_TYPE
.UNKNOWN
;
1754 Token
.DATUM_TYPE datumType
= Token
.DATUM_TYPE
.UNKNOWN
;
1755 long tokenNumber
= 0;
1756 String moduleName
= null;
1757 String datum
= null;
1758 int maxDatumSize
= 0;
1759 String
[] tokenSpaceStrRet
= null;
1762 // ----------------------------------------------
1763 // 1), Get all <ModuleSA> from FPD file.
1764 // ----------------------------------------------
1766 modules
= getComponentsFromFPD();
1768 if (modules
== null) {
1769 throw new EntityException("[FPD file error] No modules in FPD file, Please check whether there are elements in <FrameworkModules> in FPD file!");
1773 // -------------------------------------------------------------------
1774 // 2), Loop all modules to process <PcdBuildDeclarations> for each module.
1775 // -------------------------------------------------------------------
1777 for (index
= 0; index
< modules
.size(); index
++) {
1778 isDuplicate
= false;
1779 for (index2
= 0; index2
< index
; index2
++) {
1781 // BUGBUG: For transition schema, we can *not* get module's version from
1782 // <ModuleSAs>, It is work around code.
1784 primaryKey1
= UsageInstance
.getPrimaryKey(modules
.get(index
).getModuleId().getModule().getName(),
1788 modules
.get(index
).getModuleId().getArch(),
1790 primaryKey2
= UsageInstance
.getPrimaryKey(modules
.get(index2
).getModuleId().getModule().getName(),
1794 modules
.get(index2
).getModuleId().getArch(),
1796 if (primaryKey1
.equalsIgnoreCase(primaryKey2
)) {
1807 // It is legal for a module does not contains ANY pcd build definitions.
1809 if (modules
.get(index
).getPcdBuildDef() == null) {
1813 pcdBuildDataArray
= modules
.get(index
).getPcdBuildDef().getPcdDataList();
1815 moduleName
= modules
.get(index
).getModuleId().getModule().getName();
1818 // ----------------------------------------------------------------------
1819 // 2.1), Loop all Pcd entry for a module and add it into memory database.
1820 // ----------------------------------------------------------------------
1822 for (pcdIndex
= 0; pcdIndex
< pcdBuildDataArray
.size(); pcdIndex
++) {
1823 pcdBuildData
= pcdBuildDataArray
.get(pcdIndex
);
1826 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(pcdBuildData
.getTokenSpaceGuidCName());
1827 } catch ( Exception e
) {
1828 throw new EntityException ("Faile get Guid for token " + pcdBuildData
.getCName() + ":" + e
.getMessage());
1831 if (tokenSpaceStrRet
== null) {
1832 throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData
.getCName());
1835 primaryKey
= Token
.getPrimaryKeyString(pcdBuildData
.getCName(),
1836 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
1837 pcdType
= Token
.getpcdTypeFromString(pcdBuildData
.getItemType().toString());
1838 datumType
= Token
.getdatumTypeFromString(pcdBuildData
.getDatumType().toString());
1839 tokenNumber
= Long
.decode(pcdBuildData
.getToken().toString());
1840 if (pcdBuildData
.getValue() != null) {
1841 datum
= pcdBuildData
.getValue().toString();
1845 maxDatumSize
= pcdBuildData
.getMaxDatumSize();
1847 if ((pcdType
== Token
.PCD_TYPE
.FEATURE_FLAG
) &&
1848 (datumType
!= Token
.DATUM_TYPE
.BOOLEAN
)){
1849 exceptionString
= String
.format("[FPD file error] For PCD %s in module %s, the PCD type is FEATRUE_FLAG but "+
1850 "datum type of this PCD entry is not BOOLEAN!",
1851 pcdBuildData
.getCName(),
1853 throw new EntityException(exceptionString
);
1857 // -------------------------------------------------------------------------------------------
1858 // 2.1.1), Do some necessary checking work for FixedAtBuild, FeatureFlag and PatchableInModule
1859 // -------------------------------------------------------------------------------------------
1861 if (!Token
.isDynamic(pcdType
)) {
1863 // Value is required.
1865 if (datum
== null) {
1866 exceptionString
= String
.format("[FPD file error] There is no value for PCD entry %s in module %s!",
1867 pcdBuildData
.getCName(),
1869 throw new EntityException(exceptionString
);
1873 // Check whether the datum size is matched datum type.
1875 if ((exceptionString
= verifyDatum(pcdBuildData
.getCName(),
1879 maxDatumSize
)) != null) {
1880 throw new EntityException(exceptionString
);
1885 // ---------------------------------------------------------------------------------
1886 // 2.1.2), Create token or update token information for current anaylized PCD data.
1887 // ---------------------------------------------------------------------------------
1889 if (dbManager
.isTokenInDatabase(primaryKey
)) {
1891 // If the token is already exist in database, do some necessary checking
1892 // and add a usage instance into this token in database
1894 token
= dbManager
.getTokenByKey(primaryKey
);
1897 // checking for DatumType, DatumType should be unique for one PCD used in different
1900 if (token
.datumType
!= datumType
) {
1901 exceptionString
= String
.format("[FPD file error] The datum type of PCD entry %s is %s, which is different with %s defined in before!",
1902 pcdBuildData
.getCName(),
1903 pcdBuildData
.getDatumType().toString(),
1904 Token
.getStringOfdatumType(token
.datumType
));
1905 throw new EntityException(exceptionString
);
1909 // Check token number is valid
1911 if (tokenNumber
!= token
.tokenNumber
) {
1912 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!",
1913 pcdBuildData
.getCName(),
1915 throw new EntityException(exceptionString
);
1919 // For same PCD used in different modules, the PCD type should all be dynamic or non-dynamic.
1921 if (token
.isDynamicPCD
!= Token
.isDynamic(pcdType
)) {
1922 exceptionString
= String
.format("[FPD file error] For PCD entry %s in module %s, you define dynamic or non-dynamic PCD type which"+
1923 "is different with others module's",
1926 throw new EntityException(exceptionString
);
1929 if (token
.isDynamicPCD
) {
1931 // Check datum is equal the datum in dynamic information.
1932 // For dynamic PCD, you can do not write <Value> in sperated every <PcdBuildDefinition> in different <ModuleSA>,
1933 // But if you write, the <Value> must be same as the value in <DynamicPcdBuildDefinitions>.
1935 if (!token
.isSkuEnable() &&
1936 (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.DEFAULT_TYPE
) &&
1938 if (!datum
.equalsIgnoreCase(token
.getDefaultSku().value
)) {
1939 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in module %s, the datum in <ModuleSA> is "+
1940 "not equal to the datum in <DynamicPcdBuildDefinitions>, it is "+
1941 "illega! You could no set <Value> in <ModuleSA> for a dynamic PCD!",
1944 throw new EntityException(exceptionString
);
1948 if ((maxDatumSize
!= 0) &&
1949 (maxDatumSize
!= token
.datumSize
)){
1950 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in module %s, the max datum size is %d which "+
1951 "is different with <MaxDatumSize> %d defined in <DynamicPcdBuildDefinitions>!",
1956 throw new EntityException(exceptionString
);
1962 // If the token is not in database, create a new token instance and add
1963 // a usage instance into this token in database.
1966 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(pcdBuildData
.getTokenSpaceGuidCName());
1967 } catch (Exception e
) {
1968 throw new EntityException("Fail to get token space guid for token " + token
.cName
);
1971 if (tokenSpaceStrRet
== null) {
1972 throw new EntityException("Fail to get token space guid for token " + token
.cName
);
1975 token
= new Token(pcdBuildData
.getCName(),
1976 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
1978 token
.datumType
= datumType
;
1979 token
.tokenNumber
= tokenNumber
;
1980 token
.isDynamicPCD
= Token
.isDynamic(pcdType
);
1981 token
.datumSize
= maxDatumSize
;
1983 if (token
.isDynamicPCD
) {
1985 // For Dynamic and Dynamic Ex type, need find the dynamic information
1986 // in <DynamicPcdBuildDefinition> section in FPD file.
1988 updateDynamicInformation(moduleName
,
1994 dbManager
.addTokenToDatabase(primaryKey
, token
);
1998 // -----------------------------------------------------------------------------------
1999 // 2.1.3), Add the PcdType in current module into this Pcd token's supported PCD type.
2000 // -----------------------------------------------------------------------------------
2002 token
.updateSupportPcdType(pcdType
);
2005 // ------------------------------------------------
2006 // 2.1.4), Create an usage instance for this token.
2007 // ------------------------------------------------
2009 usageInstance
= new UsageInstance(token
,
2014 CommonDefinition
.getModuleType(modules
.get(index
).getModuleType()),
2016 modules
.get(index
).getModuleId().getArch(),
2020 token
.addUsageInstance(usageInstance
);
2025 // ------------------------------------------------
2026 // 3), Add unreference dynamic_Ex pcd token into Pcd database.
2027 // ------------------------------------------------
2029 List
<Token
> tokenArray
= getUnreferencedDynamicPcd();
2030 if (tokenArray
!= null) {
2031 for (index
= 0; index
< tokenArray
.size(); index
++) {
2032 dbManager
.addTokenToDatabase(tokenArray
.get(index
).getPrimaryKeyString(),
2033 tokenArray
.get(index
));
2038 private List
<Token
> getUnreferencedDynamicPcd () throws EntityException
{
2039 List
<Token
> tokenArray
= new ArrayList();
2041 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
2042 List
<DynamicPcdBuildDefinitions
.PcdBuildData
> dynamicPcdBuildDataArray
= null;
2043 DynamicPcdBuildDefinitions
.PcdBuildData pcdBuildData
= null;
2044 List
<DynamicPcdBuildDefinitions
.PcdBuildData
.SkuInfo
> skuInfoList
= null;
2045 Token
.PCD_TYPE pcdType
;
2046 SkuInstance skuInstance
= null;
2047 String primaryKey
= null;
2048 boolean hasSkuId0
= false;
2049 int index
, offset
, index2
;
2051 String exceptionString
;
2052 String hiiDefaultValue
;
2053 String tokenSpaceStrRet
[];
2054 String variableGuidString
[];
2057 // If FPD document is not be opened, open and initialize it.
2059 if (fpdDocInstance
== null) {
2061 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
2062 } catch(IOException ioE
) {
2063 throw new EntityException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
2064 } catch(XmlException xmlE
) {
2065 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
2069 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
2070 if (dynamicPcdBuildDefinitions
== null) {
2074 dynamicPcdBuildDataArray
= dynamicPcdBuildDefinitions
.getPcdBuildDataList();
2075 for (index2
= 0; index2
< dynamicPcdBuildDataArray
.size(); index2
++) {
2076 pcdBuildData
= dynamicPcdBuildDataArray
.get(index2
);
2078 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(pcdBuildData
.getTokenSpaceGuidCName());
2079 } catch ( Exception e
) {
2080 throw new EntityException ("Faile get Guid for token " + pcdBuildData
.getCName() + ":" + e
.getMessage());
2083 if (tokenSpaceStrRet
== null) {
2084 throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData
.getCName());
2087 primaryKey
= Token
.getPrimaryKeyString(pcdBuildData
.getCName(),
2088 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
2090 if (dbManager
.isTokenInDatabase(primaryKey
)) {
2094 pcdType
= Token
.getpcdTypeFromString(pcdBuildData
.getItemType().toString());
2095 if (pcdType
!= Token
.PCD_TYPE
.DYNAMIC_EX
) {
2096 throw new EntityException (String
.format("[FPD file error] It not allowed for DYNAMIC PCD %s who is no used by any module",
2097 pcdBuildData
.getCName()));
2101 // Create new token for unreference dynamic PCD token
2103 token
= new Token(pcdBuildData
.getCName(), translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
2104 token
.datumSize
= pcdBuildData
.getMaxDatumSize();
2107 token
.datumType
= Token
.getdatumTypeFromString(pcdBuildData
.getDatumType().toString());
2108 token
.tokenNumber
= Long
.decode(pcdBuildData
.getToken().toString());
2109 token
.dynamicExTokenNumber
= token
.tokenNumber
;
2110 token
.isDynamicPCD
= true;
2111 token
.updateSupportPcdType(pcdType
);
2113 exceptionString
= verifyDatum(token
.cName
,
2118 if (exceptionString
!= null) {
2119 throw new EntityException(exceptionString
);
2122 skuInfoList
= pcdBuildData
.getSkuInfoList();
2125 // Loop all sku data
2127 for (index
= 0; index
< skuInfoList
.size(); index
++) {
2128 skuInstance
= new SkuInstance();
2130 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.
2132 temp
= skuInfoList
.get(index
).getSkuId().toString();
2133 skuInstance
.id
= Integer
.decode(temp
);
2134 if (skuInstance
.id
== 0) {
2138 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.
2140 if (skuInfoList
.get(index
).getValue() != null) {
2141 skuInstance
.value
.setValue(skuInfoList
.get(index
).getValue().toString());
2142 if ((exceptionString
= verifyDatum(token
.cName
,
2144 skuInfoList
.get(index
).getValue().toString(),
2146 token
.datumSize
)) != null) {
2147 throw new EntityException(exceptionString
);
2150 token
.skuData
.add(skuInstance
);
2156 // Judge whether is HII group case.
2158 if (skuInfoList
.get(index
).getVariableName() != null) {
2159 exceptionString
= null;
2160 if (skuInfoList
.get(index
).getVariableGuid() == null) {
2161 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2162 "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",
2165 if (exceptionString
!= null) {
2166 throw new EntityException(exceptionString
);
2170 if (skuInfoList
.get(index
).getVariableOffset() == null) {
2171 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2172 "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",
2175 if (exceptionString
!= null) {
2176 throw new EntityException(exceptionString
);
2180 if (skuInfoList
.get(index
).getHiiDefaultValue() == null) {
2181 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2182 "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",
2185 if (exceptionString
!= null) {
2186 throw new EntityException(exceptionString
);
2190 if (skuInfoList
.get(index
).getHiiDefaultValue() != null) {
2191 hiiDefaultValue
= skuInfoList
.get(index
).getHiiDefaultValue().toString();
2193 hiiDefaultValue
= null;
2196 if ((exceptionString
= verifyDatum(token
.cName
,
2200 token
.datumSize
)) != null) {
2201 throw new EntityException(exceptionString
);
2204 offset
= Integer
.decode(skuInfoList
.get(index
).getVariableOffset());
2205 if (offset
> 0xFFFF) {
2206 throw new EntityException(String
.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+
2207 "exceed 64K, it is not allowed!",
2213 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.
2215 variableGuidString
= GlobalData
.getGuidInfoFromCname(skuInfoList
.get(index
).getVariableGuid().toString());
2216 if (variableGuidString
== null) {
2217 throw new EntityException(String
.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",
2219 skuInfoList
.get(index
).getVariableGuid().toString()));
2221 String variableStr
= skuInfoList
.get(index
).getVariableName();
2222 Pattern pattern
= Pattern
.compile("0x([a-fA-F0-9]){4}");
2223 Matcher matcher
= pattern
.matcher(variableStr
);
2224 List
<String
> varNameList
= new ArrayList
<String
>();
2225 while (matcher
.find()){
2226 String str
= variableStr
.substring(matcher
.start(),matcher
.end());
2227 varNameList
.add(str
);
2230 skuInstance
.value
.setHiiData(varNameList
,
2231 translateSchemaStringToUUID(variableGuidString
[1]),
2232 skuInfoList
.get(index
).getVariableOffset(),
2233 skuInfoList
.get(index
).getHiiDefaultValue().toString());
2234 token
.skuData
.add(skuInstance
);
2238 if (skuInfoList
.get(index
).getVpdOffset() != null) {
2239 skuInstance
.value
.setVpdData(skuInfoList
.get(index
).getVpdOffset());
2240 token
.skuData
.add(skuInstance
);
2244 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+
2245 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",
2247 throw new EntityException(exceptionString
);
2251 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+
2252 "no sku id = 0 data, which is required for every dynamic PCD",
2254 throw new EntityException(exceptionString
);
2257 tokenArray
.add(token
);
2264 Verify the datum value according its datum size and datum type, this
2265 function maybe moved to FPD verification tools in future.
2276 public String
verifyDatum(String cName
,
2279 Token
.DATUM_TYPE datumType
,
2281 String exceptionString
= null;
2287 if (moduleName
== null) {
2288 moduleName
= "section <DynamicPcdBuildDefinitions>";
2290 moduleName
= "module " + moduleName
;
2293 if (maxDatumSize
== 0) {
2294 exceptionString
= String
.format("[FPD file error] You maybe miss <MaxDatumSize> for PCD %s in %s",
2297 return exceptionString
;
2300 switch (datumType
) {
2302 if (maxDatumSize
!= 1) {
2303 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2304 "is UINT8, but datum size is %d, they are not matched!",
2308 return exceptionString
;
2311 if (datum
!= null) {
2313 value
= Integer
.decode(datum
);
2314 } catch (NumberFormatException nfeExp
) {
2315 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid "+
2316 "digital format of UINT8",
2319 return exceptionString
;
2322 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s exceed"+
2323 " the max size of UINT8 - 0xFF",
2327 return exceptionString
;
2332 if (maxDatumSize
!= 2) {
2333 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2334 "is UINT16, but datum size is %d, they are not matched!",
2338 return exceptionString
;
2340 if (datum
!= null) {
2342 value
= Integer
.decode(datum
);
2343 } catch (NumberFormatException nfeExp
) {
2344 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is "+
2345 "not valid digital of UINT16",
2348 return exceptionString
;
2350 if (value
> 0xFFFF) {
2351 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
2352 "which exceed the range of UINT16 - 0xFFFF",
2356 return exceptionString
;
2361 if (maxDatumSize
!= 4) {
2362 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2363 "is UINT32, but datum size is %d, they are not matched!",
2367 return exceptionString
;
2370 if (datum
!= null) {
2372 if (datum
.length() > 2) {
2373 if ((datum
.charAt(0) == '0') &&
2374 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
2375 subStr
= datum
.substring(2, datum
.length());
2376 value64
= new BigInteger(subStr
, 16);
2378 value64
= new BigInteger(datum
);
2381 value64
= new BigInteger(datum
);
2383 } catch (NumberFormatException nfeExp
) {
2384 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not "+
2385 "valid digital of UINT32",
2388 return exceptionString
;
2391 if (value64
.bitLength() > 32) {
2392 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s which "+
2393 "exceed the range of UINT32 - 0xFFFFFFFF",
2397 return exceptionString
;
2402 if (maxDatumSize
!= 8) {
2403 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2404 "is UINT64, but datum size is %d, they are not matched!",
2408 return exceptionString
;
2411 if (datum
!= null) {
2413 if (datum
.length() > 2) {
2414 if ((datum
.charAt(0) == '0') &&
2415 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
2416 subStr
= datum
.substring(2, datum
.length());
2417 value64
= new BigInteger(subStr
, 16);
2419 value64
= new BigInteger(datum
);
2422 value64
= new BigInteger(datum
);
2424 } catch (NumberFormatException nfeExp
) {
2425 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid"+
2426 " digital of UINT64",
2429 return exceptionString
;
2432 if (value64
.bitLength() > 64) {
2433 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
2434 "exceed the range of UINT64 - 0xFFFFFFFFFFFFFFFF",
2438 return exceptionString
;
2443 if (maxDatumSize
!= 1) {
2444 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2445 "is BOOLEAN, but datum size is %d, they are not matched!",
2449 return exceptionString
;
2452 if (datum
!= null) {
2453 if (!(datum
.equalsIgnoreCase("TRUE") ||
2454 datum
.equalsIgnoreCase("FALSE"))) {
2455 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
2456 "is BOOELAN, but value is not 'true'/'TRUE' or 'FALSE'/'false'",
2459 return exceptionString
;
2465 if (datum
== null) {
2469 char ch
= datum
.charAt(0);
2473 // For void* type PCD, only three datum is support:
2474 // 1) Unicode: string with start char is "L"
2475 // 2) Ansci: String start char is ""
2476 // 3) byte array: String start char "{"
2479 start
= datum
.indexOf('\"');
2480 end
= datum
.lastIndexOf('\"');
2481 if ((start
> end
) ||
2482 (end
> datum
.length())||
2483 ((start
== end
) && (datum
.length() > 0))) {
2484 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
2485 "a UNICODE string because start with L\", but format maybe"+
2486 "is not right, correct UNICODE string is L\"...\"!",
2489 return exceptionString
;
2492 strValue
= datum
.substring(start
+ 1, end
);
2493 if ((strValue
.length() * 2) > maxDatumSize
) {
2494 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
2495 "a UNICODE string, but the datum size is %d exceed to <MaxDatumSize> : %d",
2498 strValue
.length() * 2,
2500 return exceptionString
;
2502 } else if (ch
== '\"'){
2503 start
= datum
.indexOf('\"');
2504 end
= datum
.lastIndexOf('\"');
2505 if ((start
> end
) ||
2506 (end
> datum
.length())||
2507 ((start
== end
) && (datum
.length() > 0))) {
2508 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
2509 "a ANSCII string because start with \", but format maybe"+
2510 "is not right, correct ANSIC string is \"...\"!",
2513 return exceptionString
;
2515 strValue
= datum
.substring(start
+ 1, end
);
2516 if ((strValue
.length()) > maxDatumSize
) {
2517 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
2518 "a ANSCI string, but the datum size is %d which exceed to <MaxDatumSize> : %d",
2523 return exceptionString
;
2525 } else if (ch
=='{') {
2526 String
[] strValueArray
;
2528 start
= datum
.indexOf('{');
2529 end
= datum
.lastIndexOf('}');
2530 strValue
= datum
.substring(start
+ 1, end
);
2531 strValue
= strValue
.trim();
2532 if (strValue
.length() == 0) {
2535 strValueArray
= strValue
.split(",");
2536 for (index
= 0; index
< strValueArray
.length
; index
++) {
2538 value
= Integer
.decode(strValueArray
[index
].trim());
2539 } catch (NumberFormatException nfeEx
) {
2540 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
2541 "it is byte array in fact. For every byte in array should be a valid"+
2542 "byte digital, but element %s is not a valid byte digital!",
2545 strValueArray
[index
]);
2546 return exceptionString
;
2549 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, "+
2550 "it is byte array in fact. But the element of %s exceed the byte range",
2553 strValueArray
[index
]);
2554 return exceptionString
;
2558 if (strValueArray
.length
> maxDatumSize
) {
2559 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is byte"+
2560 "array, but the number of bytes is %d which exceed to <MaxDatumSzie> : %d!",
2563 strValueArray
.length
,
2565 return exceptionString
;
2568 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 "+
2569 "1) UNICODE string: like L\"xxxx\";\r\n"+
2570 "2) ANSIC string: like \"xxx\";\r\n"+
2571 "3) Byte array: like {0x2, 0x45, 0x23}\r\n"+
2572 "But the datum in seems does not following above format!",
2575 return exceptionString
;
2579 exceptionString
= String
.format("[FPD file error] For PCD entry %s in %s, datum type is unknown, it should be one of "+
2580 "UINT8, UINT16, UINT32, UINT64, VOID*, BOOLEAN",
2583 return exceptionString
;
2589 Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.
2591 This function should be implemented in GlobalData in future.
2593 @param token The token instance which has hold module's PCD information
2594 @param moduleName The name of module who will use this Dynamic PCD.
2596 @return DynamicPcdBuildDefinitions.PcdBuildData
2599 private DynamicPcdBuildDefinitions
.PcdBuildData
getDynamicInfoFromFPD(Token token
,
2601 throws EntityException
{
2603 String exceptionString
= null;
2604 String dynamicPrimaryKey
= null;
2605 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
2606 List
<DynamicPcdBuildDefinitions
.PcdBuildData
> dynamicPcdBuildDataArray
= null;
2607 String
[] tokenSpaceStrRet
= null;
2610 // If FPD document is not be opened, open and initialize it.
2612 if (fpdDocInstance
== null) {
2614 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
2615 } catch(IOException ioE
) {
2616 throw new EntityException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
2617 } catch(XmlException xmlE
) {
2618 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
2622 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
2623 if (dynamicPcdBuildDefinitions
== null) {
2624 exceptionString
= String
.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+
2625 "PCD entry %s in module %s!",
2628 throw new EntityException(exceptionString
);
2631 dynamicPcdBuildDataArray
= dynamicPcdBuildDefinitions
.getPcdBuildDataList();
2632 for (index
= 0; index
< dynamicPcdBuildDataArray
.size(); index
++) {
2633 //String tokenSpaceGuidString = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName())[1];
2634 String tokenSpaceGuidString
= null;
2636 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(dynamicPcdBuildDataArray
.get(index
).getTokenSpaceGuidCName());
2637 } catch (Exception e
) {
2638 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName());
2641 if (tokenSpaceStrRet
== null) {
2642 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName());
2645 dynamicPrimaryKey
= Token
.getPrimaryKeyString(dynamicPcdBuildDataArray
.get(index
).getCName(),
2646 translateSchemaStringToUUID(tokenSpaceStrRet
[1]));
2647 if (dynamicPrimaryKey
.equalsIgnoreCase(token
.getPrimaryKeyString())) {
2648 return dynamicPcdBuildDataArray
.get(index
);
2656 Update dynamic information for PCD entry.
2658 Dynamic information is retrieved from <PcdDynamicBuildDeclarations> in
2661 @param moduleName The name of the module who use this PCD
2662 @param token The token instance
2663 @param datum The <datum> in module's PCD information
2664 @param maxDatumSize The <maxDatumSize> in module's PCD information
2668 private Token
updateDynamicInformation(String moduleName
,
2672 throws EntityException
{
2675 String exceptionString
= null;
2676 DynamicTokenValue dynamicValue
;
2677 SkuInstance skuInstance
= null;
2679 boolean hasSkuId0
= false;
2680 Token
.PCD_TYPE pcdType
= Token
.PCD_TYPE
.UNKNOWN
;
2681 long tokenNumber
= 0;
2682 String hiiDefaultValue
= null;
2683 String
[] variableGuidString
= null;
2685 List
<DynamicPcdBuildDefinitions
.PcdBuildData
.SkuInfo
> skuInfoList
= null;
2686 DynamicPcdBuildDefinitions
.PcdBuildData dynamicInfo
= null;
2688 dynamicInfo
= getDynamicInfoFromFPD(token
, moduleName
);
2689 if (dynamicInfo
== null) {
2690 exceptionString
= String
.format("[FPD file error] For Dynamic PCD %s used by module %s, "+
2691 "there is no dynamic information in <DynamicPcdBuildDefinitions> "+
2692 "in FPD file, but it is required!",
2695 throw new EntityException(exceptionString
);
2698 token
.datumSize
= dynamicInfo
.getMaxDatumSize();
2700 exceptionString
= verifyDatum(token
.cName
,
2705 if (exceptionString
!= null) {
2706 throw new EntityException(exceptionString
);
2709 if ((maxDatumSize
!= 0) &&
2710 (maxDatumSize
!= token
.datumSize
)) {
2711 exceptionString
= String
.format("FPD file error] For dynamic PCD %s, the datum size in module %s is %d, but "+
2712 "the datum size in <DynamicPcdBuildDefinitions> is %d, they are not match!",
2716 dynamicInfo
.getMaxDatumSize());
2717 throw new EntityException(exceptionString
);
2719 tokenNumber
= Long
.decode(dynamicInfo
.getToken().toString());
2720 if (tokenNumber
!= token
.tokenNumber
) {
2721 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s, the token number in module %s is 0x%x, but"+
2722 "in <DynamicPcdBuildDefinictions>, the token number is 0x%x, they are not match!",
2727 throw new EntityException(exceptionString
);
2730 pcdType
= Token
.getpcdTypeFromString(dynamicInfo
.getItemType().toString());
2731 if (pcdType
== Token
.PCD_TYPE
.DYNAMIC_EX
) {
2732 token
.dynamicExTokenNumber
= tokenNumber
;
2735 skuInfoList
= dynamicInfo
.getSkuInfoList();
2738 // Loop all sku data
2740 for (index
= 0; index
< skuInfoList
.size(); index
++) {
2741 skuInstance
= new SkuInstance();
2743 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.
2745 temp
= skuInfoList
.get(index
).getSkuId().toString();
2746 skuInstance
.id
= Integer
.decode(temp
);
2747 if (skuInstance
.id
== 0) {
2751 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.
2753 if (skuInfoList
.get(index
).getValue() != null) {
2754 skuInstance
.value
.setValue(skuInfoList
.get(index
).getValue().toString());
2755 if ((exceptionString
= verifyDatum(token
.cName
,
2757 skuInfoList
.get(index
).getValue().toString(),
2759 token
.datumSize
)) != null) {
2760 throw new EntityException(exceptionString
);
2763 token
.skuData
.add(skuInstance
);
2766 // Judege wether is same of datum between module's information
2767 // and dynamic information.
2769 if (datum
!= null) {
2770 if ((skuInstance
.id
== 0) &&
2771 !datum
.toString().equalsIgnoreCase(skuInfoList
.get(index
).getValue().toString())) {
2772 exceptionString
= "[FPD file error] For dynamic PCD " + token
.cName
+ ", the value in module " + moduleName
+ " is " + datum
.toString() + " but the "+
2773 "value of sku 0 data in <DynamicPcdBuildDefinition> is " + skuInstance
.value
.value
+ ". They are must be same!"+
2774 " or you could not define value for a dynamic PCD in every <ModuleSA>!";
2775 throw new EntityException(exceptionString
);
2782 // Judge whether is HII group case.
2784 if (skuInfoList
.get(index
).getVariableName() != null) {
2785 exceptionString
= null;
2786 if (skuInfoList
.get(index
).getVariableGuid() == null) {
2787 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2788 "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",
2791 if (exceptionString
!= null) {
2792 throw new EntityException(exceptionString
);
2796 if (skuInfoList
.get(index
).getVariableOffset() == null) {
2797 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2798 "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",
2801 if (exceptionString
!= null) {
2802 throw new EntityException(exceptionString
);
2806 if (skuInfoList
.get(index
).getHiiDefaultValue() == null) {
2807 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
2808 "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",
2811 if (exceptionString
!= null) {
2812 throw new EntityException(exceptionString
);
2816 if (skuInfoList
.get(index
).getHiiDefaultValue() != null) {
2817 hiiDefaultValue
= skuInfoList
.get(index
).getHiiDefaultValue().toString();
2819 hiiDefaultValue
= null;
2822 if ((exceptionString
= verifyDatum(token
.cName
,
2826 token
.datumSize
)) != null) {
2827 throw new EntityException(exceptionString
);
2830 offset
= Integer
.decode(skuInfoList
.get(index
).getVariableOffset());
2831 if (offset
> 0xFFFF) {
2832 throw new EntityException(String
.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+
2833 "exceed 64K, it is not allowed!",
2839 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.
2841 variableGuidString
= GlobalData
.getGuidInfoFromCname(skuInfoList
.get(index
).getVariableGuid().toString());
2842 if (variableGuidString
== null) {
2843 throw new EntityException(String
.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",
2845 skuInfoList
.get(index
).getVariableGuid().toString()));
2847 String variableStr
= skuInfoList
.get(index
).getVariableName();
2848 Pattern pattern
= Pattern
.compile("0x([a-fA-F0-9]){4}");
2849 Matcher matcher
= pattern
.matcher(variableStr
);
2850 List
<String
> varNameList
= new ArrayList
<String
>();
2851 while (matcher
.find()){
2852 String str
= variableStr
.substring(matcher
.start(),matcher
.end());
2853 varNameList
.add(str
);
2856 skuInstance
.value
.setHiiData(varNameList
,
2857 translateSchemaStringToUUID(variableGuidString
[1]),
2858 skuInfoList
.get(index
).getVariableOffset(),
2859 skuInfoList
.get(index
).getHiiDefaultValue().toString());
2860 token
.skuData
.add(skuInstance
);
2864 if (skuInfoList
.get(index
).getVpdOffset() != null) {
2865 skuInstance
.value
.setVpdData(skuInfoList
.get(index
).getVpdOffset());
2866 token
.skuData
.add(skuInstance
);
2870 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+
2871 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",
2873 throw new EntityException(exceptionString
);
2877 exceptionString
= String
.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+
2878 "no sku id = 0 data, which is required for every dynamic PCD",
2880 throw new EntityException(exceptionString
);
2887 Translate the schema string to UUID instance.
2889 In schema, the string of UUID is defined as following two types string:
2890 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(
2891 )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?
2893 2) GuidNamingConvention: pattern =
2894 [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}
2896 This function will convert string and create uuid instance.
2898 @param uuidString UUID string in XML file
2900 @return UUID UUID instance
2902 private UUID
translateSchemaStringToUUID(String uuidString
)
2903 throws EntityException
{
2905 String
[] splitStringArray
;
2910 if (uuidString
== null) {
2914 if (uuidString
.length() == 0) {
2918 if (uuidString
.equals("0") ||
2919 uuidString
.equalsIgnoreCase("0x0")) {
2920 return new UUID(0, 0);
2923 uuidString
= uuidString
.replaceAll("\\{", "");
2924 uuidString
= uuidString
.replaceAll("\\}", "");
2927 // If the UUID schema string is GuidArrayType type then need translate
2928 // to GuidNamingConvention type at first.
2930 if ((uuidString
.charAt(0) == '0') && ((uuidString
.charAt(1) == 'x') || (uuidString
.charAt(1) == 'X'))) {
2931 splitStringArray
= uuidString
.split("," );
2932 if (splitStringArray
.length
!= 11) {
2933 throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString
);
2937 // Remove blank space from these string and remove header string "0x"
2939 for (index
= 0; index
< 11; index
++) {
2940 splitStringArray
[index
] = splitStringArray
[index
].trim();
2941 splitStringArray
[index
] = splitStringArray
[index
].substring(2, splitStringArray
[index
].length());
2945 // Add heading '0' to normalize the string length
2947 for (index
= 3; index
< 11; index
++) {
2948 chLen
= splitStringArray
[index
].length();
2949 for (chIndex
= 0; chIndex
< 2 - chLen
; chIndex
++) {
2950 splitStringArray
[index
] = "0" + splitStringArray
[index
];
2955 // construct the final GuidNamingConvention string
2957 temp
= String
.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",
2958 splitStringArray
[0],
2959 splitStringArray
[1],
2960 splitStringArray
[2],
2961 splitStringArray
[3],
2962 splitStringArray
[4],
2963 splitStringArray
[5],
2964 splitStringArray
[6],
2965 splitStringArray
[7],
2966 splitStringArray
[8],
2967 splitStringArray
[9],
2968 splitStringArray
[10]);
2972 return UUID
.fromString(uuidString
);
2976 check parameter for this action.
2978 @throws EntityException Bad parameter.
2980 private void checkParameter() throws EntityException
{
2983 if((fpdFilePath
== null) ||(workspacePath
== null)) {
2984 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
2987 if(fpdFilePath
.length() == 0 || workspacePath
.length() == 0) {
2988 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
2991 file
= new File(workspacePath
);
2992 if(!file
.exists()) {
2993 throw new EntityException("WorkpacePath " + workspacePath
+ " does not exist!");
2996 file
= new File(fpdFilePath
);
2998 if(!file
.exists()) {
2999 throw new EntityException("FPD File " + fpdFilePath
+ " does not exist!");
3006 @param argv parameter from command line
3008 public static void main(String argv
[]) throws EntityException
{
3009 CollectPCDAction ca
= new CollectPCDAction();
3010 ca
.setWorkspacePath("m:/tianocore/edk2");
3011 ca
.setFPDFilePath("m:/tianocore/edk2/EdkNt32Pkg/Nt32.fpd");
3012 ca
.setActionMessageLevel(ActionMessage
.MAX_MESSAGE_LEVEL
);
3013 GlobalData
.initInfo("Tools" + File
.separator
+ "Conf" + File
.separator
+ "FrameworkDatabase.db",
3014 "m:/tianocore/edk2",
3016 FpdParserTask fpt
= new FpdParserTask();
3017 fpt
.parseFpdFile(new File("m:/tianocore/edk2/EdkNt32Pkg/Nt32.fpd"));