X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=Tools%2FSource%2FGenBuild%2Forg%2Ftianocore%2Fbuild%2Fpcd%2Faction%2FCollectPCDAction.java;h=8242a4c87c363dca42b14fbc237c6a635f683b38;hp=da9880161c39d2468a091ab254c79751905ddd20;hb=eece174ad00f11db8688a36f7c7ef57c9ced98db;hpb=99d2c3c41e39698e527dfdf4d8d5323af20db745 diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java index da9880161c..8242a4c87c 100644 --- a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java @@ -17,50 +17,83 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ package org.tianocore.build.pcd.action; -import java.io.BufferedReader; +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.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; -import org.tianocore.FrameworkPlatformDescriptionDocument; +import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions; +import org.tianocore.FrameworkModulesDocument; import org.tianocore.ModuleSADocument; -import org.tianocore.PackageSurfaceAreaDocument; -import org.tianocore.PcdBuildDeclarationsDocument.PcdBuildDeclarations.PcdBuildData; -import org.tianocore.PcdDefinitionsDocument.PcdDefinitions; +import org.tianocore.PcdBuildDefinitionDocument; +import org.tianocore.PcdBuildDefinitionDocument.PcdBuildDefinition; +import org.tianocore.PlatformSurfaceAreaDocument; import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.fpd.FpdParserTask; import org.tianocore.build.global.GlobalData; -import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.id.FpdModuleIdentification; 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; +/** + CStructTypeDeclaration + + This class is used to store the declaration string, such as + "UINT32 PcdPlatformFlashBaseAddress", of + each memember in the C structure, which is a standard C language + feature used to implement a simple and efficient database for + dynamic(ex) type PCD entry. +**/ + +class CStructTypeDeclaration { + String key; + int alignmentSize; + String cCode; + boolean initTable; + + public CStructTypeDeclaration (String key, int alignmentSize, String cCode, boolean initTable) { + this.key = key; + this.alignmentSize = alignmentSize; + this.cCode = cCode; + this.initTable = initTable; + } +} + +/** + StringTable + + This class is used to store the String in a PCD database. + +**/ class StringTable { private ArrayList al; - private ArrayList alComments; + private ArrayList alComments; private String phase; int len; - int bodyStart; - int bodyLineNum; public StringTable (String phase) { this.phase = phase; al = new ArrayList(); - alComments = new ArrayList(); + alComments = new ArrayList(); len = 0; - bodyStart = 0; - bodyLineNum = 0; } public String getSizeMacro () { @@ -68,189 +101,249 @@ class StringTable { } private int getSize () { - // - // We have at least one Unicode Character in the table. - // + // + // 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 void genCode (ArrayList declaList, HashMap instTable) { + final String stringTable = "StringTable"; + final String tab = "\t"; + final String newLine = "\r\n"; + final String commaNewLine = ",\r\n"; + + CStructTypeDeclaration decl; - 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 getInstantiation () { - ArrayList output = new ArrayList(); - - output.add("/* StringTable */"); - - if (al.size() == 0) { - output.add("{ 0 }"); - } else { - String str; + String cDeclCode = ""; + String cInstCode = ""; - 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); - } - } + // + // If we have a empty StringTable + // + if (al.size() == 0) { + cDeclCode += String.format("%-20s%s[1]; /* StringTable is empty */", "UINT16", stringTable) + newLine; + decl = new CStructTypeDeclaration ( + stringTable, + 2, + cDeclCode, + true + ); + declaList.add(decl); + + cInstCode = String.format("/* %s */", stringTable) + newLine + tab + "{ 0 }"; + instTable.put(stringTable, cInstCode); + } else { - return output; + // + // If there is any String in the StringTable + // + for (int i = 0; i < al.size(); i++) { + String str = al.get(i); + String stringTableName; + + if (i == 0) { + // + // StringTable is a well-known name in the PCD DXE driver + // + stringTableName = stringTable; + + } else { + stringTableName = String.format("%s_%d", stringTable, i); + cDeclCode += tab; + } + cDeclCode += String.format("%-20s%s[%d]; /* %s */", "UINT16", + stringTableName, str.length() + 1, + alComments.get(i)) + + newLine; + + if (i == 0) { + cInstCode = "/* StringTable */" + newLine; + } + + cInstCode += tab + String.format("L\"%s\" /* %s */", al.get(i), alComments.get(i)); + if (i != al.size() - 1) { + cInstCode += commaNewLine; + } + } + + decl = new CStructTypeDeclaration ( + stringTable, + 2, + cDeclCode, + true + ); + declaList.add(decl); + + instTable.put(stringTable, cInstCode); + } } - public int add (String str, Token token) { + public int add (String inputStr, Token token) { int i; + int pos; + + String str = inputStr; + + // + // The input can be two types: + // "L\"Bootmode\"" or "Bootmode". + // We drop the L\" and \" for the first type. + if (str.startsWith("L\"") && str.endsWith("\"")) { + str = str.substring(2, str.length() - 1); + } + // + // Check if StringTable has this String already. + // If so, return the current pos. + // + for (i = 0, pos = 0; i < al.size(); i++) { + String s = al.get(i);; + if (str.equals(s)) { + return pos; + } + pos = s.length() + 1; + } + i = len; // // Include the NULL character at the end of String // len += str.length() + 1; al.add(str); - alComments.add(token.getPrimaryKeyString()); + alComments.add(token.getPrimaryKeyString()); return i; } } +/** + SizeTable + + This class is used to store the Size information for + POINTER TYPE PCD entry in a PCD database. + +**/ class SizeTable { - private ArrayList al; - private ArrayList alComments; - private String phase; + private ArrayList> al; + private ArrayList alComments; private int len; - private int bodyStart; - private int bodyLineNum; - + private String phase; + public SizeTable (String phase) { - this.phase = phase; - al = new ArrayList(); - alComments = new ArrayList(); + al = new ArrayList>(); + alComments = new ArrayList(); len = 0; - bodyStart = 0; - bodyLineNum = 0; + this.phase = phase; } - public String getTypeDeclaration () { - return String.format(PcdDatabase.SizeTableDeclaration, phase); + public String getSizeMacro () { + return String.format(PcdDatabase.SizeTableSizeMacro, phase, getSize()); + } + + private int getSize() { + return len == 0 ? 1 : len; } - public ArrayList getInstantiation () { - ArrayList Output = new ArrayList(); + public void genCode (ArrayList declaList, HashMap instTable, String phase) { + final String name = "SizeTable"; + + CStructTypeDeclaration decl; + String cCode; + + cCode = String.format(PcdDatabase.SizeTableDeclaration, phase); + decl = new CStructTypeDeclaration ( + name, + 2, + cCode, + true + ); + declaList.add(decl); - 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; + cCode = PcdDatabase.genInstantiationStr(getInstantiation()); + instTable.put(name, cCode); } - public int getBodyStart() { - return bodyStart; - } + private ArrayList getInstantiation () { + final String comma = ","; + ArrayList Output = new ArrayList(); - public int getBodyLineNum () { - return bodyLineNum; - } + Output.add("/* SizeTable */"); + Output.add("{"); + if (al.size() == 0) { + Output.add("\t0"); + } else { + for (int index = 0; index < al.size(); index++) { + ArrayList ial = al.get(index); + + String str = "\t"; + + for (int index2 = 0; index2 < ial.size(); index2++) { + str += " " + ial.get(index2).toString(); + if (index2 != ial.size() - 1) { + str += comma; + } + } - public int add (Token token) { - int index = len; + str += " /* " + alComments.get(index) + " */"; + + if (index != (al.size() - 1)) { + str += comma; + } - len++; - al.add(token.datumSize); - alComments.add(token.getPrimaryKeyString()); + Output.add(str); + + } + } + Output.add("}"); - return index; + return Output; } - private int getDatumSize(Token token) { - /* - switch (token.datumType) { - case Token.DATUM_TYPE.UINT8: - return 1; - default: - return 0; - } - */ - return 0; - } + public void add (Token token) { + + // + // We only have size information for POINTER type PCD entry. + // + if (token.datumType != Token.DATUM_TYPE.POINTER) { + return; + } + + ArrayList ial = token.getPointerTypeSize(); + + len+= ial.size(); - public int getTableLen () { - return al.size() == 0 ? 1 : al.size(); - } + al.add(ial); + alComments.add(token.getPrimaryKeyString()); + return; + } + } +/** + GuidTable + + This class is used to store the GUIDs in a PCD database. +**/ class GuidTable { private ArrayList al; - private ArrayList alComments; + private ArrayList alComments; private String phase; private int len; - private int bodyStart; - private int bodyLineNum; + private int bodyLineNum; public GuidTable (String phase) { this.phase = phase; al = new ArrayList(); - alComments = new ArrayList(); + alComments = new ArrayList(); len = 0; - bodyStart = 0; - bodyLineNum = 0; + bodyLineNum = 0; } public String getSizeMacro () { @@ -265,96 +358,111 @@ class GuidTable { return String.format(PcdDatabase.GuidTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); } - public String getTypeDeclaration () { - return String.format(PcdDatabase.GuidTableDeclaration, phase); - } + public void genCode (ArrayList declaList, HashMap instTable, String phase) { + final String name = "GuidTable"; + + CStructTypeDeclaration decl; + String cCode = ""; - private String getUuidCString (UUID uuid) { - String[] guidStrArray; + cCode += String.format(PcdDatabase.GuidTableDeclaration, phase); + decl = new CStructTypeDeclaration ( + name, + 4, + cCode, + true + ); + declaList.add(decl); - 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)) - ); - } + cCode = PcdDatabase.genInstantiationStr(getInstantiation()); + instTable.put(name, cCode); + } + + 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 getInstantiation () { - ArrayList Output = new ArrayList(); + private ArrayList getInstantiation () { + ArrayList Output = new ArrayList(); Output.add("/* GuidTable */"); Output.add("{"); - bodyStart = 2; - if (al.size() == 0) { - Output.add(getUuidCString(new UUID(0, 0))); - } + if (al.size() == 0) { + Output.add("\t" + getUuidCString(new UUID(0, 0))); + } - for (Object u : al) { - UUID uuid = (UUID)u; - String str = getUuidCString(uuid); + for (int i = 0; i < al.size(); i++) { + String str = "\t" + getUuidCString(al.get(i)); - if (al.indexOf(u) != (al.size() - 1)) { - str += ","; - } + str += "/* " + alComments.get(i) + " */"; + if (i != (al.size() - 1)) { + str += ","; + } Output.add(str); - bodyLineNum++; + bodyLineNum++; } - Output.add("}"); + 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 + // Check if GuidTable has this entry already. + // If so, return the GuidTable index. // + for (int i = 0; i < al.size(); i++) { + if (al.get(i).compareTo(uuid) == 0) { + return i; + } + } + len++; al.add(uuid); + alComments.add(name); - return index; + // + // Return the previous Table Index + // + return len - 1; } - public int getTableLen () { - return al.size() == 0 ? 0 : al.size(); - } - } +/** + SkuIdTable + + This class is used to store the SKU IDs in a PCD database. + +**/ class SkuIdTable { private ArrayList al; - private ArrayList alComment; + private ArrayList alComment; private String phase; private int len; - private int bodyStart; - private int bodyLineNum; public SkuIdTable (String phase) { this.phase = phase; al = new ArrayList(); - alComment = new ArrayList(); - bodyStart = 0; - bodyLineNum = 0; + alComment = new ArrayList(); len = 0; } @@ -363,100 +471,148 @@ class SkuIdTable { } private int getSize () { - return (al.size() == 0)? 1 : al.size(); + return (len == 0)? 1 : len; } public String getExistanceMacro () { return String.format(PcdDatabase.SkuTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); } - public String getTypeDeclaration () { - return String.format(PcdDatabase.SkuIdTableDeclaration, phase); + public void genCode (ArrayList declaList, HashMap instTable, String phase) { + final String name = "SkuIdTable"; + + CStructTypeDeclaration decl; + String cCode = ""; + + cCode += String.format(PcdDatabase.SkuIdTableDeclaration, phase); + decl = new CStructTypeDeclaration ( + name, + 1, + cCode, + true + ); + declaList.add(decl); + + + cCode = PcdDatabase.genInstantiationStr(getInstantiation()); + instTable.put(name, cCode); + + // + // SystemSkuId is in PEI phase PCD Database + // + if (phase.equalsIgnoreCase("PEI")) { + decl = new CStructTypeDeclaration ( + "SystemSkuId", + 1, + String.format("%-20sSystemSkuId;\r\n", "SKU_ID"), + true + ); + declaList.add(decl); + + instTable.put("SystemSkuId", "0"); + } + } - public ArrayList getInstantiation () { - ArrayList Output = new ArrayList (); + private ArrayList getInstantiation () { + ArrayList Output = new ArrayList (); Output.add("/* SkuIdTable */"); Output.add("{"); - bodyStart = 2; - if (al.size() == 0) { - Output.add("0"); - } + if (al.size() == 0) { + Output.add("\t0"); + } for (int index = 0; index < al.size(); index++) { - String str; + String str; - str = "/* " + alComment.get(index) + "*/ "; - str += "/* MaxSku */ "; + str = "/* " + alComment.get(index) + "*/ "; + str += "/* MaxSku */ "; - Integer[] ia = al.get(index); + 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 += ", "; - } - } + str += "\t" + ia[0].toString() + ", "; + for (int index2 = 1; index2 < ia.length; index2++) { + str += ia[index2].toString(); + if (!((index2 == ia.length - 1) && (index == al.size() - 1))) { + str += ", "; + } + } Output.add(str); - bodyLineNum++; } - Output.add("}"); + Output.add("}"); return Output; } public int add (Token token) { - int index; + int index; + int pos; + + // + // Check if this SKU_ID Array is already in the table + // + pos = 0; + for (Object o: al) { + Integer [] s = (Integer[]) o; + boolean different = false; + if (s[0] == token.getSkuIdCount()) { + for (index = 1; index < s.length; index++) { + if (s[index] != token.skuData.get(index-1).id) { + different = true; + break; + } + } + } else { + different = true; + } + if (different) { + pos += s[0] + 1; + } else { + return pos; + } + } - Integer [] skuIds = new Integer[token.maxSkuCount + 1]; - skuIds[0] = new Integer(token.maxSkuCount); - for (index = 1; index < skuIds.length; index++) { - skuIds[index] = new Integer(token.skuData.get(index - 1).id); - } + 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()); + alComment.add(token.getPrimaryKeyString()); return index; } - public int getTableLen () { - return al.size() == 0 ? 1 : al.size(); - } - } class LocalTokenNumberTable { private ArrayList al; - private ArrayList alComment; + private ArrayList alComment; private String phase; private int len; - private int bodyStart; - private int bodyLineNum; public LocalTokenNumberTable (String phase) { this.phase = phase; al = new ArrayList(); - alComment = new ArrayList(); - bodyStart = 0; - bodyLineNum = 0; + alComment = new ArrayList(); len = 0; } public String getSizeMacro () { - return String.format(PcdDatabase.LocalTokenNumberTableSizeMacro, phase, getSize()); + return String.format(PcdDatabase.LocalTokenNumberTableSizeMacro, phase, getSize()) + + String.format(PcdDatabase.LocalTokenNumberSizeMacro, phase, al.size()); } public int getSize () { @@ -467,156 +623,210 @@ class LocalTokenNumberTable { return String.format(PcdDatabase.DatabaseExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); } - public String getTypeDeclaration () { - return String.format(PcdDatabase.LocalTokenNumberTableDeclaration, phase); + public void genCode (ArrayList declaList, HashMap instTable, String phase) { + final String name = "LocalTokenNumberTable"; + + CStructTypeDeclaration decl; + String cCode = ""; + + cCode += String.format(PcdDatabase.LocalTokenNumberTableDeclaration, phase); + decl = new CStructTypeDeclaration ( + name, + 4, + cCode, + true + ); + declaList.add(decl); + + cCode = PcdDatabase.genInstantiationStr(getInstantiation()); + instTable.put(name, cCode); } - public ArrayList getInstantiation () { - ArrayList output = new ArrayList(); + private ArrayList getInstantiation () { + ArrayList output = new ArrayList(); output.add("/* LocalTokenNumberTable */"); output.add("{"); - bodyStart = 2; - if (al.size() == 0) { - output.add("0"); - } + if (al.size() == 0) { + output.add("\t0"); + } for (int index = 0; index < al.size(); index++) { - String str; + String str; - str = (String)al.get(index); + str = "\t" + (String)al.get(index); - str += " /* " + alComment.get(index) + " */ "; + str += " /* " + alComment.get(index) + " */ "; - if (index != (al.size() - 1)) { - str += ","; - } + if (index != (al.size() - 1)) { + str += ","; + } output.add(str); } - bodyLineNum = al.size(); - - output.add("}"); + output.add("}"); return output; } public int add (Token token) { int index = len; - String str; + String str; len++; - str = String.format(PcdDatabase.offsetOfStrTemplate, phase, token.hasDefaultValue() ? "Init" : "Uninit", token.getPrimaryKeyString()); + str = String.format(PcdDatabase.offsetOfStrTemplate, phase, token.hasDefaultValue() ? "Init" : "Uninit", token.getPrimaryKeyString()); - if (token.isStringType()) { - str += " | PCD_TYPE_STRING"; - } + if (token.isUnicodeStringType()) { + str += " | PCD_TYPE_STRING"; + } - if (token.skuEnabled) { - str += " | PCD_TYPE_SKU_ENABLED"; - } + if (token.isSkuEnable()) { + str += " | PCD_TYPE_SKU_ENABLED"; + } - if (token.hiiEnabled) { - str += " | PCD_TYPE_HII"; - } + if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.HII_TYPE) { + str += " | PCD_TYPE_HII"; + } - if (token.vpdEnabled) { - str += " | PCD_TYPE_VPD"; - } - + if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.VPD_TYPE) { + str += " | PCD_TYPE_VPD"; + } + + switch (token.datumType) { + case UINT8: + case BOOLEAN: + str += " | PCD_DATUM_TYPE_UINT8"; + break; + case UINT16: + str += " | PCD_DATUM_TYPE_UINT16"; + break; + case UINT32: + str += " | PCD_DATUM_TYPE_UINT32"; + break; + case UINT64: + str += " | PCD_DATUM_TYPE_UINT64"; + break; + case POINTER: + str += " | PCD_DATUM_TYPE_POINTER"; + break; + } + al.add(str); - alComment.add(token.getPrimaryKeyString()); + alComment.add(token.getPrimaryKeyString()); return index; } } +/** + ExMapTable + + This class is used to store the table of mapping information + between DynamicEX ID pair(Guid, TokenNumber) and + the local token number assigned by PcdDatabase class. +**/ 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); - } - } + /** + ExTriplet + + This class is used to store the mapping information + between DynamicEX ID pair(Guid, TokenNumber) and + the local token number assigned by PcdDatabase class. + **/ + 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 al; - private ArrayList alComment; + private Map alComment; private String phase; private int len; - private int bodyStart; - private int bodyLineNum; - private int base; - + private int bodyLineNum; + public ExMapTable (String phase) { this.phase = phase; al = new ArrayList(); - alComment = new ArrayList(); - bodyStart = 0; - bodyLineNum = 0; + alComment = new HashMap(); + 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(); + + String.format(PcdDatabase.ExTokenNumber, phase, 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 void genCode (ArrayList declaList, HashMap instTable, String phase) { + final String exMapTableName = "ExMapTable"; + + sortTable(); + + CStructTypeDeclaration decl; + String cCode = ""; + + cCode += String.format(PcdDatabase.ExMapTableDeclaration, phase); + decl = new CStructTypeDeclaration ( + exMapTableName, + 4, + cCode, + true + ); + declaList.add(decl); - public ArrayList getInstantiation () { - ArrayList Output = new ArrayList(); + + cCode = PcdDatabase.genInstantiationStr(getInstantiation()); + instTable.put(exMapTableName, cCode); + } + + private ArrayList getInstantiation () { + ArrayList Output = new ArrayList(); Output.add("/* ExMapTable */"); Output.add("{"); - bodyStart = 2; - - if (al.size() == 0) { - Output.add("{0, 0, 0}"); - } + if (al.size() == 0) { + Output.add("\t{0, 0, 0}"); + } - int index; + int index; for (index = 0; index < al.size(); index++) { - String str; + String str; - ExTriplet e = (ExTriplet)al.get(index); + ExTriplet e = (ExTriplet)al.get(index); - str = "{ " + e.exTokenNumber.toString() + ", "; - str += e.localTokenIdx.toString() + ", "; - str += e.guidTableIdx.toString(); + str = "\t" + "{ " + String.format("0x%08X", e.exTokenNumber) + ", "; + str += e.localTokenIdx.toString() + ", "; + str += e.guidTableIdx.toString(); - str += " /* " + alComment.get(index) + " */"; + str += "}" + " /* " + alComment.get(e) + " */" ; - if (index != al.size() - 1) { - str += ","; - } + if (index != al.size() - 1) { + str += ","; + } Output.add(str); - bodyLineNum++; + bodyLineNum++; } - Output.add("}"); + Output.add("}"); return Output; } @@ -624,33 +834,77 @@ class ExMapTable { 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); + len++; + ExTriplet et = new ExTriplet(guidTableIdx, exTokenNum, localTokenIdx); + + al.add(et); + alComment.put(et, name); return index; } - public int getTableLen () { - return al.size() == 0 ? 1 : al.size(); - } + private int getTableLen () { + return al.size() == 0 ? 1 : al.size(); + } + + // + // To simplify the algorithm for GetNextToken and GetNextTokenSpace in + // PCD PEIM/Driver, we need to sort the ExMapTable according to the + // following order: + // 1) ExGuid + // 2) ExTokenNumber + // + class ExTripletComp implements Comparator { + public int compare (ExTriplet a, ExTriplet b) { + if (a.guidTableIdx == b.guidTableIdx ) { + // + // exTokenNumber is long, we can't use simple substraction. + // + if (a.exTokenNumber > b.exTokenNumber) { + return 1; + } else if (a.exTokenNumber == b.exTokenNumber) { + return 0; + } else { + return -1; + } + } + + return a.guidTableIdx - b.guidTableIdx; + } + } + private void sortTable () { + java.util.Comparator comparator = new ExTripletComp(); + java.util.Collections.sort(al, comparator); + } } +/** + PcdDatabase + + This class is used to generate C code for Autogen.h and Autogen.c of + a PCD service DXE driver and PCD service PEIM. +**/ 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];\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];\r\n"; - public final static String SkuIdTableDeclaration = "UINT8 SkuIdTable[%s_SKUID_TABLE_SIZE];\r\n"; + private final static int SkuHeadAlignmentSize = 4; + private final String newLine = "\r\n"; + private final String commaNewLine = ",\r\n"; + private final String tab = "\t"; + 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 = "SIZE_INFO SizeTable[%s_SIZE_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 %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 SizeTableSizeMacro = "#define %s_SIZE_TABLE_SIZE %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"; @@ -661,574 +915,837 @@ class PcdDatabase { 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 alTokens; - private String phase; - private int assignedTokenNumber; - - private String hString; - private String cString; - - - class AlignmentSizeComp implements Comparator { - public int compare (Token a, Token b) { - return getAlignmentSize(b) - - getAlignmentSize(a); - } - } - - public PcdDatabase (ArrayList 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 alTokens, List initTokens, List 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.hiiEnabled) { - return 2; - } - - if (token.vpdEnabled) { - return 4; - } - - if (token.isStringType()) { - 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 () { - - final String newLine = "\r\n"; - final String instNewLine = "\\\r\n"; - final String declNewLine = ";\r\n"; - final String tab = "\t"; - final String commaInstNewLine = "\t,\\\r\n"; - final String commaNewLine = ", \r\n"; - - int i; - ArrayList decla; - ArrayList inst; - - String macroStr = ""; - String initDeclStr = ""; - String initInstStr = ""; - String uninitDeclStr = ""; - - List initTokens = new ArrayList (); - List uninitTokens = new ArrayList (); - - HashMap > initCode = new HashMap> (); - HashMap > uninitCode = new HashMap> (); - - getTwoGroupsOfTokens (alTokens, initTokens, uninitTokens); - - // - // Generate Structure Declaration for PcdTokens without Default Value - // PEI_PCD_DATABASE_INIT - // - java.util.Comparator comparator = new AlignmentSizeComp(); - List list = initTokens; - java.util.Collections.sort(list, 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; - /* - inst = stringTable.getInstantiation(); - for (i = 0; i < inst.size(); i++ ) { - initInstStr += tab + inst.get(i) + 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; - - } - - private String genInstantiationStr (ArrayList 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> processTokens (List alToken) { - - ArrayList[] output = new ArrayList[4]; - HashMap > map = new HashMap>(); - - ArrayList decl = new ArrayList(); - ArrayList declForSkuEnableType = new ArrayList(); - ArrayList inst = new ArrayList(); - ArrayList instForSkuEnableType = new ArrayList(); - - for (int index = 0; index < alToken.size(); index++) { - Token token = alToken.get(index); - - if (token.skuEnabled) { - // - // 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.hiiEnabled) { - decl.add(getVariableEnableTypeDeclaration(token)); - inst.add(getVariableEnableInstantiation(token)); - } else if (token.vpdEnabled) { - decl.add(getVpdEnableTypeDeclaration(token)); - inst.add(getVpdEnableTypeInstantiation(token)); - } else if (token.isStringType()) { - 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.assignedtokenNumber = 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.maxSkuCount); - } - - return String.format(typeStr, token.getPrimaryKeyString(), "SkuDataTable", token.maxSkuCount); - - } - - 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.maxSkuCount); - } else { - str = "{ "; - for (int idx = 0; idx < token.maxSkuCount; idx++) { - str += token.skuData.get(idx).toString(); - if (idx != token.maxSkuCount - 1) { - str += ", "; - } - } - str += "}"; - - return str; - } - - } - - private String getDataTypeInstantiation (Token token) { - - String typeStr = ""; - - if (token.datumType == Token.DATUM_TYPE.POINTER) { - return String.format("%s /* %s */", token.datum.toString(), token.getPrimaryKeyString()); - } else { - return String.format("%s /* %s */", token.datum.toString(), 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("{ %d } /* %s */", token.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) { - return String.format("{ %d, %d, %d } /* %s */", guidTable.add(token.variableGuid, token.getPrimaryKeyString()), - stringTable.add(token.variableName, token), - token.variableOffset, - token.getPrimaryKeyString()); - } - - public int getTotalTokenNumber () { - return sizeTable.getTableLen(); - } + public final static String offsetOfSkuHeadStrTemplate = "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)"; + public final static String offsetOfVariableEnabledDefault = "offsetof(%s_PCD_DATABASE, %s.%s_VariableDefault_%d)"; + public final static String offsetOfStrTemplate = "offsetof(%s_PCD_DATABASE, %s.%s)"; + + private final static String skuDataTableTemplate = "SkuDataTable"; + + + private StringTable stringTable; + private GuidTable guidTable; + private LocalTokenNumberTable localTokenNumberTable; + private SkuIdTable skuIdTable; + private SizeTable sizeTable; + private ExMapTable exMapTable; + + private ArrayList alTokens; + private String phase; + private int assignedTokenNumber; + + // + // Use two class global variable to store + // temperary + // + private String privateGlobalName; + private String privateGlobalCCode; + // + // 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 = 2; + + private String hString; + private String cString; - public static String getPcdDatabaseCommonDefinitions () - throws EntityException { + /** + Constructor for PcdDatabase class. + +

We have two PCD dynamic(ex) database for the Framework implementation. One + for PEI phase and the other for DXE phase.

+ + @param alTokens A ArrayList of Dynamic(EX) PCD entry. + @param exePhase The phase to generate PCD database for: valid input + is "PEI" or "DXE". + @param startLen The starting Local Token Number for the PCD database. For + PEI phase, the starting Local Token Number starts from 0. + For DXE phase, the starting Local Token Number starts + from the total number of PCD entry of PEI phase. + @return void + **/ + public PcdDatabase (ArrayList 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); + + // + // Local token number 0 is reserved for INVALID_TOKEN_NUMBER. + // So we will increment 1 for the startLen passed from the + // constructor. + // + assignedTokenNumber = startLen + 1; + this.alTokens = alTokens; + } - String retStr = ""; - try { - File file = new File(GlobalData.getWorkspacePath() + File.separator + - "Tools" + File.separator + - "Conf" + File.separator + - "Pcd" + File.separator + - "PcdDatabaseCommonDefinitions.sample"); - System.out.println(GlobalData.getWorkspacePath()); - FileReader reader = new FileReader(file); - BufferedReader in = new BufferedReader(reader); - String str; - while ((str = in.readLine()) != null) { - retStr = retStr +"\r\n" + str; + private void getNonExAndExTokens (ArrayList alTokens, List nexTokens, List exTokens) { + for (int i = 0; i < alTokens.size(); i++) { + Token t = (Token)alTokens.get(i); + if (t.isDynamicEx()) { + exTokens.add(t); + } else { + nexTokens.add(t); } - } catch (Exception ex) { - throw new EntityException("Fatal error when generating PcdDatabase Common Definitions"); } - return retStr; + return; } - 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; - } + private int getDataTypeAlignmentSize (Token token) { + 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; + default: + return 1; + } + } + + private int getHiiPtrTypeAlignmentSize(Token token) { + switch (token.datumType) { + case UINT8: + return 1; + case UINT16: + return 2; + case UINT32: + return 4; + case UINT64: + return 8; + case POINTER: + if (token.isHiiEnable()) { + if (token.isHiiDefaultValueUnicodeStringType()) { + return 2; + } + } + return 1; + case BOOLEAN: + return 1; + default: + return 1; + } + } + + 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; + } -/** 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; + if (token.isUnicodeStringType()) { + return 2; + } + + return getDataTypeAlignmentSize(token); + } - /// Workspacepath hold the workspace information. - private String workspacePath; + public String getCString () { + return cString; + } - /// FPD file is the root file. - private String fpdFilePath; + public String getHString () { + return hString; + } + + private void genCodeWorker(Token t, + ArrayList declaList, + HashMap instTable, String phase) + throws EntityException { - /// Message level for CollectPCDAction. - private int originalMessageLevel; + CStructTypeDeclaration decl; - /** - Set WorkspacePath parameter for this action class. + // + // Insert SKU_HEAD if isSkuEnable is true + // + if (t.isSkuEnable()) { + int tableIdx; + tableIdx = skuIdTable.add(t); + decl = new CStructTypeDeclaration(t.getPrimaryKeyString(), + SkuHeadAlignmentSize, getSkuEnabledTypeDeclaration(t), true); + declaList.add(decl); + instTable.put(t.getPrimaryKeyString(), + getSkuEnabledTypeInstantiaion(t, tableIdx)); + } - @param workspacePath parameter for this action - **/ - public void setWorkspacePath(String workspacePath) { - this.workspacePath = workspacePath; - } + // + // Insert PCD_ENTRY declaration and instantiation + // + getCDeclarationString(t); - /** - Set action message level for CollectPcdAction tool. + decl = new CStructTypeDeclaration(privateGlobalName, + getAlignmentSize(t), privateGlobalCCode, t.hasDefaultValue()); + declaList.add(decl); - The message should be restored when this action exit. + if (t.hasDefaultValue()) { + instTable.put(privateGlobalName, + getTypeInstantiation(t, declaList, instTable, phase) + ); + } - @param actionMessageLevel parameter for this action - **/ - public void setActionMessageLevel(int actionMessageLevel) { - originalMessageLevel = ActionMessage.messageLevel; - ActionMessage.messageLevel = actionMessageLevel; } - /** - Set FPDFileName parameter for this action class. + private void ProcessTokens (List tokens, + ArrayList cStructDeclList, + HashMap cStructInstTable, + String phase + ) + throws EntityException { + + for (int idx = 0; idx < tokens.size(); idx++) { + Token t = tokens.get(idx); + + genCodeWorker (t, cStructDeclList, cStructInstTable, phase); + + sizeTable.add(t); + localTokenNumberTable.add(t); + t.tokenNumber = assignedTokenNumber++; + + // + // Add a mapping if this dynamic PCD entry is a EX type + // + if (t.isDynamicEx()) { + exMapTable.add((int)t.tokenNumber, + t.dynamicExTokenNumber, + guidTable.add(translateSchemaStringToUUID(t.tokenSpaceName), t.getPrimaryKeyString()), + t.getPrimaryKeyString() + ); + } + } - @param fpdFilePath fpd file path - **/ - public void setFPDFilePath(String fpdFilePath) { - this.fpdFilePath = fpdFilePath; } + + public void genCode () throws EntityException { + + ArrayList cStructDeclList = new ArrayList(); + HashMap cStructInstTable = new HashMap(); + + List nexTokens = new ArrayList (); + List exTokens = new ArrayList (); - /** - 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. + getNonExAndExTokens (alTokens, nexTokens, exTokens); + + // + // We have to process Non-Ex type PCD entry first. The reason is + // that our optimization assumes that the Token Number of Non-Ex + // PCD entry start from 1 (for PEI phase) and grows continously upwards. + // + // EX type token number starts from the last Non-EX PCD entry and + // grows continously upwards. + // + ProcessTokens (nexTokens, cStructDeclList, cStructInstTable, phase); + ProcessTokens (exTokens, cStructDeclList, cStructInstTable, phase); + + stringTable.genCode(cStructDeclList, cStructInstTable); + skuIdTable.genCode(cStructDeclList, cStructInstTable, phase); + exMapTable.genCode(cStructDeclList, cStructInstTable, phase); + localTokenNumberTable.genCode(cStructDeclList, cStructInstTable, phase); + sizeTable.genCode(cStructDeclList, cStructInstTable, phase); + guidTable.genCode(cStructDeclList, cStructInstTable, phase); + + hString = genCMacroCode (); + + HashMap result; + + result = genCStructCode(cStructDeclList, + cStructInstTable, + phase + ); + + hString += result.get("initDeclStr"); + hString += result.get("uninitDeclStr"); + + hString += String.format("#define PCD_%s_SERVICE_DRIVER_VERSION %d", phase, version); + + cString = newLine + newLine + result.get("initInstStr"); + + } + + private String genCMacroCode () { + String macroStr = ""; + + // + // Generate size info Macro for all Tables + // + macroStr += guidTable.getSizeMacro(); + macroStr += stringTable.getSizeMacro(); + macroStr += skuIdTable.getSizeMacro(); + macroStr += localTokenNumberTable.getSizeMacro(); + macroStr += exMapTable.getSizeMacro(); + macroStr += sizeTable.getSizeMacro(); + + // + // Generate existance info Macro for all Tables + // + macroStr += guidTable.getExistanceMacro(); + macroStr += stringTable.getExistanceMacro(); + macroStr += skuIdTable.getExistanceMacro(); + macroStr += localTokenNumberTable.getExistanceMacro(); + macroStr += exMapTable.getExistanceMacro(); + + macroStr += newLine; + + return macroStr; + } + + private HashMap genCStructCode( + ArrayList declaList, + HashMap instTable, + String phase + ) { + + int i; + HashMap result = new HashMap(); + HashMap > alignmentInitDecl = new HashMap>(); + HashMap > alignmentUninitDecl = new HashMap>(); + HashMap > alignmentInitInst = new HashMap>(); + + // + // Initialize the storage for each alignment + // + for (i = 8; i > 0; i>>=1) { + alignmentInitDecl.put(new Integer(i), new ArrayList()); + alignmentInitInst.put(new Integer(i), new ArrayList()); + alignmentUninitDecl.put(new Integer(i), new ArrayList()); + } + + String initDeclStr = "typedef struct {" + newLine; + String initInstStr = String.format("%s_PCD_DATABASE_INIT g%sPcdDbInit = { ", phase.toUpperCase(), phase.toUpperCase()) + newLine; + String uninitDeclStr = "typedef struct {" + newLine; + + // + // Sort all C declaration and instantiation base on Alignment Size + // + for (Object d : declaList) { + CStructTypeDeclaration decl = (CStructTypeDeclaration) d; + + if (decl.initTable) { + alignmentInitDecl.get(new Integer(decl.alignmentSize)).add(decl.cCode); + alignmentInitInst.get(new Integer(decl.alignmentSize)).add(instTable.get(decl.key)); + } else { + alignmentUninitDecl.get(new Integer(decl.alignmentSize)).add(decl.cCode); + } + } + + // + // Generate code for every alignment size + // + boolean uinitDatabaseEmpty = true; + for (int align = 8; align > 0; align >>= 1) { + ArrayList declaListBasedOnAlignment = alignmentInitDecl.get(new Integer(align)); + ArrayList instListBasedOnAlignment = alignmentInitInst.get(new Integer(align)); + for (i = 0; i < declaListBasedOnAlignment.size(); i++) { + initDeclStr += tab + declaListBasedOnAlignment.get(i); + initInstStr += tab + instListBasedOnAlignment.get(i); + + // + // We made a assumption that both PEI_PCD_DATABASE and DXE_PCD_DATABASE + // has a least one data memember with alignment size of 1. So we can + // remove the last "," in the C structure instantiation string. Luckily, + // this is true as both data structure has SKUID_TABLE anyway. + // + if ((align == 1) && (i == declaListBasedOnAlignment.size() - 1)) { + initInstStr += newLine; + } else { + initInstStr += commaNewLine; + } + } + + declaListBasedOnAlignment = alignmentUninitDecl.get(new Integer(align)); + + if (declaListBasedOnAlignment.size() != 0) { + uinitDatabaseEmpty = false; + } + + for (Object d : declaListBasedOnAlignment) { + String s = (String)d; + uninitDeclStr += tab + s; + } + } + + if (uinitDatabaseEmpty) { + uninitDeclStr += tab + String.format("%-20sdummy; /* PCD_DATABASE_UNINIT is emptry */\r\n", "UINT8"); + } + + initDeclStr += String.format("} %s_PCD_DATABASE_INIT;", phase) + newLine + newLine; + initInstStr += "};" + newLine; + uninitDeclStr += String.format("} %s_PCD_DATABASE_UNINIT;", phase) + newLine + newLine; + + result.put("initDeclStr", initDeclStr); + result.put("initInstStr", initInstStr); + result.put("uninitDeclStr", uninitDeclStr); + + return result; + } + + public static String genInstantiationStr (ArrayList alStr) { + String str = ""; + for (int i = 0; i< alStr.size(); i++) { + if (i != 0) { + str += "\t"; + } + str += alStr.get(i); + if (i != alStr.size() - 1) { + str += "\r\n"; + } + } + + return str; + } + + private String getSkuEnabledTypeDeclaration (Token token) { + return String.format("%-20s%s;\r\n", "SKU_HEAD", 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 } /* SKU_ENABLED: %s */", offsetof, SkuTableIdx, token.getPrimaryKeyString()); + } + + private String getDataTypeInstantiationForVariableDefault (Token token, String cName, int skuId) { + return String.format("%s /* %s */", token.skuData.get(skuId).value.hiiDefaultValue, cName); + } + + private String getCType (Token t) + throws EntityException { + + if (t.isHiiEnable()) { + return "VARIABLE_HEAD"; + } + + if (t.isVpdEnable()) { + return "VPD_HEAD"; + } + + if (t.isUnicodeStringType()) { + return "STRING_HEAD"; + } + + switch (t.datumType) { + case UINT64: + return "UINT64"; + case UINT32: + return "UINT32"; + case UINT16: + return "UINT16"; + case UINT8: + return "UINT8"; + case BOOLEAN: + return "BOOLEAN"; + case POINTER: + return "UINT8"; + default: + throw new EntityException("Unknown type in getDataTypeCDeclaration"); + } + } + + // + // privateGlobalName and privateGlobalCCode is used to pass output to caller of getCDeclarationString + // + private void getCDeclarationString(Token t) + throws EntityException { + + if (t.isSkuEnable()) { + privateGlobalName = String.format("%s_%s", t.getPrimaryKeyString(), skuDataTableTemplate); + } else { + privateGlobalName = t.getPrimaryKeyString(); + } + + String type = getCType(t); + if ((t.datumType == Token.DATUM_TYPE.POINTER) && (!t.isHiiEnable()) && (!t.isUnicodeStringType())) { + int bufferSize; + if (t.isASCIIStringType()) { + // + // Build tool will add a NULL string at the end of the ASCII string + // + bufferSize = t.datumSize + 1; + } else { + bufferSize = t.datumSize; + } + privateGlobalCCode = String.format("%-20s%s[%d][%d];\r\n", type, privateGlobalName, t.getSkuIdCount(), bufferSize); + } else { + privateGlobalCCode = String.format("%-20s%s[%d];\r\n", type, privateGlobalName, t.getSkuIdCount()); + } + } + + private String getDataTypeDeclarationForVariableDefault (Token token, String cName, int skuId) + throws EntityException { + + 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) { + int size; + if (token.isHiiDefaultValueUnicodeStringType()) { + typeStr = "UINT16"; + // + // Include the NULL charactor + // + size = token.datumSize / 2 + 1; + } else { + typeStr = "UINT8"; + if (token.isHiiDefaultValueASCIIStringType()) { + // + // Include the NULL charactor + // + size = token.datumSize + 1; + } else { + size = token.datumSize; + } + } + return String.format("%-20s%s[%d];\r\n", typeStr, cName, size); + } else { + throw new EntityException("Unknown DATUM_TYPE type in when generating code for VARIABLE_ENABLED PCD entry"); + } + + return String.format("%-20s%s;\r\n", typeStr, cName); + } + + private String getTypeInstantiation (Token t, ArrayList declaList, HashMap instTable, String phase) throws EntityException { + + int i; + + String s; + s = String.format("/* %s */", t.getPrimaryKeyString()) + newLine; + s += tab + "{" + newLine; + + for (i = 0; i < t.skuData.size(); i++) { + if (t.isUnicodeStringType()) { + s += tab + tab + String.format("{ %d }", stringTable.add(t.skuData.get(i).value.value, t)); + } else if (t.isHiiEnable()) { + /* VPD_HEAD definition + typedef struct { + UINT16 GuidTableIndex; // Offset in Guid Table in units of GUID. + UINT16 StringIndex; // Offset in String Table in units of UINT16. + UINT16 Offset; // Offset in Variable + UINT16 DefaultValueOffset; // Offset of the Default Value + } VARIABLE_HEAD ; + */ + String variableDefaultName = String.format("%s_VariableDefault_%d", t.getPrimaryKeyString(), i); + + s += tab + tab + String.format("{ %d, %d, %s, %s }", guidTable.add(t.skuData.get(i).value.variableGuid, t.getPrimaryKeyString()), + stringTable.add(t.skuData.get(i).value.getStringOfVariableName(), t), + t.skuData.get(i).value.variableOffset, + String.format("offsetof(%s_PCD_DATABASE, Init.%s)", phase, variableDefaultName) + ); + // + // We need to support the default value, so we add the declaration and + // the instantiation for the default value. + // + CStructTypeDeclaration decl = new CStructTypeDeclaration (variableDefaultName, + getHiiPtrTypeAlignmentSize(t), + getDataTypeDeclarationForVariableDefault(t, variableDefaultName, i), + true + ); + declaList.add(decl); + instTable.put(variableDefaultName, getDataTypeInstantiationForVariableDefault (t, variableDefaultName, i)); + } else if (t.isVpdEnable()) { + /* typedef struct { + UINT32 Offset; + } VPD_HEAD; + */ + s += tab + tab + String.format("{ %s }", t.skuData.get(i).value.vpdOffset); + } else { + if (t.isByteStreamType()) { + // + // Byte stream type input has their own "{" "}", so we won't help to insert. + // + s += tab + tab + String.format(" %s ", t.skuData.get(i).value.value); + } else { + s += tab + tab + String.format("{ %s }", t.skuData.get(i).value.value); + } + } + + if (i != t.skuData.size() - 1) { + s += commaNewLine; + } else { + s += newLine; + } + + } + + s += tab + "}"; + + return s; + } + + 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; + } + + /** + 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); + } +} + +/** Module Info class is the data structure to hold information got from GlobalData. +*/ +class ModuleInfo { + /// + /// Module's ID for a + /// + private FpdModuleIdentification moduleId; + /// + /// xmlobject in FPD file for a + /// + private PcdBuildDefinitionDocument.PcdBuildDefinition pcdBuildDef; + + public ModuleInfo (FpdModuleIdentification moduleId, XmlObject pcdDef) { + this.moduleId = moduleId; + this.pcdBuildDef = ((PcdBuildDefinitionDocument)pcdDef).getPcdBuildDefinition(); + } + + public FpdModuleIdentification getModuleId (){ + return moduleId; + } + + public PcdBuildDefinitionDocument.PcdBuildDefinition getPcdBuildDef(){ + return pcdBuildDef; + } +} + +/** 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 PlatformSurfaceAreaDocument fpdDocInstance; + /// + /// xmlObject name + /// + private static String xmlObjectName = "PcdBuildDefinition"; + + /** + 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 @@ -1245,567 +1762,1320 @@ public class CollectPCDAction { ActionMessage.messageLevel = originalMessageLevel; } - /** - Core execution function for this action class. - - This function work flows will be: - 1) Get all token's platform information from FPD, and create token object into memory database. - 2) Get all token's module information from MSA, and create usage instance for every module's PCD entry. - 3) Get all token's inherited information from MSA's library, and create usage instance - for module who consume this library and create usage instance for library for building. - 4) Collect token's package information from SPD, update these information for token in memory - database. - 5) Generate 3 strings for a) All modules using Dynamic(Ex) PCD entry. (Token Number) - b) PEI PCD Database (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 { - FrameworkPlatformDescriptionDocument fpdDoc = null; - Object[][] modulePCDArray = null; - Map docMap = null; - ModuleSADocument.ModuleSA[] moduleSAs = null; - UsageInstance usageInstance = null; - String packageName = null; - String packageFullPath = null; - int index = 0; - int libraryIndex = 0; - int pcdArrayIndex = 0; - List listLibraryInstance = null; - String componentTypeStr = null; + /** + 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. + + **/ + public 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(); + + // + // 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 alPei = new ArrayList (); + ArrayList alDxe = new ArrayList (); + + dbManager.getTwoPhaseDynamicRecordArray(alPei, alDxe); + PcdDatabase pcdPeiDatabase = new PcdDatabase (alPei, "PEI", 0); + pcdPeiDatabase.genCode(); + MemoryDatabaseManager.PcdPeimHString = PcdCommonHeaderString + pcdPeiDatabase.getHString() + + PcdDatabase.getPcdPeiDatabaseDefinitions(); + MemoryDatabaseManager.PcdPeimCString = pcdPeiDatabase.getCString(); + + PcdDatabase pcdDxeDatabase = new PcdDatabase(alDxe, "DXE", alPei.size()); + pcdDxeDatabase.genCode(); + MemoryDatabaseManager.PcdDxeHString = MemoryDatabaseManager.PcdPeimHString + pcdDxeDatabase.getHString() + + PcdDatabase.getPcdDxeDatabaseDefinitions(); + MemoryDatabaseManager.PcdDxeCString = pcdDxeDatabase.getCString(); + } + + /** + Get component array from FPD. + + This function maybe provided by some Global class. + + @return List the component array. + + */ + private List getComponentsFromFPD() + throws EntityException { + List allModules = new ArrayList(); + FrameworkModulesDocument.FrameworkModules fModules = null; + ModuleSADocument.ModuleSA[] modules = null; + Map pcdBuildDefinitions = null; + + pcdBuildDefinitions = GlobalData.getFpdPcdBuildDefinitions(); + if (pcdBuildDefinitions == null) { + return null; + } + + // + // Loop map to retrieve all PCD build definition and Module id + // + Iterator item = pcdBuildDefinitions.keySet().iterator(); + while (item.hasNext()){ + FpdModuleIdentification id = (FpdModuleIdentification) item.next(); + allModules.add(new ModuleInfo(id, pcdBuildDefinitions.get(id))); + } + + 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 pcdBuildDataArray = new ArrayList(); + PcdBuildDefinition.PcdData pcdBuildData = null; + Token token = null; + List 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; + long tokenNumber = 0; + String moduleName = null; + String datum = null; + int maxDatumSize = 0; + String[] tokenSpaceStrRet = null; + + // + // ---------------------------------------------- + // 1), Get all 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 in FPD file!"); + } + + // + // ------------------------------------------------------------------- + // 2), Loop all modules to process for each module. + // ------------------------------------------------------------------- + // + for (index = 0; index < modules.size(); index ++) { + // + // It is legal for a module does not contains ANY pcd build definitions. + // + if (modules.get(index).getPcdBuildDef() == null) { + continue; + } + + pcdBuildDataArray = modules.get(index).getPcdBuildDef().getPcdDataList(); + + moduleName = modules.get(index).getModuleId().getModule().getName(); + + // + // ---------------------------------------------------------------------- + // 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); + + try { + tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(pcdBuildData.getTokenSpaceGuidCName()); + } catch ( Exception e ) { + throw new EntityException ("Faile get Guid for token " + pcdBuildData.getCName() + ":" + e.getMessage()); + } + + if (tokenSpaceStrRet == null) { + throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData.getCName()); + } + + primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(), tokenSpaceStrRet[1]); + pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString()); + datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString()); + tokenNumber = Long.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); + } + + // + // ------------------------------------------------------------------------------------------- + // 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 in sperated every in different , + // But if you write, the must be same as the value in . + // + 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 is "+ + "not equal to the datum in , it is "+ + "illega! You could no set in 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 %d defined in !", + 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. + // + try { + tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(pcdBuildData.getTokenSpaceGuidCName()); + } catch (Exception e) { + throw new EntityException("Fail to get token space guid for token " + token.cName); + } + + if (tokenSpaceStrRet == null) { + throw new EntityException("Fail to get token space guid for token " + token.cName); + } + + token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet[1]); + + 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 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, + modules.get(index).getModuleId().getModule(), + pcdType, + modules.get(index).getModuleId().getArch(), + datum, + maxDatumSize); + token.addUsageInstance(usageInstance); + } + } + + // + // ------------------------------------------------ + // 3), Add unreference dynamic_Ex pcd token into Pcd database. + // ------------------------------------------------ + // + List tokenArray = getUnreferencedDynamicPcd(); + if (tokenArray != null) { + for (index = 0; index < tokenArray.size(); index ++) { + dbManager.addTokenToDatabase(tokenArray.get(index).getPrimaryKeyString(), + tokenArray.get(index)); + } + } + } + + private List getUnreferencedDynamicPcd () throws EntityException { + List tokenArray = new ArrayList(); + Token token = null; + DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null; + List dynamicPcdBuildDataArray = null; + DynamicPcdBuildDefinitions.PcdBuildData pcdBuildData = null; + List skuInfoList = null; + Token.PCD_TYPE pcdType; + SkuInstance skuInstance = null; + String primaryKey = null; + boolean hasSkuId0 = false; + int index, offset, index2; + String temp; + String exceptionString; + String hiiDefaultValue; + String tokenSpaceStrRet[]; + String variableGuidString[]; // - // Collect all PCD information defined in FPD file. - // Evenry token defind in FPD will be created as an token into - // memory database. - // - fpdDoc = createTokenInDBFromFPD(); + // Open fpd document to get Section. + // BUGBUG: the function should be move GlobalData in furture. + // + if (fpdDocInstance == null) { + try { + fpdDocInstance = (PlatformSurfaceAreaDocument)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()); + } + } - // - // Searching MSA and SPD document. - // The information of MSA will be used to create usage instance into database. - // The information of SPD will be used to update the token information in database. - // + dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions(); + if (dynamicPcdBuildDefinitions == null) { + return null; + } + + dynamicPcdBuildDataArray = dynamicPcdBuildDefinitions.getPcdBuildDataList(); + for (index2 = 0; index2 < dynamicPcdBuildDataArray.size(); index2 ++) { + pcdBuildData = dynamicPcdBuildDataArray.get(index2); + try { + tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(pcdBuildData.getTokenSpaceGuidCName()); + } catch ( Exception e ) { + throw new EntityException ("Faile get Guid for token " + pcdBuildData.getCName() + ":" + e.getMessage()); + } + + if (tokenSpaceStrRet == null) { + throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData.getCName()); + } + + primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(), + tokenSpaceStrRet[1]); + + if (dbManager.isTokenInDatabase(primaryKey)) { + continue; + } - HashMap map = new HashMap(); - map.put("FrameworkPlatformDescription", fpdDoc); - SurfaceAreaQuery.setDoc(map); + pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString()); + if (pcdType != Token.PCD_TYPE.DYNAMIC_EX) { + throw new EntityException (String.format("[FPD file error] It not allowed for DYNAMIC PCD %s who is no used by any module", + pcdBuildData.getCName())); + } - moduleSAs = SurfaceAreaQuery.getFpdModules(); - for(index = 0; index < moduleSAs.length; index ++) { // - // Get module document and use SurfaceAreaQuery to get PCD information + // Create new token for unreference dynamic PCD token + // + token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet[1]); + token.datumSize = pcdBuildData.getMaxDatumSize(); + + + token.datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString()); + token.tokenNumber = Long.decode(pcdBuildData.getToken().toString()); + token.dynamicExTokenNumber = token.tokenNumber; + token.isDynamicPCD = true; + token.updateSupportPcdType(pcdType); + + exceptionString = verifyDatum(token.cName, + null, + null, + token.datumType, + token.datumSize); + if (exceptionString != null) { + throw new EntityException(exceptionString); + } + + skuInfoList = pcdBuildData.getSkuInfoList(); + // - docMap = GlobalData.getDoc(moduleSAs[index].getModuleName()); - SurfaceAreaQuery.setDoc(docMap); - modulePCDArray = SurfaceAreaQuery.getModulePCDTokenArray(); - componentTypeStr = SurfaceAreaQuery.getComponentType(); - packageName = - GlobalData.getPackageNameForModule(moduleSAs[index].getModuleName()); - packageFullPath = this.workspacePath + File.separator + - GlobalData.getPackagePath(packageName) + - packageName + ".spd"; - - if(modulePCDArray != null) { + // Loop all sku data + // + for (index = 0; index < skuInfoList.size(); index ++) { + skuInstance = new SkuInstance(); // - // If current MSA contains information, then create usage - // instance for PCD information from MSA + // 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; + } // - for(pcdArrayIndex = 0; pcdArrayIndex < modulePCDArray.length; - pcdArrayIndex ++) { - usageInstance = - createUsageInstanceFromMSA(moduleSAs[index].getModuleName(), - modulePCDArray[pcdArrayIndex]); - - if(usageInstance == null) { - continue; + // 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); + + 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 section in FPD "+ + "file, who use HII, but there is no 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 section in FPD "+ + "file, who use HII, but there is no 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 section in FPD "+ + "file, who use HII, but there is no 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 remaining PCD information from the package which this module belongs to - // - updateTokenBySPD(usageInstance, packageFullPath); + // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file. + // + variableGuidString = GlobalData.getGuidInfoFromCname(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())); + } + String variableStr = skuInfoList.get(index).getVariableName(); + Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}"); + Matcher matcher = pattern.matcher(variableStr); + List varNameList = new ArrayList(); + while (matcher.find()){ + String str = variableStr.substring(matcher.start(),matcher.end()); + varNameList.add(str); + } + + skuInstance.value.setHiiData(varNameList, + translateSchemaStringToUUID(variableGuidString[1]), + skuInfoList.get(index).getVariableOffset(), + skuInfoList.get(index).getHiiDefaultValue().toString()); + token.skuData.add(skuInstance); + continue; } - } - // - // Get inherit PCD information which inherit from library instance of this module. - // - listLibraryInstance = - SurfaceAreaQuery.getLibraryInstance(moduleSAs[index].getArch().toString(), - CommonDefinition.AlwaysConsumed); - if(listLibraryInstance != null) { - for(libraryIndex = 0; libraryIndex < listLibraryInstance.size(); - libraryIndex ++) { - inheritPCDFromLibraryInstance(listLibraryInstance.get(libraryIndex), - moduleSAs[index].getModuleName(), - packageName, - componentTypeStr); + 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 , there are "+ + "no sku id = 0 data, which is required for every dynamic PCD", + token.cName); + throw new EntityException(exceptionString); } + + tokenArray.add(token); } - - // - // Call Private function genPcdDatabaseSourceCode (void); ComponentTypeBsDriver - // 1) Generate for PEI, DXE PCD DATABASE's definition and initialization. - // - genPcdDatabaseSourceCode (); - + + return tokenArray; } - /** - This function generates source code for PCD Database. - - @param void - @throws EntityException If the token does *not* exist in memory database. + /** + 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 "; + } else { + moduleName = "module " + moduleName; + } - **/ + if (maxDatumSize == 0) { + exceptionString = String.format("[FPD file error] You maybe miss for PCD %s in %s", + cName, + moduleName); + return exceptionString; + } - private void genPcdDatabaseSourceCode () - throws EntityException { - String PcdCommonHeaderString = PcdDatabase.getPcdDatabaseCommonDefinitions (); + 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; + } - ArrayList alPei = new ArrayList (); - ArrayList alDxe = new ArrayList (); + 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; + } - 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(); - } - - /** - This function will collect inherit PCD information from library for a module. - - This function will create two usage instance for inherited PCD token, one is - for module and another is for library. - For module, if it inherited a PCD token from library, this PCD token's value - should be instanced in module level, and belongs to module. - For library, it also need a usage instance for build. - - @param libraryName The name of library instance. - @param moduleName The name of module. - @param packageName The name of package while module belongs to. - @param parentcomponentType The component type of module. - - @throws EntityException If the token does *not* exist in memory database. - - **/ - private void inheritPCDFromLibraryInstance(String libraryName, - String moduleName, - String packageName, - String parentcomponentType) - throws EntityException { - Map docMap = null; - String primaryKeyString = null; - Object[][] libPcdDataArray = null; - UUID nullUUID = new UUID(0,0); - UUID platformUUID = nullUUID; - UUID tokenSpaceGuid = null; - int tokenIndex = 0; - Token token = null; - Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; - UsageInstance usageInstance = null; - String packageFullPath = null; + 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; + } - // - // Query PCD information from library's document. - // - docMap = GlobalData.getDoc(libraryName); - SurfaceAreaQuery.setDoc(docMap); - libPcdDataArray = SurfaceAreaQuery.getModulePCDTokenArray(); + 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(libPcdDataArray == null) { - return; - } + 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; + } - for(tokenIndex = 0; tokenIndex < libPcdDataArray.length; tokenIndex ++) { - tokenSpaceGuid =((UUID)libPcdDataArray[tokenIndex][2] == null) ? - nullUUID :(UUID)libPcdDataArray[tokenIndex][2]; + 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; + } - // - // Get token from memory database. The token must be created from FPD already. - // - primaryKeyString = Token.getPrimaryKeyString((String)libPcdDataArray[tokenIndex][0], - tokenSpaceGuid, - platformUUID - ); + 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; + } - if(dbManager.isTokenInDatabase(primaryKeyString)) { - token = dbManager.getTokenByKey(primaryKeyString); - } else { - throw new EntityException("The PCD token " + primaryKeyString + - " defined in module " + moduleName + - " does not exist in FPD file!"); - } + } + break; + case POINTER: + if (datum == null) { + break; + } + char ch = datum.charAt(0); + int start, end; + String strValue; // - // Create usage instance for module. - // - pcdType = Token.getpcdTypeFromString((String)libPcdDataArray[tokenIndex][1]); - usageInstance = new UsageInstance(token, - Token.PCD_USAGE.ALWAYS_CONSUMED, - pcdType, - CommonDefinition.getComponentType(parentcomponentType), - libPcdDataArray[tokenIndex][3], - null, - (String) libPcdDataArray[tokenIndex][5], - "", - moduleName, - packageName, - true); - if(Token.PCD_USAGE.UNKNOWN == token.isUsageInstanceExist(moduleName)) { - token.addUsageInstance(usageInstance); + // 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; + } - packageFullPath = this.workspacePath + File.separator + - GlobalData.getPackagePath(packageName) + - packageName + ".spd"; - updateTokenBySPD(usageInstance, packageFullPath); - } + 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 : %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 : %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) { + exceptionString = String.format ("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+ + "it is byte array in fact, but '{}' is not valid for NULL datam but"+ + " need use '{0}'", + cName, + moduleName); + return exceptionString; + } + 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; + } + } - // - // We need create second usage instance for inherited case, which - // add library as an usage instance, because when build a module, and - // if module inherited from base library, then build process will build - // library at first. - // - if(Token.PCD_USAGE.UNKNOWN == token.isUsageInstanceExist(libraryName)) { - packageName = GlobalData.getPackageNameForModule(libraryName); - usageInstance = new UsageInstance(token, - Token.PCD_USAGE.ALWAYS_CONSUMED, - pcdType, - CommonDefinition.ComponentTypeLibrary, - libPcdDataArray[tokenIndex][3], - null, - (String)libPcdDataArray[tokenIndex][5], - "", - libraryName, - packageName, - false); - token.addUsageInstance(usageInstance); + 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 : %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; } /** - Create usage instance for PCD token defined in MSA document - - A PCD token maybe used by many modules, and every module is one of usage - instance of this token. For ALWAY_CONSUMED, SOMETIMES_CONSUMED, it is - consumer type usage instance of this token, and for ALWAYS_PRODUCED, - SOMETIMES_PRODUCED, it is produce type usage instance. - - @param moduleName The name of module - @param tokenInfoInMsa The PCD token information array retrieved from MSA. - - @return UsageInstance The usage instance created in memroy database. - - @throws EntityException If token did not exist in database yet. - - **/ - private UsageInstance createUsageInstanceFromMSA(String moduleName, - Object[] tokenInfoInMsa) + Get dynamic information for a dynamic PCD from 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 { - String packageName = null; - UsageInstance usageInstance = null; - UUID tokenSpaceGuid = null; - UUID nullUUID = new UUID(0,0); - String primaryKeyString = null; - UUID platformTokenSpace = nullUUID; - Token token = null; - Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; - Token.PCD_USAGE pcdUsage = Token.PCD_USAGE.UNKNOWN; - - tokenSpaceGuid =((UUID)tokenInfoInMsa[2] == null) ? nullUUID :(UUID)tokenInfoInMsa[2]; - - primaryKeyString = Token.getPrimaryKeyString((String)tokenInfoInMsa[0], - tokenSpaceGuid, - platformTokenSpace); + int index = 0; + String exceptionString = null; + String dynamicPrimaryKey = null; + DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null; + List dynamicPcdBuildDataArray = null; + String[] tokenSpaceStrRet = null; // - // Get token object from memory database firstly. - // - if(dbManager.isTokenInDatabase(primaryKeyString)) { - token = dbManager.getTokenByKey(primaryKeyString); - } else { - throw new EntityException("The PCD token " + primaryKeyString + " defined in module " + - moduleName + " does not exist in FPD file!" ); + // If FPD document is not be opened, open and initialize it. + // BUGBUG: The code should be moved into GlobalData in future. + // + if (fpdDocInstance == null) { + try { + fpdDocInstance = (PlatformSurfaceAreaDocument)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()); + } } - pcdType = Token.getpcdTypeFromString((String)tokenInfoInMsa[1]); - pcdUsage = Token.getUsageFromString((String)tokenInfoInMsa[4]); - - packageName = GlobalData.getPackageNameForModule(moduleName); - - if(Token.PCD_USAGE.UNKNOWN != token.isUsageInstanceExist(moduleName)) { - // - // BUGBUG: It is legal that same base name exist in one FPD file. In furture - // we should use "Guid, Version, Package" and "Arch" to differ a module. - // So currently, warning should be disabled. - // - //ActionMessage.warning(this, - // "In module " + moduleName + " exist more than one PCD token " + token.cName - // ); - return null; + + dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions(); + if (dynamicPcdBuildDefinitions == null) { + exceptionString = String.format("[FPD file error] There are no in FPD file but contains Dynamic type "+ + "PCD entry %s in module %s!", + token.cName, + moduleName); + throw new EntityException(exceptionString); } - // - // BUGBUG: following code could be enabled at current schema. Because - // current schema does not provide usage information. - // - // For FEATRURE_FLAG, FIXED_AT_BUILD, PATCH_IN_MODULE type PCD token, his - // usage is always ALWAYS_CONSUMED - // - //if((pcdType != Token.PCD_TYPE.DYNAMIC) && - // (pcdType != Token.PCD_TYPE.DYNAMIC_EX)) { - pcdUsage = Token.PCD_USAGE.ALWAYS_CONSUMED; - //} - - usageInstance = new UsageInstance(token, - pcdUsage, - pcdType, - CommonDefinition.getComponentType(SurfaceAreaQuery.getComponentType()), - tokenInfoInMsa[3], - null, - (String) tokenInfoInMsa[5], - "", - moduleName, - packageName, - false); + dynamicPcdBuildDataArray = dynamicPcdBuildDefinitions.getPcdBuildDataList(); + for (index = 0; index < dynamicPcdBuildDataArray.size(); index ++) { + //String tokenSpaceGuidString = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName())[1]; + String tokenSpaceGuidString = null; + try { + tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName()); + } catch (Exception e) { + throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray.get(index).getCName()); + } + + if (tokenSpaceStrRet == null) { + throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray.get(index).getCName()); + } - // - // Use default value defined in MSA to update datum of token, - // if datum of token does not defined in FPD file. - // - if((token.datum == null) &&(tokenInfoInMsa[3] != null)) { - token.datum = tokenInfoInMsa[3]; + dynamicPrimaryKey = Token.getPrimaryKeyString(dynamicPcdBuildDataArray.get(index).getCName(), + tokenSpaceStrRet[1]); + if (dynamicPrimaryKey.equalsIgnoreCase(token.getPrimaryKeyString())) { + return dynamicPcdBuildDataArray.get(index); + } } - token.addUsageInstance(usageInstance); - - return usageInstance; + return null; } /** - Create token instance object into memory database, the token information - comes for FPD file. Normally, FPD file will contain all token platform - informations. - - This fucntion should be executed at firsly before others collection work - such as searching token information from MSA, SPD. - - @return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage. - - @throws EntityException Failed to parse FPD xml file. - - **/ - private FrameworkPlatformDescriptionDocument createTokenInDBFromFPD() + Update dynamic information for PCD entry. + + Dynamic information is retrieved from in + FPD file. + + @param moduleName The name of the module who use this PCD + @param token The token instance + @param datum The in module's PCD information + @param maxDatumSize The in module's PCD information + + @return Token + */ + private Token updateDynamicInformation(String moduleName, + Token token, + String datum, + int maxDatumSize) throws EntityException { - XmlObject doc = null; - FrameworkPlatformDescriptionDocument fpdDoc = null; - int index = 0; - List pcdBuildDataArray = new ArrayList(); - PcdBuildData pcdBuildData = null; - Token token = null; - UUID nullUUID = new UUID(0,0); - UUID platformTokenSpace= nullUUID; - List skuDataArray = new ArrayList(); - SkuInstance skuInstance = null; - int skuIndex = 0; + 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; + long tokenNumber = 0; + String hiiDefaultValue = null; + String[] variableGuidString = null; + + List 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 "+ + "in FPD file, but it is required!", + token.cName, + moduleName); + throw new EntityException(exceptionString); + } - // - // Get all tokens from FPD file and create token into database. - // + token.datumSize = dynamicInfo.getMaxDatumSize(); - try { - doc = XmlObject.Factory.parse(new File(fpdFilePath)); - } catch(IOException ioE) { - throw new EntityException("Can't find the FPD xml fle:" + fpdFilePath); - } catch(XmlException xmlE) { - throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath); + exceptionString = verifyDatum(token.cName, + moduleName, + null, + token.datumType, + token.datumSize); + if (exceptionString != null) { + throw new EntityException(exceptionString); } - // - // Get memoryDatabaseManager instance from GlobalData. - // - if((dbManager = GlobalData.getPCDMemoryDBManager()) == null) { - throw new EntityException("The instance of PCD memory database manager is null"); + 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 is %d, they are not match!", + token.cName, + moduleName, + maxDatumSize, + dynamicInfo.getMaxDatumSize()); + throw new EntityException(exceptionString); } - - dbManager = new MemoryDatabaseManager(); - - if(!(doc instanceof FrameworkPlatformDescriptionDocument)) { - throw new EntityException("File " + fpdFilePath + - " is not a FrameworkPlatformDescriptionDocument"); + tokenNumber = Long.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 , the token number is 0x%x, they are not match!", + token.cName, + moduleName, + token.tokenNumber, + tokenNumber); + throw new EntityException(exceptionString); } - fpdDoc =(FrameworkPlatformDescriptionDocument)doc; + pcdType = Token.getpcdTypeFromString(dynamicInfo.getItemType().toString()); + token.dynamicExTokenNumber = tokenNumber; + + skuInfoList = dynamicInfo.getSkuInfoList(); // - // Add all tokens in FPD into Memory Database. - // - pcdBuildDataArray = - fpdDoc.getFrameworkPlatformDescription().getPcdBuildDeclarations().getPcdBuildDataList(); - for(index = 0; - index < fpdDoc.getFrameworkPlatformDescription().getPcdBuildDeclarations().sizeOfPcdBuildDataArray(); - index ++) { - pcdBuildData = pcdBuildDataArray.get(index); - token = new Token(pcdBuildData.getCName(), new UUID(0, 0), new UUID(0, 0)); + // Loop all sku data + // + for (index = 0; index < skuInfoList.size(); index ++) { + skuInstance = new SkuInstance(); // - // BUGBUG: in FPD, should be defined as + // 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; + } // - token.datum = pcdBuildData.getDefaultValue(); - token.tokenNumber = Integer.decode(pcdBuildData.getToken().getStringValue()); - token.hiiEnabled = pcdBuildData.getHiiEnable(); - token.variableGuid = Token.getGUIDFromSchemaObject(pcdBuildData.getVariableGuid()); - token.variableName = pcdBuildData.getVariableName(); - token.variableOffset = Integer.decode(pcdBuildData.getDataOffset()); - token.skuEnabled = pcdBuildData.getSkuEnable(); - token.maxSkuCount = Integer.decode(pcdBuildData.getMaxSku()); - token.skuId = Integer.decode(pcdBuildData.getSkuId()); - token.skuDataArrayEnabled = pcdBuildData.getSkuDataArrayEnable(); - token.assignedtokenNumber = Integer.decode(pcdBuildData.getToken().getStringValue()); - skuDataArray = pcdBuildData.getSkuDataArray1(); - token.datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString()); - token.datumSize = pcdBuildData.getDatumSize(); - - if(skuDataArray != null) { - for(skuIndex = 0; skuIndex < skuDataArray.size(); skuIndex ++) { - // - // BUGBUG: Now in current schema, The value is defined as String type, - // it is not correct, the type should be same as the datumType - // - skuInstance = new SkuInstance(((PcdBuildData.SkuData)skuDataArray.get(skuIndex)).getId(), - ((PcdBuildData.SkuData)skuDataArray.get(skuIndex)).getValue()); - token.skuData.add(skuInstance); + // 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); } - } - if(dbManager.isTokenInDatabase(Token.getPrimaryKeyString(token.cName, - token.tokenSpaceName, - platformTokenSpace))) { + token.skuData.add(skuInstance); + // - // If found duplicate token, Should tool be hold? + // 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 is " + skuInstance.value.value + ". They are must be same!"+ + " or you could not define value for a dynamic PCD in every !"; + 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 section in FPD "+ + "file, who use HII, but there is no 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 section in FPD "+ + "file, who use HII, but there is no 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 section in FPD "+ + "file, who use HII, but there is no 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)); + } + // - ActionMessage.warning(this, - "Token " + token.cName + " exists in token database"); + // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file. + // + variableGuidString = GlobalData.getGuidInfoFromCname(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())); + } + String variableStr = skuInfoList.get(index).getVariableName(); + Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}"); + Matcher matcher = pattern.matcher(variableStr); + List varNameList = new ArrayList(); + while (matcher.find()){ + String str = variableStr.substring(matcher.start(),matcher.end()); + varNameList.add(str); + } + + skuInstance.value.setHiiData(varNameList, + 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; } - token.pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString()); - dbManager.addTokenToDatabase(Token.getPrimaryKeyString(token.cName, - token.tokenSpaceName, - platformTokenSpace), - token); + + 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 , there are "+ + "no sku id = 0 data, which is required for every dynamic PCD", + token.cName); + throw new EntityException(exceptionString); } - return fpdDoc; + return token; } /** - Update PCD token in memory database by help information in SPD. - - After create token from FPD and create usage instance from MSA, we should collect - PCD package level information from SPD and update token information in memory - database. - - @param usageInstance The usage instance defined in MSA and want to search in SPD. - @param packageFullPath The SPD file path. - - @throws EntityException Failed to parse SPD xml file. - + 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 void updateTokenBySPD(UsageInstance usageInstance, - String packageFullPath) + private UUID translateSchemaStringToUUID(String uuidString) throws EntityException { - PackageSurfaceAreaDocument pkgDoc = null; - PcdDefinitions pcdDefinitions = null; - List pcdEntryArray = new ArrayList(); - int index = 0; - boolean isFoundInSpd = false; - Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN; + String temp; + String[] splitStringArray; + int index; + int chIndex; + int chLen; - try { - pkgDoc =(PackageSurfaceAreaDocument)XmlObject.Factory.parse(new File(packageFullPath)); - } catch(IOException ioE) { - throw new EntityException("Can't find the FPD xml fle:" + packageFullPath); - } catch(XmlException xmlE) { - throw new EntityException("Can't parse the FPD xml fle:" + packageFullPath); - } - pcdDefinitions = pkgDoc.getPackageSurfaceArea().getPcdDefinitions(); - // - // It is illege for SPD file does not contains any PCD information. - // - if (pcdDefinitions == null) { - return; + if (uuidString == null) { + return null; } - pcdEntryArray = pcdDefinitions.getPcdEntryList(); - if (pcdEntryArray == null) { - return; + if (uuidString.length() == 0) { + return null; } - for(index = 0; index < pcdEntryArray.size(); index ++) { - if(pcdEntryArray.get(index).getCName().equalsIgnoreCase( - usageInstance.parentToken.cName)) { - isFoundInSpd = true; - // - // From SPD file , we can get following information. - // Token: Token number defined in package level. - // PcdItemType: This item does not single one. It means all supported item type. - // datumType: UINT8, UNIT16, UNIT32, UINT64, VOID*, BOOLEAN - // datumSize: The size of default value or maxmine size. - // defaultValue: This value is defined in package level. - // HelpText: The help text is provided in package level. - // - usageInstance.parentToken.tokenNumber = Integer.decode(pcdEntryArray.get(index).getToken()); + if (uuidString.equals("0") || + uuidString.equalsIgnoreCase("0x0")) { + return new UUID(0, 0); + } - if(pcdEntryArray.get(index).getDatumType() != null) { - datumType = Token.getdatumTypeFromString( - pcdEntryArray.get(index).getDatumType().toString()); - if(usageInstance.parentToken.datumType == Token.DATUM_TYPE.UNKNOWN) { - usageInstance.parentToken.datumType = datumType; - } else { - if(datumType != usageInstance.parentToken.datumType) { - throw new EntityException("Different datum types are defined for Token :" + - usageInstance.parentToken.cName); - } - } + uuidString = uuidString.replaceAll("\\{", ""); + uuidString = uuidString.replaceAll("\\}", ""); - } else { - throw new EntityException("The datum type for token " + usageInstance.parentToken.cName + - " is not defind in SPD file " + packageFullPath); - } + // + // 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); + } - usageInstance.defaultValueInSPD = pcdEntryArray.get(index).getDefaultValue(); - usageInstance.helpTextInSPD = "Help Text in SPD"; + // + // 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()); + } - // - // If token's datum is not valid, it indicate that datum is not provided - // in FPD and defaultValue is not provided in MSA, then use defaultValue - // in SPD as the datum of token. - // - if(usageInstance.parentToken.datum == null) { - if(pcdEntryArray.get(index).getDefaultValue() != null) { - usageInstance.parentToken.datum = pcdEntryArray.get(index).getDefaultValue(); - } else { - throw new EntityException("FPD does not provide datum for token " + usageInstance.parentToken.cName + - ", MSA and SPD also does not provide for this token!"); - } + // + // 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); } /** @@ -1843,11 +3113,16 @@ public class CollectPCDAction { **/ public static void main(String argv[]) throws EntityException { CollectPCDAction ca = new CollectPCDAction(); - ca.setWorkspacePath("G:/mdk"); - ca.setFPDFilePath("G:/mdk/EdkNt32Pkg/build/Nt32.fpd"); + String projectDir = "x:/edk2"; + ca.setWorkspacePath(projectDir); + ca.setFPDFilePath(projectDir + "/EdkNt32Pkg/Nt32.fpd"); ca.setActionMessageLevel(ActionMessage.MAX_MESSAGE_LEVEL); GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db", - "G:/mdk"); + projectDir, + "tools_def.txt"); + System.out.println("After initInfo!"); + FpdParserTask fpt = new FpdParserTask(); + fpt.parseFpdFile(new File(projectDir + "/EdkNt32Pkg/Nt32.fpd")); ca.execute(); } }