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