/** @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.io.IOException; 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 org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.Ant; import org.apache.tools.ant.taskdefs.Property; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.tianocore.common.definitions.EdkDefinitions; import org.tianocore.common.definitions.ToolDefinitions; import org.tianocore.common.exception.EdkException; import org.tianocore.common.logger.EdkLog; import org.tianocore.build.FrameworkBuildTask; import org.tianocore.build.global.GlobalData; import org.tianocore.build.global.OutputManager; import org.tianocore.build.global.SurfaceAreaQuery; import org.tianocore.build.id.FpdModuleIdentification; import org.tianocore.build.id.ModuleIdentification; import org.tianocore.build.id.PackageIdentification; import org.tianocore.build.id.PlatformIdentification; import org.tianocore.build.pcd.action.PlatformPcdPreprocessActionForBuilding; import org.tianocore.build.toolchain.ToolChainElement; import org.tianocore.build.toolchain.ToolChainMap; import org.tianocore.build.toolchain.ToolChainInfo; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** FpdParserTask is an ANT task. The main function is parsing Framework Platform Descritpion (FPD) XML file and generating its ANT build script for corresponding platform.

The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR and BUILD_DIR.

The task generates ${PLATFORM}_build.xml file which will be called by top level build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage).

FpdParserTask task stores all FPD information to GlobalData. And parse tools definition file to set up compiler options for different Target and different ToolChainTag.

The method parseFpdFile is also prepared for single module build.

@since GenBuild 1.0 **/ public class FpdParserTask extends Task { /// /// Be used to ensure Global data will be initialized only once. /// private static boolean parsed = false; private File fpdFile = null; PlatformIdentification platformId; private String type; /// /// Mapping from modules identification to out put file name /// Map outfiles = new LinkedHashMap(); /// /// Mapping from FV name to its modules /// Map> fvs = new HashMap>(); /// /// Mapping from FV apriori file to its type (PEI or DXE) /// Map aprioriType = new HashMap(); /// /// FpdParserTask can specify some ANT properties. /// private Vector properties = new Vector(); SurfaceAreaQuery saq = null; boolean isUnified = true; public static String PEI_APRIORI_GUID = "1b45cc0a-156a-428a-af62-49864da0e6e6"; public static String DXE_APRIORI_GUID = "fc510ee7-ffdc-11d4-bd41-0080c73c8881"; /** 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 PlatformName_build.xml file for Flatform build;
  • Collect PCD information.
@throws BuildException Surface area is not valid. **/ public void execute() throws BuildException { this.setTaskName("FpdParser"); // // Parse FPD file // parseFpdFile(); // // Prepare BUILD_DIR // isUnified = OutputManager.getInstance().prepareBuildDir(getProject()); String buildDir = getProject().getProperty("BUILD_DIR"); // // For every Target and ToolChain // String[] targetList = GlobalData.getToolChainInfo().getTargets(); for (int i = 0; i < targetList.length; i++) { String[] toolchainList = GlobalData.getToolChainInfo().getTagnames(); for(int j = 0; j < toolchainList.length; j++) { // // Prepare FV_DIR // String ffsCommonDir = buildDir + File.separatorChar + targetList[i] + "_" + toolchainList[j]; File fvDir = new File(ffsCommonDir + File.separatorChar + "FV"); fvDir.mkdirs(); getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/")); // // Gen Fv.inf files // genFvInfFiles(ffsCommonDir); } } // // Gen build.xml // String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml"; PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile, aprioriType); fileGenerator.genBuildFile(); // // Ant call ${PLATFORM}_build.xml // Ant ant = new Ant(); ant.setProject(getProject()); ant.setAntfile(platformBuildFile); ant.setTarget(type); ant.setInheritAll(true); ant.init(); ant.execute(); } /** 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 FV_DIR. @throws BuildException File write FV.inf files error. **/ void genFvInfFiles(String ffsCommonDir) throws BuildException { String[] validFv = saq.getFpdValidImageNames(); for (int i = 0; i < validFv.length; i++) { // // Get all global variables from FPD and set them to properties // String[][] globalVariables = saq.getFpdGlobalVariable(); for (int j = 0; j < globalVariables.length; j++) { getProject().setProperty(globalVariables[j][0], globalVariables[j][1]); } getProject().setProperty("FV_FILENAME", validFv[i]); File fvFile = new File(getProject().replaceProperties( getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".inf")); if (fvFile.exists() && (fvFile.lastModified() >= fpdFile.lastModified())) { // // don't re-generate FV.inf if fpd has not been changed // continue; } fvFile.getParentFile().mkdirs(); try { FileWriter fw = new FileWriter(fvFile); BufferedWriter bw = new BufferedWriter(fw); // // Options // String[][] options = saq.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 = saq.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 = saq.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 moduleSeqSet = getModuleSequenceForFv(validFv[i]); Set filesSet = fvs.get(validFv[i]); FpdModuleIdentification[] files = null; if (moduleSeqSet == null) { if (filesSet != null) { files = filesSet.toArray(new FpdModuleIdentification[filesSet.size()]); } } else if (filesSet == null) { if (moduleSeqSet.size() != 0) { throw new BuildException("Can not find any modules belongs to FV[" + validFv[i] + "], but listed some in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1']"); } } else { // // if moduleSeqSet and filesSet is inconsistent, report error // if(moduleSeqSet.size() != filesSet.size()){ throw new BuildException("Modules for FV[" + validFv[i] + "] defined in FrameworkModules and in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1'] are inconsistent. "); } else { // // whether all modules in moduleSeqSet listed in filesSet // Iterator iter = moduleSeqSet.iterator(); while (iter.hasNext()) { FpdModuleIdentification item = iter.next(); if (!filesSet.contains(item)) { throw new BuildException("Can not find " + item + " belongs to FV[" + validFv[i] + "]"); } } } files = moduleSeqSet.toArray(new FpdModuleIdentification[moduleSeqSet.size()]); } if (files != null) { bw.write("[files]"); bw.newLine(); Set modules = null; if ( (modules = getPeiApriori(validFv[i])) != null) { // // Special GUID - validFv[i].FFS // String str = ffsCommonDir + File.separatorChar + "FV" + File.separatorChar + PEI_APRIORI_GUID + "-" + validFv[i] + ".FFS"; bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str)); bw.newLine(); File aprioriFile = new File(getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".apr"); aprioriType.put(validFv[i], PEI_APRIORI_GUID); genAprioriFile(modules, aprioriFile); } else if((modules = getDxeApriori(validFv[i])) != null) { // // Special GUID - validFv[i].FFS // String str = ffsCommonDir + File.separatorChar + "FV" + File.separatorChar + DXE_APRIORI_GUID + "-" + validFv[i] + ".FFS"; bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str)); bw.newLine(); File aprioriFile = new File(getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".apr"); aprioriType.put(validFv[i], DXE_APRIORI_GUID); genAprioriFile(modules, aprioriFile); } for (int j = 0; j < files.length; j++) { String str = ffsCommonDir + File.separatorChar + outfiles.get(files[j]); bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str)); bw.newLine(); } } bw.flush(); bw.close(); fw.close(); } catch (IOException ex) { BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage()); buildException.setStackTrace(ex.getStackTrace()); throw buildException; } catch (EdkException ex) { BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage()); buildException.setStackTrace(ex.getStackTrace()); throw buildException; } } } /** This method is used for Single Module Build. @throws BuildException FPD file is not valid. **/ public void parseFpdFile(File fpdFile) throws BuildException, EdkException { this.fpdFile = fpdFile; parseFpdFile(); // // Call Platform_build.xml prebuild firstly in stand-alone build // Prepare BUILD_DIR // isUnified = OutputManager.getInstance().prepareBuildDir(getProject()); String buildDir = getProject().getProperty("BUILD_DIR"); // // For every Target and ToolChain // String[] targetList = GlobalData.getToolChainInfo().getTargets(); for (int i = 0; i < targetList.length; i++) { String[] toolchainList = GlobalData.getToolChainInfo().getTagnames(); for(int j = 0; j < toolchainList.length; j++) { // // Prepare FV_DIR // String ffsCommonDir = buildDir + File.separatorChar + targetList[i] + "_" + toolchainList[j]; File fvDir = new File(ffsCommonDir + File.separatorChar + "FV"); fvDir.mkdirs(); } } String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml"; PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile, aprioriType); fileGenerator.genBuildFile(); Ant ant = new Ant(); ant.setProject(getProject()); ant.setAntfile(platformBuildFile); ant.setTarget("prebuild"); ant.setInheritAll(true); ant.init(); ant.execute(); } /** Parse FPD file. @throws BuildException FPD file is not valid. **/ void parseFpdFile() throws BuildException { try { XmlObject doc = XmlObject.Factory.parse(fpdFile); if (!doc.validate()) { throw new BuildException("Platform Surface Area file [" + fpdFile.getPath() + "] format is invalid!"); } Map map = new HashMap(); map.put("PlatformSurfaceArea", doc); saq = new SurfaceAreaQuery(map); // // Initialize // platformId = saq.getFpdHeader(); platformId.setFpdFile(fpdFile); getProject().setProperty("PLATFORM", platformId.getName()); getProject().setProperty("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/")); getProject().setProperty("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/")); getProject().setProperty("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/")); if( !FrameworkBuildTask.multithread) { FrameworkBuildTask.originalProperties.put("PLATFORM", platformId.getName()); FrameworkBuildTask.originalProperties.put("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/")); FrameworkBuildTask.originalProperties.put("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/")); FrameworkBuildTask.originalProperties.put("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/")); } // // Build mode. User-defined output dir. // String buildMode = saq.getFpdIntermediateDirectories(); String userDefinedOutputDir = saq.getFpdOutputDirectory(); OutputManager.getInstance().setup(userDefinedOutputDir, buildMode); // // TBD. Deal PCD and BuildOption related Info // GlobalData.setFpdBuildOptions(saq.getFpdBuildOptions()); GlobalData.setToolChainPlatformInfo(saq.getFpdToolChainInfo()); // // Parse all list modules SA // parseModuleSAFiles(); // // TBD. Deal PCD and BuildOption related Info // parseToolChainFamilyOptions(); parseToolChainOptions(); // // check if the tool chain is valid or not // checkToolChain(); saq.push(map); // // Pcd Collection. Call CollectPCDAction to collect pcd info. // if (!parsed) { PlatformPcdPreprocessActionForBuilding ca = new PlatformPcdPreprocessActionForBuilding(); ca.perform(platformId.getFpdFile().getPath()); } } catch (IOException ex) { BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage()); buildException.setStackTrace(ex.getStackTrace()); throw buildException; } catch (XmlException ex) { BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage()); buildException.setStackTrace(ex.getStackTrace()); throw buildException; } catch (EdkException ex) { BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage()); buildException.setStackTrace(ex.getStackTrace()); throw buildException; } if (!parsed) { parsed = true; } } /** Parse all modules listed in FPD file. **/ void parseModuleSAFiles() throws EdkException{ Map> moduleSAs = saq.getFpdModules(); // // For every Module lists in FPD file. // Set keys = moduleSAs.keySet(); Iterator iter = keys.iterator(); while (iter.hasNext()) { FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next(); // // Judge if Module is existed? // TBD GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId)); // // Put fpdModuleId to the corresponding FV // saq.push(GlobalData.getDoc(fpdModuleId)); String fvBinding = saq.getModuleFvBindingKeyword(); fpdModuleId.setFvBinding(fvBinding); updateFvs(fvBinding, fpdModuleId); // // Prepare for out put file name // ModuleIdentification moduleId = fpdModuleId.getModule(); String baseName = saq.getModuleOutputFileBasename(); if (baseName == null) { baseName = moduleId.getName(); } outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar + moduleId.getGuid() + "-" + baseName + getSuffix(moduleId.getModuleType())); // // parse module build options, if any // GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false)); GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true)); // // parse MSA build options // GlobalData.addMsaBuildOption(moduleId, parseMsaBuildOptions(false)); GlobalData.addMsaFamilyBuildOption(moduleId, parseMsaBuildOptions(true)); ModuleIdentification[] libraryInstances = saq.getLibraryInstance(null); for (int i = 0; i < libraryInstances.length; i++) { saq.push(GlobalData.getDoc(libraryInstances[i], fpdModuleId.getArch())); GlobalData.addMsaBuildOption(libraryInstances[i], parseMsaBuildOptions(false)); GlobalData.addMsaFamilyBuildOption(libraryInstances[i], parseMsaBuildOptions(true)); saq.pop(); } saq.pop(); } } ToolChainMap parseModuleBuildOptions(boolean toolChainFamilyFlag) throws EdkException { String[][] options = saq.getModuleBuildOptions(toolChainFamilyFlag); if (options == null || options.length == 0) { return new ToolChainMap(); } return parseOptions(options); } private ToolChainMap parsePlatformBuildOptions(boolean toolChainFamilyFlag) throws EdkException { String[][] options = saq.getPlatformBuildOptions(toolChainFamilyFlag); if (options == null || options.length == 0) { return new ToolChainMap(); } return parseOptions(options); } ToolChainMap parseMsaBuildOptions(boolean toolChainFamilyFlag) throws EdkException { String[][] options = saq.getMsaBuildOptions(toolChainFamilyFlag); if (options == null || options.length == 0) { return new ToolChainMap(); } return parseOptions(options); } private ToolChainMap parseOptions(String[][] options) throws EdkException { ToolChainMap map = new ToolChainMap(); int flagIndex = ToolChainElement.ATTRIBUTE.value; for (int i = 0; i < options.length; ++i) { String flagString = options[i][flagIndex]; if (flagString == null) { flagString = ""; } options[i][flagIndex] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_FLAGS; map.put(options[i], flagString.trim()); } return map; } private void parseToolChainFamilyOptions() throws EdkException { GlobalData.setPlatformToolChainFamilyOption(parsePlatformBuildOptions(true)); } private void parseToolChainOptions() throws EdkException { GlobalData.setPlatformToolChainOption(parsePlatformBuildOptions(false)); } /** Add the current module to corresponding FV. @param fvName current FV name @param moduleName current module identification **/ void updateFvs(String fvName, FpdModuleIdentification fpdModuleId) { if (fvName == null || fvName.trim().length() == 0) { fvName = "NULL"; } String[] fvNameArray = fvName.split("[, \t]+"); for (int i = 0; i < fvNameArray.length; i++) { // // Put module to corresponding fvName // if (fvs.containsKey(fvNameArray[i])) { Set set = fvs.get(fvNameArray[i]); set.add(fpdModuleId); } else { Set set = new LinkedHashSet(); set.add(fpdModuleId); fvs.put(fvNameArray[i], set); } } } /** Get the suffix based on module type. Current relationship are listed:
      ModuleType     Suffix
      BASE                 .FFS
      SEC                  .SEC
      PEI_CORE             .PEI
      PEIM                 .PEI
      DXE_CORE             .DXE
      DXE_DRIVER           .DXE
      DXE_RUNTIME_DRIVER   .DXE
      DXE_SAL_DRIVER       .DXE
      DXE_SMM_DRIVER       .DXE
      TOOL                 .FFS
      UEFI_DRIVER          .DXE
      UEFI_APPLICATION     .APP
      USER_DEFINED         .FFS
      
@param moduleType module type @return @throws BuildException If module type is null **/ public static String getSuffix(String moduleType) throws BuildException { if (moduleType == null) { throw new BuildException("Module type is not specified."); } String[][] suffix = EdkDefinitions.ModuleTypeExtensions; for (int i = 0; i < suffix.length; i++) { if (suffix[i][0].equalsIgnoreCase(moduleType)) { return suffix[i][1]; } } // // Default is '.FFS' // return ".FFS"; } /** Add a property. @param p property **/ public void addProperty(Property p) { properties.addElement(p); } public void setFpdFile(File fpdFile) { this.fpdFile = fpdFile; } public void setType(String type) { this.type = type; } public String getAllArchForModule(ModuleIdentification moduleId) { String archs = ""; Iterator iter = outfiles.keySet().iterator(); while (iter.hasNext()) { FpdModuleIdentification fpdModuleId = iter.next(); if (fpdModuleId.getModule().equals(moduleId)) { archs += fpdModuleId.getArch() + " "; } } return archs; } private void genAprioriFile(Set modules, File file) { try { FileWriter fw = new FileWriter(file); BufferedWriter bw = new BufferedWriter(fw); Iterator iter = modules.iterator(); while(iter.hasNext()) { bw.write(iter.next().getModule().getGuid()); bw.newLine(); } bw.flush(); bw.close(); fw.close(); } catch (IOException ex) { BuildException buildException = new BuildException("Generation of the Apriori file [" + file.getPath() + "] failed!\n" + ex.getMessage()); buildException.setStackTrace(ex.getStackTrace()); throw buildException; } } private Set getPeiApriori(String fvName) throws EdkException { Node node = saq.getPeiApriori(fvName); Set result = new LinkedHashSet(); if (node == null) { return null; } NodeList childNodes = node.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node childItem = childNodes.item(i); if (childItem.getNodeType() == Node.ELEMENT_NODE) { // // Find child elements "IncludeModules" // if (childItem.getNodeName().compareTo("IncludeModules") == 0) { // // result will be updated // processNodes(childItem, result); } else if (childItem.getNodeName().compareTo("FvName") == 0) { } else if (childItem.getNodeName().compareTo("InfFileName") == 0) { } else { // // Report Warning // EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='APRIORI' Identifier='0']"); } } } return result; } private Set getDxeApriori(String fvName) throws EdkException { Node node = saq.getDxeApriori(fvName); Set result = new LinkedHashSet(); if (node == null) { return null; } NodeList childNodes = node.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node childItem = childNodes.item(i); if (childItem.getNodeType() == Node.ELEMENT_NODE) { // // Find child elements "IncludeModules" // if (childItem.getNodeName().compareTo("IncludeModules") == 0) { // // result will be updated // processNodes(childItem, result); } else if (childItem.getNodeName().compareTo("FvName") == 0) { } else if (childItem.getNodeName().compareTo("InfFileName") == 0) { } else { // // Report Warning // EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='APRIORI' Identifier='1']"); } } } return result; } private Set getModuleSequenceForFv(String fvName) throws EdkException { Node node = saq.getFpdModuleSequence(fvName); Set result = new LinkedHashSet(); if ( node == null) { EdkLog.log(this, EdkLog.EDK_WARNING, "FV[" + fvName + "] does not specify module sequence in FPD. Assuming present sequence as default sequence in FV. "); return null; } else { NodeList childNodes = node.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node childItem = childNodes.item(i); if (childItem.getNodeType() == Node.ELEMENT_NODE) { // // Find child elements "IncludeModules" // if (childItem.getNodeName().compareTo("IncludeModules") == 0) { // // result will be updated // processNodes(childItem, result); } else if (childItem.getNodeName().compareTo("FvName") == 0) { } else if (childItem.getNodeName().compareTo("InfFileName") == 0) { } else { // // Report Warning // EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1']"); } } } } return result; } private void processNodes(Node node, Set result) throws EdkException { // // Found out all elements "Module" // NodeList childNodes = node.getChildNodes(); for (int j = 0; j < childNodes.getLength(); j++) { Node childItem = childNodes.item(j); if (childItem.getNodeType() == Node.ELEMENT_NODE) { if (childItem.getNodeName().compareTo("Module") == 0) { String moduleGuid = null; String moduleVersion = null; String packageGuid = null; String packageVersion = null; String arch = null; NamedNodeMap attr = childItem.getAttributes(); for (int i = 0; i < attr.getLength(); i++) { Node attrItem = attr.item(i); if (attrItem.getNodeName().compareTo("ModuleGuid") == 0) { moduleGuid = attrItem.getNodeValue(); } else if (attrItem.getNodeName().compareTo("ModuleVersion") == 0) { moduleVersion = attrItem.getNodeValue(); } else if (attrItem.getNodeName().compareTo("PackageGuid") == 0) { packageGuid = attrItem.getNodeValue(); } else if (attrItem.getNodeName().compareTo("PackageVersion") == 0) { packageVersion = attrItem.getNodeValue(); } else if (attrItem.getNodeName().compareTo("Arch") == 0) { arch = attrItem.getNodeValue(); } else { // // Report warning // EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised attribute " + attrItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module"); } } PackageIdentification packageId = new PackageIdentification(packageGuid, packageVersion); GlobalData.refreshPackageIdentification(packageId); ModuleIdentification moduleId = new ModuleIdentification(moduleGuid, moduleVersion); moduleId.setPackage(packageId); GlobalData.refreshModuleIdentification(moduleId); if (arch == null) { throw new EdkException("Attribute [Arch] is required for element FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module. "); } result.add(new FpdModuleIdentification(moduleId, arch)); } else { // // Report Warning // EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules"); } } } } private void checkToolChain() throws EdkException { ToolChainInfo toolChainInfo = GlobalData.getToolChainInfo(); if (toolChainInfo.getTargets().length == 0) { throw new EdkException("No valid target found! "+ "Please check the TARGET definition in Tools/Conf/target.txt, "+ "or the , in the FPD file."); } if (toolChainInfo.getTagnames().length == 0) { throw new EdkException("No valid tool chain found! "+ "Please check the TOOL_CHAIN_TAG definition in Tools/Conf/target.txt, "+ "or the in the FPD file."); } if (toolChainInfo.getArchs().length == 0) { throw new EdkException("No valid architecture found! "+ "Please check the TARGET_ARCH definition in Tools/Conf/target.txt, "+ "or the , in the FPD file."); } if (toolChainInfo.getCommands().length == 0) { throw new EdkException("No valid COMMAND found! Please check the tool chain definitions "+ "in Tools/Conf/tools_def.txt."); } } }