]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java
temp fix to remove "VOID" appended to Autogen.c
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / fpd / FpdParserTask.java
CommitLineData
878ddf1f 1/** @file\r
ff225cbb 2 This file is ANT task FpdParserTask.\r
3\r
a29c47e0 4 FpdParserTask is used to parse FPD (Framework Platform Description) and generate\r
ff225cbb 5 build.out.xml. It is for Package or Platform build use.\r
6\r
a29c47e0 7 Copyright (c) 2006, Intel Corporation\r
8 All rights reserved. This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15 **/\r
878ddf1f 16package org.tianocore.build.fpd;\r
17\r
18import java.io.BufferedWriter;\r
19import java.io.File;\r
20import java.io.FileWriter;\r
89e1408f 21import java.io.IOException;\r
878ddf1f 22import java.util.HashMap;\r
23import java.util.Iterator;\r
24import java.util.LinkedHashMap;\r
25import java.util.LinkedHashSet;\r
26import java.util.Map;\r
27import java.util.Set;\r
28import java.util.Vector;\r
878ddf1f 29\r
30import org.apache.tools.ant.BuildException;\r
31import org.apache.tools.ant.Task;\r
a29c47e0 32import org.apache.tools.ant.taskdefs.Ant;\r
878ddf1f 33import org.apache.tools.ant.taskdefs.Property;\r
89e1408f 34import org.apache.xmlbeans.XmlException;\r
878ddf1f 35import org.apache.xmlbeans.XmlObject;\r
878ddf1f 36\r
4a6a5026 37import org.tianocore.common.definitions.EdkDefinitions;\r
ff225cbb 38import org.tianocore.common.exception.EdkException;\r
bb511931 39import org.tianocore.common.logger.EdkLog;\r
ff225cbb 40import org.tianocore.pcd.action.ActionMessage;\r
aca6c736 41import org.tianocore.build.FrameworkBuildTask;\r
878ddf1f 42import org.tianocore.build.global.GlobalData;\r
43import org.tianocore.build.global.OutputManager;\r
878ddf1f 44import org.tianocore.build.global.SurfaceAreaQuery;\r
a29c47e0 45import org.tianocore.build.id.FpdModuleIdentification;\r
46import org.tianocore.build.id.ModuleIdentification;\r
bb511931 47import org.tianocore.build.id.PackageIdentification;\r
a29c47e0 48import org.tianocore.build.id.PlatformIdentification;\r
af98370e 49import org.tianocore.build.pcd.action.PlatformPcdPreprocessActionForBuilding;\r
a29c47e0 50import org.tianocore.build.toolchain.ToolChainAttribute;\r
51import org.tianocore.build.toolchain.ToolChainElement;\r
52import org.tianocore.build.toolchain.ToolChainMap;\r
bb511931 53import org.w3c.dom.NamedNodeMap;\r
54import org.w3c.dom.Node;\r
55import org.w3c.dom.NodeList;\r
878ddf1f 56\r
57/**\r
a29c47e0 58 <code>FpdParserTask</code> is an ANT task. The main function is parsing Framework\r
ff225cbb 59 Platform Descritpion (FPD) XML file and generating its ANT build script for\r
60 corresponding platform.\r
a29c47e0 61\r
62 <p>The task sets global properties PLATFORM, PLATFORM_DIR, PLATFORM_RELATIVE_DIR\r
63 and BUILD_DIR. </p>\r
ff225cbb 64\r
a29c47e0 65 <p>The task generates ${PLATFORM}_build.xml file which will be called by top level\r
4b5f5549 66 build.xml. The task also generate Fv.inf files (File is for Tool GenFvImage). </p>\r
ff225cbb 67\r
a29c47e0 68 <p>FpdParserTask task stores all FPD information to GlobalData. And parse\r
69 tools definition file to set up compiler options for different Target and\r
70 different ToolChainTag. </p>\r
ff225cbb 71\r
a29c47e0 72 <p>The method parseFpdFile is also prepared for single module build. </p>\r
ff225cbb 73\r
878ddf1f 74 @since GenBuild 1.0\r
75**/\r
76public class FpdParserTask extends Task {\r
ff225cbb 77\r
a29c47e0 78 private File fpdFile = null;\r
ff225cbb 79\r
19bf6b15 80 PlatformIdentification platformId;\r
ff225cbb 81\r
a29c47e0 82 private String type;\r
ff225cbb 83\r
878ddf1f 84 ///\r
85 /// Mapping from modules identification to out put file name\r
86 ///\r
19bf6b15 87 Map<FpdModuleIdentification, String> outfiles = new LinkedHashMap<FpdModuleIdentification, String>();\r
878ddf1f 88\r
89 ///\r
90 /// Mapping from FV name to its modules\r
91 ///\r
19bf6b15 92 Map<String, Set<FpdModuleIdentification>> fvs = new HashMap<String, Set<FpdModuleIdentification>>();\r
878ddf1f 93\r
878ddf1f 94 ///\r
ff225cbb 95 /// FpdParserTask can specify some ANT properties.\r
878ddf1f 96 ///\r
97 private Vector<Property> properties = new Vector<Property>();\r
ff225cbb 98\r
83fba802 99 SurfaceAreaQuery saq = null;\r
100 \r
19bf6b15 101 boolean isUnified = true;\r
878ddf1f 102\r
878ddf1f 103 /**\r
104 Public construct method. It is necessary for ANT task.\r
105 **/\r
a29c47e0 106 public FpdParserTask() {\r
878ddf1f 107 }\r
108\r
109 /**\r
ff225cbb 110 ANT task's entry method. The main steps is described as following:\r
111\r
a29c47e0 112 <ul>\r
ff225cbb 113 <li>Initialize global information (Framework DB, SPD files and all MSA files\r
a29c47e0 114 listed in SPD). This step will execute only once in whole build process;</li>\r
115 <li>Parse specified FPD file; </li>\r
116 <li>Generate FV.inf files; </li>\r
117 <li>Generate PlatformName_build.xml file for Flatform build; </li>\r
118 <li>Collect PCD information. </li>\r
119 </ul>\r
ff225cbb 120\r
a29c47e0 121 @throws BuildException\r
ff225cbb 122 Surface area is not valid.\r
878ddf1f 123 **/\r
124 public void execute() throws BuildException {\r
bb511931 125 this.setTaskName("FpdParser");\r
126 \r
878ddf1f 127 //\r
128 // Parse FPD file\r
129 //\r
130 parseFpdFile();\r
ff225cbb 131\r
a29c47e0 132 //\r
133 // Prepare BUILD_DIR\r
878ddf1f 134 //\r
a29c47e0 135 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
ff225cbb 136\r
02c768ee 137 String buildDir = getProject().getProperty("BUILD_DIR");\r
a29c47e0 138 //\r
139 // For every Target and ToolChain\r
140 //\r
141 String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
82516887 142 for (int i = 0; i < targetList.length; i++) {\r
a29c47e0 143 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
82516887 144 for(int j = 0; j < toolchainList.length; j++) {\r
a29c47e0 145 //\r
146 // Prepare FV_DIR\r
147 //\r
02c768ee 148 String ffsCommonDir = buildDir + File.separatorChar\r
6ae1510e 149 + targetList[i] + "_"\r
a29c47e0 150 + toolchainList[j];\r
151 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");\r
152 fvDir.mkdirs();\r
153 getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));\r
ff225cbb 154\r
a29c47e0 155 //\r
156 // Gen Fv.inf files\r
157 //\r
158 genFvInfFiles(ffsCommonDir);\r
159 }\r
160 }\r
161\r
878ddf1f 162 //\r
163 // Gen build.xml\r
164 //\r
02c768ee 165 String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";\r
166 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile);\r
a29c47e0 167 fileGenerator.genBuildFile();\r
ff225cbb 168\r
a29c47e0 169 //\r
170 // Ant call ${PLATFORM}_build.xml\r
878ddf1f 171 //\r
a29c47e0 172 Ant ant = new Ant();\r
173 ant.setProject(getProject());\r
02c768ee 174 ant.setAntfile(platformBuildFile);\r
a29c47e0 175 ant.setTarget(type);\r
176 ant.setInheritAll(true);\r
177 ant.init();\r
178 ant.execute();\r
878ddf1f 179 }\r
a29c47e0 180\r
878ddf1f 181 /**\r
ff225cbb 182 Generate Fv.inf files. The Fv.inf file is composed with four\r
183 parts: Options, Attributes, Components and Files. The Fv.inf files\r
a29c47e0 184 will be under FV_DIR.\r
ff225cbb 185\r
878ddf1f 186 @throws BuildException\r
ff225cbb 187 File write FV.inf files error.\r
878ddf1f 188 **/\r
19bf6b15 189 void genFvInfFiles(String ffsCommonDir) throws BuildException {\r
83fba802 190 String[] validFv = saq.getFpdValidImageNames();\r
878ddf1f 191 for (int i = 0; i < validFv.length; i++) {\r
878ddf1f 192 //\r
193 // Get all global variables from FPD and set them to properties\r
194 //\r
83fba802 195 String[][] globalVariables = saq.getFpdGlobalVariable();\r
878ddf1f 196 for (int j = 0; j < globalVariables.length; j++) {\r
a29c47e0 197 getProject().setProperty(globalVariables[j][0], globalVariables[j][1]);\r
878ddf1f 198 }\r
199\r
57cc2ee7 200 getProject().setProperty("FV_FILENAME", validFv[i]);\r
ff225cbb 201\r
57cc2ee7 202 File fvFile = new File(getProject().replaceProperties( getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".inf"));\r
d946661a 203 if (fvFile.exists() && (fvFile.lastModified() >= fpdFile.lastModified())) {\r
204 //\r
205 // don't re-generate FV.inf if fpd has not been changed\r
206 // \r
207 continue;\r
208 }\r
878ddf1f 209 fvFile.getParentFile().mkdirs();\r
210\r
211 try {\r
212 FileWriter fw = new FileWriter(fvFile);\r
213 BufferedWriter bw = new BufferedWriter(fw);\r
ff225cbb 214\r
878ddf1f 215 //\r
216 // Options\r
217 //\r
83fba802 218 String[][] options = saq.getFpdOptions(validFv[i]);\r
878ddf1f 219 if (options.length > 0) {\r
220 bw.write("[options]");\r
221 bw.newLine();\r
222 for (int j = 0; j < options.length; j++) {\r
223 StringBuffer str = new StringBuffer(100);\r
224 str.append(options[j][0]);\r
225 while (str.length() < 40) {\r
226 str.append(' ');\r
227 }\r
228 str.append("= ");\r
229 str.append(options[j][1]);\r
230 bw.write(getProject().replaceProperties(str.toString()));\r
231 bw.newLine();\r
232 }\r
233 bw.newLine();\r
234 }\r
ff225cbb 235\r
878ddf1f 236 //\r
237 // Attributes;\r
238 //\r
83fba802 239 String[][] attributes = saq.getFpdAttributes(validFv[i]);\r
878ddf1f 240 if (attributes.length > 0) {\r
241 bw.write("[attributes]");\r
242 bw.newLine();\r
243 for (int j = 0; j < attributes.length; j++) {\r
244 StringBuffer str = new StringBuffer(100);\r
245 str.append(attributes[j][0]);\r
246 while (str.length() < 40) {\r
247 str.append(' ');\r
248 }\r
249 str.append("= ");\r
250 str.append(attributes[j][1]);\r
a29c47e0 251 bw.write(getProject().replaceProperties(str.toString()));\r
878ddf1f 252 bw.newLine();\r
253 }\r
254 bw.newLine();\r
255 }\r
ff225cbb 256\r
878ddf1f 257 //\r
258 // Components\r
259 //\r
83fba802 260 String[][] components = saq.getFpdComponents(validFv[i]);\r
878ddf1f 261 if (components.length > 0) {\r
262 bw.write("[components]");\r
263 bw.newLine();\r
264 for (int j = 0; j < components.length; j++) {\r
265 StringBuffer str = new StringBuffer(100);\r
266 str.append(components[j][0]);\r
267 while (str.length() < 40) {\r
268 str.append(' ');\r
269 }\r
270 str.append("= ");\r
271 str.append(components[j][1]);\r
a29c47e0 272 bw.write(getProject().replaceProperties(str.toString()));\r
878ddf1f 273 bw.newLine();\r
274 }\r
275 bw.newLine();\r
276 }\r
bb511931 277 \r
878ddf1f 278 //\r
279 // Files\r
280 //\r
bb511931 281 Set<FpdModuleIdentification> moduleSeqSet = getModuleSequenceForFv(validFv[i]);\r
282 \r
57cc2ee7 283 Set<FpdModuleIdentification> filesSet = fvs.get(validFv[i]);\r
bb511931 284 \r
285 FpdModuleIdentification[] files = null;\r
286 if (moduleSeqSet == null) {\r
287 if (filesSet != null) {\r
288 files = filesSet.toArray(new FpdModuleIdentification[filesSet.size()]);\r
289 }\r
290 } else {\r
291 //\r
292 // if moduleSeqSet and filesSet is inconsistent, report error\r
293 //\r
294 if (filesSet == null && moduleSeqSet.size() != 0) {\r
295 throw new BuildException("Can not find any modules belongs to FV[" + validFv[i] + "], but listed some in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1']");\r
296 } else if(moduleSeqSet.size() != filesSet.size()){\r
297 throw new BuildException("Modules for FV[" + validFv[i] + "] defined in FrameworkModules and in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1'] are inconsistent. ");\r
298 } else {\r
299 //\r
300 // whether all modules in moduleSeqSet listed in filesSet\r
301 //\r
302 Iterator<FpdModuleIdentification> iter = moduleSeqSet.iterator();\r
303 while (iter.hasNext()) {\r
304 FpdModuleIdentification item = iter.next();\r
305 if (!filesSet.contains(item)) {\r
306 throw new BuildException("Can not find " + item + " belongs to FV[" + validFv[i] + "]");\r
307 }\r
308 }\r
309 }\r
310 \r
311 files = moduleSeqSet.toArray(new FpdModuleIdentification[moduleSeqSet.size()]);\r
312 }\r
313 \r
314 \r
315 if (files != null) {\r
878ddf1f 316 bw.write("[files]");\r
317 bw.newLine();\r
318 for (int j = 0; j < files.length; j++) {\r
a29c47e0 319 String str = ffsCommonDir + File.separatorChar + outfiles.get(files[j]);\r
320 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));\r
878ddf1f 321 bw.newLine();\r
322 }\r
323 }\r
324 bw.flush();\r
325 bw.close();\r
326 fw.close();\r
89e1408f 327 } catch (IOException ex) {\r
328 BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage());\r
329 buildException.setStackTrace(ex.getStackTrace());\r
330 throw buildException;\r
bb511931 331 } catch (EdkException ex) {\r
332 BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage());\r
333 buildException.setStackTrace(ex.getStackTrace());\r
334 throw buildException;\r
878ddf1f 335 }\r
336 }\r
337 }\r
a29c47e0 338 /**\r
339 This method is used for Single Module Build.\r
ff225cbb 340\r
341\r
a29c47e0 342 @throws BuildException\r
ff225cbb 343 FPD file is not valid.\r
a29c47e0 344 **/\r
89e1408f 345 public void parseFpdFile(File fpdFile) throws BuildException, EdkException {\r
a29c47e0 346 this.fpdFile = fpdFile;\r
5acb4b67 347 parseFpdFile();\r
2a9060e2 348 \r
349 //\r
350 // Call Platform_build.xml prebuild firstly in stand-alone build\r
351 // Prepare BUILD_DIR\r
352 //\r
353 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());\r
354\r
355 String buildDir = getProject().getProperty("BUILD_DIR");\r
356 //\r
357 // For every Target and ToolChain\r
358 //\r
359 String[] targetList = GlobalData.getToolChainInfo().getTargets();\r
360 for (int i = 0; i < targetList.length; i++) {\r
361 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();\r
362 for(int j = 0; j < toolchainList.length; j++) {\r
363 //\r
364 // Prepare FV_DIR\r
365 //\r
366 String ffsCommonDir = buildDir + File.separatorChar\r
367 + targetList[i] + "_"\r
368 + toolchainList[j];\r
369 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");\r
370 fvDir.mkdirs();\r
371 }\r
372 }\r
373\r
374 String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";\r
375 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile);\r
376 fileGenerator.genBuildFile();\r
377 \r
378 Ant ant = new Ant();\r
379 ant.setProject(getProject());\r
380 ant.setAntfile(platformBuildFile);\r
381 ant.setTarget("prebuild");\r
382 ant.setInheritAll(true);\r
383 ant.init();\r
384 ant.execute();\r
a29c47e0 385 }\r
878ddf1f 386\r
387 /**\r
ff225cbb 388 Parse FPD file.\r
389\r
878ddf1f 390 @throws BuildException\r
ff225cbb 391 FPD file is not valid.\r
a29c47e0 392 **/\r
19bf6b15 393 void parseFpdFile() throws BuildException {\r
878ddf1f 394 try {\r
a29c47e0 395 XmlObject doc = XmlObject.Factory.parse(fpdFile);\r
ff225cbb 396\r
a29c47e0 397 if (!doc.validate()) {\r
391dbbb1 398 throw new BuildException("Platform Surface Area file [" + fpdFile.getPath() + "] format is invalid!");\r
878ddf1f 399 }\r
ff225cbb 400\r
a29c47e0 401 Map<String, XmlObject> map = new HashMap<String, XmlObject>();\r
402 map.put("PlatformSurfaceArea", doc);\r
83fba802 403 saq = new SurfaceAreaQuery(map);\r
8031d48d 404\r
a29c47e0 405 //\r
406 // Initialize\r
407 //\r
83fba802 408 platformId = saq.getFpdHeader();\r
a29c47e0 409 platformId.setFpdFile(fpdFile);\r
de4bb9f6 410 getProject().setProperty("PLATFORM", platformId.getName());\r
411 getProject().setProperty("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));\r
412 getProject().setProperty("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));\r
413 getProject().setProperty("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));\r
aca6c736 414 \r
415 if( !FrameworkBuildTask.multithread) {\r
416 FrameworkBuildTask.originalProperties.put("PLATFORM", platformId.getName());\r
417 FrameworkBuildTask.originalProperties.put("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));\r
418 FrameworkBuildTask.originalProperties.put("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));\r
419 FrameworkBuildTask.originalProperties.put("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));\r
420 }\r
a29c47e0 421\r
422 //\r
ff225cbb 423 // Build mode. User-defined output dir.\r
a29c47e0 424 //\r
83fba802 425 String buildMode = saq.getFpdIntermediateDirectories();\r
426 String userDefinedOutputDir = saq.getFpdOutputDirectory();\r
a29c47e0 427\r
428 OutputManager.getInstance().setup(userDefinedOutputDir, buildMode);\r
429\r
430 //\r
431 // TBD. Deal PCD and BuildOption related Info\r
432 //\r
83fba802 433 GlobalData.setFpdBuildOptions(saq.getFpdBuildOptions());\r
ff225cbb 434\r
83fba802 435 GlobalData.setToolChainPlatformInfo(saq.getFpdToolChainInfo());\r
ff225cbb 436\r
878ddf1f 437 //\r
438 // Parse all list modules SA\r
439 //\r
07193171 440 parseModuleSAFiles();\r
a29c47e0 441\r
442 //\r
443 // TBD. Deal PCD and BuildOption related Info\r
444 //\r
445 parseToolChainFamilyOptions();\r
446 parseToolChainOptions();\r
447\r
83fba802 448 saq.push(map);\r
ff225cbb 449\r
de4bb9f6 450 //\r
451 // Pcd Collection. Call CollectPCDAction to collect pcd info.\r
452 //\r
8b7bd455 453 PlatformPcdPreprocessActionForBuilding ca = new PlatformPcdPreprocessActionForBuilding();\r
454 ca.perform(platformId.getFpdFile().getPath(), ActionMessage.NULL_MESSAGE_LEVEL);\r
89e1408f 455 } catch (IOException ex) {\r
456 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());\r
457 buildException.setStackTrace(ex.getStackTrace());\r
458 throw buildException;\r
459 } catch (XmlException ex) {\r
460 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());\r
461 buildException.setStackTrace(ex.getStackTrace());\r
462 throw buildException;\r
463 } catch (EdkException ex) {\r
464 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());\r
465 buildException.setStackTrace(ex.getStackTrace());\r
466 throw buildException;\r
878ddf1f 467 }\r
468 }\r
469\r
470 /**\r
ff225cbb 471 Parse all modules listed in FPD file.\r
878ddf1f 472 **/\r
19bf6b15 473 void parseModuleSAFiles() throws EdkException{\r
83fba802 474 Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();\r
136adffc 475\r
878ddf1f 476 //\r
477 // For every Module lists in FPD file.\r
478 //\r
a29c47e0 479 Set<FpdModuleIdentification> keys = moduleSAs.keySet();\r
480 Iterator iter = keys.iterator();\r
481 while (iter.hasNext()) {\r
482 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();\r
ff225cbb 483\r
878ddf1f 484 //\r
ff225cbb 485 // Judge if Module is existed?\r
a29c47e0 486 // TBD\r
a29c47e0 487 GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));\r
488\r
878ddf1f 489 //\r
a29c47e0 490 // Put fpdModuleId to the corresponding FV\r
878ddf1f 491 //\r
83fba802 492 saq.push(GlobalData.getDoc(fpdModuleId));\r
493 String fvBinding = saq.getModuleFvBindingKeyword();\r
a29c47e0 494\r
495 fpdModuleId.setFvBinding(fvBinding);\r
01413f0c 496 updateFvs(fvBinding, fpdModuleId);\r
ff225cbb 497\r
878ddf1f 498 //\r
a29c47e0 499 // Prepare for out put file name\r
878ddf1f 500 //\r
a29c47e0 501 ModuleIdentification moduleId = fpdModuleId.getModule();\r
82516887 502\r
83fba802 503 String baseName = saq.getModuleOutputFileBasename();\r
82516887 504 \r
a29c47e0 505 if (baseName == null) {\r
506 baseName = moduleId.getName();\r
878ddf1f 507 }\r
ff225cbb 508 outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar\r
509 + moduleId.getGuid() + "-" + baseName\r
a29c47e0 510 + getSuffix(moduleId.getModuleType()));\r
511\r
512 //\r
513 // parse module build options, if any\r
ff225cbb 514 //\r
a29c47e0 515 GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));\r
516 GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));\r
83fba802 517 saq.pop();\r
878ddf1f 518 }\r
519 }\r
520\r
19bf6b15 521 ToolChainMap parseModuleBuildOptions(boolean toolChainFamilyFlag) throws EdkException {\r
83fba802 522 String[][] options = saq.getModuleBuildOptions(toolChainFamilyFlag);\r
a29c47e0 523 if (options == null || options.length == 0) {\r
80eb97ff 524 return new ToolChainMap();\r
878ddf1f 525 }\r
a29c47e0 526 return parseOptions(options);\r
878ddf1f 527 }\r
ff225cbb 528\r
a29c47e0 529 private ToolChainMap parsePlatformBuildOptions(boolean toolChainFamilyFlag) throws EdkException {\r
83fba802 530 String[][] options = saq.getPlatformBuildOptions(toolChainFamilyFlag);\r
a29c47e0 531 if (options == null || options.length == 0) {\r
80eb97ff 532 return new ToolChainMap();\r
878ddf1f 533 }\r
a29c47e0 534 return parseOptions(options);\r
878ddf1f 535 }\r
536\r
a29c47e0 537 private ToolChainMap parseOptions(String[][] options) throws EdkException {\r
538 ToolChainMap map = new ToolChainMap();\r
539 int flagIndex = ToolChainElement.ATTRIBUTE.value;\r
540\r
541 for (int i = 0; i < options.length; ++i) {\r
542 String flagString = options[i][flagIndex];\r
543 if (flagString == null) {\r
544 flagString = "";\r
545 }\r
546 options[i][flagIndex] = ToolChainAttribute.FLAGS + "";\r
547 map.put(options[i], flagString.trim());\r
548 }\r
549\r
878ddf1f 550 return map;\r
551 }\r
ff225cbb 552\r
a29c47e0 553 private void parseToolChainFamilyOptions() throws EdkException {\r
554 GlobalData.setPlatformToolChainFamilyOption(parsePlatformBuildOptions(true));\r
555 }\r
556\r
557 private void parseToolChainOptions() throws EdkException {\r
558 GlobalData.setPlatformToolChainOption(parsePlatformBuildOptions(false));\r
559 }\r
878ddf1f 560\r
561 /**\r
ff225cbb 562 Add the current module to corresponding FV.\r
563\r
a29c47e0 564 @param fvName current FV name\r
565 @param moduleName current module identification\r
878ddf1f 566 **/\r
19bf6b15 567 void updateFvs(String fvName, FpdModuleIdentification fpdModuleId) {\r
fa2da5b1 568 if (fvName == null || fvName.trim().length() == 0) {\r
569 fvName = "NULL";\r
570 }\r
57cc2ee7 571 String[] fvNameArray = fvName.split("[, \t]+");\r
a29c47e0 572 for (int i = 0; i < fvNameArray.length; i++) {\r
878ddf1f 573 //\r
a29c47e0 574 // Put module to corresponding fvName\r
878ddf1f 575 //\r
a29c47e0 576 if (fvs.containsKey(fvNameArray[i])) {\r
577 Set<FpdModuleIdentification> set = fvs.get(fvNameArray[i]);\r
578 set.add(fpdModuleId);\r
82516887 579 } else {\r
a29c47e0 580 Set<FpdModuleIdentification> set = new LinkedHashSet<FpdModuleIdentification>();\r
581 set.add(fpdModuleId);\r
582 fvs.put(fvNameArray[i], set);\r
878ddf1f 583 }\r
878ddf1f 584 }\r
585 }\r
586\r
587 /**\r
ff225cbb 588 Get the suffix based on module type. Current relationship are listed:\r
589\r
a29c47e0 590 <pre>\r
591 <b>ModuleType</b> <b>Suffix</b>\r
592 BASE .FFS\r
593 SEC .SEC\r
594 PEI_CORE .PEI\r
595 PEIM .PEI\r
596 DXE_CORE .DXE\r
597 DXE_DRIVER .DXE\r
598 DXE_RUNTIME_DRIVER .DXE\r
599 DXE_SAL_DRIVER .DXE\r
600 DXE_SMM_DRIVER .DXE\r
601 TOOL .FFS\r
602 UEFI_DRIVER .DXE\r
603 UEFI_APPLICATION .APP\r
604 USER_DEFINED .FFS\r
605 </pre>\r
ff225cbb 606\r
a29c47e0 607 @param moduleType module type\r
608 @return\r
609 @throws BuildException\r
610 If module type is null\r
878ddf1f 611 **/\r
a29c47e0 612 public static String getSuffix(String moduleType) throws BuildException {\r
613 if (moduleType == null) {\r
614 throw new BuildException("Module type is not specified.");\r
615 }\r
878ddf1f 616\r
4a6a5026 617 String[][] suffix = EdkDefinitions.ModuleTypeExtensions;\r
ff225cbb 618\r
a29c47e0 619 for (int i = 0; i < suffix.length; i++) {\r
620 if (suffix[i][0].equalsIgnoreCase(moduleType)) {\r
621 return suffix[i][1];\r
622 }\r
623 }\r
624 //\r
625 // Default is '.FFS'\r
626 //\r
627 return ".FFS";\r
878ddf1f 628 }\r
878ddf1f 629 /**\r
ff225cbb 630 Add a property.\r
631\r
a29c47e0 632 @param p property\r
633 **/\r
634 public void addProperty(Property p) {\r
635 properties.addElement(p);\r
878ddf1f 636 }\r
637\r
a29c47e0 638 public void setFpdFile(File fpdFile) {\r
639 this.fpdFile = fpdFile;\r
878ddf1f 640 }\r
641\r
a29c47e0 642 public void setType(String type) {\r
643 this.type = type;\r
878ddf1f 644 }\r
3790e93c 645 \r
646 public String getAllArchForModule(ModuleIdentification moduleId) {\r
647 String archs = "";\r
648 Iterator<FpdModuleIdentification> iter = outfiles.keySet().iterator();\r
649 while (iter.hasNext()) {\r
650 FpdModuleIdentification fpdModuleId = iter.next();\r
651 \r
652 if (fpdModuleId.getModule().equals(moduleId)) {\r
653 archs += fpdModuleId.getArch() + " ";\r
654 }\r
655 }\r
656 \r
657 return archs;\r
658 }\r
bb511931 659 \r
660 private Set<FpdModuleIdentification> getModuleSequenceForFv(String fvName) throws EdkException {\r
661 Node node = saq.getFpdModuleSequence(fvName);\r
662 Set<FpdModuleIdentification> result = new LinkedHashSet<FpdModuleIdentification>();\r
663 \r
664 if ( node == null) {\r
665 EdkLog.log(this, EdkLog.EDK_WARNING, "FV[" + fvName + "] does not specify module sequence in FPD. Assuming present sequence as default sequence in FV. ");\r
666 return null;\r
667 } else {\r
668 NodeList childNodes = node.getChildNodes();\r
669 for (int i = 0; i < childNodes.getLength(); i++) {\r
670 Node childItem = childNodes.item(i);\r
671 if (childItem.getNodeType() == Node.ELEMENT_NODE) {\r
672 //\r
673 // Find child elements "IncludeModules"\r
674 //\r
675 if (childItem.getNodeName().compareTo("IncludeModules") == 0) {\r
676 //\r
677 // result will be updated\r
678 //\r
679 processNodes(childItem, result);\r
680 } else if (childItem.getNodeName().compareTo("FvName") == 0) {\r
681 \r
682 } else if (childItem.getNodeName().compareTo("InfFileName") == 0) {\r
683 \r
684 } else {\r
685 //\r
686 // Report Warning\r
687 //\r
688 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1']");\r
689 }\r
690 }\r
691 }\r
692 }\r
693 \r
694 return result;\r
695 }\r
696 \r
697 private void processNodes(Node node, Set<FpdModuleIdentification> result) throws EdkException {\r
698 //\r
699 // Found out all elements "Module"\r
700 //\r
701 NodeList childNodes = node.getChildNodes();\r
702 for (int j = 0; j < childNodes.getLength(); j++) {\r
703 Node childItem = childNodes.item(j);\r
704 if (childItem.getNodeType() == Node.ELEMENT_NODE) {\r
705 if (childItem.getNodeName().compareTo("Module") == 0) {\r
706 String moduleGuid = null;\r
707 String moduleVersion = null;\r
708 String packageGuid = null;\r
709 String packageVersion = null;\r
710 String arch = null;\r
711 \r
712 NamedNodeMap attr = childItem.getAttributes();\r
713 for (int i = 0; i < attr.getLength(); i++) {\r
714 Node attrItem = attr.item(i);\r
715 if (attrItem.getNodeName().compareTo("ModuleGuid") == 0) {\r
716 moduleGuid = attrItem.getNodeValue();\r
717 } else if (attrItem.getNodeName().compareTo("ModuleVersion") == 0) {\r
718 moduleVersion = attrItem.getNodeValue();\r
719 } else if (attrItem.getNodeName().compareTo("PackageGuid") == 0) {\r
720 packageGuid = attrItem.getNodeValue();\r
721 } else if (attrItem.getNodeName().compareTo("PackageVersion") == 0) {\r
722 packageVersion = attrItem.getNodeValue();\r
723 } else if (attrItem.getNodeName().compareTo("Arch") == 0) {\r
724 arch = attrItem.getNodeValue();\r
725 } else {\r
726 //\r
727 // Report warning\r
728 //\r
729 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised attribute " + attrItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module");\r
730 }\r
731 }\r
732 \r
733 PackageIdentification packageId = new PackageIdentification(packageGuid, packageVersion);\r
734 GlobalData.refreshPackageIdentification(packageId);\r
735 \r
736 ModuleIdentification moduleId = new ModuleIdentification(moduleGuid, moduleVersion);\r
737 moduleId.setPackage(packageId);\r
738 GlobalData.refreshModuleIdentification(moduleId);\r
739 \r
740 if (arch == null) {\r
741 throw new EdkException("Attribute [Arch] is required for element FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module. ");\r
742 }\r
743 \r
744 result.add(new FpdModuleIdentification(moduleId, arch));\r
745 } else {\r
746 //\r
747 // Report Warning\r
748 //\r
749 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules");\r
750 }\r
751 }\r
752 }\r
753 }\r
878ddf1f 754}\r