X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=Tools%2FJava%2FSource%2FPcdTools%2Forg%2Ftianocore%2Fpcd%2Faction%2FPlatformPcdPreprocessAction.java;fp=Tools%2FJava%2FSource%2FPcdTools%2Forg%2Ftianocore%2Fpcd%2Faction%2FPlatformPcdPreprocessAction.java;h=ee91f2a8e8aaede47fcdc3207585f96ef2f2de54;hp=0000000000000000000000000000000000000000;hb=feccee87a78e68d575dbdf44b34ca0cb5a21ea8d;hpb=214b0d1914b48d651b25e58f321ddb77a46903b8 diff --git a/Tools/Java/Source/PcdTools/org/tianocore/pcd/action/PlatformPcdPreprocessAction.java b/Tools/Java/Source/PcdTools/org/tianocore/pcd/action/PlatformPcdPreprocessAction.java new file mode 100644 index 0000000000..ee91f2a8e8 --- /dev/null +++ b/Tools/Java/Source/PcdTools/org/tianocore/pcd/action/PlatformPcdPreprocessAction.java @@ -0,0 +1,992 @@ +/** @file + PlatformPcdPreprocessAction class. + + The abstract parent class PlatformPcdPreprocessAction, This class is to collect platform's + pcd build information from fpd file. + This class will be extended by building tools and wizard tools. + +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.pcd.action; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions; +import org.tianocore.PcdBuildDefinitionDocument.PcdBuildDefinition; +import org.tianocore.pcd.entity.*; +import org.tianocore.pcd.entity.Token; +import org.tianocore.pcd.entity.MemoryDatabaseManager; +import org.tianocore.pcd.exception.PlatformPcdPreprocessException; + +/** + The abstract parent class PlatformPcdPreprocessAction, This class is to collect platform's + pcd build information from fpd file. + This class will be extended by building tools and wizard tools. + +**/ +public abstract class PlatformPcdPreprocessAction { + /// + /// PCD memory database + /// + private MemoryDatabaseManager pcdDbManager; + + /// + /// Errors string when perform preprocess + /// + private String errorString; + + /// + /// the count of errors when perform preprocess + /// + private int errorCount; + + /** + Default contructor function + **/ + public PlatformPcdPreprocessAction() { + pcdDbManager = null; + errorString = null; + errorCount = 0; + } + + /** + Set parameter pcdDbManager + + @param pcdDbManager + **/ + public void setPcdDbManager(MemoryDatabaseManager pcdDbManager) { + this.pcdDbManager = pcdDbManager; + } + + /** + Get parameter pcdDbManager + + @return MemoryDatabaseManager + **/ + public MemoryDatabaseManager getPcdDbManager() { + return pcdDbManager; + } + + /** + Abstract function: retrieve module information from FPD file. + + In building environement, this function will be implementated by FpdParserTask. + + @return List the component array. + @throws PlatformPcdPreprocessException get all modules in in FPD file. + + **/ + public abstract List getComponentsFromFpd() + throws PlatformPcdPreprocessException; + + /** + Abstract function to get GUID string from SPD file. + + In building evnironment, this function will be implementated by GlobaData. + + @param guidCName the CName of GUID + + @return String Guid information from SPD file. + @throws PlatformPcdPreprocessException + Fail to get Guid information from SPD file. + **/ + public abstract String getGuidInfoFromSpd(String guidCName) throws PlatformPcdPreprocessException; + + /** + Abstract function: Verification the PCD data. + + In different environment, such as building environment and wizard environment, + it has different implementation according to optimization. + + @param cName The token name + @param moduleName The module who use this PCD token + @param datum The PCD's datum + @param datumType The PCD's datum type + @param maxDatumSize The max size for PCD's Datum. + + @return String exception strings. + + **/ + public abstract String verifyDatum(String cName, String moduleName, String datum, + Token.DATUM_TYPE datumType, int maxDatumSize); + + /** + Abstract function: Get dynamic information for a token + + @param token + @param moduleName + + @return DynamicPcdBuildDefinitions.PcdBuildData + **/ + public abstract DynamicPcdBuildDefinitions.PcdBuildData + getDynamicInfoFromFpd(Token token, + String moduleName) + throws PlatformPcdPreprocessException; + + /** + Abstract function: Get all dynamic PCD information from FPD file. + + @return List All DYNAMIC PCD list in in FPD file. + @throws PlatformPcdPreprocessBuildException Failure to get dynamic information list. + + **/ + public abstract List + getAllDynamicPcdInfoFromFpd() + throws PlatformPcdPreprocessException; + + /** + Return the error string after preprocess + + @return String error string + **/ + public String getErrorString() { + return errorString; + } + + public void putError(String error) { + if (errorString == null) { + errorString = "### ERROR[" + errorCount + "] ###\r\n" + error + "\r\n"; + } else { + errorString += "### ERROR[" + errorCount + "] ###\r\n" + error + "\r\n"; + } + + errorCount++; + } + + /** + Collect all PCD information from FPD file into PCD memory database. + + **/ + public void initPcdMemoryDbWithPlatformInfo() + throws PlatformPcdPreprocessException { + int index; + int pcdIndex; + List pcdBuildDataArray = new ArrayList(); + PcdBuildDefinition.PcdData pcdBuildData; + Token token = null; + List modules; + String primaryKey; + String exceptionString; + UsageInstance usageInstance; + Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; + Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN; + long tokenNumber; + String moduleName; + String datum; + int maxDatumSize; + String tokenSpaceStrRet; + ModulePcdInfoFromFpd curModule; + + // + // ---------------------------------------------- + // 1), Get all from FPD file. + // ---------------------------------------------- + // + modules = getComponentsFromFpd(); + + if (modules == null) { + throw new PlatformPcdPreprocessException( + "No modules found in the FPD file.\nPlease check whether there are elements in in the FPD file!"); + } + + // + // ------------------------------------------------------------------- + // 2), Loop all modules to process for each module. + // ------------------------------------------------------------------- + // + for (index = 0; index < modules.size(); index++) { + curModule = modules.get(index); + + // + // It is legal for a module does not contains ANY pcd build definitions. + // + if (curModule.pcdBuildDefinition == null) { + continue; + } + + pcdBuildDataArray = curModule.pcdBuildDefinition.getPcdDataList(); + moduleName = curModule.usageId.moduleName; + + // + // ---------------------------------------------------------------------- + // 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); + + tokenSpaceStrRet = getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName()); + + if (tokenSpaceStrRet == null) { + putError("Failed to get Token Space Guid for token " + pcdBuildData.getCName() + + " from any SPD file. You must have an for this Token Space Guid!"); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + + primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(), tokenSpaceStrRet); + 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("In FPD file, for PCD %s in module %s, the PCD type is FEATURE_FLAG but "+ + "datum type for this PCD entry is not BOOLEAN!", + pcdBuildData.getCName(), + moduleName); + putError(exceptionString); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + + // + // ------------------------------------------------------------------------------------------- + // 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("In the FPD file, there is no value for PCD entry %s in module %s!", + pcdBuildData.getCName(), + moduleName); + putError(exceptionString); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + + // + // Check whether the datum size is matched datum type. + // + if ((exceptionString = verifyDatum(pcdBuildData.getCName(), + moduleName, + datum, + datumType, + maxDatumSize)) != null) { + putError(exceptionString); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + } + + // + // --------------------------------------------------------------------------------- + // 2.1.2), Create token or update token information for current anaylized PCD data. + // --------------------------------------------------------------------------------- + // + if (pcdDbManager.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 = pcdDbManager.getTokenByKey(primaryKey); + + // + // checking for DatumType, DatumType should be unique for one PCD used in different + // modules. + // + if (token.datumType != datumType) { + exceptionString = String.format("In the FPD file, the datum type of the PCD entry %s is %s, which is different from %s which was previously defined!", + pcdBuildData.getCName(), + pcdBuildData.getDatumType().toString(), + Token.getStringOfdatumType(token.datumType)); + putError(exceptionString); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + + // + // Check token number is valid + // + if (tokenNumber != token.tokenNumber) { + exceptionString = String.format("In the FPD file, the token number of PCD entry %s in module %s is different from the same PCD entry in other modules!", + pcdBuildData.getCName(), + moduleName); + putError(exceptionString); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + + // + // 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("In the FPD file, for PCD entry %s in module %s, you defined dynamic or non-dynamic PCD type which"+ + " is different from other module's definition.", + token.cName, + moduleName); + putError(exceptionString); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + + if (token.isDynamicPCD) { + if ((maxDatumSize != 0) && + (maxDatumSize != token.datumSize)){ + exceptionString = String.format("In the FPD file, for dynamic PCD %s in module %s, the max datum size is %d which "+ + "is different than %d defined in !", + token.cName, + moduleName, + maxDatumSize, + token.datumSize); + putError(exceptionString); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + } + + } else { + // + // If the token is not in database, create a new token instance and add + // a usage instance into this token in database. + // + tokenSpaceStrRet = getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName()); + + if (tokenSpaceStrRet == null) { + putError("Failed to get the Token Space Guid for token" + token.cName + + " from any SPD file. You must have a for this Token Space Guid!"); + // + // Do not break preprocess, continues to analysis. + // All errors will be summary to be shown. + // + continue; + } + + token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet); + + 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. + // + if (null == updateDynamicInformation(moduleName, + token, + datum, + maxDatumSize)) { + continue; + } + } + + pcdDbManager.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, + curModule.usageId, + pcdType, + datum, + maxDatumSize); + if (!token.addUsageInstance(usageInstance)) { + putError(String.format("PCD %s for module %s(%s) already exists in the database.\nPlease check all PCD build entries "+ + "in the %s module's section to make sure there are no duplicated definitions in the FPD file!", + token.cName, + curModule.usageId.moduleGuid, + moduleName, + moduleName)); + continue; + } + } + } + + // + // ------------------------------------------------ + // 3), Add unreference dynamic_Ex pcd token into Pcd database. + // ------------------------------------------------ + // + List tokenArray = getUnreferencedDynamicPcd(); + if (tokenArray != null) { + for (index = 0; index < tokenArray.size(); index++) { + pcdDbManager.addTokenToDatabase(tokenArray.get(index).getPrimaryKeyString(), + tokenArray.get(index)); + } + } + } + + /** + 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 PlatformPcdPreprocessException { + int index = 0; + int offset; + String exceptionString = null; + SkuInstance skuInstance = null; + String temp; + boolean hasSkuId0 = false; + 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("In the FPD file, the Dynamic PCD %s is used by module %s.\n" + + "However, there is no dynamic information in the " + + "section of the FPD file. This section is required!", + token.cName, + moduleName); + putError(exceptionString); + return null; + } + + token.datumSize = dynamicInfo.getMaxDatumSize(); + + exceptionString = verifyDatum(token.cName, + moduleName, + null, + token.datumType, + token.datumSize); + if (exceptionString != null) { + throw new PlatformPcdPreprocessException(exceptionString); + } + + if ((maxDatumSize != 0) && + (maxDatumSize != token.datumSize)) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s, the datum size in module %s is %d, but "+ + "the datum size in is %d, they do not match!", + token.cName, + moduleName, + maxDatumSize, + dynamicInfo.getMaxDatumSize()); + putError(exceptionString); + return null; + } + tokenNumber = Long.decode(dynamicInfo.getToken().toString()); + if (tokenNumber != token.tokenNumber) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s, the token number in module %s is 0x%x, but "+ + "in the section, the token number is 0x%x, they do not match!", + token.cName, + moduleName, + token.tokenNumber, + tokenNumber); + putError(exceptionString); + return null; + } + + token.dynamicExTokenNumber = tokenNumber; + + skuInfoList = dynamicInfo.getSkuInfoList(); + + // + // Loop all sku data + // + for (index = 0; index < skuInfoList.size(); index++) { + skuInstance = new SkuInstance(); + // + // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value. + // + temp = skuInfoList.get(index).getSkuId().toString(); + skuInstance.id = Integer.decode(temp); + if (skuInstance.id == 0) { + hasSkuId0 = true; + } + // + // Judge whether is DefaultGroup at first, because most case is DefautlGroup. + // + if (skuInfoList.get(index).getValue() != null) { + skuInstance.value.setValue(skuInfoList.get(index).getValue().toString()); + if ((exceptionString = verifyDatum(token.cName, + null, + skuInfoList.get(index).getValue().toString(), + token.datumType, + token.datumSize)) != null) { + putError(exceptionString); + return null; + } + + 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("In the FPD file, for dynamic PCD %s in section in FPD "+ + "file, use of HII was defined, but there is no defined for SKU %d data!", + token.cName, + index); + putError(exceptionString); + return null; + } + + if (skuInfoList.get(index).getVariableOffset() == null) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s in section in FPD "+ + "file, use of HII was defined, but there is no defined for SKU %d data!", + token.cName, + index); + putError(exceptionString); + return null; + } + + if (skuInfoList.get(index).getHiiDefaultValue() == null) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s in section in FPD "+ + "file, use of HII was defined, but there is no defined for SKU %d data!", + token.cName, + index); + putError(exceptionString); + return null; + } + + 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 PlatformPcdPreprocessException(exceptionString); + } + + offset = Integer.decode(skuInfoList.get(index).getVariableOffset()); + if (offset > 0xFFFF) { + putError(String.format("In the FPD file, for dynamic PCD %s, the variable offset defined in SKU %d data "+ + "exceeds 64K, which is not allowed!", + token.cName, + index)); + return null; + } + + // + // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file. + // + variableGuidString = getGuidInfoFromSpd(skuInfoList.get(index).getVariableGuid().toString()); + if (variableGuidString == null) { + putError(String.format("In the FPD file, for dynamic PCD %s, the variable guid: %s cannot be found in any SPD file!", + token.cName, + skuInfoList.get(index).getVariableGuid().toString())); + return null; + } + 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), + skuInfoList.get(index).getVariableOffset(), + skuInfoList.get(index).getHiiDefaultValue().toString()); + token.skuData.add(skuInstance); + continue; + } + + if (skuInfoList.get(index).getVpdOffset() != null) { + skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset()); + token.skuData.add(skuInstance); + continue; + } + + exceptionString = String.format("In the FPD file, for dynamic PCD %s, the dynamic info must "+ + "be one of: 'DefaultGroup', 'HIIGroup', 'VpdGroup'.", + token.cName); + putError(exceptionString); + return null; + } + + if (!hasSkuId0) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s in , there is "+ + "no SKU ID = 0 data, which is required for every dynamic PCD", + token.cName); + putError(exceptionString); + return null; + } + + return token; + } + + /** + Get all dynamic PCD defined in which unreferenced by + any in FPD file. + + @return List Return PCD token + **/ + private List getUnreferencedDynamicPcd () throws PlatformPcdPreprocessException { + List tokenArray = new ArrayList(); + Token token = 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; + + dynamicPcdBuildDataArray = getAllDynamicPcdInfoFromFpd(); + if (dynamicPcdBuildDataArray == null) { + return null; + } + + for (index2 = 0; index2 < dynamicPcdBuildDataArray.size(); index2++) { + pcdBuildData = dynamicPcdBuildDataArray.get(index2); + tokenSpaceStrRet = getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName()); + + if (tokenSpaceStrRet == null) { + putError("Failed to get the Token Space Guid for token" + pcdBuildData.getCName()); + continue; + } + + primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(), + tokenSpaceStrRet); + + if (pcdDbManager.isTokenInDatabase(primaryKey)) { + continue; + } + + pcdType = Token.getPcdTypeFromString(pcdBuildData.getItemType().toString()); + if (pcdType != Token.PCD_TYPE.DYNAMIC_EX) { + putError(String.format("In the FPD file, it not allowed to define DYNAMIC PCD %s that is not used by any module", + pcdBuildData.getCName())); + continue; + } + + // + // Create new token for unreference dynamic PCD token + // + token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet); + 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) { + putError(exceptionString); + continue; + } + + skuInfoList = pcdBuildData.getSkuInfoList(); + + // + // Loop all sku data + // + for (index = 0; index < skuInfoList.size(); index++) { + skuInstance = new SkuInstance(); + // + // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value. + // + temp = skuInfoList.get(index).getSkuId().toString(); + skuInstance.id = Integer.decode(temp); + if (skuInstance.id == 0) { + hasSkuId0 = true; + } + // + // Judge whether is DefaultGroup at first, because most case is DefautlGroup. + // + if (skuInfoList.get(index).getValue() != null) { + skuInstance.value.setValue(skuInfoList.get(index).getValue().toString()); + if ((exceptionString = verifyDatum(token.cName, + null, + skuInfoList.get(index).getValue().toString(), + token.datumType, + token.datumSize)) != null) { + putError(exceptionString); + continue; + } + + 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("In the FPD file, for dynamic PCD %s in the section of the FPD "+ + "file, use of HII is defined, but there is no defined for SKU %d data!", + token.cName, + index); + putError(exceptionString); + continue; + } + + if (skuInfoList.get(index).getVariableOffset() == null) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s in the section of the FPD "+ + "file, use of HII is defined, but there is no defined for SKU %d data!", + token.cName, + index); + putError(exceptionString); + continue; + } + + if (skuInfoList.get(index).getHiiDefaultValue() == null) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s in the section of the FPD "+ + "file, use of HII is defined, but there is no defined for SKU %d data!", + token.cName, + index); + putError(exceptionString); + continue; + } + + 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) { + putError(exceptionString); + continue; + } + + offset = Integer.decode(skuInfoList.get(index).getVariableOffset()); + if (offset > 0xFFFF) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s, the variable offset defined in SKU %d data "+ + "exceeds 64K, which is not allowed!", + token.cName, + index); + putError(exceptionString); + continue; + } + + // + // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file. + // + variableGuidString = getGuidInfoFromSpd(skuInfoList.get(index).getVariableGuid().toString()); + if (variableGuidString == null) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s, the variable guid %s cannot be found in any SPD file!", + token.cName, + skuInfoList.get(index).getVariableGuid().toString()); + putError(exceptionString); + continue; + } + 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), + skuInfoList.get(index).getVariableOffset(), + skuInfoList.get(index).getHiiDefaultValue().toString()); + token.skuData.add(skuInstance); + continue; + } + + if (skuInfoList.get(index).getVpdOffset() != null) { + skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset()); + token.skuData.add(skuInstance); + continue; + } + + exceptionString = String.format("In the FPD file, for dynamic PCD %s, the dynamic info must "+ + "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.", + token.cName); + putError(exceptionString); + } + + if (!hasSkuId0) { + exceptionString = String.format("In the FPD file, for dynamic PCD %s in , there is "+ + "no SKU ID = 0 data, which is required for every dynamic PCD", + token.cName); + putError(exceptionString); + continue; + } + + tokenArray.add(token); + } + + return tokenArray; + } + + /** + 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 PlatformPcdPreprocessException { + 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 PlatformPcdPreprocessException ("Wrong format for GUID 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); + } +} +