e28ac19eca828986a16440a12ab11ccd82d81b4a
[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.tianocore.build.toolchain.ToolChainInfo;
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 /// Mapping from FV apriori file to its type (PEI or DXE)
96 ///
97 Map<String, String> aprioriType = new HashMap<String, String>();
98
99 ///
100 /// FpdParserTask can specify some ANT properties.
101 ///
102 private Vector<Property> properties = new Vector<Property>();
103
104 SurfaceAreaQuery saq = null;
105
106 boolean isUnified = true;
107
108 public static String PEI_APRIORI_GUID = "1b45cc0a-156a-428a-af62-49864da0e6e6";
109
110 public static String DXE_APRIORI_GUID = "fc510ee7-ffdc-11d4-bd41-0080c73c8881";
111
112 /**
113 Public construct method. It is necessary for ANT task.
114 **/
115 public FpdParserTask() {
116 }
117
118 /**
119 ANT task's entry method. The main steps is described as following:
120
121 <ul>
122 <li>Initialize global information (Framework DB, SPD files and all MSA files
123 listed in SPD). This step will execute only once in whole build process;</li>
124 <li>Parse specified FPD file; </li>
125 <li>Generate FV.inf files; </li>
126 <li>Generate PlatformName_build.xml file for Flatform build; </li>
127 <li>Collect PCD information. </li>
128 </ul>
129
130 @throws BuildException
131 Surface area is not valid.
132 **/
133 public void execute() throws BuildException {
134 this.setTaskName("FpdParser");
135
136 //
137 // Parse FPD file
138 //
139 parseFpdFile();
140
141 //
142 // Prepare BUILD_DIR
143 //
144 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());
145
146 String buildDir = getProject().getProperty("BUILD_DIR");
147 //
148 // For every Target and ToolChain
149 //
150 String[] targetList = GlobalData.getToolChainInfo().getTargets();
151 for (int i = 0; i < targetList.length; i++) {
152 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
153 for(int j = 0; j < toolchainList.length; j++) {
154 //
155 // Prepare FV_DIR
156 //
157 String ffsCommonDir = buildDir + File.separatorChar
158 + targetList[i] + "_"
159 + toolchainList[j];
160 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
161 fvDir.mkdirs();
162 getProject().setProperty("FV_DIR", fvDir.getPath().replaceAll("(\\\\)", "/"));
163
164 //
165 // Gen Fv.inf files
166 //
167 genFvInfFiles(ffsCommonDir);
168 }
169 }
170
171 //
172 // Gen build.xml
173 //
174 String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";
175 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile, aprioriType);
176 fileGenerator.genBuildFile();
177
178 //
179 // Ant call ${PLATFORM}_build.xml
180 //
181 Ant ant = new Ant();
182 ant.setProject(getProject());
183 ant.setAntfile(platformBuildFile);
184 ant.setTarget(type);
185 ant.setInheritAll(true);
186 ant.init();
187 ant.execute();
188 }
189
190 /**
191 Generate Fv.inf files. The Fv.inf file is composed with four
192 parts: Options, Attributes, Components and Files. The Fv.inf files
193 will be under FV_DIR.
194
195 @throws BuildException
196 File write FV.inf files error.
197 **/
198 void genFvInfFiles(String ffsCommonDir) throws BuildException {
199 String[] validFv = saq.getFpdValidImageNames();
200 for (int i = 0; i < validFv.length; i++) {
201 //
202 // Get all global variables from FPD and set them to properties
203 //
204 String[][] globalVariables = saq.getFpdGlobalVariable();
205 for (int j = 0; j < globalVariables.length; j++) {
206 getProject().setProperty(globalVariables[j][0], globalVariables[j][1]);
207 }
208
209 getProject().setProperty("FV_FILENAME", validFv[i]);
210
211 File fvFile = new File(getProject().replaceProperties( getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".inf"));
212 if (fvFile.exists() && (fvFile.lastModified() >= fpdFile.lastModified())) {
213 //
214 // don't re-generate FV.inf if fpd has not been changed
215 //
216 continue;
217 }
218 fvFile.getParentFile().mkdirs();
219
220 try {
221 FileWriter fw = new FileWriter(fvFile);
222 BufferedWriter bw = new BufferedWriter(fw);
223
224 //
225 // Options
226 //
227 String[][] options = saq.getFpdOptions(validFv[i]);
228 if (options.length > 0) {
229 bw.write("[options]");
230 bw.newLine();
231 for (int j = 0; j < options.length; j++) {
232 StringBuffer str = new StringBuffer(100);
233 str.append(options[j][0]);
234 while (str.length() < 40) {
235 str.append(' ');
236 }
237 str.append("= ");
238 str.append(options[j][1]);
239 bw.write(getProject().replaceProperties(str.toString()));
240 bw.newLine();
241 }
242 bw.newLine();
243 }
244
245 //
246 // Attributes;
247 //
248 String[][] attributes = saq.getFpdAttributes(validFv[i]);
249 if (attributes.length > 0) {
250 bw.write("[attributes]");
251 bw.newLine();
252 for (int j = 0; j < attributes.length; j++) {
253 StringBuffer str = new StringBuffer(100);
254 str.append(attributes[j][0]);
255 while (str.length() < 40) {
256 str.append(' ');
257 }
258 str.append("= ");
259 str.append(attributes[j][1]);
260 bw.write(getProject().replaceProperties(str.toString()));
261 bw.newLine();
262 }
263 bw.newLine();
264 }
265
266 //
267 // Components
268 //
269 String[][] components = saq.getFpdComponents(validFv[i]);
270 if (components.length > 0) {
271 bw.write("[components]");
272 bw.newLine();
273 for (int j = 0; j < components.length; j++) {
274 StringBuffer str = new StringBuffer(100);
275 str.append(components[j][0]);
276 while (str.length() < 40) {
277 str.append(' ');
278 }
279 str.append("= ");
280 str.append(components[j][1]);
281 bw.write(getProject().replaceProperties(str.toString()));
282 bw.newLine();
283 }
284 bw.newLine();
285 }
286
287 //
288 // Files
289 //
290 Set<FpdModuleIdentification> moduleSeqSet = getModuleSequenceForFv(validFv[i]);
291
292 Set<FpdModuleIdentification> filesSet = fvs.get(validFv[i]);
293
294 FpdModuleIdentification[] files = null;
295
296 if (moduleSeqSet == null) {
297 if (filesSet != null) {
298 files = filesSet.toArray(new FpdModuleIdentification[filesSet.size()]);
299 }
300 } else if (filesSet == null) {
301 if (moduleSeqSet.size() != 0) {
302 throw new BuildException("Can not find any modules belongs to FV[" + validFv[i] + "], but listed some in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1']");
303 }
304 } else {
305 //
306 // if moduleSeqSet and filesSet is inconsistent, report error
307 //
308 if(moduleSeqSet.size() != filesSet.size()){
309 throw new BuildException("Modules for FV[" + validFv[i] + "] defined in FrameworkModules and in BuildOptions.UserExtensions[@UserID='IMAGES' @Identifier='1'] are inconsistent. ");
310 } else {
311 //
312 // whether all modules in moduleSeqSet listed in filesSet
313 //
314 Iterator<FpdModuleIdentification> iter = moduleSeqSet.iterator();
315 while (iter.hasNext()) {
316 FpdModuleIdentification item = iter.next();
317 if (!filesSet.contains(item)) {
318 throw new BuildException("Can not find " + item + " belongs to FV[" + validFv[i] + "]");
319 }
320 }
321 }
322
323 files = moduleSeqSet.toArray(new FpdModuleIdentification[moduleSeqSet.size()]);
324 }
325
326
327 if (files != null) {
328 bw.write("[files]");
329 bw.newLine();
330
331 Set<FpdModuleIdentification> modules = null;
332
333 if ( (modules = getPeiApriori(validFv[i])) != null) {
334 //
335 // Special GUID - validFv[i].FFS
336 //
337 String str = ffsCommonDir + File.separatorChar + "FV" + File.separatorChar + PEI_APRIORI_GUID + "-" + validFv[i] + ".FFS";
338 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));
339 bw.newLine();
340
341 File aprioriFile = new File(getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".apr");
342 aprioriType.put(validFv[i], PEI_APRIORI_GUID);
343 genAprioriFile(modules, aprioriFile);
344 } else if((modules = getDxeApriori(validFv[i])) != null) {
345 //
346 // Special GUID - validFv[i].FFS
347 //
348 String str = ffsCommonDir + File.separatorChar + "FV" + File.separatorChar + DXE_APRIORI_GUID + "-" + validFv[i] + ".FFS";
349 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));
350 bw.newLine();
351
352 File aprioriFile = new File(getProject().getProperty("FV_DIR") + File.separatorChar + validFv[i] + ".apr");
353 aprioriType.put(validFv[i], DXE_APRIORI_GUID);
354 genAprioriFile(modules, aprioriFile);
355 }
356
357 for (int j = 0; j < files.length; j++) {
358 String str = ffsCommonDir + File.separatorChar + outfiles.get(files[j]);
359 bw.write(getProject().replaceProperties("EFI_FILE_NAME = " + str));
360 bw.newLine();
361 }
362 }
363 bw.flush();
364 bw.close();
365 fw.close();
366 } catch (IOException ex) {
367 BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage());
368 buildException.setStackTrace(ex.getStackTrace());
369 throw buildException;
370 } catch (EdkException ex) {
371 BuildException buildException = new BuildException("Generation of the FV file [" + fvFile.getPath() + "] failed!\n" + ex.getMessage());
372 buildException.setStackTrace(ex.getStackTrace());
373 throw buildException;
374 }
375 }
376 }
377
378 /**
379 This method is used for Single Module Build.
380
381 @throws BuildException
382 FPD file is not valid.
383 **/
384 public void parseFpdFile(File fpdFile) throws BuildException, EdkException {
385 this.fpdFile = fpdFile;
386 parseFpdFile();
387
388 //
389 // Call Platform_build.xml prebuild firstly in stand-alone build
390 // Prepare BUILD_DIR
391 //
392 isUnified = OutputManager.getInstance().prepareBuildDir(getProject());
393
394 String buildDir = getProject().getProperty("BUILD_DIR");
395 //
396 // For every Target and ToolChain
397 //
398 String[] targetList = GlobalData.getToolChainInfo().getTargets();
399 for (int i = 0; i < targetList.length; i++) {
400 String[] toolchainList = GlobalData.getToolChainInfo().getTagnames();
401 for(int j = 0; j < toolchainList.length; j++) {
402 //
403 // Prepare FV_DIR
404 //
405 String ffsCommonDir = buildDir + File.separatorChar
406 + targetList[i] + "_"
407 + toolchainList[j];
408 File fvDir = new File(ffsCommonDir + File.separatorChar + "FV");
409 fvDir.mkdirs();
410 }
411 }
412
413 String platformBuildFile = buildDir + File.separatorChar + platformId.getName() + "_build.xml";
414 PlatformBuildFileGenerator fileGenerator = new PlatformBuildFileGenerator(getProject(), outfiles, fvs, isUnified, saq, platformBuildFile, aprioriType);
415 fileGenerator.genBuildFile();
416
417 Ant ant = new Ant();
418 ant.setProject(getProject());
419 ant.setAntfile(platformBuildFile);
420 ant.setTarget("prebuild");
421 ant.setInheritAll(true);
422 ant.init();
423 ant.execute();
424 }
425
426 /**
427 Parse FPD file.
428
429 @throws BuildException
430 FPD file is not valid.
431 **/
432 void parseFpdFile() throws BuildException {
433 try {
434 XmlObject doc = XmlObject.Factory.parse(fpdFile);
435
436 if (!doc.validate()) {
437 throw new BuildException("Platform Surface Area file [" + fpdFile.getPath() + "] format is invalid!");
438 }
439
440 Map<String, XmlObject> map = new HashMap<String, XmlObject>();
441 map.put("PlatformSurfaceArea", doc);
442 saq = new SurfaceAreaQuery(map);
443
444 //
445 // Initialize
446 //
447 platformId = saq.getFpdHeader();
448 platformId.setFpdFile(fpdFile);
449 getProject().setProperty("PLATFORM", platformId.getName());
450 getProject().setProperty("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));
451 getProject().setProperty("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));
452 getProject().setProperty("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));
453
454 if( !FrameworkBuildTask.multithread) {
455 FrameworkBuildTask.originalProperties.put("PLATFORM", platformId.getName());
456 FrameworkBuildTask.originalProperties.put("PLATFORM_FILE", platformId.getRelativeFpdFile().replaceAll("(\\\\)", "/"));
457 FrameworkBuildTask.originalProperties.put("PLATFORM_DIR", platformId.getFpdFile().getParent().replaceAll("(\\\\)", "/"));
458 FrameworkBuildTask.originalProperties.put("PLATFORM_RELATIVE_DIR", platformId.getPlatformRelativeDir().replaceAll("(\\\\)", "/"));
459 }
460
461 //
462 // Build mode. User-defined output dir.
463 //
464 String buildMode = saq.getFpdIntermediateDirectories();
465 String userDefinedOutputDir = saq.getFpdOutputDirectory();
466
467 OutputManager.getInstance().setup(userDefinedOutputDir, buildMode);
468
469 //
470 // TBD. Deal PCD and BuildOption related Info
471 //
472 GlobalData.setFpdBuildOptions(saq.getFpdBuildOptions());
473
474 GlobalData.setToolChainPlatformInfo(saq.getFpdToolChainInfo());
475
476 //
477 // Parse all list modules SA
478 //
479 parseModuleSAFiles();
480
481 //
482 // TBD. Deal PCD and BuildOption related Info
483 //
484 parseToolChainFamilyOptions();
485 parseToolChainOptions();
486
487 //
488 // check if the tool chain is valid or not
489 //
490 checkToolChain();
491
492 saq.push(map);
493
494 //
495 // Pcd Collection. Call CollectPCDAction to collect pcd info.
496 //
497 PlatformPcdPreprocessActionForBuilding ca = new PlatformPcdPreprocessActionForBuilding();
498 ca.perform(platformId.getFpdFile().getPath());
499 } catch (IOException ex) {
500 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());
501 buildException.setStackTrace(ex.getStackTrace());
502 throw buildException;
503 } catch (XmlException ex) {
504 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());
505 buildException.setStackTrace(ex.getStackTrace());
506 throw buildException;
507 } catch (EdkException ex) {
508 BuildException buildException = new BuildException("Parsing of the FPD file [" + fpdFile.getPath() + "] failed!\n" + ex.getMessage());
509 buildException.setStackTrace(ex.getStackTrace());
510 throw buildException;
511 }
512 }
513
514 /**
515 Parse all modules listed in FPD file.
516 **/
517 void parseModuleSAFiles() throws EdkException{
518 Map<FpdModuleIdentification, Map<String, XmlObject>> moduleSAs = saq.getFpdModules();
519
520 //
521 // For every Module lists in FPD file.
522 //
523 Set<FpdModuleIdentification> keys = moduleSAs.keySet();
524 Iterator iter = keys.iterator();
525 while (iter.hasNext()) {
526 FpdModuleIdentification fpdModuleId = (FpdModuleIdentification) iter.next();
527
528 //
529 // Judge if Module is existed?
530 // TBD
531 GlobalData.registerFpdModuleSA(fpdModuleId, moduleSAs.get(fpdModuleId));
532
533 //
534 // Put fpdModuleId to the corresponding FV
535 //
536 saq.push(GlobalData.getDoc(fpdModuleId));
537 String fvBinding = saq.getModuleFvBindingKeyword();
538
539 fpdModuleId.setFvBinding(fvBinding);
540 updateFvs(fvBinding, fpdModuleId);
541
542 //
543 // Prepare for out put file name
544 //
545 ModuleIdentification moduleId = fpdModuleId.getModule();
546
547 String baseName = saq.getModuleOutputFileBasename();
548
549 if (baseName == null) {
550 baseName = moduleId.getName();
551 }
552 outfiles.put(fpdModuleId, fpdModuleId.getArch() + File.separatorChar
553 + moduleId.getGuid() + "-" + baseName
554 + getSuffix(moduleId.getModuleType()));
555
556 //
557 // parse module build options, if any
558 //
559 GlobalData.addModuleToolChainOption(fpdModuleId, parseModuleBuildOptions(false));
560 GlobalData.addModuleToolChainFamilyOption(fpdModuleId, parseModuleBuildOptions(true));
561
562 //
563 // parse MSA build options
564 //
565 GlobalData.addMsaBuildOption(moduleId, parseMsaBuildOptions(false));
566 GlobalData.addMsaFamilyBuildOption(moduleId, parseMsaBuildOptions(true));
567
568 ModuleIdentification[] libraryInstances = saq.getLibraryInstance(null);
569 for (int i = 0; i < libraryInstances.length; i++) {
570 saq.push(GlobalData.getDoc(libraryInstances[i], fpdModuleId.getArch()));
571 GlobalData.addMsaBuildOption(libraryInstances[i], parseMsaBuildOptions(false));
572 GlobalData.addMsaFamilyBuildOption(libraryInstances[i], parseMsaBuildOptions(true));
573 saq.pop();
574 }
575
576 saq.pop();
577 }
578 }
579
580 ToolChainMap parseModuleBuildOptions(boolean toolChainFamilyFlag) throws EdkException {
581 String[][] options = saq.getModuleBuildOptions(toolChainFamilyFlag);
582 if (options == null || options.length == 0) {
583 return new ToolChainMap();
584 }
585 return parseOptions(options);
586 }
587
588 private ToolChainMap parsePlatformBuildOptions(boolean toolChainFamilyFlag) throws EdkException {
589 String[][] options = saq.getPlatformBuildOptions(toolChainFamilyFlag);
590 if (options == null || options.length == 0) {
591 return new ToolChainMap();
592 }
593 return parseOptions(options);
594 }
595
596 ToolChainMap parseMsaBuildOptions(boolean toolChainFamilyFlag) throws EdkException {
597 String[][] options = saq.getMsaBuildOptions(toolChainFamilyFlag);
598 if (options == null || options.length == 0) {
599 return new ToolChainMap();
600 }
601 return parseOptions(options);
602 }
603
604 private ToolChainMap parseOptions(String[][] options) throws EdkException {
605 ToolChainMap map = new ToolChainMap();
606 int flagIndex = ToolChainElement.ATTRIBUTE.value;
607
608 for (int i = 0; i < options.length; ++i) {
609 String flagString = options[i][flagIndex];
610 if (flagString == null) {
611 flagString = "";
612 }
613 options[i][flagIndex] = ToolDefinitions.TOOLS_DEF_ATTRIBUTE_FLAGS;
614 map.put(options[i], flagString.trim());
615 }
616
617 return map;
618 }
619
620 private void parseToolChainFamilyOptions() throws EdkException {
621 GlobalData.setPlatformToolChainFamilyOption(parsePlatformBuildOptions(true));
622 }
623
624 private void parseToolChainOptions() throws EdkException {
625 GlobalData.setPlatformToolChainOption(parsePlatformBuildOptions(false));
626 }
627
628 /**
629 Add the current module to corresponding FV.
630
631 @param fvName current FV name
632 @param moduleName current module identification
633 **/
634 void updateFvs(String fvName, FpdModuleIdentification fpdModuleId) {
635 if (fvName == null || fvName.trim().length() == 0) {
636 fvName = "NULL";
637 }
638 String[] fvNameArray = fvName.split("[, \t]+");
639 for (int i = 0; i < fvNameArray.length; i++) {
640 //
641 // Put module to corresponding fvName
642 //
643 if (fvs.containsKey(fvNameArray[i])) {
644 Set<FpdModuleIdentification> set = fvs.get(fvNameArray[i]);
645 set.add(fpdModuleId);
646 } else {
647 Set<FpdModuleIdentification> set = new LinkedHashSet<FpdModuleIdentification>();
648 set.add(fpdModuleId);
649 fvs.put(fvNameArray[i], set);
650 }
651 }
652 }
653
654 /**
655 Get the suffix based on module type. Current relationship are listed:
656
657 <pre>
658 <b>ModuleType</b> <b>Suffix</b>
659 BASE .FFS
660 SEC .SEC
661 PEI_CORE .PEI
662 PEIM .PEI
663 DXE_CORE .DXE
664 DXE_DRIVER .DXE
665 DXE_RUNTIME_DRIVER .DXE
666 DXE_SAL_DRIVER .DXE
667 DXE_SMM_DRIVER .DXE
668 TOOL .FFS
669 UEFI_DRIVER .DXE
670 UEFI_APPLICATION .APP
671 USER_DEFINED .FFS
672 </pre>
673
674 @param moduleType module type
675 @return
676 @throws BuildException
677 If module type is null
678 **/
679 public static String getSuffix(String moduleType) throws BuildException {
680 if (moduleType == null) {
681 throw new BuildException("Module type is not specified.");
682 }
683
684 String[][] suffix = EdkDefinitions.ModuleTypeExtensions;
685
686 for (int i = 0; i < suffix.length; i++) {
687 if (suffix[i][0].equalsIgnoreCase(moduleType)) {
688 return suffix[i][1];
689 }
690 }
691 //
692 // Default is '.FFS'
693 //
694 return ".FFS";
695 }
696 /**
697 Add a property.
698
699 @param p property
700 **/
701 public void addProperty(Property p) {
702 properties.addElement(p);
703 }
704
705 public void setFpdFile(File fpdFile) {
706 this.fpdFile = fpdFile;
707 }
708
709 public void setType(String type) {
710 this.type = type;
711 }
712
713 public String getAllArchForModule(ModuleIdentification moduleId) {
714 String archs = "";
715 Iterator<FpdModuleIdentification> iter = outfiles.keySet().iterator();
716 while (iter.hasNext()) {
717 FpdModuleIdentification fpdModuleId = iter.next();
718
719 if (fpdModuleId.getModule().equals(moduleId)) {
720 archs += fpdModuleId.getArch() + " ";
721 }
722 }
723
724 return archs;
725 }
726
727 private void genAprioriFile(Set<FpdModuleIdentification> modules, File file) {
728 try {
729 FileWriter fw = new FileWriter(file);
730 BufferedWriter bw = new BufferedWriter(fw);
731
732 Iterator<FpdModuleIdentification> iter = modules.iterator();
733 while(iter.hasNext()) {
734 bw.write(iter.next().getModule().getGuid());
735 bw.newLine();
736 }
737
738 bw.flush();
739 bw.close();
740 fw.close();
741 } catch (IOException ex) {
742 BuildException buildException = new BuildException("Generation of the Apriori file [" + file.getPath() + "] failed!\n" + ex.getMessage());
743 buildException.setStackTrace(ex.getStackTrace());
744 throw buildException;
745 }
746 }
747
748 private Set<FpdModuleIdentification> getPeiApriori(String fvName) throws EdkException {
749 Node node = saq.getPeiApriori(fvName);
750 Set<FpdModuleIdentification> result = new LinkedHashSet<FpdModuleIdentification>();
751 if (node == null) {
752 return null;
753 }
754
755 NodeList childNodes = node.getChildNodes();
756 for (int i = 0; i < childNodes.getLength(); i++) {
757 Node childItem = childNodes.item(i);
758 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
759 //
760 // Find child elements "IncludeModules"
761 //
762 if (childItem.getNodeName().compareTo("IncludeModules") == 0) {
763 //
764 // result will be updated
765 //
766 processNodes(childItem, result);
767 } else if (childItem.getNodeName().compareTo("FvName") == 0) {
768
769 } else if (childItem.getNodeName().compareTo("InfFileName") == 0) {
770
771 } else {
772 //
773 // Report Warning
774 //
775 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='APRIORI' Identifier='0']");
776 }
777 }
778 }
779
780 return result;
781 }
782
783 private Set<FpdModuleIdentification> getDxeApriori(String fvName) throws EdkException {
784 Node node = saq.getDxeApriori(fvName);
785 Set<FpdModuleIdentification> result = new LinkedHashSet<FpdModuleIdentification>();
786 if (node == null) {
787 return null;
788 }
789
790 NodeList childNodes = node.getChildNodes();
791 for (int i = 0; i < childNodes.getLength(); i++) {
792 Node childItem = childNodes.item(i);
793 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
794 //
795 // Find child elements "IncludeModules"
796 //
797 if (childItem.getNodeName().compareTo("IncludeModules") == 0) {
798 //
799 // result will be updated
800 //
801 processNodes(childItem, result);
802 } else if (childItem.getNodeName().compareTo("FvName") == 0) {
803
804 } else if (childItem.getNodeName().compareTo("InfFileName") == 0) {
805
806 } else {
807 //
808 // Report Warning
809 //
810 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='APRIORI' Identifier='1']");
811 }
812 }
813 }
814
815 return result;
816 }
817
818 private Set<FpdModuleIdentification> getModuleSequenceForFv(String fvName) throws EdkException {
819 Node node = saq.getFpdModuleSequence(fvName);
820 Set<FpdModuleIdentification> result = new LinkedHashSet<FpdModuleIdentification>();
821
822 if ( node == null) {
823 EdkLog.log(this, EdkLog.EDK_WARNING, "FV[" + fvName + "] does not specify module sequence in FPD. Assuming present sequence as default sequence in FV. ");
824 return null;
825 } else {
826 NodeList childNodes = node.getChildNodes();
827 for (int i = 0; i < childNodes.getLength(); i++) {
828 Node childItem = childNodes.item(i);
829 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
830 //
831 // Find child elements "IncludeModules"
832 //
833 if (childItem.getNodeName().compareTo("IncludeModules") == 0) {
834 //
835 // result will be updated
836 //
837 processNodes(childItem, result);
838 } else if (childItem.getNodeName().compareTo("FvName") == 0) {
839
840 } else if (childItem.getNodeName().compareTo("InfFileName") == 0) {
841
842 } else {
843 //
844 // Report Warning
845 //
846 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1']");
847 }
848 }
849 }
850 }
851
852 return result;
853 }
854
855 private void processNodes(Node node, Set<FpdModuleIdentification> result) throws EdkException {
856 //
857 // Found out all elements "Module"
858 //
859 NodeList childNodes = node.getChildNodes();
860 for (int j = 0; j < childNodes.getLength(); j++) {
861 Node childItem = childNodes.item(j);
862 if (childItem.getNodeType() == Node.ELEMENT_NODE) {
863 if (childItem.getNodeName().compareTo("Module") == 0) {
864 String moduleGuid = null;
865 String moduleVersion = null;
866 String packageGuid = null;
867 String packageVersion = null;
868 String arch = null;
869
870 NamedNodeMap attr = childItem.getAttributes();
871 for (int i = 0; i < attr.getLength(); i++) {
872 Node attrItem = attr.item(i);
873 if (attrItem.getNodeName().compareTo("ModuleGuid") == 0) {
874 moduleGuid = attrItem.getNodeValue();
875 } else if (attrItem.getNodeName().compareTo("ModuleVersion") == 0) {
876 moduleVersion = attrItem.getNodeValue();
877 } else if (attrItem.getNodeName().compareTo("PackageGuid") == 0) {
878 packageGuid = attrItem.getNodeValue();
879 } else if (attrItem.getNodeName().compareTo("PackageVersion") == 0) {
880 packageVersion = attrItem.getNodeValue();
881 } else if (attrItem.getNodeName().compareTo("Arch") == 0) {
882 arch = attrItem.getNodeValue();
883 } else {
884 //
885 // Report warning
886 //
887 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised attribute " + attrItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module");
888 }
889 }
890
891 PackageIdentification packageId = new PackageIdentification(packageGuid, packageVersion);
892 GlobalData.refreshPackageIdentification(packageId);
893
894 ModuleIdentification moduleId = new ModuleIdentification(moduleGuid, moduleVersion);
895 moduleId.setPackage(packageId);
896 GlobalData.refreshModuleIdentification(moduleId);
897
898 if (arch == null) {
899 throw new EdkException("Attribute [Arch] is required for element FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules.Module. ");
900 }
901
902 result.add(new FpdModuleIdentification(moduleId, arch));
903 } else {
904 //
905 // Report Warning
906 //
907 EdkLog.log(this, EdkLog.EDK_WARNING, "Unrecognised element " + childItem.getNodeName() + " under FPD.BuildOptions.UserExtensions[UserID='IMAGES' Identifier='1'].IncludeModules");
908 }
909 }
910 }
911 }
912
913
914 private void checkToolChain() throws EdkException {
915 ToolChainInfo toolChainInfo = GlobalData.getToolChainInfo();
916
917 if (toolChainInfo.getTargets().length == 0) {
918 throw new EdkException("No valid target found! "+
919 "Please check the TARGET definition in Tools/Conf/target.txt, "+
920 "or the <BuildTarget>, <BuildOptions> in the FPD file.");
921 }
922
923 if (toolChainInfo.getTagnames().length == 0) {
924 throw new EdkException("No valid tool chain found! "+
925 "Please check the TOOL_CHAIN_TAG definition in Tools/Conf/target.txt, "+
926 "or the <BuildOptions> in the FPD file.");
927 }
928
929 if (toolChainInfo.getArchs().length == 0) {
930 throw new EdkException("No valid architecture found! "+
931 "Please check the TARGET_ARCH definition in Tools/Conf/target.txt, "+
932 "or the <SupportedArchitectures>, <BuildOptions> in the FPD file.");
933 }
934
935 if (toolChainInfo.getCommands().length == 0) {
936 throw new EdkException("No valid COMMAND found! Please check the tool chain definitions "+
937 "in Tools/Conf/tools_def.txt.");
938 }
939 }
940 }