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