+/** @file\r
+ PlatformPcdPreprocessAction class.\r
+\r
+ The abstract parent class PlatformPcdPreprocessAction, This class is to collect platform's\r
+ pcd build information from fpd file.\r
+ This class will be extended by building tools and wizard tools.\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+package org.tianocore.pcd.action;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.UUID;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions;\r
+import org.tianocore.PcdBuildDefinitionDocument.PcdBuildDefinition;\r
+import org.tianocore.pcd.entity.MemoryDatabaseManager;\r
+import org.tianocore.pcd.exception.EntityException;\r
+import org.tianocore.pcd.entity.*;\r
+import org.tianocore.pcd.entity.Token;\r
+\r
+/**\r
+ The abstract parent class PlatformPcdPreprocessAction, This class is to collect platform's\r
+ pcd build information from fpd file.\r
+ This class will be extended by building tools and wizard tools.\r
+\r
+**/\r
+public abstract class PlatformPcdPreprocessAction {\r
+ ///\r
+ /// PCD memory database\r
+ ///\r
+ private MemoryDatabaseManager pcdDbManager;\r
+\r
+ /**\r
+ Set parameter pcdDbManager\r
+\r
+ @param pcdDbManager\r
+ **/\r
+ public void setPcdDbManager(MemoryDatabaseManager pcdDbManager) {\r
+ this.pcdDbManager = pcdDbManager;\r
+ }\r
+\r
+ /**\r
+ Get parameter pcdDbManager\r
+ \r
+ @return MemoryDatabaseManager\r
+ **/\r
+ public MemoryDatabaseManager getPcdDbManager() {\r
+ return pcdDbManager;\r
+ }\r
+ /**\r
+ Abstract function: retrieve module information from FPD file.\r
+\r
+ In building environement, this function will be implementated by FpdParserTask.\r
+\r
+ @return List<ModuleInfoFromFpd>\r
+ **/\r
+ public abstract List<ModulePcdInfoFromFpd> getComponentsFromFpd()\r
+ throws EntityException;\r
+\r
+ /**\r
+ Abstract function to get GUID string from SPD file.\r
+\r
+ In building evnironment, this function will be implementated by GlobaData.\r
+\r
+ @param guidCName the CName of GUID\r
+\r
+ @return String[] Guid Info array contains CName and Guid String\r
+ **/\r
+ public abstract String[] getGuidInfoFromSpd(String guidCName)\r
+ throws EntityException;\r
+\r
+ /**\r
+ Abstract function: Verification the PCD data.\r
+\r
+ In different environment, such as building environment and wizard environment,\r
+ it has different implementation according to optimization.\r
+\r
+ @param cName\r
+ @param moduleName\r
+ @param datum\r
+ @param datumType\r
+ @param maxDatumSize\r
+\r
+ @return String\r
+ **/\r
+ public abstract String verifyDatum(String cName,\r
+ String moduleName,\r
+ String datum,\r
+ Token.DATUM_TYPE datumType,\r
+ int maxDatumSize);\r
+\r
+ /**\r
+ Abstract function: Get dynamic information for a token\r
+\r
+ @param token\r
+ @param moduleName\r
+\r
+ @return DynamicPcdBuildDefinitions.PcdBuildData\r
+ **/\r
+ public abstract DynamicPcdBuildDefinitions.PcdBuildData\r
+ getDynamicInfoFromFpd(Token token,\r
+ String moduleName)\r
+ throws EntityException;\r
+\r
+ /**\r
+ Abstract function: Get all dynamic PCD information from FPD file.\r
+\r
+ @return List<DynamicPcdBuildDefinitions.PcdBuildData>\r
+ **/\r
+ public abstract List<DynamicPcdBuildDefinitions.PcdBuildData>\r
+ getAllDynamicPcdInfoFromFpd()\r
+ throws EntityException;\r
+\r
+ /**\r
+ Collect all PCD information from FPD file into PCD memory database.\r
+\r
+ **/\r
+ public void initPcdMemoryDbWithPlatformInfo()\r
+ throws EntityException {\r
+ int index = 0;\r
+ int pcdIndex = 0;\r
+ List<PcdBuildDefinition.PcdData> pcdBuildDataArray = new ArrayList<PcdBuildDefinition.PcdData>();\r
+ PcdBuildDefinition.PcdData pcdBuildData = null;\r
+ Token token = null;\r
+ List<ModulePcdInfoFromFpd> modules = null;\r
+ String primaryKey = null;\r
+ String exceptionString = null;\r
+ UsageInstance usageInstance = null;\r
+ Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN;\r
+ Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN;\r
+ long tokenNumber = 0;\r
+ String moduleName = null;\r
+ String datum = null;\r
+ int maxDatumSize = 0;\r
+ String[] tokenSpaceStrRet = null;\r
+\r
+ //\r
+ // ----------------------------------------------\r
+ // 1), Get all <ModuleSA> from FPD file.\r
+ // ----------------------------------------------\r
+ //\r
+ modules = getComponentsFromFpd();\r
+\r
+ if (modules == null) {\r
+ throw new EntityException("[FPD file error] No modules in FPD file, Please check whether there are elements in <FrameworkModules> in FPD file!");\r
+ }\r
+\r
+ //\r
+ // -------------------------------------------------------------------\r
+ // 2), Loop all modules to process <PcdBuildDeclarations> for each module.\r
+ // -------------------------------------------------------------------\r
+ //\r
+ for (index = 0; index < modules.size(); index ++) {\r
+ //\r
+ // It is legal for a module does not contains ANY pcd build definitions.\r
+ //\r
+ if (modules.get(index).pcdBuildDefinition == null) {\r
+ continue;\r
+ }\r
+\r
+ pcdBuildDataArray = modules.get(index).pcdBuildDefinition.getPcdDataList();\r
+\r
+ moduleName = modules.get(index).usageId.moduleName;\r
+\r
+ //\r
+ // ----------------------------------------------------------------------\r
+ // 2.1), Loop all Pcd entry for a module and add it into memory database.\r
+ // ----------------------------------------------------------------------\r
+ //\r
+ for (pcdIndex = 0; pcdIndex < pcdBuildDataArray.size(); pcdIndex ++) {\r
+ pcdBuildData = pcdBuildDataArray.get(pcdIndex);\r
+\r
+ tokenSpaceStrRet = getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName());\r
+\r
+ if (tokenSpaceStrRet == null) {\r
+ throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData.getCName());\r
+ }\r
+\r
+ primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(), tokenSpaceStrRet[1]);\r
+ pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString());\r
+ datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString());\r
+ tokenNumber = Long.decode(pcdBuildData.getToken().toString());\r
+ if (pcdBuildData.getValue() != null) {\r
+ datum = pcdBuildData.getValue().toString();\r
+ } else {\r
+ datum = null;\r
+ }\r
+ maxDatumSize = pcdBuildData.getMaxDatumSize();\r
+\r
+ if ((pcdType == Token.PCD_TYPE.FEATURE_FLAG) &&\r
+ (datumType != Token.DATUM_TYPE.BOOLEAN)){\r
+ exceptionString = String.format("[FPD file error] For PCD %s in module %s, the PCD type is FEATRUE_FLAG but "+\r
+ "datum type of this PCD entry is not BOOLEAN!",\r
+ pcdBuildData.getCName(),\r
+ moduleName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ //\r
+ // -------------------------------------------------------------------------------------------\r
+ // 2.1.1), Do some necessary checking work for FixedAtBuild, FeatureFlag and PatchableInModule\r
+ // -------------------------------------------------------------------------------------------\r
+ //\r
+ if (!Token.isDynamic(pcdType)) {\r
+ //\r
+ // Value is required.\r
+ //\r
+ if (datum == null) {\r
+ exceptionString = String.format("[FPD file error] There is no value for PCD entry %s in module %s!",\r
+ pcdBuildData.getCName(),\r
+ moduleName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ //\r
+ // Check whether the datum size is matched datum type.\r
+ //\r
+ if ((exceptionString = verifyDatum(pcdBuildData.getCName(),\r
+ moduleName,\r
+ datum,\r
+ datumType,\r
+ maxDatumSize)) != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ //\r
+ // ---------------------------------------------------------------------------------\r
+ // 2.1.2), Create token or update token information for current anaylized PCD data.\r
+ // ---------------------------------------------------------------------------------\r
+ //\r
+ if (pcdDbManager.isTokenInDatabase(primaryKey)) {\r
+ //\r
+ // If the token is already exist in database, do some necessary checking\r
+ // and add a usage instance into this token in database\r
+ //\r
+ token = pcdDbManager.getTokenByKey(primaryKey);\r
+\r
+ //\r
+ // checking for DatumType, DatumType should be unique for one PCD used in different\r
+ // modules.\r
+ //\r
+ if (token.datumType != datumType) {\r
+ exceptionString = String.format("[FPD file error] The datum type of PCD entry %s is %s, which is different with %s defined in before!",\r
+ pcdBuildData.getCName(),\r
+ pcdBuildData.getDatumType().toString(),\r
+ Token.getStringOfdatumType(token.datumType));\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ //\r
+ // Check token number is valid\r
+ //\r
+ if (tokenNumber != token.tokenNumber) {\r
+ 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!",\r
+ pcdBuildData.getCName(),\r
+ moduleName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ //\r
+ // For same PCD used in different modules, the PCD type should all be dynamic or non-dynamic.\r
+ //\r
+ if (token.isDynamicPCD != Token.isDynamic(pcdType)) {\r
+ exceptionString = String.format("[FPD file error] For PCD entry %s in module %s, you define dynamic or non-dynamic PCD type which"+\r
+ "is different with others module's",\r
+ token.cName,\r
+ moduleName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ if (token.isDynamicPCD) {\r
+ //\r
+ // Check datum is equal the datum in dynamic information.\r
+ // For dynamic PCD, you can do not write <Value> in sperated every <PcdBuildDefinition> in different <ModuleSA>,\r
+ // But if you write, the <Value> must be same as the value in <DynamicPcdBuildDefinitions>.\r
+ //\r
+ if (!token.isSkuEnable() &&\r
+ (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.DEFAULT_TYPE) &&\r
+ (datum != null)) {\r
+ if (!datum.equalsIgnoreCase(token.getDefaultSku().value)) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in module %s, the datum in <ModuleSA> is "+\r
+ "not equal to the datum in <DynamicPcdBuildDefinitions>, it is "+\r
+ "illega! You could no set <Value> in <ModuleSA> for a dynamic PCD!",\r
+ token.cName,\r
+ moduleName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ if ((maxDatumSize != 0) &&\r
+ (maxDatumSize != token.datumSize)){\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in module %s, the max datum size is %d which "+\r
+ "is different with <MaxDatumSize> %d defined in <DynamicPcdBuildDefinitions>!",\r
+ token.cName,\r
+ moduleName,\r
+ maxDatumSize,\r
+ token.datumSize);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ } else {\r
+ //\r
+ // If the token is not in database, create a new token instance and add\r
+ // a usage instance into this token in database.\r
+ //\r
+ tokenSpaceStrRet = this.getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName());\r
+\r
+ if (tokenSpaceStrRet == null) {\r
+ throw new EntityException("Fail to get token space guid for token " + token.cName);\r
+ }\r
+\r
+ token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet[1]);\r
+\r
+ token.datumType = datumType;\r
+ token.tokenNumber = tokenNumber;\r
+ token.isDynamicPCD = Token.isDynamic(pcdType);\r
+ token.datumSize = maxDatumSize;\r
+\r
+ if (token.isDynamicPCD) {\r
+ //\r
+ // For Dynamic and Dynamic Ex type, need find the dynamic information\r
+ // in <DynamicPcdBuildDefinition> section in FPD file.\r
+ //\r
+ updateDynamicInformation(moduleName,\r
+ token,\r
+ datum,\r
+ maxDatumSize);\r
+ }\r
+\r
+ pcdDbManager.addTokenToDatabase(primaryKey, token);\r
+ }\r
+\r
+ //\r
+ // -----------------------------------------------------------------------------------\r
+ // 2.1.3), Add the PcdType in current module into this Pcd token's supported PCD type.\r
+ // -----------------------------------------------------------------------------------\r
+ //\r
+ token.updateSupportPcdType(pcdType);\r
+\r
+ //\r
+ // ------------------------------------------------\r
+ // 2.1.4), Create an usage instance for this token.\r
+ // ------------------------------------------------\r
+ //\r
+ usageInstance = new UsageInstance(token,\r
+ modules.get(index).usageId,\r
+ pcdType,\r
+ datum,\r
+ maxDatumSize);\r
+ token.addUsageInstance(usageInstance);\r
+ }\r
+ }\r
+\r
+ //\r
+ // ------------------------------------------------\r
+ // 3), Add unreference dynamic_Ex pcd token into Pcd database.\r
+ // ------------------------------------------------\r
+ //\r
+ List<Token> tokenArray = getUnreferencedDynamicPcd();\r
+ if (tokenArray != null) {\r
+ for (index = 0; index < tokenArray.size(); index ++) {\r
+ pcdDbManager.addTokenToDatabase(tokenArray.get(index).getPrimaryKeyString(),\r
+ tokenArray.get(index));\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ Update dynamic information for PCD entry.\r
+\r
+ Dynamic information is retrieved from <PcdDynamicBuildDeclarations> in\r
+ FPD file.\r
+\r
+ @param moduleName The name of the module who use this PCD\r
+ @param token The token instance\r
+ @param datum The <datum> in module's PCD information\r
+ @param maxDatumSize The <maxDatumSize> in module's PCD information\r
+\r
+ @return Token\r
+ */\r
+ private Token updateDynamicInformation(String moduleName,\r
+ Token token,\r
+ String datum,\r
+ int maxDatumSize)\r
+ throws EntityException {\r
+ int index = 0;\r
+ int offset;\r
+ String exceptionString = null;\r
+ SkuInstance skuInstance = null;\r
+ String temp;\r
+ boolean hasSkuId0 = false;\r
+ long tokenNumber = 0;\r
+ String hiiDefaultValue = null;\r
+ String[] variableGuidString = null;\r
+\r
+ List<DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo> skuInfoList = null;\r
+ DynamicPcdBuildDefinitions.PcdBuildData dynamicInfo = null;\r
+\r
+ dynamicInfo = getDynamicInfoFromFpd(token, moduleName);\r
+ if (dynamicInfo == null) {\r
+ exceptionString = String.format("[FPD file error] For Dynamic PCD %s used by module %s, "+\r
+ "there is no dynamic information in <DynamicPcdBuildDefinitions> "+\r
+ "in FPD file, but it is required!",\r
+ token.cName,\r
+ moduleName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ token.datumSize = dynamicInfo.getMaxDatumSize();\r
+\r
+ exceptionString = verifyDatum(token.cName,\r
+ moduleName,\r
+ null,\r
+ token.datumType,\r
+ token.datumSize);\r
+ if (exceptionString != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ if ((maxDatumSize != 0) &&\r
+ (maxDatumSize != token.datumSize)) {\r
+ exceptionString = String.format("FPD file error] For dynamic PCD %s, the datum size in module %s is %d, but "+\r
+ "the datum size in <DynamicPcdBuildDefinitions> is %d, they are not match!",\r
+ token.cName,\r
+ moduleName,\r
+ maxDatumSize,\r
+ dynamicInfo.getMaxDatumSize());\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ tokenNumber = Long.decode(dynamicInfo.getToken().toString());\r
+ if (tokenNumber != token.tokenNumber) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s, the token number in module %s is 0x%x, but"+\r
+ "in <DynamicPcdBuildDefinictions>, the token number is 0x%x, they are not match!",\r
+ token.cName,\r
+ moduleName,\r
+ token.tokenNumber,\r
+ tokenNumber);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ token.dynamicExTokenNumber = tokenNumber;\r
+\r
+ skuInfoList = dynamicInfo.getSkuInfoList();\r
+\r
+ //\r
+ // Loop all sku data\r
+ //\r
+ for (index = 0; index < skuInfoList.size(); index ++) {\r
+ skuInstance = new SkuInstance();\r
+ //\r
+ // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.\r
+ //\r
+ temp = skuInfoList.get(index).getSkuId().toString();\r
+ skuInstance.id = Integer.decode(temp);\r
+ if (skuInstance.id == 0) {\r
+ hasSkuId0 = true;\r
+ }\r
+ //\r
+ // Judge whether is DefaultGroup at first, because most case is DefautlGroup.\r
+ //\r
+ if (skuInfoList.get(index).getValue() != null) {\r
+ skuInstance.value.setValue(skuInfoList.get(index).getValue().toString());\r
+ if ((exceptionString = verifyDatum(token.cName,\r
+ null,\r
+ skuInfoList.get(index).getValue().toString(),\r
+ token.datumType,\r
+ token.datumSize)) != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ token.skuData.add(skuInstance);\r
+\r
+ //\r
+ // Judege wether is same of datum between module's information\r
+ // and dynamic information.\r
+ //\r
+ if (datum != null) {\r
+ if ((skuInstance.id == 0) &&\r
+ !datum.toString().equalsIgnoreCase(skuInfoList.get(index).getValue().toString())) {\r
+ exceptionString = "[FPD file error] For dynamic PCD " + token.cName + ", the value in module " + moduleName + " is " + datum.toString() + " but the "+\r
+ "value of sku 0 data in <DynamicPcdBuildDefinition> is " + skuInstance.value.value + ". They are must be same!"+\r
+ " or you could not define value for a dynamic PCD in every <ModuleSA>!";\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Judge whether is HII group case.\r
+ //\r
+ if (skuInfoList.get(index).getVariableName() != null) {\r
+ exceptionString = null;\r
+ if (skuInfoList.get(index).getVariableGuid() == null) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
+ "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",\r
+ token.cName,\r
+ index);\r
+ if (exceptionString != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ if (skuInfoList.get(index).getVariableOffset() == null) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
+ "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",\r
+ token.cName,\r
+ index);\r
+ if (exceptionString != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ if (skuInfoList.get(index).getHiiDefaultValue() == null) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
+ "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",\r
+ token.cName,\r
+ index);\r
+ if (exceptionString != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ if (skuInfoList.get(index).getHiiDefaultValue() != null) {\r
+ hiiDefaultValue = skuInfoList.get(index).getHiiDefaultValue().toString();\r
+ } else {\r
+ hiiDefaultValue = null;\r
+ }\r
+\r
+ if ((exceptionString = verifyDatum(token.cName,\r
+ null,\r
+ hiiDefaultValue,\r
+ token.datumType,\r
+ token.datumSize)) != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ offset = Integer.decode(skuInfoList.get(index).getVariableOffset());\r
+ if (offset > 0xFFFF) {\r
+ throw new EntityException(String.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+\r
+ "exceed 64K, it is not allowed!",\r
+ token.cName,\r
+ index));\r
+ }\r
+\r
+ //\r
+ // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.\r
+ //\r
+ variableGuidString = getGuidInfoFromSpd(skuInfoList.get(index).getVariableGuid().toString());\r
+ if (variableGuidString == null) {\r
+ throw new EntityException(String.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",\r
+ token.cName,\r
+ skuInfoList.get(index).getVariableGuid().toString()));\r
+ }\r
+ String variableStr = skuInfoList.get(index).getVariableName();\r
+ Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}");\r
+ Matcher matcher = pattern.matcher(variableStr);\r
+ List<String> varNameList = new ArrayList<String>();\r
+ while (matcher.find()){\r
+ String str = variableStr.substring(matcher.start(),matcher.end());\r
+ varNameList.add(str);\r
+ }\r
+\r
+ skuInstance.value.setHiiData(varNameList,\r
+ translateSchemaStringToUUID(variableGuidString[1]),\r
+ skuInfoList.get(index).getVariableOffset(),\r
+ skuInfoList.get(index).getHiiDefaultValue().toString());\r
+ token.skuData.add(skuInstance);\r
+ continue;\r
+ }\r
+\r
+ if (skuInfoList.get(index).getVpdOffset() != null) {\r
+ skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset());\r
+ token.skuData.add(skuInstance);\r
+ continue;\r
+ }\r
+\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+\r
+ "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",\r
+ token.cName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ if (!hasSkuId0) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+\r
+ "no sku id = 0 data, which is required for every dynamic PCD",\r
+ token.cName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ return token;\r
+ }\r
+\r
+ /**\r
+ Get all dynamic PCD defined in <DynamicPcdBuildDefinitions> which unreferenced by \r
+ any <ModuleSA> in FPD file.\r
+ \r
+ @return List<Token> Return PCD token \r
+ **/\r
+ private List<Token> getUnreferencedDynamicPcd () throws EntityException {\r
+ List<Token> tokenArray = new ArrayList<Token>();\r
+ Token token = null;\r
+ List<DynamicPcdBuildDefinitions.PcdBuildData> dynamicPcdBuildDataArray = null;\r
+ DynamicPcdBuildDefinitions.PcdBuildData pcdBuildData = null;\r
+ List<DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo> skuInfoList = null;\r
+ Token.PCD_TYPE pcdType;\r
+ SkuInstance skuInstance = null;\r
+ String primaryKey = null;\r
+ boolean hasSkuId0 = false;\r
+ int index, offset, index2;\r
+ String temp;\r
+ String exceptionString;\r
+ String hiiDefaultValue;\r
+ String tokenSpaceStrRet[];\r
+ String variableGuidString[];\r
+\r
+ dynamicPcdBuildDataArray = getAllDynamicPcdInfoFromFpd();\r
+ if (dynamicPcdBuildDataArray == null) {\r
+ return null;\r
+ }\r
+\r
+ for (index2 = 0; index2 < dynamicPcdBuildDataArray.size(); index2 ++) {\r
+ pcdBuildData = dynamicPcdBuildDataArray.get(index2);\r
+ tokenSpaceStrRet = this.getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName());\r
+\r
+ if (tokenSpaceStrRet == null) {\r
+ throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData.getCName());\r
+ }\r
+\r
+ primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(),\r
+ tokenSpaceStrRet[1]);\r
+\r
+ if (pcdDbManager.isTokenInDatabase(primaryKey)) {\r
+ continue;\r
+ }\r
+\r
+ pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString());\r
+ if (pcdType != Token.PCD_TYPE.DYNAMIC_EX) {\r
+ throw new EntityException (String.format("[FPD file error] It not allowed for DYNAMIC PCD %s who is no used by any module",\r
+ pcdBuildData.getCName()));\r
+ }\r
+\r
+ //\r
+ // Create new token for unreference dynamic PCD token\r
+ //\r
+ token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet[1]);\r
+ token.datumSize = pcdBuildData.getMaxDatumSize();\r
+\r
+\r
+ token.datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString());\r
+ token.tokenNumber = Long.decode(pcdBuildData.getToken().toString());\r
+ token.dynamicExTokenNumber = token.tokenNumber;\r
+ token.isDynamicPCD = true;\r
+ token.updateSupportPcdType(pcdType);\r
+\r
+ exceptionString = verifyDatum(token.cName,\r
+ null,\r
+ null,\r
+ token.datumType,\r
+ token.datumSize);\r
+ if (exceptionString != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ skuInfoList = pcdBuildData.getSkuInfoList();\r
+\r
+ //\r
+ // Loop all sku data\r
+ //\r
+ for (index = 0; index < skuInfoList.size(); index ++) {\r
+ skuInstance = new SkuInstance();\r
+ //\r
+ // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.\r
+ //\r
+ temp = skuInfoList.get(index).getSkuId().toString();\r
+ skuInstance.id = Integer.decode(temp);\r
+ if (skuInstance.id == 0) {\r
+ hasSkuId0 = true;\r
+ }\r
+ //\r
+ // Judge whether is DefaultGroup at first, because most case is DefautlGroup.\r
+ //\r
+ if (skuInfoList.get(index).getValue() != null) {\r
+ skuInstance.value.setValue(skuInfoList.get(index).getValue().toString());\r
+ if ((exceptionString = verifyDatum(token.cName,\r
+ null,\r
+ skuInfoList.get(index).getValue().toString(),\r
+ token.datumType,\r
+ token.datumSize)) != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ token.skuData.add(skuInstance);\r
+\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Judge whether is HII group case.\r
+ //\r
+ if (skuInfoList.get(index).getVariableName() != null) {\r
+ exceptionString = null;\r
+ if (skuInfoList.get(index).getVariableGuid() == null) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
+ "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",\r
+ token.cName,\r
+ index);\r
+ if (exceptionString != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ if (skuInfoList.get(index).getVariableOffset() == null) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
+ "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",\r
+ token.cName,\r
+ index);\r
+ if (exceptionString != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ if (skuInfoList.get(index).getHiiDefaultValue() == null) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
+ "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",\r
+ token.cName,\r
+ index);\r
+ if (exceptionString != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+ }\r
+\r
+ if (skuInfoList.get(index).getHiiDefaultValue() != null) {\r
+ hiiDefaultValue = skuInfoList.get(index).getHiiDefaultValue().toString();\r
+ } else {\r
+ hiiDefaultValue = null;\r
+ }\r
+\r
+ if ((exceptionString = verifyDatum(token.cName,\r
+ null,\r
+ hiiDefaultValue,\r
+ token.datumType,\r
+ token.datumSize)) != null) {\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ offset = Integer.decode(skuInfoList.get(index).getVariableOffset());\r
+ if (offset > 0xFFFF) {\r
+ throw new EntityException(String.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+\r
+ "exceed 64K, it is not allowed!",\r
+ token.cName,\r
+ index));\r
+ }\r
+\r
+ //\r
+ // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.\r
+ //\r
+ variableGuidString = this.getGuidInfoFromSpd(skuInfoList.get(index).getVariableGuid().toString());\r
+ if (variableGuidString == null) {\r
+ throw new EntityException(String.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",\r
+ token.cName,\r
+ skuInfoList.get(index).getVariableGuid().toString()));\r
+ }\r
+ String variableStr = skuInfoList.get(index).getVariableName();\r
+ Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}");\r
+ Matcher matcher = pattern.matcher(variableStr);\r
+ List<String> varNameList = new ArrayList<String>();\r
+ while (matcher.find()){\r
+ String str = variableStr.substring(matcher.start(),matcher.end());\r
+ varNameList.add(str);\r
+ }\r
+\r
+ skuInstance.value.setHiiData(varNameList,\r
+ translateSchemaStringToUUID(variableGuidString[1]),\r
+ skuInfoList.get(index).getVariableOffset(),\r
+ skuInfoList.get(index).getHiiDefaultValue().toString());\r
+ token.skuData.add(skuInstance);\r
+ continue;\r
+ }\r
+\r
+ if (skuInfoList.get(index).getVpdOffset() != null) {\r
+ skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset());\r
+ token.skuData.add(skuInstance);\r
+ continue;\r
+ }\r
+\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+\r
+ "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",\r
+ token.cName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ if (!hasSkuId0) {\r
+ exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+\r
+ "no sku id = 0 data, which is required for every dynamic PCD",\r
+ token.cName);\r
+ throw new EntityException(exceptionString);\r
+ }\r
+\r
+ tokenArray.add(token);\r
+ }\r
+\r
+ return tokenArray;\r
+ }\r
+\r
+ /**\r
+ Translate the schema string to UUID instance.\r
+\r
+ In schema, the string of UUID is defined as following two types string:\r
+ 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(\r
+ )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?\r
+\r
+ 2) GuidNamingConvention: pattern =\r
+ [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}\r
+\r
+ This function will convert string and create uuid instance.\r
+\r
+ @param uuidString UUID string in XML file\r
+\r
+ @return UUID UUID instance\r
+ **/\r
+ private UUID translateSchemaStringToUUID(String uuidString)\r
+ throws EntityException {\r
+ String temp;\r
+ String[] splitStringArray;\r
+ int index;\r
+ int chIndex;\r
+ int chLen;\r
+\r
+ if (uuidString == null) {\r
+ return null;\r
+ }\r
+\r
+ if (uuidString.length() == 0) {\r
+ return null;\r
+ }\r
+\r
+ if (uuidString.equals("0") ||\r
+ uuidString.equalsIgnoreCase("0x0")) {\r
+ return new UUID(0, 0);\r
+ }\r
+\r
+ uuidString = uuidString.replaceAll("\\{", "");\r
+ uuidString = uuidString.replaceAll("\\}", "");\r
+\r
+ //\r
+ // If the UUID schema string is GuidArrayType type then need translate\r
+ // to GuidNamingConvention type at first.\r
+ //\r
+ if ((uuidString.charAt(0) == '0') && ((uuidString.charAt(1) == 'x') || (uuidString.charAt(1) == 'X'))) {\r
+ splitStringArray = uuidString.split("," );\r
+ if (splitStringArray.length != 11) {\r
+ throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString);\r
+ }\r
+\r
+ //\r
+ // Remove blank space from these string and remove header string "0x"\r
+ //\r
+ for (index = 0; index < 11; index ++) {\r
+ splitStringArray[index] = splitStringArray[index].trim();\r
+ splitStringArray[index] = splitStringArray[index].substring(2, splitStringArray[index].length());\r
+ }\r
+\r
+ //\r
+ // Add heading '0' to normalize the string length\r
+ //\r
+ for (index = 3; index < 11; index ++) {\r
+ chLen = splitStringArray[index].length();\r
+ for (chIndex = 0; chIndex < 2 - chLen; chIndex ++) {\r
+ splitStringArray[index] = "0" + splitStringArray[index];\r
+ }\r
+ }\r
+\r
+ //\r
+ // construct the final GuidNamingConvention string\r
+ //\r
+ temp = String.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",\r
+ splitStringArray[0],\r
+ splitStringArray[1],\r
+ splitStringArray[2],\r
+ splitStringArray[3],\r
+ splitStringArray[4],\r
+ splitStringArray[5],\r
+ splitStringArray[6],\r
+ splitStringArray[7],\r
+ splitStringArray[8],\r
+ splitStringArray[9],\r
+ splitStringArray[10]);\r
+ uuidString = temp;\r
+ }\r
+\r
+ return UUID.fromString(uuidString);\r
+ }\r
+}\r
+\r