From 241876c7a32330e31ce3e11b01d0246b28e81cfb Mon Sep 17 00:00:00 2001 From: klu2 Date: Tue, 1 Aug 2006 06:56:43 +0000 Subject: [PATCH] Add new PcdDatabase.java file. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@1166 6f19259b-4bc3-4df7-8a09-765794883524 --- .../build/pcd/action/PcdDatabase.java | 1653 +++++++++++++++++ 1 file changed, 1653 insertions(+) create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/action/PcdDatabase.java diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PcdDatabase.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PcdDatabase.java new file mode 100644 index 0000000000..9a8699cfe4 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PcdDatabase.java @@ -0,0 +1,1653 @@ +/** @file + PcdDatabase class. + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ +package org.tianocore.build.pcd.action; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.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.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions; +import org.tianocore.FrameworkModulesDocument; +import org.tianocore.ModuleSADocument; +import org.tianocore.PcdBuildDefinitionDocument; +import org.tianocore.PcdBuildDefinitionDocument.PcdBuildDefinition; +import org.tianocore.PlatformSurfaceAreaDocument; +import org.tianocore.build.fpd.FpdParserTask; +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.id.FpdModuleIdentification; +import org.tianocore.build.id.ModuleIdentification; +import org.tianocore.pcd.action.ActionMessage; +import org.tianocore.pcd.entity.CommonDefinition; +import org.tianocore.pcd.entity.DynamicTokenValue; +import org.tianocore.pcd.entity.MemoryDatabaseManager; +import org.tianocore.pcd.entity.SkuInstance; +import org.tianocore.pcd.entity.Token; +import org.tianocore.pcd.entity.UsageIdentification; +import org.tianocore.pcd.entity.UsageInstance; +import org.tianocore.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 String phase; + int len; + + public StringTable (String phase) { + this.phase = phase; + al = new ArrayList(); + alComments = new ArrayList(); + len = 0; + } + + public String getSizeMacro () { + return String.format(PcdDatabase.StringTableSizeMacro, phase, getSize()); + } + + private int getSize () { + // + // We have at least one Unicode Character in the table. + // + return len == 0 ? 1 : len; + } + + public 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; + + String cDeclCode = ""; + String cInstCode = ""; + + // + // 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 { + + // + // 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 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()); + + 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 int len; + private String phase; + + public SizeTable (String phase) { + al = new ArrayList>(); + alComments = new ArrayList(); + len = 0; + this.phase = phase; + } + + public String getSizeMacro () { + return String.format(PcdDatabase.SizeTableSizeMacro, phase, getSize()); + } + + private int getSize() { + return len == 0 ? 1 : len; + } + + 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); + + + cCode = PcdDatabase.genInstantiationStr(getInstantiation()); + instTable.put(name, cCode); + } + + private ArrayList getInstantiation () { + final String comma = ","; + ArrayList Output = new ArrayList(); + + 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; + } + } + + str += " /* " + alComments.get(index) + " */"; + + if (index != (al.size() - 1)) { + str += comma; + } + + Output.add(str); + + } + } + Output.add("}"); + + return Output; + } + + 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(); + + 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 String phase; + private int len; + private int bodyLineNum; + + public GuidTable (String phase) { + this.phase = phase; + al = new ArrayList(); + alComments = new ArrayList(); + len = 0; + bodyLineNum = 0; + } + + public String getSizeMacro () { + return String.format(PcdDatabase.GuidTableSizeMacro, phase, getSize()); + } + + private int getSize () { + return (al.size() == 0)? 1 : al.size(); + } + + public String getExistanceMacro () { + return String.format(PcdDatabase.GuidTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); + } + + public void genCode (ArrayList declaList, HashMap instTable, String phase) { + final String name = "GuidTable"; + + CStructTypeDeclaration decl; + String cCode = ""; + + cCode += String.format(PcdDatabase.GuidTableDeclaration, phase); + decl = new CStructTypeDeclaration ( + name, + 4, + cCode, + true + ); + declaList.add(decl); + + + 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)) + ); + } + + private ArrayList getInstantiation () { + ArrayList Output = new ArrayList(); + + Output.add("/* GuidTable */"); + Output.add("{"); + + if (al.size() == 0) { + Output.add("\t" + getUuidCString(new UUID(0, 0))); + } + + for (int i = 0; i < al.size(); i++) { + String str = "\t" + getUuidCString(al.get(i)); + + str += "/* " + alComments.get(i) + " */"; + if (i != (al.size() - 1)) { + str += ","; + } + Output.add(str); + bodyLineNum++; + + } + Output.add("}"); + + return Output; + } + + public int add (UUID uuid, String name) { + // + // 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 the previous Table Index + // + return len - 1; + } + +} + +/** + SkuIdTable + + This class is used to store the SKU IDs in a PCD database. + +**/ +class SkuIdTable { + private ArrayList al; + private ArrayList alComment; + private String phase; + private int len; + + public SkuIdTable (String phase) { + this.phase = phase; + al = new ArrayList(); + alComment = new ArrayList(); + len = 0; + } + + public String getSizeMacro () { + return String.format(PcdDatabase.SkuIdTableSizeMacro, phase, getSize()); + } + + private int getSize () { + return (len == 0)? 1 : len; + } + + public String getExistanceMacro () { + return String.format(PcdDatabase.SkuTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); + } + + 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"); + } + + } + + private ArrayList getInstantiation () { + ArrayList Output = new ArrayList (); + + Output.add("/* SkuIdTable */"); + Output.add("{"); + + if (al.size() == 0) { + Output.add("\t0"); + } + + for (int index = 0; index < al.size(); index++) { + String str; + + str = "/* " + alComment.get(index) + "*/ "; + str += "/* MaxSku */ "; + + + Integer[] ia = al.get(index); + + 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); + + } + + Output.add("}"); + + return Output; + } + + public int add (Token token) { + + 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.skuData.size() + 1]; + skuIds[0] = new Integer(token.skuData.size()); + for (index = 1; index < skuIds.length; index++) { + skuIds[index] = new Integer(token.skuData.get(index - 1).id); + } + + index = len; + + len += skuIds.length; + al.add(skuIds); + alComment.add(token.getPrimaryKeyString()); + + return index; + } + +} + +class LocalTokenNumberTable { + private ArrayList al; + private ArrayList alComment; + private String phase; + private int len; + + public LocalTokenNumberTable (String phase) { + this.phase = phase; + al = new ArrayList(); + alComment = new ArrayList(); + + len = 0; + } + + public String getSizeMacro () { + return String.format(PcdDatabase.LocalTokenNumberTableSizeMacro, phase, getSize()) + + String.format(PcdDatabase.LocalTokenNumberSizeMacro, phase, al.size()); + } + + public int getSize () { + return (al.size() == 0)? 1 : al.size(); + } + + public String getExistanceMacro () { + return String.format(PcdDatabase.DatabaseExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); + } + + public 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); + } + + private ArrayList getInstantiation () { + ArrayList output = new ArrayList(); + + output.add("/* LocalTokenNumberTable */"); + output.add("{"); + + if (al.size() == 0) { + output.add("\t0"); + } + + for (int index = 0; index < al.size(); index++) { + String str; + + str = "\t" + (String)al.get(index); + + str += " /* " + alComment.get(index) + " */ "; + + + if (index != (al.size() - 1)) { + str += ","; + } + + output.add(str); + + } + + output.add("}"); + + return output; + } + + public int add (Token token) { + int index = len; + String str; + + len++; + + str = String.format(PcdDatabase.offsetOfStrTemplate, phase, token.hasDefaultValue() ? "Init" : "Uninit", token.getPrimaryKeyString()); + + if (token.isUnicodeStringType()) { + str += " | PCD_TYPE_STRING"; + } + + if (token.isSkuEnable()) { + str += " | PCD_TYPE_SKU_ENABLED"; + } + + if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.HII_TYPE) { + str += " | PCD_TYPE_HII"; + } + + if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.VPD_TYPE) { + str += " | PCD_TYPE_VPD"; + } + + 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()); + + 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 { + + /** + 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 Map alComment; + private String phase; + private int len; + private int bodyLineNum; + + public ExMapTable (String phase) { + this.phase = phase; + al = new ArrayList(); + alComment = new HashMap(); + bodyLineNum = 0; + len = 0; + } + + public String getSizeMacro () { + return String.format(PcdDatabase.ExMapTableSizeMacro, phase, getTableLen()) + + String.format(PcdDatabase.ExTokenNumber, phase, al.size()); + } + + public String getExistanceMacro () { + return String.format(PcdDatabase.ExMapTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE"); + } + + 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); + + + cCode = PcdDatabase.genInstantiationStr(getInstantiation()); + instTable.put(exMapTableName, cCode); + } + + private ArrayList getInstantiation () { + ArrayList Output = new ArrayList(); + + Output.add("/* ExMapTable */"); + Output.add("{"); + if (al.size() == 0) { + Output.add("\t{0, 0, 0}"); + } + + int index; + for (index = 0; index < al.size(); index++) { + String str; + + ExTriplet e = (ExTriplet)al.get(index); + + str = "\t" + "{ " + String.format("0x%08X", e.exTokenNumber) + ", "; + str += e.localTokenIdx.toString() + ", "; + str += e.guidTableIdx.toString(); + + str += "}" + " /* " + alComment.get(e) + " */" ; + + if (index != al.size() - 1) { + str += ","; + } + + Output.add(str); + bodyLineNum++; + + } + + Output.add("}"); + + return Output; + } + + public int add (int localTokenIdx, long exTokenNum, int guidTableIdx, String name) { + int index = len; + + len++; + ExTriplet et = new ExTriplet(guidTableIdx, exTokenNum, localTokenIdx); + + al.add(et); + alComment.put(et, name); + + return index; + } + + 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. +**/ +public class PcdDatabase { + + 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_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"; + + + public final static String ExMapTableExistenceMacro = "#define %s_EXMAP_TABLE_EMPTY %s\r\n"; + public final static String GuidTableExistenceMacro = "#define %s_GUID_TABLE_EMPTY %s\r\n"; + public final static String DatabaseExistenceMacro = "#define %s_DATABASE_EMPTY %s\r\n"; + public final static String StringTableExistenceMacro = "#define %s_STRING_TABLE_EMPTY %s\r\n"; + public final static String SkuTableExistenceMacro = "#define %s_SKUID_TABLE_EMPTY %s\r\n"; + + public final static String offsetOfSkuHeadStrTemplate = "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)"; + public final static String 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; + + /** + 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; + } + + 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); + } + } + + return; + } + + 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; + } + + if (token.isUnicodeStringType()) { + return 2; + } + + return getDataTypeAlignmentSize(token); + } + + public String getCString () { + return cString; + } + + public String getHString () { + return hString; + } + + private void genCodeWorker(Token t, + ArrayList declaList, + HashMap instTable, String phase) + throws EntityException { + + CStructTypeDeclaration decl; + + // + // 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)); + } + + // + // Insert PCD_ENTRY declaration and instantiation + // + getCDeclarationString(t); + + decl = new CStructTypeDeclaration(privateGlobalName, + getAlignmentSize(t), privateGlobalCCode, t.hasDefaultValue()); + declaList.add(decl); + + if (t.hasDefaultValue()) { + instTable.put(privateGlobalName, + getTypeInstantiation(t, declaList, instTable, phase) + ); + } + + } + + 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() + ); + } + } + + } + + public void genCode () throws EntityException { + + ArrayList cStructDeclList = new ArrayList(); + HashMap cStructInstTable = new HashMap(); + + List nexTokens = new ArrayList (); + List exTokens = new ArrayList (); + + 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); + } +} \ No newline at end of file