]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Tools/Java/Source/GenBuild/org/tianocore/build/FfsProcess.java
Restructuring for better separation of Tool packages.
[mirror_edk2.git] / Tools / Java / Source / GenBuild / org / tianocore / build / FfsProcess.java
diff --git a/Tools/Java/Source/GenBuild/org/tianocore/build/FfsProcess.java b/Tools/Java/Source/GenBuild/org/tianocore/build/FfsProcess.java
new file mode 100644 (file)
index 0000000..26b9390
--- /dev/null
@@ -0,0 +1,422 @@
+/** @file\r
+  File is FfsProcess class which is used to get the corresponding FFS layout\r
+  information for driver module. \r
\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+package org.tianocore.build;\r
+\r
+import java.io.File;\r
+import java.util.Vector;\r
+\r
+import javax.xml.namespace.QName;\r
+\r
+import org.apache.tools.ant.BuildException;\r
+import org.apache.tools.ant.Project;\r
+import org.apache.xmlbeans.XmlCursor;\r
+import org.tianocore.BuildOptionsDocument;\r
+import org.tianocore.build.global.GlobalData;\r
+import org.tianocore.build.global.SurfaceAreaQuery;\r
+import org.tianocore.build.id.FpdModuleIdentification;\r
+import org.tianocore.common.definitions.EdkDefinitions;\r
+import org.tianocore.common.logger.EdkLog;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+/** \r
+  <p><code>FfsProcess</code> is a class to find the corresponding FFS layout. </p>\r
+  \r
+  <p>The FFS Layout is like following: </p>\r
+  \r
+  <pre>\r
+    &lt;Ffs type="APPLICATION"&gt;\r
+      &lt;Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" /&gt;\r
+      &lt;Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" /&gt;\r
+      &lt;Sections EncapsulationType="Compress"&gt;\r
+        &lt;Sections EncapsulationType="Guid-Defined"&gt;\r
+          &lt;Section SectionType="EFI_SECTION_PE32" /&gt; \r
+          &lt;Section SectionType="EFI_SECTION_USER_INTERFACE" /&gt;\r
+          &lt;Section SectionType="EFI_SECTION_VERSION" /&gt; \r
+        &lt;/Sections&gt;\r
+      &lt;/Sections&gt;\r
+    &lt;/Ffs&gt;\r
+  </pre>\r
\r
+  @since GenBuild 1.0\r
+**/\r
+public class FfsProcess {\r
+\r
+    private BuildOptionsDocument.BuildOptions.Ffs ffsXmlObject;\r
+\r
+    ///\r
+    /// ANT script to call GenFfs\r
+    ///\r
+    private Element ffsNode = null;\r
+\r
+    ///\r
+    /// Module base name\r
+    ///\r
+    private String basename;\r
+\r
+    ///\r
+    /// Sections type: normal\r
+    ///\r
+    private static int MODE_NONE = 0;\r
+\r
+    ///\r
+    /// Sections type: compress\r
+    ///\r
+    private static int MODE_COMPRESS = 1;\r
+\r
+    ///\r
+    /// Sections type: guid-define\r
+    ///\r
+    private static int MODE_GUID_DEFINED = 2;\r
+\r
+    ///\r
+    /// mapping from section type to section output file extension\r
+    ///\r
+    public static final String[][] sectionExt = EdkDefinitions.SectionTypeExtensions;\r
+\r
+    /**\r
+      search in the type, if componentType is listed in type, return true; \r
+      otherwise return false.\r
+      \r
+      @param type a list supported component type separated by comma\r
+      @param componentType current module component type\r
+      @return whether componentType is one of type \r
+    **/\r
+    private boolean isMatch(String type, String componentType) {\r
+        String[] items = type.split("[ \t]*,[ \t]*");\r
+        for (int i = 0; i < items.length; i++) {\r
+            if (items[i].equalsIgnoreCase(componentType)) {\r
+                return true;\r
+            }\r
+        }\r
+        return false;\r
+    }\r
+\r
+    /**\r
+      Find the corresponding FFS layout in <code>FPD</code>. \r
+      \r
+      @param buildType Current module's component type\r
+      @param project Ant project\r
+      @return whether find the corresponding FFS layout\r
+      @throws BuildException\r
+              If can't find FFS Layout in FPD.\r
+    **/\r
+    public boolean initSections(String buildType, Project project, FpdModuleIdentification fpdModuleId) throws BuildException {\r
+        //\r
+        // Try to find Ffs layout from FPD file\r
+        //\r
+        SurfaceAreaQuery saq = new SurfaceAreaQuery(GlobalData.getFpdBuildOptionsMap());\r
+        BuildOptionsDocument.BuildOptions.Ffs[] ffsArray = saq.getFpdFfs();\r
+        for (int i = 0; i < ffsArray.length; i++) {\r
+            if (isMatch(ffsArray[i].getFfsKey(), buildType)) {\r
+                ffsXmlObject = ffsArray[i];\r
+                return true;\r
+            }\r
+        }\r
+        \r
+        //\r
+        // If FfsFormatKey is not null, report exception and fail build\r
+        // Otherwise report warning message\r
+        //\r
+        if (buildType == null) {\r
+            EdkLog.log(EdkLog.EDK_WARNING, "Warning: this module doesn't specify a FfsFormatKey. ");\r
+        } else {\r
+            throw new BuildException("Can't find the FfsFormatKey [" + buildType + "] attribute in the FPD file!");            \r
+        }\r
+\r
+        return false;\r
+    }\r
+    \r
+    /**\r
+      Recursive parse the FFS layout. Find out all section type here used. \r
+      \r
+      @param document BaseName_build.xml Xml document\r
+      @param basename Module's base name\r
+      @param guid Module's GUID\r
+      @param targetFilename Module's final file name (GUID-BaseName.APP)\r
+      @return List of section type\r
+    **/\r
+    public String[] getGenSectionElements(Document document, String basename, String guid, String targetFilename) {\r
+        this.basename = basename;\r
+        if (ffsXmlObject == null) {\r
+            return new String[0];\r
+        }\r
+        Vector<String> sectionList = new Vector<String>();\r
+        XmlCursor cursor = null;\r
+\r
+        cursor = ffsXmlObject.newCursor();\r
+\r
+        int mode = MODE_NONE;\r
+        Element genffsfileEle = document.createElement("genffsfile");\r
+        genffsfileEle.setAttribute("outputDir", "${BIN_DIR}");\r
+        genffsfileEle.setAttribute("moduleType", "${MODULE_TYPE}");\r
+        genffsfileEle.setAttribute("BaseName", basename);\r
+        genffsfileEle.setAttribute("fileGuid", guid);\r
+\r
+        if (cursor.toFirstChild()) {\r
+            do {\r
+                if (cursor.getName().getLocalPart().equalsIgnoreCase("Attribute")) {\r
+                    String name = cursor.getAttributeText(new QName("Name"));\r
+                    String value = cursor.getAttributeText(new QName("Value"));\r
+                    genffsfileEle.setAttribute(changeAttributeName(name), value);\r
+                } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
+                    cursor.push();\r
+                    dealSection(mode, document, genffsfileEle, cursor, sectionList);\r
+                    cursor.pop();\r
+                } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
+                    cursor.push();\r
+                    dealSections(mode, document, genffsfileEle, cursor, sectionList);\r
+                    cursor.pop();\r
+                }\r
+            } while (cursor.toNextSibling());\r
+        }\r
+        //\r
+        // Check dependency \r
+        //\r
+        Element outofdateEle = document.createElement("OnDependency");\r
+        Element sourceEle = document.createElement("sourcefiles");\r
+        String[] result = new String[sectionList.size()];\r
+        for (int i = 0; i < sectionList.size(); i++) {\r
+            result[i] = (String) sectionList.get(i);\r
+            Element pathEle = document.createElement("file");\r
+            pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename\r
+                                         + getSectionExt(result[i]));\r
+            sourceEle.appendChild(pathEle);\r
+        }\r
+        outofdateEle.appendChild(sourceEle);\r
+        Element targetEle = document.createElement("targetfiles");\r
+        Element fileEle = document.createElement("file");\r
+        fileEle.setAttribute("name", "${BIN_DIR}" + File.separatorChar + targetFilename);\r
+        targetEle.appendChild(fileEle);\r
+        outofdateEle.appendChild(targetEle);\r
+        Element sequentialEle = document.createElement("sequential");\r
+        sequentialEle.appendChild(genffsfileEle);\r
+        outofdateEle.appendChild(sequentialEle);\r
+        ffsNode = outofdateEle;\r
+        return result;\r
+    }\r
+\r
+    /**\r
+      Change the attribute name. For example: \r
+      \r
+      <pre>\r
+          Before change: FFS_ATTRIB_CHECKSUM \r
+          After  change: ffsATTRIBCHECKSUM\r
+      </pre>\r
+      \r
+      @param name Original attribute name\r
+      @return Changed attribute name\r
+    **/\r
+    private String changeAttributeName(String name) {\r
+        String[] strs = name.split("_");\r
+        String str = strs[0].toLowerCase();\r
+        for (int j = 1; j < strs.length; j++) {\r
+            str += strs[j];\r
+        }\r
+        return str;\r
+    }\r
+\r
+    /**\r
+      Recursively deal with Sections. If sections does not specify a type, then omit it.\r
+      \r
+      @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
+      @param doc Xml Document\r
+      @param root Root Node\r
+      @param cursor Current FFS layout cursor\r
+      @param list List of section type here used\r
+    **/\r
+    private void dealSections(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
+        String type = cursor.getAttributeText(new QName("EncapsulationType"));\r
+        String toolName = cursor.getAttributeText(new QName("ToolName"));\r
+        String sectType = cursor.getAttributeText(new QName("SectionType"));\r
+        if (type == null && sectType == null) {\r
+            if (cursor.toFirstChild()) {\r
+                do {\r
+                    if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
+                        cursor.push();\r
+                        dealSection(mode, doc, root, cursor, list);\r
+                        cursor.pop();\r
+                    } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
+                        cursor.push();\r
+                        dealSections(mode, doc, root, cursor, list);\r
+                        cursor.pop();\r
+                    }\r
+                } while (cursor.toNextSibling());\r
+            }\r
+            return;\r
+        }\r
+        Element ele;\r
+        Element toolEle = null;\r
+        if (type.equalsIgnoreCase("COMPRESS") && (toolName == null || toolName.equalsIgnoreCase(""))) {\r
+            mode = MODE_COMPRESS;\r
+            //\r
+            // <gensection sectiontype="EFI_SECTION_COMPRESSION">   \r
+            // \r
+            ele = doc.createElement("gensection");\r
+            ele.setAttribute("sectionType", "EFI_SECTION_COMPRESSION");\r
+            \r
+        } else {\r
+            mode = MODE_GUID_DEFINED;\r
+            //\r
+            // <gensection sectiontype="EFI_SECTION_GUID_DEFINED">\r
+            // \r
+            ele = doc.createElement("gensection");\r
+            if (type != null) {\r
+                if (type.equalsIgnoreCase("COMPRESS")) {\r
+                    ele.setAttribute("sectionType", "EFI_SECTION_COMPRESSION");\r
+                }else {\r
+                    ele.setAttribute("sectiontype", "EFI_SECTION_GUID_DEFINED");    \r
+                }\r
+                \r
+            } else {\r
+                ele.setAttribute("sectiontype", sectType);\r
+            }\r
+            //\r
+            // <tool toolName="${OEMTOOLPATH}\toolname"\r
+            // outputPath = "${DEST_DIR_OUTPUT}">\r
+            //\r
+            toolEle = doc.createElement("tool");\r
+            if (toolName == null || toolName.equalsIgnoreCase("")) {\r
+                toolEle.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
+                                         + File.separatorChar + "GenCRC32Section");\r
+            }else{\r
+                File toolExe = new File(toolName);\r
+                //\r
+                //  If <Tool> element exist, add sub element under <tool> . \r
+                // \r
+                if (toolExe.isAbsolute()) {\r
+                    toolEle.setAttribute("toolName", toolName);\r
+                } else {\r
+                    toolEle.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "bin"\r
+                                         + File.separatorChar + toolName);\r
+                }\r
+            }\r
+            \r
+            toolEle.setAttribute("outputPath", "${DEST_DIR_OUTPUT}");\r
+            ele.appendChild(toolEle);\r
+        }\r
+        if (cursor.toFirstChild()) {\r
+            do {\r
+                if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) {\r
+                    cursor.push();\r
+                    if (toolEle == null) {\r
+                        dealSection(mode, doc, ele, cursor, list);\r
+                    } else {\r
+                        dealSection(mode, doc, toolEle, cursor, list);\r
+                    }\r
+                    \r
+                    cursor.pop();\r
+                } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) {\r
+                    cursor.push();\r
+                    if (toolEle == null) {\r
+                        dealSections(mode, doc, ele, cursor, list);\r
+                    } else {\r
+                        dealSections(mode, doc, toolEle, cursor, list);\r
+                    }\r
+                    \r
+                    cursor.pop();\r
+                }\r
+            } while (cursor.toNextSibling());\r
+        }\r
+        root.appendChild(ele);\r
+    }\r
+    \r
+    /**\r
+      Recursively deal with section.\r
+      \r
+      @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED)\r
+      @param doc Xml Document\r
+      @param root Root Node\r
+      @param cursor Current FFS layout cursor\r
+      @param list List of section type here used\r
+    **/\r
+    private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector<String> list) {\r
+        String type = cursor.getAttributeText(new QName("SectionType"));\r
+        \r
+        //\r
+        // Judge if file is specified? Yes, just use the file, else call Build Macro\r
+        // If fileName is null, means without FileNames specify in FPD file\r
+        //\r
+        String fileName = null;\r
+        cursor.push();\r
+        if (cursor.toFirstChild()) {\r
+            do {\r
+                if (cursor.getName().getLocalPart().equalsIgnoreCase("Filenames")) {\r
+                    cursor.push();\r
+                    if (cursor.toFirstChild()) {\r
+                        do {\r
+                            if (cursor.getName().getLocalPart().equalsIgnoreCase("Filename")) {\r
+                                fileName = cursor.getTextValue();\r
+                            }\r
+                        } while (cursor.toNextSibling());\r
+                    }\r
+                    cursor.pop();\r
+                }\r
+            } while (cursor.toNextSibling());\r
+        }\r
+\r
+        cursor.pop();\r
+        \r
+        if (fileName == null) {\r
+            list.addElement(type);\r
+        }\r
+        if (mode == MODE_GUID_DEFINED) {\r
+            //\r
+            // <input file="${DEST_DIR_OUTPUT}\Bds.pe32"/>\r
+            //\r
+            Element ele = doc.createElement("input");\r
+            if (fileName == null) {\r
+                ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
+            } else {\r
+                ele.setAttribute("file", "${PLATFORM_DIR}" + File.separatorChar + fileName);\r
+            }\r
+            root.appendChild(ele);\r
+        } else {\r
+            //\r
+            // <sectFile fileName= "..."/>\r
+            //\r
+            Element ele = doc.createElement("sectFile");\r
+            if (fileName == null) {\r
+                ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type));\r
+            } else {\r
+                ele.setAttribute("fileName", "${PLATFORM_DIR}" + File.separatorChar + fileName);\r
+            }\r
+            root.appendChild(ele);\r
+        }\r
+    }\r
+\r
+    /**\r
+      Get the corresponding section file suffix.\r
+       \r
+      @param type Section type\r
+      @return Corresponding section file extension\r
+    **/\r
+    private String getSectionExt(String type) {\r
+        for (int i = 0; i < sectionExt.length; i++) {\r
+            if (sectionExt[i][0].equalsIgnoreCase(type)) {\r
+                return sectionExt[i][1];\r
+            }\r
+        }\r
+        return ".sec";\r
+    }\r
+\r
+    /**\r
+      Return the ANT script to call GenFfs Tool.\r
+      \r
+      @return ANT script to call GenFfs Tool\r
+    **/\r
+    public Element getFfsNode() {\r
+        return ffsNode;\r
+    }\r
+}\r