--- /dev/null
+/** @file\r
+ PCDAutoGenAction class.\r
+\r
+ This class is to manage how to generate the PCD information into Autogen.c and\r
+ Autogen.h.\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.build.pcd.action;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+\r
+import org.tianocore.build.FrameworkBuildTask;\r
+import org.tianocore.build.autogen.CommonDefinition;\r
+import org.tianocore.build.global.GlobalData;\r
+import org.tianocore.build.id.ModuleIdentification;\r
+import org.tianocore.common.logger.EdkLog;\r
+import org.tianocore.pcd.action.BuildAction;\r
+import org.tianocore.pcd.entity.MemoryDatabaseManager;\r
+import org.tianocore.pcd.entity.Token;\r
+import org.tianocore.pcd.entity.UsageIdentification;\r
+import org.tianocore.pcd.entity.UsageInstance;\r
+import org.tianocore.pcd.exception.BuildActionException;\r
+\r
+/**\r
+ This class is to manage how to generate the PCD information into Autogen.c\r
+ and Autogen.h.\r
+**/\r
+public class PCDAutoGenAction extends BuildAction {\r
+ ///\r
+ /// The reference of DBManager in GlobalData class.\r
+ ///\r
+ private MemoryDatabaseManager dbManager;\r
+\r
+ ///\r
+ /// The identification for a UsageInstance.\r
+ ///\r
+ private UsageIdentification usageId;\r
+\r
+ ///\r
+ /// Whether current autogen is for building library used by current module.\r
+ ///\r
+ private boolean isBuildUsedLibrary;\r
+\r
+ ///\r
+ /// One of PEI_PCD_DRIVER, DXE_PCD_DRIVER, NOT_PCD_DRIVER \r
+ /// \r
+ private CommonDefinition.PCD_DRIVER_TYPE pcdDriverType;\r
+\r
+ ///\r
+ /// The generated string for header file.\r
+ ///\r
+ private String hAutoGenString;\r
+\r
+ ///\r
+ /// The generated string for C code file.\r
+ ///\r
+ private String cAutoGenString;\r
+\r
+ ///\r
+ /// The name array of <PcdCoded> in a module.\r
+ ///\r
+ private String[] pcdNameArrayInMsa;\r
+\r
+ private UsageIdentification parentId = null;\r
+ /**\r
+ Set parameter moduleId\r
+\r
+ @param moduleName the module name parameter.\r
+ **/\r
+ public void setUsageId(UsageIdentification usageId) {\r
+ this.usageId = usageId;\r
+ }\r
+\r
+ /**\r
+ Set paramter pcdDriverType\r
+ \r
+ @param pcdDriverType the driver type for PCD\r
+ **/\r
+ public void setPcdDriverType(CommonDefinition.PCD_DRIVER_TYPE pcdDriverType) {\r
+ this.pcdDriverType = pcdDriverType;\r
+ }\r
+ /**\r
+ set isBuildUsedLibrary parameter.\r
+\r
+ @param isBuildUsedLibrary\r
+ **/\r
+ public void setIsBuildUsedLibrary(boolean isBuildUsedLibrary) {\r
+ this.isBuildUsedLibrary = isBuildUsedLibrary;\r
+ }\r
+\r
+ /**\r
+ set pcdNameArrayInMsa parameter.\r
+\r
+ @param pcdNameArrayInMsa\r
+ */\r
+ public void setPcdNameArrayInMsa(String[] pcdNameArrayInMsa) {\r
+ this.pcdNameArrayInMsa = pcdNameArrayInMsa;\r
+ }\r
+\r
+ /**\r
+ Get the output of generated string for header file.\r
+\r
+ @return the string of header file for PCD\r
+ **/\r
+ public String getHAutoGenString() {\r
+ return hAutoGenString;\r
+ }\r
+\r
+ /**\r
+ Get the output of generated string for C Code file.\r
+\r
+ @return the string of C code file for PCD\r
+ **/\r
+ public String getCAutoGenString() {\r
+ return cAutoGenString;\r
+ }\r
+\r
+\r
+ /**\r
+ Construct function\r
+\r
+ This function mainly initialize some member variable.\r
+\r
+ @param moduleId the identification for module\r
+ @param arch the architecture for module\r
+ @param isBuildUsedLibary Is the current module library.\r
+ @param pcdNameArrayInMsa the pcd name array got from MSA file.\r
+ @param pcdDriverType one of PEI_PCD_DRIVER, DXE_PCD_DRIVER,\r
+ NOT_PCD_DRIVER\r
+ **/\r
+ public PCDAutoGenAction(ModuleIdentification moduleId,\r
+ String arch,\r
+ boolean isBuildUsedLibrary,\r
+ String[] pcdNameArrayInMsa,\r
+ CommonDefinition.PCD_DRIVER_TYPE pcdDriverType,\r
+ ModuleIdentification parentId) {\r
+ dbManager = null;\r
+ hAutoGenString = "";\r
+ cAutoGenString = "";\r
+\r
+ setUsageId(new UsageIdentification(moduleId.getName(),\r
+ moduleId.getGuid(),\r
+ moduleId.getPackage().getName(),\r
+ moduleId.getPackage().getGuid(),\r
+ arch,\r
+ moduleId.getVersion(),\r
+ moduleId.getModuleType()));\r
+ if (parentId != null) {\r
+ this.parentId = new UsageIdentification(parentId.getName(),\r
+ parentId.getGuid(),\r
+ parentId.getPackage().getName(),\r
+ parentId.getPackage().getGuid(),\r
+ arch,\r
+ parentId.getVersion(),\r
+ parentId.getModuleType());\r
+ }\r
+ setIsBuildUsedLibrary(isBuildUsedLibrary);\r
+ setPcdNameArrayInMsa(pcdNameArrayInMsa);\r
+ setPcdDriverType(pcdDriverType);\r
+ }\r
+\r
+ /**\r
+ Override function: check the parameter for action class.\r
+\r
+ @throws BuildActionException Bad parameter.\r
+ **/\r
+ public void checkParameter() {\r
+ }\r
+\r
+ /**\r
+ Core execution function for this action class.\r
+\r
+ All PCD information of this module comes from memory dabase. The collection\r
+ work should be done before this action execution.\r
+ Currently, we should generated all PCD information(maybe all dynamic) as array\r
+ in Pei emulated driver for simulating PCD runtime database.\r
+\r
+ @throws BuildActionException Failed to execute this aciton class.\r
+ **/\r
+ public void performAction() {\r
+ EdkLog.log(EdkLog.EDK_DEBUG, "Starting PCDAutoGenAction to generate autogen.h and autogen.c!...");\r
+\r
+ dbManager = GlobalData.getPCDMemoryDBManager();\r
+\r
+ if(dbManager.getDBSize() == 0) {\r
+ return;\r
+ }\r
+\r
+ EdkLog.log(EdkLog.EDK_DEBUG, "PCD memory database contains " + dbManager.getDBSize() + " PCD tokens.");\r
+\r
+ generateAutogenForModule();\r
+ }\r
+\r
+ /**\r
+ Generate the autogen string for a common module.\r
+\r
+ All PCD information of this module comes from memory dabase. The collection\r
+ work should be done before this action execution.\r
+ **/\r
+ private void generateAutogenForModule()\r
+ {\r
+ int index, index2;\r
+ List<UsageInstance> usageInstanceArray, usageContext;\r
+ String[] guidStringArray = null;\r
+ String guidStringCName = null;\r
+ String guidString = null;\r
+ String moduleName = usageId.moduleName;\r
+ UsageInstance usageInstance = null;\r
+ boolean found = false;\r
+\r
+ usageInstanceArray = null;\r
+ \r
+ if (FrameworkBuildTask.multithread) {\r
+ if (parentId == null) {\r
+ usageInstanceArray = dbManager.getUsageInstanceArrayById(usageId);\r
+ } else if ((pcdNameArrayInMsa != null) && (pcdNameArrayInMsa.length > 0)) {\r
+ usageContext = dbManager.getUsageInstanceArrayById(parentId);\r
+ //\r
+ // For building library package, although all module are library, but PCD entries of\r
+ // these library should be used to autogen.\r
+ //\r
+ if (usageContext == null) {\r
+ usageInstanceArray = dbManager.getUsageInstanceArrayById(usageId);\r
+ } else {\r
+ usageInstanceArray = new ArrayList<UsageInstance>();\r
+\r
+ //\r
+ // Try to find all PCD defined in library's PCD in all <PcdEntry> in module's\r
+ // <ModuleSA> in FPD file.\r
+ //\r
+ for (index = 0; index < pcdNameArrayInMsa.length; index++) {\r
+ found = false;\r
+ for (index2 = 0; index2 < usageContext.size(); index2 ++) {\r
+ if (pcdNameArrayInMsa[index].equalsIgnoreCase(usageContext.get(index2).parentToken.cName)) {\r
+ usageInstanceArray.add(usageContext.get(index2));\r
+ found = true;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (!found) {\r
+ //\r
+ // All library's PCD should instanted in module's <ModuleSA> who\r
+ // use this library instance. If not, give errors.\r
+ //\r
+ throw new BuildActionException (String.format("Module %s using library instance %s; the PCD %s " +\r
+ "is required by this library instance, but can not be found " +\r
+ "in the %s's <ModuleSA> in the FPD file!",\r
+ MemoryDatabaseManager.CurrentModuleName,\r
+ moduleName,\r
+ pcdNameArrayInMsa[index],\r
+ MemoryDatabaseManager.CurrentModuleName\r
+ ));\r
+ }\r
+ }\r
+ }\r
+ }\r
+ } else {\r
+ if (!isBuildUsedLibrary) {\r
+ usageInstanceArray = dbManager.getUsageInstanceArrayById(usageId);\r
+ MemoryDatabaseManager.UsageInstanceContext = usageInstanceArray;\r
+ MemoryDatabaseManager.CurrentModuleName = moduleName;\r
+ } else if ((pcdNameArrayInMsa != null) && (pcdNameArrayInMsa.length > 0)) {\r
+ usageContext = MemoryDatabaseManager.UsageInstanceContext;\r
+ //\r
+ // For building library package, although all module are library, but PCD entries of\r
+ // these library should be used to autogen.\r
+ //\r
+ if (usageContext == null) {\r
+ usageInstanceArray = dbManager.getUsageInstanceArrayById(usageId);\r
+ } else {\r
+ usageInstanceArray = new ArrayList<UsageInstance>();\r
+ \r
+ //\r
+ // Try to find all PCD defined in library's PCD in all <PcdEntry> in module's\r
+ // <ModuleSA> in FPD file.\r
+ //\r
+ for (index = 0; index < pcdNameArrayInMsa.length; index++) {\r
+ found = false;\r
+ for (index2 = 0; index2 < usageContext.size(); index2 ++) {\r
+ if (pcdNameArrayInMsa[index].equalsIgnoreCase(usageContext.get(index2).parentToken.cName)) {\r
+ usageInstanceArray.add(usageContext.get(index2));\r
+ found = true;\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if (!found) {\r
+ //\r
+ // All library's PCD should instanted in module's <ModuleSA> who\r
+ // use this library instance. If not, give errors.\r
+ //\r
+ throw new BuildActionException (String.format("Module %s using library instance %s; the PCD %s " +\r
+ "is required by this library instance, but can not be found " +\r
+ "in the %s's <ModuleSA> in the FPD file!",\r
+ MemoryDatabaseManager.CurrentModuleName,\r
+ moduleName,\r
+ pcdNameArrayInMsa[index],\r
+ MemoryDatabaseManager.CurrentModuleName\r
+ ));\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ if (usageInstanceArray == null) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Generate all PCD entry for a module.\r
+ //\r
+ for(index = 0; index < usageInstanceArray.size(); index ++) {\r
+ usageInstance = usageInstanceArray.get(index);\r
+ //\r
+ // Before generate any PCD information into autogen.h/autogen.c for a module,\r
+ // generate TokenSpaceGuid array variable firstly. For every dynamicEx type\r
+ // PCD in this module the token, they are all reference to TokenSpaceGuid\r
+ // array.\r
+ //\r
+ if (usageInstanceArray.get(index).modulePcdType == Token.PCD_TYPE.DYNAMIC_EX) {\r
+ guidStringArray = usageInstance.parentToken.tokenSpaceName.split("-");\r
+ guidStringCName = "_gPcd_TokenSpaceGuid_" +\r
+ usageInstance.parentToken.tokenSpaceName.replaceAll("-", "_");\r
+ guidString = String.format("{ 0x%s, 0x%s, 0x%s, {0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s}}",\r
+ guidStringArray[0],\r
+ guidStringArray[1],\r
+ guidStringArray[2],\r
+ (guidStringArray[3].substring(0, 2)),\r
+ (guidStringArray[3].substring(2, 4)),\r
+ (guidStringArray[4].substring(0, 2)),\r
+ (guidStringArray[4].substring(2, 4)),\r
+ (guidStringArray[4].substring(4, 6)),\r
+ (guidStringArray[4].substring(6, 8)),\r
+ (guidStringArray[4].substring(8, 10)),\r
+ (guidStringArray[4].substring(10, 12)));\r
+\r
+ Pattern pattern = Pattern.compile("(" + guidStringCName + ")+?");\r
+ Matcher matcher = pattern.matcher(cAutoGenString + " ");\r
+ //\r
+ // Find whether this guid array variable has been generated into autogen.c\r
+ // For different DyanmicEx pcd token who use same token space guid, the token space\r
+ // guid array should be only generated once.\r
+ //\r
+ if (!matcher.find()) {\r
+ hAutoGenString += String.format("extern EFI_GUID %s;\r\n", guidStringCName);\r
+ if (!isBuildUsedLibrary) {\r
+ cAutoGenString += String.format("GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID %s = %s;\r\n",\r
+ guidStringCName,\r
+ guidString);\r
+ }\r
+ }\r
+ }\r
+\r
+ usageInstance.generateAutoGen(isBuildUsedLibrary);\r
+ //\r
+ // For every PCD entry for this module(usage instance), autogen string would\r
+ // be appand.\r
+ //\r
+ hAutoGenString += usageInstance.getHAutogenStr() + "\r\n";\r
+ cAutoGenString += usageInstance.getCAutogenStr();\r
+ }\r
+\r
+ if (pcdDriverType == CommonDefinition.PCD_DRIVER_TYPE.PEI_PCD_DRIVER) {\r
+ hAutoGenString += MemoryDatabaseManager.PcdPeimHString;\r
+ cAutoGenString += MemoryDatabaseManager.PcdPeimCString;\r
+ } else if (pcdDriverType == CommonDefinition.PCD_DRIVER_TYPE.DXE_PCD_DRIVER) {\r
+ hAutoGenString += MemoryDatabaseManager.PcdDxeHString;\r
+ cAutoGenString += MemoryDatabaseManager.PcdDxeCString;\r
+ }\r
+ }\r
+}\r