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