/** @file | |
CollectPCDAction class. | |
This action class is to collect PCD information from MSA, SPD, FPD xml file. | |
This class will be used for wizard and build tools, So it can *not* inherit | |
from buildAction or wizardAction. | |
Copyright (c) 2006, Intel Corporation | |
All rights reserved. This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
package org.tianocore.build.pcd.action; | |
import java.io.BufferedReader; | |
import java.io.File; | |
import java.io.FileReader; | |
import java.io.IOException; | |
import java.math.BigInteger; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.Comparator; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.UUID; | |
import org.apache.xmlbeans.XmlException; | |
import org.apache.xmlbeans.XmlObject; | |
import org.tianocore.DynamicPcdBuildDefinitionsDocument; | |
import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions; | |
import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions.PcdBuildData; | |
import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo; | |
import org.tianocore.FrameworkModulesDocument; | |
import org.tianocore.FrameworkPlatformDescriptionDocument; | |
import org.tianocore.FrameworkPlatformDescriptionDocument.FrameworkPlatformDescription; | |
import org.tianocore.ModuleSADocument; | |
import org.tianocore.ModuleSADocument.ModuleSA; | |
import org.tianocore.PackageSurfaceAreaDocument; | |
import org.tianocore.PcdBuildDefinitionDocument.PcdBuildDefinition; | |
import org.tianocore.build.global.GlobalData; | |
import org.tianocore.build.global.SurfaceAreaQuery; | |
import org.tianocore.build.pcd.action.ActionMessage; | |
import org.tianocore.build.pcd.entity.DynamicTokenValue; | |
import org.tianocore.build.pcd.entity.MemoryDatabaseManager; | |
import org.tianocore.build.pcd.entity.SkuInstance; | |
import org.tianocore.build.pcd.entity.Token; | |
import org.tianocore.build.pcd.entity.UsageInstance; | |
import org.tianocore.build.pcd.exception.EntityException; | |
import org.tianocore.ModuleTypeDef; | |
class StringTable { | |
private ArrayList<String> al; | |
private ArrayList<String> alComments; | |
private String phase; | |
int len; | |
int bodyStart; | |
int bodyLineNum; | |
public StringTable (String phase) { | |
this.phase = phase; | |
al = new ArrayList<String>(); | |
alComments = new ArrayList<String>(); | |
len = 0; | |
bodyStart = 0; | |
bodyLineNum = 0; | |
} | |
public String getSizeMacro () { | |
return String.format(PcdDatabase.StringTableSizeMacro, phase, getSize()); | |
} | |
private int getSize () { | |
// | |
// We have at least one Unicode Character in the table. | |
// | |
return len == 0 ? 1 : len; | |
} | |
public int getTableLen () { | |
return al.size() == 0 ? 1 : al.size(); | |
} | |
public String getExistanceMacro () { | |
return String.format(PcdDatabase.StringTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); | |
} | |
public String getTypeDeclaration () { | |
String output; | |
final String stringTable = "StringTable"; | |
final String tab = "\t"; | |
final String newLine = ";\r\n"; | |
output = "/* StringTable */\r\n"; | |
if (al.size() == 0) { | |
output += tab + String.format("UINT16 %s[1] /* StringTable is Empty */", stringTable) + newLine; | |
} | |
for (int i = 0; i < al.size(); i++) { | |
String str = al.get(i); | |
if (i == 0) { | |
// | |
// StringTable is a well-known name in the PCD DXE driver | |
// | |
output += tab + String.format("UINT16 %s[%d] /* %s */", stringTable, str.length() + 1, alComments.get(i)) + newLine; | |
} else { | |
output += tab + String.format("UINT16 %s_%d[%d] /* %s */", stringTable, i, str.length() + 1, alComments.get(i)) + newLine; | |
} | |
} | |
return output; | |
} | |
public ArrayList<String> getInstantiation () { | |
ArrayList<String> output = new ArrayList<String>(); | |
output.add("/* StringTable */"); | |
if (al.size() == 0) { | |
output.add("{ 0 }"); | |
} else { | |
String str; | |
for (int i = 0; i < al.size(); i++) { | |
str = String.format("L\"%s\" /* %s */", al.get(i), alComments.get(i)); | |
if (i != al.size() - 1) { | |
str += ","; | |
} | |
output.add(str); | |
} | |
} | |
return output; | |
} | |
public int add (String str, Token token) { | |
int i; | |
i = len; | |
// | |
// Include the NULL character at the end of String | |
// | |
len += str.length() + 1; | |
al.add(str); | |
alComments.add(token.getPrimaryKeyString()); | |
return i; | |
} | |
} | |
class SizeTable { | |
private ArrayList<Integer> al; | |
private ArrayList<String> alComments; | |
private String phase; | |
private int len; | |
private int bodyStart; | |
private int bodyLineNum; | |
public SizeTable (String phase) { | |
this.phase = phase; | |
al = new ArrayList<Integer>(); | |
alComments = new ArrayList<String>(); | |
len = 0; | |
bodyStart = 0; | |
bodyLineNum = 0; | |
} | |
public String getTypeDeclaration () { | |
return String.format(PcdDatabase.SizeTableDeclaration, phase); | |
} | |
public ArrayList<String> getInstantiation () { | |
ArrayList<String> Output = new ArrayList<String>(); | |
Output.add("/* SizeTable */"); | |
Output.add("{"); | |
bodyStart = 2; | |
if (al.size() == 0) { | |
Output.add("0"); | |
} else { | |
for (int index = 0; index < al.size(); index++) { | |
Integer n = al.get(index); | |
String str = n.toString(); | |
if (index != (al.size() - 1)) { | |
str += ","; | |
} | |
str += " /* " + alComments.get(index) + " */"; | |
Output.add(str); | |
bodyLineNum++; | |
} | |
} | |
Output.add("}"); | |
return Output; | |
} | |
public int getBodyStart() { | |
return bodyStart; | |
} | |
public int getBodyLineNum () { | |
return bodyLineNum; | |
} | |
public int add (Token token) { | |
int index = len; | |
len++; | |
al.add(token.datumSize); | |
alComments.add(token.getPrimaryKeyString()); | |
return index; | |
} | |
private int getDatumSize(Token token) { | |
/* | |
switch (token.datumType) { | |
case Token.DATUM_TYPE.UINT8: | |
return 1; | |
default: | |
return 0; | |
} | |
*/ | |
return 0; | |
} | |
public int getTableLen () { | |
return al.size() == 0 ? 1 : al.size(); | |
} | |
} | |
class GuidTable { | |
private ArrayList<UUID> al; | |
private ArrayList<String> alComments; | |
private String phase; | |
private int len; | |
private int bodyStart; | |
private int bodyLineNum; | |
public GuidTable (String phase) { | |
this.phase = phase; | |
al = new ArrayList<UUID>(); | |
alComments = new ArrayList<String>(); | |
len = 0; | |
bodyStart = 0; | |
bodyLineNum = 0; | |
} | |
public String getSizeMacro () { | |
return String.format(PcdDatabase.GuidTableSizeMacro, phase, getSize()); | |
} | |
private int getSize () { | |
return (al.size() == 0)? 1 : al.size(); | |
} | |
public String getExistanceMacro () { | |
return String.format(PcdDatabase.GuidTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); | |
} | |
public String getTypeDeclaration () { | |
return String.format(PcdDatabase.GuidTableDeclaration, phase); | |
} | |
private String getUuidCString (UUID uuid) { | |
String[] guidStrArray; | |
guidStrArray =(uuid.toString()).split("-"); | |
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 } }", | |
guidStrArray[0], | |
guidStrArray[1], | |
guidStrArray[2], | |
(guidStrArray[3].substring(0, 2)), | |
(guidStrArray[3].substring(2, 4)), | |
(guidStrArray[4].substring(0, 2)), | |
(guidStrArray[4].substring(2, 4)), | |
(guidStrArray[4].substring(4, 6)), | |
(guidStrArray[4].substring(6, 8)), | |
(guidStrArray[4].substring(8, 10)), | |
(guidStrArray[4].substring(10, 12)) | |
); | |
} | |
public ArrayList<String> getInstantiation () { | |
ArrayList<String> Output = new ArrayList<String>(); | |
Output.add("/* GuidTable */"); | |
Output.add("{"); | |
bodyStart = 2; | |
if (al.size() == 0) { | |
Output.add(getUuidCString(new UUID(0, 0))); | |
} | |
for (Object u : al) { | |
UUID uuid = (UUID)u; | |
String str = getUuidCString(uuid); | |
if (al.indexOf(u) != (al.size() - 1)) { | |
str += ","; | |
} | |
Output.add(str); | |
bodyLineNum++; | |
} | |
Output.add("}"); | |
return Output; | |
} | |
public int getBodyStart() { | |
return bodyStart; | |
} | |
public int getBodyLineNum () { | |
return bodyLineNum; | |
} | |
public int add (UUID uuid, String name) { | |
int index = len; | |
// | |
// Include the NULL character at the end of String | |
// | |
len++; | |
al.add(uuid); | |
return index; | |
} | |
public int getTableLen () { | |
return al.size() == 0 ? 0 : al.size(); | |
} | |
} | |
class SkuIdTable { | |
private ArrayList<Integer[]> al; | |
private ArrayList<String> alComment; | |
private String phase; | |
private int len; | |
private int bodyStart; | |
private int bodyLineNum; | |
public SkuIdTable (String phase) { | |
this.phase = phase; | |
al = new ArrayList<Integer[]>(); | |
alComment = new ArrayList<String>(); | |
bodyStart = 0; | |
bodyLineNum = 0; | |
len = 0; | |
} | |
public String getSizeMacro () { | |
return String.format(PcdDatabase.SkuIdTableSizeMacro, phase, getSize()); | |
} | |
private int getSize () { | |
return (al.size() == 0)? 1 : al.size(); | |
} | |
public String getExistanceMacro () { | |
return String.format(PcdDatabase.SkuTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); | |
} | |
public String getTypeDeclaration () { | |
return String.format(PcdDatabase.SkuIdTableDeclaration, phase); | |
} | |
public ArrayList<String> getInstantiation () { | |
ArrayList<String> Output = new ArrayList<String> (); | |
Output.add("/* SkuIdTable */"); | |
Output.add("{"); | |
bodyStart = 2; | |
if (al.size() == 0) { | |
Output.add("0"); | |
} | |
for (int index = 0; index < al.size(); index++) { | |
String str; | |
str = "/* " + alComment.get(index) + "*/ "; | |
str += "/* MaxSku */ "; | |
Integer[] ia = al.get(index); | |
str += ia[0].toString() + ", "; | |
for (int index2 = 1; index2 < ia.length; index2++) { | |
str += ia[index2].toString(); | |
if (index != al.size() - 1) { | |
str += ", "; | |
} | |
} | |
Output.add(str); | |
bodyLineNum++; | |
} | |
Output.add("}"); | |
return Output; | |
} | |
public int add (Token token) { | |
int index; | |
Integer [] skuIds = new Integer[token.skuData.size() + 1]; | |
skuIds[0] = new Integer(token.skuData.size()); | |
for (index = 1; index < skuIds.length; index++) { | |
skuIds[index] = new Integer(token.skuData.get(index - 1).id); | |
} | |
index = len; | |
len += skuIds.length; | |
al.add(skuIds); | |
alComment.add(token.getPrimaryKeyString()); | |
return index; | |
} | |
public int getTableLen () { | |
return al.size() == 0 ? 1 : al.size(); | |
} | |
} | |
class LocalTokenNumberTable { | |
private ArrayList<String> al; | |
private ArrayList<String> alComment; | |
private String phase; | |
private int len; | |
public LocalTokenNumberTable (String phase) { | |
this.phase = phase; | |
al = new ArrayList<String>(); | |
alComment = new ArrayList<String>(); | |
len = 0; | |
} | |
public String getSizeMacro () { | |
return String.format(PcdDatabase.LocalTokenNumberTableSizeMacro, phase, getSize()) | |
+ String.format(PcdDatabase.LocalTokenNumberSizeMacro, phase, al.size()); | |
} | |
public int getSize () { | |
return (al.size() == 0)? 1 : al.size(); | |
} | |
public String getExistanceMacro () { | |
return String.format(PcdDatabase.DatabaseExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); | |
} | |
public String getTypeDeclaration () { | |
return String.format(PcdDatabase.LocalTokenNumberTableDeclaration, phase); | |
} | |
public ArrayList<String> getInstantiation () { | |
ArrayList<String> output = new ArrayList<String>(); | |
output.add("/* LocalTokenNumberTable */"); | |
output.add("{"); | |
if (al.size() == 0) { | |
output.add("0"); | |
} | |
for (int index = 0; index < al.size(); index++) { | |
String str; | |
str = (String)al.get(index); | |
str += " /* " + alComment.get(index) + " */ "; | |
if (index != (al.size() - 1)) { | |
str += ","; | |
} | |
output.add(str); | |
} | |
output.add("}"); | |
return output; | |
} | |
public int add (Token token) { | |
int index = len; | |
String str; | |
len++; | |
str = String.format(PcdDatabase.offsetOfStrTemplate, phase, token.hasDefaultValue() ? "Init" : "Uninit", token.getPrimaryKeyString()); | |
if (token.isUnicodeStringType()) { | |
str += " | PCD_TYPE_STRING"; | |
} | |
if (token.isSkuEnable()) { | |
str += " | PCD_TYPE_SKU_ENABLED"; | |
} | |
if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.HII_TYPE) { | |
str += " | PCD_TYPE_HII"; | |
} | |
if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.VPD_TYPE) { | |
str += " | PCD_TYPE_VPD"; | |
} | |
al.add(str); | |
alComment.add(token.getPrimaryKeyString()); | |
return index; | |
} | |
} | |
class ExMapTable { | |
class ExTriplet { | |
public Integer guidTableIdx; | |
public Long exTokenNumber; | |
public Long localTokenIdx; | |
public ExTriplet (int guidTableIdx, long exTokenNumber, long localTokenIdx) { | |
this.guidTableIdx = new Integer(guidTableIdx); | |
this.exTokenNumber = new Long(exTokenNumber); | |
this.localTokenIdx = new Long(localTokenIdx); | |
} | |
} | |
private ArrayList<ExTriplet> al; | |
private ArrayList<String> alComment; | |
private String phase; | |
private int len; | |
private int bodyStart; | |
private int bodyLineNum; | |
private int base; | |
public ExMapTable (String phase) { | |
this.phase = phase; | |
al = new ArrayList<ExTriplet>(); | |
alComment = new ArrayList<String>(); | |
bodyStart = 0; | |
bodyLineNum = 0; | |
len = 0; | |
} | |
public String getSizeMacro () { | |
return String.format(PcdDatabase.ExMapTableSizeMacro, phase, getTableLen()) | |
+ String.format(PcdDatabase.ExTokenNumber, phase, al.size()); | |
} | |
private int getSize () { | |
return (al.size() == 0)? 1 : al.size(); | |
} | |
public String getExistanceMacro () { | |
return String.format(PcdDatabase.ExMapTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); | |
} | |
public String getTypeDeclaration () { | |
return String.format(PcdDatabase.ExMapTableDeclaration, phase); | |
} | |
public ArrayList<String> getInstantiation () { | |
ArrayList<String> Output = new ArrayList<String>(); | |
Output.add("/* ExMapTable */"); | |
Output.add("{"); | |
bodyStart = 2; | |
if (al.size() == 0) { | |
Output.add("{0, 0, 0}"); | |
} | |
int index; | |
for (index = 0; index < al.size(); index++) { | |
String str; | |
ExTriplet e = (ExTriplet)al.get(index); | |
str = "{ " + e.exTokenNumber.toString() + ", "; | |
str += e.localTokenIdx.toString() + ", "; | |
str += e.guidTableIdx.toString(); | |
str += " /* " + alComment.get(index) + " */"; | |
if (index != al.size() - 1) { | |
str += ","; | |
} | |
Output.add(str); | |
bodyLineNum++; | |
} | |
Output.add("}"); | |
return Output; | |
} | |
public int add (int localTokenIdx, long exTokenNum, int guidTableIdx, String name) { | |
int index = len; | |
len++; | |
al.add(new ExTriplet(guidTableIdx, exTokenNum, localTokenIdx)); | |
alComment.add(name); | |
return index; | |
} | |
public int getTableLen () { | |
return al.size() == 0 ? 1 : al.size(); | |
} | |
} | |
class PcdDatabase { | |
public final static String ExMapTableDeclaration = "DYNAMICEX_MAPPING ExMapTable[%s_EXMAPPING_TABLE_SIZE];\r\n"; | |
public final static String GuidTableDeclaration = "EFI_GUID GuidTable[%s_GUID_TABLE_SIZE];\r\n"; | |
public final static String LocalTokenNumberTableDeclaration = "UINT32 LocalTokenNumberTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n"; | |
public final static String StringTableDeclaration = "UINT16 StringTable[%s_STRING_TABLE_SIZE];\r\n"; | |
public final static String SizeTableDeclaration = "UINT16 SizeTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n"; | |
public final static String SkuIdTableDeclaration = "UINT8 SkuIdTable[%s_SKUID_TABLE_SIZE];\r\n"; | |
public final static String ExMapTableSizeMacro = "#define %s_EXMAPPING_TABLE_SIZE %d\r\n"; | |
public final static String ExTokenNumber = "#define %s_EX_TOKEN_NUMBER %d\r\n"; | |
public final static String GuidTableSizeMacro = "#define %s_GUID_TABLE_SIZE %d\r\n"; | |
public final static String LocalTokenNumberTableSizeMacro = "#define %s_LOCAL_TOKEN_NUMBER_TABLE_SIZE %d\r\n"; | |
public final static String LocalTokenNumberSizeMacro = "#define %s_LOCAL_TOKEN_NUMBER %d\r\n"; | |
public final static String StringTableSizeMacro = "#define %s_STRING_TABLE_SIZE %d\r\n"; | |
public final static String SkuIdTableSizeMacro = "#define %s_SKUID_TABLE_SIZE %d\r\n"; | |
public final static String ExMapTableExistenceMacro = "#define %s_EXMAP_TABLE_EMPTY %s\r\n"; | |
public final static String GuidTableExistenceMacro = "#define %s_GUID_TABLE_EMPTY %s\r\n"; | |
public final static String DatabaseExistenceMacro = "#define %s_DATABASE_EMPTY %s\r\n"; | |
public final static String StringTableExistenceMacro = "#define %s_STRING_TABLE_EMPTY %s\r\n"; | |
public final static String SkuTableExistenceMacro = "#define %s_SKUID_TABLE_EMPTY %s\r\n"; | |
public final static String offsetOfSkuHeadStrTemplate = "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)"; | |
public final static String offsetOfStrTemplate = "offsetof(%s_PCD_DATABASE, %s.%s)"; | |
private StringTable stringTable; | |
private GuidTable guidTable; | |
private LocalTokenNumberTable localTokenNumberTable; | |
private SkuIdTable skuIdTable; | |
private SizeTable sizeTable; | |
private ExMapTable exMapTable; | |
private ArrayList<Token> alTokens; | |
private String phase; | |
private int assignedTokenNumber; | |
// | |
// After Major changes done to the PCD | |
// database generation class PcdDatabase | |
// Please increment the version and please | |
// also update the version number in PCD | |
// service PEIM and DXE driver accordingly. | |
// | |
private final int version = 1; | |
private String hString; | |
private String cString; | |
class AlignmentSizeComp implements Comparator<Token> { | |
public int compare (Token a, Token b) { | |
return getAlignmentSize(b) | |
- getAlignmentSize(a); | |
} | |
} | |
public PcdDatabase (ArrayList<Token> alTokens, String exePhase, int startLen) { | |
phase = exePhase; | |
stringTable = new StringTable(phase); | |
guidTable = new GuidTable(phase); | |
localTokenNumberTable = new LocalTokenNumberTable(phase); | |
skuIdTable = new SkuIdTable(phase); | |
sizeTable = new SizeTable(phase); | |
exMapTable = new ExMapTable(phase); | |
assignedTokenNumber = startLen; | |
this.alTokens = alTokens; | |
} | |
private void getTwoGroupsOfTokens (ArrayList<Token> alTokens, List<Token> initTokens, List<Token> uninitTokens) { | |
for (int i = 0; i < alTokens.size(); i++) { | |
Token t = (Token)alTokens.get(i); | |
if (t.hasDefaultValue()) { | |
initTokens.add(t); | |
} else { | |
uninitTokens.add(t); | |
} | |
} | |
return; | |
} | |
private int getAlignmentSize (Token token) { | |
if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.HII_TYPE) { | |
return 2; | |
} | |
if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.VPD_TYPE) { | |
return 4; | |
} | |
if (token.isUnicodeStringType()) { | |
return 2; | |
} | |
switch (token.datumType) { | |
case UINT8: | |
return 1; | |
case UINT16: | |
return 2; | |
case UINT32: | |
return 4; | |
case UINT64: | |
return 8; | |
case POINTER: | |
return 1; | |
case BOOLEAN: | |
return 1; | |
} | |
return 1; | |
} | |
public String getCString () { | |
return cString; | |
} | |
public String getHString () { | |
return hString; | |
} | |
public void genCode () | |
throws EntityException { | |
final String newLine = "\r\n"; | |
final String declNewLine = ";\r\n"; | |
final String tab = "\t"; | |
final String commaNewLine = ", \r\n"; | |
int i; | |
ArrayList<String> decla; | |
ArrayList<String> inst; | |
String macroStr = ""; | |
String initDeclStr = ""; | |
String initInstStr = ""; | |
String uninitDeclStr = ""; | |
List<Token> initTokens = new ArrayList<Token> (); | |
List<Token> uninitTokens = new ArrayList<Token> (); | |
HashMap <String, ArrayList<String>> initCode = new HashMap<String, ArrayList<String>> (); | |
HashMap <String, ArrayList<String>> uninitCode = new HashMap<String, ArrayList<String>> (); | |
getTwoGroupsOfTokens (alTokens, initTokens, uninitTokens); | |
// | |
// Generate Structure Declaration for PcdTokens without Default Value | |
// PEI_PCD_DATABASE_INIT | |
// | |
java.util.Comparator<Token> comparator = new AlignmentSizeComp(); | |
java.util.Collections.sort(initTokens, comparator); | |
initCode = processTokens(initTokens); | |
// | |
// Generate Structure Declaration for PcdTokens without Default Value | |
// PEI_PCD_DATABASE_UNINIT | |
// | |
java.util.Collections.sort(uninitTokens, comparator); | |
uninitCode = processTokens(uninitTokens); | |
// | |
// Generate size info Macro for all Tables | |
// | |
macroStr += guidTable.getSizeMacro(); | |
macroStr += stringTable.getSizeMacro(); | |
macroStr += skuIdTable.getSizeMacro(); | |
macroStr += localTokenNumberTable.getSizeMacro(); | |
macroStr += exMapTable.getSizeMacro(); | |
// | |
// Generate existance info Macro for all Tables | |
// | |
macroStr += guidTable.getExistanceMacro(); | |
macroStr += stringTable.getExistanceMacro(); | |
macroStr += skuIdTable.getExistanceMacro(); | |
macroStr += localTokenNumberTable.getExistanceMacro(); | |
macroStr += exMapTable.getExistanceMacro(); | |
// | |
// Generate Structure Declaration for PcdTokens with Default Value | |
// for example PEI_PCD_DATABASE_INIT | |
// | |
initDeclStr += "typedef struct {" + newLine; | |
{ | |
initDeclStr += tab + exMapTable.getTypeDeclaration(); | |
initDeclStr += tab + guidTable.getTypeDeclaration(); | |
initDeclStr += tab + localTokenNumberTable.getTypeDeclaration(); | |
initDeclStr += tab + stringTable.getTypeDeclaration(); | |
initDeclStr += tab + sizeTable.getTypeDeclaration(); | |
initDeclStr += tab + skuIdTable.getTypeDeclaration(); | |
if (phase.equalsIgnoreCase("PEI")) { | |
initDeclStr += tab + "SKU_ID SystemSkuId;" + newLine; | |
} | |
decla = initCode.get(new String("Declaration")); | |
for (i = 0; i < decla.size(); i++) { | |
initDeclStr += tab + decla.get(i) + declNewLine; | |
} | |
// | |
// Generate Structure Declaration for PcdToken with SkuEnabled | |
// | |
decla = initCode.get("DeclarationForSku"); | |
for (i = 0; i < decla.size(); i++) { | |
initDeclStr += tab + decla.get(i) + declNewLine; | |
} | |
} | |
initDeclStr += String.format("} %s_PCD_DATABASE_INIT;\r\n\r\n", phase); | |
// | |
// Generate MACRO for structure intialization of PCDTokens with Default Value | |
// The sequence must match the sequence of declaration of the memembers in the structure | |
String tmp = String.format("%s_PCD_DATABASE_INIT g%sPcdDbInit = { ", phase.toUpperCase(), phase.toUpperCase()); | |
initInstStr += tmp + newLine; | |
initInstStr += tab + genInstantiationStr(exMapTable.getInstantiation()) + commaNewLine; | |
initInstStr += tab + genInstantiationStr(guidTable.getInstantiation()) + commaNewLine; | |
initInstStr += tab + genInstantiationStr(localTokenNumberTable.getInstantiation()) + commaNewLine; | |
initInstStr += tab + genInstantiationStr(stringTable.getInstantiation()) + commaNewLine; | |
initInstStr += tab + genInstantiationStr(sizeTable.getInstantiation()) + commaNewLine; | |
initInstStr += tab + genInstantiationStr(skuIdTable.getInstantiation()) + commaNewLine; | |
// | |
// For SystemSkuId | |
// | |
if (phase.equalsIgnoreCase("PEI")) { | |
initInstStr += tab + "0" + tab + "/* SystemSkuId */" + commaNewLine; | |
} | |
inst = initCode.get("Instantiation"); | |
for (i = 0; i < inst.size(); i++) { | |
initInstStr += tab + inst.get(i) + commaNewLine; | |
} | |
inst = initCode.get("InstantiationForSku"); | |
for (i = 0; i < inst.size(); i++) { | |
initInstStr += tab + inst.get(i); | |
if (i != inst.size() - 1) { | |
initInstStr += commaNewLine; | |
} | |
} | |
initInstStr += "};"; | |
uninitDeclStr += "typedef struct {" + newLine; | |
{ | |
decla = uninitCode.get("Declaration"); | |
if (decla.size() == 0) { | |
uninitDeclStr += "UINT8 dummy /* The UINT struct is empty */" + declNewLine; | |
} else { | |
for (i = 0; i < decla.size(); i++) { | |
uninitDeclStr += tab + decla.get(i) + declNewLine; | |
} | |
decla = uninitCode.get("DeclarationForSku"); | |
for (i = 0; i < decla.size(); i++) { | |
uninitDeclStr += tab + decla.get(i) + declNewLine; | |
} | |
} | |
} | |
uninitDeclStr += String.format("} %s_PCD_DATABASE_UNINIT;\r\n\r\n", phase); | |
cString = initInstStr + newLine; | |
hString = macroStr + newLine | |
+ initDeclStr + newLine | |
+ uninitDeclStr + newLine | |
+ newLine; | |
hString += String.format("#define PCD_%s_SERVICE_DRIVER_VERSION %d", phase, version); | |
} | |
private String genInstantiationStr (ArrayList<String> alStr) { | |
String str = ""; | |
for (int i = 0; i< alStr.size(); i++) { | |
str += "\t" + alStr.get(i); | |
if (i != alStr.size() - 1) { | |
str += "\r\n"; | |
} | |
} | |
return str; | |
} | |
private HashMap<String, ArrayList<String>> processTokens (List<Token> alToken) | |
throws EntityException { | |
HashMap <String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>(); | |
ArrayList<String> decl = new ArrayList<String>(); | |
ArrayList<String> declForSkuEnableType = new ArrayList<String>(); | |
ArrayList<String> inst = new ArrayList<String>(); | |
ArrayList<String> instForSkuEnableType = new ArrayList<String>(); | |
for (int index = 0; index < alToken.size(); index++) { | |
Token token = alToken.get(index); | |
if (token.isSkuEnable()) { | |
// | |
// BugBug: Schema only support Data type now | |
// | |
int tableIdx; | |
tableIdx = skuIdTable.add(token); | |
decl.add(getSkuEnabledTypeDeclaration(token)); | |
if (token.hasDefaultValue()) { | |
inst.add(getSkuEnabledTypeInstantiaion(token, tableIdx)); | |
} | |
declForSkuEnableType.add(getDataTypeDeclarationForSkuEnabled(token)); | |
if (token.hasDefaultValue()) { | |
instForSkuEnableType.add(getDataTypeInstantiationForSkuEnabled(token)); | |
} | |
} else { | |
if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.HII_TYPE) { | |
decl.add(getVariableEnableTypeDeclaration(token)); | |
inst.add(getVariableEnableInstantiation(token)); | |
} else if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.VPD_TYPE) { | |
decl.add(getVpdEnableTypeDeclaration(token)); | |
inst.add(getVpdEnableTypeInstantiation(token)); | |
} else if (token.isUnicodeStringType()) { | |
decl.add(getStringTypeDeclaration(token)); | |
inst.add(getStringTypeInstantiation(stringTable.add(token.getStringTypeString(), token), token)); | |
} | |
else { | |
decl.add(getDataTypeDeclaration(token)); | |
if (token.hasDefaultValue()) { | |
inst.add(getDataTypeInstantiation(token)); | |
} | |
} | |
} | |
sizeTable.add(token); | |
localTokenNumberTable.add(token); | |
token.tokenNumber = assignedTokenNumber++; | |
} | |
map.put("Declaration", decl); | |
map.put("DeclarationForSku", declForSkuEnableType); | |
map.put("Instantiation", inst); | |
map.put("InstantiationForSku", instForSkuEnableType); | |
return map; | |
} | |
private String getSkuEnabledTypeDeclaration (Token token) { | |
return String.format("SKU_HEAD %s;\r\n", token.getPrimaryKeyString()); | |
} | |
private String getSkuEnabledTypeInstantiaion (Token token, int SkuTableIdx) { | |
String offsetof = String.format(PcdDatabase.offsetOfSkuHeadStrTemplate, phase, token.hasDefaultValue()? "Init" : "Uninit", token.getPrimaryKeyString()); | |
return String.format("{ %s, %d }", offsetof, SkuTableIdx); | |
} | |
private String getDataTypeDeclarationForSkuEnabled (Token token) { | |
String typeStr = ""; | |
if (token.datumType == Token.DATUM_TYPE.UINT8) { | |
typeStr = "UINT8 %s_%s[%d];\r\n"; | |
} else if (token.datumType == Token.DATUM_TYPE.UINT16) { | |
typeStr = "UINT16 %s_%s[%d];\r\n"; | |
} else if (token.datumType == Token.DATUM_TYPE.UINT32) { | |
typeStr = "UINT32 %s_%s[%d];\r\n"; | |
} else if (token.datumType == Token.DATUM_TYPE.UINT64) { | |
typeStr = "UINT64 %s_%s[%d];\r\n"; | |
} else if (token.datumType == Token.DATUM_TYPE.BOOLEAN) { | |
typeStr = "BOOLEAN %s_%s[%d];\r\n"; | |
} else if (token.datumType == Token.DATUM_TYPE.POINTER) { | |
return String.format("UINT8 %s_%s[%d];\r\n", token.getPrimaryKeyString(), "SkuDataTable", token.datumSize * token.skuData.size()); | |
} | |
return String.format(typeStr, token.getPrimaryKeyString(), "SkuDataTable", token.skuData.size()); | |
} | |
private String getDataTypeInstantiationForSkuEnabled (Token token) { | |
String str = ""; | |
if (token.datumType == Token.DATUM_TYPE.POINTER) { | |
return String.format("UINT8 %s_%s[%d]", token.getPrimaryKeyString(), "SkuDataTable", token.datumSize * token.skuData.size()); | |
} else { | |
str = "{ "; | |
for (int idx = 0; idx < token.skuData.size(); idx++) { | |
str += token.skuData.get(idx).toString(); | |
if (idx != token.skuData.size() - 1) { | |
str += ", "; | |
} | |
} | |
str += "}"; | |
return str; | |
} | |
} | |
private String getDataTypeInstantiation (Token token) { | |
if (token.datumType == Token.DATUM_TYPE.POINTER) { | |
return String.format("%s /* %s */", token.getDefaultSku().value, token.getPrimaryKeyString()); | |
} else { | |
return String.format("%s /* %s */", token.getDefaultSku().value, token.getPrimaryKeyString()); | |
} | |
} | |
private String getDataTypeDeclaration (Token token) { | |
String typeStr = ""; | |
if (token.datumType == Token.DATUM_TYPE.UINT8) { | |
typeStr = "UINT8"; | |
} else if (token.datumType == Token.DATUM_TYPE.UINT16) { | |
typeStr = "UINT16"; | |
} else if (token.datumType == Token.DATUM_TYPE.UINT32) { | |
typeStr = "UINT32"; | |
} else if (token.datumType == Token.DATUM_TYPE.UINT64) { | |
typeStr = "UINT64"; | |
} else if (token.datumType == Token.DATUM_TYPE.BOOLEAN) { | |
typeStr = "BOOLEAN"; | |
} else if (token.datumType == Token.DATUM_TYPE.POINTER) { | |
return String.format("UINT8 %s[%d]", token.getPrimaryKeyString(), token.datumSize); | |
} else { | |
} | |
return String.format("%s %s", typeStr, token.getPrimaryKeyString()); | |
} | |
private String getVpdEnableTypeDeclaration (Token token) { | |
return String.format("VPD_HEAD %s", token.getPrimaryKeyString()); | |
} | |
private String getVpdEnableTypeInstantiation (Token token) { | |
return String.format("{ %s } /* %s */", token.getDefaultSku().vpdOffset, | |
token.getPrimaryKeyString()); | |
} | |
private String getStringTypeDeclaration (Token token) { | |
return String.format("UINT16 %s", token.getPrimaryKeyString()); | |
} | |
private String getStringTypeInstantiation (int StringTableIdx, Token token) { | |
return String.format ("%d /* %s */", StringTableIdx, | |
token.getPrimaryKeyString()); | |
} | |
private String getVariableEnableTypeDeclaration (Token token) { | |
return String.format("VARIABLE_HEAD %s", token.getPrimaryKeyString()); | |
} | |
private String getVariableEnableInstantiation (Token token) | |
throws EntityException { | |
// | |
// Need scott fix | |
// | |
return String.format("{ %d, %d, %s } /* %s */", guidTable.add(token.getDefaultSku().variableGuid, token.getPrimaryKeyString()), | |
stringTable.add(token.getDefaultSku().getStringOfVariableName(), token), | |
token.getDefaultSku().variableOffset, | |
token.getPrimaryKeyString()); | |
} | |
public int getTotalTokenNumber () { | |
return sizeTable.getTableLen(); | |
} | |
public static String getPcdDatabaseCommonDefinitions () | |
throws EntityException { | |
String retStr = ""; | |
try { | |
File file = new File(GlobalData.getWorkspacePath() + File.separator + | |
"Tools" + File.separator + | |
"Conf" + File.separator + | |
"Pcd" + File.separator + | |
"PcdDatabaseCommonDefinitions.sample"); | |
FileReader reader = new FileReader(file); | |
BufferedReader in = new BufferedReader(reader); | |
String str; | |
while ((str = in.readLine()) != null) { | |
retStr = retStr +"\r\n" + str; | |
} | |
} catch (Exception ex) { | |
throw new EntityException("Fatal error when generating PcdDatabase Common Definitions"); | |
} | |
return retStr; | |
} | |
public static String getPcdDxeDatabaseDefinitions () | |
throws EntityException { | |
String retStr = ""; | |
try { | |
File file = new File(GlobalData.getWorkspacePath() + File.separator + | |
"Tools" + File.separator + | |
"Conf" + File.separator + | |
"Pcd" + File.separator + | |
"PcdDatabaseDxeDefinitions.sample"); | |
FileReader reader = new FileReader(file); | |
BufferedReader in = new BufferedReader(reader); | |
String str; | |
while ((str = in.readLine()) != null) { | |
retStr = retStr +"\r\n" + str; | |
} | |
} catch (Exception ex) { | |
throw new EntityException("Fatal error when generating PcdDatabase Dxe Definitions"); | |
} | |
return retStr; | |
} | |
public static String getPcdPeiDatabaseDefinitions () | |
throws EntityException { | |
String retStr = ""; | |
try { | |
File file = new File(GlobalData.getWorkspacePath() + File.separator + | |
"Tools" + File.separator + | |
"Conf" + File.separator + | |
"Pcd" + File.separator + | |
"PcdDatabasePeiDefinitions.sample"); | |
FileReader reader = new FileReader(file); | |
BufferedReader in = new BufferedReader(reader); | |
String str; | |
while ((str = in.readLine()) != null) { | |
retStr = retStr +"\r\n" + str; | |
} | |
} catch (Exception ex) { | |
throw new EntityException("Fatal error when generating PcdDatabase Pei Definitions"); | |
} | |
return retStr; | |
} | |
} | |
class ModuleInfo { | |
public ModuleSADocument.ModuleSA module; | |
public ModuleTypeDef.Enum type; | |
public ModuleInfo (ModuleSADocument.ModuleSA module, ModuleTypeDef.Enum type) { | |
this.module = module; | |
this.type = type; | |
} | |
} | |
/** This action class is to collect PCD information from MSA, SPD, FPD xml file. | |
This class will be used for wizard and build tools, So it can *not* inherit | |
from buildAction or UIAction. | |
**/ | |
public class CollectPCDAction { | |
/// memoryDatabase hold all PCD information collected from SPD, MSA, FPD. | |
private MemoryDatabaseManager dbManager; | |
/// Workspacepath hold the workspace information. | |
private String workspacePath; | |
/// FPD file is the root file. | |
private String fpdFilePath; | |
/// Message level for CollectPCDAction. | |
private int originalMessageLevel; | |
/// Cache the fpd docment instance for private usage. | |
private FrameworkPlatformDescriptionDocument fpdDocInstance; | |
/** | |
Set WorkspacePath parameter for this action class. | |
@param workspacePath parameter for this action | |
**/ | |
public void setWorkspacePath(String workspacePath) { | |
this.workspacePath = workspacePath; | |
} | |
/** | |
Set action message level for CollectPcdAction tool. | |
The message should be restored when this action exit. | |
@param actionMessageLevel parameter for this action | |
**/ | |
public void setActionMessageLevel(int actionMessageLevel) { | |
originalMessageLevel = ActionMessage.messageLevel; | |
ActionMessage.messageLevel = actionMessageLevel; | |
} | |
/** | |
Set FPDFileName parameter for this action class. | |
@param fpdFilePath fpd file path | |
**/ | |
public void setFPDFilePath(String fpdFilePath) { | |
this.fpdFilePath = fpdFilePath; | |
} | |
/** | |
Common function interface for outer. | |
@param workspacePath The path of workspace of current build or analysis. | |
@param fpdFilePath The fpd file path of current build or analysis. | |
@param messageLevel The message level for this Action. | |
@throws Exception The exception of this function. Because it can *not* be predict | |
where the action class will be used. So only Exception can be throw. | |
**/ | |
public void perform(String workspacePath, String fpdFilePath, | |
int messageLevel) throws Exception { | |
setWorkspacePath(workspacePath); | |
setFPDFilePath(fpdFilePath); | |
setActionMessageLevel(messageLevel); | |
checkParameter(); | |
execute(); | |
ActionMessage.messageLevel = originalMessageLevel; | |
} | |
/** | |
Core execution function for this action class. | |
This function work flows will be: | |
1) Collect and prepocess PCD information from FPD file, all PCD | |
information will be stored into memory database. | |
2) Generate 3 strings for | |
a) All modules using Dynamic(Ex) PCD entry.(Token Number) | |
b) PEI PCDDatabase (C Structure) for PCD Service PEIM. | |
c) DXE PCD Database (C structure) for PCD Service DXE. | |
@throws EntityException Exception indicate failed to execute this action. | |
**/ | |
private void execute() throws EntityException { | |
// | |
// Get memoryDatabaseManager instance from GlobalData. | |
// The memoryDatabaseManager should be initialized for whatever build | |
// tools or wizard tools | |
// | |
if((dbManager = GlobalData.getPCDMemoryDBManager()) == null) { | |
throw new EntityException("The instance of PCD memory database manager is null"); | |
} | |
// | |
// Collect all PCD information defined in FPD file. | |
// Evenry token defind in FPD will be created as an token into | |
// memory database. | |
// | |
createTokenInDBFromFPD(); | |
// | |
// Call Private function genPcdDatabaseSourceCode (void); ComponentTypeBsDriver | |
// 1) Generate for PEI, DXE PCD DATABASE's definition and initialization. | |
// | |
genPcdDatabaseSourceCode (); | |
} | |
/** | |
This function generates source code for PCD Database. | |
@param void | |
@throws EntityException If the token does *not* exist in memory database. | |
**/ | |
private void genPcdDatabaseSourceCode() | |
throws EntityException { | |
String PcdCommonHeaderString = PcdDatabase.getPcdDatabaseCommonDefinitions (); | |
ArrayList<Token> alPei = new ArrayList<Token> (); | |
ArrayList<Token> alDxe = new ArrayList<Token> (); | |
dbManager.getTwoPhaseDynamicRecordArray(alPei, alDxe); | |
PcdDatabase pcdPeiDatabase = new PcdDatabase (alPei, "PEI", 0); | |
pcdPeiDatabase.genCode(); | |
dbManager.PcdPeimHString = PcdCommonHeaderString + pcdPeiDatabase.getHString() | |
+ PcdDatabase.getPcdPeiDatabaseDefinitions(); | |
dbManager.PcdPeimCString = pcdPeiDatabase.getCString(); | |
PcdDatabase pcdDxeDatabase = new PcdDatabase (alDxe, | |
"DXE", | |
alPei.size() | |
); | |
pcdDxeDatabase.genCode(); | |
dbManager.PcdDxeHString = dbManager.PcdPeimHString + pcdDxeDatabase.getHString() | |
+ PcdDatabase.getPcdDxeDatabaseDefinitions(); | |
dbManager.PcdDxeCString = pcdDxeDatabase.getCString(); | |
} | |
/** | |
Get component array from FPD. | |
This function maybe provided by some Global class. | |
@return List<ModuleInfo> the component array. | |
*/ | |
private List<ModuleInfo> getComponentsFromFPD() | |
throws EntityException { | |
List<ModuleInfo> allModules = new ArrayList<ModuleInfo>(); | |
ModuleInfo current = null; | |
int index = 0; | |
org.tianocore.Components components = null; | |
FrameworkModulesDocument.FrameworkModules fModules = null; | |
ModuleSADocument.ModuleSA[] modules = null; | |
HashMap<String, XmlObject> map = new HashMap<String, XmlObject>(); | |
if (fpdDocInstance == null) { | |
try { | |
fpdDocInstance = (FrameworkPlatformDescriptionDocument)XmlObject.Factory.parse(new File(fpdFilePath)); | |
} catch(IOException ioE) { | |
throw new EntityException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage()); | |
} catch(XmlException xmlE) { | |
throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage()); | |
} | |
} | |
map.put("FrameworkPlatformDescription", fpdDocInstance); | |
SurfaceAreaQuery.setDoc(map); | |
modules = SurfaceAreaQuery.getFpdModuleSAs(); | |
for (index = 0; index < modules.length; index ++) { | |
SurfaceAreaQuery.setDoc(GlobalData.getDoc(modules[index].getModuleName())); | |
allModules.add(new ModuleInfo(modules[index], | |
ModuleTypeDef.Enum.forString(SurfaceAreaQuery.getModuleType()))); | |
} | |
return allModules; | |
} | |
/** | |
Create token instance object into memory database, the token information | |
comes for FPD file. Normally, FPD file will contain all token platform | |
informations. | |
@return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage. | |
@throws EntityException Failed to parse FPD xml file. | |
**/ | |
private void createTokenInDBFromFPD() | |
throws EntityException { | |
int index = 0; | |
int index2 = 0; | |
int pcdIndex = 0; | |
List<PcdBuildDefinition.PcdData> pcdBuildDataArray = new ArrayList<PcdBuildDefinition.PcdData>(); | |
PcdBuildDefinition.PcdData pcdBuildData = null; | |
Token token = null; | |
SkuInstance skuInstance = null; | |
int skuIndex = 0; | |
List<ModuleInfo> modules = null; | |
String primaryKey = null; | |
String exceptionString = null; | |
UsageInstance usageInstance = null; | |
String primaryKey1 = null; | |
String primaryKey2 = null; | |
boolean isDuplicate = false; | |
Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; | |
Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN; | |
int tokenNumber = 0; | |
String moduleName = null; | |
String datum = null; | |
int maxDatumSize = 0; | |
// | |
// ---------------------------------------------- | |
// 1), Get all <ModuleSA> from FPD file. | |
// ---------------------------------------------- | |
// | |
modules = getComponentsFromFPD(); | |
if (modules == null) { | |
throw new EntityException("[FPD file error] No modules in FPD file, Please check whether there are elements in <FrameworkModules> in FPD file!"); | |
} | |
// | |
// ------------------------------------------------------------------- | |
// 2), Loop all modules to process <PcdBuildDeclarations> for each module. | |
// ------------------------------------------------------------------- | |
// | |
for (index = 0; index < modules.size(); index ++) { | |
isDuplicate = false; | |
for (index2 = 0; index2 < index; index2 ++) { | |
// | |
// BUGBUG: For transition schema, we can *not* get module's version from | |
// <ModuleSAs>, It is work around code. | |
// | |
primaryKey1 = UsageInstance.getPrimaryKey(modules.get(index).module.getModuleName(), | |
null, | |
null, | |
null, | |
modules.get(index).module.getArch().toString(), | |
null); | |
primaryKey2 = UsageInstance.getPrimaryKey(modules.get(index2).module.getModuleName(), | |
null, | |
null, | |
null, | |
modules.get(index2).module.getArch().toString(), | |
null); | |
if (primaryKey1.equalsIgnoreCase(primaryKey2)) { | |
isDuplicate = true; | |
break; | |
} | |
} | |
if (isDuplicate) { | |
continue; | |
} | |
// | |
// It is legal for a module does not contains ANY pcd build definitions. | |
// | |
if (modules.get(index).module.getPcdBuildDefinition() == null) { | |
continue; | |
} | |
pcdBuildDataArray = modules.get(index).module.getPcdBuildDefinition().getPcdDataList(); | |
moduleName = modules.get(index).module.getModuleName(); | |
// | |
// ---------------------------------------------------------------------- | |
// 2.1), Loop all Pcd entry for a module and add it into memory database. | |
// ---------------------------------------------------------------------- | |
// | |
for (pcdIndex = 0; pcdIndex < pcdBuildDataArray.size(); pcdIndex ++) { | |
pcdBuildData = pcdBuildDataArray.get(pcdIndex); | |
primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(), | |
translateSchemaStringToUUID(pcdBuildData.getTokenSpaceGuid())); | |
pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString()); | |
datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString()); | |
tokenNumber = Integer.decode(pcdBuildData.getToken().toString()); | |
if (pcdBuildData.getValue() != null) { | |
datum = pcdBuildData.getValue().toString(); | |
} else { | |
datum = null; | |
} | |
maxDatumSize = pcdBuildData.getMaxDatumSize(); | |
if ((pcdType == Token.PCD_TYPE.FEATURE_FLAG) && | |
(datumType != Token.DATUM_TYPE.BOOLEAN)){ | |
exceptionString = String.format("[FPD file error] For PCD %s in module %s, the PCD type is FEATRUE_FLAG but "+ | |
"datum type of this PCD entry is not BOOLEAN!", | |
pcdBuildData.getCName(), | |
moduleName); | |
throw new EntityException(exceptionString); | |
} | |
// | |
// Check <TokenSpaceGuid> is exist? In future, because all schema verification will tools | |
// will check that, following checking code could be removed. | |
// | |
if (pcdBuildData.getTokenSpaceGuid() == null) { | |
exceptionString = String.format("[FPD file error] There is no <TokenSpaceGuid> for PCD %s in module %s! This is required!", | |
pcdBuildData.getCName(), | |
moduleName); | |
throw new EntityException(exceptionString); | |
} | |
// | |
// ------------------------------------------------------------------------------------------- | |
// 2.1.1), Do some necessary checking work for FixedAtBuild, FeatureFlag and PatchableInModule | |
// ------------------------------------------------------------------------------------------- | |
// | |
if (!Token.isDynamic(pcdType)) { | |
// | |
// Value is required. | |
// | |
if (datum == null) { | |
exceptionString = String.format("[FPD file error] There is no value for PCD entry %s in module %s!", | |
pcdBuildData.getCName(), | |
moduleName); | |
throw new EntityException(exceptionString); | |
} | |
// | |
// Check whether the datum size is matched datum type. | |
// | |
if ((exceptionString = verifyDatum(pcdBuildData.getCName(), | |
moduleName, | |
datum, | |
datumType, | |
maxDatumSize)) != null) { | |
throw new EntityException(exceptionString); | |
} | |
} | |
// | |
// --------------------------------------------------------------------------------- | |
// 2.1.2), Create token or update token information for current anaylized PCD data. | |
// --------------------------------------------------------------------------------- | |
// | |
if (dbManager.isTokenInDatabase(primaryKey)) { | |
// | |
// If the token is already exist in database, do some necessary checking | |
// and add a usage instance into this token in database | |
// | |
token = dbManager.getTokenByKey(primaryKey); | |
// | |
// checking for DatumType, DatumType should be unique for one PCD used in different | |
// modules. | |
// | |
if (token.datumType != datumType) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD entry %s is %s, which is different with %s defined in before!", | |
pcdBuildData.getCName(), | |
pcdBuildData.getDatumType().toString(), | |
Token.getStringOfdatumType(token.datumType)); | |
throw new EntityException(exceptionString); | |
} | |
// | |
// Check token number is valid | |
// | |
if (tokenNumber != token.tokenNumber) { | |
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!", | |
pcdBuildData.getCName(), | |
moduleName); | |
throw new EntityException(exceptionString); | |
} | |
// | |
// For same PCD used in different modules, the PCD type should all be dynamic or non-dynamic. | |
// | |
if (token.isDynamicPCD != Token.isDynamic(pcdType)) { | |
exceptionString = String.format("[FPD file error] For PCD entry %s in module %s, you define dynamic or non-dynamic PCD type which"+ | |
"is different with others module's", | |
token.cName, | |
moduleName); | |
throw new EntityException(exceptionString); | |
} | |
if (token.isDynamicPCD) { | |
// | |
// Check datum is equal the datum in dynamic information. | |
// For dynamic PCD, you can do not write <Value> in sperated every <PcdBuildDefinition> in different <ModuleSA>, | |
// But if you write, the <Value> must be same as the value in <DynamicPcdBuildDefinitions>. | |
// | |
if (!token.isSkuEnable() && | |
(token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.DEFAULT_TYPE) && | |
(datum != null)) { | |
if (!datum.equalsIgnoreCase(token.getDefaultSku().value)) { | |
exceptionString = String.format("[FPD file error] For dynamic PCD %s in module %s, the datum in <ModuleSA> is "+ | |
"not equal to the datum in <DynamicPcdBuildDefinitions>, it is "+ | |
"illega! You could no set <Value> in <ModuleSA> for a dynamic PCD!", | |
token.cName, | |
moduleName); | |
throw new EntityException(exceptionString); | |
} | |
} | |
if ((maxDatumSize != 0) && | |
(maxDatumSize != token.datumSize)){ | |
exceptionString = String.format("[FPD file error] For dynamic PCD %s in module %s, the max datum size is %d which "+ | |
"is different with <MaxDatumSize> %d defined in <DynamicPcdBuildDefinitions>!", | |
token.cName, | |
moduleName, | |
maxDatumSize, | |
token.datumSize); | |
throw new EntityException(exceptionString); | |
} | |
} | |
} else { | |
// | |
// If the token is not in database, create a new token instance and add | |
// a usage instance into this token in database. | |
// | |
token = new Token(pcdBuildData.getCName(), | |
translateSchemaStringToUUID(pcdBuildData.getTokenSpaceGuid())); | |
token.datumType = datumType; | |
token.tokenNumber = tokenNumber; | |
token.isDynamicPCD = Token.isDynamic(pcdType); | |
token.datumSize = maxDatumSize; | |
if (token.isDynamicPCD) { | |
// | |
// For Dynamic and Dynamic Ex type, need find the dynamic information | |
// in <DynamicPcdBuildDefinition> section in FPD file. | |
// | |
updateDynamicInformation(moduleName, | |
token, | |
datum, | |
maxDatumSize); | |
} | |
dbManager.addTokenToDatabase(primaryKey, token); | |
} | |
// | |
// ----------------------------------------------------------------------------------- | |
// 2.1.3), Add the PcdType in current module into this Pcd token's supported PCD type. | |
// ----------------------------------------------------------------------------------- | |
// | |
token.updateSupportPcdType(pcdType); | |
// | |
// ------------------------------------------------ | |
// 2.1.4), Create an usage instance for this token. | |
// ------------------------------------------------ | |
// | |
usageInstance = new UsageInstance(token, | |
moduleName, | |
null, | |
null, | |
null, | |
modules.get(index).type, | |
pcdType, | |
modules.get(index).module.getArch().toString(), | |
null, | |
datum, | |
maxDatumSize); | |
token.addUsageInstance(usageInstance); | |
} | |
} | |
} | |
/** | |
Verify the datum value according its datum size and datum type, this | |
function maybe moved to FPD verification tools in future. | |
@param cName | |
@param moduleName | |
@param datum | |
@param datumType | |
@param maxDatumSize | |
@return String | |
*/ | |
/***/ | |
public String verifyDatum(String cName, | |
String moduleName, | |
String datum, | |
Token.DATUM_TYPE datumType, | |
int maxDatumSize) { | |
String exceptionString = null; | |
int value; | |
BigInteger value64; | |
String subStr; | |
int index; | |
if (moduleName == null) { | |
moduleName = "section <DynamicPcdBuildDefinitions>"; | |
} else { | |
moduleName = "module " + moduleName; | |
} | |
if (maxDatumSize == 0) { | |
exceptionString = String.format("[FPD file error] You maybe miss <MaxDatumSize> for PCD %s in %s", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
switch (datumType) { | |
case UINT8: | |
if (maxDatumSize != 1) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+ | |
"is UINT8, but datum size is %d, they are not matched!", | |
cName, | |
moduleName, | |
maxDatumSize); | |
return exceptionString; | |
} | |
if (datum != null) { | |
try { | |
value = Integer.decode(datum); | |
} catch (NumberFormatException nfeExp) { | |
exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not valid "+ | |
"digital format of UINT8", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
if (value > 0xFF) { | |
exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s exceed"+ | |
" the max size of UINT8 - 0xFF", | |
cName, | |
moduleName, | |
datum); | |
return exceptionString; | |
} | |
} | |
break; | |
case UINT16: | |
if (maxDatumSize != 2) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+ | |
"is UINT16, but datum size is %d, they are not matched!", | |
cName, | |
moduleName, | |
maxDatumSize); | |
return exceptionString; | |
} | |
if (datum != null) { | |
try { | |
value = Integer.decode(datum); | |
} catch (NumberFormatException nfeExp) { | |
exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is "+ | |
"not valid digital of UINT16", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
if (value > 0xFFFF) { | |
exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s "+ | |
"which exceed the range of UINT16 - 0xFFFF", | |
cName, | |
moduleName, | |
datum); | |
return exceptionString; | |
} | |
} | |
break; | |
case UINT32: | |
if (maxDatumSize != 4) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+ | |
"is UINT32, but datum size is %d, they are not matched!", | |
cName, | |
moduleName, | |
maxDatumSize); | |
return exceptionString; | |
} | |
if (datum != null) { | |
try { | |
if (datum.length() > 2) { | |
if ((datum.charAt(0) == '0') && | |
((datum.charAt(1) == 'x') || (datum.charAt(1) == 'X'))){ | |
subStr = datum.substring(2, datum.length()); | |
value64 = new BigInteger(subStr, 16); | |
} else { | |
value64 = new BigInteger(datum); | |
} | |
} else { | |
value64 = new BigInteger(datum); | |
} | |
} catch (NumberFormatException nfeExp) { | |
exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not "+ | |
"valid digital of UINT32", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
if (value64.bitLength() > 32) { | |
exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s which "+ | |
"exceed the range of UINT32 - 0xFFFFFFFF", | |
cName, | |
moduleName, | |
datum); | |
return exceptionString; | |
} | |
} | |
break; | |
case UINT64: | |
if (maxDatumSize != 8) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+ | |
"is UINT64, but datum size is %d, they are not matched!", | |
cName, | |
moduleName, | |
maxDatumSize); | |
return exceptionString; | |
} | |
if (datum != null) { | |
try { | |
if (datum.length() > 2) { | |
if ((datum.charAt(0) == '0') && | |
((datum.charAt(1) == 'x') || (datum.charAt(1) == 'X'))){ | |
subStr = datum.substring(2, datum.length()); | |
value64 = new BigInteger(subStr, 16); | |
} else { | |
value64 = new BigInteger(datum); | |
} | |
} else { | |
value64 = new BigInteger(datum); | |
} | |
} catch (NumberFormatException nfeExp) { | |
exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not valid"+ | |
" digital of UINT64", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
if (value64.bitLength() > 64) { | |
exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s "+ | |
"exceed the range of UINT64 - 0xFFFFFFFFFFFFFFFF", | |
cName, | |
moduleName, | |
datum); | |
return exceptionString; | |
} | |
} | |
break; | |
case BOOLEAN: | |
if (maxDatumSize != 1) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+ | |
"is BOOLEAN, but datum size is %d, they are not matched!", | |
cName, | |
moduleName, | |
maxDatumSize); | |
return exceptionString; | |
} | |
if (datum != null) { | |
if (!(datum.equalsIgnoreCase("TRUE") || | |
datum.equalsIgnoreCase("FALSE"))) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+ | |
"is BOOELAN, but value is not 'true'/'TRUE' or 'FALSE'/'false'", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
} | |
break; | |
case POINTER: | |
if (datum == null) { | |
break; | |
} | |
char ch = datum.charAt(0); | |
int start, end; | |
String strValue; | |
// | |
// For void* type PCD, only three datum is support: | |
// 1) Unicode: string with start char is "L" | |
// 2) Ansci: String start char is "" | |
// 3) byte array: String start char "{" | |
// | |
if (ch == 'L') { | |
start = datum.indexOf('\"'); | |
end = datum.lastIndexOf('\"'); | |
if ((start > end) || | |
(end > datum.length())|| | |
((start == end) && (datum.length() > 0))) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+ | |
"a UNICODE string because start with L\", but format maybe"+ | |
"is not right, correct UNICODE string is L\"...\"!", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
strValue = datum.substring(start + 1, end); | |
if ((strValue.length() * 2) > maxDatumSize) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+ | |
"a UNICODE string, but the datum size is %d exceed to <MaxDatumSize> : %d", | |
cName, | |
moduleName, | |
strValue.length() * 2, | |
maxDatumSize); | |
return exceptionString; | |
} | |
} else if (ch == '\"'){ | |
start = datum.indexOf('\"'); | |
end = datum.lastIndexOf('\"'); | |
if ((start > end) || | |
(end > datum.length())|| | |
((start == end) && (datum.length() > 0))) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+ | |
"a ANSCII string because start with \", but format maybe"+ | |
"is not right, correct ANSIC string is \"...\"!", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
strValue = datum.substring(start + 1, end); | |
if ((strValue.length()) > maxDatumSize) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+ | |
"a ANSCI string, but the datum size is %d which exceed to <MaxDatumSize> : %d", | |
cName, | |
moduleName, | |
strValue.length(), | |
maxDatumSize); | |
return exceptionString; | |
} | |
} else if (ch =='{') { | |
String[] strValueArray; | |
start = datum.indexOf('{'); | |
end = datum.lastIndexOf('}'); | |
strValue = datum.substring(start + 1, end); | |
strValue = strValue.trim(); | |
if (strValue.length() == 0) { | |
break; | |
} | |
strValueArray = strValue.split(","); | |
for (index = 0; index < strValueArray.length; index ++) { | |
try{ | |
value = Integer.decode(strValueArray[index].trim()); | |
} catch (NumberFormatException nfeEx) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+ | |
"it is byte array in fact. For every byte in array should be a valid"+ | |
"byte digital, but element %s is not a valid byte digital!", | |
cName, | |
moduleName, | |
strValueArray[index]); | |
return exceptionString; | |
} | |
if (value > 0xFF) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, "+ | |
"it is byte array in fact. But the element of %s exceed the byte range", | |
cName, | |
moduleName, | |
strValueArray[index]); | |
return exceptionString; | |
} | |
} | |
if (strValueArray.length > maxDatumSize) { | |
exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is byte"+ | |
"array, but the number of bytes is %d which exceed to <MaxDatumSzie> : %d!", | |
cName, | |
moduleName, | |
strValueArray.length, | |
maxDatumSize); | |
return exceptionString; | |
} | |
} else { | |
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 "+ | |
"1) UNICODE string: like L\"xxxx\";\r\n"+ | |
"2) ANSIC string: like \"xxx\";\r\n"+ | |
"3) Byte array: like {0x2, 0x45, 0x23}\r\n"+ | |
"But the datum in seems does not following above format!", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
break; | |
default: | |
exceptionString = String.format("[FPD file error] For PCD entry %s in %s, datum type is unknown, it should be one of "+ | |
"UINT8, UINT16, UINT32, UINT64, VOID*, BOOLEAN", | |
cName, | |
moduleName); | |
return exceptionString; | |
} | |
return null; | |
} | |
/** | |
Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file. | |
This function should be implemented in GlobalData in future. | |
@param token The token instance which has hold module's PCD information | |
@param moduleName The name of module who will use this Dynamic PCD. | |
@return DynamicPcdBuildDefinitions.PcdBuildData | |
*/ | |
/***/ | |
private DynamicPcdBuildDefinitions.PcdBuildData getDynamicInfoFromFPD(Token token, | |
String moduleName) | |
throws EntityException { | |
int index = 0; | |
String exceptionString = null; | |
String dynamicPrimaryKey = null; | |
DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null; | |
List<DynamicPcdBuildDefinitions.PcdBuildData> dynamicPcdBuildDataArray = null; | |
// | |
// If FPD document is not be opened, open and initialize it. | |
// | |
if (fpdDocInstance == null) { | |
try { | |
fpdDocInstance = (FrameworkPlatformDescriptionDocument)XmlObject.Factory.parse(new File(fpdFilePath)); | |
} catch(IOException ioE) { | |
throw new EntityException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage()); | |
} catch(XmlException xmlE) { | |
throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage()); | |
} | |
} | |
dynamicPcdBuildDefinitions = fpdDocInstance.getFrameworkPlatformDescription().getDynamicPcdBuildDefinitions(); | |
if (dynamicPcdBuildDefinitions == null) { | |
exceptionString = String.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+ | |
"PCD entry %s in module %s!", | |
token.cName, | |
moduleName); | |
throw new EntityException(exceptionString); | |
} | |
dynamicPcdBuildDataArray = dynamicPcdBuildDefinitions.getPcdBuildDataList(); | |
for (index = 0; index < dynamicPcdBuildDataArray.size(); index ++) { | |
// | |
// Check <TokenSpaceGuid> is exist? In future, because all schema verification will tools | |
// will check that, following checking code could be removed. | |
// | |
if (dynamicPcdBuildDataArray.get(index).getTokenSpaceGuid() == null) { | |
exceptionString = String.format("[FPD file error] There is no <TokenSpaceGuid> for PCD %s in <DynamicPcdBuildDefinitions>! This is required!", | |
dynamicPcdBuildDataArray.get(index).getCName()); | |
throw new EntityException(exceptionString); | |
} | |
dynamicPrimaryKey = Token.getPrimaryKeyString(dynamicPcdBuildDataArray.get(index).getCName(), | |
translateSchemaStringToUUID(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuid())); | |
if (dynamicPrimaryKey.equalsIgnoreCase(token.getPrimaryKeyString())) { | |
return dynamicPcdBuildDataArray.get(index); | |
} | |
} | |
return null; | |
} | |
/** | |
Update dynamic information for PCD entry. | |
Dynamic information is retrieved from <PcdDynamicBuildDeclarations> in | |
FPD file. | |
@param moduleName The name of the module who use this PCD | |
@param token The token instance | |
@param datum The <datum> in module's PCD information | |
@param maxDatumSize The <maxDatumSize> in module's PCD information | |
@return Token | |
*/ | |
private Token updateDynamicInformation(String moduleName, | |
Token token, | |
String datum, | |
int maxDatumSize) | |
throws EntityException { | |
int index = 0; | |
int offset; | |
String exceptionString = null; | |
DynamicTokenValue dynamicValue; | |
SkuInstance skuInstance = null; | |
String temp; | |
boolean hasSkuId0 = false; | |
Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; | |
int tokenNumber = 0; | |
String hiiDefaultValue = null; | |
String[] variableGuidString = null; | |
List<DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo> skuInfoList = null; | |
DynamicPcdBuildDefinitions.PcdBuildData dynamicInfo = null; | |
dynamicInfo = getDynamicInfoFromFPD(token, moduleName); | |
if (dynamicInfo == null) { | |
exceptionString = String.format("[FPD file error] For Dynamic PCD %s used by module %s, "+ | |
"there is no dynamic information in <DynamicPcdBuildDefinitions> "+ | |
"in FPD file, but it is required!", | |
token.cName, | |
moduleName); | |
throw new EntityException(exceptionString); | |
} | |
token.datumSize = dynamicInfo.getMaxDatumSize(); | |
exceptionString = verifyDatum(token.cName, | |
moduleName, | |
null, | |
token.datumType, | |
token.datumSize); | |
if (exceptionString != null) { | |
throw new EntityException(exceptionString); | |
} | |
if ((maxDatumSize != 0) && | |
(maxDatumSize != token.datumSize)) { | |
exceptionString = String.format("FPD file error] For dynamic PCD %s, the datum size in module %s is %d, but "+ | |
"the datum size in <DynamicPcdBuildDefinitions> is %d, they are not match!", | |
token.cName, | |
moduleName, | |
maxDatumSize, | |
dynamicInfo.getMaxDatumSize()); | |
throw new EntityException(exceptionString); | |
} | |
tokenNumber = Integer.decode(dynamicInfo.getToken().toString()); | |
if (tokenNumber != token.tokenNumber) { | |
exceptionString = String.format("[FPD file error] For dynamic PCD %s, the token number in module %s is 0x%x, but"+ | |
"in <DynamicPcdBuildDefinictions>, the token number is 0x%x, they are not match!", | |
token.cName, | |
moduleName, | |
token.tokenNumber, | |
tokenNumber); | |
throw new EntityException(exceptionString); | |
} | |
pcdType = Token.getpcdTypeFromString(dynamicInfo.getItemType().toString()); | |
if (pcdType == Token.PCD_TYPE.DYNAMIC_EX) { | |
token.dynamicExTokenNumber = tokenNumber; | |
} | |
skuInfoList = dynamicInfo.getSkuInfoList(); | |
// | |
// Loop all sku data | |
// | |
for (index = 0; index < skuInfoList.size(); index ++) { | |
skuInstance = new SkuInstance(); | |
// | |
// Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value. | |
// | |
temp = skuInfoList.get(index).getSkuId().toString(); | |
skuInstance.id = Integer.decode(temp); | |
if (skuInstance.id == 0) { | |
hasSkuId0 = true; | |
} | |
// | |
// Judge whether is DefaultGroup at first, because most case is DefautlGroup. | |
// | |
if (skuInfoList.get(index).getValue() != null) { | |
skuInstance.value.setValue(skuInfoList.get(index).getValue().toString()); | |
if ((exceptionString = verifyDatum(token.cName, | |
null, | |
skuInfoList.get(index).getValue().toString(), | |
token.datumType, | |
token.datumSize)) != null) { | |
throw new EntityException(exceptionString); | |
} | |
token.skuData.add(skuInstance); | |
// | |
// Judege wether is same of datum between module's information | |
// and dynamic information. | |
// | |
if (datum != null) { | |
if ((skuInstance.id == 0) && | |
!datum.toString().equalsIgnoreCase(skuInfoList.get(index).getValue().toString())) { | |
exceptionString = "[FPD file error] For dynamic PCD " + token.cName + ", the value in module " + moduleName + " is " + datum.toString() + " but the "+ | |
"value of sku 0 data in <DynamicPcdBuildDefinition> is " + skuInstance.value.value + ". They are must be same!"+ | |
" or you could not define value for a dynamic PCD in every <ModuleSA>!"; | |
throw new EntityException(exceptionString); | |
} | |
} | |
continue; | |
} | |
// | |
// Judge whether is HII group case. | |
// | |
if (skuInfoList.get(index).getVariableName() != null) { | |
exceptionString = null; | |
if (skuInfoList.get(index).getVariableGuid() == null) { | |
exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+ | |
"file, who use HII, but there is no <VariableGuid> defined for Sku %d data!", | |
token.cName, | |
index); | |
if (exceptionString != null) { | |
throw new EntityException(exceptionString); | |
} | |
} | |
if (skuInfoList.get(index).getVariableOffset() == null) { | |
exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+ | |
"file, who use HII, but there is no <VariableOffset> defined for Sku %d data!", | |
token.cName, | |
index); | |
if (exceptionString != null) { | |
throw new EntityException(exceptionString); | |
} | |
} | |
if (skuInfoList.get(index).getHiiDefaultValue() == null) { | |
exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+ | |
"file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!", | |
token.cName, | |
index); | |
if (exceptionString != null) { | |
throw new EntityException(exceptionString); | |
} | |
} | |
if (skuInfoList.get(index).getHiiDefaultValue() != null) { | |
hiiDefaultValue = skuInfoList.get(index).getHiiDefaultValue().toString(); | |
} else { | |
hiiDefaultValue = null; | |
} | |
if ((exceptionString = verifyDatum(token.cName, | |
null, | |
hiiDefaultValue, | |
token.datumType, | |
token.datumSize)) != null) { | |
throw new EntityException(exceptionString); | |
} | |
offset = Integer.decode(skuInfoList.get(index).getVariableOffset()); | |
if (offset > 0xFFFF) { | |
throw new EntityException(String.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+ | |
"exceed 64K, it is not allowed!", | |
token.cName, | |
index)); | |
} | |
// | |
// Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file. | |
// | |
variableGuidString = GlobalData.getGuidInfoGuid(skuInfoList.get(index).getVariableGuid().toString()); | |
if (variableGuidString == null) { | |
throw new EntityException(String.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!", | |
token.cName, | |
skuInfoList.get(index).getVariableGuid().toString())); | |
} | |
skuInstance.value.setHiiData(skuInfoList.get(index).getVariableName(), | |
translateSchemaStringToUUID(variableGuidString[1]), | |
skuInfoList.get(index).getVariableOffset(), | |
skuInfoList.get(index).getHiiDefaultValue().toString()); | |
token.skuData.add(skuInstance); | |
continue; | |
} | |
if (skuInfoList.get(index).getVpdOffset() != null) { | |
skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset()); | |
token.skuData.add(skuInstance); | |
continue; | |
} | |
exceptionString = String.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+ | |
"be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.", | |
token.cName); | |
throw new EntityException(exceptionString); | |
} | |
if (!hasSkuId0) { | |
exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+ | |
"no sku id = 0 data, which is required for every dynamic PCD", | |
token.cName); | |
throw new EntityException(exceptionString); | |
} | |
return token; | |
} | |
/** | |
Translate the schema string to UUID instance. | |
In schema, the string of UUID is defined as following two types string: | |
1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},( | |
)*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})? | |
2) GuidNamingConvention: pattern = | |
[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} | |
This function will convert string and create uuid instance. | |
@param uuidString UUID string in XML file | |
@return UUID UUID instance | |
**/ | |
private UUID translateSchemaStringToUUID(String uuidString) | |
throws EntityException { | |
String temp; | |
String[] splitStringArray; | |
int index; | |
int chIndex; | |
int chLen; | |
if (uuidString == null) { | |
return null; | |
} | |
if (uuidString.length() == 0) { | |
return null; | |
} | |
if (uuidString.equals("0") || | |
uuidString.equalsIgnoreCase("0x0")) { | |
return new UUID(0, 0); | |
} | |
uuidString = uuidString.replaceAll("\\{", ""); | |
uuidString = uuidString.replaceAll("\\}", ""); | |
// | |
// If the UUID schema string is GuidArrayType type then need translate | |
// to GuidNamingConvention type at first. | |
// | |
if ((uuidString.charAt(0) == '0') && ((uuidString.charAt(1) == 'x') || (uuidString.charAt(1) == 'X'))) { | |
splitStringArray = uuidString.split("," ); | |
if (splitStringArray.length != 11) { | |
throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString); | |
} | |
// | |
// Remove blank space from these string and remove header string "0x" | |
// | |
for (index = 0; index < 11; index ++) { | |
splitStringArray[index] = splitStringArray[index].trim(); | |
splitStringArray[index] = splitStringArray[index].substring(2, splitStringArray[index].length()); | |
} | |
// | |
// Add heading '0' to normalize the string length | |
// | |
for (index = 3; index < 11; index ++) { | |
chLen = splitStringArray[index].length(); | |
for (chIndex = 0; chIndex < 2 - chLen; chIndex ++) { | |
splitStringArray[index] = "0" + splitStringArray[index]; | |
} | |
} | |
// | |
// construct the final GuidNamingConvention string | |
// | |
temp = String.format("%s-%s-%s-%s%s-%s%s%s%s%s%s", | |
splitStringArray[0], | |
splitStringArray[1], | |
splitStringArray[2], | |
splitStringArray[3], | |
splitStringArray[4], | |
splitStringArray[5], | |
splitStringArray[6], | |
splitStringArray[7], | |
splitStringArray[8], | |
splitStringArray[9], | |
splitStringArray[10]); | |
uuidString = temp; | |
} | |
return UUID.fromString(uuidString); | |
} | |
/** | |
check parameter for this action. | |
@throws EntityException Bad parameter. | |
**/ | |
private void checkParameter() throws EntityException { | |
File file = null; | |
if((fpdFilePath == null) ||(workspacePath == null)) { | |
throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); | |
} | |
if(fpdFilePath.length() == 0 || workspacePath.length() == 0) { | |
throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); | |
} | |
file = new File(workspacePath); | |
if(!file.exists()) { | |
throw new EntityException("WorkpacePath " + workspacePath + " does not exist!"); | |
} | |
file = new File(fpdFilePath); | |
if(!file.exists()) { | |
throw new EntityException("FPD File " + fpdFilePath + " does not exist!"); | |
} | |
} | |
/** | |
Test case function | |
@param argv parameter from command line | |
**/ | |
public static void main(String argv[]) throws EntityException { | |
CollectPCDAction ca = new CollectPCDAction(); | |
ca.setWorkspacePath("m:/tianocore/edk2"); | |
ca.setFPDFilePath("m:/tianocore/edk2/EdkNt32Pkg/Nt32.fpd"); | |
ca.setActionMessageLevel(ActionMessage.MAX_MESSAGE_LEVEL); | |
GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db", | |
"m:/tianocore/edk2"); | |
ca.execute(); | |
} | |
} |