]> git.proxmox.com Git - mirror_edk2.git/blobdiff - Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java
Add one more judgement for modulelist specified but empty.
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / fpd / FpdParserTask.java
index ea287817ee506d5ef56de8a6b671175255a5fca3..b496e32ed5de3ea933167369a1b7573bbc15bb45 100644 (file)
@@ -1,9 +1,9 @@
 /** @file\r
 /** @file\r
- This file is ANT task FpdParserTask. \r
\r
+ This file is ANT task FpdParserTask.\r
+\r
  FpdParserTask is used to parse FPD (Framework Platform Description) and generate\r
  FpdParserTask is used to parse FPD (Framework Platform Description) and generate\r
- build.out.xml. It is for Package or Platform build use. \r
\r
+ build.out.xml. It is for Package or Platform build use.\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
  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
@@ -18,6 +18,7 @@ package org.tianocore.build.fpd;
 import java.io.BufferedWriter;\r
 import java.io.File;\r
 import java.io.FileWriter;\r
 import java.io.BufferedWriter;\r
 import java.io.File;\r
 import java.io.FileWriter;\r
+import java.io.IOException;\r
 import java.util.HashMap;\r
 import java.util.Iterator;\r
 import java.util.LinkedHashMap;\r
 import java.util.HashMap;\r
 import java.util.Iterator;\r
 import java.util.LinkedHashMap;\r
@@ -25,91 +26,79 @@ import java.util.LinkedHashSet;
 import java.util.Map;\r
 import java.util.Set;\r
 import java.util.Vector;\r
 import java.util.Map;\r
 import java.util.Set;\r
 import java.util.Vector;\r
-import java.util.TreeMap;\r
 \r
 import org.apache.tools.ant.BuildException;\r
 import org.apache.tools.ant.Task;\r
 import org.apache.tools.ant.taskdefs.Ant;\r
 import org.apache.tools.ant.taskdefs.Property;\r
 \r
 import org.apache.tools.ant.BuildException;\r
 import org.apache.tools.ant.Task;\r
 import org.apache.tools.ant.taskdefs.Ant;\r
 import org.apache.tools.ant.taskdefs.Property;\r
+import org.apache.xmlbeans.XmlException;\r
 import org.apache.xmlbeans.XmlObject;\r
 \r
 import org.apache.xmlbeans.XmlObject;\r
 \r
+import org.tianocore.common.definitions.EdkDefinitions;\r
+import org.tianocore.common.exception.EdkException;\r
+import org.tianocore.common.logger.EdkLog;\r
+import org.tianocore.pcd.action.ActionMessage;\r
+import org.tianocore.build.FrameworkBuildTask;\r
 import org.tianocore.build.global.GlobalData;\r
 import org.tianocore.build.global.OutputManager;\r
 import org.tianocore.build.global.SurfaceAreaQuery;\r
 import org.tianocore.build.id.FpdModuleIdentification;\r
 import org.tianocore.build.id.ModuleIdentification;\r
 import org.tianocore.build.global.GlobalData;\r
 import org.tianocore.build.global.OutputManager;\r
 import org.tianocore.build.global.SurfaceAreaQuery;\r
 import org.tianocore.build.id.FpdModuleIdentification;\r
 import org.tianocore.build.id.ModuleIdentification;\r
+import org.tianocore.build.id.PackageIdentification;\r
 import org.tianocore.build.id.PlatformIdentification;\r
 import org.tianocore.build.id.PlatformIdentification;\r
-import org.tianocore.pcd.action.ActionMessage;\r
 import org.tianocore.build.pcd.action.PlatformPcdPreprocessActionForBuilding;\r
 import org.tianocore.build.toolchain.ToolChainAttribute;\r
 import org.tianocore.build.toolchain.ToolChainElement;\r
 import org.tianocore.build.toolchain.ToolChainMap;\r
 import org.tianocore.build.pcd.action.PlatformPcdPreprocessActionForBuilding;\r
 import org.tianocore.build.toolchain.ToolChainAttribute;\r
 import org.tianocore.build.toolchain.ToolChainElement;\r
 import org.tianocore.build.toolchain.ToolChainMap;\r
-import org.tianocore.exception.EdkException;\r
+import org.w3c.dom.NamedNodeMap;\r
+import org.w3c.dom.Node;\r
+import org.w3c.dom.NodeList;\r
 \r
 /**\r
   <code>FpdParserTask</code> is an ANT task. The main function is parsing Framework\r
 \r
 /**\r
   <code>FpdParserTask</code> is an ANT task. The main function is parsing Framework\r
-  Platform Descritpion (FPD) XML file and generating its ANT build script for \r
-  corresponding platform.  \r
+  Platform Descritpion (FPD) XML file and generating its ANT build script for\r
+  corresponding platform.\r
 \r
   <p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR\r
   and BUILD_DIR. </p>\r
 \r
   <p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR\r
   and BUILD_DIR. </p>\r
-  \r
+\r
   <p>The task generates ${PLATFORM}_build.xml file which will be called by top level\r
   <p>The task generates ${PLATFORM}_build.xml file which will be called by top level\r
-  build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage) \r
-  and flash definition file (File is for Tool FlashMap) if necessary. </p>\r
-  \r
+  build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage). </p>\r
+\r
   <p>FpdParserTask task stores all FPD information to GlobalData. And parse\r
   tools definition file to set up compiler options for different Target and\r
   different ToolChainTag. </p>\r
   <p>FpdParserTask task stores all FPD information to GlobalData. And parse\r
   tools definition file to set up compiler options for different Target and\r
   different ToolChainTag. </p>\r
-  \r
-  <p>The method parseFpdFile is also prepared for single module build. </p>\r
-  \r
-  <p>The usage is (take NT32 Platform for example):</p>\r
-\r
-  <pre>\r
-  &lt;FPDParser platformName="Nt32" /&gt;\r
-  </pre>\r
 \r
 \r
-  <p>The task will initialize all information through parsing Framework Database, \r
-  SPD, Tool chain configuration files. </p>\r
+  <p>The method parseFpdFile is also prepared for single module build. </p>\r
 \r
   @since GenBuild 1.0\r
 **/\r
 public class FpdParserTask extends Task {\r
 \r
   @since GenBuild 1.0\r
 **/\r
 public class FpdParserTask extends Task {\r
-    \r
-    private String platformName;\r
 \r
     private File fpdFile = null;\r
 \r
     private File fpdFile = null;\r
-    \r
-    private PlatformIdentification platformId;\r
-    \r
-    ///\r
-    /// \r
-    ///\r
+\r
+    PlatformIdentification platformId;\r
+\r
     private String type;\r
     private String type;\r
-    \r
+\r
     ///\r
     /// Mapping from modules identification to out put file name\r
     ///\r
     ///\r
     /// Mapping from modules identification to out put file name\r
     ///\r
-    private Map<FpdModuleIdentification, String> outfiles = new LinkedHashMap<FpdModuleIdentification, String>();\r
+    Map<FpdModuleIdentification, String> outfiles = new LinkedHashMap<FpdModuleIdentification, String>();\r
 \r
     ///\r
     /// Mapping from FV name to its modules\r
     ///\r
 \r
     ///\r
     /// Mapping from FV name to its modules\r
     ///\r
-    private Map<String, Set<FpdModuleIdentification>> fvs = new HashMap<String, Set<FpdModuleIdentification>>();\r
-\r
-    ///\r
-    /// Mapping from sequence number to FV names\r
-    ///\r
-    private Map<String, Set<String>> sequences = new TreeMap<String, Set<String>>();\r
+    Map<String, Set<FpdModuleIdentification>> fvs = new HashMap<String, Set<FpdModuleIdentification>>();\r
 \r
     ///\r
 \r
     ///\r
-    /// FpdParserTask can specify some ANT properties. \r
+    /// FpdParserTask can specify some ANT properties.\r
     ///\r
     private Vector<Property> properties = new Vector<Property>();\r
     ///\r
     private Vector<Property> properties = new Vector<Property>();\r
-    \r
-    private boolean isUnified = true;\r
 \r
 \r
+    SurfaceAreaQuery saq = null;\r
+    \r
+    boolean isUnified = true;\r
 \r
     /**\r
       Public construct method. It is necessary for ANT task.\r
 \r
     /**\r
       Public construct method. It is necessary for ANT task.\r
@@ -118,61 +107,51 @@ public class FpdParserTask extends Task {
     }\r
 \r
     /**\r
     }\r
 \r
     /**\r
-     ANT task's entry method. The main steps is described as following: \r
-     \r
+     ANT task's entry method. The main steps is described as following:\r
+\r
      <ul>\r
      <ul>\r
-     <li>Initialize global information (Framework DB, SPD files and all MSA files \r
+     <li>Initialize global information (Framework DB, SPD files and all MSA files\r
      listed in SPD). This step will execute only once in whole build process;</li>\r
      <li>Parse specified FPD file; </li>\r
      <li>Generate FV.inf files; </li>\r
      <li>Generate PlatformName_build.xml file for Flatform build; </li>\r
      <li>Collect PCD information. </li>\r
      </ul>\r
      listed in SPD). This step will execute only once in whole build process;</li>\r
      <li>Parse specified FPD file; </li>\r
      <li>Generate FV.inf files; </li>\r
      <li>Generate PlatformName_build.xml file for Flatform build; </li>\r
      <li>Collect PCD information. </li>\r
      </ul>\r
-     \r
+\r
      @throws BuildException\r
      @throws BuildException\r
-     Surface area is not valid. \r
+     Surface area is not valid.\r
     **/\r
     public void execute() throws BuildException {\r
     **/\r
     public void execute() throws BuildException {\r
-        // Remove !!\r
-        if ( fpdFile == null) {\r
-            if (platformName == null) {\r
-                throw new BuildException("FpdParserTask parameter error. Please specify platform name or FPD file. ");\r
-            }\r
-            platformId = GlobalData.getPlatformByName(platformName);\r
-            fpdFile = platformId.getFpdFile();\r
-        }\r
+        this.setTaskName("FpdParser");\r
         \r
         //\r
         // Parse FPD file\r
         //\r
         parseFpdFile();\r
         \r
         //\r
         // Parse FPD file\r
         //\r
         parseFpdFile();\r
-        \r
+\r
         //\r
         // Prepare BUILD_DIR\r
         //\r
         isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
         //\r
         // Prepare BUILD_DIR\r
         //\r
         isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
-        \r
-        //\r
-        // Generate FDF (Flash Definition File) file\r
-        //\r
 \r
 \r
+        String buildDir = getProject().getProperty("BUILD_DIR");\r
         //\r
         // For every Target and ToolChain\r
         //\r
         String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
         //\r
         // For every Target and ToolChain\r
         //\r
         String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
-        for (int i = 0; i < targetList.length; i++){\r
+        for (int i = 0; i < targetList.length; i++) {\r
             String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
             String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
-            for(int j = 0; j < toolchainList.length; j++){\r
+            for(int j = 0; j < toolchainList.length; j++) {\r
                 //\r
                 // Prepare FV_DIR\r
                 //\r
                 //\r
                 // Prepare FV_DIR\r
                 //\r
-                String ffsCommonDir = getProject().getProperty("BUILD_DIR") + File.separatorChar \r
-                                + targetList[i] + File.separatorChar \r
+                String ffsCommonDir = buildDir + File.separatorChar\r
+                                + targetList[i] + "_"\r
                                 + toolchainList[j];\r
                 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");\r
                 fvDir.mkdirs();\r
                 getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));\r
                                 + toolchainList[j];\r
                 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");\r
                 fvDir.mkdirs();\r
                 getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));\r
-                \r
+\r
                 //\r
                 // Gen Fv.inf files\r
                 //\r
                 //\r
                 // Gen Fv.inf files\r
                 //\r
@@ -183,56 +162,60 @@ public class FpdParserTask extends Task {
         //\r
         // Gen build.xml\r
         //\r
         //\r
         // Gen build.xml\r
         //\r
-        PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, sequences, isUnified);\r
+        String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";\r
+        PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile);\r
         fileGenerator.genBuildFile();\r
         fileGenerator.genBuildFile();\r
-        \r
+\r
         //\r
         // Ant call ${PLATFORM}_build.xml\r
         //\r
         //\r
         // Ant call ${PLATFORM}_build.xml\r
         //\r
-        \r
         Ant ant = new Ant();\r
         ant.setProject(getProject());\r
         Ant ant = new Ant();\r
         ant.setProject(getProject());\r
-        ant.setAntfile(platformId.getFpdFile().getParent() + File.separatorChar + platformId.getName() + "_build.xml");\r
+        ant.setAntfile(platformBuildFile);\r
         ant.setTarget(type);\r
         ant.setInheritAll(true);\r
         ant.init();\r
         ant.execute();\r
         ant.setTarget(type);\r
         ant.setInheritAll(true);\r
         ant.init();\r
         ant.execute();\r
-        \r
-//        GlobalData.log.info("Fpd build end. ");\r
     }\r
 \r
     /**\r
     }\r
 \r
     /**\r
-      Generate Fv.inf files. The Fv.inf file is composed with four \r
-      parts: Options, Attributes, Components and Files. The Fv.inf files \r
+      Generate Fv.inf files. The Fv.inf file is composed with four\r
+      parts: Options, Attributes, Components and Files. The Fv.inf files\r
       will be under FV_DIR.\r
       will be under FV_DIR.\r
-     \r
+\r
       @throws BuildException\r
       @throws BuildException\r
-                  File write FV.inf files error. \r
+                  File write FV.inf files error.\r
     **/\r
     **/\r
-    private void genFvInfFiles(String ffsCommonDir) throws BuildException {\r
-        String[] validFv = SurfaceAreaQuery.getFpdValidImageNames();\r
+    void genFvInfFiles(String ffsCommonDir) throws BuildException {\r
+        String[] validFv = saq.getFpdValidImageNames();\r
         for (int i = 0; i < validFv.length; i++) {\r
             //\r
             // Get all global variables from FPD and set them to properties\r
             //\r
         for (int i = 0; i < validFv.length; i++) {\r
             //\r
             // Get all global variables from FPD and set them to properties\r
             //\r
-            String[][] globalVariables = SurfaceAreaQuery.getFpdGlobalVariable();\r
+            String[][] globalVariables = saq.getFpdGlobalVariable();\r
             for (int j = 0; j < globalVariables.length; j++) {\r
                 getProject().setProperty(globalVariables[j][0], globalVariables[j][1]);\r
             }\r
 \r
             getProject().setProperty("FV_FILENAME", validFv[i]);\r
             for (int j = 0; j < globalVariables.length; j++) {\r
                 getProject().setProperty(globalVariables[j][0], globalVariables[j][1]);\r
             }\r
 \r
             getProject().setProperty("FV_FILENAME", validFv[i]);\r
-            \r
+\r
             File fvFile = new File(getProject().replaceProperties( getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".inf"));\r
             File fvFile = new File(getProject().replaceProperties( getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".inf"));\r
+            if (fvFile.exists() && (fvFile.lastModified() >= fpdFile.lastModified())) {\r
+                //\r
+                // don't re-generate FV.inf if fpd has not been changed\r
+                // \r
+                continue;\r
+            }\r
             fvFile.getParentFile().mkdirs();\r
 \r
             try {\r
                 FileWriter fw = new FileWriter(fvFile);\r
                 BufferedWriter bw = new BufferedWriter(fw);\r
             fvFile.getParentFile().mkdirs();\r
 \r
             try {\r
                 FileWriter fw = new FileWriter(fvFile);\r
                 BufferedWriter bw = new BufferedWriter(fw);\r
-                \r
+\r
                 //\r
                 // Options\r
                 //\r
                 //\r
                 // Options\r
                 //\r
-                String[][] options = SurfaceAreaQuery.getFpdOptions(validFv[i]);\r
+                String[][] options = saq.getFpdOptions(validFv[i]);\r
                 if (options.length > 0) {\r
                     bw.write("[options]");\r
                     bw.newLine();\r
                 if (options.length > 0) {\r
                     bw.write("[options]");\r
                     bw.newLine();\r
@@ -249,11 +232,11 @@ public class FpdParserTask extends Task {
                     }\r
                     bw.newLine();\r
                 }\r
                     }\r
                     bw.newLine();\r
                 }\r
-                \r
+\r
                 //\r
                 // Attributes;\r
                 //\r
                 //\r
                 // Attributes;\r
                 //\r
-                String[][] attributes = SurfaceAreaQuery.getFpdAttributes(validFv[i]);\r
+                String[][] attributes = saq.getFpdAttributes(validFv[i]);\r
                 if (attributes.length > 0) {\r
                     bw.write("[attributes]");\r
                     bw.newLine();\r
                 if (attributes.length > 0) {\r
                     bw.write("[attributes]");\r
                     bw.newLine();\r
@@ -270,11 +253,11 @@ public class FpdParserTask extends Task {
                     }\r
                     bw.newLine();\r
                 }\r
                     }\r
                     bw.newLine();\r
                 }\r
-                \r
+\r
                 //\r
                 // Components\r
                 //\r
                 //\r
                 // Components\r
                 //\r
-                String[][] components = SurfaceAreaQuery.getFpdComponents(validFv[i]);\r
+                String[][] components = saq.getFpdComponents(validFv[i]);\r
                 if (components.length > 0) {\r
                     bw.write("[components]");\r
                     bw.newLine();\r
                 if (components.length > 0) {\r
                     bw.write("[components]");\r
                     bw.newLine();\r
@@ -295,9 +278,44 @@ public class FpdParserTask extends Task {
                 //\r
                 // Files\r
                 //\r
                 //\r
                 // Files\r
                 //\r
+                Set<FpdModuleIdentification> moduleSeqSet = getModuleSequenceForFv(validFv[i]);\r
+                \r
                 Set<FpdModuleIdentification> filesSet = fvs.get(validFv[i]);\r
                 Set<FpdModuleIdentification> filesSet = fvs.get(validFv[i]);\r
-                if (filesSet != null) {\r
-                    FpdModuleIdentification[] files = filesSet.toArray(new FpdModuleIdentification[filesSet.size()]);\r
+                \r
+                FpdModuleIdentification[] files = null;\r
+                \r
+                if (moduleSeqSet == null) {\r
+                    if (filesSet != null) {\r
+                        files = filesSet.toArray(new FpdModuleIdentification[filesSet.size()]);\r
+                    }\r
+                } else if (filesSet == null) {\r
+                    if (moduleSeqSet.size() != 0) {\r
+                        throw new BuildException("Can not find any modules belongs to FV[" + validFv[i] + "], but listed some in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1']");\r
+                    }\r
+                } else {\r
+                    //\r
+                    // if moduleSeqSet and filesSet is inconsistent, report error\r
+                    //\r
+                    if(moduleSeqSet.size() != filesSet.size()){\r
+                        throw new BuildException("Modules for FV[" + validFv[i] + "] defined in FrameworkModules and in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1'] are inconsistent. ");\r
+                    } else {\r
+                        //\r
+                        // whether all modules in moduleSeqSet listed in filesSet\r
+                        //\r
+                        Iterator<FpdModuleIdentification> iter = moduleSeqSet.iterator();\r
+                        while (iter.hasNext()) {\r
+                            FpdModuleIdentification item = iter.next();\r
+                            if (!filesSet.contains(item)) {\r
+                                throw new BuildException("Can not find " + item + " belongs to FV[" + validFv[i] + "]");\r
+                            }\r
+                        }\r
+                    }\r
+                    \r
+                    files = moduleSeqSet.toArray(new FpdModuleIdentification[moduleSeqSet.size()]);\r
+                }\r
+                \r
+                \r
+                if (files != null) {\r
                     bw.write("[files]");\r
                     bw.newLine();\r
                     for (int j = 0; j < files.length; j++) {\r
                     bw.write("[files]");\r
                     bw.newLine();\r
                     for (int j = 0; j < files.length; j++) {\r
@@ -309,66 +327,116 @@ public class FpdParserTask extends Task {
                 bw.flush();\r
                 bw.close();\r
                 fw.close();\r
                 bw.flush();\r
                 bw.close();\r
                 fw.close();\r
-            } catch (Exception e) {\r
-                throw new BuildException("Generate FV file [" + fvFile.getPath() + "] failed. \n" + e.getMessage());\r
+            } catch (IOException ex) {\r
+                BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage());\r
+                buildException.setStackTrace(ex.getStackTrace());\r
+                throw buildException;\r
+            } catch (EdkException ex) {\r
+                BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage());\r
+                buildException.setStackTrace(ex.getStackTrace());\r
+                throw buildException;\r
             }\r
         }\r
     }\r
     /**\r
       This method is used for Single Module Build.\r
             }\r
         }\r
     }\r
     /**\r
       This method is used for Single Module Build.\r
-      \r
-      \r
+\r
+\r
       @throws BuildException\r
       @throws BuildException\r
-                  FPD file is not valid. \r
+                  FPD file is not valid.\r
     **/\r
     **/\r
-    public void parseFpdFile(File fpdFile) throws BuildException {\r
+    public void parseFpdFile(File fpdFile) throws BuildException, EdkException {\r
         this.fpdFile = fpdFile;\r
         parseFpdFile();\r
         this.fpdFile = fpdFile;\r
         parseFpdFile();\r
+        \r
+        //\r
+        // Call Platform_build.xml prebuild firstly in stand-alone build\r
+        // Prepare BUILD_DIR\r
+        //\r
+        isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
+\r
+        String buildDir = getProject().getProperty("BUILD_DIR");\r
+        //\r
+        // For every Target and ToolChain\r
+        //\r
+        String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
+        for (int i = 0; i < targetList.length; i++) {\r
+            String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
+            for(int j = 0; j < toolchainList.length; j++) {\r
+                //\r
+                // Prepare FV_DIR\r
+                //\r
+                String ffsCommonDir = buildDir + File.separatorChar\r
+                                + targetList[i] + "_"\r
+                                + toolchainList[j];\r
+                File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");\r
+                fvDir.mkdirs();\r
+            }\r
+        }\r
+\r
+        String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";\r
+        PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile);\r
+        fileGenerator.genBuildFile();\r
+        \r
+        Ant ant = new Ant();\r
+        ant.setProject(getProject());\r
+        ant.setAntfile(platformBuildFile);\r
+        ant.setTarget("prebuild");\r
+        ant.setInheritAll(true);\r
+        ant.init();\r
+        ant.execute();\r
     }\r
 \r
     /**\r
     }\r
 \r
     /**\r
-      Parse FPD file. \r
-     \r
+      Parse FPD file.\r
+\r
       @throws BuildException\r
       @throws BuildException\r
-                  FPD file is not valid. \r
+                  FPD file is not valid.\r
      **/\r
      **/\r
-    private void parseFpdFile() throws BuildException {\r
+    void parseFpdFile() throws BuildException {\r
         try {\r
             XmlObject doc = XmlObject.Factory.parse(fpdFile);\r
         try {\r
             XmlObject doc = XmlObject.Factory.parse(fpdFile);\r
-            \r
+\r
             if (!doc.validate()) {\r
             if (!doc.validate()) {\r
-                throw new BuildException("Platform Surface Area file [" + fpdFile.getPath() + "] is invalid.");\r
+                throw new BuildException("Platform Surface Area file [" + fpdFile.getPath() + "] format is invalid!");\r
             }\r
             }\r
-            \r
+\r
             Map<String, XmlObject> map = new HashMap<String, XmlObject>();\r
             map.put("PlatformSurfaceArea", doc);\r
             Map<String, XmlObject> map = new HashMap<String, XmlObject>();\r
             map.put("PlatformSurfaceArea", doc);\r
-            SurfaceAreaQuery.setDoc(map);\r
+            saq = new SurfaceAreaQuery(map);\r
 \r
             //\r
             // Initialize\r
             //\r
 \r
             //\r
             // Initialize\r
             //\r
-            platformId = SurfaceAreaQuery.getFpdHeader();\r
+            platformId = saq.getFpdHeader();\r
             platformId.setFpdFile(fpdFile);\r
             getProject().setProperty("PLATFORM", platformId.getName());\r
             getProject().setProperty("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));\r
             getProject().setProperty("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));\r
             getProject().setProperty("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));\r
             platformId.setFpdFile(fpdFile);\r
             getProject().setProperty("PLATFORM", platformId.getName());\r
             getProject().setProperty("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));\r
             getProject().setProperty("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));\r
             getProject().setProperty("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));\r
+            \r
+            if( !FrameworkBuildTask.multithread) {\r
+                FrameworkBuildTask.originalProperties.put("PLATFORM", platformId.getName());\r
+                FrameworkBuildTask.originalProperties.put("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));\r
+                FrameworkBuildTask.originalProperties.put("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));\r
+                FrameworkBuildTask.originalProperties.put("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));\r
+            }\r
 \r
             //\r
 \r
             //\r
-            // Build mode. User-defined output dir. \r
+            // Build mode. User-defined output dir.\r
             //\r
             //\r
-            String buildMode = SurfaceAreaQuery.getFpdIntermediateDirectories();\r
-            String userDefinedOutputDir = SurfaceAreaQuery.getFpdOutputDirectory();\r
+            String buildMode = saq.getFpdIntermediateDirectories();\r
+            String userDefinedOutputDir = saq.getFpdOutputDirectory();\r
 \r
             OutputManager.getInstance().setup(userDefinedOutputDir, buildMode);\r
 \r
             //\r
             // TBD. Deal PCD and BuildOption related Info\r
             //\r
 \r
             OutputManager.getInstance().setup(userDefinedOutputDir, buildMode);\r
 \r
             //\r
             // TBD. Deal PCD and BuildOption related Info\r
             //\r
-            GlobalData.setFpdBuildOptions(SurfaceAreaQuery.getFpdBuildOptions());\r
-            \r
-            GlobalData.setToolChainPlatformInfo(SurfaceAreaQuery.getFpdToolChainInfo());\r
-            \r
+            GlobalData.setFpdBuildOptions(saq.getFpdBuildOptions());\r
+\r
+            GlobalData.setToolChainPlatformInfo(saq.getFpdToolChainInfo());\r
+\r
             //\r
             // Parse all list modules SA\r
             //\r
             //\r
             // Parse all list modules SA\r
             //\r
@@ -380,29 +448,33 @@ public class FpdParserTask extends Task {
             parseToolChainFamilyOptions();\r
             parseToolChainOptions();\r
 \r
             parseToolChainFamilyOptions();\r
             parseToolChainOptions();\r
 \r
-            SurfaceAreaQuery.setDoc(map);\r
-            \r
+            saq.push(map);\r
+\r
             //\r
             // Pcd Collection. Call CollectPCDAction to collect pcd info.\r
             //\r
             //\r
             // Pcd Collection. Call CollectPCDAction to collect pcd info.\r
             //\r
-            try {\r
-                PlatformPcdPreprocessActionForBuilding ca = new PlatformPcdPreprocessActionForBuilding();\r
-                ca.perform(GlobalData.getWorkspacePath(),platformId.getFpdFile().getPath(),ActionMessage.NULL_MESSAGE_LEVEL);\r
-            } catch (Exception e){\r
-                throw new BuildException(e.getMessage());\r
-            }\r
-        } catch (Exception e) {\r
-            throw new BuildException("Load FPD file [" + fpdFile.getPath() + "] error. \n" + e.getMessage());\r
+            PlatformPcdPreprocessActionForBuilding ca = new PlatformPcdPreprocessActionForBuilding();\r
+            ca.perform(platformId.getFpdFile().getPath(), ActionMessage.NULL_MESSAGE_LEVEL);\r
+        } catch (IOException ex) {\r
+            BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());\r
+            buildException.setStackTrace(ex.getStackTrace());\r
+            throw buildException;\r
+        } catch (XmlException ex) {\r
+            BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());\r
+            buildException.setStackTrace(ex.getStackTrace());\r
+            throw buildException;\r
+        } catch (EdkException ex) {\r
+            BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());\r
+            buildException.setStackTrace(ex.getStackTrace());\r
+            throw buildException;\r
         }\r
     }\r
 \r
         }\r
     }\r
 \r
-\r
-    \r
     /**\r
     /**\r
-      Parse all modules listed in FPD file. \r
+      Parse all modules listed in FPD file.\r
     **/\r
     **/\r
-    private void parseModuleSAFiles() throws EdkException{\r
-        Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = SurfaceAreaQuery.getFpdModules();\r
+    void parseModuleSAFiles() throws EdkException{\r
+        Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();\r
 \r
         //\r
         // For every Module lists in FPD file.\r
 \r
         //\r
         // For every Module lists in FPD file.\r
@@ -411,60 +483,56 @@ public class FpdParserTask extends Task {
         Iterator iter = keys.iterator();\r
         while (iter.hasNext()) {\r
             FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();\r
         Iterator iter = keys.iterator();\r
         while (iter.hasNext()) {\r
             FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();\r
-            \r
+\r
             //\r
             //\r
-            // Judge if Module is existed? \r
+            // Judge if Module is existed?\r
             // TBD\r
             // TBD\r
-            \r
             GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));\r
 \r
             //\r
             // Put fpdModuleId to the corresponding FV\r
             //\r
             GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));\r
 \r
             //\r
             // Put fpdModuleId to the corresponding FV\r
             //\r
-            SurfaceAreaQuery.push(GlobalData.getDoc(fpdModuleId));\r
-            String fvBinding = SurfaceAreaQuery.getModuleFvBindingKeyword();\r
-            SurfaceAreaQuery.pop();\r
+            saq.push(GlobalData.getDoc(fpdModuleId));\r
+            String fvBinding = saq.getModuleFvBindingKeyword();\r
 \r
             fpdModuleId.setFvBinding(fvBinding);\r
 \r
             fpdModuleId.setFvBinding(fvBinding);\r
-            String fvSequence = fpdModuleId.getSequence();\r
-            updateFvs(fvSequence, fvBinding, fpdModuleId);\r
-            \r
+            updateFvs(fvBinding, fpdModuleId);\r
+\r
             //\r
             // Prepare for out put file name\r
             //\r
             ModuleIdentification moduleId = fpdModuleId.getModule();\r
             //\r
             // Prepare for out put file name\r
             //\r
             ModuleIdentification moduleId = fpdModuleId.getModule();\r
-            SurfaceAreaQuery.push(GlobalData.getDoc(fpdModuleId));\r
-            String baseName = SurfaceAreaQuery.getModuleOutputFileBasename();\r
-            SurfaceAreaQuery.pop();\r
+\r
+            String baseName = saq.getModuleOutputFileBasename();\r
+            \r
             if (baseName == null) {\r
                 baseName = moduleId.getName();\r
             }\r
             if (baseName == null) {\r
                 baseName = moduleId.getName();\r
             }\r
-            outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar \r
-                         + moduleId.getGuid() + "-" + baseName \r
+            outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar\r
+                         + moduleId.getGuid() + "-" + baseName\r
                          + getSuffix(moduleId.getModuleType()));\r
 \r
             //\r
             // parse module build options, if any\r
                          + getSuffix(moduleId.getModuleType()));\r
 \r
             //\r
             // parse module build options, if any\r
-            // \r
-            SurfaceAreaQuery.push(GlobalData.getDoc(fpdModuleId));\r
+            //\r
             GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));\r
             GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));\r
             GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));\r
             GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));\r
-            SurfaceAreaQuery.pop();\r
+            saq.pop();\r
         }\r
     }\r
 \r
         }\r
     }\r
 \r
-    private ToolChainMap parseModuleBuildOptions(boolean toolChainFamilyFlag) throws EdkException {\r
-        String[][] options = SurfaceAreaQuery.getModuleBuildOptions(toolChainFamilyFlag);\r
+    ToolChainMap parseModuleBuildOptions(boolean toolChainFamilyFlag) throws EdkException {\r
+        String[][] options = saq.getModuleBuildOptions(toolChainFamilyFlag);\r
         if (options == null || options.length == 0) {\r
         if (options == null || options.length == 0) {\r
-            return null;\r
+            return new ToolChainMap();\r
         }\r
         return parseOptions(options);\r
     }\r
         }\r
         return parseOptions(options);\r
     }\r
-    \r
+\r
     private ToolChainMap parsePlatformBuildOptions(boolean toolChainFamilyFlag) throws EdkException {\r
     private ToolChainMap parsePlatformBuildOptions(boolean toolChainFamilyFlag) throws EdkException {\r
-        String[][] options = SurfaceAreaQuery.getPlatformBuildOptions(toolChainFamilyFlag);\r
+        String[][] options = saq.getPlatformBuildOptions(toolChainFamilyFlag);\r
         if (options == null || options.length == 0) {\r
         if (options == null || options.length == 0) {\r
-            return null;\r
+            return new ToolChainMap();\r
         }\r
         return parseOptions(options);\r
     }\r
         }\r
         return parseOptions(options);\r
     }\r
@@ -484,7 +552,7 @@ public class FpdParserTask extends Task {
 \r
         return map;\r
     }\r
 \r
         return map;\r
     }\r
-    \r
+\r
     private void parseToolChainFamilyOptions() throws EdkException {\r
         GlobalData.setPlatformToolChainFamilyOption(parsePlatformBuildOptions(true));\r
     }\r
     private void parseToolChainFamilyOptions() throws EdkException {\r
         GlobalData.setPlatformToolChainFamilyOption(parsePlatformBuildOptions(true));\r
     }\r
@@ -494,12 +562,12 @@ public class FpdParserTask extends Task {
     }\r
 \r
     /**\r
     }\r
 \r
     /**\r
-      Add the current module to corresponding FV. \r
-     \r
+      Add the current module to corresponding FV.\r
+\r
       @param fvName current FV name\r
       @param moduleName current module identification\r
     **/\r
       @param fvName current FV name\r
       @param moduleName current module identification\r
     **/\r
-    private void updateFvs(String fvSequence, String fvName, FpdModuleIdentification fpdModuleId) {\r
+    void updateFvs(String fvName, FpdModuleIdentification fpdModuleId) {\r
         if (fvName == null || fvName.trim().length() == 0) {\r
             fvName = "NULL";\r
         }\r
         if (fvName == null || fvName.trim().length() == 0) {\r
             fvName = "NULL";\r
         }\r
@@ -511,31 +579,17 @@ public class FpdParserTask extends Task {
             if (fvs.containsKey(fvNameArray[i])) {\r
                 Set<FpdModuleIdentification> set = fvs.get(fvNameArray[i]);\r
                 set.add(fpdModuleId);\r
             if (fvs.containsKey(fvNameArray[i])) {\r
                 Set<FpdModuleIdentification> set = fvs.get(fvNameArray[i]);\r
                 set.add(fpdModuleId);\r
-            }\r
-            else {\r
+            } else {\r
                 Set<FpdModuleIdentification> set = new LinkedHashSet<FpdModuleIdentification>();\r
                 set.add(fpdModuleId);\r
                 fvs.put(fvNameArray[i], set);\r
             }\r
                 Set<FpdModuleIdentification> set = new LinkedHashSet<FpdModuleIdentification>();\r
                 set.add(fpdModuleId);\r
                 fvs.put(fvNameArray[i], set);\r
             }\r
-            \r
-            //\r
-            // Put fvName to corresponding fvSequence\r
-            //\r
-            if (sequences.containsKey(fvSequence)) {\r
-                Set<String> set = sequences.get(fvSequence);\r
-                set.add(fvNameArray[i]);\r
-            }\r
-            else {\r
-                Set<String> set = new LinkedHashSet<String>();\r
-                set.add(fvNameArray[i]);\r
-                sequences.put(fvSequence, set);\r
-            }\r
         }\r
     }\r
 \r
     /**\r
         }\r
     }\r
 \r
     /**\r
-      Get the suffix based on module type. Current relationship are listed:  \r
-      \r
+      Get the suffix based on module type. Current relationship are listed:\r
+\r
       <pre>\r
       <b>ModuleType</b>     <b>Suffix</b>\r
       BASE                 .FFS\r
       <pre>\r
       <b>ModuleType</b>     <b>Suffix</b>\r
       BASE                 .FFS\r
@@ -552,7 +606,7 @@ public class FpdParserTask extends Task {
       UEFI_APPLICATION     .APP\r
       USER_DEFINED         .FFS\r
       </pre>\r
       UEFI_APPLICATION     .APP\r
       USER_DEFINED         .FFS\r
       </pre>\r
-     \r
+\r
       @param moduleType module type\r
       @return\r
       @throws BuildException\r
       @param moduleType module type\r
       @return\r
       @throws BuildException\r
@@ -563,14 +617,8 @@ public class FpdParserTask extends Task {
             throw new BuildException("Module type is not specified.");\r
         }\r
 \r
             throw new BuildException("Module type is not specified.");\r
         }\r
 \r
-        String[][] suffix = { { "BASE", ".FFS"},\r
-                              { "SEC", ".SEC" }, { "PEI_CORE", ".PEI" }, \r
-                              { "PEIM", ".PEI" }, { "DXE_CORE", ".DXE" },\r
-                              { "DXE_DRIVER", ".DXE" }, { "DXE_RUNTIME_DRIVER", ".DXE" }, \r
-                              { "DXE_SAL_DRIVER", ".DXE" }, { "DXE_SMM_DRIVER", ".DXE" }, \r
-                              { "TOOL", ".FFS" }, { "UEFI_DRIVER", ".DXE" },\r
-                              { "UEFI_APPLICATION", ".APP" }, { "USER_DEFINED", ".FFS" } };\r
-        \r
+        String[][] suffix = EdkDefinitions.ModuleTypeExtensions;\r
+\r
         for (int i = 0; i < suffix.length; i++) {\r
             if (suffix[i][0].equalsIgnoreCase(moduleType)) {\r
                 return suffix[i][1];\r
         for (int i = 0; i < suffix.length; i++) {\r
             if (suffix[i][0].equalsIgnoreCase(moduleType)) {\r
                 return suffix[i][1];\r
@@ -582,18 +630,14 @@ public class FpdParserTask extends Task {
         return ".FFS";\r
     }\r
     /**\r
         return ".FFS";\r
     }\r
     /**\r
-     Add a property. \r
-     \r
+     Add a property.\r
+\r
      @param p property\r
      **/\r
     public void addProperty(Property p) {\r
         properties.addElement(p);\r
     }\r
 \r
      @param p property\r
      **/\r
     public void addProperty(Property p) {\r
         properties.addElement(p);\r
     }\r
 \r
-    public void setPlatformName(String platformName) {\r
-        this.platformName = platformName;\r
-    }\r
-\r
     public void setFpdFile(File fpdFile) {\r
         this.fpdFile = fpdFile;\r
     }\r
     public void setFpdFile(File fpdFile) {\r
         this.fpdFile = fpdFile;\r
     }\r
@@ -602,5 +646,112 @@ public class FpdParserTask extends Task {
         this.type = type;\r
     }\r
     \r
         this.type = type;\r
     }\r
     \r
-\r
+    public String getAllArchForModule(ModuleIdentification moduleId) {\r
+        String archs = "";\r
+        Iterator<FpdModuleIdentification> iter = outfiles.keySet().iterator();\r
+        while (iter.hasNext()) {\r
+            FpdModuleIdentification fpdModuleId = iter.next();\r
+            \r
+            if (fpdModuleId.getModule().equals(moduleId)) {\r
+                archs += fpdModuleId.getArch() + " ";\r
+            }\r
+        }\r
+        \r
+        return archs;\r
+    }\r
+    \r
+    private Set<FpdModuleIdentification> getModuleSequenceForFv(String fvName) throws EdkException {\r
+        Node node = saq.getFpdModuleSequence(fvName);\r
+        Set<FpdModuleIdentification> result = new LinkedHashSet<FpdModuleIdentification>();\r
+        \r
+        if ( node == null) {\r
+            EdkLog.log(this, EdkLog.EDK_WARNING, "FV[" + fvName + "] does not specify module sequence in FPD. Assuming present sequence as default sequence in FV. ");\r
+            return null;\r
+        } else {\r
+            NodeList childNodes = node.getChildNodes();\r
+            for (int i = 0; i < childNodes.getLength(); i++) {\r
+                Node childItem = childNodes.item(i);\r
+                if (childItem.getNodeType() == Node.ELEMENT_NODE) {\r
+                    //\r
+                    // Find child elements "IncludeModules"\r
+                    //\r
+                    if (childItem.getNodeName().compareTo("IncludeModules") == 0) {\r
+                        //\r
+                        // result will be updated\r
+                        //\r
+                        processNodes(childItem, result);\r
+                    } else if (childItem.getNodeName().compareTo("FvName") == 0) {\r
+                        \r
+                    } else if (childItem.getNodeName().compareTo("InfFileName") == 0) {\r
+                        \r
+                    } else {\r
+                        //\r
+                        // Report Warning\r
+                        //\r
+                        EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1']");\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        \r
+        return result;\r
+    }\r
+    \r
+    private void processNodes(Node node, Set<FpdModuleIdentification> result) throws EdkException {\r
+        //\r
+        // Found out all elements "Module"\r
+        //\r
+        NodeList childNodes = node.getChildNodes();\r
+        for (int j = 0; j < childNodes.getLength(); j++) {\r
+            Node childItem = childNodes.item(j);\r
+            if (childItem.getNodeType() == Node.ELEMENT_NODE) {\r
+                if (childItem.getNodeName().compareTo("Module") == 0) {\r
+                    String moduleGuid = null;\r
+                    String moduleVersion = null;\r
+                    String packageGuid = null;\r
+                    String packageVersion = null;\r
+                    String arch = null;\r
+                    \r
+                    NamedNodeMap attr = childItem.getAttributes();\r
+                    for (int i = 0; i < attr.getLength(); i++) {\r
+                        Node attrItem = attr.item(i);\r
+                        if (attrItem.getNodeName().compareTo("ModuleGuid") == 0) {\r
+                            moduleGuid = attrItem.getNodeValue();\r
+                        } else if (attrItem.getNodeName().compareTo("ModuleVersion") == 0) {\r
+                            moduleVersion = attrItem.getNodeValue();\r
+                        } else if (attrItem.getNodeName().compareTo("PackageGuid") == 0) {\r
+                            packageGuid = attrItem.getNodeValue();\r
+                        } else if (attrItem.getNodeName().compareTo("PackageVersion") == 0) {\r
+                            packageVersion = attrItem.getNodeValue();\r
+                        } else if (attrItem.getNodeName().compareTo("Arch") == 0) {\r
+                            arch = attrItem.getNodeValue();\r
+                        } else {\r
+                            //\r
+                            // Report warning\r
+                            //\r
+                            EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised attribute " + attrItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module");\r
+                        }\r
+                    }\r
+                    \r
+                    PackageIdentification packageId = new PackageIdentification(packageGuid, packageVersion);\r
+                    GlobalData.refreshPackageIdentification(packageId);\r
+                    \r
+                    ModuleIdentification moduleId = new ModuleIdentification(moduleGuid, moduleVersion);\r
+                    moduleId.setPackage(packageId);\r
+                    GlobalData.refreshModuleIdentification(moduleId);\r
+                    \r
+                    if (arch == null) {\r
+                        throw new EdkException("Attribute [Arch] is required for element FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module. ");\r
+                    }\r
+                    \r
+                    result.add(new FpdModuleIdentification(moduleId, arch));\r
+                } else {\r
+                    //\r
+                    // Report Warning\r
+                    //\r
+                    EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules");\r
+                }\r
+            }\r
+        }\r
+    }\r
 }\r
 }\r