Removed dead lines that had been commented out.
[mirror_edk2.git] / Tools / Source / Merge / src / org / tianocore / Merge / CombineMsa.java
1 // @file
2 // This Class processes multiple MSA files and merges them into a single,
3 // merged MSA file. It will optionally add the merged MSA file into a package.
4 //
5 //
6 // Copyright (c) 2006, Intel Corporation All rights reserved.
7 //
8 // This program and the accompanying materials are licensed and made
9 // available under the terms and conditions of the BSD License which
10 // accompanies this distribution. The full text of the license may
11 // be found at 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 //
17
18 package org.tianocore.Merge;
19
20 import java.io.*;
21 import java.util.*;
22 // import java.lang.*;
23 // import java.lang.ExceptionInInitializerError;
24
25 // import org.apache.xmlbeans.*;
26 import org.apache.xmlbeans.XmlCursor;
27 // import org.apache.xmlbeans.XmlObject;
28 import org.apache.xmlbeans.XmlOptions;
29 import org.apache.xmlbeans.XmlException;
30 import org.tianocore.*;
31
32 // import org.tianocore.*;
33 import org.tianocore.ModuleSurfaceAreaDocument.*;
34 import org.tianocore.MsaHeaderDocument.*;
35 import org.tianocore.LicenseDocument.*;
36 import org.tianocore.ModuleDefinitionsDocument.*;
37 import org.tianocore.LibraryClassDefinitionsDocument.*;
38 import org.tianocore.SourceFilesDocument.*;
39 import org.tianocore.PackageDependenciesDocument.*;
40 import org.tianocore.ProtocolsDocument.*;
41 import org.tianocore.EventsDocument.*;
42 import org.tianocore.HobsDocument.*;
43 import org.tianocore.PPIsDocument.*;
44 import org.tianocore.VariablesDocument.*;
45 import org.tianocore.BootModesDocument.*;
46 import org.tianocore.SystemTablesDocument.*;
47 import org.tianocore.DataHubsDocument.*;
48 import org.tianocore.HiiPackagesDocument.*;
49 import org.tianocore.GuidsDocument.*;
50 import org.tianocore.ExternsDocument.*;
51 import org.tianocore.PcdCodedDocument.*;
52 import org.tianocore.ModuleBuildOptionsDocument.*;
53 import org.tianocore.UserExtensionsDocument.*;
54
55 import org.tianocore.PackageSurfaceAreaDocument.*;
56
57 public class CombineMsa {
58
59 private final int DEBUG = 0;
60
61 private final int PASS = 0;
62
63 private final int FAIL = 1;
64
65 private final int FOUND = 0;
66
67 private final int NOTFOUND = 1;
68
69 private int result = PASS;
70
71 private String licenseTxt = "";
72
73 private ArrayList<String> aLicenses = new ArrayList<String>();
74
75 private String Copyright = "";
76
77 private ArrayList<String> aCopyright = new ArrayList<String>();
78
79 private String Abstract = "\n Merged Modules: \n";
80
81 private String Description = "\n Merging Modules: \n";
82
83 private String sArchitectures = "";
84
85 private MsaHeader header = null;
86
87 private final String Specification = "FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052";
88
89 private ModuleSurfaceArea mergeMsaFile = null;
90
91 private ModuleSurfaceArea leafMsa = null;
92
93 private ModuleDefinitions moduleDefs = null;
94
95 private LibraryClassDefinitions libClassDefs = null;
96
97 private ArrayList<String> aLibClassDefs = new ArrayList<String>();
98
99 private int libraryClassIndex = 0;
100
101 private SourceFiles mergeSourceFiles = null;
102
103 private int sourceFileIndex = 0;
104
105 private PackageDependencies mergePackageDependencies = null;
106
107 private ArrayList<String> aPackageList = new ArrayList<String>();
108
109 private int packageDependenciesIndex = 0;
110
111 private Protocols mergeProtocols = null;
112
113 private ArrayList<String> aProtocolList = new ArrayList<String>();
114
115 private ArrayList<String> aProtocolNotifyList = new ArrayList<String>();
116
117 private int protocolIndex = 0;
118
119 private int protocolNotifyIndex = 0;
120
121 private Events mergeEvents = null;
122
123 private Events.CreateEvents mergeCreateEvents = null;
124
125 private Events.SignalEvents mergeSignalEvents = null;
126
127 private ArrayList<String> aCreateEventsList = new ArrayList<String>();
128
129 private ArrayList<String> aSignalEventsList = new ArrayList<String>();
130
131 private int createEventIndex = 0;
132
133 private int signalEventIndex = 0;
134
135 private Hobs mergeHobs = null;
136
137 private ArrayList<String> aHobsList = new ArrayList<String>();
138
139 private int hobsIndex = 0;
140
141 private PPIs mergePpis = null;
142
143 private ArrayList<String> aPpiList = new ArrayList<String>();
144
145 private ArrayList<String> aPpiNotifyList = new ArrayList<String>();
146
147 private int ppiIndex = 0;
148
149 private int ppiNotifyIndex = 0;
150
151 private Variables mergeVariables = null;
152
153 private ArrayList<String> aVariablesList = new ArrayList<String>();
154
155 private int variablesIndex = 0;
156
157 private BootModes mergeBootModes = null;
158
159 private ArrayList<String> aBootModesList = new ArrayList<String>();
160
161 private int bootModesIndex = 0;
162
163 private SystemTables mergeSystemTables = null;
164
165 private ArrayList<String> aSystemTablesList = new ArrayList<String>();
166
167 private int systemTableIndex = 0;
168
169 private DataHubs mergeDataHubs = null;
170
171 private ArrayList<String> aDataHubsList = new ArrayList<String>();
172
173 private int dataHubsIndex = 0;
174
175 private HiiPackages mergeHiiPackages = null;
176
177 private ArrayList<String> aHiiPackagesList = new ArrayList<String>();
178
179 private int hiiPackageIndex = 0;
180
181 private Guids mergeGuids = null;
182
183 private ArrayList<String> aGuidsList = new ArrayList<String>();
184
185 private int guidsIndex = 0;
186
187 private Externs mergeExterns = null;
188
189 private ArrayList<String> aEntryPointList = new ArrayList<String>();
190
191 private ArrayList<String> aUnloadImageList = new ArrayList<String>();
192
193 private ArrayList<String> aDriverBindingList = new ArrayList<String>();
194
195 private ArrayList<String> aConstructorList = new ArrayList<String>();
196
197 private ArrayList<String> aDestructorList = new ArrayList<String>();
198
199 private ArrayList<String> aVirtualAddressMapList = new ArrayList<String>();
200
201 private ArrayList<String> aExitBootServicesList = new ArrayList<String>();
202
203 private int externsIndex = 0;
204
205 private ArrayList<String> aSpecArray = new ArrayList<String>();
206
207 private int specIndex = 0;
208
209 private PcdCoded mergePcdCoded = null;
210
211 private ArrayList<String> aPcdCNameList = new ArrayList<String>();
212
213 private ArrayList<String> aPcdItemTypeList = new ArrayList<String>();
214
215 private int pcdIndex = 0;
216
217 private ModuleBuildOptions mergeBuildOptions = null;
218
219 private UserExtensions mergeUserExtensions = null;
220
221 private String mergeUsage = "";
222
223 private String leafUsage = "";
224
225 private int VERBOSE = 0;
226
227 // The combineMsaFiles routine is the primary routine for creating a
228 // Merged MSA file.
229
230 public int combineMsaFiles(String msaFilename, ArrayList<String> msaFiles, String uiName, String spdFilename,
231 String baseName, int Flags) {
232 // msaFile has been verified to either not exist, or, if it does exist,
233 // it will be over written.
234 // All files in the msaFiles ArrayList have been verifed to exist.
235 // If the uiName is not null, we will have a new UI Name for the merged
236 // module.
237 // If the uiName is null, we will use the module name from the first
238 // Leaf module.
239 // If the spdFile is not null, the Package (SPD) file has been verified
240 // to exist.
241 // If the spdFile is null, don't attempt to add the new msa file.
242
243 if (Flags > 0)
244 VERBOSE = 1;
245 if (mergeMsaFile == null) {
246 //
247 // create the data structure for the merged Module
248 //
249 mergeMsaFile = ModuleSurfaceArea.Factory.newInstance();
250
251 System.out.println("Merging " + msaFiles.size() + " Modules");
252 //
253 // we always require a Header and a Module Definition section.
254 // These will be added to the mergeMsaFile after we have completed
255 // all processing of the Leaf MSA files.
256 //
257 header = MsaHeaderDocument.Factory.newInstance().addNewMsaHeader();
258 moduleDefs = ModuleDefinitionsDocument.Factory.newInstance().addNewModuleDefinitions();
259 //
260 // A merged module cannot be created from binary modules - we force
261 // the new module to be source here, however we will test every
262 // module to make sure that none are binary; exiting the program if
263 // a module is binary
264 //
265 moduleDefs.setBinaryModule(false);
266
267 for (int i = 0; i < msaFiles.size(); i++) {
268 String leafFilename = msaFiles.get(i).toString();
269 leafMsa = getLeafFile(leafFilename);
270 if (leafMsa == null) {
271 System.out.println("Could not read Leaf MSA file: " + leafFilename);
272 System.exit(FAIL);
273 }
274 if (i == 0) {
275 //
276 // Special code for first file, since this file is used
277 // to initialize some of the data in the mergeMsaFile.
278 // Set the Merge module's ModuleName to the name in the
279 // first Leaf Module. If a new module name is given,
280 // over write it later, just before writing the Merge
281 // Module MSA file.
282 header.setModuleName(leafMsa.getMsaHeader().getModuleName().toString());
283 //
284 // All modules must be of the same module type, we set it
285 // here, and test the other Leaf modules' type later.
286 header.setModuleType(leafMsa.getMsaHeader().getModuleType());
287 //
288 // This is a new Module, so we need a new GUID
289 header.setGuidValue(UUID.randomUUID().toString());
290 //
291 // Use the version from the first Leaf module as the
292 // Merge Module version number.
293 header.setVersion(leafMsa.getMsaHeader().getVersion().toString());
294 //
295 // There is no special requirement for processing the
296 // following, so we just fall through on these elements
297 // of the header.
298 // Abstract will be added after parsing all leaf MSA files.
299 // Description will be added after parsing all leaf MSA files.
300 // Copyright will be added after parsing all leaf MSA files.
301 // License will be added after parsing all leaf MSA files.
302 //
303 // Force the specification to match this tool's spec version.
304 header.setSpecification(Specification);
305 //
306 // Set the Merged Module's Output Basename to match the first
307 // leaf module
308 String OutputFileName = leafMsa.getModuleDefinitions().getOutputFileBasename().toString();
309 //
310 // Just in case someone put a space character in the first
311 // leaf module's output filename, replace the spaces with
312 // an underscore.
313 OutputFileName.replace(" ", "_");
314 moduleDefs.setOutputFileBasename(OutputFileName);
315 //
316 // We start with the first module's list of supported
317 // architectures. As we process the additional leaf modules,
318 // we may have to remove some supported architectures from
319 // the list, as we can only build for the "least common
320 // denominator" subset of architectures.
321 sArchitectures = leafMsa.getModuleDefinitions().getSupportedArchitectures().toString();
322 if ((DEBUG > 5) || (VERBOSE > 5))
323 System.out.println("New Header: \"" + header.getModuleName().toString() + "\"");
324 }
325 //
326 // We test the license in each leaf module, and will only print
327 // licenses that are may be different in wording (white spaces
328 // and line feeds are ignored in this test.)
329 if (leafMsa.getMsaHeader().getLicense() != null)
330 licenseTxt += checkDuplicateStrings(leafMsa.getMsaHeader().getLicense().getStringValue().trim(),
331 aLicenses);
332 if ((DEBUG > 10) || (VERBOSE > 10))
333 System.out.println("License: " + licenseTxt);
334 //
335 // We test the copyright line from each leaf module, and will
336 // add additional copyright lines only if they are different
337 // in wording (white spaces and line feeds are ignored in this
338 // test.)
339 if (leafMsa.getMsaHeader().getCopyright() != null)
340 Copyright += checkDuplicateStrings(leafMsa.getMsaHeader().getCopyright().toString().trim(),
341 aCopyright);
342 if ((DEBUG > 10) || (VERBOSE > 10))
343 System.out.println("Copyright: " + Copyright);
344 //
345 // ALL leaf modules must be of the same Module Type, if not,
346 // print an error and exit.
347 if (header.getModuleType() != leafMsa.getMsaHeader().getModuleType()) {
348 System.out.println("ERROR: Module Types different!");
349 System.out.println(" Expected: " + header.getModuleType());
350 System.out.println(" " + leafFilename + " ModuleType: " + leafMsa.getMsaHeader().getModuleType());
351 System.out.println("Merge ABORTED!");
352 System.exit(FAIL);
353 }
354 //
355 // Combine the Abstract and Descriptions into a single
356 // description entry, prefixing each with the Leaf MSA filename,
357 // so you know which description is from which Leaf module.
358 Description += " -- " + leafFilename + " -- \n Abstract: "
359 + leafMsa.getMsaHeader().getAbstract().toString() + "\n Description: "
360 + leafMsa.getMsaHeader().getDescription().toString() + "\n";
361 //
362 // Use the Abstract of the Merged Module to list the Leaf
363 // Module's MSA files.
364 Abstract += " -- " + leafFilename + " -- \n";
365 //
366 // Ignore ClonedFrom right now
367 //
368
369 // Process Supported Architectures
370 // A merged module supports the lowest common set of
371 // architectures
372 String testArch = "";
373 if (leafMsa.getModuleDefinitions().getSupportedArchitectures() == null) {
374 System.out
375 .println("Module " + leafFilename + " does not have the Supported Architectures defined!");
376 System.out.println("Supported Architectures is a required element!");
377 System.out.println("Merge ABORTED!");
378 System.exit(FAIL);
379 }
380 testArch = leafMsa.getModuleDefinitions().getSupportedArchitectures().toString();
381 String aArch[] = sArchitectures.split(" ");
382 for (int ictr = 0; ictr < aArch.length; ictr++) {
383 if (!testArch.contains(aArch[ictr])) {
384 sArchitectures = sArchitectures.replace(aArch[ictr], "");
385 }
386 }
387 if (sArchitectures.length() < 2) {
388 System.out.println("ERROR: The Leaf Modules' Supported Architectures are mutually exclusive.");
389 System.out.println("At least one architecture must be common to all Leaf Modules!");
390 System.out.println("Merge Aborting!");
391 System.exit(FAIL);
392 }
393 //
394 // Now start to process the rest of the Leaf Module's MSA files.
395 // We will only test a Leaf module's section if it has data, skipping
396 // empty sections
397 // As part of this process, we will only create a Library Class Definition
398 // if one was defined, and we will only do it one time.
399 if (leafMsa.isSetLibraryClassDefinitions()) {
400 //
401 // If libClassDefs == null, create a new libClassDefs and add
402 // this module's libClassDefs to the merge Module's
403 // If libClassDefs != null, check that we have only unique LibraryClass entries
404 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
405 // Mark the LibraryClass as ALWAYS_PRODUCED
406 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
407 // Mark the LibraryClass as ALWAYS_CONSUMED
408 // It is permissable to have one PRODUCED and one CONSUMED entry
409 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
410 // and another Leaf uses BY_START, create two entries, one for each.
411 //
412 // The RecommendedInstance attributes can be ignored!
413 //
414 // First PASS of the TOOL
415 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
416 // this as an error!
417 // Probable Enhancement
418 // The SupArchList, if set, must be for the "Lowest Common Denominator"
419 //
420 // First PASS of the TOOL
421 // The SupModuleList must be identical for all Leaf Modules!
422 // Probable Enhancement
423 // The SupModuleList should be combined to include all possible supported module types.
424 //
425 // First PASS of the TOOL
426 // Ignore the FeatureFlag - we are not using it now.
427 // Probable Enhancement
428 // FeatureFlags must be identical for each LibraryClass, otherwize fail the Merge
429 //
430 // Create the working copy if one does not exist!
431 if (libClassDefs == null)
432 libClassDefs = LibraryClassDefinitionsDocument.Factory.newInstance()
433 .addNewLibraryClassDefinitions();
434 //
435 // Get the Leaf LibraryClassDefinitions Section
436 LibraryClassDefinitions leafLibClassDef = leafMsa.getLibraryClassDefinitions();
437 //
438 // We only need to test there are entries in the Leaf LibraryClassDefinitions section!
439 if (leafLibClassDef.getLibraryClassList().size() > 0) {
440 for (int index = 0; index < leafLibClassDef.getLibraryClassList().size(); index++) {
441 //
442 // We can use the Keyword to search to see if the Leaf's Library Class was already
443 // added to the Merge Module.
444 String test = "";
445 String leafKeyword = leafLibClassDef.getLibraryClassList().get(index).getKeyword()
446 .toString().trim();
447
448 leafUsage = "";
449 if (leafLibClassDef.getLibraryClassList().get(index).getUsage() != null)
450 leafUsage = leafLibClassDef.getLibraryClassList().get(index).getUsage().toString()
451 .trim();
452
453 String leafSupArchList = "";
454 if (leafLibClassDef.getLibraryClassList().get(index).getSupArchList() != null)
455 leafSupArchList = leafLibClassDef.getLibraryClassList().get(index).getSupArchList()
456 .toString().trim();
457
458 String leafSupModuleList = "";
459 if (leafLibClassDef.getLibraryClassList().get(index).getSupModuleList() != null)
460 leafSupModuleList = leafLibClassDef.getLibraryClassList().get(index).getSupModuleList()
461 .toString().trim();
462
463 test = checkDuplicateStrings(leafKeyword, aLibClassDefs);
464 if (test.length() > 0) {
465 // The checkDuplicateStrings returns "" if a duplicate was found.
466 // Here, the Leaf LibraryClass gets entered because the Keyword was not found.
467 // No more testing is required, since this is the first instance of the LibraryClass
468 libClassDefs.addNewLibraryClass();
469 libClassDefs.setLibraryClassArray(libraryClassIndex++,
470 leafLibClassDef.getLibraryClassList().get(index));
471 } else {
472 // The Merged Module has already specified the Library Class
473 // Check ATTRIBUTES, following the rules above.
474 // Since we cannot get the LibraryClass entry using the Keyword, we have to search
475 // all of the Merged Module's LibraryClass statements until we find a match.
476 // Also, we may have more than one LibraryClass with the same Keyword, but different
477 // Usage, SupArchList, FeatureFlag or SupModuleList
478 for (int nidx = 0; nidx < libraryClassIndex; nidx++) {
479 String mergeKeyword = libClassDefs.getLibraryClassList().get(nidx).getKeyword()
480 .trim();
481
482 if (leafKeyword.contentEquals(mergeKeyword)) {
483 // We have the FIRST match, let's check usage, remember, we can have more than one LibraryClass Keyword.
484 mergeUsage = libClassDefs.getLibraryClassList().get(nidx).getUsage().toString()
485 .trim();
486 // If the usage is identical, check the SupArchList next
487 if (!leafUsage.contentEquals(mergeUsage)) {
488 if (checkUsage().trim().contains("DIFFERENT")) {
489 // See if there is another entry for PRODUCED or CONSUME
490 int anotherLC = NOTFOUND;
491 for (int iidx = nidx + 1; iidx < libraryClassIndex; iidx++) {
492 String innerTestKeyword = libClassDefs.getLibraryClassList()
493 .get(iidx).getKeyword()
494 .toString().trim();
495 if (leafKeyword.contentEquals(innerTestKeyword)) {
496 anotherLC = FOUND;
497 mergeUsage = libClassDefs.getLibraryClassList().get(iidx)
498 .getUsage().toString().trim();
499 if (checkProduced()) {
500 libClassDefs
501 .getLibraryClassList()
502 .get(iidx)
503 .setUsage(
504 org.tianocore.UsageTypes.ALWAYS_PRODUCED);
505 }
506 // Both Usage types are CONSUMED
507 if (checkConsumed()) {
508 libClassDefs
509 .getLibraryClassList()
510 .get(iidx)
511 .setUsage(
512 org.tianocore.UsageTypes.ALWAYS_CONSUMED);
513 }
514 if (((mergeUsage.contains("TO_START")) && (leafUsage
515 .contains("TO_START"))))
516 anotherLC = FOUND;
517 if (((mergeUsage.contains("BY_START")) && (leafUsage
518 .contains("BY_START"))))
519 anotherLC = FOUND;
520 }
521 }
522 if (anotherLC == NOTFOUND) {
523 // we need to add the leaf Library Class
524 libClassDefs.addNewLibraryClass();
525 libClassDefs
526 .setLibraryClassArray(
527 libraryClassIndex++,
528 leafLibClassDef
529 .getLibraryClassList()
530 .get(index));
531 }
532 }
533
534 // Both Usage types are PRODUCED
535 if (checkUsage().trim().contains("PRODUCED")) {
536 libClassDefs.getLibraryClassList().get(nidx)
537 .setUsage(org.tianocore.UsageTypes.ALWAYS_PRODUCED);
538 }
539 // Both Usage types are CONSUMED
540 if (checkUsage().trim().contains("CONSUMED")) {
541 libClassDefs.getLibraryClassList().get(nidx)
542 .setUsage(org.tianocore.UsageTypes.ALWAYS_CONSUMED);
543 }
544 }
545 // Usage testing completed
546 // Check SupArchList
547 String mergeSupArchList = "";
548 if (libClassDefs.getLibraryClassList().get(nidx).getSupArchList() != null)
549 mergeSupArchList = libClassDefs.getLibraryClassList().get(nidx)
550 .getSupArchList().toString().trim();
551 if (!mergeSupArchList.equalsIgnoreCase(leafSupArchList)) {
552 System.out
553 .println("ERROR: Library Class, keyword: " + leafKeyword
554 + " defines a different set of supported architectures.");
555 System.out
556 .println("Version 0.1 of the merge tool requires that they must be identical!");
557 System.out.println("First instance of the Library used: "
558 + mergeSupArchList);
559 System.out.println("While this module, " + leafFilename + " uses: "
560 + leafSupArchList);
561 System.out.println("Merge ABORTED!");
562 System.exit(FAIL);
563 }
564 // Architecture Testing completed
565 // Check SupModuleType
566 String mergeSupModuleList = "";
567 if (libClassDefs.getLibraryClassList().get(nidx).getSupModuleList() != null)
568 mergeSupModuleList = libClassDefs.getLibraryClassList().get(nidx)
569 .getSupModuleList().toString().trim();
570 if (!mergeSupModuleList.equalsIgnoreCase(leafSupModuleList)) {
571 System.out.println("ERROR: Library Class, keyword: " + leafKeyword
572 + " defines a different set of supported modules.");
573 System.out
574 .println("Version 0.1 of the merge tool requires that they must be identical!");
575 System.out.println("First instance of the Library used: "
576 + mergeSupModuleList);
577 System.out.println("While this module, " + leafFilename + " uses: "
578 + leafSupModuleList);
579 System.out.println("Merge ABORTED!");
580 System.exit(FAIL);
581 }
582 // Supported Module Testing completed
583 // Check FeatureFlage
584 // Next version, not this one.
585 }
586 } // end of processing of duplicate Library Class entries
587 } // end duplicate entry
588 } // end of test loop for duplicates
589 } // endif Merge Module LibraryModuleDefinitions existed
590 } // endif of LibraryModuleDefinition Tests
591
592 if (leafMsa.isSetSourceFiles()) {
593 // TODO: test for NULL settings
594 // Add Sourcefiles to the Merge Module. NOTE: ONLY MODIFY THE Filename, prepending the path to the MSA file.
595 // First get the path portion of the leafMSA file, which will be prepended to the filename
596 // everything else stays intact.
597 if (mergeSourceFiles == null)
598 mergeSourceFiles = SourceFilesDocument.Factory.newInstance().addNewSourceFiles();
599
600 String pathToMsa = getPathPartOfLeafMsa(leafFilename);
601 if (DEBUG > 10)
602 System.out.println("PATH TO SOURCE FILES: " + pathToMsa);
603 if (leafMsa.getSourceFiles().getFilenameList() != null) {
604 List<FilenameDocument.Filename> leafSourceFiles = leafMsa.getSourceFiles().getFilenameList();
605 for (int index = 0; index < leafSourceFiles.size(); index++) {
606 String leafFile = leafSourceFiles.get(index).getStringValue().toString();
607 leafFile = pathToMsa + leafFile;
608 leafSourceFiles.get(index).setStringValue(leafFile);
609 mergeSourceFiles.addNewFilename();
610 mergeSourceFiles.setFilenameArray(sourceFileIndex++, leafSourceFiles.get(index));
611 }
612 }
613 }
614
615 if (leafMsa.isSetPackageDependencies()) {
616 //
617 // If mergePackageDependencies == null, create a new mergePackageDependencies and
618 // add the leaf module's Package Dependencies section to the merge Module's
619 // If mergePackageDependencies != null, test the leaf Package entries against
620 // what has already been added to the mergePackageDependencies data structure.
621 //
622 // Add Unique Package entries.
623 // For this Merge Tool a Package is defined as PackageGuid
624 //
625 // ABORT THE MERGE WITH FAIL if the PACKAGE VERSION NUMBERS ARE DIFFERENT
626 // between Leaf modules
627 //
628 // Version 0.1 of the tool
629 // SupArchList, if it exists, must be identical for all Leaf Modules
630 // Probable Enhancement
631 // Just specify the lowest common denominator
632 //
633 // Create the working copy if one does not exist!
634 // TODO: CODE GOES HERE
635 if (mergePackageDependencies == null)
636 mergePackageDependencies = PackageDependenciesDocument.Factory.newInstance()
637 .addNewPackageDependencies();
638
639 PackageDependencies leafPackageDependencies = leafMsa.getPackageDependencies();
640 if (leafPackageDependencies.sizeOfPackageArray() > 0) {
641 for (int index = 0; index < leafPackageDependencies.sizeOfPackageArray(); index++) {
642 String packageGuid = leafPackageDependencies.getPackageArray(index).getPackageGuid();
643 String test = checkDuplicateStrings(packageGuid, aPackageList);
644 if (test.length() > 0) {
645 mergePackageDependencies.addNewPackage();
646 mergePackageDependencies
647 .setPackageArray(packageDependenciesIndex++,
648 leafPackageDependencies.getPackageArray(index));
649 }
650 }
651 }
652 } // endif PackageDependencies
653
654 if (leafMsa.isSetProtocols()) {
655 // TODO:
656 // TEST FOR NULL SETTINGS so we don't get an error!
657 // Add Usage Merging routines
658 //
659 // If mergeProtocols == null, create a new mergeProtocols and add
660 // leaf module's Protocols section to the merge Module's
661 //
662 // Keep ALL Protocol entries before ProtocolNotify entries!
663 //
664 // If mergeProtocols != null, check that we have only unique Protocol and ProtocolNotify entries
665 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
666 // Mark the Protocol or ProtocolNotify as ALWAYS_PRODUCED
667 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
668 // Mark the Protocol or ProtocolNotify as ALWAYS_CONSUMED
669 // It is permissable to have one PRODUCED and one CONSUMED entry
670 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
671 // and another Leaf uses BY_START, create two entries, one for each.
672 //
673 // First PASS of the TOOL
674 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
675 // this as an error!
676 // Probable Enhancement
677 // The SupArchList, if set, must be for the "Lowest Common Denominator"
678 //
679 // First PASS of the TOOL
680 // Ignore the FeatureFlag - we are not using it now.
681 // Probable Enhancement
682 // FeatureFlags must be identical for each unique Protocol or ProtocolNotify Entry, otherwise fail the Merge
683 //
684 // HelpText RULE:
685 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
686 // is the leaf Module's path and filename to the MSA file!
687 //
688 // Create the working copy if one does not exist!
689
690 if (mergeProtocols == null)
691 mergeProtocols = ProtocolsDocument.Factory.newInstance().addNewProtocols();
692
693 Protocols leafProtocols = leafMsa.getProtocols();
694 // Handle Protocol Entries First
695 if (leafProtocols.sizeOfProtocolArray() > 0) {
696 for (int index = 0; index < leafProtocols.sizeOfProtocolArray(); index++) {
697 String protocolCName = leafProtocols.getProtocolArray(index).getProtocolCName();
698 String test = checkDuplicateStrings(protocolCName, aProtocolList);
699 if (test.length() > 0) {
700 // new Protocol
701 mergeProtocols.addNewProtocol();
702 mergeProtocols.setProtocolArray(protocolIndex++, leafProtocols.getProtocolArray(index));
703 } else {
704 // Found an existing protocol
705 leafUsage = leafProtocols.getProtocolArray(index).getUsage().toString().trim();
706 for (int nidx = 0; nidx < protocolIndex; nidx++) {
707 if (mergeProtocols.getProtocolArray(nidx).getProtocolCName()
708 .contains(protocolCName)) {
709 // Found one entry that matches.
710 mergeUsage = mergeProtocols.getProtocolArray(nidx).getUsage().toString().trim();
711 if (!mergeUsage.contentEquals(leafUsage)) {
712 // Usages are different
713 if (checkUsage().trim().contains("DIFFERENT")) {
714 // We need to check to see if there's another entry
715 int anotherProtocol = NOTFOUND;
716 for (int iidx = nidx + 1; iidx < protocolIndex; iidx++) {
717
718 if (mergeProtocols.getProtocolArray(iidx).getUsage().toString()
719 .trim().contains(protocolCName)) {
720 anotherProtocol = FOUND;
721 mergeUsage = libClassDefs.getLibraryClassList().get(iidx)
722 .getUsage().toString().trim();
723 if (checkProduced()) {
724 mergeProtocols
725 .getProtocolArray(nidx)
726 .setUsage(
727 org.tianocore.UsageTypes.ALWAYS_PRODUCED);
728 anotherProtocol = FOUND;
729 }
730 // Both Usage types are CONSUMED
731 if (checkConsumed()) {
732 mergeProtocols
733 .getProtocolArray(nidx)
734 .setUsage(
735 org.tianocore.UsageTypes.ALWAYS_CONSUMED);
736 anotherProtocol = FOUND;
737 }
738 if (((mergeUsage.contains("TO_START")) && (leafUsage
739 .contains("TO_START"))))
740 anotherProtocol = FOUND;
741 if (((mergeUsage.contains("BY_START")) && (leafUsage
742 .contains("BY_START"))))
743 anotherProtocol = FOUND;
744 }
745 }
746 if (anotherProtocol == NOTFOUND) {
747 mergeProtocols.addNewProtocol();
748 mergeProtocols
749 .setProtocolArray(
750 protocolIndex++,
751 leafProtocols
752 .getProtocolArray(index));
753 }
754 } else {
755 // usage types are either both PRODUCED or CONSUMED
756 if (checkProduced())
757 mergeProtocols.getProtocolArray(nidx)
758 .setUsage(org.tianocore.UsageTypes.ALWAYS_PRODUCED);
759 if (checkConsumed())
760 mergeProtocols.getProtocolArray(nidx)
761 .setUsage(org.tianocore.UsageTypes.ALWAYS_CONSUMED);
762 }
763 }
764 }
765 } // end of Usage Test
766 }
767 }
768 }
769
770 // Handle ProtocolNotify Entries Second
771 if (leafProtocols.sizeOfProtocolNotifyArray() > 0) {
772 for (int index = 0; index < leafProtocols.sizeOfProtocolNotifyArray(); index++) {
773 String protocolNotifyCName = leafProtocols.getProtocolNotifyArray(index)
774 .getProtocolNotifyCName();
775 String test = checkDuplicateStrings(protocolNotifyCName, aProtocolNotifyList);
776 if (test.length() > 0) {
777 mergeProtocols.addNewProtocolNotify();
778 mergeProtocols.setProtocolNotifyArray(protocolNotifyIndex++,
779 leafProtocols.getProtocolNotifyArray(index));
780 } else {
781 // We have an existing ProtocolNotify Entry
782 leafUsage = leafProtocols.getProtocolNotifyArray(index).getUsage().toString().trim();
783 for (int nidx = 0; nidx < protocolIndex; nidx++) {
784 if (mergeProtocols.getProtocolNotifyArray(nidx).getProtocolNotifyCName()
785 .contains(protocolNotifyCName)) {
786 // Found one entry that matches.
787 mergeUsage = mergeProtocols.getProtocolNotifyArray(nidx).getUsage().toString().trim();
788 if (!mergeUsage.contentEquals(leafUsage)) {
789 // Usages are different
790 if (checkUsage().trim().contains("DIFFERENT")) {
791 // We need to check to see if there's another entry
792 int anotherProtocol = NOTFOUND;
793 for (int iidx = nidx + 1; iidx < protocolIndex; iidx++) {
794
795 if (mergeProtocols.getProtocolNotifyArray(iidx).getUsage().toString()
796 .trim().contains(protocolNotifyCName)) {
797 anotherProtocol = FOUND;
798 mergeUsage = libClassDefs.getLibraryClassList().get(iidx)
799 .getUsage().toString().trim();
800 if (checkProduced()) {
801 mergeProtocols
802 .getProtocolNotifyArray(nidx)
803 .setUsage(
804 org.tianocore.UsageTypes.ALWAYS_PRODUCED);
805 anotherProtocol = FOUND;
806 }
807 // Both Usage types are CONSUMED
808 if (checkConsumed()) {
809 mergeProtocols
810 .getProtocolNotifyArray(nidx)
811 .setUsage(
812 org.tianocore.UsageTypes.ALWAYS_CONSUMED);
813 anotherProtocol = FOUND;
814 }
815 if (((mergeUsage.contains("TO_START")) && (leafUsage
816 .contains("TO_START"))))
817 anotherProtocol = FOUND;
818 if (((mergeUsage.contains("BY_START")) && (leafUsage
819 .contains("BY_START"))))
820 anotherProtocol = FOUND;
821 }
822 }
823 if (anotherProtocol == NOTFOUND) {
824 mergeProtocols.addNewProtocolNotify();
825 mergeProtocols
826 .setProtocolNotifyArray(
827 protocolNotifyIndex++,
828 leafProtocols
829 .getProtocolNotifyArray(index));
830 }
831 } else {
832 // usage types are either both PRODUCED or CONSUMED
833 if (checkProduced())
834 mergeProtocols.getProtocolNotifyArray(nidx)
835 .setUsage(org.tianocore.UsageTypes.ALWAYS_PRODUCED);
836 if (checkConsumed())
837 mergeProtocols.getProtocolNotifyArray(nidx)
838 .setUsage(org.tianocore.UsageTypes.ALWAYS_CONSUMED);
839 }
840 }
841 }
842 } // end of Usage Test
843 } // end of Usage test
844 }
845 }
846
847 } // endif Protocols
848
849 if (leafMsa.isSetEvents()) {
850 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
851 //
852 // "Unique" Entries are based on EventsTypes:EventGuidCName attributes
853 // NOTE: The EventGuidCName can appear once and only once in a CreateEvents Section
854 // The SAME EventGuidCName can appear once and only once in the SignalEvents Section
855 // Two EventGuidCName entries, one in CreateEvents the other in SignalEvents IS PERMITTED!
856 //
857 // If mergeEvents == null, create a new mergeEvents and add
858 // leaf module's Events section to the merge Module's
859 //
860 // Keep ALL CreateEvents entries before SignalEvents entries!
861 //
862 // If mergeEvents != null, check that we have only unique CreateEvents and SignalEvents entries
863 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
864 // Mark the CreateEvents.EventTypes or SignalEvents.EventTypes as ALWAYS_PRODUCED
865 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
866 // Mark the CreateEvents.EventTypes or SignalEvents.EventTypes as ALWAYS_CONSUMED
867 // It is permissable to have one PRODUCED and one CONSUMED entry
868 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
869 // and another Leaf uses BY_START, create two entries, one for each.
870 //
871 // First PASS of the TOOL
872 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
873 // this as an error!
874 // Probable Enhancement
875 // The SupArchList, if set, must be for the "Lowest Common Denominator"
876 //
877 // First PASS of the TOOL
878 // Ignore the FeatureFlag - we are not using it now.
879 // Probable Enhancement
880 // FeatureFlags must be identical for each unique EventTypes, otherwise fail the Merge
881 //
882 // The EventTypes.EventType elements must be identical for all instances of
883 // the EventGuidCName FAIL THE MERGE WITH ERROR indicating the Leaf file name that
884 // was different.
885 //
886 //
887 // HelpText RULE:
888 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
889 // is the leaf Module's path and filename to the MSA file!
890 //
891 // Create the working copy if one does not exist!
892 // TODO: Code goes here
893
894 if (mergeCreateEvents == null)
895 mergeCreateEvents = EventsDocument.Events.CreateEvents.Factory.newInstance();
896
897 Events leafEvents = leafMsa.getEvents();
898 if (leafEvents.getCreateEvents() != null) {
899 Events.CreateEvents leafCreateEvents = leafEvents.getCreateEvents();
900 if (leafCreateEvents.sizeOfEventTypesArray() > 0) {
901 for (int index = 0; index < leafCreateEvents.sizeOfEventTypesArray(); index++) {
902 String EventGuidCName = leafCreateEvents.getEventTypesArray(index).getEventGuidCName();
903 String test = checkDuplicateStrings(EventGuidCName, aCreateEventsList);
904 if (test.length() > 0) {
905 mergeCreateEvents.addNewEventTypes();
906 mergeCreateEvents.setEventTypesArray(createEventIndex++,
907 leafEvents.getCreateEvents()
908 .getEventTypesArray(index));
909
910 }
911 }
912 }
913 }
914
915 if (mergeSignalEvents == null)
916 mergeSignalEvents = EventsDocument.Events.SignalEvents.Factory.newInstance();
917
918 if (leafEvents.getSignalEvents() != null) {
919 Events.SignalEvents leafSignalEvents = leafEvents.getSignalEvents();
920 if (leafSignalEvents.sizeOfEventTypesArray() > 0) {
921 for (int index = 0; index < leafSignalEvents.sizeOfEventTypesArray(); index++) {
922 String EventGuidCName = leafSignalEvents.getEventTypesArray(index).getEventGuidCName();
923 String test = checkDuplicateStrings(EventGuidCName, aSignalEventsList);
924 if (test.length() > 0) {
925 mergeSignalEvents.addNewEventTypes();
926 mergeSignalEvents.setEventTypesArray(signalEventIndex++,
927 leafEvents.getSignalEvents()
928 .getEventTypesArray(index));
929 }
930 }
931 }
932 }
933 } // endif Events
934
935 if (leafMsa.isSetHobs()) {
936 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
937 //
938 // "Unique" Entries are based on Hobs.HobTypes:HobGuidCName attribute
939 //
940 // If mergeHobs == null, create a new mergeHobs and add
941 // leaf module's Hobs section to the merge Module's
942 //
943 //
944 // If mergeHobs != null, check that we have only unique Hobs.HobTypes entries
945 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
946 // Mark the Hobs.HobTypes as ALWAYS_PRODUCED
947 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
948 // Mark the Hobs.HobTypes as ALWAYS_CONSUMED
949 // It is permissable to have one PRODUCED and one CONSUMED entry
950 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
951 // and another Leaf uses BY_START, create two entries, one for each.
952 //
953 // First PASS of the TOOL
954 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
955 // this as an error!
956 // Probable Enhancement
957 // The SupArchList, if set, must be for the "Lowest Common Denominator"
958 //
959 // First PASS of the TOOL
960 // Ignore the FeatureFlag - we are not using it now.
961 // Probable Enhancement
962 // FeatureFlags must be identical for each unique HobTypes element, otherwise fail the Merge
963 //
964 // The HobTypes.HobType elements must be identical for all instances of
965 // the HobGuidCName FAIL THE MERGE WITH ERROR indicating the Leaf file name that
966 // was different.
967 //
968 //
969 // HelpText RULE:
970 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
971 // is the leaf Module's path and filename to the MSA file!
972 //
973 // Create the working copy if one does not exist!
974 // TODO: Code goes here
975 if (mergeHobs == null)
976 mergeHobs = HobsDocument.Factory.newInstance().addNewHobs();
977
978 Hobs leafHobs = leafMsa.getHobs();
979 if (leafHobs.sizeOfHobTypesArray() > 0) {
980 for (int index = 0; index < leafHobs.sizeOfHobTypesArray(); index++) {
981 String hobGuidCName = leafHobs.getHobTypesArray(index).getHobType().toString();
982 String test = checkDuplicateStrings(hobGuidCName, aHobsList);
983 if (test.length() > 0) {
984 mergeHobs.addNewHobTypes();
985 mergeHobs.setHobTypesArray(hobsIndex++, leafHobs.getHobTypesArray(index));
986 }
987 }
988 }
989 } // endif Hobs
990
991 if (leafMsa.isSetPPIs()) {
992 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
993 //
994 // Keep only Unique Ppi or PpiNotify elements, based on the PpiCName and PpiNotifyCName respectively.
995
996 // If mergePpi == null, create a new mergePpi and add
997 // leaf module's PPIs section to the merge Module's
998 //
999 // Keep ALL Ppi entries before PpiNotify entries!
1000 //
1001 // If mergePpi != null, check that we have only unique Ppi and PpiNotify entries
1002 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
1003 // Mark the Ppi or PpiNotify as ALWAYS_PRODUCED
1004 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
1005 // Mark the Ppi or PpiNotify as ALWAYS_CONSUMED
1006 // It is permissable to have one PRODUCED and one CONSUMED entry
1007 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
1008 // and another Leaf uses BY_START, create two entries, one for each.
1009 //
1010 // First PASS of the TOOL
1011 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1012 // this as an error!
1013 // Probable Enhancement
1014 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1015 //
1016 // First PASS of the TOOL
1017 // Ignore the FeatureFlag - we are not using it now.
1018 // Probable Enhancement
1019 // FeatureFlags must be identical for each unique Ppi or PpiNotify Entry, otherwise fail the Merge
1020 //
1021 // HelpText RULE:
1022 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
1023 // is the leaf Module's path and filename to the MSA file!
1024 //
1025 // Create the working copy if one does not exist!
1026 // TODO: Code Goes Here!
1027 if (mergePpis == null)
1028 mergePpis = PPIsDocument.Factory.newInstance().addNewPPIs();
1029
1030 PPIs leafPPIs = leafMsa.getPPIs();
1031 // Handle the PPI Entries First
1032 if (leafPPIs.sizeOfPpiArray() > 0) {
1033 for (int index = 0; index < leafPPIs.sizeOfPpiArray(); index++) {
1034 String ppiCName = leafPPIs.getPpiArray(index).getPpiCName();
1035 String test = checkDuplicateStrings(ppiCName, aPpiList);
1036 if (test.length() > 0) {
1037 mergePpis.addNewPpi();
1038 mergePpis.setPpiArray(ppiIndex++, leafPPIs.getPpiArray(index));
1039 }
1040 }
1041 }
1042
1043 // Handle the PpiNotify Second
1044 if (leafPPIs.sizeOfPpiNotifyArray() > 0) {
1045 for (int index = 0; index < leafPPIs.sizeOfPpiNotifyArray(); index++) {
1046 String ppiNotifyCName = leafPPIs.getPpiNotifyArray(index).getPpiNotifyCName();
1047 String test = checkDuplicateStrings(ppiNotifyCName, aPpiNotifyList);
1048 if (test.length() > 0) {
1049 mergePpis.addNewPpiNotify();
1050 mergePpis.setPpiNotifyArray(ppiNotifyIndex++, leafPPIs.getPpiNotifyArray(index));
1051 }
1052 }
1053 }
1054
1055 } // endif Ppis
1056
1057 if (leafMsa.isSetVariables()) {
1058 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1059 //
1060 // Keep only Unique Variable elements, based on the VariableName element.
1061 //
1062 // If mergeVariables == null, create a new mergeVariables and add
1063 // leaf module's Variables section to the merge Module's
1064 //
1065 // If mergeVariables != null, check that we have only unique Variable entries
1066 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
1067 // Mark the Variable as ALWAYS_PRODUCED
1068 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
1069 // Mark the Variable as ALWAYS_CONSUMED
1070 // It is permissable to have one PRODUCED and one CONSUMED entry
1071 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
1072 // and another Leaf uses BY_START, create two entries, one for each.
1073 //
1074 // First PASS of the TOOL
1075 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1076 // this as an error!
1077 // Probable Enhancement
1078 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1079 //
1080 // First PASS of the TOOL
1081 // Ignore the FeatureFlag - we are not using it now.
1082 // Probable Enhancement
1083 // FeatureFlags must be identical for each unique Variable entry, otherwise fail the Merge
1084 //
1085 // HelpText RULE:
1086 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
1087 // is the leaf Module's path and filename to the MSA file!
1088 //
1089 // Create the working copy if one does not exist!
1090 // TODO: Code Goes Here!
1091 if (mergeVariables == null)
1092 mergeVariables = VariablesDocument.Factory.newInstance().addNewVariables();
1093
1094 Variables leafVariables = leafMsa.getVariables();
1095 if (leafVariables.sizeOfVariableArray() > 0) {
1096 for (int index = 0; index < leafVariables.sizeOfVariableArray(); index++) {
1097 String variableGuidCName = leafVariables.getVariableArray(index).getGuidCName();
1098 String test = checkDuplicateStrings(variableGuidCName, aVariablesList);
1099 if (test.length() > 0) {
1100 mergeVariables.addNewVariable();
1101 mergeVariables
1102 .setVariableArray(variablesIndex++, leafVariables.getVariableArray(index));
1103 }
1104 }
1105 }
1106
1107 }// endif Variables
1108
1109 if (leafMsa.isSetBootModes()) {
1110 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1111 //
1112 // Keep only Unique BootMode elements, based on the BootModeName Attribute.
1113 //
1114 // If mergeBootModes == null, create a new mergeBootModes and add
1115 // leaf module's BootModes section to the merge Module's
1116 //
1117 // If mergeBootModes != null, check that we have only unique BootMode entries
1118 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
1119 // Mark the BootMode as ALWAYS_PRODUCED
1120 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
1121 // Mark the BootMode as ALWAYS_CONSUMED
1122 // It is permissable to have one PRODUCED and one CONSUMED entry
1123 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
1124 // and another Leaf uses BY_START, create two entries, one for each.
1125 //
1126 // First PASS of the TOOL
1127 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1128 // this as an error!
1129 // Probable Enhancement
1130 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1131 //
1132 // First PASS of the TOOL
1133 // Ignore the FeatureFlag - we are not using it now.
1134 // Probable Enhancement
1135 // FeatureFlags must be identical for each unique BootMode entry, otherwise fail the Merge
1136 //
1137 // HelpText RULE:
1138 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
1139 // is the leaf Module's path and filename to the MSA file!
1140 //
1141 // Create the working copy if one does not exist!
1142 // TODO: Code Goes Here!
1143 if (mergeBootModes == null)
1144 mergeBootModes = BootModesDocument.Factory.newInstance().addNewBootModes();
1145
1146 BootModes leafBootModes = leafMsa.getBootModes();
1147 if (leafBootModes.sizeOfBootModeArray() > 0) {
1148 for (int index = 0; index < leafBootModes.sizeOfBootModeArray(); index++) {
1149 String bootModeName = leafBootModes.getBootModeArray(index).getBootModeName().toString();
1150 String test = checkDuplicateStrings(bootModeName, aBootModesList);
1151 if (test.length() > 0) {
1152 mergeBootModes.addNewBootMode();
1153 mergeBootModes
1154 .setBootModeArray(bootModesIndex++, leafBootModes.getBootModeArray(index));
1155 }
1156 }
1157 }
1158
1159 }// endif BootMode
1160
1161 if (leafMsa.isSetSystemTables()) {
1162 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1163 //
1164 // Keep only Unique SystemTableCNames elements, based on the SystemTableCName element.
1165 //
1166 // If mergeSystemTables == null, create a new mergeSystemTables and add
1167 // leaf module's Variables section to the merge Module's
1168 //
1169 // If mergeSystemTables != null, check that we have only unique SystemTableCNames entries
1170 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
1171 // Mark the SystemTableCName as ALWAYS_PRODUCED
1172 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
1173 // Mark the SystemTableCName as ALWAYS_CONSUMED
1174 // It is permissable to have one PRODUCED and one CONSUMED entry
1175 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
1176 // and another Leaf uses BY_START, create two entries, one for each.
1177 //
1178 // First PASS of the TOOL
1179 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1180 // this as an error!
1181 // Probable Enhancement
1182 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1183 //
1184 // First PASS of the TOOL
1185 // Ignore the FeatureFlag - we are not using it now.
1186 // Probable Enhancement
1187 // FeatureFlags must be identical for each unique SystemTableCNames entry, otherwise fail the Merge
1188 //
1189 // HelpText RULE:
1190 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
1191 // is the leaf Module's path and filename to the MSA file!
1192 //
1193 // Create the working copy if one does not exist!
1194 // TODO: Code Goes Here!
1195 if (mergeSystemTables == null)
1196 mergeSystemTables = SystemTablesDocument.Factory.newInstance().addNewSystemTables();
1197
1198 SystemTables leafSystemTables = leafMsa.getSystemTables();
1199 if (leafSystemTables.sizeOfSystemTableCNamesArray() > 0) {
1200 for (int index = 0; index < leafSystemTables.sizeOfSystemTableCNamesArray(); index++) {
1201 String systemTableCName = leafSystemTables.getSystemTableCNamesArray(index)
1202 .getSystemTableCName();
1203 String test = checkDuplicateStrings(systemTableCName, aSystemTablesList);
1204 if (test.length() > 0) {
1205 mergeSystemTables.addNewSystemTableCNames();
1206 mergeSystemTables
1207 .setSystemTableCNamesArray(
1208 systemTableIndex++,
1209 leafSystemTables
1210 .getSystemTableCNamesArray(index));
1211 }
1212 }
1213 }
1214
1215 }// endif SystemTables
1216
1217 if (leafMsa.isSetDataHubs()) {
1218 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1219 //
1220 // Keep only Unique DataHubs elements, based on the DataHubRecord.DataHubCName element.
1221 //
1222 // If mergeDataHubs == null, create a new mergeDataHubs and add
1223 // leaf module's DataHubs section to the merge Module's
1224 //
1225 // If mergeDataHubs != null, check that we have only unique DataHubRecord entries
1226 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
1227 // Mark the DataHubCName as ALWAYS_PRODUCED
1228 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
1229 // Mark the DataHubCName as ALWAYS_CONSUMED
1230 // It is permissable to have one PRODUCED and one CONSUMED entry
1231 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
1232 // and another Leaf uses BY_START, create two entries, one for each.
1233 //
1234 // First PASS of the TOOL
1235 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1236 // this as an error!
1237 // Probable Enhancement
1238 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1239 //
1240 // First PASS of the TOOL
1241 // Ignore the FeatureFlag - we are not using it now.
1242 // Probable Enhancement
1243 // FeatureFlags must be identical for each unique DataHubRecord entry, otherwise fail the Merge
1244 //
1245 // HelpText RULE:
1246 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
1247 // is the leaf Module's path and filename to the MSA file!
1248 //
1249 // Create the working copy if one does not exist!
1250 // TODO: Code Goes Here!
1251 if (mergeDataHubs == null)
1252 mergeDataHubs = DataHubsDocument.Factory.newInstance().addNewDataHubs();
1253
1254 DataHubs leafDataHubs = leafMsa.getDataHubs();
1255 if (leafDataHubs.sizeOfDataHubRecordArray() > 0) {
1256 for (int index = 0; index < leafDataHubs.sizeOfDataHubRecordArray(); index++) {
1257 String dataHubCName = leafDataHubs.getDataHubRecordArray(index).getDataHubCName();
1258 String test = checkDuplicateStrings(dataHubCName, aDataHubsList);
1259 if (test.length() > 0) {
1260 mergeDataHubs.addNewDataHubRecord();
1261 mergeDataHubs.setDataHubRecordArray(dataHubsIndex++,
1262 leafDataHubs.getDataHubRecordArray(index));
1263 }
1264 }
1265 }
1266
1267 }// endif DataHubs
1268
1269 if (leafMsa.isSetHiiPackages()) {
1270 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1271 //
1272 // Keep only Unique HiiPackage elements, based on the HiiPackage.HiiCName element.
1273 //
1274 // If mergeHiiPackages == null, create a new mergeHiiPackages and add
1275 // leaf module's DataHubs section to the merge Module's
1276 //
1277 // If mergeHiiPackages != null, check that we have only unique HiiPackage entries
1278 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
1279 // Mark the HiiPackage as ALWAYS_PRODUCED
1280 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
1281 // Mark the HiiPackage as ALWAYS_CONSUMED
1282 // It is permissable to have one PRODUCED and one CONSUMED entry
1283 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
1284 // and another Leaf uses BY_START, create two entries, one for each.
1285 //
1286 // First PASS of the TOOL
1287 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1288 // this as an error!
1289 // Probable Enhancement
1290 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1291 //
1292 // First PASS of the TOOL
1293 // Ignore the FeatureFlag - we are not using it now.
1294 // Probable Enhancement
1295 // FeatureFlags must be identical for each unique HiiPackage entry, otherwise fail the Merge
1296 //
1297 // HelpText RULE:
1298 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
1299 // is the leaf Module's path and filename to the MSA file!
1300 //
1301 // Create the working copy if one does not exist!
1302 // TODO: Code Goes Here!
1303 if (mergeHiiPackages == null)
1304 mergeHiiPackages = HiiPackagesDocument.Factory.newInstance().addNewHiiPackages();
1305
1306 HiiPackages leafHiiPackages = leafMsa.getHiiPackages();
1307 if (leafHiiPackages.sizeOfHiiPackageArray() > 0) {
1308 for (int index = 0; index < leafHiiPackages.sizeOfHiiPackageArray(); index++) {
1309 String hiiCName = leafHiiPackages.getHiiPackageArray(index).getHiiCName();
1310 String test = checkDuplicateStrings(hiiCName, aHiiPackagesList);
1311 if (test.length() > 0) {
1312 mergeHiiPackages.addNewHiiPackage();
1313 mergeHiiPackages.setHiiPackageArray(hiiPackageIndex++,
1314 leafHiiPackages.getHiiPackageArray(index));
1315 }
1316 }
1317 }
1318
1319 }// endif HiiPackage
1320
1321 if (leafMsa.isSetGuids()) {
1322 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1323 //
1324 // Keep only Unique Guids elements, based on the GuidCNames.GuidCName element.
1325 //
1326 // If mergeGuids == null, create a new mergeGuids and add
1327 // leaf module's Guids section to the merge Module's
1328 //
1329 // If mergeGuids != null, check that we have only unique GuidCNames entries
1330 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
1331 // Mark the GuidCNames as ALWAYS_PRODUCED
1332 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
1333 // Mark the GuidCNames as ALWAYS_CONSUMED
1334 // It is permissable to have one PRODUCED and one CONSUMED entry
1335 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
1336 // and another Leaf uses BY_START, create two entries, one for each.
1337 //
1338 // First PASS of the TOOL
1339 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1340 // this as an error!
1341 // Probable Enhancement
1342 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1343 //
1344 // First PASS of the TOOL
1345 // Ignore the FeatureFlag - we are not using it now.
1346 // Probable Enhancement
1347 // FeatureFlags must be identical for each unique GuidCNames entry, otherwise fail the Merge
1348 //
1349 // HelpText RULE:
1350 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
1351 // is the leaf Module's path and filename to the MSA file!
1352 //
1353 // Create the working copy if one does not exist!
1354 // TODO: Code Goes Here!
1355 if (mergeGuids == null)
1356 mergeGuids = GuidsDocument.Factory.newInstance().addNewGuids();
1357
1358 Guids leafGuids = leafMsa.getGuids();
1359 if (leafGuids.sizeOfGuidCNamesArray() > 0) {
1360 for (int index = 0; index < leafGuids.sizeOfGuidCNamesArray(); index++) {
1361 String hiiCName = leafGuids.getGuidCNamesArray(index).getGuidCName();
1362 String test = checkDuplicateStrings(hiiCName, aGuidsList);
1363 if (test.length() > 0) {
1364 mergeGuids.addNewGuidCNames();
1365 mergeGuids.setGuidCNamesArray(guidsIndex++, leafGuids.getGuidCNamesArray(index));
1366 }
1367 }
1368 }
1369
1370 }// endif GuidCNames
1371
1372 if (leafMsa.isSetExterns()) {
1373 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1374 //
1375 // FAIL THE MERGE if Externs.PcdIsDriver is present
1376 // FAIL THE MERGE if Externs.TianoR8FlashMap_h is TRUE
1377 //
1378 // Keep only Unique Extern elements, based on the Extern.* elements.
1379 //
1380 // If mergeExterns == null, create a new mergeExterns and add
1381 // leaf module's Extern section to the merge Module's
1382 //
1383 // If mergeExterns != null, check that we have only unique Extern.* entries
1384 //
1385 // After storing the initial LEAF MODULE'S SPECIFICATION SECTION
1386 // ALL other Leaf Modules must declare the exact same specifications
1387 // If they do not, FAIL the MERGE with an error message, printing the
1388 // name of the leaf MSA that did not match, along with
1389 // Expected: from the merge module's specification list
1390 // Got: from the leaf file that fails!
1391 //
1392 // For Each <Extern>
1393 // For each pair of <ModuleEntryPoint> and/or <ModuleUnloadImage>
1394 // The ModuleUnloadImage value must be identical for an identical pair of ModuleEntryPoint values
1395 // If not, FAIL THE MERGE, giving the current leaf MSA filename as the failure, along with the
1396 // additional error information as follows:
1397 // -- leafFilename --
1398 // ModuleEntryPoint:
1399 // Expected ModuleUnloadImage: fromMergeModule
1400 // Got ModuleUnloadImage: fromLeaf
1401 // Merge Aborted!
1402 // More than one <Extern> Section with a pair of <ModuleEntryPoint><ModuleUnloadImage> is allowed
1403 //
1404 // For each pair of one <Constructor> and/or one <Destructor> elements
1405 // The <Extern> section containing the <Constructor> <Destructor> pairs
1406 // The Destructor value in all leaf modules must be identical for all Constructor elements that are identical.
1407 // More than one <Extern> Section with Constructor/Destructor pair is permitted.
1408 //
1409 // For each Set four elements, DriverBinding, ComponentName, DriverConfig and DriverDiag,
1410 // 1 DriverBinding and
1411 // 0 or 1 ComponentName and/or
1412 // 0 or 1 DriverConfig and/or
1413 // 0 or 1 DriverDiag
1414 // elements must appear in 1 <Extern> Section.
1415 //
1416 // A ComponentName cannot be used without a DriverBinding element.
1417 // A DriverConfig element cannot appear without a DriverBinding element.
1418 // A DriverDiag element cannot appear without a DriverBinding element
1419 // These elements are matched within a single <Extern> Section uniquely defined by the DriverBinding element.
1420 // Multiple <Extern> sections of this type are permitted.
1421 //
1422 // Each pair of SetVirtualAddressMapCallBack and ExitBootServiceCallBack elements MUST
1423 // BE in one Extern Section. ONE AND ONLY ONE of this section is permitted.
1424 //
1425 // First PASS of the TOOL
1426 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1427 // this as an error!
1428 // Probable Enhancement
1429 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1430 //
1431 // First PASS of the TOOL
1432 // Ignore the FeatureFlag - we are not using it now.
1433 // Probable Enhancement
1434 // FeatureFlags must be identical for each unique Extern entry, otherwise fail the Merge
1435 //
1436 // Create the working copy if one does not exist!
1437 // TODO: Code Goes Here!
1438 if (mergeExterns == null)
1439 mergeExterns = ExternsDocument.Factory.newInstance().addNewExterns();
1440
1441 Externs leafExterns = leafMsa.getExterns();
1442 // PCD IS DRIVER NOT ALLOWED IN A MERGED Module
1443 if (leafExterns.isSetPcdIsDriver()) {
1444 System.out.println("The Module: " + leafFilename + " is a PCD Driver and CANNOT BE MERGED!");
1445 System.out.println("Merge Aborted");
1446 System.err.flush();
1447 System.exit(FAIL);
1448 }
1449
1450 // TIANO R8 FLASHMAP.H NOT ALLOWED IN A MERGED Module
1451 if (leafExterns.isSetTianoR8FlashMapH()) {
1452 System.out.println("The Module: " + leafFilename
1453 + " set the Tiano R8 FlashMap.h Flag and CANNOT BE MERGED!");
1454 System.out.println("Merge Aborted");
1455 System.err.flush();
1456 System.exit(FAIL);
1457 }
1458
1459 // Add the Specification Array, one time only.
1460 if (leafExterns.sizeOfSpecificationArray() > 0) {
1461 for (int index = 0; index < leafExterns.sizeOfSpecificationArray(); index++) {
1462 String spec = leafExterns.getSpecificationArray(index);
1463 String test = checkSpecs(spec, leafFilename, aSpecArray);
1464 if (test.length() > 0) {
1465 mergeExterns.addNewSpecification();
1466 mergeExterns.setSpecificationArray(specIndex++, test);
1467 }
1468 }
1469 }
1470
1471 if (leafExterns.sizeOfExternArray() > 0) {
1472 for (int index = 0; index < leafExterns.sizeOfExternArray(); index++) {
1473 String test = "";
1474 if (leafExterns.getExternArray(index).isSetModuleEntryPoint()) {
1475 // ModuleEntryPoint, if an Unload Image is paired with
1476 // the Module Entry point, it will piggy back on the
1477 // Module Entry Point Extern
1478 String moduleEntryPoint = leafExterns.getExternArray(index).getModuleEntryPoint();
1479 test = checkDuplicateStrings(moduleEntryPoint, aEntryPointList);
1480
1481 } else if (leafExterns.getExternArray(index).isSetModuleUnloadImage()) {
1482 // Module Unload Image is here in case there is no
1483 // Entry Point - not very typical
1484 String moduleUnloadImage = leafExterns.getExternArray(index).getModuleUnloadImage();
1485 test = checkDuplicateStrings(moduleUnloadImage, aUnloadImageList);
1486
1487 } else if (leafExterns.getExternArray(index).isSetConstructor()) {
1488 // Constructors must be unique, if a Destructor is
1489 // paired with a constructor, it will pigback on
1490 // the constructor
1491 String constructor = leafExterns.getExternArray(index).getConstructor();
1492 test = checkDuplicateStrings(constructor, aConstructorList);
1493
1494 } else if (leafExterns.getExternArray(index).isSetDestructor()) {
1495 // Destructors must be unique
1496 String destructor = leafExterns.getExternArray(index).getDestructor();
1497 test = checkDuplicateStrings(destructor, aDestructorList);
1498
1499 } else if (leafExterns.getExternArray(index).isSetDriverBinding()) {
1500 // Driver Bindings must be unique
1501 // Fixed the MSA files - ComponentName, Driver Config and
1502 // Driver Diag statments must be inside of an Extern that
1503 // has a Driver Binding
1504 String driverBinding = leafExterns.getExternArray(index).getDriverBinding();
1505 test = checkDuplicateStrings(driverBinding, aDriverBindingList);
1506
1507 } else if (leafExterns.getExternArray(index).isSetSetVirtualAddressMapCallBack()) {
1508 // Handle Virtual Address Map and Exit Boot Services Call Backs
1509 // in a single Extern if they are present
1510 String virtualAddressMap = leafExterns.getExternArray(index)
1511 .getSetVirtualAddressMapCallBack();
1512 test = checkDuplicateStrings(virtualAddressMap, aVirtualAddressMapList);
1513
1514 } else if (leafExterns.getExternArray(index).isSetExitBootServicesCallBack()) {
1515 // Handle a stand alone Exit Boot Services Call Back
1516 String exitBootServices = leafExterns.getExternArray(index)
1517 .getExitBootServicesCallBack();
1518 test = checkDuplicateStrings(exitBootServices, aExitBootServicesList);
1519 } else {
1520 // Unknown Extern FAIL - May be an invalid Component Name in it's own Extern Statement
1521 System.out.println("Unknown EXTERN defined in Module: " + leafFilename);
1522 System.out.println("Value: " + leafExterns.getExternArray(index).toString());
1523 System.out.println("Merge Aborted!");
1524 System.err.flush();
1525 System.exit(FAIL);
1526 }
1527
1528 if (test.length() > 0) {
1529 mergeExterns.addNewExtern();
1530 mergeExterns.setExternArray(externsIndex++, leafExterns.getExternArray(index));
1531 }
1532 }
1533 }
1534 }// endif mergeExterns
1535
1536 if (leafMsa.isSetPcdCoded()) {
1537 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1538 //
1539 // Keep only Unique PcdCoded elements, based on the PcdCoded.PcdEntry.C_Name element.
1540 //
1541 // If mergePcdCoded == null, create a new mergePcdCoded and add
1542 // leaf module's PcdCoded section to the merge Module's
1543 //
1544 // If mergePcdCoded != null, check that we have only unique PcdEntry entries
1545 // IF one Leaf usage is SOMETIMES_PRODUCED, and another Leaf usage is ALWAYS_PRODUCED,
1546 // Mark the PcdEntry as ALWAYS_PRODUCED
1547 // IF one Leaf usage is SOMETIMES_CONSUMED, and another Leaf usage is ALWAYS_CONSUMED,
1548 // Mark the PcdEntry as ALWAYS_CONSUMED
1549 // It is permissable to have one PRODUCED and one CONSUMED entry
1550 // TO_START and BY_START cannot be combined in any fashion, if one Leaf uses TO_START
1551 // and another Leaf uses BY_START, create two entries, one for each.
1552 //
1553 // First PASS of the TOOL
1554 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
1555 // this as an error!
1556 // Probable Enhancement
1557 // The SupArchList, if set, must be for the "Lowest Common Denominator"
1558 //
1559 // First PASS of the TOOL
1560 // Ignore the FeatureFlag - we are not using it now.
1561 // Probable Enhancement
1562 // FeatureFlags must be identical for each unique HiiPackage entry, otherwise fail the Merge
1563 //
1564 // First PASS of the TOOL
1565 // Ignore the PcdEntry:Usage Attribute
1566 // Probable Enhancment
1567 // Have Usage Combined like was done for the Library Class
1568 //
1569 // First PASS of the TOOL
1570 // If Different PcdItemTypes, Abort The MERGE
1571 //
1572 // Probably Enhancement
1573 // The PcdItemType Should be checked using the following rules
1574 // Feature Flag MUST ALWAYS BE A FEATURE FLAG
1575 // If different Item Types occur, mark the PCD as DYNAMIC
1576 //
1577 // HelpText RULE:
1578 // HelpText should be concatenated with a line -- leafFilename -- separator, where leafFilename
1579 // is the leaf Module's path and filename to the MSA file!
1580 //
1581 // Create the working copy if one does not exist!
1582 // TODO: Code Goes Here!
1583 if (mergePcdCoded == null)
1584 mergePcdCoded = PcdCodedDocument.Factory.newInstance().addNewPcdCoded();
1585
1586 PcdCoded leafPcdCoded = leafMsa.getPcdCoded();
1587 if (leafPcdCoded.sizeOfPcdEntryArray() > 0) {
1588 for (int index = 0; index < leafPcdCoded.sizeOfPcdEntryArray(); index++) {
1589 String pcdCName = leafPcdCoded.getPcdEntryArray(index).getCName();
1590 String pcdItemType = leafPcdCoded.getPcdEntryArray(index).getPcdItemType().toString();
1591 String test = checkPcd(pcdCName, pcdItemType, leafFilename, aPcdCNameList);
1592 if (test.length() > 0) {
1593 mergePcdCoded.addNewPcdEntry();
1594 mergePcdCoded.setPcdEntryArray(pcdIndex++, leafPcdCoded.getPcdEntryArray(index));
1595 }
1596 }
1597 }
1598
1599 }// endif PcdCoded
1600
1601 if (leafMsa.isSetModuleBuildOptions()) {
1602 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1603 //
1604 // Any element that appear within a leaf's ModuleBuildOptions should be appended to
1605 // the Merge Module's BuildOptions section.
1606 //
1607 // NO ATTEMPT IS MADE TO VERIFY UNIQUENESS ON ANYTHING WITHIN THIS SECTION!
1608 //
1609 // Create the working copy if one does not exist!
1610 // if (mergeBuildOptions == null)
1611 // mergeBuildOptions = ModuleBuildOptionsDocument.Factory.newInstance().addNewModuleBuildOptions();
1612
1613 // ModuleBuildOptions leafModuleBuildOptions = leafMsa.getModuleBuildOptions();
1614
1615 // mergeBuildOptions.addNewModuleBuildOptions();
1616 // mergeBuildOptions.setModuleBuildOptions(leafModuleBuildOptions);
1617
1618 //
1619 // TODO: Code Goes Here!
1620 } // endif ModuleBuildOptions
1621
1622 // Need to process any UserExtensions here too.
1623 if (leafMsa.getUserExtensionsList() != null) {
1624
1625 if (mergeUserExtensions == null)
1626 mergeUserExtensions = UserExtensionsDocument.Factory.newInstance().addNewUserExtensions();
1627
1628 // for (int index = 0; index < leafMsa.getUserExtensionsList().size(); index++)
1629
1630 }
1631
1632 } // Completed parsing all leaf files.
1633
1634 header.setAbstract(Abstract);
1635 header.setCopyright(Copyright);
1636 header.setDescription(Description);
1637 License mLicense = License.Factory.newInstance();
1638 mLicense.setStringValue(licenseTxt);
1639 header.setLicense(mLicense);
1640 if ((DEBUG > 0) || (VERBOSE > 0))
1641 System.out.println("Merged Module supports: " + sArchitectures + " architectures.");
1642 List<String> lArchitectures = new ArrayList<String>();
1643 String s[] = sArchitectures.replace(" ", " ").trim().split(" ");
1644 for (int idx = 0; idx < s.length; idx++) {
1645 lArchitectures.add(s[idx]);
1646 if (DEBUG > 7)
1647 System.out.println("Adding architecture: " + s[idx]);
1648 }
1649 moduleDefs.setSupportedArchitectures(lArchitectures);
1650
1651 } // endif mergeMsaFile == null
1652
1653 if ((uiName != null) && (uiName.length() > 0) && (result == PASS)) {
1654 // TODO: Stub for replacing the msaFile UiName
1655 if ((DEBUG > 0) || (VERBOSE > 0))
1656 System.out.println("Updating the uiName: " + uiName);
1657 header.setModuleName(uiName);
1658 }
1659
1660 if ((baseName != null) && (baseName.length() > 0) && (result == PASS)) {
1661 if ((DEBUG > 0) || (VERBOSE > 0))
1662 System.out.println("Setting the Output Filename:" + baseName);
1663 moduleDefs.setOutputFileBasename(baseName);
1664 }
1665
1666 if (result == PASS) {
1667 // TODO: Stub to write out the new MSA file
1668 File outMsa = new File(msaFilename);
1669 try {
1670 if (DEBUG > 2)
1671 System.out.println("SAVING new MSA FILE: " + msaFilename);
1672
1673 mergeMsaFile.setMsaHeader(header);
1674 mergeMsaFile.setModuleDefinitions(moduleDefs);
1675 // ALL THE REST OF THE SECTIONS ARE OPTIONAL
1676 // SO check that they are not null before adding them to the merged MSA file!
1677 if (libClassDefs != null)
1678 mergeMsaFile.setLibraryClassDefinitions(libClassDefs);
1679 if (mergeSourceFiles != null)
1680 mergeMsaFile.setSourceFiles(mergeSourceFiles);
1681 if (mergePackageDependencies != null)
1682 mergeMsaFile.setPackageDependencies(mergePackageDependencies);
1683 if (mergeProtocols != null)
1684 mergeMsaFile.setProtocols(mergeProtocols);
1685
1686 if ((mergeCreateEvents != null) || (mergeSignalEvents != null)) {
1687 if (mergeEvents == null)
1688 mergeEvents = EventsDocument.Factory.newInstance().addNewEvents();
1689
1690 if (mergeCreateEvents.getEventTypesList().size() > 0) {
1691 mergeEvents.addNewCreateEvents();
1692 mergeEvents.setCreateEvents(mergeCreateEvents);
1693 }
1694 if (mergeSignalEvents.getEventTypesList().size() > 0) {
1695 mergeEvents.addNewSignalEvents();
1696 mergeEvents.setSignalEvents(mergeSignalEvents);
1697 }
1698
1699 mergeMsaFile.setEvents(mergeEvents);
1700 }
1701
1702 if (mergeHobs != null)
1703 mergeMsaFile.setHobs(mergeHobs);
1704
1705 if (mergePpis != null)
1706 mergeMsaFile.setPPIs(mergePpis);
1707
1708 if (mergeVariables != null)
1709 mergeMsaFile.setVariables(mergeVariables);
1710
1711 if (mergeBootModes != null)
1712 mergeMsaFile.setBootModes(mergeBootModes);
1713
1714 if (mergeSystemTables != null)
1715 mergeMsaFile.setSystemTables(mergeSystemTables);
1716
1717 if (mergeDataHubs != null)
1718 mergeMsaFile.setDataHubs(mergeDataHubs);
1719
1720 if (mergeHiiPackages != null)
1721 mergeMsaFile.setHiiPackages(mergeHiiPackages);
1722
1723 if (mergeGuids != null)
1724 mergeMsaFile.setGuids(mergeGuids);
1725
1726 if (mergeExterns != null)
1727 mergeMsaFile.setExterns(mergeExterns);
1728
1729 if (mergePcdCoded != null)
1730 mergeMsaFile.setPcdCoded(mergePcdCoded);
1731
1732 XmlCursor cursor = XmlConfig.setupXmlCursor(mergeMsaFile.newCursor());
1733 XmlOptions options = XmlConfig.setupXmlOptions();
1734 ModuleSurfaceAreaDocument msaDoc = ModuleSurfaceAreaDocument.Factory.newInstance();
1735 msaDoc.addNewModuleSurfaceArea();
1736 msaDoc.setModuleSurfaceArea(mergeMsaFile);
1737 msaDoc.save(outMsa, options);
1738 System.out.println("The Merged MSA file: " + msaFilename + ", has been created!");
1739 } catch (IOException e) {
1740 System.out.println("Problem writing the output file: " + msaFilename + " " + e);
1741 result = FAIL;
1742 }
1743 }
1744
1745 if ((spdFilename != null) && (result == PASS)) {
1746 // TODO: Stub for adding the msaFile to the <MsaFiles><Filename> in the spdFile
1747 String msaLine = getPathFromSpd(spdFilename, msaFilename);
1748 System.out.println("Updating the SPD file (" + spdFilename + ") with: " + msaLine);
1749 try {
1750 File spdFile = new File(spdFilename);
1751 PackageSurfaceAreaDocument spdDoc = PackageSurfaceAreaDocument.Factory.parse(spdFile);
1752 PackageSurfaceArea spd = spdDoc.getPackageSurfaceArea();
1753
1754 List<String> msaFilenames = spd.getMsaFiles().getFilenameList();
1755 msaFilenames.add(msaLine);
1756 XmlCursor cursor = XmlConfig.setupXmlCursor(spd.newCursor());
1757 XmlOptions options = XmlConfig.setupXmlOptions();
1758 spdDoc.save(spdFile, options);
1759 } catch (IOException e) {
1760 System.out.println("I/O Exception on spd file: " + spdFilename + " " + e);
1761 } catch (XmlException x) {
1762 System.out.println("XML Exception on SPD file: " + spdFilename + " " + x);
1763 }
1764 } else if ((spdFilename == null) && (result == PASS)) {
1765
1766 System.out.println("The file: " + msaFilename + ", must be added to a package file before it can be used!");
1767 }
1768 return result;
1769 }
1770
1771 public ModuleSurfaceArea getLeafFile(String filename) {
1772 File leafMsaFile = new File(filename);
1773 if ((DEBUG > 1) || (VERBOSE > 1))
1774 System.out.println("Processing MSA File: " + filename);
1775 try {
1776 leafMsa = ModuleSurfaceAreaDocument.Factory.parse(leafMsaFile).getModuleSurfaceArea();
1777 if ((DEBUG > 4) || (VERBOSE > 4))
1778 System.out.println("Binary: " + leafMsa.getModuleDefinitions().getBinaryModule());
1779 if (leafMsa.getModuleDefinitions().getBinaryModule()) {
1780 System.out.println("ERROR: Binary Module was specified in MSA: " + filename);
1781 System.out.println("Merge Aborted!");
1782 System.err.flush();
1783 return null;
1784 }
1785 } catch (IOException e) {
1786 System.out.println("I/O Exception on filename: " + filename + " " + e);
1787 System.out.println("Merge Aborted!");
1788 System.err.flush();
1789 System.exit(FAIL);
1790 } catch (XmlException x) {
1791 System.out.println("XML Exception reading file: " + filename + " " + x);
1792 System.out.println("Merge Aborted!");
1793 System.err.flush();
1794 System.exit(FAIL);
1795 }
1796 return leafMsa;
1797 }
1798
1799 private String getPathFromSpd(String spdFn, String msaFn) {
1800 String path2Msa = null;
1801
1802 spdFn = spdFn.replace("\\", "/").trim();
1803 String s[] = spdFn.split("/");
1804 String justSpdFilename = s[s.length - 1];
1805
1806 String Cwd = System.getProperty("user.dir");
1807 Cwd = Cwd.replace("\\", "/").trim();
1808 if ((DEBUG > 10) || (VERBOSE > 10)) {
1809 System.out.println("Current directory = " + Cwd);
1810 }
1811 String sp[] = Cwd.split("/");
1812 int theDirectory = sp.length - (s.length - 1);
1813 if (DEBUG > 10)
1814 System.out.println("The Directory length: " + theDirectory + " s.length: " + s.length + " sp.length: "
1815 + (sp.length - 1));
1816
1817 String path2Spd = "";
1818 for (int ictr = 0; ictr < theDirectory; ictr++) {
1819 path2Spd += sp[ictr] + "/";
1820 if (DEBUG > 10)
1821 System.out.println("Creating path to SPD file: " + path2Spd);
1822 }
1823
1824 String testPath2Spd = path2Spd + justSpdFilename;
1825
1826 File tFile = new File(testPath2Spd);
1827 if (!tFile.exists()) {
1828 System.out.println("The specified SPD file, " + spdFn + " does not exist at: " + testPath2Spd);
1829 System.out.println("Please use the FrameworkWizard to add this MSA file to the package.");
1830 System.exit(FAIL);
1831 }
1832 path2Msa = Cwd.replace(path2Spd, "");
1833 path2Msa = path2Msa + "/" + msaFn;
1834 return path2Msa;
1835 }
1836
1837 private String checkDuplicateStrings(String aString, ArrayList<String> aList) {
1838
1839 for (int lctr = 0; lctr < aList.size(); lctr++) {
1840 if (DEBUG > 8)
1841 System.out.println("Comparing: \n" + aString.replace(" ", "").replace("\n", "") + "\nTo: \n"
1842 + aList.get(lctr).replace(" ", "").replace("\n", "").toString().trim());
1843 if (aString.replace(" ", "").replace("\n", "").contains(
1844 aList.get(lctr).replace(" ", "").replace("\n", "")
1845 .toString().trim())) {
1846 if ((DEBUG > 3) || (VERBOSE > 3))
1847 System.out.println("Found a duplicate String, skipping!");
1848 return "";
1849 }
1850 }
1851 if ((DEBUG > 3) || (VERBOSE > 3))
1852 System.out.println("Returning UNIQUE String!\n " + aString);
1853 aList.add(aString);
1854 return aString;
1855 }
1856
1857 private String checkSpecs(String specName, String filename, ArrayList<String> aList) {
1858 // Check Specifications
1859 // Skip of Specs are identical
1860 String spec[] = new String[2];
1861 spec = specName.replace(" ", " ").trim().split(" ");
1862 String specInMem[] = new String[2];
1863 if ((DEBUG > 10) || (VERBOSE > 10))
1864 System.out.println("Specification: " + specName);
1865
1866 for (int lctr = 0; lctr < aList.size(); lctr++) {
1867 if (DEBUG > 8)
1868 System.out.println("Comparing: \n" + specName.replace(" ", "").replace("\n", "") + "\nTo: \n"
1869 + aList.get(lctr).replace(" ", "").replace("\n", "").toString().trim());
1870 if (specName.replace(" ", "").replace("\n", "").contains(
1871 aList.get(lctr).replace(" ", "").replace("\n", "")
1872 .toString().trim())) {
1873 if ((DEBUG > 3) || (VERBOSE > 3))
1874 System.out.println("Found a duplicate String, skipping!");
1875 return "";
1876 }
1877 specInMem = aList.get(lctr).replace(" ", " ").trim().split(" ");
1878 if (spec[0].contentEquals(specInMem[0])) {
1879 if (!spec[1].contains(specInMem[1])) {
1880 System.out.println("Module: " + filename + " is coded to " + specName);
1881 System.out.println("Merge needs to be coded to: " + aList.get(lctr));
1882 System.out.println("Merge Aborted!");
1883 System.err.flush();
1884 System.exit(FAIL);
1885 }
1886 }
1887
1888 }
1889 if ((DEBUG > 3) || (VERBOSE > 3))
1890 System.out.println("Returning Specification: " + specName);
1891 aList.add(specName);
1892 return specName;
1893 }
1894
1895 private String checkPcd(String pcdName, String itemType, String filename, ArrayList<String> aList) {
1896
1897 for (int lctr = 0; lctr < aList.size(); lctr++) {
1898 if (DEBUG > 8)
1899 System.out.println("Comparing: \n" + pcdName.replace(" ", "").replace("\n", "") + "\nTo: \n"
1900 + aList.get(lctr).replace(" ", "").replace("\n", "").toString().trim());
1901 if (pcdName.replace(" ", "").replace("\n", "").contains(
1902 aList.get(lctr).replace(" ", "").replace("\n", "")
1903 .toString().trim())) {
1904 if (!aPcdItemTypeList.get(lctr).contains(itemType)) {
1905 System.out
1906 .println("The Pcd Item Type for " + pcdName + " in file: " + filename + "does not match!");
1907 System.out.println("Expected: " + aPcdItemTypeList.get(lctr));
1908 System.out.println("Was set to: " + itemType);
1909 System.out.println("Merge Aborted!");
1910 System.err.flush();
1911 System.exit(FAIL);
1912 }
1913 if ((DEBUG > 3) || (VERBOSE > 3))
1914 System.out.println("Found a duplicate String, skipping!");
1915 return "";
1916 }
1917 }
1918 if ((DEBUG > 3) || (VERBOSE > 3))
1919 System.out.println("Returning UNIQUE String!\n " + pcdName);
1920 aPcdItemTypeList.add(itemType);
1921 aList.add(pcdName);
1922 return pcdName;
1923 }
1924
1925 private String checkUsage() {
1926 String result = "";
1927 // Usage types are different
1928 if (((mergeUsage.contains("CONSUMED")) && (leafUsage.contains("PRODUCED")))
1929 || ((mergeUsage.contains("PRODUCED")) && (leafUsage.contains("CONSUMED")))
1930 || ((mergeUsage.contains("TO_START")) && (leafUsage.contains("BY_START")))
1931 || ((mergeUsage.contains("BY_START")) && (leafUsage.contains("TO_START")))) {
1932 result = "DIFFERENT";
1933 }
1934 // Both Usage types are PRODUCED
1935 if (((mergeUsage.contains("ALWAYS_PRODUCED")) && (leafUsage.contains("SOMETIMES_PRODUCED")))
1936 || ((mergeUsage.contains("SOMETIMES_PRODUCED")) && (leafUsage.contains("ALWAYS_PRODUCED")))) {
1937 result = "PRODUCED";
1938 }
1939
1940 // Both Usage types are CONSUMED
1941 if (((mergeUsage.contains("ALWAYS_CONSUMED")) && (leafUsage.contains("SOMETIMES_CONSUMED")))
1942 || ((mergeUsage.contains("SOMETIMES_CONSUMED")) && (leafUsage.contains("ALWAYS_CONSUMED")))) {
1943 result = "CONSUMED";
1944 }
1945 return result;
1946 }
1947
1948 private boolean checkProduced() {
1949 boolean result = false;
1950
1951 if (((mergeUsage.contains("ALWAYS_PRODUCED")) && (leafUsage.contains("SOMETIMES_PRODUCED")))
1952 || ((mergeUsage.contains("SOMETIMES_PRODUCED")) && (leafUsage.contains("ALWAYS_PRODUCED")))) {
1953 result = true;
1954 }
1955 return result;
1956 }
1957
1958 private boolean checkConsumed() {
1959 boolean result = false;
1960
1961 if (((mergeUsage.contains("ALWAYS_CONSUMED")) && (leafUsage.contains("SOMETIMES_CONSUMED")))
1962 || ((mergeUsage.contains("SOMETIMES_CONSUMED")) && (leafUsage.contains("ALWAYS_CONSUMED")))) {
1963 result = true;
1964 }
1965 return result;
1966 }
1967
1968 private String getPathPartOfLeafMsa(String sFilename) {
1969 String pathName = "";
1970 String s[] = sFilename.replace("\\", "/").trim().split("/");
1971 for (int j = 0; j < (s.length - 1); j++) {
1972 pathName += s[j] + "/";
1973 }
1974 return pathName;
1975 }
1976
1977 private static class XmlConfig {
1978 public static XmlCursor setupXmlCursor(XmlCursor cursor) {
1979 String uri = "http://www.TianoCore.org/2006/Edk2.0";
1980 cursor.push();
1981 cursor.toNextToken();
1982 cursor.insertNamespace("", uri);
1983 cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
1984 cursor.pop();
1985 return cursor;
1986
1987 }
1988
1989 public static XmlOptions setupXmlOptions() {
1990 XmlOptions options = new XmlOptions();
1991 options.setCharacterEncoding("UTF-8");
1992 options.setSavePrettyPrint();
1993 options.setSavePrettyPrintIndent(2);
1994 return options;
1995 }
1996
1997 }
1998 }