From 878ddf1fc3540a715f63594ed22b6929e881afb4 Mon Sep 17 00:00:00 2001 From: bbahnsen Date: Fri, 21 Apr 2006 22:54:32 +0000 Subject: Initial import. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524 --- Tools/Source/GenBuild/GenBuild.tasks | 11 + Tools/Source/GenBuild/build.xml | 51 + .../GenBuild/org/tianocore/build/ExpandTask.java | 52 + .../GenBuild/org/tianocore/build/FfsProcess.java | 390 ++++ .../GenBuild/org/tianocore/build/FileProcess.java | 225 +++ .../GenBuild/org/tianocore/build/GenBuildTask.java | 1170 ++++++++++++ .../org/tianocore/build/OutputDirSetupTask.java | 190 ++ .../org/tianocore/build/autogen/AutoGen.java | 2006 ++++++++++++++++++++ .../tianocore/build/autogen/AutogenLibOrder.java | 306 +++ .../tianocore/build/autogen/CommonDefinition.java | 257 +++ .../build/fpd/FpdModuleIdentification.java | 131 ++ .../org/tianocore/build/fpd/FpdParserTask.java | 808 ++++++++ .../org/tianocore/build/global/DpFile.java | 129 ++ .../org/tianocore/build/global/DpFileList.java | 50 + .../org/tianocore/build/global/GlobalData.java | 637 +++++++ .../org/tianocore/build/global/GlobalShare.java | 178 ++ .../build/global/LibBuildFileGenerator.java | 412 ++++ .../build/global/ModuleIdentification.java | 55 + .../org/tianocore/build/global/OnDependency.java | 121 ++ .../org/tianocore/build/global/OutputManager.java | 176 ++ .../tianocore/build/global/OverrideProcess.java | 354 ++++ .../GenBuild/org/tianocore/build/global/Spd.java | 414 ++++ .../tianocore/build/global/SurfaceAreaParser.java | 218 +++ .../tianocore/build/global/SurfaceAreaQuery.java | 1109 +++++++++++ .../org/tianocore/build/global/VariableTask.java | 71 + .../tianocore/build/pcd/action/ActionMessage.java | 129 ++ .../tianocore/build/pcd/action/BuildAction.java | 114 ++ .../build/pcd/action/CollectPCDAction.java | 669 +++++++ .../build/pcd/action/PCDAutoGenAction.java | 452 +++++ .../build/pcd/action/ShowPCDDatabaseAction.java | 130 ++ .../org/tianocore/build/pcd/action/UIAction.java | 83 + .../build/pcd/entity/MemoryDatabaseManager.java | 306 +++ .../tianocore/build/pcd/entity/SkuInstance.java | 40 + .../org/tianocore/build/pcd/entity/Token.java | 641 +++++++ .../tianocore/build/pcd/entity/UsageInstance.java | 471 +++++ .../build/pcd/exception/BuildActionException.java | 33 + .../build/pcd/exception/EntityException.java | 31 + .../tianocore/build/pcd/exception/UIException.java | 31 + .../tianocore/build/pcd/ui/PCDDatabaseFrame.java | 184 ++ .../tianocore/build/toolchain/ConfigReader.java | 218 +++ .../build/toolchain/ToolChainFactory.java | 529 ++++++ .../tianocore/build/toolchain/ToolChainTask.java | 60 + 42 files changed, 13642 insertions(+) create mode 100644 Tools/Source/GenBuild/GenBuild.tasks create mode 100644 Tools/Source/GenBuild/build.xml create mode 100644 Tools/Source/GenBuild/org/tianocore/build/ExpandTask.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/FileProcess.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/GenBuildTask.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/OutputDirSetupTask.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/autogen/AutoGen.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/autogen/CommonDefinition.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/fpd/FpdModuleIdentification.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/DpFile.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/DpFileList.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/GlobalData.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/GlobalShare.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/LibBuildFileGenerator.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/ModuleIdentification.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/OutputManager.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/OverrideProcess.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/Spd.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaParser.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaQuery.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/global/VariableTask.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/action/ActionMessage.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/action/BuildAction.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/action/PCDAutoGenAction.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/action/ShowPCDDatabaseAction.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/action/UIAction.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/entity/MemoryDatabaseManager.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/entity/SkuInstance.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/entity/Token.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/entity/UsageInstance.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/exception/BuildActionException.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/exception/EntityException.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/exception/UIException.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/pcd/ui/PCDDatabaseFrame.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/toolchain/ConfigReader.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainFactory.java create mode 100644 Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainTask.java (limited to 'Tools/Source/GenBuild') diff --git a/Tools/Source/GenBuild/GenBuild.tasks b/Tools/Source/GenBuild/GenBuild.tasks new file mode 100644 index 0000000000..c767cfb1dd --- /dev/null +++ b/Tools/Source/GenBuild/GenBuild.tasks @@ -0,0 +1,11 @@ +FPDParser = org.tianocore.build.fpd.FpdParserTask +bl = org.tianocore.build.global.VariableTask +bf = org.tianocore.build.global.LibBuildFileGenerator +GenBuild = org.tianocore.build.GenBuildTask +ToolChainSetup = org.tianocore.build.toolchain.ToolChainTask +Expand = org.tianocore.build.ExpandTask +OutputDirSetup = org.tianocore.build.OutputDirSetupTask +OnDependency = org.tianocore.build.global.OnDependency +sourcefiles = org.tianocore.build.global.DpFileList +targetfiles = org.tianocore.build.global.DpFileList +file = org.tianocore.build.global.DpFile diff --git a/Tools/Source/GenBuild/build.xml b/Tools/Source/GenBuild/build.xml new file mode 100644 index 0000000000..38801f1495 --- /dev/null +++ b/Tools/Source/GenBuild/build.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/GenBuild/org/tianocore/build/ExpandTask.java b/Tools/Source/GenBuild/org/tianocore/build/ExpandTask.java new file mode 100644 index 0000000000..d3df8cf7a6 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/ExpandTask.java @@ -0,0 +1,52 @@ +/** @file + This file is ANT task Expand. + + Expand task is used to prepare ANT properties for further build. + +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; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +import org.tianocore.build.global.GlobalData; + +/** + Expand task is used to prepare ANT properties for further build. +

Current, prepare the dependent Library instance list for LIBS

+ + @since GenBuild 1.0 +**/ +public class ExpandTask extends Task { + + /** + Public construct method. It is necessary for ANT task. + **/ + public ExpandTask () { + } + + /** + ANT task's entry point, will be called after init(). + + Set LIBS for further build usage. + **/ + public void execute() throws BuildException { + + String[] libraries = GlobalData.getModuleLibrary(getProject().getProperty("BASE_NAME")); + String str = ""; + for (int i = 0; i < libraries.length; i ++){ + str += " " + GlobalData.getLibrary(libraries[i]); + } + getProject().setProperty("LIBS", str); + + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java b/Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java new file mode 100644 index 0000000000..dbbddba3db --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java @@ -0,0 +1,390 @@ +/** @file + File is FfsProcess class which is used to get the corresponding FFS layout + information for driver module. + +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; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Vector; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** +

FfsProcess is a class to find the corresponding FFS layout.

+ +

Property COMMON_FILE specified which file to search. The element + in COMMON_FILE is like following:

+ +
+    <Ffs type="APPLICATION">
+      <Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" />
+      <Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" />
+      <Sections EncapsulationType="Compress">
+        <Sections EncapsulationType="Guid-Defined">
+          <Section SectionType="EFI_SECTION_PE32" /> 
+          <Section SectionType="EFI_SECTION_USER_INTERFACE" />
+          <Section SectionType="EFI_SECTION_VERSION" /> 
+        </Sections>
+      </Sections>
+    </Ffs>
+  
+ + @since GenBuild 1.0 +**/ +public class FfsProcess { + + /// + /// Xml Document Node for corresponding FFS layout + /// + private Node ffs; + + /// + /// ANT script to call GenFfs + /// + private Element ffsNode = null; + + /// + /// Module base name + /// + private String basename; + + /// + /// Sections type: normal + /// + private static int MODE_NONE = 0; + + /// + /// Sections type: compress + /// + private static int MODE_COMPRESS = 1; + + /// + /// Sections type: guid-define + /// + private static int MODE_GUID_DEFINED = 2; + + /// + /// mapping from section type to section output file extension + /// + public static final String[][] sectionExt = { { "EFI_SECTION_FREEFORM_SUBTYPE_GUID", ".sec" }, + { "EFI_SECTION_VERSION", ".ver" }, + { "EFI_SECTION_USER_INTERFACE", ".ui" }, + { "EFI_SECTION_DXE_DEPEX", ".dpx" }, + { "EFI_SECTION_PEI_DEPEX", ".dpx" }, + { "EFI_SECTION_PE32", ".pe32" }, + { "EFI_SECTION_PIC", ".pic" }, + { "EFI_SECTION_TE", ".tes" }, + { "EFI_SECTION_RAW", ".sec" }, + { "EFI_SECTION_COMPRESSION", ".sec" }, + { "EFI_SECTION_GUID_DEFINED", ".sec" }, + { "EFI_SECTION_COMPATIBILITY16", ".sec" }, + { "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", ".sec" } }; + + /** + search in the type, if componentType is listed in type, return true; + otherwise return false. + + @param type a list supported component type separated by comma + @param componentType current module component type + @return whether componentType is one of type + **/ + private boolean isMatch(String type, String componentType) { + String[] items = type.split("[ \t]*,[ \t]*"); + for (int i = 0; i < items.length; i++) { + if (items[i].equalsIgnoreCase(componentType)) { + return true; + } + } + return false; + } + + /** + Find the corresponding FFS layout in COMMON_FILE if it + does not specify in module's surface area. + + @param buildType Current module's component type + @param project Ant project + @return whether find the corresponding FFS layout + @throws BuildException + If specified COMMON_FILE XML file is not valide. + **/ + public boolean initSections(String buildType, Project project) throws BuildException { + // + // first try to sections defined in PLATFORM level + // + + // + // if module specify sections itself, it's okay + // otherwise find sections from WORKSPACE default setting with + // ComponentType + // + if (ffs == null) { + File file = new File(project.getProperty("COMMON_FILE")); + // + // if common file is not existed, just return + // + if (!file.exists()) { + return false; + } + DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dombuilder = domfac.newDocumentBuilder(); + InputStream is = new FileInputStream(file); + Document doc = dombuilder.parse(is); + Element root = doc.getDocumentElement(); + NodeList items = root.getChildNodes(); + for (int i = 0; i < items.getLength(); i++) { + Node node = items.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + String nodeName = node.getNodeName(); + if (nodeName.equalsIgnoreCase("Ffs")) { + NamedNodeMap attr = node.getAttributes(); + Node type = attr.getNamedItem("type"); + if (type != null) { + if (isMatch(type.getTextContent(), buildType)) { + ffs = node; + return true; + } + } + } + } + } + } catch (Exception e) { + throw new BuildException("Parse COMMON_FILE [" + file.getPath() + "] error!\n" + e.getMessage()); + } + } + if (ffs == null) { + return false; + } else { + return true; + } + } + + /** + Recursive parse the FFS layout. Find out all section type here used. + + @param document BaseName_build.xml Xml document + @param basename Module's base name + @param guid Module's GUID + @param targetFilename Module's final file name (GUID-BaseName.APP) + @return List of section type + **/ + public String[] getGenSectionElements(Document document, String basename, String guid, String targetFilename) { + this.basename = basename; + if (ffs == null) { + return new String[0]; + } + Vector sectionList = new Vector(); + XmlCursor cursor = null; + try { + cursor = XmlObject.Factory.parse(ffs).newCursor(); + } catch (Exception e) { + return null; + } + int mode = MODE_NONE; + Element root = document.createElement("genffsfile"); + root.setAttribute("outputDir", "${BIN_DIR}"); + root.setAttribute("BaseName", basename); + root.setAttribute("fileGuid", guid); + cursor.toFirstChild(); + if (cursor.toFirstChild()) { + do { + if (cursor.getName().getLocalPart().equalsIgnoreCase("Attribute")) { + String name = cursor.getAttributeText(new QName("Name")); + String value = cursor.getAttributeText(new QName("Value")); + root.setAttribute(changeAttributeName(name), value); + } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) { + cursor.push(); + dealSection(mode, document, root, cursor, sectionList); + cursor.pop(); + } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) { + cursor.push(); + dealSections(mode, document, root, cursor, sectionList); + cursor.pop(); + } + } while (cursor.toNextSibling()); + } + // + // Check dependency + // + Element outofdateEle = document.createElement("OnDependency"); + Element sourceEle = document.createElement("sourcefiles"); + String[] result = new String[sectionList.size()]; + for (int i = 0; i < sectionList.size(); i++) { + result[i] = (String) sectionList.get(i); + Element pathEle = document.createElement("file"); + pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + + getSectionExt(result[i])); + sourceEle.appendChild(pathEle); + } + outofdateEle.appendChild(sourceEle); + Element targetEle = document.createElement("targetfiles"); + Element fileEle = document.createElement("file"); + fileEle.setAttribute("name", "${BIN_DIR}\\" + targetFilename); + targetEle.appendChild(fileEle); + outofdateEle.appendChild(targetEle); + Element sequentialEle = document.createElement("sequential"); + sequentialEle.appendChild(root); + outofdateEle.appendChild(sequentialEle); + ffsNode = outofdateEle; + return result; + } + + /** + Change the attribute name. For example: + +
+          Before change: FFS_ATTRIB_CHECKSUM 
+          After  change: ffsATTRIBCHECKSUM
+      
+ + @param name Original attribute name + @return Changed attribute name + **/ + private String changeAttributeName(String name) { + String[] strs = name.split("_"); + String str = strs[0].toLowerCase(); + for (int j = 1; j < strs.length; j++) { + str += strs[j]; + } + return str; + } + + /** + Recursively deal with Sections. If sections does not specify a type, then omit it. + + @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED) + @param doc Xml Document + @param root Root Node + @param cursor Current FFS layout cursor + @param list List of section type here used + **/ + private void dealSections(int mode, Document doc, Element root, XmlCursor cursor, Vector list) { + String type = cursor.getAttributeText(new QName("EncapsulationType")); + if (type == null) { + if (cursor.toFirstChild()) { + do { + if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) { + cursor.push(); + dealSection(mode, doc, root, cursor, list); + cursor.pop(); + } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) { + cursor.push(); + dealSections(mode, doc, root, cursor, list); + cursor.pop(); + } + } while (cursor.toNextSibling()); + } + return; + } + Element ele; + if (type.equalsIgnoreCase("COMPRESS")) { + mode = MODE_COMPRESS; + // + // + // + ele = doc.createElement("compress"); + ele.setAttribute("compressName", "dummy"); + } else { + mode = MODE_GUID_DEFINED; + // + // + // + ele = doc.createElement("tool"); + ele.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "Bin" + + File.separatorChar + "GenCRC32Section"); + ele.setAttribute("outputPath", "${DEST_DIR_OUTPUT}"); + } + if (cursor.toFirstChild()) { + do { + if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) { + cursor.push(); + dealSection(mode, doc, ele, cursor, list); + cursor.pop(); + } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) { + cursor.push(); + dealSections(mode, doc, ele, cursor, list); + cursor.pop(); + } + } while (cursor.toNextSibling()); + } + root.appendChild(ele); + } + + /** + Recursively deal with section. + + @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED) + @param doc Xml Document + @param root Root Node + @param cursor Current FFS layout cursor + @param list List of section type here used + **/ + private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector list) { + String type = cursor.getAttributeText(new QName("SectionType")); + list.addElement(type); + if (mode == MODE_GUID_DEFINED) { + // + // + // + Element ele = doc.createElement("input"); + ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type)); + root.appendChild(ele); + } else { + // + // + // + Element ele = doc.createElement("sectFile"); + ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type)); + root.appendChild(ele); + } + } + + /** + Get the corresponding section file suffix. + + @param type Section type + @return Corresponding section file extension + **/ + private String getSectionExt(String type) { + for (int i = 0; i < sectionExt.length; i++) { + if (sectionExt[i][0].equalsIgnoreCase(type)) { + return sectionExt[i][1]; + } + } + return ".sec"; + } + + /** + Return the ANT script to call GenFfs Tool. + + @return ANT script to call GenFfs Tool + **/ + public Element getFfsNode() { + return ffsNode; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/FileProcess.java b/Tools/Source/GenBuild/org/tianocore/build/FileProcess.java new file mode 100644 index 0000000000..87650af827 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/FileProcess.java @@ -0,0 +1,225 @@ +/** @file + File is FileProcess class which is used to generate ANT script to build + source files. + +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; + +import java.io.File; +import java.util.Set; + +import org.apache.tools.ant.Project; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** +

FileProcess is class to generate ANT script to build source + files.

+ +

If file does not specify file type, FileProcess will judge + by its extension. Following is the current supported extensions.

+ +
   
+          .c         |      C_Code
+          .asm       |      Assembly
+          .s         |      IPF_Assembly_Code
+          .h         |      Header
+          .lib       |      Static_Library
+          .i         |      IPF_PP_Code
+          .vfr       |      Vfr
+          .uni       |      Unicode
+          .dxs       |      Dependency_File
+          .bmp       |      Graphics
+          .efi       |      EFI
+  
+ + @since GenBuild 1.0 +**/ +public class FileProcess { + /// + /// The mapping information about source suffix, result suffix, file type. + /// + public final String[][] fileTypes = { { ".c", ".obj", "C_Code" }, { ".asm", ".obj", "Assembly" }, + { ".s", ".obj", "IPF_Assembly_Code" }, { ".h", "", "Header" }, + { ".lib", "", "Static_Library" }, { ".src", ".c", "" }, + { ".i", ".obj", "IPF_PP_Code" }, { ".vfr", ".obj", "Vfr" }, + { ".uni", "", "Unicode" }, { ".dxs", "", "Dependency_File" }, + { ".bmp", "", "Graphics" }, { ".efi", "", "EFI" } }; + + /// + /// Current ANT context. + /// + private Project project; + + /// + /// Current module's include pathes + /// + private Set includes; + + /// + /// Current source files. + /// + private Set sourceFiles; + + /// + /// Xml Document. + /// + private Document document; + + /// + /// The flag to ensure all unicode files build before others. + /// + private boolean unicodeFirst = true; + + /// + /// The flag present whether current module contains Unicode files or not. + /// + private boolean unicodeExist = false; + + /** + Initialize the project, includes, sourceFiles, document members. + + @param project ANT project + @param includes Module include pathes + @param sourceFiles Modules source files + @param document XML document + **/ + public void init(Project project, Set includes, Set sourceFiles, Document document) { + this.document = document; + this.includes = includes; + this.project = project; + this.sourceFiles = sourceFiles; + } + + /** + Parse file without file type. + + @param filename Source file name + @param root Root node + @param unicodeFirst whether build Unicode file firstly or not + **/ + public synchronized void parseFile(String filename, Node root, boolean unicodeFirst) { + this.unicodeFirst = unicodeFirst; + parseFile(filename, root); + } + + /** + Get whether current module contains Unicode files or not. + + @return Whether current module contains Unicode files or not + **/ + public boolean isUnicodeExist() { + return unicodeExist; + } + + /** + Parse file. + + @param filename Source file name + @param filetype Source file type + @param root Root node + @param unicodeFirst whether build Unicode file firstly or not + **/ + public synchronized void parseFile(String filename, String filetype, Node root, boolean unicodeFirst) { + this.unicodeFirst = unicodeFirst; + parseFile(filename, filetype, root); + } + + /** + Find out source file's type. + + @param filename Source file name + @param root Root node + **/ + public synchronized void parseFile(String filename, Node root) { + boolean flag = false; + for (int i = 0; i < fileTypes.length; i++) { + if (filename.toLowerCase().endsWith(fileTypes[i][0])) { + flag = true; + parseFile(filename, fileTypes[i][2], root); + } + } + if (!flag) { + System.out.println("Warning: File " + filename + " is not known from its suffix."); + } + } + + /** + Parse file. If flag unicodeFirst is true, then build all + unicode files firstly. + +

Note that AutoGen.c is processed specially. It's output path is always + ${DEST_DIR_OUTPUT}, others are ${DEST_DIR_OUTPUT} + and relative to module path.

+ + @param filename Source file name + @param filetype Source file type + @param root Root node + **/ + public synchronized void parseFile(String filename, String filetype, Node root) { + if (unicodeFirst) { + if ( ! filetype.equalsIgnoreCase("Unicode")){ + return ; + } + unicodeExist= true; + } else { + if (filetype.equalsIgnoreCase("Unicode")){ + return ; + } + } + sourceFiles.add(filename); + if (filetype.equalsIgnoreCase("Header")) { + return; + } + if (filetype.equalsIgnoreCase("IPF_PP_Code")) { + return; + } + String module_path = project.getProperty("MODULE_DIR"); + File moduleFile = new File(module_path); + File sourceFile = new File(filename); + // If source file is AutoGen.c, then Filepath is . + String sourceFilepath; + String sourceFilename; + if (sourceFile.getPath().endsWith("AutoGen.c")) { + sourceFilepath = "."; + sourceFilename = "AutoGen"; + filetype = "AUTOGEN"; + } else { + // sourceFile. + String str = sourceFile.getPath().substring(moduleFile.getPath().length() + 1); + int index = str.lastIndexOf(File.separatorChar); + sourceFilepath = "."; + if (index > 0) { + sourceFilepath = str.substring(0, index); + str = str.substring(index + 1); + } + sourceFilename = str; + index = str.lastIndexOf('.'); + if (index > 0) { + sourceFilename = str.substring(0, index); + } + } + // + Element ele = document.createElement("Build_" + filetype); + ele.setAttribute("FILEPATH", sourceFilepath); + ele.setAttribute("FILENAME", sourceFilename); + String[] includePaths = includes.toArray(new String[includes.size()]); + Element includesEle = document.createElement("EXTRA.INC"); + for (int i = 0; i < includePaths.length; i++) { + Element includeEle = document.createElement("includepath"); + includeEle.setAttribute("path", includePaths[i]); + includesEle.appendChild(includeEle); + } + ele.appendChild(includesEle); + root.appendChild(ele); + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/GenBuildTask.java b/Tools/Source/GenBuild/org/tianocore/build/GenBuildTask.java new file mode 100644 index 0000000000..2d91991b8a --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/GenBuildTask.java @@ -0,0 +1,1170 @@ +/** @file + This file is ANT task GenBuild. + + The file is used to parse a specified Module, and generate its build time + ANT script build.xml, then call the the ANT script to build the module. + +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; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Ant; +import org.apache.xmlbeans.XmlObject; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.tianocore.build.autogen.AutoGen; +import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.fpd.FpdParserTask; +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.OutputManager; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.toolchain.ToolChainFactory; +import org.tianocore.FilenameDocument; +import org.tianocore.MsaHeaderDocument; +import org.tianocore.MsaLibHeaderDocument; + +/** +

+ GenBuildTask is an ANT task that can be used in ANT build + system. The main function of this task is to parse module's surface area, + then generate the corresponding BaseName_build.xml (the real ANT + build script) and call this to build the module. +

+ +

+ The usage is (take module HelloWorld for example): +

+ +
+   <GenBuild baseName="HelloWorld" 
+             mbdFilename="${MODULE_DIR}/HelloWorld.mbd" 
+             msaFilename="${MODULE_DIR}/HelloWorld.msa"/>
+  
+ +

+ This task calls AutoGen to generate AutoGen.c and + AutoGen.h. The task also parses the development environment + configuration files, such as collecting package information, setting compiler + flags and so on. +

+ + + @since GenBuild 1.0 +**/ +public class GenBuildTask extends Task { + + /// + /// Module surface area file. + /// + File msaFilename; + + /// + /// Module build description file. + /// + File mbdFilename; + + /// + /// Module surface area information after overrided. + /// + public Map map = new HashMap(); + + /// + /// Module's base name. + /// + private String baseName; + + /// + /// Current build Arch, such as IA32, X64, IPF and so on. + /// + private String arch; + + /// + /// Module's GUID (Globally Unique Identifier). + /// + private String guid; + + /// + /// Module's component type, such as SEC, LIBRARY, BS_DRIVER and so on. + /// + private String componentType; + + /// + /// This value is used in build time. Override module's component type. When + /// search FFS (Sections information) in common file, buildtype instead of + /// component type. + /// + private String buildType; + + /// + /// List all required includes for current build module. + /// + public Set includes = new LinkedHashSet(); + + /// + /// List all libraries for current build module. + /// + public Set libraries = new LinkedHashSet(); + + /// + /// List all source files for current build module. + /// + public Set sourceFiles = new LinkedHashSet(); + + /// + /// Flag to identify what surface area files are specified. Current value is + /// NO_SA, ONLY_MSA, ONLY_LIBMSA, + /// MSA_AND_MBD or LIBMSA_AND_LIBMBD. + /// + /// @see org.tianocore.build.global.GlobaData + /// + private int flag = GlobalData.NO_SA; + + /// + /// The information at the header of build.xml. + /// + private String info = "====================================================================\n" + + "DO NOT EDIT \n" + + "File auto-generated by build utility\n" + + "\n" + + "Abstract:\n" + + "Auto-generated ANT build file for building of EFI Modules/Platforms\n" + + "====================================================================="; + + /** + Public construct method. It is necessary for ANT task. + **/ + public GenBuildTask() { + } + + /** + ANT task's entry point, will be called after init(). The main steps is described + as following: +
    +
  • Judge current build mode (MODULE | PACKAGE | PLATFORM). This step will execute + only once in whole build process;
  • +
  • Initialize global information (Framework DB, SPD files and all MSA files + listed in SPD). This step will execute only once in whole build process;
  • +
  • Restore some important ANT property. If current build is single module + build, here will set many default values;
  • +
  • Get the current module's overridded surface area information from + global data;
  • +
  • Set up the output directories, including BIN_DIR, DEST_DIR_OUTPUT and + DEST_DIR_DEBUG;
  • +
  • Get module dependent library instances and include pathes;
  • +
  • Judge whether current module is built. If yes, skip it;
  • +
  • Call AutoGen and PCD to generate AutoGen.c & AutoGen.h
  • +
  • Set up the compile flags;
  • +
  • Generate BaseName_build.xml;
  • +
  • Call to BaseName_build.xml, and build the current module.
  • +
+ +

Build is dependent on BuildMacro.xml which define many macro.

+ + @throws BuildException + From module build, exception from module surface area invalid. + **/ + public void execute() throws BuildException { + System.out.println("Module [" + baseName + "] start."); + OutputManager.update(getProject()); + GlobalData.initInfo("Tools" + File.separatorChar + "Conf" + File.separatorChar + "FrameworkDatabase.db", + getProject().getProperty("WORKSPACE_DIR")); + recallFixedProperties(); + arch = getProject().getProperty("ARCH"); + arch = arch.toUpperCase(); + map = GlobalData.getDoc(baseName); + // + // Initialize SurfaceAreaQuery + // + SurfaceAreaQuery.setDoc(map); + // + // Setup Output Management + // + String[] outdir = SurfaceAreaQuery.getOutputDirectory(); + OutputManager.update(getProject(), outdir[1], outdir[0]); + + updateIncludesAndLibraries(); + + if (GlobalData.isModuleBuilt(baseName, arch)) { + return; + } else { + GlobalData.registerBuiltModule(baseName, arch); + } + // + // Call AutoGen + // + AutoGen autogen = new AutoGen(getProject().getProperty("DEST_DIR_DEBUG"), baseName, arch); + autogen.genAutogen(); + // + // Update parameters + // + updateParameters(); + // + // Update flags like CC_FLAGS, LIB_FLAGS etc. + // + flagsSetup(); + GlobalData.addLibrary(baseName, getProject().getProperty("BIN_DIR") + File.separatorChar + baseName + ".lib"); + GlobalData.addModuleLibrary(baseName, libraries); + // + // If ComponentType is USER_DEFINED, + // then call the exist BaseName_build.xml directly. + // + if (buildType.equalsIgnoreCase("CUSTOM_BUILD")) { + System.out.println("Call user-defined " + baseName + "_build.xml"); + Ant ant = new Ant(); + ant.setProject(getProject()); + ant.setAntfile(getProject().getProperty("MODULE_DIR") + File.separatorChar + baseName + "_build.xml"); + ant.setInheritAll(true); + ant.init(); + ant.execute(); + return; + } + // + // Generate ${BASE_NAME}_build.xml file + // + System.out.println("Generate " + baseName + "_build.xml"); + genBuildFile(); + System.out.println("Call the " + baseName + "_build.xml"); + Ant ant = new Ant(); + ant.setProject(getProject()); + ant.setAntfile(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName + "_build.xml"); + ant.setInheritAll(true); + ant.init(); + ant.execute(); + } + + /** + Get the dependent library instances and include package name from + surface area, and initialize module include pathes. + + **/ + private void updateIncludesAndLibraries() { + List rawIncludes = SurfaceAreaQuery.getIncludePackageName(arch); + if (rawIncludes != null) { + Iterator iter = rawIncludes.iterator(); + while (iter.hasNext()) { + String packageName = (String) iter.next(); + includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName) + + File.separatorChar + "Include"); + includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName) + + File.separatorChar + "Include" + File.separatorChar + "${ARCH}"); + } + } + includes.add("${DEST_DIR_DEBUG}"); + List rawLibraries = SurfaceAreaQuery.getLibraryInstance(this.arch, CommonDefinition.AlwaysConsumed); + if (rawLibraries != null) { + Iterator iter = rawLibraries.iterator(); + while (iter.hasNext()) { + libraries.add((String) iter.next()); + } + } + normalize(); + } + + /** + Normalize all dependent library instance and include pathes' format. + + **/ + private void normalize() { + String[] includesArray = includes.toArray(new String[includes.size()]); + includes.clear(); + for (int i = 0; i < includesArray.length; i++) { + includes.add((new File(includesArray[i])).getPath()); + } + String[] librariesArray = libraries.toArray(new String[libraries.size()]); + libraries.clear(); + for (int i = 0; i < librariesArray.length; i++) { + libraries.add((new File(librariesArray[i])).getPath()); + } + } + + /** + Restore some important ANT property. If current build is single module + build, here will set many default values. + +

If current build is single module build, then the default ARCH + is IA32. Also set up the properties PACKAGE, + PACKAGE_DIR, TARGET and MODULE_DIR

+ +

Note that for package build, package name is stored in PLATFORM + and package directory is stored in PLATFORM_DIR.

+ + @see org.tianocore.build.global.OutputManager + **/ + private void recallFixedProperties() { + // + // If build is for module build + // + if (getProject().getProperty("PACKAGE_DIR") == null) { + ToolChainFactory toolChainFactory = new ToolChainFactory(getProject()); + toolChainFactory.setupToolChain(); + // + // PACKAGE PACKAGE_DIR ARCH (Default) COMMON_FILE BUILD_MACRO + // + if (getProject().getProperty("ARCH") == null) { + getProject().setProperty("ARCH", "IA32"); + } + String packageName = GlobalData.getPackageNameForModule(baseName); + getProject().setProperty("PACKAGE", packageName); + + String packageDir = GlobalData.getPackagePath(packageName); + getProject().setProperty("PACKAGE_DIR", + getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + packageDir); + + getProject().setProperty("TARGET", toolChainFactory.getCurrentTarget()); + + getProject().setProperty("MODULE_DIR", + getProject().replaceProperties(getProject().getProperty("MODULE_DIR"))); + } + if (OutputManager.PLATFORM != null) { + getProject().setProperty("PLATFORM", OutputManager.PLATFORM); + } + if (OutputManager.PLATFORM_DIR != null) { + getProject().setProperty("PLATFORM_DIR", OutputManager.PLATFORM_DIR); + } + } + + /** + The whole BaseName_build.xml is composed of seven part. +
    +
  • ANT properties;
  • +
  • Dependent module (dependent library instances in most case);
  • +
  • Source files;
  • +
  • Sections if module is not library;
  • +
  • Output (different for library module and driver module);
  • +
  • Clean;
  • +
  • Clean all.
  • +
+ + @throws BuildException + Error throws during BaseName_build.xml generating. + **/ + private void genBuildFile() throws BuildException { + FfsProcess fp = new FfsProcess(); + DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dombuilder = domfac.newDocumentBuilder(); + Document document = dombuilder.newDocument(); + Comment rootComment = document.createComment(info); + // + // create root element and its attributes + // + Element root = document.createElement("project"); + // + // root.setAttribute("name", base_name); + // + root.setAttribute("default", "main"); + root.setAttribute("basedir", "."); + // + // element for External ANT tasks + // + root.appendChild(document.createComment("Apply external ANT tasks")); + Element ele = document.createElement("taskdef"); + ele.setAttribute("resource", "frameworktasks.tasks"); + root.appendChild(ele); + ele = document.createElement("taskdef"); + ele.setAttribute("resource", "cpptasks.tasks"); + root.appendChild(ele); + ele = document.createElement("typedef"); + ele.setAttribute("resource", "cpptasks.types"); + root.appendChild(ele); + ele = document.createElement("taskdef"); + ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml"); + root.appendChild(ele); + // + // elements for Properties + // + root.appendChild(document.createComment("All Properties")); + ele = document.createElement("property"); + ele.setAttribute("name", "BASE_NAME"); + ele.setAttribute("value", baseName); + root.appendChild(ele); + // + // Generate the default target, + // which depends on init, sections and output target + // + root.appendChild(document.createComment("Default target")); + ele = document.createElement("target"); + ele.setAttribute("name", "main"); + ele.setAttribute("depends", "libraries, sourcefiles, sections, output"); + root.appendChild(ele); + // + // compile all source files + // + root.appendChild(document.createComment("Compile all dependency Library instances.")); + ele = document.createElement("target"); + ele.setAttribute("name", "libraries"); + // + // Parse all sourfiles but files specified in sections + // + applyLibraryInstance(document, ele); + root.appendChild(ele); + // + // compile all source files + // + root.appendChild(document.createComment("sourcefiles target")); + ele = document.createElement("target"); + ele.setAttribute("name", "sourcefiles"); + // + // Parse all sourfiles but files specified in sections + // + applyCompileElement(document, ele); + root.appendChild(ele); + // + // generate the init target + // main purpose is create all nessary pathes + // generate the sections target + // + root.appendChild(document.createComment("sections target")); + ele = document.createElement("target"); + ele.setAttribute("name", "sections"); + applySectionsElement(document, ele, fp); + root.appendChild(ele); + // + // generate the output target + // + root.appendChild(document.createComment("output target")); + ele = document.createElement("target"); + ele.setAttribute("name", "output"); + applyOutputElement(document, ele, fp); + root.appendChild(ele); + // + // generate the clean target + // + root.appendChild(document.createComment("clean target")); + ele = document.createElement("target"); + ele.setAttribute("name", "clean"); + applyCleanElement(document, ele); + root.appendChild(ele); + // + // generate the Clean All target + // + root.appendChild(document.createComment("Clean All target")); + ele = document.createElement("target"); + ele.setAttribute("name", "cleanall"); + applyDeepcleanElement(document, ele); + root.appendChild(ele); + // + // add the root element to the document + // + document.appendChild(rootComment); + document.appendChild(root); + // + // Prepare the DOM document for writing + // + Source source = new DOMSource(document); + // + // Prepare the output file + // + File file = new File(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName + + "_build.xml"); + // + // generate all directory path + // + (new File(file.getParent())).mkdirs(); + Result result = new StreamResult(file); + // + // Write the DOM document to the file + // + Transformer xformer = TransformerFactory.newInstance().newTransformer(); + xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + xformer.setOutputProperty(OutputKeys.INDENT, "yes"); + xformer.transform(source, result); + } catch (Exception ex) { + throw new BuildException("Module [" + baseName + "] generating build file failed.\n" + ex.getMessage()); + } + } + + /** + Generate the clean elements for BaseName_build.xml. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyCleanElement(Document document, Node root) { + String[] libinstances = libraries.toArray(new String[libraries.size()]); + for (int i = 0; i < libinstances.length; i++) { + File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml"); + + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", file.getPath()); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element ele = document.createElement("ant"); + ele.setAttribute("antfile", file.getPath()); + ele.setAttribute("inheritAll", "false"); + ele.setAttribute("target", libinstances[i] + "_clean"); + // + // Workspace_DIR + // + Element property = document.createElement("property"); + property.setAttribute("name", "WORKSPACE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}"); + ele.appendChild(property); + // + // Package Dir + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(libinstances[i])); + ele.appendChild(property); + // + // ARCH + // + property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", "${ARCH}"); + ele.appendChild(property); + // + // TARGET + // + property = document.createElement("property"); + property.setAttribute("name", "TARGET"); + property.setAttribute("value", "${TARGET}"); + ele.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i])); + ele.appendChild(property); + + elseEle.appendChild(ele); + ifEle.appendChild(elseEle); + root.appendChild(ifEle); + } + } + + /** + Generate the cleanall elements for BaseName_build.xml. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyDeepcleanElement(Document document, Node root) { + String[] libinstances = libraries.toArray(new String[libraries.size()]); + for (int i = 0; i < libinstances.length; i++) { + File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml"); + + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", file.getPath()); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element ele = document.createElement("ant"); + ele.setAttribute("antfile", file.getPath()); + ele.setAttribute("inheritAll", "false"); + ele.setAttribute("target", libinstances[i] + "_cleanall"); + // + // Workspace_DIR + // + Element property = document.createElement("property"); + property.setAttribute("name", "WORKSPACE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}"); + ele.appendChild(property); + // + // Package Dir + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(libinstances[i])); + ele.appendChild(property); + // + // ARCH + // + property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", "${ARCH}"); + ele.appendChild(property); + // + // TARGET + // + property = document.createElement("property"); + property.setAttribute("name", "TARGET"); + property.setAttribute("value", "${TARGET}"); + ele.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i])); + ele.appendChild(property); + + elseEle.appendChild(ele); + ifEle.appendChild(elseEle); + root.appendChild(ifEle); + } + } + + /** + Generate the dependent library instances elements for BaseName_build.xml. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyLibraryInstance(Document document, Node root) { + String[] libinstances = libraries.toArray(new String[libraries.size()]); + for (int i = 0; i < libinstances.length; i++) { + Element ele = document.createElement("ant"); + File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml"); + ele.setAttribute("antfile", file.getPath()); + ele.setAttribute("inheritAll", "false"); + ele.setAttribute("target", libinstances[i]); + // + // Workspace_DIR + // + Element property = document.createElement("property"); + property.setAttribute("name", "WORKSPACE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}"); + ele.appendChild(property); + // + // Package Dir + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(libinstances[i])); + ele.appendChild(property); + // + // ARCH + // + property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", "${ARCH}"); + ele.appendChild(property); + // + // TARGET + // + property = document.createElement("property"); + property.setAttribute("name", "TARGET"); + property.setAttribute("value", "${TARGET}"); + ele.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i])); + ele.appendChild(property); + root.appendChild(ele); + } + Element expand = document.createElement("Expand"); + root.appendChild(expand); + } + + /** + Generate the build source files elements for BaseName_build.xml. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyCompileElement(Document document, Node root) { + FileProcess fileProcess = new FileProcess(); + fileProcess.init(getProject(), includes, sourceFiles, document); + Node[] files = this.getSourceFiles(); + // + // Parse all unicode files + // + for (int i = 0; i < files.length; i++) { + String filetype = getFiletype(files[i]); + if (filetype != null) { + fileProcess.parseFile(getFilename(files[i]), filetype, root, true); + } else { + fileProcess.parseFile(getFilename(files[i]), root, true); + } + } + if (fileProcess.isUnicodeExist()) { + Element ele = document.createElement("Build_Unicode_Database"); + ele.setAttribute("FILEPATH", "."); + ele.setAttribute("FILENAME", "${BASE_NAME}"); + root.appendChild(ele); + } + + // + // Parse AutoGen.c & AutoGen.h + // + if (!baseName.equalsIgnoreCase("Shell")) { + fileProcess.parseFile(getProject().getProperty("DEST_DIR_DEBUG") + File.separatorChar + "AutoGen.c", root, + false); + } + // + // Parse all source files + // + for (int i = 0; i < files.length; i++) { + String filetype = getFiletype(files[i]); + if (filetype != null) { + fileProcess.parseFile(getFilename(files[i]), filetype, root, false); + } else { + fileProcess.parseFile(getFilename(files[i]), root, false); + } + } + // + // root.appendChild(parallelEle); + // + Iterator iter = sourceFiles.iterator(); + String str = ""; + while (iter.hasNext()) { + str += " " + (String) iter.next(); + } + getProject().setProperty("SOURCE_FILES", str); + } + + /** + Generate the section elements for BaseName_build.xml. Library module will + skip this process. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applySectionsElement(Document document, Node root, FfsProcess fp) { + if (fp.initSections(buildType, getProject())) { + String targetFilename = guid + "-" + baseName + FpdParserTask.getSuffix(componentType); + String[] list = fp.getGenSectionElements(document, baseName, guid, targetFilename); + + for (int i = 0; i < list.length; i++) { + Element ele = document.createElement(list[i]); + ele.setAttribute("FILEPATH", "."); + ele.setAttribute("FILENAME", "${BASE_NAME}"); + root.appendChild(ele); + } + } + } + + /** + Generate the output elements for BaseName_build.xml. If module is library, + call the LIB command, else call the GenFfs command. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyOutputElement(Document document, Node root, FfsProcess fp) { + if (flag == GlobalData.ONLY_LIBMSA || flag == GlobalData.LIBMSA_AND_LIBMBD) { + // + // call Lib command + // + Element cc = document.createElement("Build_Library"); + cc.setAttribute("FILENAME", baseName); + root.appendChild(cc); + } + // + // if it is a module but library + // + else { + if (fp.getFfsNode() != null) { + root.appendChild(fp.getFfsNode()); + } + } + } + + /** + Get file name from node. If some wrong, return string with zero length. + + @param node Filename node of MSA/MBD or specified in each Section + @return File name + **/ + private String getFilename(Node node) { + String path = null; + String filename = "${MODULE_DIR}" + File.separatorChar; + String str = ""; + try { + FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node); + str = file.getFilename().getStringValue().trim(); + path = file.getFilename().getPath(); + } catch (Exception e) { + str = ""; + } + if (path != null) { + filename += path + File.separatorChar + str; + } else { + filename += str; + } + return getProject().replaceProperties(filename); + } + + /** + Get file type from node. If some wrong or not specified, return + null. + + @param node Filename node of MSA/MBD or specified in each Section + @return File type + **/ + private String getFiletype(Node node) { + String str = null; + try { + FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node); + str = file.getFilename().getFileType(); + } catch (Exception e) { + str = null; + } + return str; + } + + /** + Return all source files but AutoGen.c. + + @return source files Node array + **/ + public Node[] getSourceFiles() { + XmlObject[] files = SurfaceAreaQuery.getSourceFiles(arch); + if (files == null) { + return new Node[0]; + } + Vector vector = new Vector(); + for (int i = 0; i < files.length; i++) { + vector.addElement(files[i].getDomNode()); + } + // + // To be consider sourcefiles from Sections + // + return vector.toArray(new Node[vector.size()]); + } + + /** + Get current module's base name. + + @return base name + **/ + public String getBaseName() { + return baseName; + } + + /** + Set MBD surface area file. For ANT use. + + @param mbdFilename Surface Area file + **/ + public void setMbdFilename(File mbdFilename) { + this.mbdFilename = mbdFilename; + } + + /** + Set MSA surface area file. For ANT use. + + @param msaFilename Surface Area file + **/ + public void setMsaFilename(File msaFilename) { + this.msaFilename = msaFilename; + } + + /** + Compile flags setup. + +

Take command CC and arch IA32 for example, + Those flags are from ToolChainFactory:

+
    +
  • IA32_CC
  • +
  • IA32_CC_STD_FLAGS
  • +
  • IA32_CC_GLOBAL_FLAGS
  • +
  • IA32_CC_GLOBAL_ADD_FLAGS
  • +
  • IA32_CC_GLOBAL_SUB_FLAGS
  • +
+ Those flags can user-define: +
    +
  • IA32_CC_PROJ_FLAGS
  • +
  • IA32_CC_PROJ_ADD_FLAGS
  • +
  • IA32_CC_PROJ_SUB_FLAGS
  • +
  • CC_PROJ_FLAGS
  • +
  • CC_PROJ_ADD_FLAGS
  • +
  • CC_PROJ_SUB_FLAGS
  • +
  • CC_FLAGS
  • +
  • IA32_CC_FLAGS
  • +
+ +

The final flags is composed of STD, GLOBAL and PROJ. If CC_FLAGS or + IA32_CC_FLAGS is specified, STD, GLOBAL and PROJ will not affect.

+ + Note that the ToolChainFactory executes only once + during whole build process. + **/ + private void flagsSetup() { + Project project = getProject(); + // + // If ToolChain has been set up before, do nothing. + // + ToolChainFactory toolChainFactory = new ToolChainFactory(project); + toolChainFactory.setupToolChain(); + + String[] cmd = ToolChainFactory.commandType; + Set addSet = new HashSet(40); + Set subSet = new HashSet(40); + for (int i = 0; i < cmd.length; i++) { + String str = ToolChainFactory.getValue(arch + "_" + cmd[i]); + // + // Command line path+command name + // + if (str != null) { + project.setProperty(cmd[i], str); + } + // + // ARCH_CMD_STD_FLAGS + // + str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_STD_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + project.setProperty(cmd[i] + "_STD_FLAGS", str); + } + // + // ARCH_CMD_GLOBAL_FLAGS + // + str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // ARCH_CMD_GLOBAL_ADD_FLAGS + // + str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_ADD_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // ARCH_CMD_GLOBAL_SUB_FLAGS + // + str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_SUB_FLAGS"); + if (str != null) { + putFlagsToSet(subSet, str); + } + // + // ARCH_CMD_PROJ_FLAGS + // + str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // ARCH_CMD_PROG_FLAGS + // + str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_ADD_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // ARCH_CMD_PROG_FLAGS + // + str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_SUB_FLAGS"); + if (str != null) { + putFlagsToSet(subSet, str); + } + // + // CMD_PROJ_FLAGS + // + str = project.getProperty(cmd[i] + "_PROJ_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // CMD_PROG_FLAGS + // + str = project.getProperty(cmd[i] + "_PROJ_ADD_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // CMD_PROG_FLAGS + // + str = project.getProperty(cmd[i] + "_PROJ_SUB_FLAGS"); + if (str != null) { + putFlagsToSet(subSet, str); + } + // + // If IA32_CC_FLAGS or IA32_LIB_FLAGS .. has defined in BuildOptions + // + if ((str = project.getProperty(arch + "_" + cmd[i] + "_FLAGS")) != null) { + project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet)); + addSet.clear(); + subSet.clear(); + putFlagsToSet(addSet, project.replaceProperties(str)); + project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet))); + addSet.clear(); + subSet.clear(); + } + // + // If CC_FLAGS or LIB_FLAGS .. has defined in BuildOptions + // + else if ((str = project.getProperty(cmd[i] + "_FLAGS")) != null) { + project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet)); + addSet.clear(); + subSet.clear(); + putFlagsToSet(addSet, project.replaceProperties(str)); + project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet))); + addSet.clear(); + subSet.clear(); + } else { + project.setProperty(cmd[i] + "_FLAGS", getFlags(addSet, subSet)); + addSet.clear(); + subSet.clear(); + } + } + project.setProperty("C_FLAGS", project.getProperty("CC_FLAGS")); + } + + /** + Initialize some properties will be used in current module build, including + user-defined option from Option of BuildOptions in + surface area. + **/ + private void updateParameters() { + getProject().setProperty("OBJECTS", ""); + getProject().setProperty("SDB_FILES", ""); + getProject().setProperty("BASE_NAME", baseName); + if (map.get("MsaHeader") != null) { + flag = GlobalData.MSA_AND_MBD; + MsaHeaderDocument.MsaHeader header = ((MsaHeaderDocument) map.get("MsaHeader")).getMsaHeader(); + guid = header.getGuid().getStringValue(); + componentType = header.getComponentType().toString(); + } + + else if (map.get("MsaLibHeader") != null) { + flag = GlobalData.LIBMSA_AND_LIBMBD; + MsaLibHeaderDocument.MsaLibHeader header = ((MsaLibHeaderDocument) map.get("MsaLibHeader")) + .getMsaLibHeader(); + guid = header.getGuid().getStringValue(); + componentType = header.getComponentType().toString(); + } + + if (componentType != null) { + getProject().setProperty("COMPONENT_TYPE", componentType); + } + + if (guid != null) { + getProject().setProperty("FILE_GUID", guid); + } + // + // Get all options and set to properties + // + String[][] options = SurfaceAreaQuery.getOptions(arch); + for (int i = 0; i < options.length; i++) { + if (options[i][0] != null && options[i][1] != null) { + getProject().setProperty(options[i][0], getProject().replaceProperties(options[i][1])); + } + } + + buildType = getProject().getProperty("BUILD_TYPE"); + if (buildType == null) { + buildType = componentType; + } + + } + + /** + Separate the string and instore in set. + +

String is separated by Java Regulation Expression + "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+".

+ +

For example:

+ +
+        "/nologo", "/W3", "/WX"
+        "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""
+      
+ + @param set store the separated string + @param str string to separate + **/ + private void putFlagsToSet(Set set, String str) { + Pattern myPattern = Pattern.compile("[^\\\\]?(\".*?[^\\\\]\")[ \t,]+"); + Matcher matcher = myPattern.matcher(str + " "); + while (matcher.find()) { + String item = str.substring(matcher.start(1), matcher.end(1)); + if (!set.contains(item)) { + set.add(item); + } + } + } + + /** + Generate the final flags string will be used by compile command. + + @param add the add flags set + @param sub the sub flags set + @return final flags after add set substract sub set + **/ + private String getFlags(Set add, Set sub) { + String result = ""; + add.removeAll(sub); + Iterator iter = add.iterator(); + while (iter.hasNext()) { + String str = getProject().replaceProperties((String) iter.next()); + result += str.substring(1, str.length() - 1) + " "; + } + return result; + } + + /** + Generate the flags string with original format. The format is defined by + Java Regulation Expression "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+".

+ +

For example:

+ +
+        "/nologo", "/W3", "/WX"
+        "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""
+      
+ + @param add the add flags set + @param sub the sub flags set + @return flags with original format + **/ + private String getRawFlags(Set add, Set sub) { + String result = ""; + add.removeAll(sub); + Iterator iter = add.iterator(); + while (iter.hasNext()) { + String str = getProject().replaceProperties((String) iter.next()); + result += "\"" + str.substring(1, str.length() - 1) + "\", "; + } + return result; + } + + /** + Set base name. For ANT use. + + @param baseName Base name + **/ + public void setBaseName(String baseName) { + this.baseName = baseName; + } + +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/OutputDirSetupTask.java b/Tools/Source/GenBuild/org/tianocore/build/OutputDirSetupTask.java new file mode 100644 index 0000000000..c2b7cc997b --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/OutputDirSetupTask.java @@ -0,0 +1,190 @@ +/** @file + + This file is an ANT task OutputDirSetupTask. + + This task main purpose is to setup some necessary properties for Package, + Platform or Module clean. + +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; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.xmlbeans.XmlObject; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.OutputManager; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.toolchain.ToolChainFactory; + +/** + OutputDirSetupTask is an ANT task that can be used in ANT build + system. The main function of this task is to initialize some basic information + for Package|Platform|Module clean or cleanall usage. + +

Here is an example:

+
+     <OutputDirSetup baseName="HelloWorld" 
+                     mbdFilename="${MODULE_DIR}\HelloWorld.mbd" 
+                     msaFilename="${MODULE_DIR}\HelloWorld.msa" />
+  
+ +

Note that all this task doing is part of GenBuildTask.

+ + @since GenBuild 1.0 + @see org.tianocore.build.GenBuildTask +**/ +public class OutputDirSetupTask extends Task { + + /// + /// Module surface area file. + /// + File msaFilename; + + /// + /// Module build description file. + /// + File mbdFilename; + + /// + /// Module surface area information after overrided. + /// + public Map map = new HashMap(); + + /// + /// Module's base name. + /// + private String baseName; + + /** + Public construct method. It is necessary for ANT task. + **/ + public OutputDirSetupTask () { + } + + /** + ANT task's entry point, will be called after init(). The main steps is described + as following: +
    +
  • Judge current build mode (MODULE | PACKAGE | PLATFORM). This step will execute + only once in whole build process;
  • +
  • Initialize global information (Framework DB, SPD files and all MSA files + listed in SPD). This step will execute only once in whole build process;
  • +
  • Restore some important ANT property. If current build is single module + build, here will set many default values;
  • +
  • Get the current module's overridded surface area information from + global data;
  • +
  • Set up the output directories, including BIN_DIR, DEST_DIR_OUTPUT and + DEST_DIR_DEBUG;
  • +
+ + @throws BuildException + From module build, exception from module surface area invalid. + **/ + public void execute() throws BuildException { + System.out.println("Deleting module [" + baseName + "] start."); + OutputManager.update(getProject()); + GlobalData.initInfo("Tools" + File.separatorChar + "Conf" + File.separatorChar + "FrameworkDatabase.db", getProject() + .getProperty("WORKSPACE_DIR")); + recallFixedProperties(); + map = GlobalData.getDoc(baseName); + // + // Initialize SurfaceAreaQuery + // + SurfaceAreaQuery.setDoc(map); + // + // Setup Output Management + // + String[] outdir = SurfaceAreaQuery.getOutputDirectory(); + OutputManager.update(getProject(), outdir[1], outdir[0]); + } + + /** + Get current module's base name. + + @return base name + **/ + public String getBaseName() { + return baseName; + } + + /** + Set base name. For ANT use. + + @param baseName Base name + **/ + public void setBaseName(String baseName) { + this.baseName = baseName; + } + + /** + Set MBD surface area file. For ANT use. + + @param mbdFilename Surface Area file + **/ + public void setMbdFilename(File mbdFilename) { + this.mbdFilename = mbdFilename; + } + + /** + Set MSA surface area file. For ANT use. + + @param msaFilename Surface Area file + **/ + public void setMsaFilename(File msaFilename) { + this.msaFilename = msaFilename; + } + + /** + Restore some important ANT property. If current build is single module + build, here will set many default values. + +

If current build is single module build, then the default ARCH + is IA32. Also set up the properties PACKAGE, + PACKAGE_DIR, TARGET and MODULE_DIR

+ +

Note that for package build, package name is stored in PLATFORM + and package directory is stored in PLATFORM_DIR.

+ + @see org.tianocore.build.global.OutputManager + **/ + private void recallFixedProperties(){ + // + // If build is for module build + // + if (getProject().getProperty("PACKAGE_DIR") == null) { + ToolChainFactory toolChainFactory = new ToolChainFactory(getProject()); + toolChainFactory.setupToolChain(); + // + // PACKAGE PACKAGE_DIR ARCH (Default) COMMON_FILE BUILD_MACRO + // + if (getProject().getProperty("ARCH") == null){ + getProject().setProperty("ARCH", "IA32"); + } + String packageName = GlobalData.getPackageNameForModule(baseName); + getProject().setProperty("PACKAGE", packageName); + String packageDir = GlobalData.getPackagePath(packageName); + getProject().setProperty("PACKAGE_DIR", getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + packageDir); + getProject().setProperty("TARGET", toolChainFactory.getCurrentTarget()); + getProject().setProperty("MODULE_DIR", getProject().replaceProperties(getProject().getProperty("MODULE_DIR"))); + } + if (OutputManager.PLATFORM != null) { + getProject().setProperty("PLATFORM", OutputManager.PLATFORM); + } + if (OutputManager.PLATFORM_DIR != null) { + getProject().setProperty("PLATFORM_DIR", OutputManager.PLATFORM_DIR); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/autogen/AutoGen.java b/Tools/Source/GenBuild/org/tianocore/build/autogen/AutoGen.java new file mode 100644 index 0000000000..f1e9c5b4ec --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/autogen/AutoGen.java @@ -0,0 +1,2006 @@ +/** @file + AutoGen class. + + This class is to generate Autogen.h and Autogen.c according to module surface area + or library surface area. + + 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.autogen; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.Spd; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.GuidsDocument; +import org.tianocore.LibraryClassDocument.LibraryClass; +import org.tianocore.PPIsDocument; +import org.tianocore.ProtocolsDocument; +import org.tianocore.build.pcd.action.PCDAutoGenAction; + +import org.apache.tools.ant.BuildException; +import org.apache.xmlbeans.XmlObject; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + This class is to generate Autogen.h and Autogen.c according to module surface + area or library surface area. +**/ +public class AutoGen { + /// + /// The output path of Autogen.h and Autogen.c + /// + private String outputPath; + + /// + /// The base name of module or library. + /// + private String baseName; + + /// + /// The build architecture + /// + private String arch; + + /// + /// PcdAutogen instance which is used to manage how to generate the PCD + /// information. + /// + private PCDAutoGenAction myPcdAutogen; + + /// + /// The protocl list which records in module or library surface area and + /// it's dependence on library instance surface area. + /// + private List mProtocolList = new ArrayList(); + + /// + /// The Ppi list which recorded in module or library surface area and its + /// dependency on library instance surface area. + /// + private List mPpiList = new ArrayList(); + + /// + /// The Guid list which recoreded in module or library surface are and it's + /// dependence on library instance surface area. + /// + private List mGuidList = new ArrayList(); + + /** + Construct function + + This function mainly initialize some member variable. + + @param outputPath Output path of AutoGen file. + @param baseName Module base name. + @param arch Target architecture. + **/ + public AutoGen(String outputPath, String baseName, String arch) { + this.outputPath = outputPath; + this.baseName = baseName; + this.arch = arch; + + } + + /** + saveFile function + + This function save the content in stringBuffer to file. + + @param fileName The name of file. + @param fileBuffer The content of AutoGen file in buffer. + @return "true" successful, "false" failed. + **/ + private boolean saveFile(String fileName, StringBuffer fileBuffer) { + try { + File autoGenH = new File(fileName); + + // + // if the file exists, compare their content + // + if (autoGenH.exists()) { + FileReader fIn = new FileReader(autoGenH); + char[] oldFileBuffer = new char[(int) autoGenH.length()]; + fIn.read(oldFileBuffer, 0, (int) autoGenH.length()); + fIn.close(); + + // + // if we got the same file, don't re-generate it to prevent + // sources depending on it from re-building + // + if (fileBuffer.toString().compareTo(new String(oldFileBuffer)) == 0) { + return true; + } + } + FileWriter fOut = new FileWriter(autoGenH); + fOut.write(fileBuffer.toString()); + fOut.close(); + } catch (Exception e) { + return false; + } + return true; + } + + /** + genAutogen function + + This function call libGenAutoGen or moduleGenAutogen function, which + dependence on generate library autogen or module autogen. + + @throws BuildException Failed to creat AutoGen.c & AutoGen.h. + **/ + public void genAutogen() throws BuildException { + try { + // + // If outputPath do not exist, create it. + // + File path = new File(outputPath); + path.mkdirs(); + + // + // Check current is library or not, then call the corresponding + // function. + // + if (SurfaceAreaQuery.getComponentType().equalsIgnoreCase( + CommonDefinition.LibraryStr)) { + libGenAutogen(); + } else { + moduleGenAutogen(); + } + + } catch (Exception e) { + throw new BuildException( + "Failed to create AutoGen.c & AutoGen.h!\n" + + e.getMessage()); + } + } + + /** + moduleGenAutogen function + + This function generates AutoGen.c & AutoGen.h for module. + + @throws BuildException Faile to create module AutoGen.c & AutoGen.h. + **/ + void moduleGenAutogen() throws BuildException { + + try { + moduleGenAutogenC(); + moduleGenAutogenH(); + } catch (Exception e) { + throw new BuildException( + "Faile to create module AutoGen.c & AutoGen.h!\n" + + e.getMessage()); + } + } + + /** + libGenAutogen function + + This function generates AutoGen.c & AutoGen.h for library. + + @throws BuildException + Faile to create library AutoGen.c & AutoGen.h + **/ + void libGenAutogen() throws BuildException { + try { + libGenAutogenC(); + libGenAutogenH(); + } catch (Exception e) { + throw new BuildException( + "Faile to create library AutoGen.c & AutoGen.h!\n" + + e.getMessage()); + } + } + + /** + moduleGenAutogenH + + This function generates AutoGen.h for module. + + @throws BuildException + Failed to generate AutoGen.h. + **/ + void moduleGenAutogenH() throws BuildException { + + List libClassIncludeH; + String moduleType; + List headerFileList; + + StringBuffer fileBuffer = new StringBuffer(8192); + + // + // Write Autogen.h header notation + // + fileBuffer.append(CommonDefinition.autogenHNotation); + + // + // Add #ifndef ${BaseName}_AUTOGENH + // #def ${BseeName}_AUTOGENH + // + fileBuffer.append("#ifndef " + this.baseName.toUpperCase() + "_AUTOGENH\r\n"); + fileBuffer.append("#define " + this.baseName.toUpperCase() + "_AUTOGENH\r\n\r\n"); + + // + // Write the specification version and release version at the begine + // of autogen.h file. + // Note: the specification version and release version should + // be got from module surface area instead of hard code by it's moduleType. + // + moduleType = SurfaceAreaQuery.getModuleType(); + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append(CommonDefinition.autoGenHLine1); + break; + default: + fileBuffer.append(CommonDefinition.autoGenHVersionDefault); + break; + } + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append(CommonDefinition.autoGenHReleaseDefault); + break; + default: + fileBuffer.append(CommonDefinition.autoGenHLine2); + break; + } + + // + // Add "extern int __make_me_compile_correctly;" at begin of + // AutoGen.h. + // + fileBuffer.append(CommonDefinition.autoGenHbegin); + + // + // Write consumed package's mdouleInfo related .h file to autogen.h + // + List consumedPkgList = SurfaceAreaQuery + .getIncludePackageName(this.arch); + if (consumedPkgList != null) { + headerFileList = IncludesToAutogenH(consumedPkgList, moduleType); + for (int i = 0; i < headerFileList.size(); i++) { + fileBuffer.append(headerFileList.get(i)); + } + } + + // + // Write library class's related *.h file to autogen.h. + // + LibraryClass[] libClassList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysConsumed); + if (libClassList != null) { + libClassIncludeH = LibraryClassToAutogenH(libClassList); + for (int i = 0; i < libClassIncludeH.size(); i++) { + fileBuffer.append(libClassIncludeH.get(i)); + } + } + + libClassList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysProduced); + if (libClassList != null) { + libClassIncludeH = LibraryClassToAutogenH(libClassList); + for (int i = 0; i < libClassIncludeH.size(); i++) { + fileBuffer.append(libClassIncludeH.get(i)); + } + } + fileBuffer.append("\r\n"); + + // + // Write PCD autogen information to AutoGen.h. + // + if (this.myPcdAutogen != null) { + fileBuffer.append(this.myPcdAutogen.OutputH()); + } + + // + // Append the #endif at AutoGen.h + // + fileBuffer.append("#endif\r\n"); + + // + // Save string buffer content in AutoGen.h. + // + if (!saveFile(outputPath + File.separatorChar + "AutoGen.h", fileBuffer)) { + throw new BuildException("Failed to generate AutoGen.h !!!"); + } + } + + /** + moduleGenAutogenC + + This function generates AutoGen.c for module. + + @throws BuildException + Failed to generate AutoGen.c. + **/ + void moduleGenAutogenC() throws BuildException { + + StringBuffer fileBuffer = new StringBuffer(8192); + // + // Write Autogen.c header notation + // + fileBuffer.append(CommonDefinition.autogenCNotation); + + // + // Write #include at beginning of AutoGen.c + // + fileBuffer.append(CommonDefinition.includeAutogenH); + + // + // Write DriverBinding/ComponentName/DriverConfiguration/DriverDialog + // to AutoGen.c + // + ExternsDriverBindingToAutoGenC(fileBuffer); + + // + // Write DriverExitBootServicesEvent/DriverSetVirtualAddressMapEvent + // to Autogen.c + // + ExternCallBackToAutoGenC(fileBuffer); + + // + // Write EntryPoint to autgoGen.c + // + String[] entryPointList = SurfaceAreaQuery.getModuleEntryPointArray(); + if (entryPointList != null) { + EntryPointToAutoGen(entryPointList, fileBuffer); + } + + // + // Write Guid to autogen.c + // + String guid = SurfaceAreaQuery.getModuleGuid(); + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiCallerIdGuid = {"); + if (guid == null) { + throw new BuildException("Guid value must set!\n"); + } + + // + // Formate Guid as ANSI c form.Example: + // {0xd2b2b828, 0x826, 0x48a7,{0xb3, 0xdf, 0x98, 0x3c, 0x0, 0x60, 0x24, 0xf0}} + // + fileBuffer.append(Spd.formatGuidName(guid)); + fileBuffer.append("};\r\n"); + + // + // Generate library instance consumed protocol, guid, ppi, pcd list. + // Save those to this.protocolList, this.ppiList, this.pcdList, + // this.guidList. Write Consumed library constructor and desconstuct to + // autogen.c + // + LibInstanceToAutogenC(fileBuffer); + + // + // Write consumed ppi, guid, protocol to autogen.c + // + ProtocolGuidToAutogenC(fileBuffer); + PpiGuidToAutogenC(fileBuffer); + GuidGuidToAutogenC(fileBuffer); + + // + // Call pcd autogen. PCDAutoGenAction tool only need module name and + // isPcdEmulatedDriver as parameter. Library inherits PCD and module's + // PCD information has been collected in FPDParser task by + // CollectPCDAction. + // Note : when PCD image tool ready, + // isPCDEmulatedDriver parameter will be removed. + // + try { + this.myPcdAutogen = new PCDAutoGenAction(baseName, + baseName.equalsIgnoreCase("PcdEmulatorPeim")); + this.myPcdAutogen.execute(); + } catch (Exception e) { + throw new BuildException("PCD Autogen failed:" + e.getMessage()); + } + + if (this.myPcdAutogen != null) { + fileBuffer.append(this.myPcdAutogen.OutputC()); + } + + if (!saveFile(outputPath + File.separatorChar + "AutoGen.c", fileBuffer)) { + throw new BuildException("Failed to generate AutoGen.c !!!"); + } + + } + + /** + libGenAutogenH + + This function generates AutoGen.h for library. + + @throws BuildException + Failed to generate AutoGen.c. + **/ + void libGenAutogenH() throws BuildException { + + List libClassIncludeH; + String moduleType; + List headerFileList; + StringBuffer fileBuffer = new StringBuffer(10240); + + // + // Write Autogen.h header notation + // + fileBuffer.append(CommonDefinition.autogenHNotation); + + // + // Add #ifndef ${BaseName}_AUTOGENH + // #def ${BseeName}_AUTOGENH + // + fileBuffer.append("#ifndef " + this.baseName.toUpperCase() + "_AUTOGENH\r\n"); + fileBuffer.append("#define " + this.baseName.toUpperCase() + "_AUTOGENH\r\n\r\n"); + + // + // Write EFI_SPECIFICATION_VERSION and EDK_RELEASE_VERSION + // to autogen.h file. + // Note: the specification version and release version should + // be get from module surface area instead of hard code. + // + fileBuffer.append(CommonDefinition.autoGenHbegin); + fileBuffer.append(CommonDefinition.autoGenHLine1); + fileBuffer.append(CommonDefinition.autoGenHLine2); + + // + // Write consumed package's mdouleInfo related *.h file to autogen.h. + // + moduleType = SurfaceAreaQuery.getModuleType(); + List cosumedPkglist = SurfaceAreaQuery + .getIncludePackageName(this.arch); + headerFileList = IncludesToAutogenH(cosumedPkglist, moduleType); + for (int i = 0; i < headerFileList.size(); i++) { + fileBuffer.append(headerFileList.get(i)); + } + + // + // Write library class's related *.h file to autogen.h + // + LibraryClass[] libClassList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysConsumed); + if (libClassList != null) { + libClassIncludeH = LibraryClassToAutogenH(libClassList); + for (int i = 0; i < libClassIncludeH.size(); i++) { + fileBuffer.append(libClassIncludeH.get(i)); + } + } + + libClassList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysProduced); + if (libClassList != null) { + libClassIncludeH = LibraryClassToAutogenH(libClassList); + for (int i = 0; i < libClassIncludeH.size(); i++) { + fileBuffer.append(libClassIncludeH.get(i)); + } + } + fileBuffer.append("\r\n"); + + // + // Write PCD information to library AutoGen.h. + // + if (this.myPcdAutogen != null) { + fileBuffer.append(this.myPcdAutogen.OutputH()); + } + + // + // Append the #endif at AutoGen.h + // + fileBuffer.append("#endif\r\n"); + + // + // Save content of string buffer to AutoGen.h file. + // + if (!saveFile(outputPath + File.separatorChar + "AutoGen.h", fileBuffer)) { + throw new BuildException("Failed to generate AutoGen.h !!!"); + } + } + + /** + libGenAutogenC + + This function generates AutoGen.h for library. + + @throws BuildException + Failed to generate AutoGen.c. + **/ + void libGenAutogenC() throws BuildException { + StringBuffer fileBuffer = new StringBuffer(10240); + + // + // Write Autogen.c header notation + // + fileBuffer.append(CommonDefinition.autogenCNotation); + + fileBuffer.append(CommonDefinition.autoGenCLine1); + fileBuffer.append("\r\n"); + + // + // Call pcd autogen. PCDAutoGenAction tool only need module name and + // isPcdEmulatedDriver as parameter. Library inherit PCD and module's + // PCD information has been collected in FPDParser task by + // CollectPCDAction. + // Note : when PCD image tool ready, + // isPCDEmulatedDriver parameter will be removed. + // + try { + this.myPcdAutogen = new PCDAutoGenAction(baseName, baseName + .equalsIgnoreCase("PcdEmulatorPeim")); + this.myPcdAutogen.execute(); + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + + if (this.myPcdAutogen != null) { + fileBuffer.append(this.myPcdAutogen.OutputC()); + } + + if (!saveFile(outputPath + File.separatorChar + "AutoGen.c", fileBuffer)) { + throw new BuildException("Failed to generate AutoGen.c !!!"); + } + } + + /** + LibraryClassToAutogenH + + This function returns *.h files declared by library classes which are + consumed or produced by current build module or library. + + @param libClassList List of library class which consumed or produce + by current build module or library. + @return includeStrList List of *.h file. + **/ + List LibraryClassToAutogenH(LibraryClass[] libClassList) { + List includStrList = new ArrayList(); + String includerName; + String str = ""; + + // + // Get include file from GlobalData's SPDTable according to + // library class name. + // + for (int i = 0; i < libClassList.length; i++) { + includerName = GlobalData.getLibClassIncluder(libClassList[i] + .getStringValue()); + if (includerName != null) { + str = CommonDefinition.include + " " + "<"; + str = str + includerName + ">\r\n"; + includStrList.add(str); + includerName = null; + } + } + return includStrList; + } + + /** + IncludesToAutogenH + + This function add include file in AutoGen.h file. + @param packageNameList List of module depended package. + @param moduleType Module type. + @return + **/ + List IncludesToAutogenH(List packageNameList, + String moduleType) { + + List includeStrList = new ArrayList(); + String packageName = ""; + String includeStr = ""; + + // + // Get include file from moduleInfo file + // + for (int i = 0; i < packageNameList.size(); i++) { + packageName = packageNameList.get(i); + includeStr = GlobalData.getModuleInfoByPackageName(packageName, + moduleType); + includeStrList.add(includeStr); + } + return includeStrList; + } + + /** + EntryPointToAutoGen + + This function convert & information + in mas to AutoGen.c + + @param entryPointList List of entry point. + @param fileBuffer String buffer fo AutoGen.c. + @throws Exception + **/ + void EntryPointToAutoGen(String[] entryPointList, StringBuffer fileBuffer) + throws BuildException { + + String typeStr = SurfaceAreaQuery.getModuleType(); + + // + // The parameters and return value of entryPoint is difference + // for difference module type. + // + switch (CommonDefinition.getModuleType(typeStr)) { + + case CommonDefinition.ModuleTypePeiCore: + if (entryPointList.length != 1 || entryPointList[0].equals("")) { + throw new BuildException( + "Module type = 'PEI_CORE', only have one module entry point!"); + } else { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,\r\n"); + fileBuffer + .append(" IN VOID *OldCoreData\r\n"); + fileBuffer.append(" );\r\n\r\n"); + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer + .append(" IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,\r\n"); + fileBuffer + .append(" IN VOID *OldCoreData\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + fileBuffer.append(" return "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (PeiStartupDescriptor, OldCoreData);\r\n"); + fileBuffer.append("}\r\n\r\n"); + } + break; + + case CommonDefinition.ModuleTypeDxeCore: + fileBuffer.append("const UINT32 _gUefiDriverRevision = 0;\r\n"); + if (entryPointList.length != 1 || entryPointList[0].equals("")) { + throw new BuildException( + "Module type = 'DXE_CORE', only have one module entry point!"); + } else { + + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (\n"); + fileBuffer.append(" IN VOID *HobStart\r\n"); + fileBuffer.append(" );\r\n\r\n"); + + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer.append(" IN VOID *HobStart\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + fileBuffer.append(" "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (HobStart);\r\n"); + fileBuffer.append("}\r\n\r\n"); + } + break; + + case CommonDefinition.ModuleTypePeim: + int entryPointCount = 0; + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = 0;\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer + .append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer.append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer.append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + + if (entryPointCount == 0) { + fileBuffer.append(" return EFI_SUCCESS;\r\n"); + } else if (entryPointCount == 1) { + fileBuffer.append(" return "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (FfsHeader, PeiServices);\r\n"); + } else { + fileBuffer.append(" EFI_STATUS Status;\r\n"); + fileBuffer.append(" EFI_STATUS CombinedStatus;\r\n\r\n"); + fileBuffer.append(" CombinedStatus = EFI_LOAD_ERROR;\r\n\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append(" Status = "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (FfsHeader, PeiServices)\r\n"); + fileBuffer + .append(" if (!EFI_ERROR (Status) || EFI_ERROR (CombinedStatus)) {\r\n"); + fileBuffer.append(" CombinedStatus = Status;\r\n"); + fileBuffer.append(" }\r\n\r\n"); + } else { + break; + } + } + fileBuffer.append(" return CombinedStatus;\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + break; + + case CommonDefinition.ModuleTypeDxeSmmDriver: + entryPointCount = 0; + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverEntryPointCount = "); + fileBuffer.append(Integer.toString(entryPointCount)); + fileBuffer.append(";\r\n"); + fileBuffer + .append("static BASE_LIBRARY_JUMP_BUFFER mJumpContext;\r\n"); + fileBuffer + .append("static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR;\r\n\r\n"); + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer + .append(" if (SetJump (&mJumpContext) == 0) {\r\n"); + fileBuffer.append(" ExitDriver ("); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (ImageHandle, SystemTable));\r\n"); + fileBuffer.append(" ASSERT (FALSE);\r\n"); + fileBuffer.append(" }\r\n"); + } else { + break; + } + } + fileBuffer.append(" return mDriverEntryPointStatus;\r\n"); + fileBuffer.append("}\r\n\r\n"); + + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ExitDriver (\r\n"); + fileBuffer.append(" IN EFI_STATUS Status\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + fileBuffer + .append(" if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) {\r\n"); + fileBuffer.append(" mDriverEntryPointStatus = Status;\r\n"); + fileBuffer.append(" }\r\n"); + fileBuffer.append(" LongJump (&mJumpContext, (UINTN)-1);\r\n"); + fileBuffer.append(" ASSERT (FALSE);\r\n"); + fileBuffer.append("}\r\n\r\n"); + + // + // Add "ModuleUnloadImage" for DxeSmmDriver module type; + // + entryPointList = SurfaceAreaQuery.getModuleUnloadImageArray(); + entryPointCount = 0; + if (entryPointList != null) { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + } + + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = "); + fileBuffer.append(Integer.toString(entryPointCount)); + fileBuffer.append(";\r\n\r\n"); + + if (entryPointList != null) { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" );\r\n"); + } else { + break; + } + } + } + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleUnloadList (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" )\r\n"); + fileBuffer.append("{\r\n"); + + if (entryPointCount == 0) { + fileBuffer.append(" return EFI_SUCCESS;\r\n"); + } else if (entryPointCount == 1) { + fileBuffer.append(" return "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append("(ImageHandle);\r\n"); + } else { + fileBuffer.append(" EFI_STATUS Status;\r\n\r\n"); + fileBuffer.append(" Status = EFI_SUCCESS;\r\n\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append(" if (EFI_ERROR (Status)) {\r\n"); + fileBuffer.append(" "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append("(ImageHandle);\r\n"); + fileBuffer.append(" } else {\r\n"); + fileBuffer.append(" Status = "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append("(ImageHandle);\r\n"); + fileBuffer.append(" }\r\n"); + } else { + break; + } + } + fileBuffer.append(" return Status;\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + break; + + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + entryPointCount = 0; + fileBuffer.append("const UINT32 _gUefiDriverRevision = 0;\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverEntryPointCount = "); + fileBuffer.append(Integer.toString(entryPointCount)); + fileBuffer.append(";\r\n"); + if (entryPointCount > 1) { + fileBuffer + .append("static BASE_LIBRARY_JUMP_BUFFER mJumpContext;\r\n"); + fileBuffer + .append("static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR;\r\n"); + } + fileBuffer.append("\n"); + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + + if (entryPointCount == 0) { + fileBuffer.append(" return EFI_SUCCESS;\r\n"); + } else if (entryPointCount == 1) { + fileBuffer.append(" return ("); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (ImageHandle, SystemTable));\r\n"); + } else { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer + .append(" if (SetJump (&mJumpContext) == 0) {\r\n"); + fileBuffer.append(" ExitDriver ("); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (ImageHandle, SystemTable));\r\n"); + fileBuffer.append(" ASSERT (FALSE);\r\n"); + fileBuffer.append(" }\r\n"); + } else { + break; + } + } + fileBuffer.append(" return mDriverEntryPointStatus;\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + + fileBuffer.append("VOID\n"); + fileBuffer.append("EFIAPI\n"); + fileBuffer.append("ExitDriver (\r\n"); + fileBuffer.append(" IN EFI_STATUS Status\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + if (entryPointCount <= 1) { + fileBuffer.append(" if (EFI_ERROR (Status)) {\r\n"); + fileBuffer + .append(" ProcessLibraryDestructorList (gImageHandle, gST);\r\n"); + fileBuffer.append(" }\r\n"); + fileBuffer + .append(" gBS->Exit (gImageHandle, Status, 0, NULL);\r\n"); + } else { + fileBuffer + .append(" if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) {\r\n"); + fileBuffer.append(" mDriverEntryPointStatus = Status;\r\n"); + fileBuffer.append(" }\r\n"); + fileBuffer.append(" LongJump (&mJumpContext, (UINTN)-1);\r\n"); + fileBuffer.append(" ASSERT (FALSE);\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + + // + // Add ModuleUnloadImage for DxeDriver and UefiDriver module type. + // + entryPointList = SurfaceAreaQuery.getModuleUnloadImageArray(); + entryPointCount = 0; + if (entryPointList != null) { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + } + + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = "); + fileBuffer.append(Integer.toString(entryPointCount)); + fileBuffer.append(";\r\n\r\n"); + + if (entryPointList != null) { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" );\r\n"); + } else { + break; + } + } + } + + fileBuffer.append("EFI_STATUS\n"); + fileBuffer.append("EFIAPI\n"); + fileBuffer.append("ProcessModuleUnloadList (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" )\r\n"); + fileBuffer.append("{\r\n"); + + if (entryPointCount == 0) { + fileBuffer.append(" return EFI_SUCCESS;\r\n"); + } else if (entryPointCount == 1) { + fileBuffer.append(" return "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append("(ImageHandle);\r\n"); + } else { + fileBuffer.append(" EFI_STATUS Status;\r\n\r\n"); + fileBuffer.append(" Status = EFI_SUCCESS;\r\n\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append(" if (EFI_ERROR (Status)) {\r\n"); + fileBuffer.append(" "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append("(ImageHandle);\r\n"); + fileBuffer.append(" } else {\r\n"); + fileBuffer.append(" Status = "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append("(ImageHandle);\r\n"); + fileBuffer.append(" }\r\n"); + } else { + break; + } + } + fileBuffer.append(" return Status;\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + break; + } + } + + /** + PpiGuidToAutogenc + + This function gets GUIDs from SPD file accrodeing to information and + write those GUIDs to AutoGen.c. + + @param fileBuffer String Buffer for Autogen.c file. + @throws BuildException Guid must set value! + **/ + void PpiGuidToAutogenC(StringBuffer fileBuffer) throws BuildException { + String[] cNameGuid = null; + boolean isEqual = false; + + PPIsDocument.PPIs.Ppi[] ppiList = SurfaceAreaQuery.getPpiArray(null); + if (ppiList != null) { + for (int i = 0; i < ppiList.length; i++) { + isEqual = false; + for (int j = 0; j < this.mPpiList.size(); j++) { + if (this.mPpiList.get(j).equalsIgnoreCase( + ppiList[i].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mPpiList.add(ppiList[i].getStringValue()); + } + } + } + + PPIsDocument.PPIs.PpiNotify[] ppiNotifyList = SurfaceAreaQuery + .getPpiNotifyArray(null); + if (ppiNotifyList != null) { + for (int i = 0; i < ppiNotifyList.length; i++) { + isEqual = false; + for (int j = 0; j < this.mPpiList.size(); j++) { + if (this.mPpiList.get(j).equalsIgnoreCase( + ppiNotifyList[i].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mPpiList.add(ppiNotifyList[i].getStringValue()); + } + } + } + + for (int i = 0; i < this.mPpiList.size(); i++) { + if (this.mPpiList.get(i) != null) { + cNameGuid = GlobalData.getPpiInfoGuid(this.mPpiList.get(i)); + if (cNameGuid != null) { + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID "); + fileBuffer.append(cNameGuid[0]); + fileBuffer.append(" = { "); + fileBuffer.append(cNameGuid[1]); + fileBuffer.append(" } ;"); + } + } else { + throw new BuildException("Guid must set value!"); + } + } + } + + /** + ProtocolGuidToAutogenc + + This function gets GUIDs from SPD file accrodeing to + information and write those GUIDs to AutoGen.c. + + @param fileBuffer String Buffer for Autogen.c file. + @throws BuildException Protocol name must set. + **/ + void ProtocolGuidToAutogenC(StringBuffer fileBuffer) throws BuildException { + String[] cNameGuid = null; + boolean isEqual = false; + + ProtocolsDocument.Protocols.Protocol[] protocolList = SurfaceAreaQuery + .getProtocolArray(null); + if (protocolList != null) { + for (int i = 0; i < protocolList.length; i++) { + isEqual = false; + for (int j = 0; j < this.mProtocolList.size(); j++) { + if (this.mProtocolList.get(j).equalsIgnoreCase( + protocolList[i].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mProtocolList.add(protocolList[i].getStringValue()); + + } + } + } + + ProtocolsDocument.Protocols.ProtocolNotify[] protocolNotifyList = SurfaceAreaQuery + .getProtocolNotifyArray(null); + if (protocolNotifyList != null) { + for (int i = 0; i < protocolNotifyList.length; i++) { + isEqual = false; + for (int j = 0; j < this.mProtocolList.size(); j++) { + if (this.mProtocolList.get(j).equalsIgnoreCase( + protocolNotifyList[i].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mProtocolList.add(protocolNotifyList[i] + .getStringValue()); + + } + } + } + if (this.mProtocolList.size() > 0) { + for (int i = 0; i < this.mProtocolList.size(); i++) { + if (this.mProtocolList.get(i) != null) { + cNameGuid = GlobalData + .getProtocolInfoGuid(this.mProtocolList.get(i)); + if (cNameGuid != null) { + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID "); + fileBuffer.append(cNameGuid[0]); + fileBuffer.append(" = { "); + fileBuffer.append(cNameGuid[1]); + fileBuffer.append(" } ;"); + } + } else { + throw new BuildException("Protocol name must set!"); + } + } + } + } + + /** + GuidGuidToAutogenc + + This function gets GUIDs from SPD file accrodeing to information + and write those GUIDs to AutoGen.c. + + @param fileBuffer String Buffer for Autogen.c file. + + **/ + void GuidGuidToAutogenC(StringBuffer fileBuffer) { + String[] cNameGuid = null; + boolean isEqual = false; + GuidsDocument.Guids.GuidEntry[] guidList = SurfaceAreaQuery + .getGuidEntryArray(null); + + if (guidList != null) { + for (int i = 0; i < guidList.length; i++) { + for (int j = 0; j < this.mGuidList.size(); j++) { + isEqual = false; + if (this.mGuidList.get(j).getCName().equalsIgnoreCase( + guidList[i].getCName().toString())) { + isEqual = true; + break; + } + } + if (!isEqual) { + this.mGuidList.add(guidList[i]); + + } + + } + } + + for (int i = 0; i < this.mGuidList.size(); i++) { + if (this.mGuidList.get(i).getCName() != null) { + cNameGuid = GlobalData.getGuidInfoGuid(this.mGuidList.get(i) + .getCName()); + if (cNameGuid != null) { + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID "); + fileBuffer.append(cNameGuid[0]); + fileBuffer.append(" = { "); + fileBuffer.append(cNameGuid[1]); + fileBuffer.append("} ;"); + } + } + } + } + + /** + LibInstanceToAutogenC + + This function adds dependent library instance to autogen.c,which includeing + library's constructor, destructor, and library dependent ppi, protocol, guid, + pcd information. + + @param fileBuffer String buffer for AutoGen.c + @throws BuildException + **/ + void LibInstanceToAutogenC(StringBuffer fileBuffer) throws BuildException { + int index; + boolean isEqual = false; + + String moduleType = SurfaceAreaQuery.getModuleType(); + List libConstructList = new ArrayList(); + List libDestructList = new ArrayList(); + + String libConstructName = null; + String libDestructName = null; + List libraryList = SurfaceAreaQuery.getLibraryInstance( + this.arch, CommonDefinition.AlwaysConsumed); + + try { + if (libraryList != null) { + // + // Reorder library instance sequence. + // + AutogenLibOrder libOrder = new AutogenLibOrder(libraryList); + List orderList = libOrder.orderLibInstance(); + + if (orderList != null) { + // + // Process library instance one by one. + // + for (int i = 0; i < orderList.size(); i++) { + + // + // Get library instance basename. + // + String libInstanceName = orderList.get(i).toString(); + + // + // Get override map + // + Map libDoc = GlobalData + .getDoc(libInstanceName); + SurfaceAreaQuery.push(libDoc); + + // + // Get , , list of this library + // instance. + // + PPIsDocument.PPIs.Ppi[] ppiList = SurfaceAreaQuery + .getPpiArray(null); + PPIsDocument.PPIs.PpiNotify[] ppiNotifyList = SurfaceAreaQuery + .getPpiNotifyArray(null); + ProtocolsDocument.Protocols.Protocol[] protocolList = SurfaceAreaQuery + .getProtocolArray(null); + ProtocolsDocument.Protocols.ProtocolNotify[] protocolNotifyList = SurfaceAreaQuery + .getProtocolNotifyArray(null); + GuidsDocument.Guids.GuidEntry[] guidList = SurfaceAreaQuery + .getGuidEntryArray(null); + + // + // Add those ppi, protocol, guid in global ppi, protocol, guid + // list. + // + if (ppiList != null) { + for (index = 0; index < ppiList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mPpiList.size(); j++) { + if (this.mPpiList.get(j).equalsIgnoreCase( + ppiList[index].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mPpiList.add(ppiList[index] + .getStringValue()); + } + } + } + if (ppiNotifyList != null) { + for (index = 0; index < ppiNotifyList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mPpiList.size(); j++) { + if (this.mPpiList.get(j).equalsIgnoreCase( + ppiNotifyList[index] + .getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mPpiList.add(ppiNotifyList[index] + .getStringValue()); + } + } + } + if (protocolList != null) { + for (index = 0; index < protocolList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mProtocolList.size(); j++) { + if (this.mProtocolList.get(j) + .equalsIgnoreCase( + protocolList[index] + .getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mProtocolList.add(protocolList[index] + .getStringValue()); + } + } + } + if (protocolNotifyList != null) { + for (index = 0; index < protocolNotifyList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mProtocolList.size(); j++) { + if (this.mProtocolList.get(j) + .equalsIgnoreCase( + protocolNotifyList[index] + .getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mProtocolList + .add(protocolNotifyList[index] + .getStringValue()); + } + } + } + if (guidList != null) { + for (index = 0; index < guidList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mGuidList.size(); j++) { + if (this.mGuidList.get(j).getCName() + .equalsIgnoreCase( + guidList[index].getCName())) { + isEqual = true; + } + } + if (!isEqual) { + this.mGuidList.add(guidList[index]); + } + } + } + + // + // If not yet parse this library instance's constructor + // element,parse it. + // + if (!GlobalData.isHaveLibInstance(libInstanceName)) { + libConstructName = SurfaceAreaQuery + .getLibConstructorName(); + libDestructName = SurfaceAreaQuery + .getLibDestructorName(); + + GlobalData.setLibInstanceInfo(libInstanceName, + libConstructName, libDestructName); + } else { + libConstructName = GlobalData + .getLibInstanceConstructor(libInstanceName); + libDestructName = GlobalData + .getLibInstanceDestructor(libInstanceName); + } + SurfaceAreaQuery.pop(); + // + // Add dependent library instance constructor function. + // + if (libConstructName != null) { + libConstructList.add(libConstructName); + } + // + // Add dependent library instance destructor fuction. + // + if (libDestructName != null) { + libDestructList.add(libDestructName); + } + } + + } + + // + // Add library constructor to AutoGen.c + // + LibConstructorToAutogenC(libConstructList, moduleType, + fileBuffer/* autogenC */); + // + // Add library destructor to AutoGen.c + // + LibDestructorToAutogenC(libDestructList, moduleType, + fileBuffer/* autogenC */); + } + + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + + /** + LibConstructorToAutogenc + + This function writes library constructor list to AutoGen.c. The library + constructor's parameter and return value depend on module type. + + @param libInstanceList List of library construct name. + @param moduleType Module type. + @param fileBuffer String buffer for AutoGen.c + @throws Exception + **/ + void LibConstructorToAutogenC(List libInstanceList, + String moduleType, StringBuffer fileBuffer) throws Exception { + boolean isFirst = true; + + // + // The library constructor's parameter and return value depend on + // module type. + // + for (int i = 0; i < libInstanceList.size(); i++) { + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + fileBuffer.append("RETURN_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" VOID\r\n"); + fileBuffer.append(" );\r\n"); + break; + + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer + .append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + fileBuffer.append(" );\r\n"); + break; + + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" IN EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" IN EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" );\r\n"); + break; + } + } + + // + // Add ProcessLibraryConstructorList in AutoGen.c + // + fileBuffer.append("VOID\r\n"); + fileBuffer.append("ProcessLibraryConstructorList (\r\n"); + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + fileBuffer.append(" VOID\r\n"); + break; + + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + fileBuffer.append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer + .append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + break; + + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append(" IN EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" IN EFI_SYSTEM_TABLE *SystemTable\r\n"); + break; + } + + fileBuffer.append(" )\r\n"); + fileBuffer.append("{\r\n"); + + for (int i = 0; i < libInstanceList.size(); i++) { + if (isFirst) { + fileBuffer.append(" EFI_STATUS Status;\r\n"); + fileBuffer.append("\r\n"); + isFirst = false; + } + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + fileBuffer.append(" Status = "); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append("();\r\n"); + fileBuffer.append(" VOID\r\n"); + break; + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + fileBuffer.append(" Status = "); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (FfsHeader, PeiServices);\r\n"); + break; + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append(" Status = "); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (ImageHandle, SystemTable);\r\n"); + break; + } + fileBuffer.append(" ASSERT_EFI_ERROR (Status);\r\n"); + } + fileBuffer.append("}\r\n"); + } + + /** + LibDestructorToAutogenc + + This function writes library destructor list to AutoGen.c. The library + destructor's parameter and return value depend on module type. + + @param libInstanceList List of library destructor name. + @param moduleType Module type. + @param fileBuffer String buffer for AutoGen.c + @throws Exception + **/ + void LibDestructorToAutogenC(List libInstanceList, + String moduleType, StringBuffer fileBuffer) throws Exception { + boolean isFirst = true; + for (int i = 0; i < libInstanceList.size(); i++) { + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + fileBuffer.append("RETURN_STATUS\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" VOID\r\n"); + fileBuffer.append(" );\r\n"); + break; + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer + .append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + fileBuffer.append(" );\r\n"); + break; + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" IN EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" IN EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" );\r\n"); + break; + } + } + + // + // Write ProcessLibraryDestructor list to autogen.c + // + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + break; + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append("VOID\r\n"); + fileBuffer.append("ProcessLibraryDestructorList (\r\n"); + fileBuffer.append(" IN EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" IN EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" )\r\n"); + fileBuffer.append("{\r\n"); + + for (int i = 0; i < libInstanceList.size(); i++) { + if (isFirst) { + fileBuffer.append(" EFI_STATUS Status;\r\n"); + fileBuffer.append("\r\n"); + isFirst = false; + } + fileBuffer.append(" Status = "); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append("(ImageHandle, SystemTable);\r\n"); + fileBuffer.append(" ASSERT_EFI_ERROR (Status);\r\n"); + } + fileBuffer.append("}\r\n"); + break; + } + } + + /** + ExternsDriverBindingToAutoGenC + + This function is to write DRIVER_BINDING, COMPONENT_NAME, + DRIVER_CONFIGURATION, DRIVER_DIAGNOSTIC in AutoGen.c. + + @param fileBuffer String buffer for AutoGen.c + */ + void ExternsDriverBindingToAutoGenC(StringBuffer fileBuffer) + throws BuildException { + + // + // Check what contains. And the number of following elements + // under should be same. 1. DRIVER_BINDING 2. COMPONENT_NAME + // 3.DRIVER_CONFIGURATION 4. DRIVER_DIAGNOSTIC + // + + String[] drvBindList = SurfaceAreaQuery.getDriverBindingArray(); + + // + // If component name protocol,component configuration protocol, + // component diagnostic protocol is not null or empty, check + // if every one have the same number of the driver binding protocol. + // + if (drvBindList == null || drvBindList.length == 0) { + return; + } + + String[] compNamList = SurfaceAreaQuery.getComponentNameArray(); + String[] compConfList = SurfaceAreaQuery.getDriverConfigArray(); + String[] compDiagList = SurfaceAreaQuery.getDriverDiagArray(); + + int BitMask = 0; + + // + // Write driver binding protocol extern to autogen.c + // + for (int i = 0; i < drvBindList.length; i++) { + fileBuffer.append("extern EFI_DRIVER_BINDING_PROTOCOL "); + fileBuffer.append(drvBindList[i]); + fileBuffer.append(";\r\n"); + } + + // + // Write component name protocol extern to autogen.c + // + if (compNamList != null && compNamList.length != 0) { + if (drvBindList.length != compNamList.length) { + throw new BuildException( + "Different number of Driver Binding and Component Name protocols!"); + } + + BitMask |= 0x01; + for (int i = 0; i < compNamList.length; i++) { + fileBuffer.append("extern EFI_COMPONENT_NAME_PROTOCOL "); + fileBuffer.append(compNamList[i]); + fileBuffer.append(";\r\n"); + } + } + + // + // Write driver configration protocol extern to autogen.c + // + if (compConfList != null && compConfList.length != 0) { + if (drvBindList.length != compConfList.length) { + throw new BuildException( + "Different number of Driver Binding and Driver Configuration protocols!"); + } + + BitMask |= 0x02; + for (int i = 0; i < compConfList.length; i++) { + fileBuffer.append("extern EFI_DRIVER_CONFIGURATION_PROTOCOL "); + fileBuffer.append(compConfList[i]); + fileBuffer.append(";\r\n"); + } + } + + // + // Write driver dignastic protocol extern to autogen.c + // + if (compDiagList != null && compDiagList.length != 0) { + if (drvBindList.length != compDiagList.length) { + throw new BuildException( + "Different number of Driver Binding and Driver Configuration protocols!"); + } + + BitMask |= 0x04; + for (int i = 0; i < compDiagList.length; i++) { + fileBuffer.append("extern EFI_DRIVER_DIAGNOSTICS_PROTOCOL "); + fileBuffer.append(compDiagList[i]); + fileBuffer.append(";\r\n"); + } + } + + // + // Write driver module protocol bitmask. + // + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverModelProtocolBitmask = "); + fileBuffer.append(Integer.toString(BitMask)); + fileBuffer.append(";\r\n"); + + // + // Write driver module protocol list entry + // + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gDriverModelProtocolListEntries = "); + + fileBuffer.append(Integer.toString(drvBindList.length)); + fileBuffer.append(";\r\n"); + + // + // Write drive module protocol list to autogen.c + // + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const EFI_DRIVER_MODEL_PROTOCOL_LIST _gDriverModelProtocolList[] = {"); + for (int i = 0; i < drvBindList.length; i++) { + if (i != 0) { + fileBuffer.append(","); + } + fileBuffer.append("\r\n {\r\n"); + fileBuffer.append(" &"); + fileBuffer.append(drvBindList[i]); + fileBuffer.append(", \r\n"); + + if (compNamList != null) { + fileBuffer.append(" &"); + fileBuffer.append(compNamList[i]); + fileBuffer.append(", \r\n"); + } else { + fileBuffer.append(" NULL, \r\n"); + } + + if (compConfList != null) { + fileBuffer.append(" &"); + fileBuffer.append(compConfList[i]); + fileBuffer.append(", \r\n"); + } else { + fileBuffer.append(" NULL, \r\n"); + } + + if (compDiagList != null) { + fileBuffer.append(" &"); + fileBuffer.append(compDiagList[i]); + fileBuffer.append(", \r\n"); + } else { + fileBuffer.append(" NULL, \r\n"); + } + fileBuffer.append(" }"); + } + fileBuffer.append("\r\n};\r\n"); + } + + /** + ExternCallBackToAutoGenC + + This function adds and + infomation to AutoGen.c + + @param fileBuffer String buffer for AutoGen.c + @throws BuildException + **/ + void ExternCallBackToAutoGenC(StringBuffer fileBuffer) + throws BuildException { + String[] setVirtualList = SurfaceAreaQuery + .getSetVirtualAddressMapCallBackArray(); + String[] exitBootList = SurfaceAreaQuery + .getExitBootServicesCallBackArray(); + String moduleType = SurfaceAreaQuery.getModuleType(); + boolean UefiOrDxeModule = false; + int Count = 0; + int i; + + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + // + // Entry point lib for these module types needs to know the count + // of entryPoint. + // + UefiOrDxeModule = true; + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gDriverSetVirtualAddressMapEventCount = "); + + // + // If the list is not valid or has no entries set count to zero else + // set count to the number of valid entries + // + Count = 0; + if (setVirtualList != null) { + for (i = 0; i < setVirtualList.length; i++) { + if (setVirtualList[i].equalsIgnoreCase("")) { + break; + } + } + Count = i; + } + + fileBuffer.append(Integer.toString(Count)); + fileBuffer.append(";\r\n\r\n"); + break; + default: + break; + } + + if (setVirtualList == null) { + if (UefiOrDxeModule) { + // + // No data so make a NULL list + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const EFI_EVENT_NOTIFY _gDriverSetVirtualAddressMapEvent[] = {\r\n"); + fileBuffer.append(" NULL\r\n"); + fileBuffer.append("};\r\n\r\n"); + } + } else { + // + // Write SetVirtualAddressMap function definition. + // + for (i = 0; i < setVirtualList.length; i++) { + if (setVirtualList[i].equalsIgnoreCase("")) { + break; + } + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\n"); + fileBuffer.append(setVirtualList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" IN EFI_EVENT Event,\r\n"); + fileBuffer.append(" IN VOID *Context\r\n"); + fileBuffer.append(" );\r\n\r\n"); + } + + // + // Write SetVirtualAddressMap entry point array. + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const EFI_EVENT_NOTIFY _gDriverSetVirtualAddressMapEvent[] = {"); + for (i = 0; i < setVirtualList.length; i++) { + if (setVirtualList[i].equalsIgnoreCase("")) { + break; + } + + if (i == 0) { + fileBuffer.append("\r\n "); + } else { + fileBuffer.append(",\r\n "); + } + + fileBuffer.append(setVirtualList[i]); + } + if (Count == 0) { + fileBuffer.append("\r\n NULL"); + } + fileBuffer.append("\r\n};\r\n\r\n"); + } + + if (UefiOrDxeModule) { + // + // Entry point lib for these module types needs to know the count. + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gDriverExitBootServicesEventCount = "); + + // + // If the list is not valid or has no entries set count to zero else + // set count to the number of valid entries. + // + Count = 0; + if (exitBootList != null) { + if (setVirtualList != null) { + for (i = 0; i < exitBootList.length; i++) { + if (exitBootList[i].equalsIgnoreCase("")) { + break; + } + } + Count = i; + } + } + fileBuffer.append(Integer.toString(Count)); + fileBuffer.append(";\r\n\r\n"); + } + + if (exitBootList == null) { + if (UefiOrDxeModule) { + // + // No data so make a NULL list. + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const EFI_EVENT_NOTIFY _gDriverExitBootServicesEvent[] = {\r\n"); + fileBuffer.append(" NULL\r\n"); + fileBuffer.append("};\r\n\r\n"); + } + } else { + // + // Write DriverExitBootServices function definition. + // + for (i = 0; i < exitBootList.length; i++) { + if (exitBootList[i].equalsIgnoreCase("")) { + break; + } + + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\n"); + fileBuffer.append(exitBootList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" IN EFI_EVENT Event,\r\n"); + fileBuffer.append(" IN VOID *Context\r\n"); + fileBuffer.append(" );\r\n\r\n"); + } + + // + // Write DriverExitBootServices entry point array. + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const EFI_EVENT_NOTIFY _gDriverExitBootServicesEvent[] = {"); + for (i = 0; i < exitBootList.length; i++) { + if (exitBootList[i].equalsIgnoreCase("")) { + break; + } + + if (i == 0) { + fileBuffer.append("\r\n "); + } else { + fileBuffer.append(",\r\n "); + } + fileBuffer.append(exitBootList[i]); + } + if (Count == 0) { + fileBuffer.append("\r\n NULL"); + } + fileBuffer.append("\r\n};\r\n\r\n"); + } + + } + +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java b/Tools/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java new file mode 100644 index 0000000000..77404d4007 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java @@ -0,0 +1,306 @@ +/**@file + AutogenLibOrder class. + + This class is to reorder library instance sequence according to library + dependence. + + 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.autogen; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.xmlbeans.XmlObject; +import org.tianocore.LibraryClassDocument.LibraryClass; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.SurfaceAreaQuery; + +/** + This class This class is to reorder library instance sequence according to + library dependence. +**/ +public class AutogenLibOrder { + /// + /// The map of library class and its library instance. + /// + private Map libClassMap = new HashMap(); + + /// + /// The map of library instance and its implemet instance. + /// + private Map libInstanceMap = new HashMap(); + + /// + /// List of library instance. It is String[3] list, String[0] is libraryName, + /// String[1] is libraryConstructor name, String[2] is libDestructor name. + /// + private List libInstanceList = new ArrayList(); + + /** + Constructor function + + This function mainly initialize some member variable. + + @param libraryList List of the library instance. + @throws Exception + **/ + AutogenLibOrder(List libraryList) throws Exception { + String[] libInstance = new String[3]; + LibraryClass[] libClassDeclList = null; + LibraryClass[] libClassConsmList = null; + + for (int i = 0; i < libraryList.size(); i++) { + // + // Add libraryInstance in to libInstanceList. + // + libInstance[0] = libraryList.get(i); + Map libDoc = GlobalData.getDoc(libInstance[0]); + SurfaceAreaQuery.push(libDoc); + libInstance[1] = SurfaceAreaQuery.getLibConstructorName(); + libInstance[2] = SurfaceAreaQuery.getLibDestructorName(); + libInstanceList.add(libInstance.clone()); + + // + // Add library instance and consumed library class list to + // libInstanceMap. + // + libClassConsmList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysConsumed); + if (libClassConsmList != null) { + String[] classStr = new String[libClassConsmList.length]; + for (int k = 0; k < libClassConsmList.length; k++) { + classStr[k] = libClassConsmList[k].getStringValue(); + } + if (this.libInstanceMap.containsKey(libInstance[0])) { + throw new Exception( + libInstance[0] + + "this library instance is already exist, please check you library instance list!"); + } else { + this.libInstanceMap.put(libInstance[0], classStr); + } + } + + // + // Add library class and library instance map. + // + libClassDeclList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysProduced); + if (libClassDeclList != null) { + for (int j = 0; j < libClassDeclList.length; j++) { + if (this.libClassMap.containsKey(libClassDeclList[j] + .getStringValue())) { + System.out.println(libClassDeclList[j].getStringValue() + + " class is already implement by " + + this.libClassMap.get(libClassDeclList[j] + .getStringValue())); + throw new Exception(libClassDeclList + + " is already have library instance!"); + } else { + this.libClassMap.put(libClassDeclList[j] + .getStringValue(), libInstance[0]); + } + } + } + SurfaceAreaQuery.pop(); + } + + // + // Check is the library instance list meet the require; + // + for (int s = 0; s < this.libInstanceList.size(); s++) { + String[] libClass = this.libInstanceMap.get(this.libInstanceList + .get(s)); + if (libClass != null) { + for (int t = 0; t < libClass.length; t++) { + if (this.libClassMap.get(libClass[t]) == null) { + // + // Note: There exist a kind of module which depend on + // library class with no instance or whose instance will + // never be linked into the module. + // For this satuation, the module has the description of + // library class in MSA file but no description of + // corresponding library instance in MBD file. There + // will be a warnig message given here after a standard + // log way has been decided. + // + } + } + } + } + } + + /** + orderLibInstance + + This function reorder the library instance according the library class + dependency. + + @return List which content the ordered library instance. + **/ + List orderLibInstance() { + List orderList = new ArrayList(); + // + // Stack of node which track the library instance name ant its visiting + // flag. + // + List stackList = new ArrayList(); + int stackSize = 0; + String libInstance = null; + if (libInstanceList.size() < 0) { + return null; + } + + // + // Reorder the library instance. + // + for (int i = 0; i < libInstanceList.size(); i++) { + // + // If library instance is already in the order list skip it. + // + if (isInLibInstance(orderList, libInstanceList.get(i)[0])) { + continue; + } + + Node node = new Node(libInstanceList.get(i)[0], false); + // + // Use stack to reorder library instance. + // Push node to stack. + // + stackList.add(node); + while (stackList.size() > 0) { + stackSize = stackList.size() - 1; + // + // Pop the first node in stack. If the node flag has been visited + // add this node to orderlist and remove it from stack. + // + if (stackList.get(stackSize).isVisit) { + if (!isInLibInstance(orderList, + stackList.get(stackSize).nodeName)) { + orderList.add(stackList.get(stackSize).nodeName); + stackList.remove(stackSize); + } + + } else { + // + // Get the node value and set visit flag as true. + // + stackList.get(stackList.size() - 1).isVisit = true; + String[] libClassList = this.libInstanceMap.get(stackList + .get(stackSize).nodeName); + // + // Push the node dependence library instance to the stack. + // + if (libClassList != null) { + for (int j = 0; j < libClassList.length; j++) { + libInstance = this.libClassMap.get(libClassList[j]); + if (libInstance != null + && !isInLibInstance(orderList, libInstance)) { + // + // If and only if the currently library instance + // is not in stack and it have constructor or + // destructor function, push this library + // instacne in stack. + // + if (!isInStackList(stackList, this.libClassMap + .get(libClassList[j])) && isHaveConsDestructor(libInstance)) { + stackList.add(new Node(this.libClassMap + .get(libClassList[j]), false)); + } + } + } + } + } + } + } + return orderList; + } + + /** + isInLibInstance + + This function check does the library instance already in the list. + + @param list List of the library instance. + @param instanceName Name of library instance. + @return "true" the library instance in list | + "false" the library instance is not in list. + **/ + private boolean isInLibInstance(List list, String instanceName) { + for (int i = 0; i < list.size(); i++) { + if (instanceName.equalsIgnoreCase(list.get(i).toString())) { + return true; + } + } + return false; + } + + /** + isInStackList + + This function check if the node already in the stack. + + @param list Stack. + @param nodeName Name of node. + @return "true" if node have in stack | + "false" if node don't in stack. + **/ + private boolean isInStackList(List list, String nodeName) { + for (int i = 0; i < list.size(); i++) { + if (nodeName.equalsIgnoreCase(list.get(i).nodeName)) { + return true; + } + } + return false; + } + + /** + isHaveConsDestructor + + This function check if the library have constructor or destructor + function. + + @param libName Name of library + @return "true" if library have constructor or desconstructor | + "false" if library don't have constructor + and desconstructor. + **/ + private boolean isHaveConsDestructor (String libName){ + for (int i = 0; i < libInstanceList.size(); i++){ + if (libInstanceList.get(i)[0].equalsIgnoreCase(libName)){ + if (libInstanceList.get(i)[1] != null || libInstanceList.get(i)[2] != null){ + return true; + } + } + } + return false; + } +} + +/** + Node + + This class is used as stack node. + + **/ +class Node { + String nodeName; + + boolean isVisit; + + Node(String name, boolean isVisit) { + this.nodeName = name; + this.isVisit = false; + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/autogen/CommonDefinition.java b/Tools/Source/GenBuild/org/tianocore/build/autogen/CommonDefinition.java new file mode 100644 index 0000000000..2490d97467 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/autogen/CommonDefinition.java @@ -0,0 +1,257 @@ +/** @file + CommonDefinition class. + + This class is to define some common marcos and funcions, which used by AutoGen. + + 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.autogen; + +/** + CommonDefinition + + This class is to define some common marcos, which used by AutoGen. + +**/ +public class CommonDefinition { + public final static String spdSuffix = ".spd"; + public final static String mbdSuffix = ".mbd"; + public final static String msaSuffix = ".msa"; + public final static String LibraryStr = "LIBRARY"; + public final static String autoGenHbegin = "extern int __make_me_compile_correctly;\r\n"; + public final static String include = "#include"; + public final static String autoGenCLine1 = "\r\n"; + + public final static String autoGenCLine2 = "const UINT8 _gDebugPropertyMask " + + "= DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED" + + " | DEBUG_PROPERTY_DEBUG_PRINT_ENABLED" + + " | DEBUG_PROPERTY_DEBUG_CODE_ENABLED;\r\n"; + + public final static String autoGenCLine3 = "const UINTN _gModuleDefaultErrorLevel" + + " = EFI_D_ERROR | EFI_D_LOAD;\r\n"; + + public final static String autoGenHLine1 = "#define EFI_SPECIFICATION_VERSION 0x00020000\r\n"; + public final static String autoGenHVersionDefault = "#define EFI_SPECIFICATION_VERSION 0x00000000\r\n"; + public final static String autoGenHLine2 = "#define EDK_RELEASE_VERSION 0x00090000\r\n"; + public final static String autoGenHReleaseDefault = "#define EDK_RELEASE_VERSION 0x00000000\r\n"; + + public final static String includeAutogenH = "#include \r\n" ; + + public final static String gEfi = "gEfi"; + public final static String protocolGuid = "ProtocolGuid"; + public final static String ppiGuid = "PpiGuid"; + public final static String guidGuid = "Guid"; + + // + // AutoGen.h and AutoGen.c file's header + // + public final static String autogenHNotation = + "/**\r\n" + + " DO NOT EDIT\r\n" + + " FILE auto-generated by GenBuild tasks\r\n" + + " Module name:\r\n" + + " AutoGen.h\r\n" + + " Abstract:" + + " Auto-generated AutoGen.h for building module or library.\r\n" + + "**/\r\n\r\n"; + + public final static String autogenCNotation = + "/**\r\n" + + " DO NOT EDIT\r\n" + + " FILE auto-generated by GenBuild tasks\r\n" + + " Module name:\r\n" + + " AutoGen.c\r\n" + + " Abstract:" + + " Auto-generated AutoGen.c for building module or library.\r\n" + + "**/\r\n\r\n"; + + // + // module type + // + public final static int ModuleTypeBase = 0; + public final static int ModuleTypeSec = 1; + public final static int ModuleTypePeiCore = 2; + public final static int ModuleTypePeim = 3; + public final static int ModuleTypeDxeCore = 4; + public final static int ModuleTypeDxeDriver = 5; + public final static int ModuleTypeDxeRuntimeDriver = 6; + public final static int ModuleTypeDxeSmmDriver = 7; + public final static int ModuleTypeDxeSalDriver = 8; + public final static int ModuleTypeUefiDriver = 9; + public final static int ModuleTypeUefiApplication = 10; + public final static int ModuleTypeUnknown = 11; + + + // + // component type + // + public final static int ComponentTypeNull = 0; + public final static int ComponentTypeApriori = 1; + public final static int ComponentTypeSec = 2; + public final static int ComponentTypeLibrary = 3; + public final static int ComponentTypeFvImageFile = 4; + public final static int ComponentTypeBsDriver = 5; + public final static int ComponentTypeRtDriver = 6; + public final static int ComponentTypeSalRtDriver =7; + public final static int ComponentTypePe32Peim = 8; + public final static int ComponentTypePicPeim =9; + public final static int ComponentTypeCombinedPeimDriver =10; + public final static int ComponentTypePeiCore = 11; + public final static int ComponentTypeDxeCore = 12; + public final static int ComponentTypeApplication = 13; + public final static int ComponentTypeBsDriverEfi = 14; + public final static int ComponentTypeShellApp = 15; + public final static int ComponentTypeBinary =16; + public final static int ComponentTypeLogo = 17; + public final static int ComponentTypeCustomBuild = 18; + public final static int ComponentTypeUnknown = 19; + + + // + // Usaged style + // + public final static String AlwaysConsumed = "ALWAYS_CONSUMED"; + public final static String AlwaysProduced = "ALWAYS_PRODUCED"; + + + public static class MyEnum { + String moduleTypeStr; + int type; + + MyEnum (String str, int type) { + this.type = type; + this.moduleTypeStr = str; + } + + int ForInt(String str) { + if (str.equals(this.moduleTypeStr)) { + return this.type; + } else + return -1; + } + } + + // + // Module type + // + public static final MyEnum[] moduleEnum = new MyEnum[] { + new MyEnum("BASE", ModuleTypeBase), + new MyEnum("SEC", ModuleTypeSec), + new MyEnum("PEI_CORE", ModuleTypePeiCore), + new MyEnum("PEIM", ModuleTypePeim), + new MyEnum("DXE_CORE", ModuleTypeDxeCore), + new MyEnum("DXE_DRIVER", ModuleTypeDxeRuntimeDriver), + new MyEnum("DXE_RUNTIME_DRIVER", ModuleTypeDxeRuntimeDriver), + new MyEnum("DXE_SAL_DRIVER", ModuleTypeDxeSmmDriver), + new MyEnum("DXE_SMM_DRIVER", ModuleTypeDxeSalDriver), + new MyEnum("UEFI_DRIVER", ModuleTypeUefiDriver), + new MyEnum("UEFI_APPLICATION", ModuleTypeUefiApplication) }; + + // + // Component type + // + public static final MyEnum[] componentEnum = new MyEnum[]{ + new MyEnum("APRIORI", ComponentTypeApriori), + new MyEnum("SEC", ComponentTypeSec), + new MyEnum("LIBRARY", ComponentTypeLibrary), + new MyEnum("FV_IMAGE_FILE", ComponentTypeFvImageFile), + new MyEnum("BS_DRIVER", ComponentTypeBsDriver), + new MyEnum("RT_DRIVER", ComponentTypeRtDriver), + new MyEnum("SAL_RT_DRIVER", ComponentTypeSalRtDriver), + new MyEnum("PE32_PEIM", ComponentTypePe32Peim), + new MyEnum("PIC_PEIM", ComponentTypePicPeim), + new MyEnum("COMBINED_PEIM_DRIVER", ComponentTypeCombinedPeimDriver), + new MyEnum("PEI_CORE", ComponentTypePeiCore), + new MyEnum("DXE_CORE", ComponentTypeDxeCore), + new MyEnum("APPLICATION", ComponentTypeApplication), + new MyEnum("BS_DRIVER_EFI", ComponentTypeBsDriverEfi), + new MyEnum("SHELLAPP", ComponentTypeShellApp), + new MyEnum("BINARY", ComponentTypeBinary), + new MyEnum("LOGO", ComponentTypeLogo), + new MyEnum("CUSTOM_BUILD", ComponentTypeCustomBuild) + }; + + /** + getModuleType + + This function get the module type value according module type string. + + @param moduleTypeStr String of modlue type. + @return + **/ + static public int getModuleType(String moduleTypeStr) { + int returnValue = -1; + for (int i = 0; i < CommonDefinition.moduleEnum.length; i++) { + returnValue = CommonDefinition.moduleEnum[i].ForInt(moduleTypeStr); + if (returnValue != -1) { + return returnValue; + } + } + return CommonDefinition.ModuleTypeUnknown; + } + + /** + getComponentType + + This function get the component type value according commponet type + string. + + @param componentTypeStr String of component type. + @return + **/ + static public int getComponentType (String componentTypeStr){ + int returnValue = -1; + for (int i = 0; i < CommonDefinition.componentEnum.length; i++) { + returnValue = CommonDefinition.componentEnum[i].ForInt(componentTypeStr); + if (returnValue != -1) { + return returnValue; + } + } + return CommonDefinition.ComponentTypeUnknown; + } + + /** + getComponentTypeString + + This function get the commponet type string according component type value. + + @param componentType Integer value of component type. + @return + **/ + static public String getComponentTypeString (int componentType) { + if ((componentType > CommonDefinition.ComponentTypeUnknown) || + (componentType < CommonDefinition.ComponentTypeNull)) { + return null; + } + for (int index = 0; index < CommonDefinition.componentEnum.length; index ++) { + if (componentType == CommonDefinition.componentEnum[index].type) { + return CommonDefinition.componentEnum[index].moduleTypeStr; + } + } + return null; + } + + /** + isLibraryComponent + + This function is to check does componet is library according to commponet + type value. + + @param componentType Integer value of component type. + @return + **/ + static public boolean isLibraryComponent (int componentType) { + if (ComponentTypeLibrary == componentType) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdModuleIdentification.java b/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdModuleIdentification.java new file mode 100644 index 0000000000..261cf58a35 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdModuleIdentification.java @@ -0,0 +1,131 @@ +/** @file + Java class FpdModuleIdentification is used to present a module identification + from BaseName, GUID, Version, PackageName, and ARCH. + +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.fpd; + +/** + This class is used to identify a module with BaseName, GUID, Version, PackageName + and ARCH. + + @since GenBuild 1.0 + **/ +public class FpdModuleIdentification { + + private String arch; + + private String fvBinding; + + private String baseName; + + private String packageName; + + private String guid; + + private String version; + + private String sequence; + + /** + + @param baseName the base name of the module + @param guid the GUID of the module + @param arch the ARCH of the module + **/ + public FpdModuleIdentification(String baseName, String guid, String arch){ + this.baseName = baseName; + this.guid = guid; + this.arch = arch; + } + + /** + Override java.lang.Object#equals. + +

Currently, use BaseName and ARCH to identify a module. It will enhance + in the next version.

+ + @see java.lang.Object#equals(java.lang.Object) + **/ + public boolean equals(Object obj) { + if (obj instanceof FpdModuleIdentification) { + FpdModuleIdentification moduleIdObj = (FpdModuleIdentification)obj; + if ( baseName.equalsIgnoreCase(moduleIdObj.baseName) && arch.equalsIgnoreCase(moduleIdObj.arch)) { + return true; + } + // TBD + return false; + } + else { + return super.equals(obj); + } + } + + public void setArch(String arch) { + this.arch = arch; + } + + public void setFvBinding(String fvBinding) { + this.fvBinding = fvBinding; + } + + public void setSequence(String sequence) { + this.sequence = sequence; + } + + public String toString(){ + return arch + ":" + guid + "_" + baseName; + } + + public void setBaseName(String baseName) { + this.baseName = baseName; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getArch() { + return arch; + } + + public String getBaseName() { + return baseName; + } + + public String getFvBinding() { + return fvBinding; + } + + public String getGuid() { + return guid; + } + + public String getPackageName() { + return packageName; + } + + public String getSequence() { + return sequence; + } + + public String getVersion() { + return version; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java b/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java new file mode 100644 index 0000000000..99b7242ebc --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java @@ -0,0 +1,808 @@ +/** @file + This file is ANT task FpdParserTask. + + FpdParserTask is used to parse FPD (Framework Platform Description) and generate + build.out.xml. It is for Package or Platform build use. + +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.fpd; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Property; +import org.apache.xmlbeans.XmlObject; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.OutputManager; +import org.tianocore.build.global.OverrideProcess; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.pcd.action.CollectPCDAction; +import org.tianocore.build.pcd.action.ActionMessage; +import org.tianocore.BuildOptionsDocument; +import org.tianocore.FrameworkPlatformDescriptionDocument; +import org.tianocore.ModuleSADocument; + + +/** + FpdParserTask is an ANT task. The main function is parsing FPD + XML file and generating its ANT build script for Platform or Package. + +

The usage is (take NT32 Platform for example):

+ +
+    <FPDParser fpdfilename="Build\Nt32.fpd" />
+  
+ +

The task will initialize all information through parsing Framework Database, + SPD, Tool chain configuration files.

+ + @since GenBuild 1.0 +**/ +public class FpdParserTask extends Task { + + /// + /// FV dir: ${PLATFORM_DIR}/Build/FV + /// + public static final String FV_OUTPUT_DIR = "${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "FV"; + + private File fpdFilename; + + private File guiddatabase; + + /// + /// Keep platform buildoption information + /// + public static XmlObject platformBuildOptions = null; + + /// + /// Mapping from modules identification to out put file name + /// + private Map outfiles = new LinkedHashMap(); + + /// + /// Mapping from FV name to its modules + /// + private Map > fvs = new HashMap >(); + + /// + /// Mapping from sequence number to its modules + /// + private Map > sequences = new HashMap >(); + + /// + /// FpdParserTask can specify some ANT properties. + /// + private Vector properties = new Vector(); + + private String info = "====================================================================\n" + + "DO NOT EDIT \n" + + "File auto-generated by build utility\n" + + "\n" + + "Abstract:\n" + + "Auto-generated ANT build file for building of EFI Modules/Platforms\n" + + "====================================================================="; + + /** + Public construct method. It is necessary for ANT task. + **/ + public FpdParserTask () { + } + + /** + ANT task's entry method. The main steps is described as following: + +
    +
  • Initialize global information (Framework DB, SPD files and all MSA files + listed in SPD). This step will execute only once in whole build process;
  • +
  • Parse specified FPD file;
  • +
  • Generate FV.inf files;
  • +
  • Generate build.out.xml file for Flatform or Package build;
  • +
  • Collect PCD information.
  • +
+ + @throws BuildException + Surface area is not valid. + **/ + public void execute() throws BuildException { + OutputManager.update(getProject()); + // + // Parse DB and SPDs files. Initialize Global Data + // + GlobalData.initInfo("Tools" + File.separatorChar + "Conf" + File.separatorChar + "FrameworkDatabase.db", getProject() + .getProperty("WORKSPACE_DIR")); + // + // Parse FPD file + // + parseFpdFile(); + // + // Gen Fv.inf files + // + genFvInfFiles(); + // + // Gen build.xml + // + genBuildFile(); + // + // Collect PCD information + // + collectPCDInformation (); + } + + /** + Generate Fv.inf files. The Fv.inf file is composed with four + parts: Options, Attributes, Components and Files. The Fv.inf files + will be under ${PLATFOMR_DIR}\Build\Fv. + + @throws BuildException + File write FV.inf files error. + **/ + private void genFvInfFiles() throws BuildException{ + String[] validFv = SurfaceAreaQuery.getFpdValidImageNames(); + for (int i = 0; i < validFv.length; i++) { + getProject().setProperty("FV_FILENAME", validFv[i].toUpperCase()); + // + // Get all global variables from FPD and set them to properties + // + String[][] globalVariables = SurfaceAreaQuery + .getFpdGlobalVariable(); + for (int j = 0; j < globalVariables.length; j++) { + getProject().setProperty(globalVariables[j][0], + globalVariables[j][1]); + } + + File fvFile = new File(getProject().replaceProperties( + FV_OUTPUT_DIR + File.separatorChar + validFv[i].toUpperCase() + + ".inf")); + fvFile.getParentFile().mkdirs(); + + try { + FileWriter fw = new FileWriter(fvFile); + BufferedWriter bw = new BufferedWriter(fw); + // + // Options + // + String[][] options = SurfaceAreaQuery.getFpdOptions(validFv[i]); + if (options.length > 0) { + bw.write("[options]"); + bw.newLine(); + for (int j = 0; j < options.length; j++) { + StringBuffer str = new StringBuffer(100); + str.append(options[j][0]); + while (str.length() < 40) { + str.append(' '); + } + str.append("= "); + str.append(options[j][1]); + bw.write(getProject().replaceProperties(str.toString())); + bw.newLine(); + } + bw.newLine(); + } + // + // Attributes; + // + String[][] attributes = SurfaceAreaQuery + .getFpdAttributes(validFv[i]); + if (attributes.length > 0) { + bw.write("[attributes]"); + bw.newLine(); + for (int j = 0; j < attributes.length; j++) { + StringBuffer str = new StringBuffer(100); + str.append(attributes[j][0]); + while (str.length() < 40) { + str.append(' '); + } + str.append("= "); + str.append(attributes[j][1]); + bw + .write(getProject().replaceProperties( + str.toString())); + bw.newLine(); + } + bw.newLine(); + } + // + // Components + // + String[][] components = SurfaceAreaQuery + .getFpdComponents(validFv[i]); + if (components.length > 0) { + bw.write("[components]"); + bw.newLine(); + for (int j = 0; j < components.length; j++) { + StringBuffer str = new StringBuffer(100); + str.append(components[j][0]); + while (str.length() < 40) { + str.append(' '); + } + str.append("= "); + str.append(components[j][1]); + bw + .write(getProject().replaceProperties( + str.toString())); + bw.newLine(); + } + bw.newLine(); + } + // + // Files + // + Set filesSet = fvs.get(validFv[i].toUpperCase()); + if (filesSet != null) { + FpdModuleIdentification[] files = filesSet.toArray(new FpdModuleIdentification[filesSet + .size()]); + bw.write("[files]"); + bw.newLine(); + for (int j = 0; j < files.length; j++) { + String str = outfiles.get(files[j]); + bw.write(getProject().replaceProperties( + "EFI_FILE_NAME = " + str)); + bw.newLine(); + } + } + bw.flush(); + bw.close(); + fw.close(); + } catch (Exception e) { + throw new BuildException("Generate Fv.inf file failed. \n" + e.getMessage()); + } + } + } + + /** + Parse FPD file. + + @throws BuildException + FPD file is not valid. + **/ + private void parseFpdFile() throws BuildException { + try { + FrameworkPlatformDescriptionDocument doc = (FrameworkPlatformDescriptionDocument) XmlObject.Factory + .parse(fpdFilename); + if ( ! doc.validate() ){ + throw new BuildException("FPD file is invalid."); + } + platformBuildOptions = doc.getFrameworkPlatformDescription() + .getBuildOptions(); + HashMap map = new HashMap(); + map.put("FrameworkPlatformDescription", doc); + SurfaceAreaQuery.setDoc(map); + // + // Parse all list modules SA + // + parseModuleSAFiles(); + SurfaceAreaQuery.setDoc(map); + } catch (Exception e) { + throw new BuildException("Load FPD file [" + fpdFilename.getPath() + + "] error. \n" + e.getMessage()); + } + } + + /** + Parse all modules listed in FPD file. + **/ + private void parseModuleSAFiles() { + ModuleSADocument.ModuleSA[] moduleSAs = SurfaceAreaQuery + .getFpdModules(); + // + // For every Module lists in FPD file. + // + for (int i = 0; i < moduleSAs.length; i++) { + String defaultFv = "NULL"; + String defaultArch = "IA32"; + String baseName = moduleSAs[i].getModuleName(); + if (baseName == null) { + System.out.println("Warning: Module Name is not specified."); + continue; + } + String fvBinding = moduleSAs[i].getFvBinding(); + // + // If the module do not specify any FvBinding, use the default value. + // Else update the default FvBinding value to this value. + // + if (fvBinding == null) { + fvBinding = defaultFv; + } + else { + defaultFv = fvBinding; + } + String arch; + // + // If the module do not specify any Arch, use the default value. + // Else update the default Arch value to this value. + // + if (moduleSAs[i].getArch() == null ){ + arch = defaultArch; + } + else { + arch = moduleSAs[i].getArch().toString(); + defaultArch = arch; + } + Map msaMap = GlobalData.getNativeMsa(baseName); + Map mbdMap = GlobalData.getNativeMbd(baseName); + Map map = new HashMap(); + // + // Whether the Module SA has parsed before or not + // + if (!GlobalData.isModuleParsed(baseName)) { + OverrideProcess op = new OverrideProcess(); + // + // using overriding rules + // Here we can also put platform Build override + // + map = op.override(mbdMap, msaMap); + Map overrideMap = op.override( + getPlatformOverrideInfo(moduleSAs[i]), + OverrideProcess.deal(map)); + GlobalData.registerModule(baseName, overrideMap); + } else { + map = GlobalData.getDoc(baseName); + } + SurfaceAreaQuery.setDoc(map); + String guid = SurfaceAreaQuery.getModuleGuid(); + String componentType = SurfaceAreaQuery.getComponentType(); + FpdModuleIdentification moduleId = new FpdModuleIdentification(baseName, guid, arch); + updateFvs(fvBinding, moduleId); + outfiles.put(moduleId, "${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + + "${TARGET}" + File.separatorChar + arch + + File.separatorChar + guid + "-" + baseName + + getSuffix(componentType)); + } + } + + /** + Add the current module to corresponding FV. + + @param fvName current FV name + @param moduleName current module identification + **/ + private void updateFvs(String fvName, FpdModuleIdentification moduleName) { + String upcaseFvName = fvName.toUpperCase(); + if (fvs.containsKey(upcaseFvName)) { + Set set = fvs.get(upcaseFvName); + set.add(moduleName); + } else { + Set set = new LinkedHashSet(); + set.add(moduleName); + fvs.put(upcaseFvName, set); + } + } + + /** + Get the suffix based on component type. Current relationship are listed: + +
+        ComponentType   Suffix
+           APPLICATION          .APP
+           SEC                  .SEC
+           PEI_CORE             .PEI
+           PE32_PEIM            .PEI
+           RELOCATABLE_PEIM     .PEI
+           PIC_PEIM             .PEI
+           COMBINED_PEIM_DRIVER .PEI
+           TE_PEIM              .PEI
+           LOGO                 .FFS
+           others               .DXE
+      
+ + @param componentType component type + @return + @throws BuildException + If component type is null + **/ + public static String getSuffix(String componentType) throws BuildException{ + if (componentType == null) { + throw new BuildException("Component type is not specified."); + } + String str = ".DXE"; + if (componentType.equalsIgnoreCase("APPLICATION")) { + str = ".APP"; + } else if (componentType.equalsIgnoreCase("SEC")) { + str = ".SEC"; + } else if (componentType.equalsIgnoreCase("PEI_CORE")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("PE32_PEIM")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("RELOCATABLE_PEIM")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("PIC_PEIM")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("COMBINED_PEIM_DRIVER")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("TE_PEIM")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("LOGO")) { + str = ".FFS"; + } + return str; + } + + /** + Parse module surface are info described in FPD file and put them into map. + + @param sa module surface area info descibed in FPD file + @return map list with top level elements + **/ + private Map getPlatformOverrideInfo( + ModuleSADocument.ModuleSA sa) { + Map map = new HashMap(); + map.put("SourceFiles", sa.getSourceFiles()); + map.put("Includes", sa.getIncludes()); + map.put("Libraries", sa.getLibraries()); + map.put("Protocols", sa.getProtocols()); + map.put("Events", sa.getEvents()); + map.put("Hobs", sa.getHobs()); + map.put("PPIs", sa.getPPIs()); + map.put("Variables", sa.getVariables()); + map.put("BootModes", sa.getBootModes()); + map.put("SystemTables", sa.getSystemTables()); + map.put("DataHubs", sa.getDataHubs()); + map.put("Formsets", sa.getFormsets()); + map.put("Guids", sa.getGuids()); + map.put("Externs", sa.getExterns()); + map.put("BuildOptions", platformBuildOptions); + return map; + } + + /** + Generate build.out.xml file. + + @throws BuildException + build.out.xml XML document create error + **/ + private void genBuildFile() throws BuildException { + DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dombuilder = domfac.newDocumentBuilder(); + Document document = dombuilder.newDocument(); + Comment rootComment = document.createComment(info); + // + // create root element and its attributes + // + Element root = document.createElement("project"); + root.setAttribute("name", getProject().getProperty("PLATFORM")); + root.setAttribute("default", "main"); + root.setAttribute("basedir", "."); + // + // element for External ANT tasks + // + root.appendChild(document.createComment("Apply external ANT tasks")); + Element ele = document.createElement("taskdef"); + ele.setAttribute("resource", "GenBuild.tasks"); + root.appendChild(ele); + + ele = document.createElement("taskdef"); + ele.setAttribute("resource", "frameworktasks.tasks"); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("environment", "env"); + root.appendChild(ele); + // + // Default Target + // + root.appendChild(document.createComment("Default target")); + ele = document.createElement("target"); + ele.setAttribute("name", "main"); + ele.setAttribute("depends", "modules, fvs"); + root.appendChild(ele); + // + // Modules Target + // + root.appendChild(document.createComment("Modules target")); + ele = document.createElement("target"); + ele.setAttribute("name", "modules"); + + Set set = outfiles.keySet(); + Iterator iter = set.iterator(); + while (iter.hasNext()) { + FpdModuleIdentification moduleId = (FpdModuleIdentification) iter.next(); + String baseName = moduleId.getBaseName(); + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + moduleEle.setAttribute("target", baseName); + // + // ARCH + // + Element property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", moduleId.getArch()); + moduleEle.appendChild(property); + // + // PACKAGE_DIR + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(baseName)); + moduleEle.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData + .getPackageNameForModule(baseName)); + moduleEle.appendChild(property); + ele.appendChild(moduleEle); + } + root.appendChild(ele); + // + // FVS Target + // + root.appendChild(document.createComment("FVs target")); + ele = document.createElement("target"); + ele.setAttribute("name", "fvs"); + + String[] validFv = SurfaceAreaQuery.getFpdValidImageNames(); + for (int i = 0; i < validFv.length; i++) { + String inputFile = FV_OUTPUT_DIR + "" + File.separatorChar + + validFv[i].toUpperCase() + ".inf"; + Element fvEle = document.createElement("genfvimage"); + fvEle.setAttribute("infFile", inputFile); + ele.appendChild(fvEle); + Element moveEle = document.createElement("move"); + moveEle.setAttribute("file", validFv[i].toUpperCase() + ".fv"); + moveEle.setAttribute("todir", FV_OUTPUT_DIR); + ele.appendChild(moveEle); + } + root.appendChild(ele); + + boolean isUnified = false; + BuildOptionsDocument.BuildOptions buildOptions = (BuildOptionsDocument.BuildOptions)platformBuildOptions; + if (buildOptions.getOutputDirectory() != null){ + if (buildOptions.getOutputDirectory().getIntermediateDirectories() != null){ + if (buildOptions.getOutputDirectory().getIntermediateDirectories().toString().equalsIgnoreCase("UNIFIED")){ + isUnified = true; + } + } + } + // + // Clean Target + // + root.appendChild(document.createComment("Clean target")); + ele = document.createElement("target"); + ele.setAttribute("name", "clean"); + + if (isUnified) { + Element cleanEle = document.createElement("delete"); + cleanEle.setAttribute("includeemptydirs", "true"); + Element filesetEle = document.createElement("fileset"); + filesetEle.setAttribute("dir", getProject().getProperty("PLATFORM_DIR") + File.separatorChar + "Build" + File.separatorChar + "${TARGET}"); + filesetEle.setAttribute("includes", "**/OUTPUT/**"); + cleanEle.appendChild(filesetEle); + ele.appendChild(cleanEle); + } + else { + set = outfiles.keySet(); + iter = set.iterator(); + while (iter.hasNext()) { + FpdModuleIdentification moduleId = (FpdModuleIdentification) iter.next(); + String baseName = moduleId.getBaseName(); + + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + moduleEle.setAttribute("target", baseName + "_clean"); + // + // ARCH + // + Element property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", moduleId.getArch()); + moduleEle.appendChild(property); + // + // PACKAGE_DIR + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(baseName)); + moduleEle.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData + .getPackageNameForModule(baseName)); + moduleEle.appendChild(property); + elseEle.appendChild(moduleEle); + ifEle.appendChild(elseEle); + ele.appendChild(ifEle); + } + } + root.appendChild(ele); + // + // Deep Clean Target + // + root.appendChild(document.createComment("Clean All target")); + ele = document.createElement("target"); + ele.setAttribute("name", "cleanall"); + + if (isUnified) { + Element cleanAllEle = document.createElement("delete"); + cleanAllEle.setAttribute("dir", getProject().getProperty("PLATFORM_DIR") + File.separatorChar + "Build" + File.separatorChar + "${TARGET}"); + ele.appendChild(cleanAllEle); + } + else { + set = outfiles.keySet(); + iter = set.iterator(); + while (iter.hasNext()) { + FpdModuleIdentification moduleId = (FpdModuleIdentification) iter.next(); + String baseName = moduleId.getBaseName(); + + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + moduleEle.setAttribute("target", baseName + "_cleanall"); + // + // ARCH + // + Element property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", moduleId.getArch()); + moduleEle.appendChild(property); + // + // PACKAGE_DIR + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(baseName)); + moduleEle.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData + .getPackageNameForModule(baseName)); + moduleEle.appendChild(property); + elseEle.appendChild(moduleEle); + ifEle.appendChild(elseEle); + ele.appendChild(ifEle); + } + } + root.appendChild(ele); + + document.appendChild(rootComment); + document.appendChild(root); + // + // Prepare the DOM document for writing + // + Source source = new DOMSource(document); + // + // Prepare the output file + // + File file = new File(getProject().getProperty("PLATFORM_DIR") + + File.separatorChar + "build.out.xml"); + // + // generate all directory path + // + (new File(file.getParent())).mkdirs(); + Result result = new StreamResult(file); + // + // Write the DOM document to the file + // + Transformer xformer = TransformerFactory.newInstance() + .newTransformer(); + xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + xformer.setOutputProperty(OutputKeys.INDENT, "yes"); + xformer.transform(source, result); + } catch (Exception ex) { + throw new BuildException("Generate build.out.xml failed. \n" + ex.getMessage()); + } + } + + /** + Add a property. + + @param p property + **/ + public void addProperty(Property p) { + properties.addElement(p); + } + + /** + Get FPD file name. + + @return FPD file name. + **/ + public File getFpdFilename() { + return fpdFilename; + } + + /** + Set FPD file name. + + @param fpdFilename FPD file name + **/ + public void setFpdFilename(File fpdFilename) { + this.fpdFilename = fpdFilename; + } + + public File getGuiddatabase() { + return guiddatabase; + } + + public void setGuiddatabase(File guiddatabase) { + this.guiddatabase = guiddatabase; + } + + public void collectPCDInformation() { + CollectPCDAction collectAction = new CollectPCDAction (); + // + // Set memory database log file path. It should be put into same directory with FPD file. + // + GlobalData.getPCDMemoryDBManager().setLogFileName( + fpdFilename.getPath() + ".PCDMemroyDatabaseLog.txt" + ); + // + // Collect all PCD information from FPD to MSA, and get help information from SPD. + // These all information will be stored into memory database for future usage such + // as autogen. + // + try { + collectAction.perform ( + getProject().getProperty("WORKSPACE_DIR"), + fpdFilename.getPath(), + ActionMessage.NULL_MESSAGE_LEVEL + ); + } catch (Exception exp) { + throw new BuildException (exp.getMessage()); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/DpFile.java b/Tools/Source/GenBuild/org/tianocore/build/global/DpFile.java new file mode 100644 index 0000000000..78cde75604 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/DpFile.java @@ -0,0 +1,129 @@ +/** @file +This file is used to define class which represents dependency file in ANT task + +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.global; + +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Path; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.LineNumberReader; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + DpFile is a ANT DataType which can be used to specify dependency files from + a file list file, from file list string separated by space, comma or semi-comma, + or from file name with absolute path + **/ +public class DpFile extends DataType { + /// + /// keep the list of files path + /// + private List nameList = new ArrayList(); + + /** + Empty constructor just in case + **/ + public DpFile() { + } + + /** + Empty execute method of ANT task, just in case + **/ + public void execute() { + } + + /** + Standard set method of ANT task/datatype, for ListFile attribute. It simply + fetch one file path a line from specified list file, and put them in nameList + + @param fileListFile file which contains a file list, one file a line, + with full path + **/ + public void setListFile(String fileListFile) { + File file = new File(fileListFile); + if (!file.exists()) { + return; + } + + try { + FileReader fileReader = new FileReader(file); + LineNumberReader lineReader = new LineNumberReader(fileReader); + + String filePath = null; + while ((filePath = lineReader.readLine()) != null) { + filePath = filePath.trim(); + if (filePath.length() == 0) { + continue; + } + this.nameList.add(filePath); + } + + lineReader.close(); + fileReader.close(); + } catch (IOException e) { + System.out.println (e.getMessage()); + } + } + + /** + Standard set method of ANT task/datatype, for List attribute. + + @param fileList string with file pathes separated by space, comma, + or semi-comma + **/ + public void setList(String fileList) { + // + // space, comma or semi-comma separated files list + // + Pattern pattern = Pattern.compile("([^ ,;\n\r]++)[ ,;\n\r]*+"); + Matcher matcher = pattern.matcher(fileList); + + while (matcher.find()) { + // + // keep each file name before " ,;\n\r" + // + String filePath = fileList.substring(matcher.start(1), matcher.end(1)).trim(); + if (filePath.length() == 0) { + continue; + } + nameList.add(Path.translateFile(filePath)); + } + + } + + /** + Standard set method of ANT task/datatype, for Name attribute. + + @param fileName string of a file full path + **/ + public void setName(String fileName) { + this.nameList.add(fileName); + } + + /** + Fetch the file name list. + + @returns A string list which contains file names specified to check dependnecy + **/ + public List getList() { + return this.nameList; + } +} + + diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/DpFileList.java b/Tools/Source/GenBuild/org/tianocore/build/global/DpFileList.java new file mode 100644 index 0000000000..8b4b4a0add --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/DpFileList.java @@ -0,0 +1,50 @@ +/** @file +This file is used to nest elements corresponding to DpFile + +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.global; + +import java.util.ArrayList; +import java.util.List; + +/** + DpFileList is a container of Dpfile at the point of ANT task/datatype + **/ +public class DpFileList { + /// + /// Keep all the file names from all nested DpFile + /// + List nameList = new ArrayList(); + + /** + Empty constructor just in case + **/ + public DpFileList() { + } + + /** + Empty execute method of ANT task. ANT will call it even we don't need it. + **/ + public void execute() { + } + + /** + Standard add method of ANT task, for nested DpFile type of elements. It just + simply fetch the files list from DpFile and put them in its own nameList. + + @param f a DpFile object which will be instantiated by ANT + **/ + public void addConfiguredFile(DpFile f) { + this.nameList.addAll(f.getList()); + } +} + diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/GlobalData.java b/Tools/Source/GenBuild/org/tianocore/build/global/GlobalData.java new file mode 100644 index 0000000000..611758a4ef --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/GlobalData.java @@ -0,0 +1,637 @@ +/** @file + GlobalData class. + + GlobalData provide initializing, instoring, querying and update global data. + It is a bridge to intercommunicate between multiple component, such as AutoGen, + PCD and so on. + +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.global; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tools.ant.BuildException; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.FrameworkDatabaseDocument; +import org.tianocore.MsaFilesDocument; +import org.tianocore.PackageListDocument; +import org.tianocore.PackageSurfaceAreaDocument; +import org.tianocore.MsaHeaderDocument.MsaHeader; +import org.tianocore.MsaLibHeaderDocument.MsaLibHeader; +import org.tianocore.build.pcd.entity.MemoryDatabaseManager; +import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.fpd.FpdParserTask; + +/** + GlobalData provide initializing, instoring, querying and update global data. + It is a bridge to intercommunicate between multiple component, such as AutoGen, + PCD and so on. + +

Note that all global information are initialized incrementally. All data will + parse and record only it is necessary during build time.

+ + @since GenBuild 1.0 +**/ +public class GlobalData { + + /// + /// means no surface area information for module + /// + public static final int NO_SA = 0; + + /// + /// means only MSA + /// + public static final int ONLY_MSA = 1; + + /// + /// means only Library MSA + /// + public static final int ONLY_LIBMSA = 2; + + /// + /// means both MSA and MBD + /// + public static final int MSA_AND_MBD = 3; + + /// + /// means both Library MSA and Library MBD + /// + public static final int LIBMSA_AND_LIBMBD = 4; + + /// + /// Be used to ensure Global data will be initialized only once. + /// + public static boolean globalFlag = false; + + /// + /// Record current WORKSPACE Directory + /// + private static String workspaceDir = ""; + + /// + /// Two columns: Package Name (Key), Package Path(ralative to WORKSPACE) + /// + private static final Map packageInfo = new HashMap(); + + /// + /// spdTable + /// Key: Package Name, Value: SPD detail info + /// + private static final Map spdTable = new HashMap(); + + /// + /// Three columns: + /// 1. Module Name | BaseName (Key) + /// 2. Module Path + Msa file name (relative to Package) + /// 3. Package Name (This module belong to which package) + /// + private static final Map moduleInfo = new HashMap(); + + /// + /// List all libraries for current build module + /// Key: Library BaseName, Value: output library path+name + /// + private static final Map libraries = new HashMap(); + + /// + /// Store every module's relative library instances BaseName + /// Key: Module BaseName, Value: All library instances module depends on. + /// + private static final Map > moduleLibraryMap = new HashMap >(); + + /// + /// Key: Module BaseName, Value: original MSA info + /// + private static final Map > nativeMsa = new HashMap >(); + + /// + /// Key: Module BaseName, Value: original MBD info + /// + private static final Map > nativeMbd = new HashMap >(); + + /// + /// Two columns: Module Name or Base Name as Key + /// Value is a HashMap with overridden data from MSA/MBD or/and Platform + /// + private static final Map > parsedModules = new HashMap >(); + + /// + /// List all built Module; Value is Module BaseName + Arch. TBD + /// + private static final Set builtModules = new HashSet(); + + /// + /// Library instance information table which recored the library and it's + /// constructor and distructor function + /// + private static final Map libInstanceInfo = new HashMap(); + + /// + /// PCD memory database stored all PCD information which collected from FPD,MSA and SPD. + /// + private static final MemoryDatabaseManager pcdDbManager = new MemoryDatabaseManager(); + + /** + Query the module's absolute path with module base name. + + @param moduleName the base name of the module + @return the absolute module path + **/ + public synchronized static String getModulePath(String moduleName) { + String[] info = moduleInfo.get(moduleName); + String packagePath = (String) packageInfo.get(info[1]); + File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]); + return convertFile.getParent(); + } + + /** + Query the module's absolute MSA file path with module base name. + + @param moduleName the base name of the module + @return the absolute MSA file name + @throws BuildException + Base name is not registered in any SPD files + **/ + private synchronized static String getMsaFilename(String moduleName) throws BuildException { + String[] info = moduleInfo.get(moduleName); + if (info == null) { + throw new BuildException("Module base name [" + moduleName + "] can't found in all SPD."); + } + String packagePath = (String) packageInfo.get(info[1]); + File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]); + return convertFile.getPath(); + } + + /** + Query the module's absolute MBD file path with module base name. + + @param moduleName the base name of the module + @return the absolute MBD file name + @throws BuildException + Base name is not registered in any SPD files + **/ + private synchronized static String getMbdFilename(String moduleName) throws BuildException { + String[] info = moduleInfo.get(moduleName); + if (info == null) { + throw new BuildException("Info: Module base name [" + moduleName + "] can't found in all SPD."); + } + String packagePath = (String) packageInfo.get(info[1]); + File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]); + return convertFile.getPath().substring(0, convertFile.getPath().length() - 4) + ".mbd"; + } + + /** + Get the current WORKSPACE Directory. + @return current workspace directory + **/ + public synchronized static String getWorkspacePath() { + return workspaceDir; + } + + /** + Query package relative path to WORKSPACE_DIR with package name. + + @param packageName the name of the package + @return the path relative to WORKSPACE_DIR + **/ + public synchronized static String getPackagePath(String packageName) { + return (String) packageInfo.get(packageName); + } + + /** + Query package (which the module belongs to) relative path to WORSPACE_DIR. + + @param moduleName the base name of the module + @return the relative path to WORKSPACE_DIR of the package which the module belongs to + **/ + public synchronized static String getPackagePathForModule(String moduleName) { + String[] info = moduleInfo.get(moduleName); + String packagePath = (String) packageInfo.get(info[1]); + return packagePath; + } + + /** + Query the package name which the module belongs to with the module's base name. + + @param moduleName the base name of the module + @return the package name which the module belongs to + **/ + public synchronized static String getPackageNameForModule(String moduleName) { + return moduleInfo.get(moduleName)[1]; + } + + /** + Parse framework database (DB) and all SPD files listed in DB to initialize + the environment for next build. This method will only be executed only once + in the whole build process. + + @param workspaceDatabaseFile the file name of framework database + @param workspaceDir current workspace directory path + @throws BuildException + Framework Dababase or SPD or MSA file is not valid + **/ + public synchronized static void initInfo(String workspaceDatabaseFile, String workspaceDir) throws BuildException { + if (globalFlag) { + return; + } + globalFlag = true; + GlobalData.workspaceDir = workspaceDir; + File dbFile = new File(workspaceDir + File.separatorChar + workspaceDatabaseFile); + try { + FrameworkDatabaseDocument db = (FrameworkDatabaseDocument) XmlObject.Factory.parse(dbFile); + List packages = db.getFrameworkDatabase().getPackageList() + .getPackageList(); + Iterator iter = packages.iterator(); + while (iter.hasNext()) { + PackageListDocument.PackageList.Package packageItem = (PackageListDocument.PackageList.Package) iter + .next(); + String name = packageItem.getPackageNameArray(0).getStringValue(); + String path = packageItem.getPathArray(0).getStringValue(); + packageInfo.put(name, path); + File spdFile = new File(workspaceDir + File.separatorChar + path + File.separatorChar + name + ".spd"); + initPackageInfo(spdFile.getPath(), name); + // + // SPD Parse. + // + PackageSurfaceAreaDocument spdDoc = (PackageSurfaceAreaDocument) XmlObject.Factory.parse(spdFile); + Spd spd = new Spd(spdDoc, path); + spdTable.put(name, spd); + + } + } catch (Exception e) { + throw new BuildException("Parse workspace Database [" + dbFile.getPath() + "] Error.\n" + e.getMessage()); + } + } + + /** + Parse every MSA files, get base name from MSA Header. And record those + values to ModuleInfo. + + @param packageFilename the file name of the package + @param packageName the name of the package + @throws BuildException + SPD or MSA file is not valid + **/ + private synchronized static void initPackageInfo(String packageFilename, String packageName) throws BuildException { + File packageFile = new File(packageFilename); + try { + PackageSurfaceAreaDocument spd = (PackageSurfaceAreaDocument) XmlObject.Factory.parse(packageFile); + List msasList = spd.getPackageSurfaceArea().getMsaFiles() + .getMsaFileList(); + Iterator msasIter = msasList.iterator(); + while (msasIter.hasNext()) { + MsaFilesDocument.MsaFiles.MsaFile msas = (MsaFilesDocument.MsaFiles.MsaFile) msasIter.next(); + String msaFilename = msas.getFilename().getStringValue(); + File msaFile = new File(workspaceDir + File.separatorChar + GlobalData.getPackagePath(packageName) + + File.separatorChar + msaFilename); + SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser(); + Map map = surfaceAreaParser.parseFile(msaFile); + String baseName = ""; + XmlObject header = null; + if ((header = map.get("MsaHeader")) != null) { + baseName = ((MsaHeader) header).getBaseName().getStringValue(); + } else if ((header = map.get("MsaLibHeader")) != null) { + baseName = ((MsaLibHeader) header).getBaseName().getStringValue(); + } else { + continue; + } + nativeMsa.put(baseName, map); + String[] info = { msaFilename, packageName }; + moduleInfo.put(baseName, info); + } + } catch (Exception e) { + throw new BuildException("Parse package description file [" + packageFile.getPath() + "] Error.\n" + + e.getMessage()); + } + } + + /** + Query the libraries which the module depends on. + + @param moduleName the base name of the module + @return the libraries which the module depends on + **/ + public synchronized static String[] getModuleLibrary(String moduleName) { + Set set = moduleLibraryMap.get(moduleName); + return set.toArray(new String[set.size()]); + } + + /** + Register module's library list which it depends on for later use. + + @param moduleName the base name of the module + @param libraryList the libraries which the module depends on + **/ + public synchronized static void addModuleLibrary(String moduleName, Set libraryList) { + moduleLibraryMap.put(moduleName, libraryList); + } + + /** + Query the library absolute file name with library name. + + @param library the base name of the library + @return the library absolute file name + **/ + public synchronized static String getLibrary(String library) { + return libraries.get(library); + } + + /** + Register library absolute file name for later use. + + @param library the base name of the library + @param resultPath the library absolute file name + **/ + public synchronized static void addLibrary(String library, String resultPath) { + libraries.put(library, resultPath); + } + + /** + Whether the module with ARCH has built in the previous build. + + @param moduleName the base name of the module + @param arch current build ARCH + @return true if the module has built in previous, otherwise return false + **/ + public synchronized static boolean isModuleBuilt(String moduleName, String arch) { + return builtModules.contains(moduleName + "-" + arch); + } + + /** + Register the module with ARCH has built. + + @param moduleName the base name of the module + @param arch current build ARCH + **/ + public synchronized static void registerBuiltModule(String moduleName, String arch) { + builtModules.add(moduleName + "-" + arch); + } + + /** + Whether the module's surface area has parsed in the previous build. + + @param moduleName the base name of the module + @return true if the module's surface area has parsed in previous, otherwise + return false + **/ + public synchronized static boolean isModuleParsed(String moduleName) { + return parsedModules.containsKey(moduleName); + } + + /** + Query overrided module surface area information. If current is Package + or Platform build, also include the information from FPD file. + +

Note that surface area parsing is incremental. That means the method will + only to parse the MSA and MBD files when never parsed before.

+ + @param moduleName the base name of the module + @return the overrided module surface area information + @throws BuildException + MSA or MBD is not valid + **/ + public synchronized static Map getDoc(String moduleName) throws BuildException { + if (parsedModules.containsKey(moduleName)) { + return parsedModules.get(moduleName); + } + Map msaMap = getNativeMsa(moduleName); + Map mbdMap = getNativeMbd(moduleName); + OverrideProcess op = new OverrideProcess(); + Map map = op.override(mbdMap, msaMap); + // + // IF IT IS A PALTFORM BUILD, OVERRIDE FROM PLATFORM + // + if (FpdParserTask.platformBuildOptions != null) { + Map platformMap = new HashMap(); + platformMap.put("BuildOptions", FpdParserTask.platformBuildOptions); + Map overrideMap = op.override(platformMap, OverrideProcess.deal(map)); + GlobalData.registerModule(moduleName, overrideMap); + return overrideMap; + } else { + parsedModules.put(moduleName, map); + return map; + } + } + + /** + Query the native MSA information with module base name. + +

Note that MSA parsing is incremental. That means the method will + only to parse the MSA files when never parsed before.

+ + @param moduleName the base name of the module + @return the native MSA information + @throws BuildException + MSA file is not valid + **/ + public synchronized static Map getNativeMsa(String moduleName) throws BuildException { + if (nativeMsa.containsKey(moduleName)) { + return nativeMsa.get(moduleName); + } + String msaFilename = getMsaFilename(moduleName); + File msaFile = new File(msaFilename); + if (!msaFile.exists()) { + throw new BuildException("Info: Surface Area file [" + msaFile.getPath() + "] can't found."); + } + SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser(); + Map map = surfaceAreaParser.parseFile(msaFile); + nativeMsa.put(moduleName, map); + return map; + } + + /** + Query the native MBD information with module base name. + +

Note that MBD parsing is incremental. That means the method will + only to parse the MBD files when never parsed before.

+ + @param moduleName the base name of the module + @return the native MBD information + @throws BuildException + MBD file is not valid + **/ + public synchronized static Map getNativeMbd(String moduleName) throws BuildException { + if (nativeMbd.containsKey(moduleName)) { + return nativeMbd.get(moduleName); + } + String mbdFilename = getMbdFilename(moduleName); + File mbdFile = new File(mbdFilename); + if (!mbdFile.exists()) { + throw new BuildException("Info: Surface Area file [" + mbdFile.getPath() + "] can't found."); + } + SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser(); + Map map = surfaceAreaParser.parseFile(mbdFile); + nativeMbd.put(moduleName, map); + return map; + } + + /** + Register module overrided surface area information. If has existed, then update. + + @param moduleName the base name of the module + @param map the overrided surface area information + **/ + public synchronized static void registerModule(String moduleName, Map map) { + parsedModules.put(moduleName, map); + } + + /** + * + * @param protocolName + * @return + */ + public synchronized static String[] getProtocolInfoGuid(String protocolName) { + Set set = spdTable.keySet(); + Iterator iter = set.iterator(); + String[] cNameGuid = null; + + while (iter.hasNext()) { + Spd spd = (Spd) spdTable.get(iter.next()); + cNameGuid = spd.getProtocolNameGuidArray(protocolName); + if (cNameGuid != null) { + break; + } + } + return cNameGuid; + } + + public synchronized static String[] getPpiInfoGuid(String ppiName) { + Set set = spdTable.keySet(); + Iterator iter = set.iterator(); + String[] cNameGuid = null; + + while (iter.hasNext()) { + Spd spd = (Spd) spdTable.get(iter.next()); + cNameGuid = spd.getPpiCnameGuidArray(ppiName); + + if (cNameGuid != null) { + break; + } + } + return cNameGuid; + } + + /** + * + * @param guidName + * @return + */ + public synchronized static String[] getGuidInfoGuid(String guidName) { + String[] cNameGuid = null; + Set set = spdTable.keySet(); + Iterator iter = set.iterator(); + + while (iter.hasNext()) { + Spd spd = (Spd) spdTable.get(iter.next()); + cNameGuid = spd.getGuidNameArray(guidName); + if (cNameGuid != null) { + break; + } + } + return cNameGuid; + } + + public synchronized static String getLibClassIncluder(String libName) { + String libIncluder = null; + Set set = spdTable.keySet(); + Iterator iter = set.iterator(); + + while (iter.hasNext()) { + String packageName = (String) iter.next(); + Spd spd = (Spd) spdTable.get(packageName); + libIncluder = spd.getLibClassIncluder(libName); + String packagePath = spd.packagePath; + if (packagePath != null) { + packagePath = packagePath.replace('\\', File.separatorChar); + packagePath = packagePath.replace('/', File.separatorChar); + } else { + packagePath = packageName; + } + if (libIncluder != null) { + libIncluder = libIncluder.replace('\\', File.separatorChar); + libIncluder = libIncluder.replace('/', File.separatorChar); + libIncluder = packageName + File.separatorChar + libIncluder; + break; + } + } + return libIncluder; + } + + public synchronized static String getModuleInfoByPackageName(String packageName, String moduleType) { + Spd spd; + String includeFile = null; + String includeStr = ""; + String cleanPath = ""; + + spd = (Spd) spdTable.get(packageName); + includeFile = spd.getModuleTypeIncluder(moduleType); + if (includeFile != null) { + includeFile = includeFile.replace('\\', File.separatorChar); + includeFile = includeFile.replace('/', File.separatorChar); + includeStr = CommonDefinition.include + " <" + includeStr; + cleanPath = spd.packagePath; + cleanPath = cleanPath.replace('\\', File.separatorChar); + cleanPath = cleanPath.replace('/', File.separatorChar); + + if (cleanPath.charAt(spd.packagePath.length() - 1) != File.separatorChar) { + cleanPath = cleanPath + File.separatorChar; + } + includeStr = includeStr + cleanPath; + includeStr = includeStr + includeFile; + includeStr = includeStr + ">\r\n"; + } + + return includeStr; + } + + public synchronized static void setLibInstanceInfo(String libName, String libConstructor, String libDesturctor) { + String[] libConsDes = new String[2]; + libConsDes[0] = libConstructor; + libConsDes[1] = libDesturctor; + + libInstanceInfo.put(libName, libConsDes); + } + + public synchronized static boolean isHaveLibInstance(String libName) { + return libInstanceInfo.containsKey(libName); + } + + public synchronized static String getLibInstanceConstructor(String libName) { + String[] libInstanceValue; + libInstanceValue = libInstanceInfo.get(libName); + if (libInstanceValue != null) { + return libInstanceValue[0]; + } else { + return null; + } + } + + public synchronized static String getLibInstanceDestructor(String libName) { + String[] libInstanceValue; + libInstanceValue = libInstanceInfo.get(libName); + if (libInstanceValue != null) { + return libInstanceValue[1]; + } else { + return null; + } + } + + public synchronized static MemoryDatabaseManager getPCDMemoryDBManager() { + return pcdDbManager; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/GlobalShare.java b/Tools/Source/GenBuild/org/tianocore/build/global/GlobalShare.java new file mode 100644 index 0000000000..5912127a10 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/GlobalShare.java @@ -0,0 +1,178 @@ +/*++ + + 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. + + Module Name: + ShareObject.java + + Abstract: + + --*/ +package org.tianocore.build.global; + +import java.util.*; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.types.DataType; + +public class GlobalShare extends DataType implements DynamicConfigurator { + private static final HashMap objStorage = new HashMap(); + + private DataObjectOp op; + + private String objName; + + private Object objInst; + + private String objClassPackage = "org.tianocore"; + + public GlobalShare () { + + } + + public GlobalShare (String objName) { + this.objName = objName; + this.objInst = objStorage.get(this.objName); + } + + public GlobalShare (String objName, Object obj) { + this.objName = objName; + this.objInst = obj; + objStorage.put(this.objName, this.objInst); + } + + public Object createDynamicElement(String name) throws BuildException { + String className = objClassPackage + "." + name; + log("GlobalShare.createDynamicElement(" + name + ")", + Project.MSG_VERBOSE); + try { + objInst = Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + throw new BuildException("class name is not found"); + } catch (InstantiationException e) { + throw new BuildException("the class cannnot be instantiated"); + } catch (IllegalAccessException e) { + throw new BuildException("cannot access the class"); + } + + return objInst; + } + + public void setDynamicAttribute(String name, String value) + throws BuildException { + log("name = " + name + " value = " + value, Project.MSG_VERBOSE); + throw new BuildException(); + } + + public void setName(String name) { + this.objName = name; + if (this.op != null) { + issueOperation(); + } + } + + public String getName() { + return this.objName; + } + + public void setPackage(String name) { + log("ShareObject.setPackage(" + name + ")", Project.MSG_VERBOSE); + this.objClassPackage = name; + } + + public String getPackage() { + return this.objClassPackage; + } + + public void setOperation(String opName) { + log("ShareObject.setOperation(" + opName + ")", Project.MSG_VERBOSE); + this.op = DataObjectOp.formString(opName); + + if (this.objName != null) { + issueOperation(); + } + } + + public String getOperation() { + return this.op.toString(); + } + + public void issueOperation() { + if (this.op == DataObjectOp.ADD) { + + log("ShareObject: adding ... " + this.objName, Project.MSG_VERBOSE); + objStorage.put(this.objName, this.objInst); + + } else if (this.op == DataObjectOp.GET) { + + log("ShareObject: fetching ... " + this.objName, + Project.MSG_VERBOSE); + objInst = objStorage.get(objName); + + } else if (this.op == DataObjectOp.DEL) { + + log("ShareObject: removing ... " + this.objName, + Project.MSG_VERBOSE); + objInst = objStorage.remove(objName); + + } else { + throw new BuildException("not supported operation"); + } + } + + public Object get() { + return this.objInst; + } + + public static int getObjectNum() { + return objStorage.size(); + } + + public static Object add(String objName, Object obj) { + return objStorage.put(objName, obj); + } + + public static Object retrieve(String objName) { + return objStorage.get(objName); + } + + public static Object remove(String objName) { + return objStorage.remove(objName); + } + + public static void empty() { + objStorage.clear(); + } +} + +class DataObjectOp { + private static final HashMap opMap = new HashMap(); + + private final String opName; + + private DataObjectOp (String name) { + this.opName = name; + opMap.put(this.opName, this); + } + + public String toString() { + return opName; + } + + public static DataObjectOp formString(String opName) { + return opMap.get(opName); + } + + public static final DataObjectOp ADD = new DataObjectOp("ADD"); + + public static final DataObjectOp GET = new DataObjectOp("GET"); + + public static final DataObjectOp DEL = new DataObjectOp("DEL"); +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/LibBuildFileGenerator.java b/Tools/Source/GenBuild/org/tianocore/build/global/LibBuildFileGenerator.java new file mode 100644 index 0000000000..4d7e870587 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/LibBuildFileGenerator.java @@ -0,0 +1,412 @@ +/** @file + This file is an ANT task. + + LibBuildFileGenerator task is used to generate module's build.xml file. + +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.global; + +import java.io.File; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.MsaHeaderDocument.MsaHeader; +import org.tianocore.MsaLibHeaderDocument.MsaLibHeader; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + This class LibBuildFileGenerator is an ANT task to generate + build.xml for each module. Here are two usages. + +
    +
  • + For one module (bf is LibBuildFileGenerator task name): +
    +        <bf buildFile="Application\HelloWorld\HelloWorld.msa" />
    +      
    +
  • +
  • + For one package: +
    +        <bf recursive="true" />
    +      
    +
  • +
+ + @since GenBuild 1.0 +**/ +public class LibBuildFileGenerator extends Task { + + private File buildFile; + + private boolean recursive = false; + + private String license = " Copyright (c) 2006, Intel Corporation \n" + + "All rights reserved. This program and the accompanying materials \n" + + "are licensed and made available under the terms and conditions of the BSD License \n" + + "which accompanies this distribution. The full text of the license may be found at \n" + + "http://opensource.org/licenses/bsd-license.php \n" + + "\n" + + "THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN \"AS IS\" BASIS, \n" + + "WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED."; + + private String base_name; + + private String module_relative_path; + + private File base_file = new File("."); + + /** + Public construct method. It is necessary for ANT task. + **/ + public LibBuildFileGenerator () { + } + + /** + ANT task's entry point, will be called after init(). + + @throws BuildException + buildFile do not specify while recursive set to false + **/ + public void execute() throws BuildException { + if(recursive){ + searchMsa(new File(".")); + } + else { + Map map = new HashMap(); + String basename = buildFile.getName(); + int k = basename.lastIndexOf('.'); + base_name = basename.substring(0, k); + map.put(base_name, buildFile); + genBuildFile(map); + } + } + + /** + Recursivly find all MSA files and record all modules. + + @param path Package path + **/ + private void searchMsa(File path){ + File[] files = path.listFiles(); + Vector vec = new Vector(); + for(int i=0; i < files.length; i ++){ + if (files[i].isFile()){ + if(files[i].getName().endsWith(".msa")){ + System.out.println("#" + files[i].getPath()); + vec.add(files[i]); + } + } + } + Map mapBasename = new HashMap(); + if (vec.size() > 0){ + base_name = null; + for ( int j = 0 ; j < vec.size(); j++){ + if ( vec.size() > 1){ + System.out.println("##" + vec.get(0)); + } + File f = (File)vec.get(j); + SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser(); + Map map = surfaceAreaParser.parseFile(f); + String baseName = ""; + XmlObject header = null; + if ( (header = map.get("MsaHeader")) != null ){ + baseName = ((MsaHeader)header).getBaseName().getStringValue(); + } + else if ( (header = map.get("MsaLibHeader")) != null){ + baseName = ((MsaLibHeader)header).getBaseName().getStringValue(); + } else { + continue ; + } + if ( base_name == null || base_name.length() > baseName.length()){ + base_name = baseName; + buildFile = f; + try { + module_relative_path = buildFile.getParent().substring(base_file.getPath().length() + 1); + } + catch(Exception e){ + module_relative_path = "."; + } + } + mapBasename.put(baseName, f); + } + genBuildFile(mapBasename); + } + + for(int i=0; i < files.length; i ++){ + if (files[i].isDirectory()){ + searchMsa(files[i]); + } + } + } + + /** + Generate build.xml. + + @param map All base name under one module directory + **/ + private void genBuildFile(Map map) { + DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dombuilder = domfac.newDocumentBuilder(); + Document document = dombuilder.newDocument(); + // + // create root element and its attributes + // + document.appendChild(document.createComment(license)); + Element root = document.createElement("project"); + root.setAttribute("default", base_name); + root.setAttribute("basedir", "."); + // + // element for External ANT tasks + // + root.appendChild(document.createComment("Apply external ANT tasks")); + Element ele = document.createElement("taskdef"); + ele.setAttribute("resource", "GenBuild.tasks"); + root.appendChild(ele); + // + // + // + ele = document.createElement("taskdef"); + ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml"); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("environment", "env"); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("name", "WORKSPACE_DIR"); + ele.setAttribute("value", "${env.WORKSPACE}"); + root.appendChild(ele); + + ele = document.createElement("import"); + ele.setAttribute("file", "${WORKSPACE_DIR}"+File.separatorChar+"Tools"+File.separatorChar+"Conf"+File.separatorChar+"BuildMacro.xml"); + root.appendChild(ele); + + root.appendChild(document.createComment("MODULE_RELATIVE PATH is relative to PACKAGE_DIR")); + ele = document.createElement("property"); + ele.setAttribute("name", "MODULE_RELATIVE_PATH"); + ele.setAttribute("value", module_relative_path); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("name", "MODULE_DIR"); + ele.setAttribute("value", "${PACKAGE_DIR}" + File.separatorChar + "${MODULE_RELATIVE_PATH}"); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("name", "COMMON_FILE"); + ele.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + + File.separatorChar + "Conf" + File.separatorChar + "Common.xml"); + root.appendChild(ele); + + // + // generate the buildfmd target + // + Set set = map.keySet(); + Iterator iter = set.iterator(); + while (iter.hasNext()){ + String bName = (String)iter.next(); + File msaFile = (File)map.get(bName); + String msaFilename = "${MODULE_DIR}" + File.separatorChar + msaFile.getName(); + String mbdFilename = msaFilename.substring(0 , msaFilename.length() - 4) + ".mbd"; + ele = document.createElement("target"); + ele.setAttribute("name", bName); + Element target = document.createElement("GenBuild"); + target.setAttribute("msaFilename", msaFilename); + target.setAttribute("mbdFilename", mbdFilename); + target.setAttribute("baseName", bName); + ele.appendChild(target); + root.appendChild(ele); + } + + root.appendChild(ele); + // + // Default clean + // + ele = document.createElement("target"); + ele.setAttribute("name", "clean"); + ele.setAttribute("depends", base_name + "_clean"); + root.appendChild(ele); + // + // Default Clean ALl + // + ele = document.createElement("target"); + ele.setAttribute("name", "cleanall"); + ele.setAttribute("depends", base_name + "_cleanall"); + root.appendChild(ele); + // + // Every clean target for each BaseName + // + set = map.keySet(); + iter = set.iterator(); + while (iter.hasNext()){ + String bName = (String)iter.next(); + File msaFile = (File)map.get(bName); + String msaFilename = "${MODULE_DIR}" + File.separatorChar + msaFile.getName(); + String mbdFilename = msaFilename.substring(0 , msaFilename.length() - 4) + ".mbd"; + + ele = document.createElement("target"); + ele.setAttribute("name", bName + "_clean"); + // + // Output Dir + // + Element target = document.createElement("OutputDirSetup"); + target.setAttribute("msaFilename", msaFilename); + target.setAttribute("mbdFilename", mbdFilename); + target.setAttribute("baseName", bName); + ele.appendChild(target); + // + // Call BaseName_build.xml clean + // + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + bName + "_build.xml"); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", "${DEST_DIR_OUTPUT}" + File.separatorChar + bName + "_build.xml"); + moduleEle.setAttribute("target", "clean"); + + elseEle.appendChild(moduleEle); + ifEle.appendChild(elseEle); + ele.appendChild(ifEle); + // + // just delete + // + Element clean = document.createElement("delete"); + clean.setAttribute("dir", "${DEST_DIR_OUTPUT}"); + clean.setAttribute("excludes", "*.xml"); + ele.appendChild(clean); + + root.appendChild(ele); + } + // + // Every Clean ALl target for each BaseName + // + set = map.keySet(); + iter = set.iterator(); + while (iter.hasNext()){ + String bName = (String)iter.next(); + File msaFile = (File)map.get(bName); + String msaFilename = "${MODULE_DIR}" + File.separatorChar + msaFile.getName(); + String mbdFilename = msaFilename.substring(0 , msaFilename.length() - 4) + ".mbd"; + + ele = document.createElement("target"); + ele.setAttribute("name", bName + "_cleanall"); + // + // Output Dir + // + Element target = document.createElement("OutputDirSetup"); + target.setAttribute("msaFilename", msaFilename); + target.setAttribute("mbdFilename", mbdFilename); + target.setAttribute("baseName", bName); + ele.appendChild(target); + // + // Call BaseName_build.xml clean + // + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + bName + "_build.xml"); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", "${DEST_DIR_OUTPUT}" + File.separatorChar + bName + "_build.xml"); + moduleEle.setAttribute("target", "cleanall"); + + elseEle.appendChild(moduleEle); + ifEle.appendChild(elseEle); + ele.appendChild(ifEle); + // + // just delete + // + Element clean = document.createElement("delete"); + clean.setAttribute("dir", "${DEST_DIR_OUTPUT}"); + ele.appendChild(clean); + + clean = document.createElement("delete"); + clean.setAttribute("dir", "${DEST_DIR_DEBUG}"); + ele.appendChild(clean); + + clean = document.createElement("delete"); + Element fileset = document.createElement("fileset"); + fileset.setAttribute("dir", "${BIN_DIR}"); + fileset.setAttribute("includes", "**" + bName + "*"); + clean.appendChild(fileset); + ele.appendChild(clean); + + root.appendChild(ele); + } + document.appendChild(root); + // + // Prepare the DOM document for writing + // + Source source = new DOMSource(document); + // + // Prepare the output file + // + String filename = buildFile.getParent() + File.separatorChar + "build.xml"; + File file = new File(getProject().replaceProperties(filename)); + // + // generate all directory path + // + Result result = new StreamResult(file); + // + // Write the DOM document to the file + // + Transformer xformer = TransformerFactory.newInstance() + .newTransformer(); + xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + xformer.setOutputProperty(OutputKeys.INDENT, "yes"); + xformer.transform(source, result); + } catch (Exception ex) { + System.out.println("##" + ex); + } + } + + + public File getBuildFile() { + return buildFile; + } + + public void setBuildFile(File buildFile) { + this.buildFile = buildFile; + } + + public boolean isRecursive() { + return recursive; + } + + public void setRecursive(boolean recursive) { + this.recursive = recursive; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/ModuleIdentification.java b/Tools/Source/GenBuild/org/tianocore/build/global/ModuleIdentification.java new file mode 100644 index 0000000000..74311d4541 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/ModuleIdentification.java @@ -0,0 +1,55 @@ +package org.tianocore.build.global; + +public class ModuleIdentification { + + private String baseName; + + private String packageName; + + private String guid; + + private String version; + + public ModuleIdentification(String baseName, String packageName, String guid, String version){ + this.baseName = baseName; + this.packageName = packageName; + this.guid = guid; + this.version = version; + } + + public boolean equals(Object obj) { + if (obj instanceof ModuleIdentification) { + ModuleIdentification moduleIdObj = (ModuleIdentification)obj; + if ( baseName.equalsIgnoreCase(moduleIdObj.baseName)) { + return true; + } + // TBD + return false; + } + else { + return super.equals(obj); + } + } + + public String toString(){ + return packageName + ":" + guid + "_" + baseName + "_" + version; + } + + public void setBaseName(String baseName) { + this.baseName = baseName; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public void setVersion(String version) { + this.version = version; + } + + +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java b/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java new file mode 100644 index 0000000000..936dac8ea3 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java @@ -0,0 +1,121 @@ +/** @file +This file is to define OnDependency 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.global; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Sequential; + +import java.io.File; +import java.util.Iterator; + +/** + Class OnDepdendency is used to check the timestamp between source files and + target files, which can be used to determine if the target files are needed to + be re-generated from source files. + **/ +public class OnDependency extends Task { + /// + /// source files list + /// + private DpFileList sources = null; + /// + /// target files list + /// + private DpFileList targets = null; + /// + /// tasks to be performed to generate target files + /// + private Sequential task = null; + + /// + /// An empty constructor for an ANT task can avoid some potential issues + /// + public OnDependency(){ + } + + /** + Standard execute method of ANT task + **/ + public void execute() { + if (isOutOfDate() && task != null) { + task.perform(); + } + } + + /// + /// check if the target files are outofdate + /// + private boolean isOutOfDate() { + /// + /// if no source files specified, take it as a fresh start + /// + if (sources.nameList.size() == 0) { + return true; + } + + Iterator dstIt = targets.nameList.iterator(); + while (dstIt.hasNext()) { + String dstFileName = (String)dstIt.next(); + File dstFile = new File(dstFileName); + if (!dstFile.exists()) { + return true; + } + + long dstTimeStamp = dstFile.lastModified(); + Iterator srcIt = sources.nameList.iterator(); + while (srcIt.hasNext()) { + String srcFileName = (String)srcIt.next(); + File srcFile = new File(srcFileName); + if (!srcFile.exists()) { + throw new BuildException(srcFileName + " doesn't exist !!!"); + } + + if (dstTimeStamp < srcFile.lastModified()) { + return true; + } + } + } + + return false; + } + + /** + Add method of ANT task for nested element with Sequential type + + @param task Sequential object which contains tasks for generating target files + **/ + public void addSequential(Sequential task) { + this.task = task; + } + + /** + Add method of ANT task for nested element with DpFileList type + + @param sources DpFileList object which contains the list of source files + **/ + public void addSourcefiles(DpFileList sources) { + this.sources = sources; + } + + /** + Add method of ANT task for nested element with DpFileList type + + @param targets DpFileList object which contains the list of target files + **/ + public void addTargetfiles(DpFileList targets) { + this.targets = targets; + } +} + diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/OutputManager.java b/Tools/Source/GenBuild/org/tianocore/build/global/OutputManager.java new file mode 100644 index 0000000000..01e24e653f --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/OutputManager.java @@ -0,0 +1,176 @@ +/** @file + OutputManager class. + + OutputManager class set output directories for every module by BUILD_MODE. + +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.global; + +import org.apache.tools.ant.Project; +import java.io.File; + +/** + OutputManager class is used to setup output directories (BIN_DIR, DEST_DIR_OUTPUT, + DEST_DIR_DEBUG) according to BUILD_MODE. + + @since GenBuild 1.0 +**/ +public class OutputManager { + + /// + /// Single Module build + /// + public static final String MODULE_BUILD = "MODULE"; + + /// + /// Package build + /// + public static final String PACKAGE_BUILD = "PACKAGE"; + + /// + /// Platform build + /// + public static final String PLATFORM_BUILD = "PLATFORM"; + + public static String buildMode = MODULE_BUILD; + + /// + /// For Package build, PLATFORM represent PACKAGE + /// + public static String PLATFORM; + + /// + /// For Platform build, PLATFORM_DIR represent PACKAGE_DIR + /// + public static String PLATFORM_DIR; + + /// + /// means intermediate files will put under Module's dir + /// + public static final String MODULE = "MODULE"; + + /// + /// mean intermediate files will put under a unify dir + /// + public static final String UNIFIED = "UNIFIED"; + + /// + /// Flag to ensure the function update will be called only one in the whole build. + /// + private static boolean flag = true; + + /** + If BUILD_MODE is PLATFORM or PACKAGE, record PLATFORM and PLARFORM_DIR. + Reminder that for PACKAGE build, here set value PACKAGE to PLATFORM and + PACKAGE_DIR to PLARFORM_DIR, and also update the ant properties. + +

Note that this function will be called only once in the whole build.

+ + @param project current ANT build Project + **/ + public synchronized static void update(Project project) { + if (flag){ + flag = false; + String str = project.getProperty("BUILD_MODE"); + if (str != null){ + if (str.equals(PLATFORM_BUILD)) { + buildMode = PLATFORM_BUILD; + PLATFORM = project.getProperty("PLATFORM"); + PLATFORM_DIR = project.getProperty("PLATFORM_DIR"); + } + else if (str.equals(PACKAGE_BUILD)) { + buildMode = PACKAGE_BUILD; + PLATFORM = project.getProperty("PACKAGE"); + PLATFORM_DIR = project.getProperty("PACKAGE_DIR"); + project.setProperty("PLATFORM", PLATFORM); + project.setProperty("PLATFORM_DIR", PLATFORM_DIR); + } + } + } + } + + /** + Setup BIN_DIR, DEST_DIR_OUTPUT and DEST_DIR_OUTPUT, following are the rules: + +
+        Those three variables are defined as following
+        DEST_DIR_OUTPUT (intermediate files)
+        DEST_DIR_DEBUG (intermediate debug files)
+        BIN_DIR (final files)
+        
+        Output Dir (MODULE or UNIFIED):
+        For Module build: 
+        All intermediate files are at ${MODULE_DIR}/Build/${TARGET}/${ARCH}/DEBUG|OUTPUT
+        All final files are at ${MODULE_DIR}/Build/${TARGET}/${ARCH}
+        
+        For Platform build:
+        If specified with MODULE
+        Intermediate files->${MODULE_DIR}/Build/${PLATFORM}/${TARGET}/${ARCH}/DEBUG|OUTPUT
+        Final files -> ${PLARFORM_DIR}/Build/${TARGET}/${ARCH}
+        
+        Else if specified with UNIFIED
+        Intermediate files->${PLARFORM_DIR}/Build/${TARGET}/${ARCH}/${PACKAGE}/${SOURCE_RELATIVE_PATH}/DEBUG|OUTPUT
+        Final files -> ${PLARFORM_DIR}/Build/${TARGET}/${ARCH}
+        
+        For Package build:
+        If specified with MODULE
+        Intermediate files->${MODULE_DIR}/Build/${PACKAGE}/${TARGET}/${ARCH}/DEBUG|OUTPUT
+        Final files -> ${PACKAGE_DIR}/Build/${TARGET}/${ARCH}
+        
+        Else if specified with UNIFIED
+        Intermediate files->${PACKAGE_DIR}/Build/${TARGET}/${ARCH}/${PACKAGE}/${SOURCE_RELATIVE_PATH}/DEBUG|OUTPUT
+        Final files -> ${PACKAGE_DIR}/Build/${TARGET}/${ARCH}
+      
+ + @param project current ANT build Project + @param userdir user-defined directory + @param type the module build type (MODULE or UNIFIED) + **/ + public synchronized static void update(Project project, String userdir, String type) { + // + // userdir TBD + // + if( type == null || ! type.equals(MODULE)){ + type = UNIFIED; + } + if (buildMode.equals(MODULE_BUILD)){ + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${MODULE_DIR}" + + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + + File.separatorChar + "${ARCH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + else if (buildMode.equals(PLATFORM_BUILD)) { + if (type.equals(MODULE)) { + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${PLATFORM}" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${PLATFORM}" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + else if (type.equals(UNIFIED)){ + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "${PACKAGE}" + File.separatorChar + "${MODULE_RELATIVE_PATH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "${PACKAGE}" + File.separatorChar + "${MODULE_RELATIVE_PATH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + } + else if (buildMode.equals(PACKAGE_BUILD)) { + if (type.equals(MODULE)) { + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${PLATFORM}" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${PLATFORM}" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + else if (type.equals(UNIFIED)){ + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "${PACKAGE}" + File.separatorChar + "${MODULE_RELATIVE_PATH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "${PACKAGE}" + File.separatorChar + "${MODULE_RELATIVE_PATH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/OverrideProcess.java b/Tools/Source/GenBuild/org/tianocore/build/global/OverrideProcess.java new file mode 100644 index 0000000000..dae2ca29aa --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/OverrideProcess.java @@ -0,0 +1,354 @@ +/** @file + OverrideProcess class. + + OverrideProcess class is used to override surface area information. + +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.global; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tools.ant.BuildException; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.BootModesDocument; +import org.tianocore.BuildOptionsDocument; +import org.tianocore.DataHubsDocument; +import org.tianocore.EventsDocument; +import org.tianocore.ExternsDocument; +import org.tianocore.FormsetsDocument; +import org.tianocore.GuidsDocument; +import org.tianocore.HobsDocument; +import org.tianocore.IncludesDocument; +import org.tianocore.LibrariesDocument; +import org.tianocore.LibraryClassDefinitionsDocument; +import org.tianocore.MsaHeaderDocument; +import org.tianocore.MsaLibHeaderDocument; +import org.tianocore.PCDsDocument; +import org.tianocore.PPIsDocument; +import org.tianocore.ProtocolsDocument; +import org.tianocore.SourceFilesDocument; +import org.tianocore.SystemTablesDocument; +import org.tianocore.VariablesDocument; + +/** + This class is used to override surface area information. For example, MBD can + overried MSA, Platform can override all information of the module. + +

Override will take effect if two element satisfy one of following two condition:

+
    +
  • Element name and its attribute OverrideID equal each other.
  • +
  • Element is defined as exclusive which mean such element can be + only appeared in the surface area.
  • +
+ +

For example, here OutputDirectory element is exclusive:

+ +
+  Low priority Xml Document fragment:
+     <Libraries>
+       <Arch ArchType="IA32">
+         <Library OverrideID="8888">EdkPeCoffLoaderLib</Library>
+         <Library OverrideID="8888">BasePeCoffLib</Library>
+       </Arch>
+     </Libraries> 
+     <BuildOptions>
+       <OutputDirectory IntermediateDirectories="MODULE"/>
+       <Option>CC_FLAGS = "/NOLOGO", "/C"</Option>
+     <BuildOptions>
+ 
+  High priority Xml Document fragment:
+     <Libraries>
+       <Arch ArchType="IA32">
+         <Library OverrideID="8888">Nt32PeCoffLoaderLib</Library>
+       </Arch>
+     </Libraries>
+     <BuildOptions>
+       <OutputDirectory IntermediateDirectories="UNIFIED"/>
+       <Option>LIB_FLAGS = "/NOLOGO"</Option>
+     <BuildOptions>
+     
+   The result is: 
+     <Libraries>
+       <Arch ArchType="IA32">
+         <Library OverrideID="8888">Nt32PeCoffLoaderLib</Library>
+       </Arch>
+     </Libraries>
+     <BuildOptions>
+       <OutputDirectory IntermediateDirectories="UNIFIED"/>
+       <Option>CC_FLAGS = "/NOLOGO", "/C"</Option>
+       <Option>LIB_FLAGS = "/NOLOGO"</Option>
+     <BuildOptions>
+   
+  
+ +

Note that using XmlBeans to walk through the whole XML document tree.

+ + @since GenBuild 1.0 + @see org.apache.xmlbeans.XmlBeans +**/ +public class OverrideProcess { + + /// + /// URI, the namespace of current XML schema + /// + public static String prefix = "http://www.TianoCore.org/2006/Edk2.0"; + + /// + /// list of top elements of surface area + /// + public static String[] topElements = { "LibraryClassDefinitions", + "SourceFiles", "Includes", "Libraries", "Protocols", + "Events", "Hobs", "PPIs", "Variables", "BootModes", + "SystemTables", "DataHubs", "Formsets", "Guids", "Externs", + "PCDs", "BuildOptions" }; + + /// + /// list of exclusive elements + /// + public static String[] exclusiveElements = {"OutputDirectory"}; + + /** + Recursively find out all elements specified with OverrideId attribute + and exclusive elements in current XML object. + + @param o curent parsing XML object + @param map Map to list elements specified OverrideID attribute + @param execlusiveMap Map to list exclusive elements appeared in current XMl object + @param level the depth in XML document tree + **/ + private void listOverrideID(XmlObject o, Map map, Map execlusiveMap, int level) { + XmlCursor cursor = o.newCursor(); + String name = cursor.getName().getLocalPart(); + for (int i = 0 ; i < exclusiveElements.length; i++){ + if (name.equalsIgnoreCase(exclusiveElements[i])){ + execlusiveMap.put(exclusiveElements[i], cursor.getObject()); + } + } + String overrideID = cursor.getAttributeText(new QName("OverrideID")); + if (overrideID != null) { + map.put(name + ":" + overrideID, cursor.getObject()); + } + if (cursor.toFirstChild()) { + do { + listOverrideID(cursor.getObject(), map, execlusiveMap, level + 1); + } while (cursor.toNextSibling()); + } + } + + /** + This function is used to prepare for overriding with changing data. + + @param map original surface area information + @return after normalize surface area information + **/ + public synchronized static Map deal(Map map) { + Map newMap = new HashMap(); + if (map.get("MsaHeader") != null) { + newMap.put("MsaHeader", ((MsaHeaderDocument) map.get("MsaHeader")) + .getMsaHeader()); + } + if (map.get("MsaLibHeader") != null) { + newMap.put("MsaLibHeader", ((MsaLibHeaderDocument) map + .get("MsaLibHeader")).getMsaLibHeader()); + } + if (map.get("LibraryClassDefinitions") != null) { + newMap.put("LibraryClassDefinitions", + ((LibraryClassDefinitionsDocument) map + .get("LibraryClassDefinitions")) + .getLibraryClassDefinitions()); + } + if (map.get("SourceFiles") != null) { + newMap.put("SourceFiles", ((SourceFilesDocument) map + .get("SourceFiles")).getSourceFiles()); + } + if (map.get("Includes") != null) { + newMap.put("Includes", ((IncludesDocument) map.get("Includes")) + .getIncludes()); + } + if (map.get("Libraries") != null) { + newMap.put("Libraries", ((LibrariesDocument) map.get("Libraries")) + .getLibraries()); + } + if (map.get("Protocols") != null) { + newMap.put("Protocols", ((ProtocolsDocument) map.get("Protocols")) + .getProtocols()); + } + if (map.get("Events") != null) { + newMap.put("Events", ((EventsDocument) map.get("Events")) + .getEvents()); + } + if (map.get("Hobs") != null) { + newMap.put("Hobs", ((HobsDocument) map.get("Hobs")).getHobs()); + } + if (map.get("PPIs") != null) { + newMap.put("PPIs", ((PPIsDocument) map.get("PPIs")).getPPIs()); + } + if (map.get("Variables") != null) { + newMap.put("Variables", ((VariablesDocument) map.get("Variables")) + .getVariables()); + } + if (map.get("BootModes") != null) { + newMap.put("BootModes", ((BootModesDocument) map.get("BootModes")) + .getBootModes()); + } + if (map.get("SystemTables") != null) { + newMap.put("SystemTables", ((SystemTablesDocument) map + .get("SystemTables")).getSystemTables()); + } + if (map.get("DataHubs") != null) { + newMap.put("DataHubs", ((DataHubsDocument) map.get("DataHubs")) + .getDataHubs()); + } + if (map.get("Formsets") != null) { + newMap.put("Formsets", ((FormsetsDocument) map.get("Formsets")) + .getFormsets()); + } + if (map.get("Guids") != null) { + newMap.put("Guids", ((GuidsDocument) map.get("Guids")).getGuids()); + } + if (map.get("Externs") != null) { + newMap.put("Externs", ((ExternsDocument) map.get("Externs")) + .getExterns()); + } + if (map.get("PCDs") != null) { + newMap.put("PCDs", ((PCDsDocument) map.get("PCDs")).getPCDs()); + } + if (map.get("BuildOptions") != null) { + newMap.put("BuildOptions", ((BuildOptionsDocument) map + .get("BuildOptions")).getBuildOptions()); + } + return newMap; + } + + /** + Recursively remove all subelement in Xml Object l (with low priority) + based on OverrideID or exclusive elements. + + @param l the XML object to process + @param map list of elements with OverrideID in high priority XML object + @param execusiveMap list of exclusive elements in high priority XML object + **/ + private void cut(XmlCursor l, Map map, Map execusiveMap) { + String name = l.getName().getLocalPart(); + if (execusiveMap.containsKey(name)){ + l.removeXml(); + return; + } + String overrideID = l.getAttributeText(new QName("OverrideID")); + if (overrideID != null) { + if (map.containsKey(name + ":" + overrideID)) { + l.removeXml(); + return; + } + } + if (l.toFirstChild()) { + do { + cut(l, map, execusiveMap); + } while (l.toNextSibling()); + } + } + + private XmlObject cloneXmlObject(XmlObject object, boolean deep) throws BuildException { + XmlObject result = null; + try { + result = XmlObject.Factory.parse(object.getDomNode() + .cloneNode(deep)); + } catch (Exception ex) { + throw new BuildException(ex.getMessage()); + } + return result; + } + + /** + Process every item list in h and l. + + @param h surface area info with high priority + @param l surface area info with low priority + @return surface area after override + **/ + public Map override(Map h, + Map l) { + Map result = new HashMap(); + result.put("MsaHeader", override(l.get("MsaHeader"), null)); + result.put("MsaLibHeader", override(l.get("MsaLibHeader"), null)); + for (int i = 0; i < topElements.length; i++) { + result.put(topElements[i], override(h.get(topElements[i]), l + .get(topElements[i]))); + } + return result; + } + + /** + Recursively override two Xml Objects. + + @param h Xml Object info with high priority + @param l Xml Object info with low priority + @return Xml Object after area + **/ + public XmlObject override(XmlObject h, XmlObject l) { + if (l == null && h == null) { + return null; + } + if (h == null) { + return cloneXmlObject(l, true); + } + if (l == null) { + return cloneXmlObject(h, true); + } + XmlCursor hc = h.newCursor(); + if (h.getClass() != l.getClass()) { + System.out + .println("Error: Two XmlObject does not with compliant format."); + return null; + } + if (!hc.toFirstChild()) { + return cloneXmlObject(l, true); + } + + XmlCursor result = cloneXmlObject(h, true).newCursor(); + XmlCursor lcursor = cloneXmlObject(l, true).newCursor(); + result.push(); + result.toNextToken(); + result.insertNamespace("", prefix); + result.toFirstChild(); + // + // found out all element specified a OverrideID + // + Map hmap = new HashMap(); + Map execlusiveMap = new HashMap(); + listOverrideID(h, hmap, execlusiveMap, 0); + lcursor.toNextToken(); + lcursor.push(); + // + // for every direct subelement of l, cut all element satisfied with + // override rule + // + if (lcursor.toFirstChild()) { + do { + cut(lcursor, hmap, execlusiveMap); + } while (lcursor.toNextSibling()); + } + lcursor.pop(); + if (lcursor.toFirstChild()) { + do { + lcursor.copyXml(result); + result.insertChars("\n"); + } while (lcursor.toNextSibling()); + } + result.pop(); + return result.getObject(); + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/Spd.java b/Tools/Source/GenBuild/org/tianocore/build/global/Spd.java new file mode 100644 index 0000000000..54c1391094 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/Spd.java @@ -0,0 +1,414 @@ +/** @file + Spd class. + + This class is to generate a global table for the content of spd file. + + 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.global; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.tianocore.PackageSurfaceAreaDocument; +import org.tianocore.GuidDeclarationsDocument.GuidDeclarations; +import org.tianocore.IncludeHeaderDocument.IncludeHeader; +import org.tianocore.LibraryClassDeclarationDocument.LibraryClassDeclaration; +import org.tianocore.LibraryClassDeclarationsDocument.LibraryClassDeclarations; +import org.tianocore.PackageHeadersDocument.PackageHeaders; +import org.tianocore.PackageSurfaceAreaDocument.PackageSurfaceArea; +import org.tianocore.PpiDeclarationsDocument.PpiDeclarations; +import org.tianocore.ProtocolDeclarationsDocument.ProtocolDeclarations; + +/** + + This class is to generate a global table for the content of spd file. + +**/ +public class Spd { + /// + /// Map of module name and package it belongs to. + /// Key : Module BaseName + /// Value: Relative Path to Package + /// + Map msaInfo = new HashMap(); + + /// + /// Map of module info. + /// Key : moduletype + /// Value: moduletype related include file + /// + Map moduleInfo = new HashMap(); + + /// + /// Map of PPI info. + /// Key : PPI name + /// value: String[] a. PPI C_NAME; b. PPI GUID; + /// + Map ppiInfo = new HashMap(); + + /// + /// Map of Protocol info. + /// Key : Protocol name + /// value: String[] a. Protocol C_NAME; b. Protocol GUID; + /// + Map protocolInfo = new HashMap(); + + /// + /// Map of Guid info. + /// Key : Guid name + /// value: String[] a. Guid C_NAME; b. Guid's GUID; + /// + Map guidInfo = new HashMap(); + + + /// + /// Map of library class and its exposed header file. + /// Key : library class name + /// value : library class corresponding header file + /// + Map libClassHeaderList = new HashMap(); + + /// + /// Package path. + /// + String packagePath = null; + + /** + Constructor function + + This function mainly initialize some member variables. + + @param spdDoc Handle of spd document. + @param spdPath Path of spd file. + **/ + Spd (PackageSurfaceAreaDocument spdDoc, String spdPath) { + + PackageSurfaceArea spd = spdDoc.getPackageSurfaceArea(); + this.packagePath = spdPath; + + GuidDeclarations spdGuidInfo = spd.getGuidDeclarations(); + genGuidInfoList(spdGuidInfo); + + PpiDeclarations spdPpiInfo = spd.getPpiDeclarations(); + genPpiInfoList(spdPpiInfo); + + ProtocolDeclarations spdProtocolInfo = spd.getProtocolDeclarations(); + genProtocolInfoList(spdProtocolInfo); + + LibraryClassDeclarations spdLibClassDeclare = spd + .getLibraryClassDeclarations(); + genLibClassDeclare(spdLibClassDeclare); + + PackageHeaders spdPackageHeaderInfo = spd.getPackageHeaders(); + genModuleInfoList(spdPackageHeaderInfo); + + } + + /** + genModuleInfoList + + This function is to generate Module info map. + + @param packageHeader The information of packageHeader which descripted + in spd file. + **/ + public void genModuleInfoList(PackageHeaders packageHeader) { + + if (packageHeader != null) { + List headerList = packageHeader.getIncludeHeaderList(); + for (int i = 0; i < headerList.size(); i++) { + try { + this.moduleInfo + .put(headerList.get(i).getModuleType() + .toString(), headerList.get(i) + .getStringValue()); + } catch (Exception e) { + System.out + .print("can't find ModuleHeaders ModuleType & includeHeader!\n"); + } + } + } + } + + /** + genPpiInfoList + + This function is to generate Ppi info map. + + @param ppiInfo The information of PpiDeclarations which descripted + in spd file. + **/ + public void genPpiInfoList(PpiDeclarations ppiInfo) { + String[] cNameGuid = new String[2]; + + if (ppiInfo != null) { + List ppiEntryList = ppiInfo.getEntryList(); + for (int i = 0; i < ppiEntryList.size(); i++) { + try { + cNameGuid[0] = ppiEntryList.get(i).getCName(); + cNameGuid[1] = formatGuidName(ppiEntryList.get(i) + .getGuid().getStringValue()); + this.ppiInfo.put(ppiEntryList.get(i).getName(), new String[] { + cNameGuid[0], cNameGuid[1] }); + } catch (Exception e) { + System.out + .print("can't find GuidDeclarations C_Name & Guid!\n"); + } + } + } + } + + /** + genProtocolInfoList + + This function is to generate Protocol info map. + + @param proInfo The information of ProtocolDeclarations which + descripted in spd file. + **/ + public void genProtocolInfoList(ProtocolDeclarations proInfo) { + String[] cNameGuid = new String[2]; + if (proInfo != null) { + List protocolEntryList = proInfo.getEntryList(); + for (int i = 0; i < protocolEntryList.size(); i++) { + try { + cNameGuid[0] = protocolEntryList.get(i).getCName(); + cNameGuid[1] = formatGuidName(protocolEntryList.get(i) + .getGuid().getStringValue()); + + String temp = new String(protocolEntryList.get(i).getName()); + this.protocolInfo.put(temp, new String[] { cNameGuid[0], + cNameGuid[1] }); + } catch (Exception e) { + System.out + .print("can't find ProtocolDeclarations C_Name & Guid!\n"); + } + } + } + } + + /** + genGuidInfoList + + This function is to generate GUID inf map. + + @param guidInfo The information of GuidDeclarations which descripted + in spd file. + + **/ + public void genGuidInfoList(GuidDeclarations guidInfo) { + String[] cNameGuid = new String[2]; + if (guidInfo != null) { + + List guidEntryList = guidInfo.getEntryList(); + for (int i = 0; i < guidEntryList.size(); i++) { + cNameGuid[0] = guidEntryList.get(i).getCName(); + cNameGuid[1] = formatGuidName(guidEntryList.get(i) + .getGuid().getStringValue()); + this.guidInfo.put(guidEntryList.get(i).getName(), new String[] { + cNameGuid[0], cNameGuid[1] }); + } + } + } + + /** + genLibClassDeclare + + This function is to generate the libClassHeader list. + + @param libClassDeclares The information of LibraryClassDeclarations which + descripted in spd file. + **/ + public void genLibClassDeclare(LibraryClassDeclarations libClassDeclares) { + if (libClassDeclares != null && libClassDeclares.getLibraryClassDeclarationList() != null) { + if (libClassDeclares.getLibraryClassDeclarationList().size() > 0) { + List libDeclareList = libClassDeclares.getLibraryClassDeclarationList(); + for (int i = 0; i < libDeclareList.size(); i++) { + libClassHeaderList.put(libDeclareList.get(i).getLibraryClass() + .getStringValue(), libDeclareList.get(i) + .getIncludeHeader().getStringValue()); + } + } + } + } + + /** + getPpiGuid + + This function is to get ppi GUID according ppi name. + + @param ppiStr Name of ppi. + @return PPi's GUID. + **/ + public String getPpiGuid(String ppiStr) { + if (ppiInfo.get(ppiStr) != null) { + return ppiInfo.get(ppiStr)[1]; + } else { + return null; + } + + } + + /** + getPpiCnameGuidArray + + This function is to get the ppi CName and it's GUID according to ppi name. + + @param ppiName Name of ppi. + @return Ppi CName and it's GUID. + **/ + public String[] getPpiCnameGuidArray(String ppiName) { + return this.ppiInfo.get(ppiName); + } + + /** + getProtocolGuid + + This function is to get the protocol GUID according to protocol's name. + + @param protocolStr Name of protocol. + @return Protocol's GUID. + **/ + public String getProtocolGuid(String protocolStr) { + if (protocolInfo.get(protocolStr) != null) { + return this.protocolInfo.get(protocolStr)[0]; + } else { + return null; + } + } + + /** + getProtocolNameGuidArray + + This function is to get the protocol's CName ant it's GUID according to + protocol's namej. + + @param protocolName Name of protocl. + @return Protocol's CName and it's GUID. + **/ + public String[] getProtocolNameGuidArray(String protocolName) { + return this.protocolInfo.get(protocolName); + } + + /** + getGUIDGuid + + This function is to get the GUID according to GUID's name + + @param guidStr Name of GUID + @return GUID. + **/ + public String getGUIDGuid(String guidStr) { + if (guidInfo.get(guidStr) != null) { + return guidInfo.get(guidStr)[1]; + } else { + return null; + } + + } + + /** + getGuidNameArray + + This function is to get the GUID's CName and it's GUID according to + GUID's name + + @param guidName Name of GUID + @return CName and GUID. + **/ + public String[] getGuidNameArray(String guidName) { + return this.guidInfo.get(guidName); + } + + /** + getLibClassInclude + + This function is to get the library exposed header file name according + library class name. + + @param libName Name of library class + @return Name of header file + **/ + String getLibClassIncluder(String libName) { + return libClassHeaderList.get(libName); + } + + /** + getModuleTypeIncluder + + This function is to get the header file name from module info map + according to module type. + + @param moduleType Module type. + @return Name of header file. + **/ + String getModuleTypeIncluder(String moduleType) { + return moduleInfo.get(moduleType); + } + + /** + formateGuidName + + This function is to formate GUID to ANSI c form. + + @param guidNameCon String of GUID. + @return Formated GUID. + **/ + public static String formatGuidName (String guidNameConv) { + String[] strList; + String guid = ""; + int index = 0; + if (guidNameConv + .matches("[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}")) { + strList = guidNameConv.split("-"); + guid = "0x" + strList[0] + ", "; + guid = guid + "0x" + strList[1] + ", "; + guid = guid + "0x" + strList[2] + ", "; + guid = guid + "{"; + guid = guid + "0x" + strList[3].substring(0, 2) + ", "; + guid = guid + "0x" + strList[3].substring(2, 4); + + while (index < strList[4].length()) { + guid = guid + ", "; + guid = guid + "0x" + strList[4].substring(index, index + 2); + index = index + 2; + } + guid = guid + "}"; + return guid; + } else if (guidNameConv + .matches("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}( )*(\\})?")) { + strList = guidNameConv.split(","); + + // + // chang Microsoft specific form to ANSI c form + // + for (int i = 0; i < 3; i++){ + guid = guid + strList[i] + ","; + } + guid = guid + "{"; + + for (int i = 3; i < strList.length; i++){ + if (i == strList.length - 1){ + guid = guid + strList[i]; + } else { + guid = guid + strList[i] + ","; + } + } + guid = guid + "}"; + return guid; + } else { + System.out.println("Check GUID Value, it don't conform to the schema!!!"); + return "0"; + + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaParser.java b/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaParser.java new file mode 100644 index 0000000000..96003c2e71 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaParser.java @@ -0,0 +1,218 @@ +/** @file + SurfaceAreaParser class. + + SurfaceAreaParser class is used to parse module surface area include both + driver and library. + +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.global; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tools.ant.BuildException; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.LibraryModuleBuildDescriptionDocument; +import org.tianocore.LibraryModuleSurfaceAreaDocument; +import org.tianocore.ModuleBuildDescriptionDocument; +import org.tianocore.ModuleSurfaceAreaDocument; + +/** + This class is used to parse module surface area (MSA & MBD) include both + driver and library. + + @since GenBuild 1.0 +**/ +public class SurfaceAreaParser { + + /** + Using XmlBeans to parse and valid surface area file. + + @param surfaceAreaFile the surface area file to parse + @return top level elements and its value mapping information + @throws BuildException + If surface area is not well-formed or invalid + **/ + public Map parseFile(File surfaceAreaFile) throws BuildException { + Map map = new HashMap(); + try { + XmlObject sadoc = XmlObject.Factory.parse(surfaceAreaFile); + // Validate File if they obey XML Schema + + if ( ! sadoc.validate()){ + throw new BuildException("Surface Area file [" + surfaceAreaFile.getPath() + "] is invalid."); + } + if (sadoc instanceof ModuleSurfaceAreaDocument){ + parseFile((ModuleSurfaceAreaDocument) sadoc, map); + } + else if(sadoc instanceof ModuleBuildDescriptionDocument){ + parseFile((ModuleBuildDescriptionDocument) sadoc, map); + } + else if(sadoc instanceof LibraryModuleSurfaceAreaDocument){ + parseFile((LibraryModuleSurfaceAreaDocument) sadoc, map); + } + else if(sadoc instanceof LibraryModuleBuildDescriptionDocument){ + parseFile((LibraryModuleBuildDescriptionDocument) sadoc, map); + } + } + catch (Exception ex){ + throw new BuildException(ex.getMessage()); + } + return map; + } + + + /** + Parse MSA. + + @param doc top level surface area XML document + @param msaMap the map to store the result + **/ + private void parseFile(ModuleSurfaceAreaDocument doc, Map msaMap) { + msaMap.put("MsaHeader", doc.getModuleSurfaceArea().getMsaHeader()); + msaMap.put("LibraryClassDefinitions", doc.getModuleSurfaceArea() + .getLibraryClassDefinitions()); + msaMap.put("SourceFiles", doc.getModuleSurfaceArea().getSourceFiles()); + msaMap.put("Includes", doc.getModuleSurfaceArea().getIncludes()); + msaMap.put("Protocols", doc.getModuleSurfaceArea().getProtocols()); + + msaMap.put("Events", doc.getModuleSurfaceArea().getEvents()); + msaMap.put("Hobs", doc.getModuleSurfaceArea().getHobs()); + msaMap.put("PPIs", doc.getModuleSurfaceArea().getPPIs()); + msaMap.put("Variables", doc.getModuleSurfaceArea().getVariables()); + msaMap.put("BootModes", doc.getModuleSurfaceArea().getBootModes()); + + msaMap + .put("SystemTables", doc.getModuleSurfaceArea() + .getSystemTables()); + msaMap.put("DataHubs", doc.getModuleSurfaceArea().getDataHubs()); + msaMap.put("Formsets", doc.getModuleSurfaceArea().getFormsets()); + msaMap.put("Guids", doc.getModuleSurfaceArea().getGuids()); + msaMap.put("Externs", doc.getModuleSurfaceArea().getExterns()); + + msaMap.put("PCDs", doc.getModuleSurfaceArea().getPCDs()); + msaMap + .put("BuildOptions", doc.getModuleSurfaceArea() + .getBuildOptions()); + } + + /** + Parse MBD. + + @param doc top level surface area XML document + @param msaMap the map to store the result + **/ + private void parseFile(ModuleBuildDescriptionDocument doc, Map mbdMap) { + mbdMap.put("MbdHeader", doc.getModuleBuildDescription().getMbdHeader()); + mbdMap.put("Libraries", doc.getModuleBuildDescription().getLibraries()); + mbdMap.put("SourceFiles", doc.getModuleBuildDescription() + .getSourceFiles()); + mbdMap.put("Includes", doc.getModuleBuildDescription().getIncludes()); + mbdMap.put("Protocols", doc.getModuleBuildDescription().getProtocols()); + + mbdMap.put("Events", doc.getModuleBuildDescription().getEvents()); + mbdMap.put("Hobs", doc.getModuleBuildDescription().getHobs()); + mbdMap.put("PPIs", doc.getModuleBuildDescription().getPPIs()); + mbdMap.put("Variables", doc.getModuleBuildDescription().getVariables()); + mbdMap.put("BootModes", doc.getModuleBuildDescription().getBootModes()); + + mbdMap.put("SystemTables", doc.getModuleBuildDescription() + .getSystemTables()); + mbdMap.put("DataHubs", doc.getModuleBuildDescription().getDataHubs()); + mbdMap.put("Formsets", doc.getModuleBuildDescription().getFormsets()); + mbdMap.put("Guids", doc.getModuleBuildDescription().getGuids()); + mbdMap.put("Externs", doc.getModuleBuildDescription().getExterns()); + + mbdMap.put("PCDs", doc.getModuleBuildDescription().getPCDs()); + mbdMap.put("BuildOptions", doc.getModuleBuildDescription() + .getBuildOptions()); + } + /** + Parse Library MSA. + + @param doc top level surface area XML document + @param msaMap the map to store the result + **/ + private void parseFile(LibraryModuleSurfaceAreaDocument doc, Map msaMap) { + msaMap.put("MsaLibHeader", doc.getLibraryModuleSurfaceArea() + .getMsaLibHeader()); + msaMap.put("LibraryClassDefinitions", doc.getLibraryModuleSurfaceArea() + .getLibraryClassDefinitions()); + msaMap.put("SourceFiles", doc.getLibraryModuleSurfaceArea() + .getSourceFiles()); + msaMap.put("Includes", doc.getLibraryModuleSurfaceArea().getIncludes()); + msaMap.put("Protocols", doc.getLibraryModuleSurfaceArea() + .getProtocols()); + + msaMap.put("Events", doc.getLibraryModuleSurfaceArea().getEvents()); + msaMap.put("Hobs", doc.getLibraryModuleSurfaceArea().getHobs()); + msaMap.put("PPIs", doc.getLibraryModuleSurfaceArea().getPPIs()); + msaMap.put("Variables", doc.getLibraryModuleSurfaceArea() + .getVariables()); + msaMap.put("BootModes", doc.getLibraryModuleSurfaceArea() + .getBootModes()); + + msaMap.put("SystemTables", doc.getLibraryModuleSurfaceArea() + .getSystemTables()); + msaMap.put("DataHubs", doc.getLibraryModuleSurfaceArea().getDataHubs()); + msaMap.put("Formsets", doc.getLibraryModuleSurfaceArea().getFormsets()); + msaMap.put("Guids", doc.getLibraryModuleSurfaceArea().getGuids()); + msaMap.put("Externs", doc.getLibraryModuleSurfaceArea().getExterns()); + + msaMap.put("PCDs", doc.getLibraryModuleSurfaceArea().getPCDs()); + msaMap.put("BuildOptions", doc.getLibraryModuleSurfaceArea() + .getBuildOptions()); + } + + /** + Parse Library MBD. + + @param doc top level surface area XML document + @param msaMap the map to store the result + **/ + private void parseFile(LibraryModuleBuildDescriptionDocument doc, Map mbdMap) { + mbdMap.put("MbdLibHeader", doc.getLibraryModuleBuildDescription() + .getMbdLibHeader()); + mbdMap.put("Libraries", doc.getLibraryModuleBuildDescription() + .getLibraries()); + mbdMap.put("SourceFiles", doc.getLibraryModuleBuildDescription() + .getSourceFiles()); + mbdMap.put("Includes", doc.getLibraryModuleBuildDescription() + .getIncludes()); + mbdMap.put("Protocols", doc.getLibraryModuleBuildDescription() + .getProtocols()); + + mbdMap + .put("Events", doc.getLibraryModuleBuildDescription() + .getEvents()); + mbdMap.put("Hobs", doc.getLibraryModuleBuildDescription().getHobs()); + mbdMap.put("PPIs", doc.getLibraryModuleBuildDescription().getPPIs()); + mbdMap.put("Variables", doc.getLibraryModuleBuildDescription() + .getVariables()); + mbdMap.put("BootModes", doc.getLibraryModuleBuildDescription() + .getBootModes()); + + mbdMap.put("SystemTables", doc.getLibraryModuleBuildDescription() + .getSystemTables()); + mbdMap.put("DataHubs", doc.getLibraryModuleBuildDescription() + .getDataHubs()); + mbdMap.put("Formsets", doc.getLibraryModuleBuildDescription() + .getFormsets()); + mbdMap.put("Guids", doc.getLibraryModuleBuildDescription().getGuids()); + mbdMap.put("Externs", doc.getLibraryModuleBuildDescription() + .getExterns()); + + mbdMap.put("PCDs", doc.getLibraryModuleBuildDescription().getPCDs()); + mbdMap.put("BuildOptions", doc.getLibraryModuleBuildDescription() + .getBuildOptions()); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaQuery.java b/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaQuery.java new file mode 100644 index 0000000000..03c8d4328d --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaQuery.java @@ -0,0 +1,1109 @@ +/** @file + This file is for surface area information retrieval. + + 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.global; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.xmlbeans.XmlNormalizedString; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlString; +import org.tianocore.BuildOptionsDocument; +import org.tianocore.CName; +import org.tianocore.ExternsDocument; +import org.tianocore.FfsDocument; +import org.tianocore.FileNameConvention; +import org.tianocore.FrameworkComponentTypes; +import org.tianocore.FvImageOptionsDocument; +import org.tianocore.GuidDocument; +import org.tianocore.GuidsDocument; +import org.tianocore.LibrariesDocument; +import org.tianocore.LibraryClassDocument; +import org.tianocore.LibraryUsage; +import org.tianocore.ModuleSADocument; +import org.tianocore.ModuleTypeDef; +import org.tianocore.NameValueDocument; +import org.tianocore.OutputDirectoryDocument; +import org.tianocore.PPIsDocument; +import org.tianocore.PackageNameDocument; +import org.tianocore.ProtocolsDocument; +import org.tianocore.PCDsDocument.PCDs; + +/** + SurfaceAreaQuery class is used to query Surface Area information from msa, mbd, + spd and fpd files. + + This class should not instantiated. All the public interfaces is static. + + @since GenBuild 1.0 + **/ +public class SurfaceAreaQuery { + /// + /// Contains name/value pairs of Surface Area document object. The name is + /// always the top level element name. + /// + private static Map map = null; + + /// + /// mapStack is used to do nested query + /// + private static Stack< Map > mapStack = new Stack< Map >(); + + /// + /// prefix of name space + /// + private static String nsPrefix = "sans"; + + /// + /// xmlbeans needs a name space for each Xpath element + /// + private static String ns = null; + + /// + /// keep the namep declaration for xmlbeans Xpath query + /// + private static String queryDeclaration = null; + + /** + Set a Surface Area document for query later + + @param map A Surface Area document in TopLevelElementName/XmlObject format. + **/ + public static void setDoc(Map map) { + ns = OverrideProcess.prefix; + queryDeclaration = "declare namespace " + nsPrefix + "='" + ns + "'; "; + SurfaceAreaQuery.map = map; + } + + /** + Push current used Surface Area document into query stack. The given new + document will be used for any immediately followed getXXX() callings, + untill pop() is called. + + @param newMap The TopLevelElementName/XmlObject format of a Surface Area document. + **/ + public static void push(Map newMap) { + mapStack.push(SurfaceAreaQuery.map); + SurfaceAreaQuery.map = newMap; + } + + /** + Discard current used Surface Area document and use the top document in stack + instead. + **/ + public static void pop() { + SurfaceAreaQuery.map = mapStack.pop(); + } + + /// + /// Convert xPath to be namespace qualified, which is necessary for XmlBeans + /// selectPath(). For example, converting /MsaHeader/ModuleType to + /// /ns:MsaHeader/ns:ModuleType + /// + private static String normalizeQueryString(String[] exp, String from) { + StringBuffer normQueryString = new StringBuffer(4096); + + int i = 0; + while (i < exp.length) { + String newExp = from + exp[i]; + Pattern pattern = Pattern.compile("([^/]*)(/|//)([^/]+)"); + Matcher matcher = pattern.matcher(newExp); + + while (matcher.find()) { + String starter = newExp.substring(matcher.start(1), matcher.end(1)); + String seperator = newExp.substring(matcher.start(2), matcher.end(2)); + String token = newExp.substring(matcher.start(3), matcher.end(3)); + + normQueryString.append(starter); + normQueryString.append(seperator); + normQueryString.append(nsPrefix); + normQueryString.append(":"); + normQueryString.append(token); + } + + ++i; + if (i < exp.length) { + normQueryString.append(" | "); + } + } + + return normQueryString.toString(); + } + + /** + Search all XML documents stored in "map" for the specified xPath, using + relative path (starting with '$this') + + @param xPath xpath query string array + @returns An array of XmlObject if elements are found at the specified xpath + @returns NULL if nothing is at the specified xpath + **/ + public static XmlObject[] get(String[] xPath) { + if (map == null) { + return null; + } + + String[] keys = (String[]) map.keySet().toArray(new String[map.size()]); + List result = new ArrayList(); + for (int i = 0; i < keys.length; ++i) { + XmlObject rootNode = (XmlObject) map.get(keys[i]); + if (rootNode == null) { + continue; + } + + String query = queryDeclaration + normalizeQueryString(xPath, "$this/" + keys[i]); + XmlObject[] tmp = rootNode.selectPath(query); + for (int j = 0; j < tmp.length; ++j) { + result.add(tmp[j]); + } + } + + int size = result.size(); + if (size <= 0) { + return null; + } + + return (XmlObject[]) result.toArray(new XmlObject[size]); + } + + /** + Search XML documents named by "rootName" for the given xPath, using + relative path (starting with '$this') + + @param rootName The top level element name + @param xPath The xpath query string array + @returns An array of XmlObject if elements are found at the given xpath + @returns NULL if nothing is found at the given xpath + **/ + public static XmlObject[] get(String rootName, String[] xPath) { + if (map == null) { + return null; + } + + XmlObject root = (XmlObject) map.get(rootName); + if (root == null) { + return null; + } + + String query = queryDeclaration + normalizeQueryString(xPath, "$this/" + rootName); + XmlObject[] result = root.selectPath(query); + if (result.length > 0) { + return result; + } + + query = queryDeclaration + normalizeQueryString(xPath, "/" + rootName); + result = root.selectPath(query); + if (result.length > 0) { + return result; + } + + return null; + } + + /** + Retrieve SourceFiles/Filename for specified ARCH type + + @param arch architecture name + @returns An array of XmlObject if elements are found at the known xpath + @returns NULL if nothing is found at the known xpath + **/ + public static XmlObject[] getSourceFiles(String arch) { + String[] xPath; + + if (arch == null || arch.equals("")) { + xPath = new String[] { + "/Filename", + "/Arch/Filename" + }; + } else { + xPath = new String[] { + "/Filename[not(@ArchType) or @ArchType='ALL' or @ArchType='" + arch + "']", + "/Arch[@ArchType='ALL' or @ArchType='" + arch + "']/Filename" + }; + } + + return get("SourceFiles", xPath); + } + + /** + Retrieve BuildOptions/Ffs + + @returns FfsDocument.Ffs object if elements are found at the known xpath + @returns NULL if nothing is found at the known xpath + **/ + public static FfsDocument.Ffs getFfs() { + String[] xPath = new String[] { "/Ffs" }; + + XmlObject[] returns = get("BuildOptions", xPath); + if (returns != null && returns.length > 0) { + return (FfsDocument.Ffs) returns[0]; + } + + return null; + } + + /** + Retrieve BuildOptions/OutputDirectory + + @returns Directory names array if elements are found at the known xpath + @returns Empty if nothing is found at the known xpath + **/ + public static String[] getOutputDirectory() { + String[] xPath = new String[] { "/OutputDirectory" }; + + XmlObject[] returns = get("BuildOptions", xPath); + if (returns != null && returns.length > 0) { + String[] dirString = new String[2]; + + OutputDirectoryDocument.OutputDirectory[] dir = (OutputDirectoryDocument.OutputDirectory[]) returns; + dirString[0] = dir[0].getIntermediateDirectories().toString(); + dirString[1] = dir[0].getStringValue(); + + return dirString; + } + + return new String[] { "UNIFIED", null }; + } + + /** + Retrieve BuildOptions/Option or Arch/Option + + @param arch architecture name + + @returns name/value pairs of options if elements are found at the known xpath + @returns Empty array if nothing is there + **/ + public static String[][] getOptions(String arch){ + String[] xPath; + + if (arch == null || arch.equals("")) { + xPath = new String[] { + "/Option", + "/Arch/Option" + }; + } else { + xPath = new String[] { + "/Option", + "/Arch[@ArchType='ALL' or @ArchType='" + arch + "']/Option" + }; + } + + XmlObject[] returns = get("BuildOptions", xPath); + if (returns == null){ + return new String[0][2]; + } + + String[][] result = new String[returns.length][2]; + for (int i = 0; i < returns.length; i ++){ + String str; + String name = null; + String value = null; + + if (returns[i] instanceof BuildOptionsDocument.BuildOptions.Option) { + BuildOptionsDocument.BuildOptions.Option option = (BuildOptionsDocument.BuildOptions.Option)returns[i]; + str = option.getStringValue(); + } else if (returns[i] instanceof BuildOptionsDocument.BuildOptions.Arch.Option) { + BuildOptionsDocument.BuildOptions.Arch.Option archOption = (BuildOptionsDocument.BuildOptions.Arch.Option)returns[i]; + str = archOption.getStringValue(); + } else { + continue; + } + + int equalIndex = str.indexOf('='); + if ( equalIndex > 0) { + name = str.substring(0, equalIndex).trim(); + value = str.substring(equalIndex + 1).trim(); + // TBD remove some forbidden name: BASE_NAME, ARCH and so on + if (name.length() == 0){ + name = null; + } + } + result[i][0] = name; + result[i][1] = value; + } + + return result; + } + + /** + Retrieve /ModuleType + + @returns The module type name if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getModuleType() { + String[] xPath = new String[] { "/ModuleType" }; + + XmlObject[] returns = get(xPath); + if (returns != null && returns.length > 0) { + ModuleTypeDef type = (ModuleTypeDef) returns[0]; + return type.enumValue().toString(); + } + + return null; + } + + /** + Retrieve /ComponentType + + @returns The component type name if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getComponentType() { + String[] xPath = new String[] { "/ComponentType" }; + + XmlObject[] returns = get(xPath); + if (returns != null && returns.length > 0) { + FrameworkComponentTypes type = (FrameworkComponentTypes) returns[0]; + return type.enumValue().toString(); + } + + return null; + } + + /** + Retrieve Includes/PackageName + + @param arch Architecture name + + @returns package name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static List getIncludePackageName(String arch) { + String[] xPath; + + if (arch == null || arch.equals("")) { + xPath = new String[] { + "/PackageName", + "/Arch/PackageName" + }; + } else { + xPath = new String[] { + "/PackageName", + "/Arch[@ArchType='ALL' or @ArchType='" + arch + "']/PackageName" + }; + } + + XmlObject[] returns = get("Includes", xPath); + if (returns == null || returns.length == 0) { + return null; + } + + List packageNames = new ArrayList(); + PackageNameDocument.PackageName[] nameObj = (PackageNameDocument.PackageName[])returns; + for (int i = 0; i < returns.length; ++i) { + packageNames.add(nameObj[i].getStringValue()); + } + + return packageNames; + } + + /** + Retrieve LibraryClassDefinitions/LibraryClass for specified usage + + @param usage Library class usage + + @returns LibraryClass objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static LibraryClassDocument.LibraryClass[] getLibraryClassArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] {"/LibraryClass"}; + } else { + xPath = new String[] {"/LibraryClass[@Usage='" + usage + "']"}; + } + + XmlObject[] returns = get("LibraryClassDefinitions", xPath); + if (returns != null && returns.length > 0) { + return (LibraryClassDocument.LibraryClass[]) returns; + } + + return null; + } + + /** + Retrieve ModuleEntryPoint names + + @returns ModuleEntryPoint name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getModuleEntryPointArray() { + String[] xPath = new String[] { "/Extern/ModuleEntryPoint" }; + + XmlObject[] returns = get("Externs", xPath); + + if (returns != null && returns.length > 0) { + String[] entryPoints = new String[returns.length]; + + for (int i = 0; i < returns.length; ++i) { + entryPoints[i] = ((XmlNormalizedString) returns[i]) + .getStringValue(); + } + + return entryPoints; + } + + return null; + } + + /** + Retrieve module Guid string + + @returns GUILD string if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getModuleGuid() { + String[] xPath = new String[] { "/Guid" }; + + XmlObject[] returns = get(xPath); + if (returns != null && returns.length > 0) { + GuidDocument.Guid guid = (GuidDocument.Guid) returns[0]; + return guid.getStringValue(); + } + + return null; + } + + /** + retrieve Protocol for specified usage + + @param usage Protocol usage + + @returns Protocol objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static ProtocolsDocument.Protocols.Protocol[] getProtocolArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] {"/Protocol"}; + } else { + xPath = new String[] {"/Protocol[@Usage='" + usage + "']"}; + } + + XmlObject[] returns = get("Protocols", xPath); + if (returns != null && returns.length > 0) { + return (ProtocolsDocument.Protocols.Protocol[]) returns; + } + + return null; + } + + /** + Retrieve ProtocolNotify for specified usage + + @param usage ProtocolNotify usage + + @returns ProtocolNotify objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static ProtocolsDocument.Protocols.ProtocolNotify[] getProtocolNotifyArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] {"/ProtocolNotify"}; + } else { + xPath = new String[] {"/ProtocolNotify[@Usage='" + usage + "']"}; + } + + XmlObject[] returns = get("Protocols", xPath); + if (returns != null && returns.length > 0) { + return (ProtocolsDocument.Protocols.ProtocolNotify[]) returns; + } + + return null; + } + + /** + Retrieve ModuleUnloadImage names + + @returns ModuleUnloadImage name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getModuleUnloadImageArray() { + String[] xPath = new String[] { "/Extern/ModuleUnloadImage" }; + + XmlObject[] returns = get("Externs", xPath); + if (returns != null && returns.length > 0) { + String[] stringArray = new String[returns.length]; + XmlNormalizedString[] doc = (XmlNormalizedString[])returns; + + for (int i = 0; i < returns.length; ++i) { + stringArray[i] = doc[i].getStringValue(); + } + + return stringArray; + } + + return null; + } + + /** + Retrieve Extern + + @returns Extern objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static ExternsDocument.Externs.Extern[] getExternArray() { + String[] xPath = new String[] { "/Extern" }; + + XmlObject[] returns = get("Externs", xPath); + if (returns != null && returns.length > 0) { + return (ExternsDocument.Externs.Extern[]) returns; + } + + return null; + } + + /** + Retrieve Ppi information + + @param usage Ppi usage + + @returns Ppi objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static PPIsDocument.PPIs.Ppi[] getPpiArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] { "/Ppi" }; + } else { + xPath = new String[] { "/Ppi[@Usage='" + usage + "']" }; + } + + XmlObject[] returns = get("PPIs", xPath); + if (returns != null && returns.length > 0) { + return (PPIsDocument.PPIs.Ppi[])returns; + } + + return null; + } + + /** + Retrive PpiNotify information + + @param usage + + @returns PpiNotify objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static PPIsDocument.PPIs.PpiNotify[] getPpiNotifyArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] { "/PpiNotify" }; + } else { + xPath = new String[] { "/PpiNotify[@Usage='" + usage + "']" }; + } + + XmlObject[] returns = get("PPIs", xPath); + if (returns != null && returns.length > 0) { + return (PPIsDocument.PPIs.PpiNotify[])returns; + } + + return null; + } + + /** + Retrieve GuidEntry information for specified usage + + @param usage GuidEntry usage + + @returns GuidEntry objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static GuidsDocument.Guids.GuidEntry[] getGuidEntryArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] { "/GuidEntry" }; + } else { + xPath = new String[] { "/GuidEntry[@Usage='" + usage + "']" }; + } + + XmlObject[] returns = get("Guids", xPath); + if (returns != null && returns.length > 0) { + return (GuidsDocument.Guids.GuidEntry[])returns; + } + + return null; + } + + /** + Retrieve Library instance information + + @param arch Architecture name + @param usage Library instance usage + + @returns library instance name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static List getLibraryInstance(String arch, String usage) { + String[] xPath; + String archAttribute = ""; + String usageAttribute = ""; + + if ((arch != null) || (!arch.equals(""))) { + archAttribute = "[@ArchType='ALL' or @ArchType='" + arch + "']"; + } + + if ((usage != null) || (!usage.equals(""))) { + // if no Usage attribute specified, default to ALWAYS_CONSUMED + if (usage.equals(LibraryUsage.ALWAYS_CONSUMED.toString())) { + usageAttribute = "[not(@Usage) or @Usage='" + usage + "']"; + } else { + usageAttribute = "[@Usage='" + usage + "']"; + } + } + + xPath = new String[] { + "/Library" + usageAttribute, + "/Arch" + archAttribute + "/Library" + usageAttribute + }; + + XmlObject[] returns = get("Libraries", xPath); + if (returns == null || returns.length == 0) { + return null; + } + + List instances = new ArrayList(); + for (int i = 0; i < returns.length; ++i) { + if (returns[i] instanceof LibrariesDocument.Libraries.Library) { + LibrariesDocument.Libraries.Library lib = (LibrariesDocument.Libraries.Library)returns[i]; + instances.add(lib.getStringValue()); + } else if (returns[i] instanceof LibrariesDocument.Libraries.Arch.Library) { + LibrariesDocument.Libraries.Arch.Library lib = (LibrariesDocument.Libraries.Arch.Library)returns[i]; + instances.add(lib.getStringValue()); + } + } + + return instances; + } + + /// + /// This method is used for retrieving the elements information which has + /// CName sub-element + /// + private static String[] getCNames(String from, String xPath[]) { + XmlObject[] returns = get(from, xPath); + if (returns == null || returns.length == 0) { + return null; + } + + String[] strings = new String[returns.length]; + for (int i = 0; i < returns.length; ++i) { + strings[i] = ((CName)returns[i]).getStringValue(); + } + + return strings; + } + + /** + Retrive library's constructor name + + @returns constructor name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getLibConstructorName() { + String[] xPath = new String[] {"/Extern/Constructor"}; + + XmlObject[] returns = get("Externs", xPath); + if (returns != null && returns.length > 0) { + CName constructor = (CName)returns[0]; + return constructor.getStringValue(); + } + + return null; + } + + /** + Retrive library's destructor name + + @returns destructor name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getLibDestructorName() { + String[] xPath = new String[] {"/Extern/Destructor"}; + + XmlObject[] returns = get("Externs", xPath); + if (returns != null && returns.length > 0) { + CName destructor = (CName)returns[0]; + return destructor.getStringValue(); + } + + return null; + } + + /** + Retrive DriverBinding names + + @returns DriverBinding name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getDriverBindingArray() { + String[] xPath = new String[] {"/Extern/DriverBinding"}; + return getCNames("Externs", xPath); + } + + /** + Retrive ComponentName names + + @returns ComponentName name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getComponentNameArray() { + String[] xPath = new String[] {"/Extern/ComponentName"}; + return getCNames("Externs", xPath); + } + + /** + Retrive DriverConfig names + + @returns DriverConfig name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getDriverConfigArray() { + String[] xPath = new String[] {"/Extern/DriverConfig"}; + return getCNames("Externs", xPath); + } + + /** + Retrive DriverDiag names + + @returns DriverDiag name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getDriverDiagArray() { + String[] xPath = new String[] {"/Extern/DriverDiag"}; + return getCNames("Externs", xPath); + } + + /** + Retrive SetVirtualAddressMapCallBack names + + @returns SetVirtualAddressMapCallBack name list + if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getSetVirtualAddressMapCallBackArray() { + String[] xPath = new String[] {"/Extern/SetVirtualAddressMapCallBack"}; + return getCNames("Externs", xPath); + } + + /** + Retrive ExitBootServicesCallBack names + + @returns ExitBootServicesCallBack name list + if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getExitBootServicesCallBackArray() { + String[] xPath = new String[] {"/Extern/ExitBootServicesCallBack"}; + return getCNames("Externs", xPath); + } + + /** + Retrieve module surface area file information + + @returns ModuleSA objects list if elements are found at the known xpath + @returns Empty ModuleSA list if nothing is there + **/ + public static ModuleSADocument.ModuleSA[] getFpdModules() { + String[] xPath = new String[] { "/TianoImage/*/ModuleSA" }; + + XmlObject[] result = get("FrameworkPlatformDescription", xPath); + if (result == null) { + return new ModuleSADocument.ModuleSA[0]; + } + + return (ModuleSADocument.ModuleSA[]) result; + } + + /** + Retrieve variables for FV images + + @returns name/value list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[][] getFpdGlobalVariable() { + String[] xPath = new String[] { "/Flash/FvImages/NameValue" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0][]; + } + + String[][] result = new String[queryResult.length][2]; + for (int i = 0; i < queryResult.length; i++){ + result[i][0] = ((NameValueDocument.NameValue)queryResult[i]).getName(); + result[i][1] = ((NameValueDocument.NameValue)queryResult[i]).getValue(); + } + + return result; + } + + /** + Retrieve valid image names + + @returns valid iamges name list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[] getFpdValidImageNames(){ + String[] xPath = new String[] { "/Flash/FvImages/FvImage[@Type='ValidImageNames']/FvImageNames" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0]; + } + + String[] result = new String[queryResult.length]; + for (int i = 0; i < queryResult.length; i++){ + result[i] = ((XmlString)queryResult[i]).getStringValue(); + } + + return result; + } + + /** + Retrieve FV image option information + + @param fvName FV image name + + @returns option name/value list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[][] getFpdOptions(String fvName){ + String[] xPath = new String[] {"/Flash/FvImages/FvImageName[@Name='" + fvName.toUpperCase() + "']/FvImageOptions/NameValue" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0][]; + } + + String[][] result = new String[queryResult.length][2]; + for (int i = 0; i < queryResult.length; i++){ + result[i][0] = ((NameValueDocument.NameValue)queryResult[i]).getName(); + result[i][1] = ((NameValueDocument.NameValue)queryResult[i]).getValue(); + } + + return result; + } + + /** + Retrieve FV image attributes information + + @param fvName FV image name + + @returns attribute name/value list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[][] getFpdAttributes(String fvName){ + String[] xPath = new String[] {"/Flash/FvImages/FvImage[@Type='Attributes' and ./FvImageNames='" + fvName.toUpperCase() + "']/FvImageOptions" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0][]; + } + + ArrayList list = new ArrayList(); + for (int i = 0 ; i < queryResult.length; i++){ + FvImageOptionsDocument.FvImageOptions item = (FvImageOptionsDocument.FvImageOptions)queryResult[i]; + + List namevalues = item.getNameValueList(); + Iterator iter = namevalues.iterator(); + while (iter.hasNext()) { + NameValueDocument.NameValue nvItem = (NameValueDocument.NameValue)iter.next(); + list.add(new String[]{nvItem.getName(), nvItem.getValue()}); + } + + List enables = item.getEnableList(); + iter = enables.iterator(); + while (iter.hasNext()) { + String enableItem = (String)iter.next(); + list.add(new String[]{enableItem, "TRUE"}); + } + + List disables = item.getDisableList(); + iter = disables.iterator(); + while (iter.hasNext()) { + String disableItem = (String)iter.next(); + list.add(new String[]{disableItem, "FALSE"}); + } + } + + String[][] result = new String[list.size()][2]; + for (int i = 0; i < list.size(); i++){ + result[i][0] = list.get(i)[0]; + result[i][1] = list.get(i)[1]; + } + + return result; + } + + /** + Retrieve flash definition file name + + @returns file name if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getFlashDefinitionFile(){ + String[] xPath = new String[] {"/Flash/FlashDefinitionFile" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null || queryResult.length == 0) { + return null; + } + + FileNameConvention filename = (FileNameConvention)queryResult[queryResult.length - 1]; + return filename.getStringValue(); + } + + /** + Retrieve FV image component options + + @param fvName FV image name + + @returns name/value pairs list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[][] getFpdComponents(String fvName){ + String[] xPath = new String[] {"/Flash/FvImages/FvImage[@Type='Components' and ./FvImageNames='" + fvName.toUpperCase() + "']/FvImageOptions" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0][]; + } + + ArrayList list = new ArrayList(); + for (int i = 0 ; i < queryResult.length; i++){ + FvImageOptionsDocument.FvImageOptions item = (FvImageOptionsDocument.FvImageOptions)queryResult[i]; + + List namevalues = item.getNameValueList(); + Iterator iter = namevalues.iterator(); + while (iter.hasNext()) { + NameValueDocument.NameValue nvItem = (NameValueDocument.NameValue)iter.next(); + list.add(new String[]{nvItem.getName(), nvItem.getValue()}); + } + + List enables = item.getEnableList(); + iter = enables.iterator(); + while (iter.hasNext()) { + String enableItem = (String)iter.next(); + list.add(new String[]{enableItem, "TRUE"}); + } + + List disables = item.getDisableList(); + iter = disables.iterator(); + while (iter.hasNext()) { + String disableItem = (String)iter.next(); + list.add(new String[]{disableItem, "FALSE"}); + } + } + + String[][] result = new String[list.size()][2]; + for (int i = 0; i < list.size(); i++){ + result[i][0] = list.get(i)[0]; + result[i][1] = list.get(i)[1]; + } + + return result; + } + + /** + Retrieve PCD tokens + + @returns CName/ItemType pairs list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[][] getPcdTokenArray() { + String[] xPath = new String[] {"/PcdData"}; + + XmlObject[] returns = get("PCDs", xPath); + if (returns == null || returns.length == 0) { + return null; + } + + PCDs.PcdData[] pcds = (PCDs.PcdData[]) returns; + String[][] result = new String[pcds.length][2]; + for (int i = 0; i < returns.length; ++i) { + if (pcds[i].getItemType() != null) { + result[i][1] = pcds[i].getItemType().toString(); + } else { + result[i][1] = null; + } + result[i][0] = pcds[i].getCName(); + } + + return result; + } + + /** + Get the PcdToken array from module's surface area document. + The array should contains following data: +

-------------------------------------------------------------------

+

CName | ItemType | TokenspaceName | DefaultValue | Usage | HelpText

+

-------------------------------------------------------------------

+

Note: Until new schema applying, now we can only get CName, ItemType,

+ + @return 2-array table contains all information of PCD token retrieved from MSA. + **/ + public static Object[][] getModulePCDTokenArray () { + int index; + Object[][] result; + PCDs.PcdData[] pcds; + String[] xPath = new String[] {"/PcdData"}; + XmlObject[] returns = get ("PCDs", xPath); + + if ((returns == null) || (returns.length == 0)) { + return null; + } + + pcds = (PCDs.PcdData[]) returns; + result = new Object[pcds.length][6]; + for (index = 0; index < pcds.length; index ++) { + // + // Get CName + // + result [index][0] = pcds[index].getCName(); + // + // Get ItemType: FEATURE_FLAG, FIXED_AT_BUILD, PATCHABLE_IN_MODLE, DYNAMIC, DYNAMIC_EX + // + if (pcds[index].getItemType() != null) { + result [index][1] = pcds[index].getItemType().toString(); + } else { + result [index][1] = null; + } + + // + // BUGBUG: following field can *not* be got from current MSA until schema changed. + // + //result [index][2] = pcds[index].getTokenSpaceName(); + result [index][2] = null; + result [index][3] = pcds[index].getDefaultValue(); + //result [index][4] = pcds[index].getUsage (); + result [index][4] = null; + //result [index][5] = pcds[index].getHelpText (); + result [index][5] = null; + } + return result; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/VariableTask.java b/Tools/Source/GenBuild/org/tianocore/build/global/VariableTask.java new file mode 100644 index 0000000000..f830e0ac76 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/VariableTask.java @@ -0,0 +1,71 @@ +/** @file + * This file is ANT task VariableTask. + * + * VariableTask task implements part of ANT property task. The difference is + * this task will override variable with same name, but ANT property task do not. + * + * 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.global; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +/** + * VariableTask task implements part of ANT property task. The difference is + * this task will override variable with same name, but ANT property task do not. + * + * @since GenBuild 1.0 + */ +public class VariableTask extends Task { + + /** + * property value + */ + private String value; + + /** + * property name + */ + private String name; + + /** + * Set property name. + * + * @param name property name + */ + public void setName( String name ) { + this.name = name; + } + + + /** + * Set property value. + * + * @param value property value + */ + public void setValue( String value ) { + this.value = value; + } + + /** + * ANT task's entry point, will be called after init(). + * + * @exception BuildException + * If name or value is null + */ + public void execute() throws BuildException { + if (name == null || value == null) { + throw new BuildException("Name or value must not null."); + } + getProject().setProperty(name, value); + } +} + diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ActionMessage.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ActionMessage.java new file mode 100644 index 0000000000..a67d2f9e4d --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ActionMessage.java @@ -0,0 +1,129 @@ +/** @file + ActionMessage class. + + ActionMessage class take over all message for loging and waning. This class should + dispatch message into different class according to instance class type. + +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 org.apache.tools.ant.Task; +import org.tianocore.build.pcd.action.BuildAction; +import org.tianocore.build.pcd.action.UIAction; + +/** ActionMessage class take over all message for loging and waning. This class + should dispatch message into different Action class according to instance + class type. +**/ +public class ActionMessage { + /// + /// Macro definition for NULL messge level. + /// In this meessage level, all message will be hidden. + /// + public final static int NULL_MESSAGE_LEVEL = 0; + /// + /// Macro definition for Log messge level. + /// In this message level, Only log information will be shown. + /// + public final static int LOG_MESSAGE_LEVEL = 1; + /// + /// Macro definition for Warning message level. + /// In this message level, log and waning message will be shown. + /// + public final static int WARNING_MESSAGE_LEVEL = 2; + /// + /// Macro definition for Debug mesage level. + /// In this message level, log, warning, debug message will be shown. + /// + public final static int DEBUG_MESSAGE_LEVEL = 3; + /// + /// Macor definition for MAX message level. + /// In this message level, all message will be shown. + /// + public final static int MAX_MESSAGE_LEVEL = 4; + /// + /// Current message level. It will control all message output for PCD tool. + /// + public static int messageLevel = NULL_MESSAGE_LEVEL; + + /** + Log() function provide common log information functionality for all + PCD tool includes all function + + This function will dispatch message to special class such as BuildAction + Class, Entity Class etc. + + @param thisClass The class object who want log information. + @param logStr The string contains log information. + **/ + public static void log(Object thisClass, String logStr) { + if(messageLevel < LOG_MESSAGE_LEVEL) { + return; + } + + if(thisClass instanceof Task) { + BuildAction.logMsg(thisClass, "$$LOG$$:" + logStr); + } else if(thisClass instanceof UIAction) { + UIAction.logMsg(thisClass, "$$LOG$$:" + logStr); + } else { + System.out.println("$$LOG$$:" + logStr); + } + } + + /** + Warning() function provide common warning information functionality for all + PCD tool. + + This function will dispatch message to special class such as BuildAction + Class, Entity Class etc. + + @param thisClass The class object who want warn information. + @param warningStr The string contains warning information. + **/ + public static void warning(Object thisClass, String warningStr) { + if(messageLevel < WARNING_MESSAGE_LEVEL) { + return; + } + + if(thisClass instanceof Task) { + BuildAction.warningMsg(thisClass, "**WARNING**:" + warningStr); + } else if(thisClass instanceof UIAction) { + UIAction.warningMsg(thisClass, "**WARNING**:" + warningStr); + } else { + System.out.println("**WARNING**:" + warningStr); + } + } + + /** + Debug() function provide common Debug information functionality for all + PCD tool. + + This function will dispatch message to special class such as BuildAction + Class, Entity Class etc. + + @param thisClass The class object who want Debug information. + @param debugStr The string contains Debug information. + **/ + public static void debug(Object thisClass, String debugStr) { + if(messageLevel < DEBUG_MESSAGE_LEVEL) { + return; + } + + if(thisClass instanceof Task) { + BuildAction.logMsg(thisClass, "%%DEBUG%%:" + debugStr); + } else if(thisClass instanceof UIAction) { + UIAction.logMsg(thisClass, "%%DEBUG%%:" + debugStr); + } else { + System.out.println("%%DEBUG%%:" + debugStr); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/BuildAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/BuildAction.java new file mode 100644 index 0000000000..c8b0d9dba1 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/BuildAction.java @@ -0,0 +1,114 @@ +/** @file + BuildAction class. + + BuildAction is the parent class for all action related to ant Task. This class will + define some common utility functionality, such as logMsg, warningMsg..etc. + +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 org.apache.tools.ant.Task; +import org.tianocore.build.pcd.exception.BuildActionException; + +/** BuildAction is the parent class for all action related to ant Task. This class will + define some common utility functionality, such as logMsg, warningMsg..etc. +**/ +abstract class BuildAction extends Task { + /// + /// Original message level before this action. This value will + /// be restored when quit this action. + /// + private int originalMessageLevel; + + /** + checkParameter function check all parameter valid. + + This function will be overrided by child class. + **/ + abstract void checkParameter() throws BuildActionException; + + /** + performAction is to execute the detail action. + + This function will be overrided by child class. + **/ + abstract void performAction() throws BuildActionException; + + /** + setMessageLevel function set current message for task instance object. + + The message should be restored when this action exit. + + @param messageLevel The message level for this action. + **/ + public void setMessageLevel(int messageLevel) { + originalMessageLevel = ActionMessage.messageLevel; + ActionMessage.messageLevel = messageLevel; + } + + /** + logMsg function provide common log information functionality for all + PCD tool extends from ANT task class. + + This function will use the log function in Ant task class. + + @param action The class object who want log information. + @param logStr The string contains log information. + **/ + public static void logMsg(Object action, String logStr) { + // + // Comment following code because in console debug environment, we can't + // get Project instance. + //((Task) action).log(errorText, Project.MSG_INFO); + // + System.out.println(logStr); + } + + /** + warningMsg function provide common warning information functionality for all + PCD tool. + + This function will dispatch message to special class such as BuildAction + Class, Entity Class etc. + + @param action The class object who want warn information. + @param warningStr The string contains warning information. + **/ + public static void warningMsg(Object action, String warningStr) { + // + // Comment following code because in console debug environment, we can't + // get Project instance. + //((Task) action).log(warningText, Project.MSG_WARN); + // + System.out.println(warningStr); + } + + /** + execute function is the main flow for all build action class. + + This workflow will be: + 1) Check paramet of this action. + 2) Perform the child class action function. + 3) Restore the message level. + + @throws BuildActionException + **/ + public void execute() throws BuildActionException { + checkParameter(); + performAction(); + + // + // Restore orignal message level when exist the action. + // + ActionMessage.messageLevel = originalMessageLevel; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java new file mode 100644 index 0000000000..055563df1b --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java @@ -0,0 +1,669 @@ +/** @file + CollectPCDAction class. + + This action class is to collect PCD information from MSA, SPD, FPD xml file. + This class will be used for wizard and build tools, So it can *not* inherit + from buildAction or wizardAction. + +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.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.FrameworkPlatformDescriptionDocument; +import org.tianocore.ModuleSADocument; +import org.tianocore.PackageSurfaceAreaDocument; +import org.tianocore.PcdBuildDeclarationsDocument.PcdBuildDeclarations.PcdBuildData; +import org.tianocore.PcdDefinitionsDocument.PcdDefinitions; +import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.pcd.action.ActionMessage; +import org.tianocore.build.pcd.entity.MemoryDatabaseManager; +import org.tianocore.build.pcd.entity.SkuInstance; +import org.tianocore.build.pcd.entity.Token; +import org.tianocore.build.pcd.entity.UsageInstance; +import org.tianocore.build.pcd.exception.EntityException; + +/** This action class is to collect PCD information from MSA, SPD, FPD xml file. + This class will be used for wizard and build tools, So it can *not* inherit + from buildAction or UIAction. +**/ +public class CollectPCDAction { + /// memoryDatabase hold all PCD information collected from SPD, MSA, FPD. + private MemoryDatabaseManager dbManager; + + /// Workspacepath hold the workspace information. + private String workspacePath; + + /// FPD file is the root file. + private String fpdFilePath; + + /// Message level for CollectPCDAction. + private int originalMessageLevel; + + /** + Set WorkspacePath parameter for this action class. + + @param workspacePath parameter for this action + **/ + public void setWorkspacePath(String workspacePath) { + this.workspacePath = workspacePath; + } + + /** + Set action message level for CollectPcdAction tool. + + The message should be restored when this action exit. + + @param actionMessageLevel parameter for this action + **/ + public void setActionMessageLevel(int actionMessageLevel) { + originalMessageLevel = ActionMessage.messageLevel; + ActionMessage.messageLevel = actionMessageLevel; + } + + /** + Set FPDFileName parameter for this action class. + + @param fpdFilePath fpd file path + **/ + public void setFPDFilePath(String fpdFilePath) { + this.fpdFilePath = fpdFilePath; + } + + /** + Common function interface for outer. + + @param workspacePath The path of workspace of current build or analysis. + @param fpdFilePath The fpd file path of current build or analysis. + @param messageLevel The message level for this Action. + + @throws Exception The exception of this function. Because it can *not* be predict + where the action class will be used. So only Exception can be throw. + + **/ + public void perform(String workspacePath, String fpdFilePath, + int messageLevel) throws Exception { + setWorkspacePath(workspacePath); + setFPDFilePath(fpdFilePath); + setActionMessageLevel(messageLevel); + checkParameter(); + execute(); + ActionMessage.messageLevel = originalMessageLevel; + } + + /** + Core execution function for this action class. + + This function work flows will be: + 1) Get all token's platform information from FPD, and create token object into memory database. + 2) Get all token's module information from MSA, and create usage instance for every module's PCD entry. + 3) Get all token's inherited information from MSA's library, and create usage instance + for module who consume this library and create usage instance for library for building. + 4) Collect token's package information from SPD, update these information for token in memory + database. + + @throws EntityException Exception indicate failed to execute this action. + + **/ + private void execute() throws EntityException { + FrameworkPlatformDescriptionDocument fpdDoc = null; + Object[][] modulePCDArray = null; + Map docMap = null; + ModuleSADocument.ModuleSA[] moduleSAs = null; + UsageInstance usageInstance = null; + String packageName = null; + String packageFullPath = null; + int index = 0; + int libraryIndex = 0; + int pcdArrayIndex = 0; + List listLibraryInstance = null; + String componentTypeStr = null; + + // + // Collect all PCD information defined in FPD file. + // Evenry token defind in FPD will be created as an token into + // memory database. + // + fpdDoc = createTokenInDBFromFPD(); + + // + // Searching MSA and SPD document. + // The information of MSA will be used to create usage instance into database. + // The information of SPD will be used to update the token information in database. + // + + HashMap map = new HashMap(); + map.put("FrameworkPlatformDescription", fpdDoc); + SurfaceAreaQuery.setDoc(map); + + moduleSAs = SurfaceAreaQuery.getFpdModules(); + for(index = 0; index < moduleSAs.length; index ++) { + // + // Get module document and use SurfaceAreaQuery to get PCD information + // + docMap = GlobalData.getDoc(moduleSAs[index].getModuleName()); + SurfaceAreaQuery.setDoc(docMap); + modulePCDArray = SurfaceAreaQuery.getModulePCDTokenArray(); + componentTypeStr = SurfaceAreaQuery.getComponentType(); + packageName = + GlobalData.getPackageNameForModule(moduleSAs[index].getModuleName()); + packageFullPath = this.workspacePath + File.separator + + GlobalData.getPackagePath(packageName) + + packageName + ".spd"; + + if(modulePCDArray != null) { + // + // If current MSA contains information, then create usage + // instance for PCD information from MSA + // + for(pcdArrayIndex = 0; pcdArrayIndex < modulePCDArray.length; + pcdArrayIndex ++) { + usageInstance = + createUsageInstanceFromMSA(moduleSAs[index].getModuleName(), + modulePCDArray[pcdArrayIndex]); + + if(usageInstance == null) { + continue; + } + // + // Get remaining PCD information from the package which this module belongs to + // + updateTokenBySPD(usageInstance, packageFullPath); + } + } + + // + // Get inherit PCD information which inherit from library instance of this module. + // + listLibraryInstance = + SurfaceAreaQuery.getLibraryInstance(moduleSAs[index].getArch().toString(), + CommonDefinition.AlwaysConsumed); + if(listLibraryInstance != null) { + for(libraryIndex = 0; libraryIndex < listLibraryInstance.size(); + libraryIndex ++) { + inheritPCDFromLibraryInstance(listLibraryInstance.get(libraryIndex), + moduleSAs[index].getModuleName(), + packageName, + componentTypeStr); + } + } + } + } + + /** + This function will collect inherit PCD information from library for a module. + + This function will create two usage instance for inherited PCD token, one is + for module and another is for library. + For module, if it inherited a PCD token from library, this PCD token's value + should be instanced in module level, and belongs to module. + For library, it also need a usage instance for build. + + @param libraryName The name of library instance. + @param moduleName The name of module. + @param packageName The name of package while module belongs to. + @param parentcomponentType The component type of module. + + @throws EntityException If the token does *not* exist in memory database. + + **/ + private void inheritPCDFromLibraryInstance(String libraryName, + String moduleName, + String packageName, + String parentcomponentType) + throws EntityException { + Map docMap = null; + String primaryKeyString = null; + Object[][] libPcdDataArray = null; + UUID nullUUID = new UUID(0,0); + UUID platformUUID = nullUUID; + UUID tokenSpaceGuid = null; + int tokenIndex = 0; + Token token = null; + Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; + UsageInstance usageInstance = null; + String packageFullPath = null; + + // + // Query PCD information from library's document. + // + docMap = GlobalData.getDoc(libraryName); + SurfaceAreaQuery.setDoc(docMap); + libPcdDataArray = SurfaceAreaQuery.getModulePCDTokenArray(); + + if(libPcdDataArray == null) { + return; + } + + for(tokenIndex = 0; tokenIndex < libPcdDataArray.length; tokenIndex ++) { + tokenSpaceGuid =((UUID)libPcdDataArray[tokenIndex][2] == null) ? + nullUUID :(UUID)libPcdDataArray[tokenIndex][2]; + + // + // Get token from memory database. The token must be created from FPD already. + // + primaryKeyString = Token.getPrimaryKeyString((String)libPcdDataArray[tokenIndex][0], + tokenSpaceGuid, + platformUUID + ); + + if(dbManager.isTokenInDatabase(primaryKeyString)) { + token = dbManager.getTokenByKey(primaryKeyString); + } else { + throw new EntityException("The PCD token " + primaryKeyString + + " defined in module " + moduleName + + " does not exist in FPD file!"); + } + + // + // Create usage instance for module. + // + pcdType = Token.getpcdTypeFromString((String)libPcdDataArray[tokenIndex][1]); + usageInstance = new UsageInstance(token, + Token.PCD_USAGE.ALWAYS_CONSUMED, + pcdType, + CommonDefinition.getComponentType(parentcomponentType), + libPcdDataArray[tokenIndex][3], + null, + (String) libPcdDataArray[tokenIndex][5], + "", + moduleName, + packageName, + true); + if(Token.PCD_USAGE.UNKNOWN == token.isUsageInstanceExist(moduleName)) { + token.addUsageInstance(usageInstance); + + packageFullPath = this.workspacePath + File.separator + + GlobalData.getPackagePath(packageName) + + packageName + ".spd"; + updateTokenBySPD(usageInstance, packageFullPath); + } + + // + // We need create second usage instance for inherited case, which + // add library as an usage instance, because when build a module, and + // if module inherited from base library, then build process will build + // library at first. + // + if(Token.PCD_USAGE.UNKNOWN == token.isUsageInstanceExist(libraryName)) { + packageName = GlobalData.getPackageNameForModule(libraryName); + usageInstance = new UsageInstance(token, + Token.PCD_USAGE.ALWAYS_CONSUMED, + pcdType, + CommonDefinition.ComponentTypeLibrary, + libPcdDataArray[tokenIndex][3], + null, + (String)libPcdDataArray[tokenIndex][5], + "", + libraryName, + packageName, + false); + token.addUsageInstance(usageInstance); + } + } + } + + /** + Create usage instance for PCD token defined in MSA document + + A PCD token maybe used by many modules, and every module is one of usage + instance of this token. For ALWAY_CONSUMED, SOMETIMES_CONSUMED, it is + consumer type usage instance of this token, and for ALWAYS_PRODUCED, + SOMETIMES_PRODUCED, it is produce type usage instance. + + @param moduleName The name of module + @param tokenInfoInMsa The PCD token information array retrieved from MSA. + + @return UsageInstance The usage instance created in memroy database. + + @throws EntityException If token did not exist in database yet. + + **/ + private UsageInstance createUsageInstanceFromMSA(String moduleName, + Object[] tokenInfoInMsa) + throws EntityException { + String packageName = null; + UsageInstance usageInstance = null; + UUID tokenSpaceGuid = null; + UUID nullUUID = new UUID(0,0); + String primaryKeyString = null; + UUID platformTokenSpace = nullUUID; + Token token = null; + Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; + Token.PCD_USAGE pcdUsage = Token.PCD_USAGE.UNKNOWN; + + tokenSpaceGuid =((UUID)tokenInfoInMsa[2] == null) ? nullUUID :(UUID)tokenInfoInMsa[2]; + + primaryKeyString = Token.getPrimaryKeyString((String)tokenInfoInMsa[0], + tokenSpaceGuid, + platformTokenSpace); + + // + // Get token object from memory database firstly. + // + if(dbManager.isTokenInDatabase(primaryKeyString)) { + token = dbManager.getTokenByKey(primaryKeyString); + } else { + throw new EntityException("The PCD token " + primaryKeyString + " defined in module " + + moduleName + " does not exist in FPD file!" ); + } + pcdType = Token.getpcdTypeFromString((String)tokenInfoInMsa[1]); + pcdUsage = Token.getUsageFromString((String)tokenInfoInMsa[4]); + + packageName = GlobalData.getPackageNameForModule(moduleName); + + if(Token.PCD_USAGE.UNKNOWN != token.isUsageInstanceExist(moduleName)) { + // + // BUGBUG: It should *not* throw exception here. Becaues in MdePkg.fpd, + // more than on BaseLib exist. But why? need confirmation. + // + //throw new EntityException( + // "In module " + moduleName + " exist more than one PCD token " + token.cName + // ); + ActionMessage.warning(this, + "In module " + moduleName + " exist more than one PCD token " + token.cName + ); + return null; + } + + // + // BUGBUG: following code could be enabled at current schema. Because + // current schema does not provide usage information. + // + // For FEATRURE_FLAG, FIXED_AT_BUILD, PATCH_IN_MODULE type PCD token, his + // usage is always ALWAYS_CONSUMED + // + //if((pcdType != Token.PCD_TYPE.DYNAMIC) && + // (pcdType != Token.PCD_TYPE.DYNAMIC_EX)) { + pcdUsage = Token.PCD_USAGE.ALWAYS_CONSUMED; + //} + + usageInstance = new UsageInstance(token, + pcdUsage, + pcdType, + CommonDefinition.getComponentType(SurfaceAreaQuery.getComponentType()), + tokenInfoInMsa[3], + null, + (String) tokenInfoInMsa[5], + "", + moduleName, + packageName, + false); + + // + // Use default value defined in MSA to update datum of token, + // if datum of token does not defined in FPD file. + // + if((token.datum == null) &&(tokenInfoInMsa[3] != null)) { + token.datum = tokenInfoInMsa[3]; + } + + token.addUsageInstance(usageInstance); + + return usageInstance; + } + + /** + Create token instance object into memory database, the token information + comes for FPD file. Normally, FPD file will contain all token platform + informations. + + This fucntion should be executed at firsly before others collection work + such as searching token information from MSA, SPD. + + @return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage. + + @throws EntityException Failed to parse FPD xml file. + + **/ + private FrameworkPlatformDescriptionDocument createTokenInDBFromFPD() + throws EntityException { + XmlObject doc = null; + FrameworkPlatformDescriptionDocument fpdDoc = null; + int index = 0; + List pcdBuildDataArray = new ArrayList(); + PcdBuildData pcdBuildData = null; + Token token = null; + UUID nullUUID = new UUID(0,0); + UUID platformTokenSpace= nullUUID; + List skuDataArray = new ArrayList(); + SkuInstance skuInstance = null; + int skuIndex = 0; + + // + // Get all tokens from FPD file and create token into database. + // + + try { + doc = XmlObject.Factory.parse(new File(fpdFilePath)); + } catch(IOException ioE) { + throw new EntityException("Can't find the FPD xml fle:" + fpdFilePath); + } catch(XmlException xmlE) { + throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath); + } + + // + // Get memoryDatabaseManager instance from GlobalData. + // + if((dbManager = GlobalData.getPCDMemoryDBManager()) == null) { + throw new EntityException("The instance of PCD memory database manager is null"); + } + + dbManager = new MemoryDatabaseManager(); + + if(!(doc instanceof FrameworkPlatformDescriptionDocument)) { + throw new EntityException("File " + fpdFilePath + + " is not a FrameworkPlatformDescriptionDocument"); + } + + fpdDoc =(FrameworkPlatformDescriptionDocument)doc; + + // + // Add all tokens in FPD into Memory Database. + // + pcdBuildDataArray = + fpdDoc.getFrameworkPlatformDescription().getPcdBuildDeclarations().getPcdBuildDataList(); + for(index = 0; + index < fpdDoc.getFrameworkPlatformDescription().getPcdBuildDeclarations().sizeOfPcdBuildDataArray(); + index ++) { + pcdBuildData = pcdBuildDataArray.get(index); + token = new Token(pcdBuildData.getCName(), new UUID(0, 0), new UUID(0, 0)); + // + // BUGBUG: in FPD, should be defined as + // + token.datum = pcdBuildData.getDefaultValue(); + token.hiiEnabled = pcdBuildData.getHiiEnable(); + token.variableGuid = Token.getGUIDFromSchemaObject(pcdBuildData.getVariableGuid()); + token.variableName = pcdBuildData.getVariableName(); + token.variableOffset = Integer.decode(pcdBuildData.getDataOffset()); + token.skuEnabled = pcdBuildData.getSkuEnable(); + token.maxSkuCount = Integer.decode(pcdBuildData.getMaxSku()); + token.skuId = Integer.decode(pcdBuildData.getSkuId()); + token.skuDataArrayEnabled = pcdBuildData.getSkuDataArrayEnable(); + token.assignedtokenNumber = Integer.decode(pcdBuildData.getToken().getStringValue()); + skuDataArray = pcdBuildData.getSkuDataArray1(); + + if(skuDataArray != null) { + for(skuIndex = 0; skuIndex < skuDataArray.size(); skuIndex ++) { + // + // BUGBUG: Now in current schema, The value is defined as String type, + // it is not correct, the type should be same as the datumType + // + skuInstance = new SkuInstance(((PcdBuildData.SkuData)skuDataArray.get(skuIndex)).getId(), + ((PcdBuildData.SkuData)skuDataArray.get(skuIndex)).getValue()); + token.skuData.add(skuInstance); + } + } + + if(dbManager.isTokenInDatabase(Token.getPrimaryKeyString(token.cName, + token.tokenSpaceName, + platformTokenSpace))) { + // + // If found duplicate token, Should tool be hold? + // + ActionMessage.warning(this, + "Token " + token.cName + " exists in token database"); + continue; + } + token.pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString()); + dbManager.addTokenToDatabase(Token.getPrimaryKeyString(token.cName, + token.tokenSpaceName, + platformTokenSpace), + token); + } + + return fpdDoc; + } + + /** + Update PCD token in memory database by help information in SPD. + + After create token from FPD and create usage instance from MSA, we should collect + PCD package level information from SPD and update token information in memory + database. + + @param usageInstance The usage instance defined in MSA and want to search in SPD. + @param packageFullPath The SPD file path. + + @throws EntityException Failed to parse SPD xml file. + + **/ + private void updateTokenBySPD(UsageInstance usageInstance, + String packageFullPath) + throws EntityException { + PackageSurfaceAreaDocument pkgDoc = null; + List pcdEntryArray = new ArrayList(); + int index; + boolean isFoundInSpd = false; + Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN; + + try { + pkgDoc =(PackageSurfaceAreaDocument)XmlObject.Factory.parse(new File(packageFullPath)); + } catch(IOException ioE) { + throw new EntityException("Can't find the FPD xml fle:" + packageFullPath); + } catch(XmlException xmlE) { + throw new EntityException("Can't parse the FPD xml fle:" + packageFullPath); + } + + pcdEntryArray = pkgDoc.getPackageSurfaceArea().getPcdDefinitions().getPcdEntryList(); + for(index = 0; index < pcdEntryArray.size(); index ++) { + if(pcdEntryArray.get(index).getCName().equalsIgnoreCase( + usageInstance.parentToken.cName)) { + isFoundInSpd = true; + // + // From SPD file , we can get following information. + // Token: Token number defined in package level. + // PcdItemType: This item does not single one. It means all supported item type. + // datumType: UINT8, UNIT16, UNIT32, UINT64, VOID*, BOOLEAN + // datumSize: The size of default value or maxmine size. + // defaultValue: This value is defined in package level. + // HelpText: The help text is provided in package level. + // + + usageInstance.parentToken.tokenNumber = Integer.decode(pcdEntryArray.get(index).getToken()); + + if(pcdEntryArray.get(index).getDatumType() != null) { + datumType = Token.getdatumTypeFromString( + pcdEntryArray.get(index).getDatumType().toString()); + if(usageInstance.parentToken.datumType == Token.DATUM_TYPE.UNKNOWN) { + usageInstance.parentToken.datumType = datumType; + } else { + if(datumType != usageInstance.parentToken.datumType) { + throw new EntityException("Different datum types are defined for Token :" + + usageInstance.parentToken.cName); + } + } + + } else { + throw new EntityException("The datum type for token " + usageInstance.parentToken.cName + + " is not defind in SPD file " + packageFullPath); + } + + usageInstance.defaultValueInSPD = pcdEntryArray.get(index).getDefaultValue(); + usageInstance.helpTextInSPD = "Help Text in SPD"; + + // + // If token's datum is not valid, it indicate that datum is not provided + // in FPD and defaultValue is not provided in MSA, then use defaultValue + // in SPD as the datum of token. + // + if(usageInstance.parentToken.datum == null) { + if(pcdEntryArray.get(index).getDefaultValue() != null) { + usageInstance.parentToken.datum = pcdEntryArray.get(index).getDefaultValue(); + } else { + throw new EntityException("FPD does not provide datum for token " + usageInstance.parentToken.cName + + ", MSA and SPD also does not provide for this token!"); + } + } + } + } + + if(!isFoundInSpd ) { + ActionMessage.warning(this, + "Can *not* find the PCD token " + usageInstance.parentToken.cName + + " in SPD file!"); + } + } + + /** + check parameter for this action. + + @throws EntityException Bad parameter. + **/ + private void checkParameter() throws EntityException { + File file = null; + + if((fpdFilePath == null) ||(workspacePath == null)) { + throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); + } + + if(fpdFilePath.length() == 0 || workspacePath.length() == 0) { + throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); + } + + file = new File(workspacePath); + if(!file.exists()) { + throw new EntityException("WorkpacePath " + workspacePath + " does not exist!"); + } + + file = new File(fpdFilePath); + + if(!file.exists()) { + throw new EntityException("FPD File " + fpdFilePath + " does not exist!"); + } + } + + /** + Test case function + + @param argv parameter from command line + **/ + public static void main(String argv[]) throws EntityException { + CollectPCDAction ca = new CollectPCDAction(); + ca.setWorkspacePath("G:/mdk"); + ca.setFPDFilePath("G:/mdk/EdkNt32Pkg/build/Nt32.fpd"); + ca.setActionMessageLevel(ActionMessage.MAX_MESSAGE_LEVEL); + GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db", + "G:/mdk"); + ca.execute(); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PCDAutoGenAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PCDAutoGenAction.java new file mode 100644 index 0000000000..ca65c7546c --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PCDAutoGenAction.java @@ -0,0 +1,452 @@ +/** @file + PCDAutoGenAction class. + + This class is to manage how to generate the PCD information into Autogen.c and + Autogen.h. + +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.File; +import java.util.List; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.pcd.entity.MemoryDatabaseManager; +import org.tianocore.build.pcd.entity.Token; +import org.tianocore.build.pcd.entity.UsageInstance; +import org.tianocore.build.pcd.exception.BuildActionException; +import org.tianocore.build.pcd.exception.EntityException; + +/** This class is to manage how to generate the PCD information into Autogen.c and + Autogen.h. +**/ +public class PCDAutoGenAction extends BuildAction { + /// + /// The reference of DBManager in GlobalData class. + /// + private MemoryDatabaseManager dbManager; + /// + /// The name of module which is analysised currently. + /// + private String moduleName; + /// + /// Wheter current module is PCD emulated driver. It is only for + /// emulated PCD driver and will be kept until PCD IMAGE tool ready. + /// + private boolean isEmulatedPCDDriver; + /// + /// The generated string for header file. + /// + private String hAutoGenString; + /// + /// The generated string for C code file. + /// + private String cAutoGenString; + + /** + Set parameter ModuleName + + @param moduleName the module name parameter. + **/ + public void setModuleName(String moduleName) { + this.moduleName = moduleName; + } + + /** + Set parameter isEmulatedPCDDriver + + @param isEmulatedPCDDriver whether this module is PeiEmulatedPCD driver + **/ + public void setIsEmulatedPCDDriver(boolean isEmulatedPCDDriver) { + this.isEmulatedPCDDriver = isEmulatedPCDDriver; + } + + /** + Get the output of generated string for header file. + + @return the string of header file for PCD + **/ + public String OutputH() { + return hAutoGenString; + } + + /** + Get the output of generated string for C Code file. + + @return the string of C code file for PCD + **/ + public String OutputC() { + return cAutoGenString; + } + + /** + Construct function + + This function mainly initialize some member variable. + + @param moduleName Parameter of this action class. + @param isEmulatedPCDDriver Parameter of this action class. + **/ + public PCDAutoGenAction(String moduleName, boolean isEmulatedPCDDriver) { + dbManager = null; + setIsEmulatedPCDDriver(isEmulatedPCDDriver); + setModuleName(moduleName); + } + + /** + check the parameter for action class. + + @throws BuildActionException Bad parameter. + **/ + void checkParameter() throws BuildActionException { + if(!isEmulatedPCDDriver &&(moduleName == null)) { + throw new BuildActionException("Wrong module name parameter for PCDAutoGenAction tool!"); + } + + if(!isEmulatedPCDDriver && moduleName.length() == 0) { + throw new BuildActionException("Wrong module name parameter for PCDAutoGenAction tool!"); + } + + // + // Check the PCD memory database manager is valid. + // + if(GlobalData.getPCDMemoryDBManager() == null) { + throw new BuildActionException("Memory database has not been initlizated!"); + } + + dbManager = GlobalData.getPCDMemoryDBManager(); + + if(dbManager.getDBSize() == 0) { + throw new BuildActionException("Memory database does not contain any record!"); + } + + ActionMessage.debug(this, + "PCD memory database contains " + dbManager.getDBSize() + " PCD tokens"); + } + + /** + Core execution function for this action class. + + All PCD information of this module comes from memory dabase. The collection + work should be done before this action execution. + Currently, we should generated all PCD information(maybe all dynamic) as array + in Pei emulated driver for simulating PCD runtime database. + + @throws BuildActionException Failed to execute this aciton class. + **/ + void performAction() throws BuildActionException { + ActionMessage.debug(this, + "Starting PCDAutoGenAction to generate autogen.h and autogen.c!..."); + + hAutoGenString = ""; + cAutoGenString = ""; + + if(isEmulatedPCDDriver) { + generateAutogenForPCDEmulatedDriver(); + } else { + generateAutogenForModule(); + } + } + + /** + Generate the autogen string for a common module. + + All PCD information of this module comes from memory dabase. The collection + work should be done before this action execution. + **/ + private void generateAutogenForModule() + { + int index; + List usageInstanceArray; + + usageInstanceArray = dbManager.getUsageInstanceArrayByModuleName(moduleName); + + if(usageInstanceArray.size() != 0) { + // + // Add "#include 'PcdLib.h'" for Header file + // + hAutoGenString = "#include \r\n"; + } + + for(index = 0; index < usageInstanceArray.size(); index ++) { + ActionMessage.debug(this, + "Module " + moduleName + "'s PCD [" + Integer.toHexString(index) + + "]: " + usageInstanceArray.get(index).parentToken.cName); + try { + usageInstanceArray.get(index).generateAutoGen(); + hAutoGenString += usageInstanceArray.get(index).getHAutogenStr() + "\r\n"; + cAutoGenString += usageInstanceArray.get(index).getCAutogenStr() + "\r\n"; + } catch(EntityException exp) { + throw new BuildActionException(exp.getMessage()); + } + } + + ActionMessage.debug(this, + "Module " + moduleName + "'s PCD header file:\r\n" + hAutoGenString + "\r\n" + ); + ActionMessage.debug(this, + "Module " + moduleName + "'s PCD C file:\r\n" + cAutoGenString + "\r\n" + ); + } + + /** + Generate all PCD autogen string and the emulated PCD IMAGE array for emulated driver. + + Currently, we should generated all PCD information(maybe all dynamic) as array + in Pei emulated driver for simulating PCD runtime database. + + **/ + private void generateAutogenForPCDEmulatedDriver() { + int index; + Token[] tokenArray; + UsageInstance usageInstance; + + // + // Add "#include 'PcdLib.h'" for Header file + // + hAutoGenString = "#include \r\n"; + + tokenArray = dbManager.getRecordArray(); + for(index = 0; index < tokenArray.length; index ++) { + // + // Get one consumer instance and generate autogen for this token. + // + if(tokenArray[index].consumers != null ) { + if(tokenArray[index].consumers.size() == 0) { + continue; + } + + usageInstance = tokenArray[index].consumers.get(0); + try { + usageInstance.generateAutoGen(); + } catch(EntityException exp) { + throw new BuildActionException(exp.getMessage()); + } + + hAutoGenString += usageInstance.getHAutogenStr(); + cAutoGenString += usageInstance.getCAutogenStr(); + + hAutoGenString += "\r\n"; + cAutoGenString += "\r\n"; + } + } + + generatePCDEmulatedArray(tokenArray); + + ActionMessage.debug(this, + "PCD emulated driver's header: \r\n" + hAutoGenString + "\r\n" + ); + ActionMessage.debug(this, + "PCD emulated driver's C code: \r\n" + cAutoGenString + "\r\n" + ); + + } + + /** + Generate PCDEmulated array in PCDEmulated driver for emulated runtime database. + + @param tokenArray All PCD token in memory database. + + @throws BuildActionException Unknown PCD_TYPE + **/ + private void generatePCDEmulatedArray(Token[] tokenArray) + throws BuildActionException { + int index; + Token token; + String[] guidStrArray; + String value; + + // + // The value of String type of PCD entry maybe use byte array but not string direcly + // such as {0x1, 0x2, 0x3}, and define PCD1_STRING_Value as L"string define here" + // For this case, we should generate a string array to C output and use the address + // of generated string array. + // + for(index = 0; index < tokenArray.length; index ++) { + token = tokenArray[index]; + + if((token.producers.size() == 0) &&(token.consumers.size() == 0)) { + // + // If no one use this PCD token, it will not generated in emulated array. + // + continue; + } + value = token.datum.toString(); + if(token.datumType == Token.DATUM_TYPE.POINTER) { + if(!((value.charAt(0) == 'L' && value.charAt(1) == '"') ||(value.charAt(0) == '"'))) { + cAutoGenString += String.format("UINT8 _mPcdArray%08x[] = %s;\r\n", + index, + value + ); + } + } + } + + // + // Output emulated PCD entry array + // + cAutoGenString += "\r\nEMULATED_PCD_ENTRY gEmulatedPcdEntry[] = {\r\n"; + + for(index = 0; index < tokenArray.length; index ++) { + token = tokenArray[index]; + + if((token.producers.size() == 0) &&(token.consumers.size() == 0)) { + // + // If no one use this PCD token, it will not generated in emulated array. + // + continue; + } + + if(index != 0) { + cAutoGenString += ",\r\n"; + } + + // + // Print Start "{" for a Token item in array + // + cAutoGenString += " {\r\n"; + + // + // Print Token Name + // + cAutoGenString += String.format(" _PCD_TOKEN_%s,\r\n", token.cName); + + // + // Print Hii information + // + if(token.hiiEnabled) { + cAutoGenString += String.format(" TRUE,\r\n"); + } else { + cAutoGenString += String.format(" FALSE,\r\n"); + } + + // + // Print sku information + // + if(token.skuEnabled) { + cAutoGenString += String.format(" TRUE,\r\n"); + } else { + cAutoGenString += String.format(" FALSE,\r\n"); + } + + // + // Print maxSkuCount + // + cAutoGenString += String.format(" %d,\r\n", token.maxSkuCount); + + cAutoGenString += String.format(" %d,\r\n", token.skuId); + + if(token.variableGuid == null) { + cAutoGenString += " { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\r\n"; + } else { + guidStrArray =(token.variableGuid.toString()).split("-"); + + cAutoGenString += 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\n", + 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)) + ); + + } + + value = token.datum.toString(); + if(token.datumType == Token.DATUM_TYPE.POINTER) { + if((value.charAt(0) == 'L' && value.charAt(1) == '"') || value.charAt(0) == '"') { + cAutoGenString += String.format(" sizeof(_PCD_VALUE_%s),\r\n", token.cName); + cAutoGenString += String.format(" 0, %s, %s,\r\n", token.variableName, value); + } else { + cAutoGenString += String.format(" sizeof(_mPcdArray%08x),\r\n", index); + cAutoGenString += String.format(" 0, &_mPcdArray%08x, %s,\r\n", index, token.variableName); + } + } else { + switch(token.datumType) { + case UINT8: + cAutoGenString += " 1,\r\n"; + break; + case UINT16: + cAutoGenString += " 2,\r\n"; + break; + case UINT32: + cAutoGenString += " 4,\r\n"; + break; + case UINT64: + cAutoGenString += " 8,\r\n"; + break; + case BOOLEAN: + cAutoGenString += " 1,\r\n"; + break; + default: + throw new BuildActionException("Unknown datum size"); + } + cAutoGenString += String.format(" %s, %s, NULL,\r\n", value, token.variableName); + } + + // + // Print end "}" for a token item in array + // + cAutoGenString += " }"; + } + + cAutoGenString += "\r\n};\r\n"; + cAutoGenString += "\r\n"; + cAutoGenString += "UINTN\r\n"; + cAutoGenString += "GetPcdDataBaseSize(\r\n"; + cAutoGenString += " VOID\r\n"; + cAutoGenString += " )\r\n"; + cAutoGenString += "{\r\n"; + cAutoGenString += " return sizeof(gEmulatedPcdEntry);\r\n"; + cAutoGenString += "}\r\n"; + } + + /** + Test case function + + @param argv paramter from command line + **/ + public static void main(String argv[]) { + String logFilePath = "G:/mdk/EdkNt32Pkg/build/Nt32.fpd"; + + // + // At first, CollectPCDAction should be invoked to collect + // all PCD information from SPD, MSA, FPD. + // + CollectPCDAction collectionAction = new CollectPCDAction(); + GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db", + "G:/mdk"); + + GlobalData.getPCDMemoryDBManager().setLogFileName(logFilePath + ".PCDMemroyDatabaseLog.txt"); + + try { + collectionAction.perform("G:/mdk", + logFilePath, + ActionMessage.MAX_MESSAGE_LEVEL); + } catch(Exception e) { + e.printStackTrace(); + } + + // + // Then execute the PCDAuotoGenAction to get generated Autogen.h and Autogen.c + // + PCDAutoGenAction autogenAction = new PCDAutoGenAction("HelloWorld", + true + ); + autogenAction.execute(); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ShowPCDDatabaseAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ShowPCDDatabaseAction.java new file mode 100644 index 0000000000..cd67dd46c9 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ShowPCDDatabaseAction.java @@ -0,0 +1,130 @@ +/** @file + ShowPCDDatabase class. + + This class is the action to diplay the PCD database. + +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.File; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.pcd.exception.UIException; +import org.tianocore.build.pcd.ui.PCDDatabaseFrame; + +/** This class is the action to show PCD database. +**/ +public class ShowPCDDatabaseAction extends UIAction { + /// + /// The workspace path parameter. + /// + private String workspacePath; + /// + /// The FpdfileName parameter. + /// + private String fpdFilePath; + + /** + set workspace path parameter for this action. + + @param workspacePath the string of workspace path. + **/ + public void setWorkspacePath(String workspacePath) { + this.workspacePath = workspacePath; + } + + /** + set fpd file path parameter for this action. + + @param fpdFilePath file path string + **/ + public void setFPDFilePath(String fpdFilePath) { + this.fpdFilePath = "./" + fpdFilePath; + } + + /** + check paramter for this action. + + @throw UIException wrong paramter. + **/ + void checkParamter() throws UIException { + File file = null; + + if((fpdFilePath == null) ||(workspacePath == null)) { + throw new UIException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); + } + + if(fpdFilePath.length() == 0 || workspacePath.length() == 0) { + throw new UIException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); + } + + file = new File(workspacePath); + if(!file.exists()) { + throw new UIException("WorkpacePath " + workspacePath + " does not exist!"); + } + + file = new File(fpdFilePath); + + if(!file.exists()) { + throw new UIException("FPD File " + fpdFilePath + " does not exist!"); + } + } + + /** + Core workflow function. + + @throw UIException Fail to show PCD database. + **/ + void performAction() throws UIException { + CollectPCDAction collectAction = null; + PCDDatabaseFrame dbFrame = null; + + // + // Initialize global data. + // + GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db", + workspacePath); + GlobalData.getPCDMemoryDBManager().setLogFileName(fpdFilePath + ".PCDMemroyDatabaseLog.txt"); + + // + // Collect PCD information. + // + collectAction = new CollectPCDAction(); + + try { + collectAction.perform(workspacePath, + fpdFilePath, + ActionMessage.LOG_MESSAGE_LEVEL); + } catch(Exception exp) { + throw new UIException(exp.getMessage()); + } + + // + // Start tree windows. + // + dbFrame = new PCDDatabaseFrame(GlobalData.getPCDMemoryDBManager()); + } + + /** + Entry function. + + The action is run from command line. + + @param argv command line parameter. + **/ + public static void main(String[] argv) throws UIException { + ShowPCDDatabaseAction showAction = new ShowPCDDatabaseAction(); + showAction.setWorkspacePath(argv[0]); + showAction.setFPDFilePath(argv[1]); + showAction.execute(); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/UIAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/UIAction.java new file mode 100644 index 0000000000..2cde9b24ec --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/UIAction.java @@ -0,0 +1,83 @@ +/** @file + UIAction class. + + This class is the parent action class of UI wizard. + +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 org.tianocore.build.pcd.exception.UIException; + +/** This class is the parent class for all UI wizard action. +**/ +public abstract class UIAction { + /// + /// original message level. when finish this action, original + /// message level will be restored. + /// + private int originalMessageLevel; + + /** + Check the parameter for this aciton. + + This function will be overrided by child class. + **/ + abstract void checkParamter() throws UIException; + + /** + Perform action. + + This function will be overrided by child class. + **/ + abstract void performAction() throws UIException; + + /** + set the message level for this action. + + @param messageLevel message level wanted. + **/ + public void setMessageLevel(int messageLevel) { + originalMessageLevel = ActionMessage.messageLevel; + ActionMessage.messageLevel = messageLevel; + } + + /** + log message for UI wizard aciton. + + @param actionObj aciton instance object. + @param logStr log message string + **/ + public static void logMsg(Object actionObj, String logStr) { + System.out.println(logStr); + } + + /** + Warning message for UI wizard action. + + @param warningObj action instance object. + @param warningStr warning message string. + **/ + public static void warningMsg(Object warningObj, String warningStr) { + System.out.println(warningStr); + } + + /** + Entry function for all UI wizard actions. + **/ + public void execute() throws UIException { + checkParamter(); + performAction(); + + ActionMessage.messageLevel = originalMessageLevel; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/MemoryDatabaseManager.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/MemoryDatabaseManager.java new file mode 100644 index 0000000000..6f4f8949ef --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/MemoryDatabaseManager.java @@ -0,0 +1,306 @@ +/** @file + MemoryDatabaseManager class. + + Database hold all PCD information comes from SPD, MSA, FPD file in memory. + +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.entity; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.pcd.action.ActionMessage; + +/** Database hold all PCD information comes from SPD, MSA, FPD file in memory. +**/ +public class MemoryDatabaseManager { + /// + /// Memory database. The string "cName + SpaceNameGuid" is primary key. + /// memory database is in global scope, and it will be used for others PCD tools. + /// + private static Map memoryDatabase = null; + /// + /// The log file name for dumping memory database. + /// + private static String logFileName = null; + + /** + Constructure function + **/ + public MemoryDatabaseManager() { + // + // Allocate memory for new database in global scope. + // + if (memoryDatabase == null) { + memoryDatabase = new HashMap(); + } + } + + /** + Get the log file name. + **/ + public String getLogFileName() { + return logFileName; + } + + /** + Set parameter log file name. + + @param fileName log file name parameter. + **/ + public void setLogFileName(String fileName) { + logFileName = fileName; + } + + /** + Judege whether token exists in memory database + + @param primaryKey the primaryKey for searching token + + @retval TRUE - token already exist in database. + @retval FALSE - token does not exist in database. + **/ + public boolean isTokenInDatabase(String primaryKey) { + return (memoryDatabase.get(primaryKey) != null); + } + + /** + Add a pcd token into memory database. + + @param primaryKey the primary key for searching token + @param token token instance + **/ + public void addTokenToDatabase(String primaryKey, Token token) { + memoryDatabase.put(primaryKey, token); + } + + /** + Get a token instance from memory database with primary key. + + @param primaryKey the primary key for searching token + + @return token instance. + **/ + public Token getTokenByKey(String primaryKey) { + return memoryDatabase.get(primaryKey); + } + + /** + Get the number of PCD token record in memory database. + + @return the number of PCD token record in memory database. + **/ + public int getDBSize() { + return memoryDatabase.size(); + } + + /** + Get the token record array contained all PCD token in memory database. + + @return the token record array contained all PCD token in memory database. + **/ + public Token[] getRecordArray() { + Token[] tokenArray = null; + Object[] dataArray = null; + Map.Entry entry = null; + int index = 0; + + if (memoryDatabase == null) { + return null; + } + + dataArray = memoryDatabase.entrySet().toArray(); + tokenArray = new Token[memoryDatabase.size()]; + for (index = 0; index < memoryDatabase.size(); index ++) { + entry =(Map.Entry) dataArray [index]; + tokenArray[index] =(Token) entry.getValue(); + } + + return tokenArray; + } + + /** + Get all PCD record for a module according to module's name. + + @param moduleName the name of module. + + @return all usage instance for this module in memory database. + **/ + public List getUsageInstanceArrayByModuleName(String moduleName) { + Token[] tokenArray = null; + int recordIndex = 0; + int usageInstanceIndex = 0; + List usageInstanceArray = null; + UsageInstance usageInstance = null; + List returnArray = new ArrayList(); + + tokenArray = getRecordArray(); + + // + // Loop to find all PCD record related to current module + // + for (recordIndex = 0; recordIndex < getDBSize(); recordIndex ++) { + if (tokenArray[recordIndex].producers != null) { + usageInstanceArray = tokenArray[recordIndex].producers; + for (usageInstanceIndex = 0; usageInstanceIndex < usageInstanceArray.size(); usageInstanceIndex ++) { + usageInstance =(UsageInstance) usageInstanceArray.get(usageInstanceIndex); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + returnArray.add(usageInstance); + } + } + } + + if (tokenArray[recordIndex].consumers != null) { + usageInstanceArray = tokenArray[recordIndex].consumers; + for (usageInstanceIndex = 0; usageInstanceIndex < usageInstanceArray.size(); usageInstanceIndex ++) { + usageInstance =(UsageInstance) usageInstanceArray.get(usageInstanceIndex); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + returnArray.add(usageInstance); + } + } + } + } + + if (returnArray.size() == 0) { + ActionMessage.warning(this, "Can *not* find any usage instance for " + moduleName + " !"); + } + + return returnArray; + } + + /** + Get all modules name who contains PCD information + + @return Array for module name + **/ + public List getAllModuleArray() + { + int indexToken = 0; + int usageIndex = 0; + int moduleIndex = 0; + Token[] tokenArray = null; + List moduleNames = new ArrayList(); + UsageInstance usageInstance = null; + boolean bFound = false; + + tokenArray = this.getRecordArray(); + // + // Find all producer usage instance for retrieving module's name + // + for (indexToken = 0; indexToken < getDBSize(); indexToken ++) { + for (usageIndex = 0; usageIndex < tokenArray[indexToken].producers.size(); usageIndex ++) { + usageInstance = tokenArray[indexToken].producers.get(usageIndex); + bFound = false; + for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) { + if (moduleNames.get(moduleIndex).equalsIgnoreCase(usageInstance.moduleName)) { + bFound = true; + break; + } + } + if (!bFound) { + moduleNames.add(usageInstance.moduleName); + } + } + } + + // + // Find all consumer usage instance for retrieving module's name + // + for (indexToken = 0; indexToken < getDBSize(); indexToken ++) { + for (usageIndex = 0; usageIndex < tokenArray[indexToken].consumers.size(); usageIndex ++) { + usageInstance = tokenArray[indexToken].consumers.get(usageIndex); + bFound = false; + for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) { + if (moduleNames.get(moduleIndex).equalsIgnoreCase(usageInstance.moduleName)) { + bFound = true; + break; + } + } + if (!bFound) { + moduleNames.add(usageInstance.moduleName); + } + } + } + return moduleNames; + } + + /** + Dump all PCD record into file for reviewing. + **/ + public void DumpAllRecords() { + BufferedWriter bWriter = null; + Object[] tokenArray = null; + Map.Entry entry = null; + Token token = null; + int index = 0; + int usageIndex = 0; + UsageInstance usageInstance = null; + String inheritString = null; + String componentTypeName = null; + + try { + bWriter = new BufferedWriter(new FileWriter(new File(logFileName))); + tokenArray = memoryDatabase.entrySet().toArray(); + for (index = 0; index < memoryDatabase.size(); index ++) { + entry =(Map.Entry) tokenArray [index]; + token =(Token) entry.getValue(); + bWriter.write("****** token [" + Integer.toString(index) + "] ******\r\n"); + bWriter.write(" cName:" + token.cName + "\r\n"); + for (usageIndex = 0; usageIndex < token.producers.size(); usageIndex ++) { + usageInstance =(UsageInstance)token.producers.get(usageIndex); + componentTypeName = CommonDefinition.getComponentTypeString(usageInstance.componentType); + + if (usageInstance.isInherit) { + inheritString = "Inherit"; + } else { + inheritString = ""; + } + bWriter.write(String.format(" (Producer)#%d: %s:%s Package:%s %s\r\n", + usageIndex, + componentTypeName, + usageInstance.moduleName, + usageInstance.packageName, + inheritString + ) + ); + } + for (usageIndex = 0; usageIndex < token.consumers.size(); usageIndex ++) { + usageInstance =(UsageInstance)token.consumers.get(usageIndex); + componentTypeName = CommonDefinition.getComponentTypeString(usageInstance.componentType); + if (usageInstance.isInherit) { + inheritString = "Inherit"; + } else { + inheritString = ""; + } + bWriter.write(String.format(" (Consumer)#%d: %s:%s Package:%s %s\r\n", + usageIndex, + componentTypeName, + usageInstance.moduleName, + usageInstance.packageName, + inheritString + ) + ); + } + } + bWriter.close(); + } catch (IOException exp) { + ActionMessage.warning(this, "Failed to open database log file: " + logFileName); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/SkuInstance.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/SkuInstance.java new file mode 100644 index 0000000000..2886506411 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/SkuInstance.java @@ -0,0 +1,40 @@ +/** @file + SkuInstance class. + + Sku instance contains ID and value, A pcd token maybe contains more than one Sku instance. + +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.entity; + +/** Sku instance contains ID and value, A pcd token maybe contains more than one Sku instance. +**/ +public class SkuInstance { + /// + /// The id number of this SKU instance + /// + public int id; + /// + /// The value of this SKU instance + /// + public Object value; + + /** + Constructure function + + @param id sku id + @param value sku value for this id. + **/ + public SkuInstance(int id, Object value) { + this.id = id; + this.value = value; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/Token.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/Token.java new file mode 100644 index 0000000000..e4ecfc034c --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/Token.java @@ -0,0 +1,641 @@ +/** @file + Token class. + + This module contains all classes releted to PCD token. + +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.entity; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.tianocore.build.pcd.action.ActionMessage; + +/** This class is to descript a PCD token object. The information of a token mainly + comes from MSA, SPD and setting produced by platform developer. +**/ +public class Token { + /// + /// Enumeration macro defintion for PCD type. + /// BUGBUG: Not use upcase charater is to facility for reading. It may be changed + /// in coding review. + public enum PCD_TYPE {FEATURE_FLAG, FIXED_AT_BUILD, PATCHABLE_IN_MODULE, DYNAMIC, + DYNAMIC_EX, UNKNOWN} + + /// + /// Enumeration macro definition for datum type. All type mainly comes from ProcessBind.h. + /// Wizard maybe expand this type as "int, unsigned int, short, unsigned short etc" in + /// prompt dialog. + /// + public enum DATUM_TYPE {UINT8, UINT16, UINT32, UINT64, BOOLEAN, POINTER, UNKNOWN} + + /// + /// Enumeration macor defintion for usage of PCD + /// + public enum PCD_USAGE {ALWAYS_PRODUCED, ALWAYS_CONSUMED, SOMETIMES_PRODUCED, + SOMETIMES_CONSUMED, UNKNOWN} + + /// + /// cName is to identify a PCD entry and will be used for generating autogen.h/autogen.c. + /// cName will be defined in MSA, SPD and FPD, can be regarded as primary key with token space guid. + /// + public String cName; + + /// + /// Token space name is the guid defined by token itself in package or module level. This + /// name mainly for DynamicEx type. For other PCD type token, his token space name is the + /// assignedtokenSpaceName as follows. + /// tokenSpaceName is defined in MSA, SPD, FPD, can be regarded as primary key with cName. + /// + public UUID tokenSpaceName; + + /// + /// tokenNumber is allocated by platform. tokenNumber indicate an index for this token in + /// platform token space. + /// tokenNumber is defined in SPD, FPD. + /// + public int tokenNumber; + + /// + /// The token space name assigned by platform. For Non-DynamicEx driver this value is same. + /// assignedtokenSpaceName is defined in FPD. + /// + public UUID assignedtokenSpaceName; + + /// + /// The token number assigned by platform. The number indiect the offset of this token in platform + /// token space. + /// AssgiendtokenNumber is defined in FPD. + /// + public int assignedtokenNumber; + + /// + /// pcdType is the PCD item type defined by platform developer. + /// + public PCD_TYPE pcdType; + + /// + /// PCDtype is set by platform developer. It is final PCD type of this token. + /// SupportedPcdType is defined in SPD. + /// + public PCD_TYPE[] supportedpcdType; + + /// + /// datumSize is to descript the fix size or max size for this token. + /// datumSize is defined in SPD. + /// + public int datumSize; + + /// + /// datum type is to descript what type can be expressed by a PCD token. + /// datumType is defined in SPD. + /// + public DATUM_TYPE datumType; + + /// + /// Isplatform is to descript whether this token is defined in platform level. + /// If token is belong to platform level. The value can be different for every + /// module. All are determined by platform developer. + /// + public boolean isPlatform; + + /// + /// hiiEnabled is to indicate whether the token support Hii functionality. + /// hiiEnabled is defined in FPD. + /// + public boolean hiiEnabled; + + /// + /// variableName is valid only when this token support Hii functionality. variableName + /// indicates the value of token is associated with what variable. + /// variableName is defined in FPD. + /// + public String variableName; + + /// + /// variableGuid is the GUID this token associated with. + /// variableGuid is defined in FPD. + /// + public UUID variableGuid; + + /// + /// Variable offset indicate the associated variable's offset in NV storage. + /// variableOffset is defined in FPD. + /// + public int variableOffset; + + /// + /// skuEnabled is to indicate whether the token support Sku functionality. + /// skuEnabled is defined in FPD. + /// + public boolean skuEnabled; + + /// + /// skuDataArrayEnabled is to indicate wheter use the skuData array or default value. + /// + public boolean skuDataArrayEnabled; + + /// + /// skuData contains all value for SkuNumber of token. + /// skuData is defined in FPD. + /// + public List skuData; + + /// + /// maxSkuCount indicate the max count of sku data. + /// maxSkuCount is defined in FPD. + /// + public int maxSkuCount; + + /// + /// SkuId is the id of current selected SKU. + /// SkuId is defined in FPD. + /// + public int skuId; + + /// + /// datum is the value set by platform developer. + /// datum is defined in FPD. + /// + public Object datum; + + /// + /// Default value of this token. + /// This default value is defined in SPD level. + /// + public Object defaultValue; + + /// + /// BUGBUG: fix comment + /// vpdEnabled is defined in FPD. + /// + public boolean vpdEnabled; + + /// + /// BUGBUG: fix comment + /// vpdOffset is defined in FPD. + /// + public long vpdOffset; + + /// + /// producers array record all module private information who produce this PCD token. + /// + public List producers; + + /// + /// consumers array record all module private information who consume this PCD token. + /// + public List consumers; + + /** + Constructure function. + + Initialize the value of token. + + @param cName The cName of this token + @param tokenSpaceName The tokenSpaceName of this token, it is a GUID. + @param assignedtokenSpaceName The assignedtokenSpaceName of this token, it is a GUID. + + **/ + public Token(String cName, UUID tokenSpaceName, UUID assignedtokenSpaceName) { + UUID nullUUID = new UUID(0, 0); + + this.cName = cName; + this.tokenSpaceName =(tokenSpaceName == null) ? nullUUID : tokenSpaceName; + this.assignedtokenSpaceName =(assignedtokenSpaceName == null) ? nullUUID : assignedtokenSpaceName; + this.tokenNumber = 0; + this.assignedtokenNumber = 0; + this.pcdType = PCD_TYPE.UNKNOWN; + this.supportedpcdType = null; + this.isPlatform = false; + this.datumType = DATUM_TYPE.UNKNOWN; + this.datumSize = -1; + this.defaultValue = null; + this.datum = null; + this.hiiEnabled = false; + this.variableGuid = null; + this.variableName = ""; + this.variableOffset = -1; + this.skuEnabled = false; + this.skuDataArrayEnabled = false; + this.skuId = -1; + this.maxSkuCount = -1; + this.skuData = new ArrayList(); + this.vpdEnabled = false; + this.vpdOffset = -1; + + this.producers = new ArrayList(); + this.consumers = new ArrayList(); + } + + /** + Use "TokencName + "-" + SpaceTokenName" as primary key when adding token into database + + @param cName Token name. + @param tokenSpaceName The token space guid defined in MSA or SPD + @param platformtokenSpaceName The token space guid for current platform token space, + + @return primary key for this token in token database. + **/ + public static String getPrimaryKeyString(String cName, UUID tokenSpaceName, + UUID platformtokenSpaceName) { + UUID nullUUID = new UUID(0, 0); + + if (platformtokenSpaceName == nullUUID) { + return cName + "-" + tokenSpaceName.toString(); + } else { + return cName + "-" + platformtokenSpaceName.toString(); + } + } + + /** + Judge datumType is valid + + @param type The datumType want to be judged. + + @retval TRUE - The type is valid. + @retval FALSE - The type is invalid. + **/ + public static boolean isValiddatumType(DATUM_TYPE type) { + if ((type.ordinal() < DATUM_TYPE.UINT8.ordinal() ) || + (type.ordinal() > DATUM_TYPE.POINTER.ordinal())) { + return false; + } + return true; + } + + /** + Judge pcdType is valid + + @param type The PCdType want to be judged. + + @retval TRUE - The type is valid. + @retval FALSE - The type is invalid. + **/ + public static boolean isValidpcdType(PCD_TYPE type) { + if ((type.ordinal() < PCD_TYPE.FEATURE_FLAG.ordinal() ) || + (type.ordinal() > PCD_TYPE.DYNAMIC_EX.ordinal())) { + return false; + } + return true; + } + + /** + Add an usage instance for token + + @param usageInstance The usage instance + + @retval TRUE - Success to add usage instance. + @retval FALSE - Fail to add usage instance + **/ + public boolean addUsageInstance(UsageInstance usageInstance) { + if (usageInstance.usage == PCD_USAGE.UNKNOWN) { + return false; + } + + if ((usageInstance.usage == PCD_USAGE.ALWAYS_PRODUCED) || + (usageInstance.usage == PCD_USAGE.SOMETIMES_PRODUCED)) { + producers.add(usageInstance); + } else { + consumers.add(usageInstance); + } + return true; + } + + /** + Judge whether exist an usage instance for this token + + @param moduleName Use xmlFilePath as keyword to search the usage instance + + @retval PCD_USAGE - if UsageInstance exists. + @retval UNKNOWN - if UsageInstance does not exist, return UNKONW. + **/ + public PCD_USAGE isUsageInstanceExist(String moduleName) { + int index; + UsageInstance usageInstance; + + if (moduleName == null) { + ActionMessage.warning(this, "Error parameter for isUsageInstanceExist() function!"); + return PCD_USAGE.UNKNOWN; + } + + if (moduleName.length() == 0) { + return PCD_USAGE.UNKNOWN; + } + + // + // Searching the usage instance in module's producer and consumer according to + // module's name. + // + for (index = 0; index < producers.size(); index ++) { + usageInstance =(UsageInstance)producers.get(index); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + return usageInstance.usage; + } + } + + for (index = 0; index < consumers.size(); index ++) { + usageInstance =(UsageInstance)consumers.get(index); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + return usageInstance.usage; + } + } + return PCD_USAGE.UNKNOWN; + } + + /** + Get usage instance according to a MSA file name + + @param moduleName The file path string of MSA file. + + @return usage instance object. + **/ + public UsageInstance getUsageInstance(String moduleName) { + int usageIndex; + UsageInstance usageInstance; + + if (moduleName == null) { + ActionMessage.warning(this, "Error parameter for isUsageInstanceExist() function!"); + return null; + } + + if (moduleName.length() == 0) { + return null; + } + + if (producers.size() != 0) { + for (usageIndex = 0; usageIndex < producers.size(); usageIndex ++) { + usageInstance =(UsageInstance)producers.get(usageIndex); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + return usageInstance; + } + } + } + + if (consumers.size() != 0) { + for (usageIndex = 0; usageIndex < consumers.size(); usageIndex ++) { + usageInstance =(UsageInstance)consumers.get(usageIndex); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + return usageInstance; + } + } + } + return null; + } + + /** + Get the PCD_TYPE according to the string of PCD_TYPE + + @param pcdTypeStr The string of PCD_TYPE + + @return PCD_TYPE + **/ + public static PCD_TYPE getpcdTypeFromString(String pcdTypeStr) { + if (pcdTypeStr == null) { + return PCD_TYPE.UNKNOWN; + } + + if (pcdTypeStr.equalsIgnoreCase("FEATURE_FLAG")) { + return PCD_TYPE.FEATURE_FLAG; + } else if (pcdTypeStr.equalsIgnoreCase("FIXED_AT_BUILD")) { + return PCD_TYPE.FIXED_AT_BUILD; + } else if (pcdTypeStr.equalsIgnoreCase("PATCHABLE_IN_MODULE")) { + return PCD_TYPE.PATCHABLE_IN_MODULE; + } else if (pcdTypeStr.equalsIgnoreCase("DYNAMIC")) { + return PCD_TYPE.DYNAMIC; + } else if (pcdTypeStr.equalsIgnoreCase("DYNAMIC_EX")) { + return PCD_TYPE.DYNAMIC_EX; + } else { + return PCD_TYPE.UNKNOWN; + } + } + + /** + Get the string of given datumType. This string will be used for generating autogen files + + @param datumType Given datumType + + @return The string of datum type. + **/ + public static String getStringOfdatumType(DATUM_TYPE datumType) { + switch (datumType) { + case UINT8: + return "UINT8"; + case UINT16: + return "UINT16"; + case UINT32: + return "UINT32"; + case UINT64: + return "UINT64"; + case POINTER: + return "POINTER"; + case BOOLEAN: + return "BOOLEAN"; + } + return "UNKNOWN"; + } + + /** + Get the datumType according to a string. + + @param datumTypeStr The string of datumType + + @return DATUM_TYPE + **/ + public static DATUM_TYPE getdatumTypeFromString(String datumTypeStr) { + if (datumTypeStr.equalsIgnoreCase("UINT8")) { + return DATUM_TYPE.UINT8; + } else if (datumTypeStr.equalsIgnoreCase("UINT16")) { + return DATUM_TYPE.UINT16; + } else if (datumTypeStr.equalsIgnoreCase("UINT32")) { + return DATUM_TYPE.UINT32; + } else if (datumTypeStr.equalsIgnoreCase("UINT64")) { + return DATUM_TYPE.UINT64; + } else if (datumTypeStr.equalsIgnoreCase("VOID*")) { + return DATUM_TYPE.POINTER; + } else if (datumTypeStr.equalsIgnoreCase("BOOLEAN")) { + return DATUM_TYPE.BOOLEAN; + } + return DATUM_TYPE.UNKNOWN; + } + + /** + Get string of given pcdType + + @param pcdType The given PcdType + + @return The string of PCD_TYPE. + **/ + public static String getStringOfpcdType(PCD_TYPE pcdType) { + switch (pcdType) { + case FEATURE_FLAG: + return "FEATURE_FLAG"; + case FIXED_AT_BUILD: + return "FIXED_AT_BUILD"; + case PATCHABLE_IN_MODULE: + return "PATCHABLE_IN_MODULE"; + case DYNAMIC: + return "DYNAMIC"; + case DYNAMIC_EX: + return "DYNAMIC_EX"; + } + return "UNKNOWN"; + } + + /** + Get the PCD_USAGE according to a string + + @param usageStr The string of PCD_USAGE + + @return The PCD_USAGE + **/ + public static PCD_USAGE getUsageFromString(String usageStr) { + if (usageStr == null) { + return PCD_USAGE.UNKNOWN; + } + + if (usageStr.equalsIgnoreCase("ALWAYS_PRODUCED")) { + return PCD_USAGE.ALWAYS_PRODUCED; + } else if (usageStr.equalsIgnoreCase("SOMETIMES_PRODUCED")) { + return PCD_USAGE.SOMETIMES_PRODUCED; + } else if (usageStr.equalsIgnoreCase("ALWAYS_CONSUMED")) { + return PCD_USAGE.ALWAYS_CONSUMED; + } else if (usageStr.equalsIgnoreCase("SOMETIMES_CONSUMED")) { + return PCD_USAGE.SOMETIMES_CONSUMED; + } + + return PCD_USAGE.UNKNOWN; + } + + /** + Get the string of given PCD_USAGE + + @param usage The given PCD_USAGE + + @return The string of PDC_USAGE. + **/ + public static String getStringOfUsage(PCD_USAGE usage) { + switch (usage) { + case ALWAYS_PRODUCED: + return "ALWAYS_PRODUCED"; + case ALWAYS_CONSUMED: + return "ALWAYS_CONSUMED"; + case SOMETIMES_PRODUCED: + return "SOMETIMES_PRODUCED"; + case SOMETIMES_CONSUMED: + return "SOMETIMES_CONSUMED"; + } + return "UNKNOWN"; + } + + /** + Get the Defined datumType string for autogen. The string is for generating some MACROs in Autogen.h + + @param datumType The given datumType + + @return string of datum type for autogen. + **/ + public static String GetAutogenDefinedatumTypeString(DATUM_TYPE datumType) { + switch (datumType) { + + case UINT8: + return "8"; + case UINT16: + return "16"; + case BOOLEAN: + return "BOOL"; + case POINTER: + return "PTR"; + case UINT32: + return "32"; + case UINT64: + return "64"; + default: + return null; + } + } + + /** + Get the datumType String for Autogen. This string will be used for generating defintions of PCD token in autogen + + @param datumType The given datumType + + @return string of datum type. + **/ + public static String getAutogendatumTypeString(DATUM_TYPE datumType) { + switch (datumType) { + case UINT8: + return "UINT8"; + case UINT16: + return "UINT16"; + case UINT32: + return "UINT32"; + case UINT64: + return "UINT64"; + case POINTER: + return "VOID*"; + case BOOLEAN: + return "BOOLEAN"; + } + return null; + } + + /** + Get the datumType string for generating some MACROs in autogen file of Library + + @param datumType The given datumType + + @return String of datum for genrating bit charater. + **/ + public static String getAutogenLibrarydatumTypeString(DATUM_TYPE datumType) { + switch (datumType) { + case UINT8: + return "8"; + case UINT16: + return "16"; + case BOOLEAN: + return "Bool"; + case POINTER: + return "Ptr"; + case UINT32: + return "32"; + case UINT64: + return "64"; + default: + return null; + } + } + + /** + UUID defined in Schems is object, this function is to tranlate this object + to UUID data. + + @param uuidObj The object comes from schema. + + @return The traslated UUID instance. + **/ + public static UUID getGUIDFromSchemaObject(Object uuidObj) { + UUID uuid; + if (uuidObj.toString().equalsIgnoreCase("0")) { + uuid = new UUID(0,0); + } else { + uuid = UUID.fromString(uuidObj.toString()); + } + + return uuid; + } +} + + + + diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/UsageInstance.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/UsageInstance.java new file mode 100644 index 0000000000..a11633d91b --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/UsageInstance.java @@ -0,0 +1,471 @@ +/** @file + UsageInstance class. + + This class indicate an usage instance for a PCD token. This instance maybe a module + or platform setting. When a module produce or cosume a PCD token, then this module + is an usage instance for this PCD token. + +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.entity; + + +import org.tianocore.build.pcd.exception.EntityException; +import org.tianocore.build.pcd.action.ActionMessage; + +import org.tianocore.build.autogen.CommonDefinition; + +/** + This class indicate an usage instance for a PCD token. This instance maybe a module + or platform setting. When a module produce or cosume a PCD token, then this module + is an usage instance for this PCD token. +**/ +public class UsageInstance { + /// + /// This parent that this usage instance belongs to. + /// + public Token parentToken; + /// + /// The usage of this token for platform or module. + /// + public Token.PCD_USAGE usage; + /// + /// Whether this usage instance inherit from library + /// + public boolean isInherit; + /// + /// The pcd type of this token for module. + /// + public Token.PCD_TYPE modulePcdType; + /// + /// The name of the module who contains this PCD. + /// + public String moduleName; + /// + /// The name of the package whose module contains this PCD. + /// + public String packageName; + /// + /// The component type for this usage instance. + /// + public int componentType; + /// + /// The default value defined in MSA has high prior than defined in SPD. + /// + public Object defaultValueInMSA; + /// + /// The default value defined in SPD. + /// + public Object defaultValueInSPD; + /// + /// Help text in MSA + /// + public String helpTextInMSA; + /// + /// Help text in SPD + /// + public String helpTextInSPD; + /// + /// Autogen string for header file. + /// + public String hAutogenStr; + /** + * Auotgen string for C code file. + */ + public String cAutogenStr; + + /** + Constructure function + + @param parentToken Member variable. + @param usage Member variable. + @param pcdType Member variable. + @param componentType Member variable. + @param defaultValueInMSA Member variable. + @param defaultValueInSPD Member variable. + @param helpTextInMSA Member variable. + @param helpTextInSPD Member variable. + @param moduleName Member variable. + @param packageName Member variable. + @param isInherit Member variable. + **/ + public UsageInstance( + Token parentToken, + Token.PCD_USAGE usage, + Token.PCD_TYPE pcdType, + int componentType, + Object defaultValueInMSA, + Object defaultValueInSPD, + String helpTextInMSA, + String helpTextInSPD, + String moduleName, + String packageName, + boolean isInherit + ) + { + this.parentToken = parentToken; + this.usage = usage; + this.modulePcdType = pcdType; + this.componentType = componentType; + this.defaultValueInMSA = defaultValueInMSA; + this.defaultValueInSPD = defaultValueInSPD; + this.helpTextInMSA = helpTextInMSA; + this.helpTextInSPD = helpTextInSPD; + this.moduleName = moduleName; + this.packageName = packageName; + this.isInherit = isInherit; + } + + /** + Generate autogen string for header file and C code file. + + @throws EntityException Fail to generate. + **/ + public void generateAutoGen() throws EntityException { + Object value = null; + int tokenNumber = 0; + + hAutogenStr = ""; + cAutogenStr = ""; + + value = this.parentToken.datum; + + // + // If this pcd token's PCD_TYPE is DYNAMIC_EX, use itself token space name + // otherwices use assgined token space name from tool automatically. + // + if(parentToken.pcdType == Token.PCD_TYPE.DYNAMIC_EX) { + tokenNumber = parentToken.tokenNumber; + } else { + tokenNumber = parentToken.assignedtokenNumber; + } + + hAutogenStr += String.format("#define _PCD_TOKEN_%s 0x%016x\r\n", + parentToken.cName, tokenNumber); + + switch(modulePcdType) { + case FEATURE_FLAG: + // + // BUGBUG: The judegement of module PCD type and platform PCD type should not be + // done here, but in wizard tools, But here is just following something + // PcdEmulation driver. + // + if(parentToken.pcdType.ordinal() > Token.PCD_TYPE.FEATURE_FLAG.ordinal()) { + throw new EntityException( + String.format( + "%s:Platform PCD Type %d is not compatible with Module PCD Type %d\r\n", + parentToken.cName, + parentToken.pcdType.name(), + modulePcdType.name() + ) + ); + } + + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern const BOOLEAN _gPcd_FixedAtBuild_%s;\r\n", + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_FixedAtBuild_%s\r\n", + parentToken.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value.toString() + ); + hAutogenStr += String.format( + "extern const BOOLEAN _gPcd_FixedAtBuild_%s;\r\n", + parentToken.cName + ); + cAutogenStr += String.format( + "GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_%s = _PCD_VALUE_%s;\r\n", + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _PCD_VALUE_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + break; + case FIXED_AT_BUILD: + // + // BUGBUG: The judegement of module PCD type and platform PCD type should not be + // done here, but in wizard tools, But here is just following something + // PcdEmulation driver. + // + if(parentToken.pcdType.ordinal() > Token.PCD_TYPE.FIXED_AT_BUILD.ordinal()) { + throw new EntityException( + String.format( + "%s:Platform PCD Type %d is not compatible with Module PCD Type %d\r\n", + parentToken.cName, + parentToken.pcdType.name(), + modulePcdType.name() + ) + ); + } + + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern const %s _gPcd_FixedAtBuild_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_FixedAtBuild_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value.toString() + ); + hAutogenStr += String.format( + "extern const %s _gPcd_FixedAtBuild_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + cAutogenStr += String.format( + "GLOBAL_REMOVE_IF_UNREFERENCED const %s _gPcd_FixedAtBuild_%s = _PCD_VALUE_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _PCD_VALUE_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + break; + case PATCHABLE_IN_MODULE: + // + // BUGBUG: The judegement of module PCD type and platform PCD type should not be + // done here, but in wizard tools, But here is just following something + // PcdEmulation driver. + // + if(parentToken.pcdType.ordinal() > Token.PCD_TYPE.PATCHABLE_IN_MODULE.ordinal()) { + throw new EntityException( + String.format( + "%s:Platform PCD Type %d is not compatible with Module PCD Type %d\r\n", + parentToken.cName, + parentToken.pcdType.name(), + modulePcdType.name() + ) + ); + } + + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern %s _gPcd_BinaryPatch_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_BinaryPatch_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value + ); + hAutogenStr += String.format( + "extern %s _gPcd_BinaryPatch_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + cAutogenStr += String.format( + "GLOBAL_REMOVE_IF_UNREFERENCED %s _gPcd_BinaryPatch_%s = _PCD_VALUE_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_BinaryPatch_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + + break; + case DYNAMIC: + // + // BUGBUG: The judegement of module PCD type and platform PCD type should not be + // done here, but in wizard tools, But here is just following something + // PcdEmulation driver. + // + if(parentToken.pcdType.ordinal() > Token.PCD_TYPE.DYNAMIC.ordinal()) { + throw new EntityException( + String.format( + "%s:Platform PCD Type %d is not compatible with Module PCD Type %d\r\n", + parentToken.cName, + parentToken.pcdType.name(), + modulePcdType.name() + ) + ); + } + + switch(parentToken.pcdType) { + case FEATURE_FLAG: + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern const BOOLEAN _gPcd_FixedAtBuild_%s;\r\n", + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_FixedAtBuild_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value + ); + hAutogenStr += String.format( + "extern const BOOLEAN _gPcd_FixedAtBuild_%s;\r\n", + parentToken.cName + ); + cAutogenStr += String.format( + "const BOOLEAN _gPcd_FixedAtBuild_%s = _PCD_VALUE_%s;\r\n", + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _PCD_VALUE_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + break; + case FIXED_AT_BUILD: + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern const %s _gPcd_FixedAtBuild_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_FixedAtBuild_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value + ); + hAutogenStr += String.format( + "extern const %s _gPcd_FixedAtBuild_%s\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + cAutogenStr += String.format( + "const %s _gPcd_FixedAtBuild_%s = _PCD_VALUE_%s;\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _PCD_VALUE_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + break; + case PATCHABLE_IN_MODULE: + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value + ); + hAutogenStr += String.format( + "extern %s _gPcd_BinaryPatch_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + cAutogenStr += String.format( + "%s _gPcd_BinaryPatch_%s = _PCD_VALUE_%s;", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_BinaryPatch_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + break; + case DYNAMIC: + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s LibPcdGet%s(_PCD_TOKEN_%s)\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + Token.getAutogenLibrarydatumTypeString(parentToken.datumType), + parentToken.cName + ); + break; + default: + ActionMessage.log( + this, + "The PCD_TYPE setted by platform is unknown" + ); + } + break; + case DYNAMIC_EX: + break; + } + } + + /** + Get the autogen string for header file. + + @return The string of header file. + **/ + public String getHAutogenStr() { + return hAutogenStr; + } + + /** + Get the autogen string for C code file. + + @return The string of C Code file. + **/ + public String getCAutogenStr() { + return cAutogenStr; + } +} + diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/BuildActionException.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/BuildActionException.java new file mode 100644 index 0000000000..357ebf017a --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/BuildActionException.java @@ -0,0 +1,33 @@ +/** @file + BuildActionException class. + + BuildAction Exception deals with all build action exceptions. + +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.exception; + +import org.apache.tools.ant.BuildException; + +/** + BuildAction Exception deals with all build action exceptions. +**/ +public class BuildActionException extends BuildException { + static final long serialVersionUID = -7034897190740066939L; + /** + Constructure function + + @param reason exception message string. + **/ + public BuildActionException(String reason) { + super(reason); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/EntityException.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/EntityException.java new file mode 100644 index 0000000000..1e7ebfcbe1 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/EntityException.java @@ -0,0 +1,31 @@ +/** @file + EntityException class. + + The class handle the exception throwed by entity 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.exception; + +/** + The class handle the exception throwed by entity class. +**/ +public class EntityException extends Exception { + static final long serialVersionUID = -8034897190740066939L; + /** + Constructure function + + @param expStr exception message string. + **/ + public EntityException(String expStr) { + super("[EntityException]:" + expStr); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/UIException.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/UIException.java new file mode 100644 index 0000000000..96575a1450 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/UIException.java @@ -0,0 +1,31 @@ +/** @file + UIException class. + + The class handle the exception throwed by UI action 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.exception; + +/** + The class handle the exception throwed by UI action class. +**/ +public class UIException extends Exception { + static final long serialVersionUID = -7034897190740066930L; + /** + Constructure function + + @param reason exception message string. + **/ + public UIException(String reason) { + super(reason); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/ui/PCDDatabaseFrame.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/ui/PCDDatabaseFrame.java new file mode 100644 index 0000000000..81eb63025b --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/ui/PCDDatabaseFrame.java @@ -0,0 +1,184 @@ +/** @file + PCDDatabaseFrame class. + + The class is the frame class for displaying PCD database in tree method. + +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.ui; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; + +import org.tianocore.build.pcd.action.ActionMessage; +import org.tianocore.build.pcd.entity.MemoryDatabaseManager; +import org.tianocore.build.pcd.entity.Token; +import org.tianocore.build.pcd.entity.UsageInstance; + +/** + The class is the frame class for displaying PCD database in tree method. +**/ +public class PCDDatabaseFrame extends JFrame { + static final long serialVersionUID = -7034897190740068939L; + /// + /// Database instance + /// + private MemoryDatabaseManager dbManager; + /// + /// The token and module tree + /// + private JTree databaseTree; + + /** + Constructure function. + + Create the UI component and display frame. + + @param dbManager databaase manager instance. + **/ + public PCDDatabaseFrame(MemoryDatabaseManager dbManager) { + if (dbManager != null) { + this.dbManager = dbManager; + } + // + // Put the frame into center of desktop. + // + setLocation(100, 100); + initializeComponent(); + + setTitle("PCD View Tool"); + pack(); + setVisible(true); + } + + /** + Initliaze the UI component in Display frame. + **/ + public void initializeComponent() { + JScrollPane scrollPane = new JScrollPane(); + Container contentPane = getContentPane(); + + contentPane.setLayout(new BorderLayout()); + scrollPane.setViewportView(initializeTree()); + contentPane.add(scrollPane); + + addWindowListener(new PCDDatabaseFrameAdapter()); + } + + /** + Initiliaze the TREE control. + **/ + public JTree initializeTree() { + Token[] tokenArray = null; + Token token = null; + DefaultMutableTreeNode root = new DefaultMutableTreeNode(dbManager.getLogFileName()); + DefaultMutableTreeNode rootByPCD = new DefaultMutableTreeNode("By PCD"); + DefaultMutableTreeNode rootByModule = new DefaultMutableTreeNode("By Module"); + DefaultMutableTreeNode tokenNode = null; + DefaultMutableTreeNode usageNode = null; + DefaultMutableTreeNode moduleNode = null; + java.util.List moduleNames = null; + int index = 0; + int usageIndex = 0; + int moduleIndex = 0; + java.util.List usageArray = null; + UsageInstance usageInstance = null; + + root.add(rootByPCD); + // + // By PCD Node + // + + tokenArray = dbManager.getRecordArray(); + for (index = 0; index < tokenArray.length; index ++) { + token = tokenArray[index]; + ActionMessage.debug(this, token.cName); + tokenNode = new DefaultMutableTreeNode(token.cName); + tokenNode.add(new DefaultMutableTreeNode(String.format("TOKEN NUMBER: 0x%08x", token.tokenNumber))); + tokenNode.add(new DefaultMutableTreeNode(String.format("ASSIGNED TOKEN NUMBER: 0x%08x", token.assignedtokenNumber))); + tokenNode.add(new DefaultMutableTreeNode("TOKEN SPACE NAME: " + token.tokenSpaceName.toString())); + tokenNode.add(new DefaultMutableTreeNode("ASSIGNED TOKEN SPACE NAME: " + token.assignedtokenSpaceName.toString())); + tokenNode.add(new DefaultMutableTreeNode("PCD TYPE: " + Token.getStringOfpcdType(token.pcdType))); + tokenNode.add(new DefaultMutableTreeNode("DATUM TYPE: " +Token.getStringOfdatumType(token.datumType))); + tokenNode.add(new DefaultMutableTreeNode("DATUM: " + token.datum.toString())); + tokenNode.add(new DefaultMutableTreeNode("HIIENABLE: " +(token.hiiEnabled?"true":"false"))); + tokenNode.add(new DefaultMutableTreeNode("VARIABLE NAME: " + token.variableName)); + tokenNode.add(new DefaultMutableTreeNode("VARIABLE GUID: " + token.variableGuid.toString())); + tokenNode.add(new DefaultMutableTreeNode("SKUENABLE: " +(token.skuEnabled?"true":"false"))); + tokenNode.add(new DefaultMutableTreeNode("SKUDATA ARRAY ENABLE: " +(token.skuDataArrayEnabled?"true":"false"))); + tokenNode.add(new DefaultMutableTreeNode(String.format("SKUID: %d", token.skuId))); + tokenNode.add(new DefaultMutableTreeNode(String.format("MAX SKU COUNT: %d", token.maxSkuCount))); + tokenNode.add(new DefaultMutableTreeNode("VPDENABLE: " +(token.vpdEnabled?"true":"false"))); + + usageNode = new DefaultMutableTreeNode("PRODUCER"); + tokenNode.add(usageNode); + + // + // Prepare producer's leaf node + // + + for (usageIndex = 0; usageIndex < token.producers.size(); usageIndex ++) { + usageNode.add(new DefaultMutableTreeNode(token.producers.get(usageIndex).moduleName)); + } + + // + // Prepare consumer's leaf node + // + usageNode = new DefaultMutableTreeNode("CONSUMER"); + tokenNode.add(usageNode); + + for (usageIndex = 0; usageIndex < token.consumers.size(); usageIndex ++) { + usageNode.add(new DefaultMutableTreeNode(token.consumers.get(usageIndex).moduleName)); + } + + rootByPCD.add(tokenNode); + } + + // + // BY MODULE Node + // + root.add(rootByModule); + moduleNames = dbManager.getAllModuleArray(); + for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) { + ActionMessage.debug(this, "ModuleName:" + moduleNames.get(moduleIndex)); + } + for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) { + moduleNode = new DefaultMutableTreeNode(moduleNames.get(moduleIndex)); + usageArray = dbManager.getUsageInstanceArrayByModuleName(moduleNames.get(moduleIndex)); + for (usageIndex = 0; usageIndex < usageArray.size(); usageIndex ++) { + usageInstance = usageArray.get(usageIndex); + usageNode = new DefaultMutableTreeNode(usageInstance.parentToken.cName); + usageNode.add(new DefaultMutableTreeNode("MODULE PCD TYPE: " + Token.getStringOfpcdType(usageInstance.modulePcdType))); + usageNode.add(new DefaultMutableTreeNode("HELP TEXT: " + usageInstance.helpTextInMSA)); + usageNode.add(new DefaultMutableTreeNode("IS INHERIT: " +(usageInstance.isInherit?"true":"false"))); + usageNode.add(new DefaultMutableTreeNode("USAGE: " + Token.getStringOfUsage(usageInstance.usage))); + moduleNode.add(usageNode); + } + rootByModule.add(moduleNode); + } + + databaseTree = new JTree(root); + return databaseTree; + } +} + +/** + The adatper class for PCDDatabaseFrame. This class instance many windows message + callback function. +**/ +class PCDDatabaseFrameAdapter extends WindowAdapter { + public void windowClosing(WindowEvent e) { + System.exit(0); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/toolchain/ConfigReader.java b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ConfigReader.java new file mode 100644 index 0000000000..f48735966e --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ConfigReader.java @@ -0,0 +1,218 @@ +/** @file + ConfigReader class. + + ConfigReader is used to read tool chain config file with flat format. + +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.toolchain; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; + +/** + + ConfigReader is used to read tool chain config file with flat format. Comments + is line starting with character '#'. + + @since GenBuild 1.0 +**/ +public class ConfigReader { + + private static String confPath = "."; + + /** + Public construct method. + **/ + public ConfigReader () { + } + + /** + Default filepath is ".". + + @param filename the config file name like "target.txt" + @return the variables defined in file + **/ + public static synchronized String[][] parse(String filename) { + return parse(confPath, filename); + } + + /** + Get all variables defined in config file. the config file format is flat + with "A=B". If line started with '#' looks as comments. + + @param confPath the path of config file + @param filename the file name of the config file + @return the variables defined in the config file + @throws BuildException + Config file's format is not valid + **/ + public static synchronized String[][] parse(String confPath, String filename) throws BuildException { + try { + Map map = new HashMap(20); + File file = new File(confPath + File.separatorChar + filename); + FileReader reader = new FileReader(file); + BufferedReader in = new BufferedReader(reader); + String str; + while ((str = in.readLine()) != null) { + str = str.trim(); + // + // if str is empty line or comments (start with '#') + // + if (str.equalsIgnoreCase("") || str.startsWith("#")) { + continue; + } + // + // if str without '=' or start with '=' + // + if (str.indexOf('=') <= 0) { + continue; + } + // + // look as line "A = B" + // + int index = str.indexOf('='); + String key = str.substring(0, index).trim(); + String value = str.substring(index + 1).trim(); + // + // if key is existed, then update + // + if (map.containsKey(key)) { + map.remove(key); + } + map.put(key, value); + } + Set keyset = map.keySet(); + Iterator iter = keyset.iterator(); + String[][] result = new String[map.size()][2]; + int i = 0; + while (iter.hasNext()) { + String key = (String) iter.next(); + result[i][0] = key; + result[i++][1] = (String) map.get(key); + } + return result; + } catch (Exception e) { + throw new BuildException("Processor file [" + filename + "] error. \n" + e.getMessage()); + } + } + + /** + Parse global flags table. The format is like such(global flag name, value, + vendor_arch_cmd, [add flags], [sub flags]): + +
+        # EFI_DEBUG
+        EFI_DEBUG YES MSFT_IA32_ASM    ADD.["/Zi", "/DEBUG"]
+        EFI_DEBUG YES MSFT_IA32_CC     ADD.["/Zi", "/Gm", "/D EFI_DEBUG"] SUB.["/nologo", "/WX"]
+        EFI_DEBUG YES MSFT_IA32_LINK   ADD.["/DEBUG"]
+        EFI_DEBUG YES MSFT_NT32_CC     ADD.["/DEBUG"]
+      
+ + @param confPath the file path of config file + @param filename the file name of config file + @return the value list + @throws BuildException + Config file is not valid + **/ + public static synchronized String[][] parseTable(String confPath, + String filename) throws BuildException { + try { + Vector vector = new Vector(20); + File file = new File(confPath + File.separatorChar + filename); + FileReader reader = new FileReader(file); + BufferedReader in = new BufferedReader(reader); + String str; + while ((str = in.readLine()) != null) { + str = str.trim(); + // + // if str is empty line or comments (start with '#') + // + if (str.equalsIgnoreCase("") || str.startsWith("#")) { + continue; + } + String[] item = new String[5]; + for(int i=0; i < item.length; i++){ + item[i] = ""; + } + // + // EFI_DEBUG YES MSFT_IA32_ASM ADD.["/Zi", "/DEBUG"] + // FLAGS: EFI_DEBUG + // + int index = str.indexOf(" "); + item[0] = str.substring(0, index); + str = str.substring(index + 1).trim(); + // + // Setting: YES + // + index = str.indexOf(" "); + item[1] = str.substring(0, index); + str = str.substring(index + 1).trim(); + // + // Vendor_Arch_Commandtype: MSFT_IA32_ASM + // + index = str.indexOf(" "); + item[2] = str.substring(0, index); + str = str.substring(index + 1).trim(); + // + // Add or/and Sub + // + if (str.startsWith("ADD.")) { + index = str.indexOf("]"); + if ( index > 0){ + item[3] = str.substring(5, index); + str = str.substring(index + 1).trim(); + } + } + else if(str.startsWith("SUB.")){ + index = str.indexOf("]"); + if ( index > 0){ + item[4] = str.substring(5, index); + str = str.substring(index + 1).trim(); + } + } + else { + throw new BuildException("File [" + filename + "] never conform to Global Flags Table format."); + } + + if (str.startsWith("ADD.")) { + index = str.indexOf("]"); + if ( index > 0){ + item[3] = str.substring(5, index); + str = str.substring(index + 1).trim(); + } + } + else if(str.startsWith("SUB.")){ + index = str.indexOf("]"); + if ( index > 0){ + item[4] = str.substring(5, index); + str = str.substring(index + 1).trim(); + } + } + vector.addElement(item); + } + String[][] result = new String[vector.size()][5]; + for(int i=0; i < vector.size(); i++){ + result[i] = (String[])vector.get(i); + } + return result; + } catch (Exception e) { + throw new BuildException("Processor file [" + filename + "] error. \n" + e.getMessage()); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainFactory.java b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainFactory.java new file mode 100644 index 0000000000..e3010fccf4 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainFactory.java @@ -0,0 +1,529 @@ +/** @file + ToolChainFactory class. + + ToolChainFactory class parse all config files and get STD_FLAGS, GLOBAL_FLAGS, + and also command path + name. + +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.toolchain; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.io.File; + +import org.apache.tools.ant.Project; + + +/** + This class parse all config files and get STD_FLAGS, GLOBAL_FLAGS, and also + command path + name. + + @since GenBuild 1.0 +**/ +public class ToolChainFactory { + /// + /// list of Arch: EBC, ARM, IA32, X64, IPF, PPC + /// + public final static String[] arch = { "EBC", "ARM", "IA32", "X64", "IPF", + "PPC"}; + + /// + /// list of OS: Linux, Windows + /// + public final static String[] os = { "WINDOWS", "LINUX" }; + + /// + /// list of Command Type: CC, LIB, LINK, ASL, ASM, ASMLINK, PP + /// + public final static String[] commandType = { "CC", "LIB", "LINK", "ASL", + "ASM", "ASMLINK", "PP" }; + + /// + /// default command name for every command + /// + public final static String[][] defaultCmdName = { { "CC", "cl" }, + { "LIB", "lib" }, { "LINK", "link" }, { "ASL", "iasl" }, + { "ASM", "ml" }, { "ASMLINK", "link" }, { "PP", "cl" } }; + + private String confPath = "."; + + private String toolChainName = "MSFT"; + + private String sTargetFilename = "target.txt"; + + private String sToolsdefFilename = "tools_def.txt"; + + private String sWorkspaceTarget = "WORKSPACE_TARGET"; + + private String sTargetArch = "TARGET_ARCH"; + + private HashMap filesMap = new HashMap(); + + private HashMap globalFlagsMap = new HashMap(); + + private String[][] globalFlagTable; + + private String currentTarget = "RELEASE"; + + /// + /// toolchain array list all results by parsing config files + /// + public static String[][] toolchain = null; + + /** + Public construct method. + **/ + public ToolChainFactory () { + } + + /** + Public construct method. + + @param project current ANT Project. + **/ + public ToolChainFactory (Project project) { + this.confPath = project.replaceProperties("${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "Conf"); + } + + /** + Public construct method. + + @param confPath the path of config files + @param toolChainName TOOL_CHAIN name + **/ + public ToolChainFactory (String confPath, String toolChainName) { + this.confPath = confPath; + // + // If set tool used the set one, otherwise use default one. + // toolChain used to define open tools define txt file. + // + if (toolChainName != null && toolChainName.length() > 0){ + this.toolChainName = toolChainName; + } + } + + /** + Parse all config files, following are the detail steps: + +
    +
  • Parse target.txt file. This file define the current build TARGET + and supported ARCH list.
  • +
  • Parse tools_def.txt file. This file define every command name, path + and vendor.
  • +
  • For every supported ARCH and Command Type, find out STD_FLAGS, + GLOBAL_ADD_FLAGS, GLOBAL_SUB_FLAGS.
  • +
+ +

Note that this method will be called only once during the whole build + process.

+ **/ + public void setupToolChain() { + if (toolchain != null) { + return ; + } + Map map = new HashMap(40); + // + // parse target.txt + // + String[][] target = ConfigReader.parse(confPath, sTargetFilename); + // + // get workspace_target and initialize global flags setting + // + currentTarget = getValue(sWorkspaceTarget, target); + parseGlobalSetting(currentTarget); + String[] archList = getArchs(getValue(sTargetArch, target)); + + // + // If user write the ${toolChain}_Tools_Def.txt use this one, + // otherwise used "tools_def.txt" file. + // + File tempFile = new File (confPath + File.separator + toolChainName.toLowerCase() + "_tools_def.txt"); + if (tempFile.exists()){ + sToolsdefFilename = toolChainName.toLowerCase() + "_tools_def.txt"; + } + + System.out.println("Tools definition file is: " + sToolsdefFilename); + // + // parse tools_def.txt + // + String[][] tools_def = ConfigReader.parse(confPath, sToolsdefFilename); + // + // for each arch find all command's path&name and flags + // + for (int i = 0; i < archList.length; i++) { + for (int j = 0; j < commandType.length; j++) { + // + // Path & Name + // + map.put(archList[i] + "_" + commandType[j], getAbsoluteCmdPath( + archList[i], commandType[j], tools_def)); + // + // Flags: CMD_STD_FLAGS + CMD_GLOBAL_FLAGS + CMD_PROJ_FLAGS + // ARCH_CMD_STD_FLAGS + // + map.put(archList[i] + "_" + commandType[j] + "_STD_FLAGS", + getStdFlags(archList[i], commandType[j], + tools_def)); + // + // Flags:ARCH_CMD_VENDOR or ARCH_VENDOR + // + map.put(archList[i]+ "_"+commandType[j]+"_VENDOR", getVendorFlag(archList[i], + commandType[j], tools_def)); + // + // ARCH_CMD_GLOBAL_FLAGS + // + String[] globalFlags = getGlobalFlags(archList[i], commandType[j], + tools_def); + map.put(archList[i] + "_" + commandType[j] + "_GLOBAL_ADD_FLAGS", + globalFlags[0]); + map.put(archList[i] + "_" + commandType[j] + "_GLOBAL_SUB_FLAGS", + globalFlags[1]); + // + // ARCH_CMD_GLOBAL_FLAGS, default is "". + // + map.put(archList[i] + "_" + commandType[j] + "_PROJ_FLAGS", ""); + } + map.put(archList[i]+"_VENDOR", getVendorFlag(archList[i], null, tools_def)); + } + Set keyset = map.keySet(); + Iterator iter = keyset.iterator(); + String[][] result = new String[map.size()][2]; + int i = 0; + while (iter.hasNext()) { + String key = (String) iter.next(); + result[i][0] = key; + result[i++][1] = (String) map.get(key); + } + toolchain = result; + } + + /** + Get the standard flags (STD_FLAGS) for specified arch and command type. + +
    +
  • Find out Vendor that cmd Command Type with arch ARCH used. The + search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here + we suppose default Vendor is MSFT.
  • +
  • Search ${Vendor}_tools.txt file, and get the corrsponding flags. +
  • +
+ + @param arch the ARCH + @param cmd the command type + @param map detail flags information of tools_def.txt + @return the standard flags of arch ARCH and cmd Command Type + **/ + private String getStdFlags(String arch, String cmd, String[][] map) { + // + // first is to find out its Vendor in map + // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT" + // Here we suppose default Vendor is MSFT. + // + String vendor = "MSFT"; + String str; + if ((str = getValue(arch + "_" + cmd + "_VENDOR", map)) != null) { + vendor = str; + } else if ((str = getValue(arch + "_VENDOR", map)) != null) { + vendor = str; + } + // + // change to low letter + // + vendor = vendor.toLowerCase(); + // + // parse the corresponding file and get arch_cmd value + // + String filename = vendor + "_tools.txt"; + String[][] flagsMap; + if (filesMap.containsKey(filename)) { + flagsMap = (String[][]) filesMap.get(filename); + } else { + // + // read file and store in filesMap + // + flagsMap = ConfigReader.parse(confPath, vendor + "_tools.txt"); + filesMap.put(filename, flagsMap); + } + if ((str = getValue(arch + "_" + cmd, flagsMap)) != null) { + return str; + } + return ""; + } + + /** + Get the global flags (GLOBAL_ADD_FLAGS & GLOBAL_SUB_FLAGS) for specified + arch and command type. + +
    +
  • Find out Vendor that cmd Command Type with arch ARCH used. The + search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here + we suppose default Vendor is MSFT.
  • +
  • Search efi_flags_table.txt file, and get the corrsponding flags. +
  • +
+ + @param arch the ARCH + @param cmd the command type + @param map detail flags information of tools_def.txt + @return two values, first is GLOBAL_ADD_FLAGS and another value is + GLOBAL_SUB_FLAGS + **/ + private String[] getGlobalFlags(String arch, String cmd, String[][] map) { + String addStr = ""; + String subStr = ""; + // + // first is to find out its Vendor in map + // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT" + // Here we suppose default Vendor is MSFT. + // + String vendor = "MSFT"; + String str; + if ((str = getValue(arch + "_" + cmd + "_VENDOR", map)) != null) { + vendor = str; + } else if ((str = getValue(arch + "_VENDOR", map)) != null) { + vendor = str; + } + // + // parse global flags table + // + if (globalFlagTable == null) { + globalFlagTable = ConfigReader.parseTable(confPath, "efi_flags_table.txt"); + } + for (int i=0; i < globalFlagTable.length; i++){ + String[] item = globalFlagTable[i]; + if (item[2].equalsIgnoreCase(vendor + "_" + arch + "_" + cmd)){ + // + // if item[0] == item[1] is existed in globalFlagsMap + // + if (globalFlagsMap.containsKey(item[0])){ + if( item[1].equalsIgnoreCase((String)globalFlagsMap.get(item[0]))){ + addStr += item[3] + " "; + subStr += item[4] + " "; + } + } + } + } + + return new String[]{addStr, subStr}; + } + + /** + Find out command path and command name. + +
+        Command path searching sequence in tools_def.txt file:
+        Path: ARCH_CMD_PATH -> ARCH_PATH -> Set to "".
+        
+        Command name searching sequence in tools_def.txt file:
+        Name: ARCH_CMD_NAME -> CMD_NAME -> Default Value.
+      
+ + @param arch the ARCH + @param cmd the Command Type + @param map detail flags information of tools_def.txt + @return the absolute command path and name + **/ + private String getAbsoluteCmdPath(String arch, String cmd, String[][] map) { + String path = ""; + String name = ""; + String str; + // + // find Path + // + if ((str = getValue(arch + "_" + cmd + "_PATH", map)) != null) { + path = str; + } else if ((str = getValue(arch + "_PATH", map)) != null) { + path = str; + } + // + // find Name + // + if ((str = getValue(arch + "_" + cmd + "_NAME", map)) != null) { + name = str; + } else if ((str = getValue(cmd + "_NAME", map)) != null) { + name = str; + } else { + name = getValue(cmd, defaultCmdName); + } + if (path.equalsIgnoreCase("")) { + return name; + } + return path + File.separatorChar + name; + } + + /** + Find out all global flags value, such as EFI_DEBUG equal YES or NO. Here + are three type files: global_efi_flags.txt, ${TARGET}_efi_flags.txt, + my_efi_flags.txt. global_efi_flags.txt with the highest priority while + my_efi_flags.txt with the lowest priority. + +

All global flags value will store in globalFlagsMap for + getGlobalFlags using.

+ + @param target current build TARGET value + **/ + private void parseGlobalSetting(String target){ + // + // parse global_efi_flags -> ${TARGET}_efi_flags -> my_efi_flags + // parse global_efi_flags + // + String[][] map = ConfigReader.parse(confPath, "global_efi_flags.txt"); + for (int i = 0; i < map.length; i++){ + if(globalFlagsMap.containsKey(map[i][0])){ + globalFlagsMap.remove(map[i][0]); + } + globalFlagsMap.put(map[i][0], map[i][1]); + } + // + // parse ${TARGET}_efi_flags + // + map = ConfigReader.parse(confPath, target + "_efi_flags.txt"); + for (int i = 0; i < map.length; i++){ + if(globalFlagsMap.containsKey(map[i][0])){ + globalFlagsMap.remove(map[i][0]); + } + globalFlagsMap.put(map[i][0], map[i][1]); + } + // + // parse my_efi_flags.txt + // + map = ConfigReader.parse(confPath, "my_efi_flags.txt"); + for (int i = 0; i < map.length; i++){ + if(globalFlagsMap.containsKey(map[i][0])){ + globalFlagsMap.remove(map[i][0]); + } + globalFlagsMap.put(map[i][0], map[i][1]); + } + } + + /** + Find value with key from map. If not found, return null. + +

Note that default is case-insensitive

+ + @param key key value + @param map mapping information + @return the related value of key + **/ + private String getValue(String key, String[][] map) { + return getValue(key, map, false); + } + + /** + Find value with key from map. If not found, return null. + + @param key key value + @param map mapping information + @param caseSensitive whether case sesitive or not + @return the related value of key + **/ + private String getValue(String key, String[][] map, boolean caseSensitive) { + for (int i = 0; i < map.length; i++) { + if (caseSensitive) { + if (key.compareTo(map[i][0]) == 0) { + return map[i][1]; + } + } else { + if (key.compareToIgnoreCase(map[i][0]) == 0) { + return map[i][1]; + } + } + } + return null; + } + + /** + Find value with key from toolchain. If not found, return null. + + @param key key value + @return the related value of key + **/ + public static String getValue(String key){ + for (int i = 0; i < toolchain.length; i++) { + if (key.compareToIgnoreCase(toolchain[i][0]) == 0) { + return toolchain[i][1]; + } + } + return null; + } + + /** + Get Arch list from a string separated with comma. + +
+        For example:
+          If the arch string is "IA32, X64, EBC".
+          Then the result is {"IA32", "X64", "EBC"}. 
+      
+ + @param arch string separated with comma + @return Arch list + **/ + public String[] getArchs(String arch) { + if (arch == null) { + return new String[0]; + } + StringTokenizer st = new StringTokenizer(arch, " \t,"); + String[] archs = new String[st.countTokens()]; + int i = 0; + while (st.hasMoreTokens()) { + archs[i++] = st.nextToken().toUpperCase(); + } + return archs; + } + + /** + Get current target value. + + @return current target value + **/ + public String getCurrentTarget() { + return currentTarget; + } + + /** + Find out Vendor that cmd Command Type with arch ARCH used. The + search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here + we suppose default Vendor is MSFT. + + @param arch the ARCH + @param cmd the Command Type + @param map detail flags information of tools_def.txt + @return the related vendor name + **/ + public String getVendorFlag (String arch, String cmdType, String[][] map){ + // + // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT" + // Here we suppose default Vendor is MSFT. + // + String str; + String vendor = ""; + if (cmdType != null){ + if ((str = getValue(arch + "_" + cmdType + "_VENDOR", map)) != null) { + vendor = str; + }else { + vendor = ""; + } + }else if (arch != null){ + if ((str = getValue(arch + "_VENDOR", map)) != null) { + vendor = str; + }else { + vendor = ""; + } + } + return vendor; + } + +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainTask.java b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainTask.java new file mode 100644 index 0000000000..04dab1c3e3 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainTask.java @@ -0,0 +1,60 @@ +/** @file + ToolChainTask class. + + ToolChainTask class's main fucntion is read all tool chain related config files. + +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.toolchain; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +/** + This class is an ANT task. The main function is to read all tool chain related + config files. + + @since GenBuild 1.0 +**/ +public class ToolChainTask extends Task{ + + private String confPath = "."; + + /** + Public construct method. It is necessary for ANT task. + **/ + public ToolChainTask(){ + } + + /** + ANT task's entry point, will be called after init(). Using + ToolChainFactory to parse all config files, and + set TARGET property. + + @throws BuildException + Config files are invalid. + **/ + public void execute() throws BuildException { + String toolChain = getProject().getProperty("env.TOOL_CHAIN"); + ToolChainFactory toolchain = new ToolChainFactory(confPath, toolChain); + toolchain.setupToolChain(); + getProject().setProperty("TARGET", toolchain.getCurrentTarget()); + } + + /** + Set the path of config files. + + @param confPath the path of config files + **/ + public void setConfPath(String confPath) { + this.confPath = confPath; + } +} -- cgit v1.2.3