4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 package org
.tianocore
.build
.pcd
.action
;
16 import java
.io
.BufferedReader
;
18 import java
.io
.FileReader
;
19 import java
.io
.IOException
;
20 import java
.math
.BigInteger
;
21 import java
.util
.ArrayList
;
22 import java
.util
.Comparator
;
23 import java
.util
.HashMap
;
24 import java
.util
.Iterator
;
25 import java
.util
.List
;
28 import java
.util
.UUID
;
29 import java
.util
.regex
.Matcher
;
30 import java
.util
.regex
.Pattern
;
32 import org
.apache
.xmlbeans
.XmlException
;
33 import org
.apache
.xmlbeans
.XmlObject
;
34 import org
.tianocore
.DynamicPcdBuildDefinitionsDocument
.DynamicPcdBuildDefinitions
;
35 import org
.tianocore
.FrameworkModulesDocument
;
36 import org
.tianocore
.ModuleSADocument
;
37 import org
.tianocore
.PcdBuildDefinitionDocument
;
38 import org
.tianocore
.PcdBuildDefinitionDocument
.PcdBuildDefinition
;
39 import org
.tianocore
.PlatformSurfaceAreaDocument
;
40 import org
.tianocore
.build
.fpd
.FpdParserTask
;
41 import org
.tianocore
.build
.global
.GlobalData
;
42 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
43 import org
.tianocore
.build
.id
.ModuleIdentification
;
44 import org
.tianocore
.pcd
.action
.ActionMessage
;
45 import org
.tianocore
.pcd
.entity
.CommonDefinition
;
46 import org
.tianocore
.pcd
.entity
.DynamicTokenValue
;
47 import org
.tianocore
.pcd
.entity
.MemoryDatabaseManager
;
48 import org
.tianocore
.pcd
.entity
.SkuInstance
;
49 import org
.tianocore
.pcd
.entity
.Token
;
50 import org
.tianocore
.pcd
.entity
.UsageIdentification
;
51 import org
.tianocore
.pcd
.entity
.UsageInstance
;
52 import org
.tianocore
.pcd
.exception
.EntityException
;
55 CStructTypeDeclaration
57 This class is used to store the declaration string, such as
58 "UINT32 PcdPlatformFlashBaseAddress", of
59 each memember in the C structure, which is a standard C language
60 feature used to implement a simple and efficient database for
61 dynamic(ex) type PCD entry.
63 class CStructTypeDeclaration
{
69 public CStructTypeDeclaration (String key
, int alignmentSize
, String cCode
, boolean initTable
) {
71 this.alignmentSize
= alignmentSize
;
73 this.initTable
= initTable
;
80 This class is used to store the String in a PCD database.
84 private ArrayList
<String
> al
;
85 private ArrayList
<String
> alComments
;
89 public StringTable (String phase
) {
91 al
= new ArrayList
<String
>();
92 alComments
= new ArrayList
<String
>();
96 public String
getSizeMacro () {
97 return String
.format(PcdDatabase
.StringTableSizeMacro
, phase
, getSize());
100 private int getSize () {
102 // We have at least one Unicode Character in the table.
104 return len
== 0 ?
1 : len
;
107 public String
getExistanceMacro () {
108 return String
.format(PcdDatabase
.StringTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
111 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
) {
112 final String stringTable
= "StringTable";
113 final String tab
= "\t";
114 final String newLine
= "\r\n";
115 final String commaNewLine
= ",\r\n";
117 CStructTypeDeclaration decl
;
119 String cDeclCode
= "";
120 String cInstCode
= "";
123 // If we have a empty StringTable
125 if (al
.size() == 0) {
126 cDeclCode
+= String
.format("%-20s%s[1]; /* StringTable is empty */", "UINT16", stringTable
) + newLine
;
127 decl
= new CStructTypeDeclaration (
135 cInstCode
= String
.format("/* %s */", stringTable
) + newLine
+ tab
+ "{ 0 }";
136 instTable
.put(stringTable
, cInstCode
);
140 // If there is any String in the StringTable
142 for (int i
= 0; i
< al
.size(); i
++) {
143 String str
= al
.get(i
);
144 String stringTableName
;
148 // StringTable is a well-known name in the PCD DXE driver
150 stringTableName
= stringTable
;
153 stringTableName
= String
.format("%s_%d", stringTable
, i
);
156 cDeclCode
+= String
.format("%-20s%s[%d]; /* %s */", "UINT16",
157 stringTableName
, str
.length() + 1,
162 cInstCode
= "/* StringTable */" + newLine
;
165 cInstCode
+= tab
+ String
.format("L\"%s\" /* %s */", al
.get(i
), alComments
.get(i
));
166 if (i
!= al
.size() - 1) {
167 cInstCode
+= commaNewLine
;
171 decl
= new CStructTypeDeclaration (
179 instTable
.put(stringTable
, cInstCode
);
183 public int add (String inputStr
, Token token
) {
187 String str
= inputStr
;
190 // The input can be two types:
191 // "L\"Bootmode\"" or "Bootmode".
192 // We drop the L\" and \" for the first type.
193 if (str
.startsWith("L\"") && str
.endsWith("\"")) {
194 str
= str
.substring(2, str
.length() - 1);
197 // Check if StringTable has this String already.
198 // If so, return the current pos.
200 for (i
= 0, pos
= 0; i
< al
.size(); i
++) {
201 String s
= al
.get(i
);;
206 pos
= s
.length() + 1;
211 // Include the NULL character at the end of String
213 len
+= str
.length() + 1;
215 alComments
.add(token
.getPrimaryKeyString());
224 This class is used to store the Size information for
225 POINTER TYPE PCD entry in a PCD database.
229 private ArrayList
<ArrayList
<Integer
>> al
;
230 private ArrayList
<String
> alComments
;
232 private String phase
;
234 public SizeTable (String phase
) {
235 al
= new ArrayList
<ArrayList
<Integer
>>();
236 alComments
= new ArrayList
<String
>();
241 public String
getSizeMacro () {
242 return String
.format(PcdDatabase
.SizeTableSizeMacro
, phase
, getSize());
245 private int getSize() {
246 return len
== 0 ?
1 : len
;
249 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
250 final String name
= "SizeTable";
252 CStructTypeDeclaration decl
;
255 cCode
= String
.format(PcdDatabase
.SizeTableDeclaration
, phase
);
256 decl
= new CStructTypeDeclaration (
265 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
266 instTable
.put(name
, cCode
);
269 private ArrayList
<String
> getInstantiation () {
270 final String comma
= ",";
271 ArrayList
<String
> Output
= new ArrayList
<String
>();
273 Output
.add("/* SizeTable */");
275 if (al
.size() == 0) {
278 for (int index
= 0; index
< al
.size(); index
++) {
279 ArrayList
<Integer
> ial
= al
.get(index
);
283 for (int index2
= 0; index2
< ial
.size(); index2
++) {
284 str
+= " " + ial
.get(index2
).toString();
285 if (index2
!= ial
.size() - 1) {
290 str
+= " /* " + alComments
.get(index
) + " */";
292 if (index
!= (al
.size() - 1)) {
305 public void add (Token token
) {
308 // We only have size information for POINTER type PCD entry.
310 if (token
.datumType
!= Token
.DATUM_TYPE
.POINTER
) {
314 ArrayList
<Integer
> ial
= token
.getPointerTypeSize();
319 alComments
.add(token
.getPrimaryKeyString());
329 This class is used to store the GUIDs in a PCD database.
332 private ArrayList
<UUID
> al
;
333 private ArrayList
<String
> alComments
;
334 private String phase
;
336 private int bodyLineNum
;
338 public GuidTable (String phase
) {
340 al
= new ArrayList
<UUID
>();
341 alComments
= new ArrayList
<String
>();
346 public String
getSizeMacro () {
347 return String
.format(PcdDatabase
.GuidTableSizeMacro
, phase
, getSize());
350 private int getSize () {
351 return (al
.size() == 0)?
1 : al
.size();
354 public String
getExistanceMacro () {
355 return String
.format(PcdDatabase
.GuidTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
358 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
359 final String name
= "GuidTable";
361 CStructTypeDeclaration decl
;
364 cCode
+= String
.format(PcdDatabase
.GuidTableDeclaration
, phase
);
365 decl
= new CStructTypeDeclaration (
374 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
375 instTable
.put(name
, cCode
);
378 private String
getUuidCString (UUID uuid
) {
379 String
[] guidStrArray
;
381 guidStrArray
=(uuid
.toString()).split("-");
383 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}}",
387 (guidStrArray
[3].substring(0, 2)),
388 (guidStrArray
[3].substring(2, 4)),
389 (guidStrArray
[4].substring(0, 2)),
390 (guidStrArray
[4].substring(2, 4)),
391 (guidStrArray
[4].substring(4, 6)),
392 (guidStrArray
[4].substring(6, 8)),
393 (guidStrArray
[4].substring(8, 10)),
394 (guidStrArray
[4].substring(10, 12))
398 private ArrayList
<String
> getInstantiation () {
399 ArrayList
<String
> Output
= new ArrayList
<String
>();
401 Output
.add("/* GuidTable */");
404 if (al
.size() == 0) {
405 Output
.add("\t" + getUuidCString(new UUID(0, 0)));
408 for (int i
= 0; i
< al
.size(); i
++) {
409 String str
= "\t" + getUuidCString(al
.get(i
));
411 str
+= "/* " + alComments
.get(i
) + " */";
412 if (i
!= (al
.size() - 1)) {
424 public int add (UUID uuid
, String name
) {
426 // Check if GuidTable has this entry already.
427 // If so, return the GuidTable index.
429 for (int i
= 0; i
< al
.size(); i
++) {
430 if (al
.get(i
).compareTo(uuid
) == 0) {
437 alComments
.add(name
);
440 // Return the previous Table Index
450 This class is used to store the SKU IDs in a PCD database.
454 private ArrayList
<Integer
[]> al
;
455 private ArrayList
<String
> alComment
;
456 private String phase
;
459 public SkuIdTable (String phase
) {
461 al
= new ArrayList
<Integer
[]>();
462 alComment
= new ArrayList
<String
>();
466 public String
getSizeMacro () {
467 return String
.format(PcdDatabase
.SkuIdTableSizeMacro
, phase
, getSize());
470 private int getSize () {
471 return (len
== 0)?
1 : len
;
474 public String
getExistanceMacro () {
475 return String
.format(PcdDatabase
.SkuTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
478 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
479 final String name
= "SkuIdTable";
481 CStructTypeDeclaration decl
;
484 cCode
+= String
.format(PcdDatabase
.SkuIdTableDeclaration
, phase
);
485 decl
= new CStructTypeDeclaration (
494 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
495 instTable
.put(name
, cCode
);
498 // SystemSkuId is in PEI phase PCD Database
500 if (phase
.equalsIgnoreCase("PEI")) {
501 decl
= new CStructTypeDeclaration (
504 String
.format("%-20sSystemSkuId;\r\n", "SKU_ID"),
509 instTable
.put("SystemSkuId", "0");
514 private ArrayList
<String
> getInstantiation () {
515 ArrayList
<String
> Output
= new ArrayList
<String
> ();
517 Output
.add("/* SkuIdTable */");
520 if (al
.size() == 0) {
524 for (int index
= 0; index
< al
.size(); index
++) {
527 str
= "/* " + alComment
.get(index
) + "*/ ";
528 str
+= "/* MaxSku */ ";
531 Integer
[] ia
= al
.get(index
);
533 str
+= "\t" + ia
[0].toString() + ", ";
534 for (int index2
= 1; index2
< ia
.length
; index2
++) {
535 str
+= ia
[index2
].toString();
536 if (!((index2
== ia
.length
- 1) && (index
== al
.size() - 1))) {
550 public int add (Token token
) {
556 // Check if this SKU_ID Array is already in the table
560 Integer
[] s
= (Integer
[]) o
;
561 boolean different
= false;
562 if (s
[0] == token
.getSkuIdCount()) {
563 for (index
= 1; index
< s
.length
; index
++) {
564 if (s
[index
] != token
.skuData
.get(index
-1).id
) {
579 Integer
[] skuIds
= new Integer
[token
.skuData
.size() + 1];
580 skuIds
[0] = new Integer(token
.skuData
.size());
581 for (index
= 1; index
< skuIds
.length
; index
++) {
582 skuIds
[index
] = new Integer(token
.skuData
.get(index
- 1).id
);
587 len
+= skuIds
.length
;
589 alComment
.add(token
.getPrimaryKeyString());
596 class LocalTokenNumberTable
{
597 private ArrayList
<String
> al
;
598 private ArrayList
<String
> alComment
;
599 private String phase
;
602 public LocalTokenNumberTable (String phase
) {
604 al
= new ArrayList
<String
>();
605 alComment
= new ArrayList
<String
>();
610 public String
getSizeMacro () {
611 return String
.format(PcdDatabase
.LocalTokenNumberTableSizeMacro
, phase
, getSize())
612 + String
.format(PcdDatabase
.LocalTokenNumberSizeMacro
, phase
, al
.size());
615 public int getSize () {
616 return (al
.size() == 0)?
1 : al
.size();
619 public String
getExistanceMacro () {
620 return String
.format(PcdDatabase
.DatabaseExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
623 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
624 final String name
= "LocalTokenNumberTable";
626 CStructTypeDeclaration decl
;
629 cCode
+= String
.format(PcdDatabase
.LocalTokenNumberTableDeclaration
, phase
);
630 decl
= new CStructTypeDeclaration (
638 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
639 instTable
.put(name
, cCode
);
642 private ArrayList
<String
> getInstantiation () {
643 ArrayList
<String
> output
= new ArrayList
<String
>();
645 output
.add("/* LocalTokenNumberTable */");
648 if (al
.size() == 0) {
652 for (int index
= 0; index
< al
.size(); index
++) {
655 str
= "\t" + (String
)al
.get(index
);
657 str
+= " /* " + alComment
.get(index
) + " */ ";
660 if (index
!= (al
.size() - 1)) {
673 public int add (Token token
) {
679 str
= String
.format(PcdDatabase
.offsetOfStrTemplate
, phase
, token
.hasDefaultValue() ?
"Init" : "Uninit", token
.getPrimaryKeyString());
681 if (token
.isUnicodeStringType()) {
682 str
+= " | PCD_TYPE_STRING";
685 if (token
.isSkuEnable()) {
686 str
+= " | PCD_TYPE_SKU_ENABLED";
689 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
690 str
+= " | PCD_TYPE_HII";
693 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
694 str
+= " | PCD_TYPE_VPD";
697 switch (token
.datumType
) {
700 str
+= " | PCD_DATUM_TYPE_UINT8";
703 str
+= " | PCD_DATUM_TYPE_UINT16";
706 str
+= " | PCD_DATUM_TYPE_UINT32";
709 str
+= " | PCD_DATUM_TYPE_UINT64";
712 str
+= " | PCD_DATUM_TYPE_POINTER";
717 alComment
.add(token
.getPrimaryKeyString());
726 This class is used to store the table of mapping information
727 between DynamicEX ID pair(Guid, TokenNumber) and
728 the local token number assigned by PcdDatabase class.
735 This class is used to store the mapping information
736 between DynamicEX ID pair(Guid, TokenNumber) and
737 the local token number assigned by PcdDatabase class.
740 public Integer guidTableIdx
;
741 public Long exTokenNumber
;
742 public Long localTokenIdx
;
744 public ExTriplet (int guidTableIdx
, long exTokenNumber
, long localTokenIdx
) {
745 this.guidTableIdx
= new Integer(guidTableIdx
);
746 this.exTokenNumber
= new Long(exTokenNumber
);
747 this.localTokenIdx
= new Long(localTokenIdx
);
751 private ArrayList
<ExTriplet
> al
;
752 private Map
<ExTriplet
, String
> alComment
;
753 private String phase
;
755 private int bodyLineNum
;
757 public ExMapTable (String phase
) {
759 al
= new ArrayList
<ExTriplet
>();
760 alComment
= new HashMap
<ExTriplet
, String
>();
765 public String
getSizeMacro () {
766 return String
.format(PcdDatabase
.ExMapTableSizeMacro
, phase
, getTableLen())
767 + String
.format(PcdDatabase
.ExTokenNumber
, phase
, al
.size());
770 public String
getExistanceMacro () {
771 return String
.format(PcdDatabase
.ExMapTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
774 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
775 final String exMapTableName
= "ExMapTable";
779 CStructTypeDeclaration decl
;
782 cCode
+= String
.format(PcdDatabase
.ExMapTableDeclaration
, phase
);
783 decl
= new CStructTypeDeclaration (
792 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
793 instTable
.put(exMapTableName
, cCode
);
796 private ArrayList
<String
> getInstantiation () {
797 ArrayList
<String
> Output
= new ArrayList
<String
>();
799 Output
.add("/* ExMapTable */");
801 if (al
.size() == 0) {
802 Output
.add("\t{0, 0, 0}");
806 for (index
= 0; index
< al
.size(); index
++) {
809 ExTriplet e
= (ExTriplet
)al
.get(index
);
811 str
= "\t" + "{ " + String
.format("0x%08X", e
.exTokenNumber
) + ", ";
812 str
+= e
.localTokenIdx
.toString() + ", ";
813 str
+= e
.guidTableIdx
.toString();
815 str
+= "}" + " /* " + alComment
.get(e
) + " */" ;
817 if (index
!= al
.size() - 1) {
831 public int add (int localTokenIdx
, long exTokenNum
, int guidTableIdx
, String name
) {
835 ExTriplet et
= new ExTriplet(guidTableIdx
, exTokenNum
, localTokenIdx
);
838 alComment
.put(et
, name
);
843 private int getTableLen () {
844 return al
.size() == 0 ?
1 : al
.size();
848 // To simplify the algorithm for GetNextToken and GetNextTokenSpace in
849 // PCD PEIM/Driver, we need to sort the ExMapTable according to the
854 class ExTripletComp
implements Comparator
<ExTriplet
> {
855 public int compare (ExTriplet a
, ExTriplet b
) {
856 if (a
.guidTableIdx
== b
.guidTableIdx
) {
858 // exTokenNumber is long, we can't use simple substraction.
860 if (a
.exTokenNumber
> b
.exTokenNumber
) {
862 } else if (a
.exTokenNumber
== b
.exTokenNumber
) {
869 return a
.guidTableIdx
- b
.guidTableIdx
;
873 private void sortTable () {
874 java
.util
.Comparator
<ExTriplet
> comparator
= new ExTripletComp();
875 java
.util
.Collections
.sort(al
, comparator
);
882 This class is used to generate C code for Autogen.h and Autogen.c of
883 a PCD service DXE driver and PCD service PEIM.
885 public class PcdDatabase
{
887 private final static int SkuHeadAlignmentSize
= 4;
888 private final String newLine
= "\r\n";
889 private final String commaNewLine
= ",\r\n";
890 private final String tab
= "\t";
891 public final static String ExMapTableDeclaration
= "DYNAMICEX_MAPPING ExMapTable[%s_EXMAPPING_TABLE_SIZE];\r\n";
892 public final static String GuidTableDeclaration
= "EFI_GUID GuidTable[%s_GUID_TABLE_SIZE];\r\n";
893 public final static String LocalTokenNumberTableDeclaration
= "UINT32 LocalTokenNumberTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";
894 public final static String StringTableDeclaration
= "UINT16 StringTable[%s_STRING_TABLE_SIZE];\r\n";
895 public final static String SizeTableDeclaration
= "SIZE_INFO SizeTable[%s_SIZE_TABLE_SIZE];\r\n";
896 public final static String SkuIdTableDeclaration
= "UINT8 SkuIdTable[%s_SKUID_TABLE_SIZE];\r\n";
899 public final static String ExMapTableSizeMacro
= "#define %s_EXMAPPING_TABLE_SIZE %d\r\n";
900 public final static String ExTokenNumber
= "#define %s_EX_TOKEN_NUMBER %d\r\n";
901 public final static String GuidTableSizeMacro
= "#define %s_GUID_TABLE_SIZE %d\r\n";
902 public final static String LocalTokenNumberTableSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER_TABLE_SIZE %d\r\n";
903 public final static String LocalTokenNumberSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER %d\r\n";
904 public final static String SizeTableSizeMacro
= "#define %s_SIZE_TABLE_SIZE %d\r\n";
905 public final static String StringTableSizeMacro
= "#define %s_STRING_TABLE_SIZE %d\r\n";
906 public final static String SkuIdTableSizeMacro
= "#define %s_SKUID_TABLE_SIZE %d\r\n";
909 public final static String ExMapTableExistenceMacro
= "#define %s_EXMAP_TABLE_EMPTY %s\r\n";
910 public final static String GuidTableExistenceMacro
= "#define %s_GUID_TABLE_EMPTY %s\r\n";
911 public final static String DatabaseExistenceMacro
= "#define %s_DATABASE_EMPTY %s\r\n";
912 public final static String StringTableExistenceMacro
= "#define %s_STRING_TABLE_EMPTY %s\r\n";
913 public final static String SkuTableExistenceMacro
= "#define %s_SKUID_TABLE_EMPTY %s\r\n";
915 public final static String offsetOfSkuHeadStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)";
916 public final static String offsetOfVariableEnabledDefault
= "offsetof(%s_PCD_DATABASE, %s.%s_VariableDefault_%d)";
917 public final static String offsetOfStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s)";
919 private final static String skuDataTableTemplate
= "SkuDataTable";
922 private StringTable stringTable
;
923 private GuidTable guidTable
;
924 private LocalTokenNumberTable localTokenNumberTable
;
925 private SkuIdTable skuIdTable
;
926 private SizeTable sizeTable
;
927 private ExMapTable exMapTable
;
929 private ArrayList
<Token
> alTokens
;
930 private String phase
;
931 private int assignedTokenNumber
;
934 // Use two class global variable to store
937 private String privateGlobalName
;
938 private String privateGlobalCCode
;
940 // After Major changes done to the PCD
941 // database generation class PcdDatabase
942 // Please increment the version and please
943 // also update the version number in PCD
944 // service PEIM and DXE driver accordingly.
946 private final int version
= 2;
948 private String hString
;
949 private String cString
;
952 Constructor for PcdDatabase class.
954 <p>We have two PCD dynamic(ex) database for the Framework implementation. One
955 for PEI phase and the other for DXE phase. </p>
957 @param alTokens A ArrayList of Dynamic(EX) PCD entry.
958 @param exePhase The phase to generate PCD database for: valid input
960 @param startLen The starting Local Token Number for the PCD database. For
961 PEI phase, the starting Local Token Number starts from 0.
962 For DXE phase, the starting Local Token Number starts
963 from the total number of PCD entry of PEI phase.
966 public PcdDatabase (ArrayList
<Token
> alTokens
, String exePhase
, int startLen
) {
969 stringTable
= new StringTable(phase
);
970 guidTable
= new GuidTable(phase
);
971 localTokenNumberTable
= new LocalTokenNumberTable(phase
);
972 skuIdTable
= new SkuIdTable(phase
);
973 sizeTable
= new SizeTable(phase
);
974 exMapTable
= new ExMapTable(phase
);
977 // Local token number 0 is reserved for INVALID_TOKEN_NUMBER.
978 // So we will increment 1 for the startLen passed from the
981 assignedTokenNumber
= startLen
+ 1;
982 this.alTokens
= alTokens
;
985 private void getNonExAndExTokens (ArrayList
<Token
> alTokens
, List
<Token
> nexTokens
, List
<Token
> exTokens
) {
986 for (int i
= 0; i
< alTokens
.size(); i
++) {
987 Token t
= (Token
)alTokens
.get(i
);
988 if (t
.isDynamicEx()) {
998 private int getDataTypeAlignmentSize (Token token
) {
999 switch (token
.datumType
) {
1017 private int getHiiPtrTypeAlignmentSize(Token token
) {
1018 switch (token
.datumType
) {
1028 if (token
.isHiiEnable()) {
1029 if (token
.isHiiDefaultValueUnicodeStringType()) {
1041 private int getAlignmentSize (Token token
) {
1042 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
1046 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
1050 if (token
.isUnicodeStringType()) {
1054 return getDataTypeAlignmentSize(token
);
1057 public String
getCString () {
1061 public String
getHString () {
1065 private void genCodeWorker(Token t
,
1066 ArrayList
<CStructTypeDeclaration
> declaList
,
1067 HashMap
<String
, String
> instTable
, String phase
)
1068 throws EntityException
{
1070 CStructTypeDeclaration decl
;
1073 // Insert SKU_HEAD if isSkuEnable is true
1075 if (t
.isSkuEnable()) {
1077 tableIdx
= skuIdTable
.add(t
);
1078 decl
= new CStructTypeDeclaration(t
.getPrimaryKeyString(),
1079 SkuHeadAlignmentSize
, getSkuEnabledTypeDeclaration(t
), true);
1080 declaList
.add(decl
);
1081 instTable
.put(t
.getPrimaryKeyString(),
1082 getSkuEnabledTypeInstantiaion(t
, tableIdx
));
1086 // Insert PCD_ENTRY declaration and instantiation
1088 getCDeclarationString(t
);
1090 decl
= new CStructTypeDeclaration(privateGlobalName
,
1091 getAlignmentSize(t
), privateGlobalCCode
, t
.hasDefaultValue());
1092 declaList
.add(decl
);
1094 if (t
.hasDefaultValue()) {
1095 instTable
.put(privateGlobalName
,
1096 getTypeInstantiation(t
, declaList
, instTable
, phase
)
1102 private void ProcessTokens (List
<Token
> tokens
,
1103 ArrayList
<CStructTypeDeclaration
> cStructDeclList
,
1104 HashMap
<String
, String
> cStructInstTable
,
1107 throws EntityException
{
1109 for (int idx
= 0; idx
< tokens
.size(); idx
++) {
1110 Token t
= tokens
.get(idx
);
1112 genCodeWorker (t
, cStructDeclList
, cStructInstTable
, phase
);
1115 localTokenNumberTable
.add(t
);
1116 t
.tokenNumber
= assignedTokenNumber
++;
1119 // Add a mapping if this dynamic PCD entry is a EX type
1121 if (t
.isDynamicEx()) {
1122 exMapTable
.add((int)t
.tokenNumber
,
1123 t
.dynamicExTokenNumber
,
1124 guidTable
.add(translateSchemaStringToUUID(t
.tokenSpaceName
), t
.getPrimaryKeyString()),
1125 t
.getPrimaryKeyString()
1132 public void genCode () throws EntityException
{
1134 ArrayList
<CStructTypeDeclaration
> cStructDeclList
= new ArrayList
<CStructTypeDeclaration
>();
1135 HashMap
<String
, String
> cStructInstTable
= new HashMap
<String
, String
>();
1137 List
<Token
> nexTokens
= new ArrayList
<Token
> ();
1138 List
<Token
> exTokens
= new ArrayList
<Token
> ();
1140 getNonExAndExTokens (alTokens
, nexTokens
, exTokens
);
1143 // We have to process Non-Ex type PCD entry first. The reason is
1144 // that our optimization assumes that the Token Number of Non-Ex
1145 // PCD entry start from 1 (for PEI phase) and grows continously upwards.
1147 // EX type token number starts from the last Non-EX PCD entry and
1148 // grows continously upwards.
1150 ProcessTokens (nexTokens
, cStructDeclList
, cStructInstTable
, phase
);
1151 ProcessTokens (exTokens
, cStructDeclList
, cStructInstTable
, phase
);
1153 stringTable
.genCode(cStructDeclList
, cStructInstTable
);
1154 skuIdTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1155 exMapTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1156 localTokenNumberTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1157 sizeTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1158 guidTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1160 hString
= genCMacroCode ();
1162 HashMap
<String
, String
> result
;
1164 result
= genCStructCode(cStructDeclList
,
1169 hString
+= result
.get("initDeclStr");
1170 hString
+= result
.get("uninitDeclStr");
1172 hString
+= String
.format("#define PCD_%s_SERVICE_DRIVER_VERSION %d", phase
, version
);
1174 cString
= newLine
+ newLine
+ result
.get("initInstStr");
1178 private String
genCMacroCode () {
1179 String macroStr
= "";
1182 // Generate size info Macro for all Tables
1184 macroStr
+= guidTable
.getSizeMacro();
1185 macroStr
+= stringTable
.getSizeMacro();
1186 macroStr
+= skuIdTable
.getSizeMacro();
1187 macroStr
+= localTokenNumberTable
.getSizeMacro();
1188 macroStr
+= exMapTable
.getSizeMacro();
1189 macroStr
+= sizeTable
.getSizeMacro();
1192 // Generate existance info Macro for all Tables
1194 macroStr
+= guidTable
.getExistanceMacro();
1195 macroStr
+= stringTable
.getExistanceMacro();
1196 macroStr
+= skuIdTable
.getExistanceMacro();
1197 macroStr
+= localTokenNumberTable
.getExistanceMacro();
1198 macroStr
+= exMapTable
.getExistanceMacro();
1200 macroStr
+= newLine
;
1205 private HashMap
<String
, String
> genCStructCode(
1206 ArrayList
<CStructTypeDeclaration
> declaList
,
1207 HashMap
<String
, String
> instTable
,
1212 HashMap
<String
, String
> result
= new HashMap
<String
, String
>();
1213 HashMap
<Integer
, ArrayList
<String
>> alignmentInitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1214 HashMap
<Integer
, ArrayList
<String
>> alignmentUninitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1215 HashMap
<Integer
, ArrayList
<String
>> alignmentInitInst
= new HashMap
<Integer
, ArrayList
<String
>>();
1218 // Initialize the storage for each alignment
1220 for (i
= 8; i
> 0; i
>>=1) {
1221 alignmentInitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1222 alignmentInitInst
.put(new Integer(i
), new ArrayList
<String
>());
1223 alignmentUninitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1226 String initDeclStr
= "typedef struct {" + newLine
;
1227 String initInstStr
= String
.format("%s_PCD_DATABASE_INIT g%sPcdDbInit = { ", phase
.toUpperCase(), phase
.toUpperCase()) + newLine
;
1228 String uninitDeclStr
= "typedef struct {" + newLine
;
1231 // Sort all C declaration and instantiation base on Alignment Size
1233 for (Object d
: declaList
) {
1234 CStructTypeDeclaration decl
= (CStructTypeDeclaration
) d
;
1236 if (decl
.initTable
) {
1237 alignmentInitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1238 alignmentInitInst
.get(new Integer(decl
.alignmentSize
)).add(instTable
.get(decl
.key
));
1240 alignmentUninitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1245 // Generate code for every alignment size
1247 boolean uinitDatabaseEmpty
= true;
1248 for (int align
= 8; align
> 0; align
>>= 1) {
1249 ArrayList
<String
> declaListBasedOnAlignment
= alignmentInitDecl
.get(new Integer(align
));
1250 ArrayList
<String
> instListBasedOnAlignment
= alignmentInitInst
.get(new Integer(align
));
1251 for (i
= 0; i
< declaListBasedOnAlignment
.size(); i
++) {
1252 initDeclStr
+= tab
+ declaListBasedOnAlignment
.get(i
);
1253 initInstStr
+= tab
+ instListBasedOnAlignment
.get(i
);
1256 // We made a assumption that both PEI_PCD_DATABASE and DXE_PCD_DATABASE
1257 // has a least one data memember with alignment size of 1. So we can
1258 // remove the last "," in the C structure instantiation string. Luckily,
1259 // this is true as both data structure has SKUID_TABLE anyway.
1261 if ((align
== 1) && (i
== declaListBasedOnAlignment
.size() - 1)) {
1262 initInstStr
+= newLine
;
1264 initInstStr
+= commaNewLine
;
1268 declaListBasedOnAlignment
= alignmentUninitDecl
.get(new Integer(align
));
1270 if (declaListBasedOnAlignment
.size() != 0) {
1271 uinitDatabaseEmpty
= false;
1274 for (Object d
: declaListBasedOnAlignment
) {
1275 String s
= (String
)d
;
1276 uninitDeclStr
+= tab
+ s
;
1280 if (uinitDatabaseEmpty
) {
1281 uninitDeclStr
+= tab
+ String
.format("%-20sdummy; /* PCD_DATABASE_UNINIT is emptry */\r\n", "UINT8");
1284 initDeclStr
+= String
.format("} %s_PCD_DATABASE_INIT;", phase
) + newLine
+ newLine
;
1285 initInstStr
+= "};" + newLine
;
1286 uninitDeclStr
+= String
.format("} %s_PCD_DATABASE_UNINIT;", phase
) + newLine
+ newLine
;
1288 result
.put("initDeclStr", initDeclStr
);
1289 result
.put("initInstStr", initInstStr
);
1290 result
.put("uninitDeclStr", uninitDeclStr
);
1295 public static String
genInstantiationStr (ArrayList
<String
> alStr
) {
1297 for (int i
= 0; i
< alStr
.size(); i
++) {
1301 str
+= alStr
.get(i
);
1302 if (i
!= alStr
.size() - 1) {
1310 private String
getSkuEnabledTypeDeclaration (Token token
) {
1311 return String
.format("%-20s%s;\r\n", "SKU_HEAD", token
.getPrimaryKeyString());
1314 private String
getSkuEnabledTypeInstantiaion (Token token
, int SkuTableIdx
) {
1316 String offsetof
= String
.format(PcdDatabase
.offsetOfSkuHeadStrTemplate
, phase
, token
.hasDefaultValue()?
"Init" : "Uninit", token
.getPrimaryKeyString());
1317 return String
.format("{ %s, %d } /* SKU_ENABLED: %s */", offsetof
, SkuTableIdx
, token
.getPrimaryKeyString());
1320 private String
getDataTypeInstantiationForVariableDefault (Token token
, String cName
, int skuId
) {
1321 return String
.format("%s /* %s */", token
.skuData
.get(skuId
).value
.hiiDefaultValue
, cName
);
1324 private String
getCType (Token t
)
1325 throws EntityException
{
1327 if (t
.isHiiEnable()) {
1328 return "VARIABLE_HEAD";
1331 if (t
.isVpdEnable()) {
1335 if (t
.isUnicodeStringType()) {
1336 return "STRING_HEAD";
1339 switch (t
.datumType
) {
1353 throw new EntityException("Unknown type in getDataTypeCDeclaration");
1358 // privateGlobalName and privateGlobalCCode is used to pass output to caller of getCDeclarationString
1360 private void getCDeclarationString(Token t
)
1361 throws EntityException
{
1363 if (t
.isSkuEnable()) {
1364 privateGlobalName
= String
.format("%s_%s", t
.getPrimaryKeyString(), skuDataTableTemplate
);
1366 privateGlobalName
= t
.getPrimaryKeyString();
1369 String type
= getCType(t
);
1370 if ((t
.datumType
== Token
.DATUM_TYPE
.POINTER
) && (!t
.isHiiEnable()) && (!t
.isUnicodeStringType())) {
1372 if (t
.isASCIIStringType()) {
1374 // Build tool will add a NULL string at the end of the ASCII string
1376 bufferSize
= t
.datumSize
+ 1;
1378 bufferSize
= t
.datumSize
;
1380 privateGlobalCCode
= String
.format("%-20s%s[%d][%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount(), bufferSize
);
1382 privateGlobalCCode
= String
.format("%-20s%s[%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount());
1386 private String
getDataTypeDeclarationForVariableDefault (Token token
, String cName
, int skuId
)
1387 throws EntityException
{
1391 if (token
.datumType
== Token
.DATUM_TYPE
.UINT8
) {
1393 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT16
) {
1395 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT32
) {
1397 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT64
) {
1399 } else if (token
.datumType
== Token
.DATUM_TYPE
.BOOLEAN
) {
1400 typeStr
= "BOOLEAN";
1401 } else if (token
.datumType
== Token
.DATUM_TYPE
.POINTER
) {
1403 if (token
.isHiiDefaultValueUnicodeStringType()) {
1406 // Include the NULL charactor
1408 size
= token
.datumSize
/ 2 + 1;
1411 if (token
.isHiiDefaultValueASCIIStringType()) {
1413 // Include the NULL charactor
1415 size
= token
.datumSize
+ 1;
1417 size
= token
.datumSize
;
1420 return String
.format("%-20s%s[%d];\r\n", typeStr
, cName
, size
);
1422 throw new EntityException("Unknown DATUM_TYPE type in when generating code for VARIABLE_ENABLED PCD entry");
1425 return String
.format("%-20s%s;\r\n", typeStr
, cName
);
1428 private String
getTypeInstantiation (Token t
, ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) throws EntityException
{
1433 s
= String
.format("/* %s */", t
.getPrimaryKeyString()) + newLine
;
1434 s
+= tab
+ "{" + newLine
;
1436 for (i
= 0; i
< t
.skuData
.size(); i
++) {
1437 if (t
.isUnicodeStringType()) {
1438 s
+= tab
+ tab
+ String
.format("{ %d }", stringTable
.add(t
.skuData
.get(i
).value
.value
, t
));
1439 } else if (t
.isHiiEnable()) {
1440 /* VPD_HEAD definition
1442 UINT16 GuidTableIndex; // Offset in Guid Table in units of GUID.
1443 UINT16 StringIndex; // Offset in String Table in units of UINT16.
1444 UINT16 Offset; // Offset in Variable
1445 UINT16 DefaultValueOffset; // Offset of the Default Value
1448 String variableDefaultName
= String
.format("%s_VariableDefault_%d", t
.getPrimaryKeyString(), i
);
1450 s
+= tab
+ tab
+ String
.format("{ %d, %d, %s, %s }", guidTable
.add(t
.skuData
.get(i
).value
.variableGuid
, t
.getPrimaryKeyString()),
1451 stringTable
.add(t
.skuData
.get(i
).value
.getStringOfVariableName(), t
),
1452 t
.skuData
.get(i
).value
.variableOffset
,
1453 String
.format("offsetof(%s_PCD_DATABASE, Init.%s)", phase
, variableDefaultName
)
1456 // We need to support the default value, so we add the declaration and
1457 // the instantiation for the default value.
1459 CStructTypeDeclaration decl
= new CStructTypeDeclaration (variableDefaultName
,
1460 getHiiPtrTypeAlignmentSize(t
),
1461 getDataTypeDeclarationForVariableDefault(t
, variableDefaultName
, i
),
1464 declaList
.add(decl
);
1465 instTable
.put(variableDefaultName
, getDataTypeInstantiationForVariableDefault (t
, variableDefaultName
, i
));
1466 } else if (t
.isVpdEnable()) {
1471 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.vpdOffset
);
1473 if (t
.isByteStreamType()) {
1475 // Byte stream type input has their own "{" "}", so we won't help to insert.
1477 s
+= tab
+ tab
+ String
.format(" %s ", t
.skuData
.get(i
).value
.value
);
1479 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.value
);
1483 if (i
!= t
.skuData
.size() - 1) {
1496 public static String
getPcdDatabaseCommonDefinitions ()
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 "PcdDatabaseCommonDefinitions.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 Common Definitions");
1519 public static String
getPcdDxeDatabaseDefinitions ()
1520 throws EntityException
{
1524 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1525 "Tools" + File
.separator
+
1526 "Conf" + File
.separator
+
1527 "Pcd" + File
.separator
+
1528 "PcdDatabaseDxeDefinitions.sample");
1529 FileReader reader
= new FileReader(file
);
1530 BufferedReader in
= new BufferedReader(reader
);
1532 while ((str
= in
.readLine()) != null) {
1533 retStr
= retStr
+"\r\n" + str
;
1535 } catch (Exception ex
) {
1536 throw new EntityException("Fatal error when generating PcdDatabase Dxe Definitions");
1542 public static String
getPcdPeiDatabaseDefinitions ()
1543 throws EntityException
{
1547 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1548 "Tools" + File
.separator
+
1549 "Conf" + File
.separator
+
1550 "Pcd" + File
.separator
+
1551 "PcdDatabasePeiDefinitions.sample");
1552 FileReader reader
= new FileReader(file
);
1553 BufferedReader in
= new BufferedReader(reader
);
1555 while ((str
= in
.readLine()) != null) {
1556 retStr
= retStr
+"\r\n" + str
;
1558 } catch (Exception ex
) {
1559 throw new EntityException("Fatal error when generating PcdDatabase Pei Definitions");
1566 Translate the schema string to UUID instance.
1568 In schema, the string of UUID is defined as following two types string:
1569 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(
1570 )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?
1572 2) GuidNamingConvention: pattern =
1573 [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}
1575 This function will convert string and create uuid instance.
1577 @param uuidString UUID string in XML file
1579 @return UUID UUID instance
1581 private UUID
translateSchemaStringToUUID(String uuidString
)
1582 throws EntityException
{
1584 String
[] splitStringArray
;
1589 if (uuidString
== null) {
1593 if (uuidString
.length() == 0) {
1597 if (uuidString
.equals("0") ||
1598 uuidString
.equalsIgnoreCase("0x0")) {
1599 return new UUID(0, 0);
1602 uuidString
= uuidString
.replaceAll("\\{", "");
1603 uuidString
= uuidString
.replaceAll("\\}", "");
1606 // If the UUID schema string is GuidArrayType type then need translate
1607 // to GuidNamingConvention type at first.
1609 if ((uuidString
.charAt(0) == '0') && ((uuidString
.charAt(1) == 'x') || (uuidString
.charAt(1) == 'X'))) {
1610 splitStringArray
= uuidString
.split("," );
1611 if (splitStringArray
.length
!= 11) {
1612 throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString
);
1616 // Remove blank space from these string and remove header string "0x"
1618 for (index
= 0; index
< 11; index
++) {
1619 splitStringArray
[index
] = splitStringArray
[index
].trim();
1620 splitStringArray
[index
] = splitStringArray
[index
].substring(2, splitStringArray
[index
].length());
1624 // Add heading '0' to normalize the string length
1626 for (index
= 3; index
< 11; index
++) {
1627 chLen
= splitStringArray
[index
].length();
1628 for (chIndex
= 0; chIndex
< 2 - chLen
; chIndex
++) {
1629 splitStringArray
[index
] = "0" + splitStringArray
[index
];
1634 // construct the final GuidNamingConvention string
1636 temp
= String
.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",
1637 splitStringArray
[0],
1638 splitStringArray
[1],
1639 splitStringArray
[2],
1640 splitStringArray
[3],
1641 splitStringArray
[4],
1642 splitStringArray
[5],
1643 splitStringArray
[6],
1644 splitStringArray
[7],
1645 splitStringArray
[8],
1646 splitStringArray
[9],
1647 splitStringArray
[10]);
1651 return UUID
.fromString(uuidString
);