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
.util
.ArrayList
;
20 import java
.util
.Comparator
;
21 import java
.util
.HashMap
;
22 import java
.util
.List
;
24 import java
.util
.UUID
;
25 import org
.tianocore
.build
.global
.GlobalData
;
26 import org
.tianocore
.pcd
.entity
.DynamicTokenValue
;
27 import org
.tianocore
.pcd
.entity
.Token
;
28 import org
.tianocore
.pcd
.exception
.EntityException
;
31 CStructTypeDeclaration
33 This class is used to store the declaration string, such as
34 "UINT32 PcdPlatformFlashBaseAddress", of
35 each memember in the C structure, which is a standard C language
36 feature used to implement a simple and efficient database for
37 dynamic(ex) type PCD entry.
39 class CStructTypeDeclaration
{
45 public CStructTypeDeclaration (String key
, int alignmentSize
, String cCode
, boolean initTable
) {
47 this.alignmentSize
= alignmentSize
;
49 this.initTable
= initTable
;
56 This class is used to store the String in a PCD database.
60 private ArrayList
<String
> al
;
61 private ArrayList
<String
> alComments
;
65 public StringTable (String phase
) {
67 al
= new ArrayList
<String
>();
68 alComments
= new ArrayList
<String
>();
72 public String
getSizeMacro () {
73 return String
.format(PcdDatabase
.StringTableSizeMacro
, phase
, getSize());
76 private int getSize () {
78 // We have at least one Unicode Character in the table.
80 return len
== 0 ?
1 : len
;
83 public String
getExistanceMacro () {
84 return String
.format(PcdDatabase
.StringTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
87 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
) {
88 final String stringTable
= "StringTable";
89 final String tab
= "\t";
90 final String newLine
= "\r\n";
91 final String commaNewLine
= ",\r\n";
93 CStructTypeDeclaration decl
;
95 String cDeclCode
= "";
96 String cInstCode
= "";
99 // If we have a empty StringTable
101 if (al
.size() == 0) {
102 cDeclCode
+= String
.format("%-20s%s[1]; /* StringTable is empty */", "UINT16", stringTable
) + newLine
;
103 decl
= new CStructTypeDeclaration (
111 cInstCode
= String
.format("/* %s */", stringTable
) + newLine
+ tab
+ "{ 0 }";
112 instTable
.put(stringTable
, cInstCode
);
116 // If there is any String in the StringTable
118 for (int i
= 0; i
< al
.size(); i
++) {
119 String str
= al
.get(i
);
120 String stringTableName
;
124 // StringTable is a well-known name in the PCD DXE driver
126 stringTableName
= stringTable
;
129 stringTableName
= String
.format("%s_%d", stringTable
, i
);
132 cDeclCode
+= String
.format("%-20s%s[%d]; /* %s */", "UINT16",
133 stringTableName
, str
.length() + 1,
138 cInstCode
= "/* StringTable */" + newLine
;
141 cInstCode
+= tab
+ String
.format("L\"%s\" /* %s */", al
.get(i
), alComments
.get(i
));
142 if (i
!= al
.size() - 1) {
143 cInstCode
+= commaNewLine
;
147 decl
= new CStructTypeDeclaration (
155 instTable
.put(stringTable
, cInstCode
);
159 public int add (String inputStr
, Token token
) {
163 String str
= inputStr
;
166 // The input can be two types:
167 // "L\"Bootmode\"" or "Bootmode".
168 // We drop the L\" and \" for the first type.
169 if (str
.startsWith("L\"") && str
.endsWith("\"")) {
170 str
= str
.substring(2, str
.length() - 1);
173 // Check if StringTable has this String already.
174 // If so, return the current pos.
176 for (i
= 0, pos
= 0; i
< al
.size(); i
++) {
177 String s
= al
.get(i
);;
182 pos
= s
.length() + 1;
187 // Include the NULL character at the end of String
189 len
+= str
.length() + 1;
191 alComments
.add(token
.getPrimaryKeyString());
200 This class is used to store the Size information for
201 POINTER TYPE PCD entry in a PCD database.
205 private ArrayList
<ArrayList
<Integer
>> al
;
206 private ArrayList
<String
> alComments
;
208 private String phase
;
210 public SizeTable (String phase
) {
211 al
= new ArrayList
<ArrayList
<Integer
>>();
212 alComments
= new ArrayList
<String
>();
217 public String
getSizeMacro () {
218 return String
.format(PcdDatabase
.SizeTableSizeMacro
, phase
, getSize());
221 private int getSize() {
222 return len
== 0 ?
1 : len
;
225 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
226 final String name
= "SizeTable";
228 CStructTypeDeclaration decl
;
231 cCode
= String
.format(PcdDatabase
.SizeTableDeclaration
, phase
);
232 decl
= new CStructTypeDeclaration (
241 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
242 instTable
.put(name
, cCode
);
245 private ArrayList
<String
> getInstantiation () {
246 final String comma
= ",";
247 ArrayList
<String
> Output
= new ArrayList
<String
>();
249 Output
.add("/* SizeTable */");
251 if (al
.size() == 0) {
254 for (int index
= 0; index
< al
.size(); index
++) {
255 ArrayList
<Integer
> ial
= al
.get(index
);
259 for (int index2
= 0; index2
< ial
.size(); index2
++) {
260 str
+= " " + ial
.get(index2
).toString();
261 if (index2
!= ial
.size() - 1) {
266 str
+= " /* " + alComments
.get(index
) + " */";
268 if (index
!= (al
.size() - 1)) {
281 public void add (Token token
) {
284 // We only have size information for POINTER type PCD entry.
286 if (token
.datumType
!= Token
.DATUM_TYPE
.POINTER
) {
290 ArrayList
<Integer
> ial
= token
.getPointerTypeSize();
295 alComments
.add(token
.getPrimaryKeyString());
305 This class is used to store the GUIDs in a PCD database.
308 private ArrayList
<UUID
> al
;
309 private ArrayList
<String
> alComments
;
310 private String phase
;
312 private int bodyLineNum
;
314 public GuidTable (String phase
) {
316 al
= new ArrayList
<UUID
>();
317 alComments
= new ArrayList
<String
>();
322 public String
getSizeMacro () {
323 return String
.format(PcdDatabase
.GuidTableSizeMacro
, phase
, getSize());
326 private int getSize () {
327 return (al
.size() == 0)?
1 : al
.size();
330 public String
getExistanceMacro () {
331 return String
.format(PcdDatabase
.GuidTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
334 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
335 final String name
= "GuidTable";
337 CStructTypeDeclaration decl
;
340 cCode
+= String
.format(PcdDatabase
.GuidTableDeclaration
, phase
);
341 decl
= new CStructTypeDeclaration (
350 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
351 instTable
.put(name
, cCode
);
354 private String
getUuidCString (UUID uuid
) {
355 String
[] guidStrArray
;
357 guidStrArray
=(uuid
.toString()).split("-");
359 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}}",
363 (guidStrArray
[3].substring(0, 2)),
364 (guidStrArray
[3].substring(2, 4)),
365 (guidStrArray
[4].substring(0, 2)),
366 (guidStrArray
[4].substring(2, 4)),
367 (guidStrArray
[4].substring(4, 6)),
368 (guidStrArray
[4].substring(6, 8)),
369 (guidStrArray
[4].substring(8, 10)),
370 (guidStrArray
[4].substring(10, 12))
374 private ArrayList
<String
> getInstantiation () {
375 ArrayList
<String
> Output
= new ArrayList
<String
>();
377 Output
.add("/* GuidTable */");
380 if (al
.size() == 0) {
381 Output
.add("\t" + getUuidCString(new UUID(0, 0)));
384 for (int i
= 0; i
< al
.size(); i
++) {
385 String str
= "\t" + getUuidCString(al
.get(i
));
387 str
+= "/* " + alComments
.get(i
) + " */";
388 if (i
!= (al
.size() - 1)) {
400 public int add (UUID uuid
, String name
) {
402 // Check if GuidTable has this entry already.
403 // If so, return the GuidTable index.
405 for (int i
= 0; i
< al
.size(); i
++) {
406 if (al
.get(i
).compareTo(uuid
) == 0) {
413 alComments
.add(name
);
416 // Return the previous Table Index
426 This class is used to store the SKU IDs in a PCD database.
430 private ArrayList
<Integer
[]> al
;
431 private ArrayList
<String
> alComment
;
432 private String phase
;
435 public SkuIdTable (String phase
) {
437 al
= new ArrayList
<Integer
[]>();
438 alComment
= new ArrayList
<String
>();
442 public String
getSizeMacro () {
443 return String
.format(PcdDatabase
.SkuIdTableSizeMacro
, phase
, getSize());
446 private int getSize () {
447 return (len
== 0)?
1 : len
;
450 public String
getExistanceMacro () {
451 return String
.format(PcdDatabase
.SkuTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
454 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
455 final String name
= "SkuIdTable";
457 CStructTypeDeclaration decl
;
460 cCode
+= String
.format(PcdDatabase
.SkuIdTableDeclaration
, phase
);
461 decl
= new CStructTypeDeclaration (
470 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
471 instTable
.put(name
, cCode
);
474 // SystemSkuId is in PEI phase PCD Database
476 if (phase
.equalsIgnoreCase("PEI")) {
477 decl
= new CStructTypeDeclaration (
480 String
.format("%-20sSystemSkuId;\r\n", "SKU_ID"),
485 instTable
.put("SystemSkuId", "0");
490 private ArrayList
<String
> getInstantiation () {
491 ArrayList
<String
> Output
= new ArrayList
<String
> ();
493 Output
.add("/* SkuIdTable */");
496 if (al
.size() == 0) {
500 for (int index
= 0; index
< al
.size(); index
++) {
503 str
= "/* " + alComment
.get(index
) + "*/ ";
504 str
+= "/* MaxSku */ ";
507 Integer
[] ia
= al
.get(index
);
509 str
+= "\t" + ia
[0].toString() + ", ";
510 for (int index2
= 1; index2
< ia
.length
; index2
++) {
511 str
+= ia
[index2
].toString();
512 if (!((index2
== ia
.length
- 1) && (index
== al
.size() - 1))) {
526 public int add (Token token
) {
532 // Check if this SKU_ID Array is already in the table
536 Integer
[] s
= (Integer
[]) o
;
537 boolean different
= false;
538 if (s
[0] == token
.getSkuIdCount()) {
539 for (index
= 1; index
< s
.length
; index
++) {
540 if (s
[index
] != token
.skuData
.get(index
-1).id
) {
555 Integer
[] skuIds
= new Integer
[token
.skuData
.size() + 1];
556 skuIds
[0] = new Integer(token
.skuData
.size());
557 for (index
= 1; index
< skuIds
.length
; index
++) {
558 skuIds
[index
] = new Integer(token
.skuData
.get(index
- 1).id
);
563 len
+= skuIds
.length
;
565 alComment
.add(token
.getPrimaryKeyString());
572 class LocalTokenNumberTable
{
573 private ArrayList
<String
> al
;
574 private ArrayList
<String
> alComment
;
575 private String phase
;
578 public LocalTokenNumberTable (String phase
) {
580 al
= new ArrayList
<String
>();
581 alComment
= new ArrayList
<String
>();
586 public String
getSizeMacro () {
587 return String
.format(PcdDatabase
.LocalTokenNumberTableSizeMacro
, phase
, getSize())
588 + String
.format(PcdDatabase
.LocalTokenNumberSizeMacro
, phase
, al
.size());
591 public int getSize () {
592 return (al
.size() == 0)?
1 : al
.size();
595 public String
getExistanceMacro () {
596 return String
.format(PcdDatabase
.DatabaseExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
599 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
600 final String name
= "LocalTokenNumberTable";
602 CStructTypeDeclaration decl
;
605 cCode
+= String
.format(PcdDatabase
.LocalTokenNumberTableDeclaration
, phase
);
606 decl
= new CStructTypeDeclaration (
614 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
615 instTable
.put(name
, cCode
);
618 private ArrayList
<String
> getInstantiation () {
619 ArrayList
<String
> output
= new ArrayList
<String
>();
621 output
.add("/* LocalTokenNumberTable */");
624 if (al
.size() == 0) {
628 for (int index
= 0; index
< al
.size(); index
++) {
631 str
= "\t" + (String
)al
.get(index
);
633 str
+= " /* " + alComment
.get(index
) + " */ ";
636 if (index
!= (al
.size() - 1)) {
649 public int add (Token token
) {
655 str
= String
.format(PcdDatabase
.offsetOfStrTemplate
, phase
, token
.hasDefaultValue() ?
"Init" : "Uninit", token
.getPrimaryKeyString());
657 if (token
.isUnicodeStringType()) {
658 str
+= " | PCD_TYPE_STRING";
661 if (token
.isSkuEnable()) {
662 str
+= " | PCD_TYPE_SKU_ENABLED";
665 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
666 str
+= " | PCD_TYPE_HII";
669 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
670 str
+= " | PCD_TYPE_VPD";
673 switch (token
.datumType
) {
676 str
+= " | PCD_DATUM_TYPE_UINT8";
679 str
+= " | PCD_DATUM_TYPE_UINT16";
682 str
+= " | PCD_DATUM_TYPE_UINT32";
685 str
+= " | PCD_DATUM_TYPE_UINT64";
688 str
+= " | PCD_DATUM_TYPE_POINTER";
693 alComment
.add(token
.getPrimaryKeyString());
702 This class is used to store the table of mapping information
703 between DynamicEX ID pair(Guid, TokenNumber) and
704 the local token number assigned by PcdDatabase class.
711 This class is used to store the mapping information
712 between DynamicEX ID pair(Guid, TokenNumber) and
713 the local token number assigned by PcdDatabase class.
716 public Integer guidTableIdx
;
717 public Long exTokenNumber
;
718 public Long localTokenIdx
;
720 public ExTriplet (int guidTableIdx
, long exTokenNumber
, long localTokenIdx
) {
721 this.guidTableIdx
= new Integer(guidTableIdx
);
722 this.exTokenNumber
= new Long(exTokenNumber
);
723 this.localTokenIdx
= new Long(localTokenIdx
);
727 private ArrayList
<ExTriplet
> al
;
728 private Map
<ExTriplet
, String
> alComment
;
729 private String phase
;
731 private int bodyLineNum
;
733 public ExMapTable (String phase
) {
735 al
= new ArrayList
<ExTriplet
>();
736 alComment
= new HashMap
<ExTriplet
, String
>();
741 public String
getSizeMacro () {
742 return String
.format(PcdDatabase
.ExMapTableSizeMacro
, phase
, getTableLen())
743 + String
.format(PcdDatabase
.ExTokenNumber
, phase
, al
.size());
746 public String
getExistanceMacro () {
747 return String
.format(PcdDatabase
.ExMapTableExistenceMacro
, phase
, (al
.size() == 0)?
"TRUE":"FALSE");
750 public void genCode (ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) {
751 final String exMapTableName
= "ExMapTable";
755 CStructTypeDeclaration decl
;
758 cCode
+= String
.format(PcdDatabase
.ExMapTableDeclaration
, phase
);
759 decl
= new CStructTypeDeclaration (
768 cCode
= PcdDatabase
.genInstantiationStr(getInstantiation());
769 instTable
.put(exMapTableName
, cCode
);
772 private ArrayList
<String
> getInstantiation () {
773 ArrayList
<String
> Output
= new ArrayList
<String
>();
775 Output
.add("/* ExMapTable */");
777 if (al
.size() == 0) {
778 Output
.add("\t{0, 0, 0}");
782 for (index
= 0; index
< al
.size(); index
++) {
785 ExTriplet e
= (ExTriplet
)al
.get(index
);
787 str
= "\t" + "{ " + String
.format("0x%08X", e
.exTokenNumber
) + ", ";
788 str
+= e
.localTokenIdx
.toString() + ", ";
789 str
+= e
.guidTableIdx
.toString();
791 str
+= "}" + " /* " + alComment
.get(e
) + " */" ;
793 if (index
!= al
.size() - 1) {
807 public int add (int localTokenIdx
, long exTokenNum
, int guidTableIdx
, String name
) {
811 ExTriplet et
= new ExTriplet(guidTableIdx
, exTokenNum
, localTokenIdx
);
814 alComment
.put(et
, name
);
819 private int getTableLen () {
820 return al
.size() == 0 ?
1 : al
.size();
824 // To simplify the algorithm for GetNextToken and GetNextTokenSpace in
825 // PCD PEIM/Driver, we need to sort the ExMapTable according to the
830 class ExTripletComp
implements Comparator
<ExTriplet
> {
831 public int compare (ExTriplet a
, ExTriplet b
) {
832 if (a
.guidTableIdx
== b
.guidTableIdx
) {
834 // exTokenNumber is long, we can't use simple substraction.
836 if (a
.exTokenNumber
> b
.exTokenNumber
) {
838 } else if (a
.exTokenNumber
== b
.exTokenNumber
) {
845 return a
.guidTableIdx
- b
.guidTableIdx
;
849 private void sortTable () {
850 java
.util
.Comparator
<ExTriplet
> comparator
= new ExTripletComp();
851 java
.util
.Collections
.sort(al
, comparator
);
858 This class is used to generate C code for Autogen.h and Autogen.c of
859 a PCD service DXE driver and PCD service PEIM.
861 public class PcdDatabase
{
863 private final static int SkuHeadAlignmentSize
= 4;
864 private final String newLine
= "\r\n";
865 private final String commaNewLine
= ",\r\n";
866 private final String tab
= "\t";
867 public final static String ExMapTableDeclaration
= "DYNAMICEX_MAPPING ExMapTable[%s_EXMAPPING_TABLE_SIZE];\r\n";
868 public final static String GuidTableDeclaration
= "EFI_GUID GuidTable[%s_GUID_TABLE_SIZE];\r\n";
869 public final static String LocalTokenNumberTableDeclaration
= "UINT32 LocalTokenNumberTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";
870 public final static String StringTableDeclaration
= "UINT16 StringTable[%s_STRING_TABLE_SIZE];\r\n";
871 public final static String SizeTableDeclaration
= "SIZE_INFO SizeTable[%s_SIZE_TABLE_SIZE];\r\n";
872 public final static String SkuIdTableDeclaration
= "UINT8 SkuIdTable[%s_SKUID_TABLE_SIZE];\r\n";
875 public final static String ExMapTableSizeMacro
= "#define %s_EXMAPPING_TABLE_SIZE %d\r\n";
876 public final static String ExTokenNumber
= "#define %s_EX_TOKEN_NUMBER %d\r\n";
877 public final static String GuidTableSizeMacro
= "#define %s_GUID_TABLE_SIZE %d\r\n";
878 public final static String LocalTokenNumberTableSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER_TABLE_SIZE %d\r\n";
879 public final static String LocalTokenNumberSizeMacro
= "#define %s_LOCAL_TOKEN_NUMBER %d\r\n";
880 public final static String SizeTableSizeMacro
= "#define %s_SIZE_TABLE_SIZE %d\r\n";
881 public final static String StringTableSizeMacro
= "#define %s_STRING_TABLE_SIZE %d\r\n";
882 public final static String SkuIdTableSizeMacro
= "#define %s_SKUID_TABLE_SIZE %d\r\n";
885 public final static String ExMapTableExistenceMacro
= "#define %s_EXMAP_TABLE_EMPTY %s\r\n";
886 public final static String GuidTableExistenceMacro
= "#define %s_GUID_TABLE_EMPTY %s\r\n";
887 public final static String DatabaseExistenceMacro
= "#define %s_DATABASE_EMPTY %s\r\n";
888 public final static String StringTableExistenceMacro
= "#define %s_STRING_TABLE_EMPTY %s\r\n";
889 public final static String SkuTableExistenceMacro
= "#define %s_SKUID_TABLE_EMPTY %s\r\n";
891 public final static String offsetOfSkuHeadStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)";
892 public final static String offsetOfVariableEnabledDefault
= "offsetof(%s_PCD_DATABASE, %s.%s_VariableDefault_%d)";
893 public final static String offsetOfStrTemplate
= "offsetof(%s_PCD_DATABASE, %s.%s)";
895 private final static String skuDataTableTemplate
= "SkuDataTable";
898 private StringTable stringTable
;
899 private GuidTable guidTable
;
900 private LocalTokenNumberTable localTokenNumberTable
;
901 private SkuIdTable skuIdTable
;
902 private SizeTable sizeTable
;
903 private ExMapTable exMapTable
;
905 private ArrayList
<Token
> alTokens
;
906 private String phase
;
907 private int assignedTokenNumber
;
910 // Use two class global variable to store
913 private String privateGlobalName
;
914 private String privateGlobalCCode
;
916 // After Major changes done to the PCD
917 // database generation class PcdDatabase
918 // Please increment the version and please
919 // also update the version number in PCD
920 // service PEIM and DXE driver accordingly.
922 private final int version
= 2;
924 private String hString
;
925 private String cString
;
928 Constructor for PcdDatabase class.
930 <p>We have two PCD dynamic(ex) database for the Framework implementation. One
931 for PEI phase and the other for DXE phase. </p>
933 @param alTokens A ArrayList of Dynamic(EX) PCD entry.
934 @param exePhase The phase to generate PCD database for: valid input
936 @param startLen The starting Local Token Number for the PCD database. For
937 PEI phase, the starting Local Token Number starts from 0.
938 For DXE phase, the starting Local Token Number starts
939 from the total number of PCD entry of PEI phase.
942 public PcdDatabase (ArrayList
<Token
> alTokens
, String exePhase
, int startLen
) {
945 stringTable
= new StringTable(phase
);
946 guidTable
= new GuidTable(phase
);
947 localTokenNumberTable
= new LocalTokenNumberTable(phase
);
948 skuIdTable
= new SkuIdTable(phase
);
949 sizeTable
= new SizeTable(phase
);
950 exMapTable
= new ExMapTable(phase
);
953 // Local token number 0 is reserved for INVALID_TOKEN_NUMBER.
954 // So we will increment 1 for the startLen passed from the
957 assignedTokenNumber
= startLen
+ 1;
958 this.alTokens
= alTokens
;
961 private void getNonExAndExTokens (ArrayList
<Token
> alTokens
, List
<Token
> nexTokens
, List
<Token
> exTokens
) {
962 for (int i
= 0; i
< alTokens
.size(); i
++) {
963 Token t
= (Token
)alTokens
.get(i
);
964 if (t
.isDynamicEx()) {
974 private int getDataTypeAlignmentSize (Token token
) {
975 switch (token
.datumType
) {
993 private int getHiiPtrTypeAlignmentSize(Token token
) {
994 switch (token
.datumType
) {
1004 if (token
.isHiiEnable()) {
1005 if (token
.isHiiDefaultValueUnicodeStringType()) {
1017 private int getAlignmentSize (Token token
) {
1018 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.HII_TYPE
) {
1022 if (token
.getDefaultSku().type
== DynamicTokenValue
.VALUE_TYPE
.VPD_TYPE
) {
1026 if (token
.isUnicodeStringType()) {
1030 return getDataTypeAlignmentSize(token
);
1033 public String
getCString () {
1037 public String
getHString () {
1041 private void genCodeWorker(Token t
,
1042 ArrayList
<CStructTypeDeclaration
> declaList
,
1043 HashMap
<String
, String
> instTable
, String phase
)
1044 throws EntityException
{
1046 CStructTypeDeclaration decl
;
1049 // Insert SKU_HEAD if isSkuEnable is true
1051 if (t
.isSkuEnable()) {
1053 tableIdx
= skuIdTable
.add(t
);
1054 decl
= new CStructTypeDeclaration(t
.getPrimaryKeyString(),
1055 SkuHeadAlignmentSize
, getSkuEnabledTypeDeclaration(t
), true);
1056 declaList
.add(decl
);
1057 instTable
.put(t
.getPrimaryKeyString(),
1058 getSkuEnabledTypeInstantiaion(t
, tableIdx
));
1062 // Insert PCD_ENTRY declaration and instantiation
1064 getCDeclarationString(t
);
1066 decl
= new CStructTypeDeclaration(privateGlobalName
,
1067 getAlignmentSize(t
), privateGlobalCCode
, t
.hasDefaultValue());
1068 declaList
.add(decl
);
1070 if (t
.hasDefaultValue()) {
1071 instTable
.put(privateGlobalName
,
1072 getTypeInstantiation(t
, declaList
, instTable
, phase
)
1078 private void ProcessTokens (List
<Token
> tokens
,
1079 ArrayList
<CStructTypeDeclaration
> cStructDeclList
,
1080 HashMap
<String
, String
> cStructInstTable
,
1083 throws EntityException
{
1085 for (int idx
= 0; idx
< tokens
.size(); idx
++) {
1086 Token t
= tokens
.get(idx
);
1088 genCodeWorker (t
, cStructDeclList
, cStructInstTable
, phase
);
1091 localTokenNumberTable
.add(t
);
1092 t
.tokenNumber
= assignedTokenNumber
++;
1095 // Add a mapping if this dynamic PCD entry is a EX type
1097 if (t
.isDynamicEx()) {
1098 exMapTable
.add((int)t
.tokenNumber
,
1099 t
.dynamicExTokenNumber
,
1100 guidTable
.add(translateSchemaStringToUUID(t
.tokenSpaceName
), t
.getPrimaryKeyString()),
1101 t
.getPrimaryKeyString()
1108 public void genCode () throws EntityException
{
1110 ArrayList
<CStructTypeDeclaration
> cStructDeclList
= new ArrayList
<CStructTypeDeclaration
>();
1111 HashMap
<String
, String
> cStructInstTable
= new HashMap
<String
, String
>();
1113 List
<Token
> nexTokens
= new ArrayList
<Token
> ();
1114 List
<Token
> exTokens
= new ArrayList
<Token
> ();
1116 getNonExAndExTokens (alTokens
, nexTokens
, exTokens
);
1119 // We have to process Non-Ex type PCD entry first. The reason is
1120 // that our optimization assumes that the Token Number of Non-Ex
1121 // PCD entry start from 1 (for PEI phase) and grows continously upwards.
1123 // EX type token number starts from the last Non-EX PCD entry and
1124 // grows continously upwards.
1126 ProcessTokens (nexTokens
, cStructDeclList
, cStructInstTable
, phase
);
1127 ProcessTokens (exTokens
, cStructDeclList
, cStructInstTable
, phase
);
1129 stringTable
.genCode(cStructDeclList
, cStructInstTable
);
1130 skuIdTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1131 exMapTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1132 localTokenNumberTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1133 sizeTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1134 guidTable
.genCode(cStructDeclList
, cStructInstTable
, phase
);
1136 hString
= genCMacroCode ();
1138 HashMap
<String
, String
> result
;
1140 result
= genCStructCode(cStructDeclList
,
1145 hString
+= result
.get("initDeclStr");
1146 hString
+= result
.get("uninitDeclStr");
1148 hString
+= String
.format("#define PCD_%s_SERVICE_DRIVER_VERSION %d", phase
, version
);
1150 cString
= newLine
+ newLine
+ result
.get("initInstStr");
1154 private String
genCMacroCode () {
1155 String macroStr
= "";
1158 // Generate size info Macro for all Tables
1160 macroStr
+= guidTable
.getSizeMacro();
1161 macroStr
+= stringTable
.getSizeMacro();
1162 macroStr
+= skuIdTable
.getSizeMacro();
1163 macroStr
+= localTokenNumberTable
.getSizeMacro();
1164 macroStr
+= exMapTable
.getSizeMacro();
1165 macroStr
+= sizeTable
.getSizeMacro();
1168 // Generate existance info Macro for all Tables
1170 macroStr
+= guidTable
.getExistanceMacro();
1171 macroStr
+= stringTable
.getExistanceMacro();
1172 macroStr
+= skuIdTable
.getExistanceMacro();
1173 macroStr
+= localTokenNumberTable
.getExistanceMacro();
1174 macroStr
+= exMapTable
.getExistanceMacro();
1176 macroStr
+= newLine
;
1181 private HashMap
<String
, String
> genCStructCode(
1182 ArrayList
<CStructTypeDeclaration
> declaList
,
1183 HashMap
<String
, String
> instTable
,
1188 HashMap
<String
, String
> result
= new HashMap
<String
, String
>();
1189 HashMap
<Integer
, ArrayList
<String
>> alignmentInitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1190 HashMap
<Integer
, ArrayList
<String
>> alignmentUninitDecl
= new HashMap
<Integer
, ArrayList
<String
>>();
1191 HashMap
<Integer
, ArrayList
<String
>> alignmentInitInst
= new HashMap
<Integer
, ArrayList
<String
>>();
1194 // Initialize the storage for each alignment
1196 for (i
= 8; i
> 0; i
>>=1) {
1197 alignmentInitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1198 alignmentInitInst
.put(new Integer(i
), new ArrayList
<String
>());
1199 alignmentUninitDecl
.put(new Integer(i
), new ArrayList
<String
>());
1202 String initDeclStr
= "typedef struct {" + newLine
;
1203 String initInstStr
= String
.format("%s_PCD_DATABASE_INIT g%sPcdDbInit = { ", phase
.toUpperCase(), phase
.toUpperCase()) + newLine
;
1204 String uninitDeclStr
= "typedef struct {" + newLine
;
1207 // Sort all C declaration and instantiation base on Alignment Size
1209 for (Object d
: declaList
) {
1210 CStructTypeDeclaration decl
= (CStructTypeDeclaration
) d
;
1212 if (decl
.initTable
) {
1213 alignmentInitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1214 alignmentInitInst
.get(new Integer(decl
.alignmentSize
)).add(instTable
.get(decl
.key
));
1216 alignmentUninitDecl
.get(new Integer(decl
.alignmentSize
)).add(decl
.cCode
);
1221 // Generate code for every alignment size
1223 boolean uinitDatabaseEmpty
= true;
1224 for (int align
= 8; align
> 0; align
>>= 1) {
1225 ArrayList
<String
> declaListBasedOnAlignment
= alignmentInitDecl
.get(new Integer(align
));
1226 ArrayList
<String
> instListBasedOnAlignment
= alignmentInitInst
.get(new Integer(align
));
1227 for (i
= 0; i
< declaListBasedOnAlignment
.size(); i
++) {
1228 initDeclStr
+= tab
+ declaListBasedOnAlignment
.get(i
);
1229 initInstStr
+= tab
+ instListBasedOnAlignment
.get(i
);
1232 // We made a assumption that both PEI_PCD_DATABASE and DXE_PCD_DATABASE
1233 // has a least one data memember with alignment size of 1. So we can
1234 // remove the last "," in the C structure instantiation string. Luckily,
1235 // this is true as both data structure has SKUID_TABLE anyway.
1237 if ((align
== 1) && (i
== declaListBasedOnAlignment
.size() - 1)) {
1238 initInstStr
+= newLine
;
1240 initInstStr
+= commaNewLine
;
1244 declaListBasedOnAlignment
= alignmentUninitDecl
.get(new Integer(align
));
1246 if (declaListBasedOnAlignment
.size() != 0) {
1247 uinitDatabaseEmpty
= false;
1250 for (Object d
: declaListBasedOnAlignment
) {
1251 String s
= (String
)d
;
1252 uninitDeclStr
+= tab
+ s
;
1256 if (uinitDatabaseEmpty
) {
1257 uninitDeclStr
+= tab
+ String
.format("%-20sdummy; /* PCD_DATABASE_UNINIT is emptry */\r\n", "UINT8");
1260 initDeclStr
+= String
.format("} %s_PCD_DATABASE_INIT;", phase
) + newLine
+ newLine
;
1261 initInstStr
+= "};" + newLine
;
1262 uninitDeclStr
+= String
.format("} %s_PCD_DATABASE_UNINIT;", phase
) + newLine
+ newLine
;
1264 result
.put("initDeclStr", initDeclStr
);
1265 result
.put("initInstStr", initInstStr
);
1266 result
.put("uninitDeclStr", uninitDeclStr
);
1271 public static String
genInstantiationStr (ArrayList
<String
> alStr
) {
1273 for (int i
= 0; i
< alStr
.size(); i
++) {
1277 str
+= alStr
.get(i
);
1278 if (i
!= alStr
.size() - 1) {
1286 private String
getSkuEnabledTypeDeclaration (Token token
) {
1287 return String
.format("%-20s%s;\r\n", "SKU_HEAD", token
.getPrimaryKeyString());
1290 private String
getSkuEnabledTypeInstantiaion (Token token
, int SkuTableIdx
) {
1292 String offsetof
= String
.format(PcdDatabase
.offsetOfSkuHeadStrTemplate
, phase
, token
.hasDefaultValue()?
"Init" : "Uninit", token
.getPrimaryKeyString());
1293 return String
.format("{ %s, %d } /* SKU_ENABLED: %s */", offsetof
, SkuTableIdx
, token
.getPrimaryKeyString());
1296 private String
getDataTypeInstantiationForVariableDefault (Token token
, String cName
, int skuId
) {
1297 return String
.format("%s /* %s */", token
.skuData
.get(skuId
).value
.hiiDefaultValue
, cName
);
1300 private String
getCType (Token t
)
1301 throws EntityException
{
1303 if (t
.isHiiEnable()) {
1304 return "VARIABLE_HEAD";
1307 if (t
.isVpdEnable()) {
1311 if (t
.isUnicodeStringType()) {
1312 return "STRING_HEAD";
1315 switch (t
.datumType
) {
1329 throw new EntityException("Unknown type in getDataTypeCDeclaration");
1334 // privateGlobalName and privateGlobalCCode is used to pass output to caller of getCDeclarationString
1336 private void getCDeclarationString(Token t
)
1337 throws EntityException
{
1339 if (t
.isSkuEnable()) {
1340 privateGlobalName
= String
.format("%s_%s", t
.getPrimaryKeyString(), skuDataTableTemplate
);
1342 privateGlobalName
= t
.getPrimaryKeyString();
1345 String type
= getCType(t
);
1346 if ((t
.datumType
== Token
.DATUM_TYPE
.POINTER
) && (!t
.isHiiEnable()) && (!t
.isUnicodeStringType())) {
1348 if (t
.isASCIIStringType()) {
1350 // Build tool will add a NULL string at the end of the ASCII string
1352 bufferSize
= t
.datumSize
+ 1;
1354 bufferSize
= t
.datumSize
;
1356 privateGlobalCCode
= String
.format("%-20s%s[%d][%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount(), bufferSize
);
1358 privateGlobalCCode
= String
.format("%-20s%s[%d];\r\n", type
, privateGlobalName
, t
.getSkuIdCount());
1362 private String
getDataTypeDeclarationForVariableDefault (Token token
, String cName
, int skuId
)
1363 throws EntityException
{
1367 if (token
.datumType
== Token
.DATUM_TYPE
.UINT8
) {
1369 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT16
) {
1371 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT32
) {
1373 } else if (token
.datumType
== Token
.DATUM_TYPE
.UINT64
) {
1375 } else if (token
.datumType
== Token
.DATUM_TYPE
.BOOLEAN
) {
1376 typeStr
= "BOOLEAN";
1377 } else if (token
.datumType
== Token
.DATUM_TYPE
.POINTER
) {
1379 if (token
.isHiiDefaultValueUnicodeStringType()) {
1382 // Include the NULL charactor
1384 size
= token
.datumSize
/ 2 + 1;
1387 if (token
.isHiiDefaultValueASCIIStringType()) {
1389 // Include the NULL charactor
1391 size
= token
.datumSize
+ 1;
1393 size
= token
.datumSize
;
1396 return String
.format("%-20s%s[%d];\r\n", typeStr
, cName
, size
);
1398 throw new EntityException("Unknown DATUM_TYPE type in when generating code for VARIABLE_ENABLED PCD entry");
1401 return String
.format("%-20s%s;\r\n", typeStr
, cName
);
1404 private String
getTypeInstantiation (Token t
, ArrayList
<CStructTypeDeclaration
> declaList
, HashMap
<String
, String
> instTable
, String phase
) throws EntityException
{
1409 s
= String
.format("/* %s */", t
.getPrimaryKeyString()) + newLine
;
1410 s
+= tab
+ "{" + newLine
;
1412 for (i
= 0; i
< t
.skuData
.size(); i
++) {
1413 if (t
.isUnicodeStringType()) {
1414 s
+= tab
+ tab
+ String
.format("{ %d }", stringTable
.add(t
.skuData
.get(i
).value
.value
, t
));
1415 } else if (t
.isHiiEnable()) {
1416 /* VPD_HEAD definition
1418 UINT16 GuidTableIndex; // Offset in Guid Table in units of GUID.
1419 UINT16 StringIndex; // Offset in String Table in units of UINT16.
1420 UINT16 Offset; // Offset in Variable
1421 UINT16 DefaultValueOffset; // Offset of the Default Value
1424 String variableDefaultName
= String
.format("%s_VariableDefault_%d", t
.getPrimaryKeyString(), i
);
1426 s
+= tab
+ tab
+ String
.format("{ %d, %d, %s, %s }", guidTable
.add(t
.skuData
.get(i
).value
.variableGuid
, t
.getPrimaryKeyString()),
1427 stringTable
.add(t
.skuData
.get(i
).value
.getStringOfVariableName(), t
),
1428 t
.skuData
.get(i
).value
.variableOffset
,
1429 String
.format("offsetof(%s_PCD_DATABASE, Init.%s)", phase
, variableDefaultName
)
1432 // We need to support the default value, so we add the declaration and
1433 // the instantiation for the default value.
1435 CStructTypeDeclaration decl
= new CStructTypeDeclaration (variableDefaultName
,
1436 getHiiPtrTypeAlignmentSize(t
),
1437 getDataTypeDeclarationForVariableDefault(t
, variableDefaultName
, i
),
1440 declaList
.add(decl
);
1441 instTable
.put(variableDefaultName
, getDataTypeInstantiationForVariableDefault (t
, variableDefaultName
, i
));
1442 } else if (t
.isVpdEnable()) {
1447 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.vpdOffset
);
1449 if (t
.isByteStreamType()) {
1451 // Byte stream type input has their own "{" "}", so we won't help to insert.
1453 s
+= tab
+ tab
+ String
.format(" %s ", t
.skuData
.get(i
).value
.value
);
1455 s
+= tab
+ tab
+ String
.format("{ %s }", t
.skuData
.get(i
).value
.value
);
1459 if (i
!= t
.skuData
.size() - 1) {
1472 public static String
getPcdDatabaseCommonDefinitions ()
1473 throws EntityException
{
1477 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1478 "Tools" + File
.separator
+
1479 "Conf" + File
.separator
+
1480 "Pcd" + File
.separator
+
1481 "PcdDatabaseCommonDefinitions.sample");
1482 FileReader reader
= new FileReader(file
);
1483 BufferedReader in
= new BufferedReader(reader
);
1485 while ((str
= in
.readLine()) != null) {
1486 retStr
= retStr
+"\r\n" + str
;
1488 } catch (Exception ex
) {
1489 throw new EntityException("Fatal error when generating PcdDatabase Common Definitions");
1495 public static String
getPcdDxeDatabaseDefinitions ()
1496 throws EntityException
{
1500 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1501 "Tools" + File
.separator
+
1502 "Conf" + File
.separator
+
1503 "Pcd" + File
.separator
+
1504 "PcdDatabaseDxeDefinitions.sample");
1505 FileReader reader
= new FileReader(file
);
1506 BufferedReader in
= new BufferedReader(reader
);
1508 while ((str
= in
.readLine()) != null) {
1509 retStr
= retStr
+"\r\n" + str
;
1511 } catch (Exception ex
) {
1512 throw new EntityException("Fatal error when generating PcdDatabase Dxe Definitions");
1518 public static String
getPcdPeiDatabaseDefinitions ()
1519 throws EntityException
{
1523 File file
= new File(GlobalData
.getWorkspacePath() + File
.separator
+
1524 "Tools" + File
.separator
+
1525 "Conf" + File
.separator
+
1526 "Pcd" + File
.separator
+
1527 "PcdDatabasePeiDefinitions.sample");
1528 FileReader reader
= new FileReader(file
);
1529 BufferedReader in
= new BufferedReader(reader
);
1531 while ((str
= in
.readLine()) != null) {
1532 retStr
= retStr
+"\r\n" + str
;
1534 } catch (Exception ex
) {
1535 throw new EntityException("Fatal error when generating PcdDatabase Pei Definitions");
1542 Translate the schema string to UUID instance.
1544 In schema, the string of UUID is defined as following two types string:
1545 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(
1546 )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?
1548 2) GuidNamingConvention: pattern =
1549 [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}
1551 This function will convert string and create uuid instance.
1553 @param uuidString UUID string in XML file
1555 @return UUID UUID instance
1557 private UUID
translateSchemaStringToUUID(String uuidString
)
1558 throws EntityException
{
1560 String
[] splitStringArray
;
1565 if (uuidString
== null) {
1569 if (uuidString
.length() == 0) {
1573 if (uuidString
.equals("0") ||
1574 uuidString
.equalsIgnoreCase("0x0")) {
1575 return new UUID(0, 0);
1578 uuidString
= uuidString
.replaceAll("\\{", "");
1579 uuidString
= uuidString
.replaceAll("\\}", "");
1582 // If the UUID schema string is GuidArrayType type then need translate
1583 // to GuidNamingConvention type at first.
1585 if ((uuidString
.charAt(0) == '0') && ((uuidString
.charAt(1) == 'x') || (uuidString
.charAt(1) == 'X'))) {
1586 splitStringArray
= uuidString
.split("," );
1587 if (splitStringArray
.length
!= 11) {
1588 throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString
);
1592 // Remove blank space from these string and remove header string "0x"
1594 for (index
= 0; index
< 11; index
++) {
1595 splitStringArray
[index
] = splitStringArray
[index
].trim();
1596 splitStringArray
[index
] = splitStringArray
[index
].substring(2, splitStringArray
[index
].length());
1600 // Add heading '0' to normalize the string length
1602 for (index
= 3; index
< 11; index
++) {
1603 chLen
= splitStringArray
[index
].length();
1604 for (chIndex
= 0; chIndex
< 2 - chLen
; chIndex
++) {
1605 splitStringArray
[index
] = "0" + splitStringArray
[index
];
1610 // construct the final GuidNamingConvention string
1612 temp
= String
.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",
1613 splitStringArray
[0],
1614 splitStringArray
[1],
1615 splitStringArray
[2],
1616 splitStringArray
[3],
1617 splitStringArray
[4],
1618 splitStringArray
[5],
1619 splitStringArray
[6],
1620 splitStringArray
[7],
1621 splitStringArray
[8],
1622 splitStringArray
[9],
1623 splitStringArray
[10]);
1627 return UUID
.fromString(uuidString
);