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