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.
6 // Copyright (c) 2006, Intel Corporation All rights reserved.
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
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.
18 package org
.tianocore
.Merge
;
22 // import java.lang.*;
23 // import java.lang.ExceptionInInitializerError;
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
.*;
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
.*;
55 import org
.tianocore
.PackageSurfaceAreaDocument
.*;
57 public class CombineMsa
{
59 private final int DEBUG
= 0;
61 private final int PASS
= 0;
63 private final int FAIL
= 1;
65 private final int FOUND
= 0;
67 private final int NOTFOUND
= 1;
69 private int result
= PASS
;
71 private String licenseTxt
= "";
73 private ArrayList
<String
> aLicenses
= new ArrayList
<String
>();
75 private String Copyright
= "";
77 private ArrayList
<String
> aCopyright
= new ArrayList
<String
>();
79 private String Abstract
= "\n Merged Modules: \n";
81 private String Description
= "\n Merging Modules: \n";
83 private String sArchitectures
= "";
85 private MsaHeader header
= null;
87 private final String Specification
= "FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052";
89 private ModuleSurfaceArea mergeMsaFile
= null;
91 private ModuleSurfaceArea leafMsa
= null;
93 private ModuleDefinitions moduleDefs
= null;
95 private LibraryClassDefinitions libClassDefs
= null;
97 private ArrayList
<String
> aLibClassDefs
= new ArrayList
<String
>();
99 private int libraryClassIndex
= 0;
101 private SourceFiles mergeSourceFiles
= null;
103 private int sourceFileIndex
= 0;
105 private PackageDependencies mergePackageDependencies
= null;
107 private ArrayList
<String
> aPackageList
= new ArrayList
<String
>();
109 private int packageDependenciesIndex
= 0;
111 private Protocols mergeProtocols
= null;
113 private ArrayList
<String
> aProtocolList
= new ArrayList
<String
>();
115 private ArrayList
<String
> aProtocolNotifyList
= new ArrayList
<String
>();
117 private int protocolIndex
= 0;
119 private int protocolNotifyIndex
= 0;
121 private Events mergeEvents
= null;
123 private Events
.CreateEvents mergeCreateEvents
= null;
125 private Events
.SignalEvents mergeSignalEvents
= null;
127 private ArrayList
<String
> aCreateEventsList
= new ArrayList
<String
>();
129 private ArrayList
<String
> aSignalEventsList
= new ArrayList
<String
>();
131 private int createEventIndex
= 0;
133 private int signalEventIndex
= 0;
135 private Hobs mergeHobs
= null;
137 private ArrayList
<String
> aHobsList
= new ArrayList
<String
>();
139 private int hobsIndex
= 0;
141 private PPIs mergePpis
= null;
143 private ArrayList
<String
> aPpiList
= new ArrayList
<String
>();
145 private ArrayList
<String
> aPpiNotifyList
= new ArrayList
<String
>();
147 private int ppiIndex
= 0;
149 private int ppiNotifyIndex
= 0;
151 private Variables mergeVariables
= null;
153 private ArrayList
<String
> aVariablesList
= new ArrayList
<String
>();
155 private int variablesIndex
= 0;
157 private BootModes mergeBootModes
= null;
159 private ArrayList
<String
> aBootModesList
= new ArrayList
<String
>();
161 private int bootModesIndex
= 0;
163 private SystemTables mergeSystemTables
= null;
165 private ArrayList
<String
> aSystemTablesList
= new ArrayList
<String
>();
167 private int systemTableIndex
= 0;
169 private DataHubs mergeDataHubs
= null;
171 private ArrayList
<String
> aDataHubsList
= new ArrayList
<String
>();
173 private int dataHubsIndex
= 0;
175 private HiiPackages mergeHiiPackages
= null;
177 private ArrayList
<String
> aHiiPackagesList
= new ArrayList
<String
>();
179 private int hiiPackageIndex
= 0;
181 private Guids mergeGuids
= null;
183 private ArrayList
<String
> aGuidsList
= new ArrayList
<String
>();
185 private int guidsIndex
= 0;
187 private Externs mergeExterns
= null;
189 private ArrayList
<String
> aEntryPointList
= new ArrayList
<String
>();
191 private ArrayList
<String
> aUnloadImageList
= new ArrayList
<String
>();
193 private ArrayList
<String
> aDriverBindingList
= new ArrayList
<String
>();
195 private ArrayList
<String
> aConstructorList
= new ArrayList
<String
>();
197 private ArrayList
<String
> aDestructorList
= new ArrayList
<String
>();
199 private ArrayList
<String
> aVirtualAddressMapList
= new ArrayList
<String
>();
201 private ArrayList
<String
> aExitBootServicesList
= new ArrayList
<String
>();
203 private int externsIndex
= 0;
205 private ArrayList
<String
> aSpecArray
= new ArrayList
<String
>();
207 private int specIndex
= 0;
209 private PcdCoded mergePcdCoded
= null;
211 private ArrayList
<String
> aPcdCNameList
= new ArrayList
<String
>();
213 private ArrayList
<String
> aPcdItemTypeList
= new ArrayList
<String
>();
215 private int pcdIndex
= 0;
217 private ModuleBuildOptions mergeBuildOptions
= null;
219 private UserExtensions mergeUserExtensions
= null;
221 private String mergeUsage
= "";
223 private String leafUsage
= "";
225 private int VERBOSE
= 0;
227 // The combineMsaFiles routine is the primary routine for creating a
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
237 // If the uiName is null, we will use the module name from the first
239 // If the spdFile is not null, the Package (SPD) file has been verified
241 // If the spdFile is null, don't attempt to add the new msa file.
245 if (mergeMsaFile
== null) {
247 // create the data structure for the merged Module
249 mergeMsaFile
= ModuleSurfaceArea
.Factory
.newInstance();
251 System
.out
.println("Merging " + msaFiles
.size() + " Modules");
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.
257 header
= MsaHeaderDocument
.Factory
.newInstance().addNewMsaHeader();
258 moduleDefs
= ModuleDefinitionsDocument
.Factory
.newInstance().addNewModuleDefinitions();
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
265 moduleDefs
.setBinaryModule(false);
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
);
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
282 header
.setModuleName(leafMsa
.getMsaHeader().getModuleName().toString());
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());
288 // This is a new Module, so we need a new GUID
289 header
.setGuidValue(UUID
.randomUUID().toString());
291 // Use the version from the first Leaf module as the
292 // Merge Module version number.
293 header
.setVersion(leafMsa
.getMsaHeader().getVersion().toString());
295 // There is no special requirement for processing the
296 // following, so we just fall through on these elements
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.
303 // Force the specification to match this tool's spec version.
304 header
.setSpecification(Specification
);
306 // Set the Merged Module's Output Basename to match the first
308 String OutputFileName
= leafMsa
.getModuleDefinitions().getOutputFileBasename().toString();
310 // Just in case someone put a space character in the first
311 // leaf module's output filename, replace the spaces with
313 OutputFileName
.replace(" ", "_");
314 moduleDefs
.setOutputFileBasename(OutputFileName
);
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() + "\"");
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(),
332 if ((DEBUG
> 10) || (VERBOSE
> 10))
333 System
.out
.println("License: " + licenseTxt
);
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
339 if (leafMsa
.getMsaHeader().getCopyright() != null)
340 Copyright
+= checkDuplicateStrings(leafMsa
.getMsaHeader().getCopyright().toString().trim(),
342 if ((DEBUG
> 10) || (VERBOSE
> 10))
343 System
.out
.println("Copyright: " + Copyright
);
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!");
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";
362 // Use the Abstract of the Merged Module to list the Leaf
363 // Module's MSA files.
364 Abstract
+= " -- " + leafFilename
+ " -- \n";
366 // Ignore ClonedFrom right now
369 // Process Supported Architectures
370 // A merged module supports the lowest common set of
372 String testArch
= "";
373 if (leafMsa
.getModuleDefinitions().getSupportedArchitectures() == null) {
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!");
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
], "");
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!");
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
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()) {
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.
412 // The RecommendedInstance attributes can be ignored!
414 // First PASS of the TOOL
415 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
417 // Probable Enhancement
418 // The SupArchList, if set, must be for the "Lowest Common Denominator"
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.
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
430 // Create the working copy if one does not exist!
431 if (libClassDefs
== null)
432 libClassDefs
= LibraryClassDefinitionsDocument
.Factory
.newInstance()
433 .addNewLibraryClassDefinitions();
435 // Get the Leaf LibraryClassDefinitions Section
436 LibraryClassDefinitions leafLibClassDef
= leafMsa
.getLibraryClassDefinitions();
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
++) {
442 // We can use the Keyword to search to see if the Leaf's Library Class was already
443 // added to the Merge Module.
445 String leafKeyword
= leafLibClassDef
.getLibraryClassList().get(index
).getKeyword()
449 if (leafLibClassDef
.getLibraryClassList().get(index
).getUsage() != null)
450 leafUsage
= leafLibClassDef
.getLibraryClassList().get(index
).getUsage().toString()
453 String leafSupArchList
= "";
454 if (leafLibClassDef
.getLibraryClassList().get(index
).getSupArchList() != null)
455 leafSupArchList
= leafLibClassDef
.getLibraryClassList().get(index
).getSupArchList()
458 String leafSupModuleList
= "";
459 if (leafLibClassDef
.getLibraryClassList().get(index
).getSupModuleList() != null)
460 leafSupModuleList
= leafLibClassDef
.getLibraryClassList().get(index
).getSupModuleList()
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
));
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()
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()
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()
495 if (leafKeyword
.contentEquals(innerTestKeyword
)) {
497 mergeUsage
= libClassDefs
.getLibraryClassList().get(iidx
)
498 .getUsage().toString().trim();
499 if (checkProduced()) {
501 .getLibraryClassList()
504 org
.tianocore
.UsageTypes
.ALWAYS_PRODUCED
);
506 // Both Usage types are CONSUMED
507 if (checkConsumed()) {
509 .getLibraryClassList()
512 org
.tianocore
.UsageTypes
.ALWAYS_CONSUMED
);
514 if (((mergeUsage
.contains("TO_START")) && (leafUsage
515 .contains("TO_START"))))
517 if (((mergeUsage
.contains("BY_START")) && (leafUsage
518 .contains("BY_START"))))
522 if (anotherLC
== NOTFOUND
) {
523 // we need to add the leaf Library Class
524 libClassDefs
.addNewLibraryClass();
526 .setLibraryClassArray(
529 .getLibraryClassList()
534 // Both Usage types are PRODUCED
535 if (checkUsage().trim().contains("PRODUCED")) {
536 libClassDefs
.getLibraryClassList().get(nidx
)
537 .setUsage(org
.tianocore
.UsageTypes
.ALWAYS_PRODUCED
);
539 // Both Usage types are CONSUMED
540 if (checkUsage().trim().contains("CONSUMED")) {
541 libClassDefs
.getLibraryClassList().get(nidx
)
542 .setUsage(org
.tianocore
.UsageTypes
.ALWAYS_CONSUMED
);
545 // Usage testing completed
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
)) {
553 .println("ERROR: Library Class, keyword: " + leafKeyword
554 + " defines a different set of supported architectures.");
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: "
559 System
.out
.println("While this module, " + leafFilename
+ " uses: "
561 System
.out
.println("Merge ABORTED!");
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.");
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!");
582 // Supported Module Testing completed
583 // Check FeatureFlage
584 // Next version, not this one.
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
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();
600 String pathToMsa
= getPathPartOfLeafMsa(leafFilename
);
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
));
615 if (leafMsa
.isSetPackageDependencies()) {
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.
622 // Add Unique Package entries.
623 // For this Merge Tool a Package is defined as PackageGuid
625 // ABORT THE MERGE WITH FAIL if the PACKAGE VERSION NUMBERS ARE DIFFERENT
626 // between Leaf modules
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
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();
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
));
652 } // endif PackageDependencies
654 if (leafMsa
.isSetProtocols()) {
656 // TEST FOR NULL SETTINGS so we don't get an error!
657 // Add Usage Merging routines
659 // If mergeProtocols == null, create a new mergeProtocols and add
660 // leaf module's Protocols section to the merge Module's
662 // Keep ALL Protocol entries before ProtocolNotify entries!
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.
673 // First PASS of the TOOL
674 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
676 // Probable Enhancement
677 // The SupArchList, if set, must be for the "Lowest Common Denominator"
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
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!
688 // Create the working copy if one does not exist!
690 if (mergeProtocols
== null)
691 mergeProtocols
= ProtocolsDocument
.Factory
.newInstance().addNewProtocols();
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) {
701 mergeProtocols
.addNewProtocol();
702 mergeProtocols
.setProtocolArray(protocolIndex
++, leafProtocols
.getProtocolArray(index
));
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
++) {
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()) {
725 .getProtocolArray(nidx
)
727 org
.tianocore
.UsageTypes
.ALWAYS_PRODUCED
);
728 anotherProtocol
= FOUND
;
730 // Both Usage types are CONSUMED
731 if (checkConsumed()) {
733 .getProtocolArray(nidx
)
735 org
.tianocore
.UsageTypes
.ALWAYS_CONSUMED
);
736 anotherProtocol
= FOUND
;
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
;
746 if (anotherProtocol
== NOTFOUND
) {
747 mergeProtocols
.addNewProtocol();
752 .getProtocolArray(index
));
755 // usage types are either both PRODUCED or CONSUMED
757 mergeProtocols
.getProtocolArray(nidx
)
758 .setUsage(org
.tianocore
.UsageTypes
.ALWAYS_PRODUCED
);
760 mergeProtocols
.getProtocolArray(nidx
)
761 .setUsage(org
.tianocore
.UsageTypes
.ALWAYS_CONSUMED
);
765 } // end of Usage Test
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
));
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
++) {
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()) {
802 .getProtocolNotifyArray(nidx
)
804 org
.tianocore
.UsageTypes
.ALWAYS_PRODUCED
);
805 anotherProtocol
= FOUND
;
807 // Both Usage types are CONSUMED
808 if (checkConsumed()) {
810 .getProtocolNotifyArray(nidx
)
812 org
.tianocore
.UsageTypes
.ALWAYS_CONSUMED
);
813 anotherProtocol
= FOUND
;
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
;
823 if (anotherProtocol
== NOTFOUND
) {
824 mergeProtocols
.addNewProtocolNotify();
826 .setProtocolNotifyArray(
827 protocolNotifyIndex
++,
829 .getProtocolNotifyArray(index
));
832 // usage types are either both PRODUCED or CONSUMED
834 mergeProtocols
.getProtocolNotifyArray(nidx
)
835 .setUsage(org
.tianocore
.UsageTypes
.ALWAYS_PRODUCED
);
837 mergeProtocols
.getProtocolNotifyArray(nidx
)
838 .setUsage(org
.tianocore
.UsageTypes
.ALWAYS_CONSUMED
);
842 } // end of Usage Test
843 } // end of Usage test
849 if (leafMsa
.isSetEvents()) {
850 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
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!
857 // If mergeEvents == null, create a new mergeEvents and add
858 // leaf module's Events section to the merge Module's
860 // Keep ALL CreateEvents entries before SignalEvents entries!
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.
871 // First PASS of the TOOL
872 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
874 // Probable Enhancement
875 // The SupArchList, if set, must be for the "Lowest Common Denominator"
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
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
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!
891 // Create the working copy if one does not exist!
892 // TODO: Code goes here
894 if (mergeCreateEvents
== null)
895 mergeCreateEvents
= EventsDocument
.Events
.CreateEvents
.Factory
.newInstance();
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
));
915 if (mergeSignalEvents
== null)
916 mergeSignalEvents
= EventsDocument
.Events
.SignalEvents
.Factory
.newInstance();
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
));
935 if (leafMsa
.isSetHobs()) {
936 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
938 // "Unique" Entries are based on Hobs.HobTypes:HobGuidCName attribute
940 // If mergeHobs == null, create a new mergeHobs and add
941 // leaf module's Hobs section to the merge Module's
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.
953 // First PASS of the TOOL
954 // SupArchList must be identical for all Leaf Modules! Fail the Merge if not, reporting
956 // Probable Enhancement
957 // The SupArchList, if set, must be for the "Lowest Common Denominator"
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
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
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!
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();
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
));
991 if (leafMsa
.isSetPPIs()) {
992 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
994 // Keep only Unique Ppi or PpiNotify elements, based on the PpiCName and PpiNotifyCName respectively.
996 // If mergePpi == null, create a new mergePpi and add
997 // leaf module's PPIs section to the merge Module's
999 // Keep ALL Ppi entries before PpiNotify entries!
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.
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"
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
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!
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();
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
));
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
));
1057 if (leafMsa
.isSetVariables()) {
1058 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1060 // Keep only Unique Variable elements, based on the VariableName element.
1062 // If mergeVariables == null, create a new mergeVariables and add
1063 // leaf module's Variables section to the merge Module's
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.
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"
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
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!
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();
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();
1102 .setVariableArray(variablesIndex
++, leafVariables
.getVariableArray(index
));
1109 if (leafMsa
.isSetBootModes()) {
1110 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1112 // Keep only Unique BootMode elements, based on the BootModeName Attribute.
1114 // If mergeBootModes == null, create a new mergeBootModes and add
1115 // leaf module's BootModes section to the merge Module's
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.
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"
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
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!
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();
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();
1154 .setBootModeArray(bootModesIndex
++, leafBootModes
.getBootModeArray(index
));
1161 if (leafMsa
.isSetSystemTables()) {
1162 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1164 // Keep only Unique SystemTableCNames elements, based on the SystemTableCName element.
1166 // If mergeSystemTables == null, create a new mergeSystemTables and add
1167 // leaf module's Variables section to the merge Module's
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.
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"
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
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!
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();
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();
1207 .setSystemTableCNamesArray(
1210 .getSystemTableCNamesArray(index
));
1215 }// endif SystemTables
1217 if (leafMsa
.isSetDataHubs()) {
1218 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1220 // Keep only Unique DataHubs elements, based on the DataHubRecord.DataHubCName element.
1222 // If mergeDataHubs == null, create a new mergeDataHubs and add
1223 // leaf module's DataHubs section to the merge Module's
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.
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"
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
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!
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();
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
));
1269 if (leafMsa
.isSetHiiPackages()) {
1270 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1272 // Keep only Unique HiiPackage elements, based on the HiiPackage.HiiCName element.
1274 // If mergeHiiPackages == null, create a new mergeHiiPackages and add
1275 // leaf module's DataHubs section to the merge Module's
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.
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"
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
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!
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();
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
));
1319 }// endif HiiPackage
1321 if (leafMsa
.isSetGuids()) {
1322 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1324 // Keep only Unique Guids elements, based on the GuidCNames.GuidCName element.
1326 // If mergeGuids == null, create a new mergeGuids and add
1327 // leaf module's Guids section to the merge Module's
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.
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"
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
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!
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();
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
));
1370 }// endif GuidCNames
1372 if (leafMsa
.isSetExterns()) {
1373 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1375 // FAIL THE MERGE if Externs.PcdIsDriver is present
1376 // FAIL THE MERGE if Externs.TianoR8FlashMap_h is TRUE
1378 // Keep only Unique Extern elements, based on the Extern.* elements.
1380 // If mergeExterns == null, create a new mergeExterns and add
1381 // leaf module's Extern section to the merge Module's
1383 // If mergeExterns != null, check that we have only unique Extern.* entries
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!
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
1402 // More than one <Extern> Section with a pair of <ModuleEntryPoint><ModuleUnloadImage> is allowed
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.
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.
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.
1422 // Each pair of SetVirtualAddressMapCallBack and ExitBootServiceCallBack elements MUST
1423 // BE in one Extern Section. ONE AND ONLY ONE of this section is permitted.
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"
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
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();
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");
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");
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
);
1471 if (leafExterns
.sizeOfExternArray() > 0) {
1472 for (int index
= 0; index
< leafExterns
.sizeOfExternArray(); index
++) {
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
);
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
);
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
1491 String constructor
= leafExterns
.getExternArray(index
).getConstructor();
1492 test
= checkDuplicateStrings(constructor
, aConstructorList
);
1494 } else if (leafExterns
.getExternArray(index
).isSetDestructor()) {
1495 // Destructors must be unique
1496 String destructor
= leafExterns
.getExternArray(index
).getDestructor();
1497 test
= checkDuplicateStrings(destructor
, aDestructorList
);
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
);
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
);
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
);
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!");
1528 if (test
.length() > 0) {
1529 mergeExterns
.addNewExtern();
1530 mergeExterns
.setExternArray(externsIndex
++, leafExterns
.getExternArray(index
));
1534 }// endif mergeExterns
1536 if (leafMsa
.isSetPcdCoded()) {
1537 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1539 // Keep only Unique PcdCoded elements, based on the PcdCoded.PcdEntry.C_Name element.
1541 // If mergePcdCoded == null, create a new mergePcdCoded and add
1542 // leaf module's PcdCoded section to the merge Module's
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.
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"
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
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
1569 // First PASS of the TOOL
1570 // If Different PcdItemTypes, Abort The MERGE
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
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!
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();
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
));
1601 if (leafMsa
.isSetModuleBuildOptions()) {
1602 // TODO: TEST FOR NULL SETTINGS so we don't get an error!
1604 // Any element that appear within a leaf's ModuleBuildOptions should be appended to
1605 // the Merge Module's BuildOptions section.
1607 // NO ATTEMPT IS MADE TO VERIFY UNIQUENESS ON ANYTHING WITHIN THIS SECTION!
1609 // Create the working copy if one does not exist!
1610 // if (mergeBuildOptions == null)
1611 // mergeBuildOptions = ModuleBuildOptionsDocument.Factory.newInstance().addNewModuleBuildOptions();
1613 // ModuleBuildOptions leafModuleBuildOptions = leafMsa.getModuleBuildOptions();
1615 // mergeBuildOptions.addNewModuleBuildOptions();
1616 // mergeBuildOptions.setModuleBuildOptions(leafModuleBuildOptions);
1619 // TODO: Code Goes Here!
1620 } // endif ModuleBuildOptions
1622 // Need to process any UserExtensions here too.
1623 if (leafMsa
.getUserExtensionsList() != null) {
1625 if (mergeUserExtensions
== null)
1626 mergeUserExtensions
= UserExtensionsDocument
.Factory
.newInstance().addNewUserExtensions();
1628 // for (int index = 0; index < leafMsa.getUserExtensionsList().size(); index++)
1632 } // Completed parsing all leaf files.
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
]);
1647 System
.out
.println("Adding architecture: " + s
[idx
]);
1649 moduleDefs
.setSupportedArchitectures(lArchitectures
);
1651 } // endif mergeMsaFile == null
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
);
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
);
1666 if (result
== PASS
) {
1667 // TODO: Stub to write out the new MSA file
1668 File outMsa
= new File(msaFilename
);
1671 System
.out
.println("SAVING new MSA FILE: " + msaFilename
);
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
);
1686 if ((mergeCreateEvents
!= null) || (mergeSignalEvents
!= null)) {
1687 if (mergeEvents
== null)
1688 mergeEvents
= EventsDocument
.Factory
.newInstance().addNewEvents();
1690 if (mergeCreateEvents
.getEventTypesList().size() > 0) {
1691 mergeEvents
.addNewCreateEvents();
1692 mergeEvents
.setCreateEvents(mergeCreateEvents
);
1694 if (mergeSignalEvents
.getEventTypesList().size() > 0) {
1695 mergeEvents
.addNewSignalEvents();
1696 mergeEvents
.setSignalEvents(mergeSignalEvents
);
1699 mergeMsaFile
.setEvents(mergeEvents
);
1702 if (mergeHobs
!= null)
1703 mergeMsaFile
.setHobs(mergeHobs
);
1705 if (mergePpis
!= null)
1706 mergeMsaFile
.setPPIs(mergePpis
);
1708 if (mergeVariables
!= null)
1709 mergeMsaFile
.setVariables(mergeVariables
);
1711 if (mergeBootModes
!= null)
1712 mergeMsaFile
.setBootModes(mergeBootModes
);
1714 if (mergeSystemTables
!= null)
1715 mergeMsaFile
.setSystemTables(mergeSystemTables
);
1717 if (mergeDataHubs
!= null)
1718 mergeMsaFile
.setDataHubs(mergeDataHubs
);
1720 if (mergeHiiPackages
!= null)
1721 mergeMsaFile
.setHiiPackages(mergeHiiPackages
);
1723 if (mergeGuids
!= null)
1724 mergeMsaFile
.setGuids(mergeGuids
);
1726 if (mergeExterns
!= null)
1727 mergeMsaFile
.setExterns(mergeExterns
);
1729 if (mergePcdCoded
!= null)
1730 mergeMsaFile
.setPcdCoded(mergePcdCoded
);
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
);
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
);
1750 File spdFile
= new File(spdFilename
);
1751 PackageSurfaceAreaDocument spdDoc
= PackageSurfaceAreaDocument
.Factory
.parse(spdFile
);
1752 PackageSurfaceArea spd
= spdDoc
.getPackageSurfaceArea();
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
);
1764 } else if ((spdFilename
== null) && (result
== PASS
)) {
1766 System
.out
.println("The file: " + msaFilename
+ ", must be added to a package file before it can be used!");
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
);
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!");
1785 } catch (IOException e
) {
1786 System
.out
.println("I/O Exception on filename: " + filename
+ " " + e
);
1787 System
.out
.println("Merge Aborted!");
1790 } catch (XmlException x
) {
1791 System
.out
.println("XML Exception reading file: " + filename
+ " " + x
);
1792 System
.out
.println("Merge Aborted!");
1799 private String
getPathFromSpd(String spdFn
, String msaFn
) {
1800 String path2Msa
= null;
1802 spdFn
= spdFn
.replace("\\", "/").trim();
1803 String s
[] = spdFn
.split("/");
1804 String justSpdFilename
= s
[s
.length
- 1];
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
);
1811 String sp
[] = Cwd
.split("/");
1812 int theDirectory
= sp
.length
- (s
.length
- 1);
1814 System
.out
.println("The Directory length: " + theDirectory
+ " s.length: " + s
.length
+ " sp.length: "
1817 String path2Spd
= "";
1818 for (int ictr
= 0; ictr
< theDirectory
; ictr
++) {
1819 path2Spd
+= sp
[ictr
] + "/";
1821 System
.out
.println("Creating path to SPD file: " + path2Spd
);
1824 String testPath2Spd
= path2Spd
+ justSpdFilename
;
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.");
1832 if (path2Spd
.equals(Cwd
+ "/"))
1834 // .msa file and .spd in the same directory
1839 path2Msa
= Cwd
.replace(path2Spd
, "");
1840 path2Msa
= path2Msa
+ "/" + msaFn
;
1846 private String
checkDuplicateStrings(String aString
, ArrayList
<String
> aList
) {
1848 for (int lctr
= 0; lctr
< aList
.size(); lctr
++) {
1850 System
.out
.println("Comparing: \n" + aString
.replace(" ", "").replace("\n", "") + "\nTo: \n"
1851 + aList
.get(lctr
).replace(" ", "").replace("\n", "").toString().trim());
1852 if (aString
.replace(" ", "").replace("\n", "").contains(
1853 aList
.get(lctr
).replace(" ", "").replace("\n", "")
1854 .toString().trim())) {
1855 if ((DEBUG
> 3) || (VERBOSE
> 3))
1856 System
.out
.println("Found a duplicate String, skipping!");
1860 if ((DEBUG
> 3) || (VERBOSE
> 3))
1861 System
.out
.println("Returning UNIQUE String!\n " + aString
);
1866 private String
checkSpecs(String specName
, String filename
, ArrayList
<String
> aList
) {
1867 // Check Specifications
1868 // Skip of Specs are identical
1869 String spec
[] = new String
[2];
1870 spec
= specName
.replace(" ", " ").trim().split(" ");
1871 String specInMem
[] = new String
[2];
1872 if ((DEBUG
> 10) || (VERBOSE
> 10))
1873 System
.out
.println("Specification: " + specName
);
1875 for (int lctr
= 0; lctr
< aList
.size(); lctr
++) {
1877 System
.out
.println("Comparing: \n" + specName
.replace(" ", "").replace("\n", "") + "\nTo: \n"
1878 + aList
.get(lctr
).replace(" ", "").replace("\n", "").toString().trim());
1879 if (specName
.replace(" ", "").replace("\n", "").contains(
1880 aList
.get(lctr
).replace(" ", "").replace("\n", "")
1881 .toString().trim())) {
1882 if ((DEBUG
> 3) || (VERBOSE
> 3))
1883 System
.out
.println("Found a duplicate String, skipping!");
1886 specInMem
= aList
.get(lctr
).replace(" ", " ").trim().split(" ");
1887 if (spec
[0].contentEquals(specInMem
[0])) {
1888 if (!spec
[1].contains(specInMem
[1])) {
1889 System
.out
.println("Module: " + filename
+ " is coded to " + specName
);
1890 System
.out
.println("Merge needs to be coded to: " + aList
.get(lctr
));
1891 System
.out
.println("Merge Aborted!");
1898 if ((DEBUG
> 3) || (VERBOSE
> 3))
1899 System
.out
.println("Returning Specification: " + specName
);
1900 aList
.add(specName
);
1904 private String
checkPcd(String pcdName
, String itemType
, String filename
, ArrayList
<String
> aList
) {
1906 for (int lctr
= 0; lctr
< aList
.size(); lctr
++) {
1908 System
.out
.println("Comparing: \n" + pcdName
.replace(" ", "").replace("\n", "") + "\nTo: \n"
1909 + aList
.get(lctr
).replace(" ", "").replace("\n", "").toString().trim());
1910 if (pcdName
.replace(" ", "").replace("\n", "").contains(
1911 aList
.get(lctr
).replace(" ", "").replace("\n", "")
1912 .toString().trim())) {
1913 if (!aPcdItemTypeList
.get(lctr
).contains(itemType
)) {
1915 .println("The Pcd Item Type for " + pcdName
+ " in file: " + filename
+ "does not match!");
1916 System
.out
.println("Expected: " + aPcdItemTypeList
.get(lctr
));
1917 System
.out
.println("Was set to: " + itemType
);
1918 System
.out
.println("Merge Aborted!");
1922 if ((DEBUG
> 3) || (VERBOSE
> 3))
1923 System
.out
.println("Found a duplicate String, skipping!");
1927 if ((DEBUG
> 3) || (VERBOSE
> 3))
1928 System
.out
.println("Returning UNIQUE String!\n " + pcdName
);
1929 aPcdItemTypeList
.add(itemType
);
1934 private String
checkUsage() {
1936 // Usage types are different
1937 if (((mergeUsage
.contains("CONSUMED")) && (leafUsage
.contains("PRODUCED")))
1938 || ((mergeUsage
.contains("PRODUCED")) && (leafUsage
.contains("CONSUMED")))
1939 || ((mergeUsage
.contains("TO_START")) && (leafUsage
.contains("BY_START")))
1940 || ((mergeUsage
.contains("BY_START")) && (leafUsage
.contains("TO_START")))) {
1941 result
= "DIFFERENT";
1943 // Both Usage types are PRODUCED
1944 if (((mergeUsage
.contains("ALWAYS_PRODUCED")) && (leafUsage
.contains("SOMETIMES_PRODUCED")))
1945 || ((mergeUsage
.contains("SOMETIMES_PRODUCED")) && (leafUsage
.contains("ALWAYS_PRODUCED")))) {
1946 result
= "PRODUCED";
1949 // Both Usage types are CONSUMED
1950 if (((mergeUsage
.contains("ALWAYS_CONSUMED")) && (leafUsage
.contains("SOMETIMES_CONSUMED")))
1951 || ((mergeUsage
.contains("SOMETIMES_CONSUMED")) && (leafUsage
.contains("ALWAYS_CONSUMED")))) {
1952 result
= "CONSUMED";
1957 private boolean checkProduced() {
1958 boolean result
= false;
1960 if (((mergeUsage
.contains("ALWAYS_PRODUCED")) && (leafUsage
.contains("SOMETIMES_PRODUCED")))
1961 || ((mergeUsage
.contains("SOMETIMES_PRODUCED")) && (leafUsage
.contains("ALWAYS_PRODUCED")))) {
1967 private boolean checkConsumed() {
1968 boolean result
= false;
1970 if (((mergeUsage
.contains("ALWAYS_CONSUMED")) && (leafUsage
.contains("SOMETIMES_CONSUMED")))
1971 || ((mergeUsage
.contains("SOMETIMES_CONSUMED")) && (leafUsage
.contains("ALWAYS_CONSUMED")))) {
1977 private String
getPathPartOfLeafMsa(String sFilename
) {
1978 String pathName
= "";
1979 String s
[] = sFilename
.replace("\\", "/").trim().split("/");
1980 for (int j
= 0; j
< (s
.length
- 1); j
++) {
1981 pathName
+= s
[j
] + "/";
1986 private static class XmlConfig
{
1987 public static XmlCursor
setupXmlCursor(XmlCursor cursor
) {
1988 String uri
= "http://www.TianoCore.org/2006/Edk2.0";
1990 cursor
.toNextToken();
1991 cursor
.insertNamespace("", uri
);
1992 cursor
.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
1998 public static XmlOptions
setupXmlOptions() {
1999 XmlOptions options
= new XmlOptions();
2000 options
.setCharacterEncoding("UTF-8");
2001 options
.setSavePrettyPrint();
2002 options
.setSavePrettyPrintIndent(2);