2 PlatformPcdPreprocessActionForBuilding class.
4 This action class is to collect PCD information from MSA, SPD, FPD xml file.
5 This class will be used for wizard and build tools, So it can *not* inherit
6 from buildAction or wizardAction.
8 Copyright (c) 2006, Intel Corporation
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 package org
.tianocore
.build
.pcd
.action
;
21 import java
.io
.IOException
;
22 import java
.math
.BigInteger
;
23 import java
.util
.ArrayList
;
24 import java
.util
.Iterator
;
25 import java
.util
.List
;
28 import org
.apache
.xmlbeans
.XmlException
;
29 import org
.apache
.xmlbeans
.XmlObject
;
30 import org
.tianocore
.DynamicPcdBuildDefinitionsDocument
.DynamicPcdBuildDefinitions
;
31 import org
.tianocore
.PlatformSurfaceAreaDocument
;
32 import org
.tianocore
.build
.fpd
.FpdParserTask
;
33 import org
.tianocore
.build
.global
.GlobalData
;
34 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
35 import org
.tianocore
.pcd
.action
.ActionMessage
;
36 import org
.tianocore
.pcd
.entity
.ModulePcdInfoFromFpd
;
37 import org
.tianocore
.pcd
.entity
.MemoryDatabaseManager
;
38 import org
.tianocore
.pcd
.entity
.Token
;
39 import org
.tianocore
.pcd
.entity
.UsageIdentification
;
40 import org
.tianocore
.pcd
.exception
.EntityException
;
41 import org
.tianocore
.pcd
.action
.PlatformPcdPreprocessAction
;
42 import org
.tianocore
.build
.exception
.PlatformPcdPreprocessBuildException
;
43 import org
.tianocore
.pcd
.exception
.PlatformPcdPreprocessException
;
46 This action class is to collect PCD information from MSA, SPD, FPD xml file.
47 This class will be used for wizard and build tools, So it can *not* inherit
48 from buildAction or UIAction.
50 public class PlatformPcdPreprocessActionForBuilding
extends PlatformPcdPreprocessAction
{
52 /// FPD file is the root file.
54 private String fpdFilePath
;
57 /// Message level for CollectPCDAction.
59 private int originalMessageLevel
;
62 /// Cache the fpd docment instance for private usage.
64 private PlatformSurfaceAreaDocument fpdDocInstance
;
67 Set action message level for CollectPcdAction tool.
69 The message should be restored when this action exit.
71 @param actionMessageLevel parameter for this action
73 public void setActionMessageLevel(int actionMessageLevel
) {
74 originalMessageLevel
= ActionMessage
.messageLevel
;
75 ActionMessage
.messageLevel
= actionMessageLevel
;
79 Set FPDFileName parameter for this action class.
81 @param fpdFilePath fpd file path
83 public void setFPDFilePath(String fpdFilePath
) {
84 this.fpdFilePath
= fpdFilePath
;
88 Common function interface for outer.
90 @param fpdFilePath The fpd file path of current build or analysis.
91 @param messageLevel The message level for this Action.
93 @throws PlatformPreprocessBuildException
94 The exception of this function. Because it can *not* be predict
95 where the action class will be used. So only Exception can be throw.
98 public void perform(String fpdFilePath
, int messageLevel
)
99 throws PlatformPcdPreprocessBuildException
{
100 setFPDFilePath(fpdFilePath
);
101 setActionMessageLevel(messageLevel
);
104 ActionMessage
.messageLevel
= originalMessageLevel
;
108 Core execution function for this action class.
110 This function work flows will be:
111 1) Collect and prepocess PCD information from FPD file, all PCD
112 information will be stored into memory database.
113 2) Generate 3 strings for
114 a) All modules using Dynamic(Ex) PCD entry.(Token Number)
115 b) PEI PCDDatabase (C Structure) for PCD Service PEIM.
116 c) DXE PCD Database (C structure) for PCD Service DXE.
119 @throws EntityException Exception indicate failed to execute this action.
122 public void execute() throws PlatformPcdPreprocessBuildException
{
123 String errorMessageHeader
= "Fail to initialize Pcd memory database for building. Because:";
125 // Get memoryDatabaseManager instance from GlobalData.
126 // The memoryDatabaseManager should be initialized as static variable
127 // in some Pre-process class.
129 setPcdDbManager(GlobalData
.getPCDMemoryDBManager());
132 // Collect all PCD information defined in FPD file.
133 // Evenry token defind in FPD will be created as an token into
137 initPcdMemoryDbWithPlatformInfo();
138 } catch (PlatformPcdPreprocessException exp
) {
139 throw new PlatformPcdPreprocessBuildException(errorMessageHeader
+ exp
.getMessage());
143 // Generate for PEI, DXE PCD DATABASE's definition and initialization.
146 genPcdDatabaseSourceCode ();
147 } catch (EntityException exp
) {
148 throw new PlatformPcdPreprocessBuildException(errorMessageHeader
+ exp
.getMessage());
153 Override function: implementate the method of get Guid string information from SPD file.
155 @param guidCName Guid CName string.
157 @return String[] Guid information from SPD file.
158 @throws PlatformPcdPreprocessException
159 Fail to get Guid information from SPD file.
161 public String
[] getGuidInfoFromSpd(String guidCName
) throws PlatformPcdPreprocessException
{
162 String
[] tokenSpaceStrRet
= null;
164 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(guidCName
);
165 } catch ( Exception e
) {
166 throw new PlatformPcdPreprocessException ("Failed get Guid CName " + guidCName
+ "from SPD file!");
168 return tokenSpaceStrRet
;
172 This function generates source code for PCD Database.
174 @throws EntityException If the token does *not* exist in memory database.
177 private void genPcdDatabaseSourceCode()
178 throws EntityException
{
179 String PcdCommonHeaderString
= PcdDatabase
.getPcdDatabaseCommonDefinitions();
181 ArrayList
<Token
> alPei
= new ArrayList
<Token
> ();
182 ArrayList
<Token
> alDxe
= new ArrayList
<Token
> ();
184 getPcdDbManager().getTwoPhaseDynamicRecordArray(alPei
, alDxe
);
185 PcdDatabase pcdPeiDatabase
= new PcdDatabase (alPei
, "PEI", 0);
186 pcdPeiDatabase
.genCode();
187 MemoryDatabaseManager
.PcdPeimHString
= PcdCommonHeaderString
+ pcdPeiDatabase
.getHString() +
188 PcdDatabase
.getPcdPeiDatabaseDefinitions();
189 MemoryDatabaseManager
.PcdPeimCString
= pcdPeiDatabase
.getCString();
191 PcdDatabase pcdDxeDatabase
= new PcdDatabase(alDxe
, "DXE", alPei
.size());
192 pcdDxeDatabase
.genCode();
193 MemoryDatabaseManager
.PcdDxeHString
= MemoryDatabaseManager
.PcdPeimHString
+ pcdDxeDatabase
.getHString() +
194 PcdDatabase
.getPcdDxeDatabaseDefinitions();
195 MemoryDatabaseManager
.PcdDxeCString
= pcdDxeDatabase
.getCString();
199 Override function: Get component array from FPD.
201 This function maybe provided by some Global class.
203 @return List<ModuleInfo> the component array.
204 @throws PlatformPcdPreprocessException get all modules in <ModuleSA> in FPD file.
207 public List
<ModulePcdInfoFromFpd
> getComponentsFromFpd()
208 throws PlatformPcdPreprocessException
{
209 List
<ModulePcdInfoFromFpd
> allModules
= new ArrayList
<ModulePcdInfoFromFpd
>();
210 Map
<FpdModuleIdentification
, XmlObject
> pcdBuildDefinitions
= null;
211 UsageIdentification usageId
= null;
213 pcdBuildDefinitions
= GlobalData
.getFpdPcdBuildDefinitions();
214 if (pcdBuildDefinitions
== null) {
219 // Loop map to retrieve all PCD build definition and Module id
221 Iterator item
= pcdBuildDefinitions
.keySet().iterator();
222 while (item
.hasNext()){
223 FpdModuleIdentification id
= (FpdModuleIdentification
) item
.next();
224 usageId
= new UsageIdentification(id
.getModule().getName(),
225 id
.getModule().getGuid(),
226 id
.getModule().getPackage().getName(),
227 id
.getModule().getPackage().getGuid(),
229 id
.getModule().getVersion(),
230 id
.getModule().getModuleType());
231 allModules
.add(new ModulePcdInfoFromFpd(usageId
, pcdBuildDefinitions
.get(id
)));
237 Override function: Verify the datum value according its datum size and datum type, this
238 function maybe moved to FPD verification tools in future.
240 @param cName The token name
241 @param moduleName The module who use this PCD token
242 @param datum The PCD's datum
243 @param datumType The PCD's datum type
244 @param maxDatumSize The max size for PCD's Datum.
246 @return String exception strings.
248 public String
verifyDatum(String cName
,
251 Token
.DATUM_TYPE datumType
,
253 String exceptionString
= null;
259 if (moduleName
== null) {
260 moduleName
= "section <DynamicPcdBuildDefinitions>";
262 moduleName
= "module " + moduleName
;
265 if (maxDatumSize
== 0) {
266 exceptionString
= String
.format("[FPD file error] You maybe miss <MaxDatumSize> for PCD %s in %s",
269 return exceptionString
;
274 if (maxDatumSize
!= 1) {
275 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
276 "is UINT8, but datum size is %d, they are not matched!",
280 return exceptionString
;
285 value
= Integer
.decode(datum
);
286 } catch (NumberFormatException nfeExp
) {
287 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid "+
288 "digital format of UINT8",
291 return exceptionString
;
294 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s exceed"+
295 " the max size of UINT8 - 0xFF",
299 return exceptionString
;
304 if (maxDatumSize
!= 2) {
305 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
306 "is UINT16, but datum size is %d, they are not matched!",
310 return exceptionString
;
314 value
= Integer
.decode(datum
);
315 } catch (NumberFormatException nfeExp
) {
316 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is "+
317 "not valid digital of UINT16",
320 return exceptionString
;
322 if (value
> 0xFFFF) {
323 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
324 "which exceed the range of UINT16 - 0xFFFF",
328 return exceptionString
;
333 if (maxDatumSize
!= 4) {
334 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
335 "is UINT32, but datum size is %d, they are not matched!",
339 return exceptionString
;
344 if (datum
.length() > 2) {
345 if ((datum
.charAt(0) == '0') &&
346 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
347 subStr
= datum
.substring(2, datum
.length());
348 value64
= new BigInteger(subStr
, 16);
350 value64
= new BigInteger(datum
);
353 value64
= new BigInteger(datum
);
355 } catch (NumberFormatException nfeExp
) {
356 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not "+
357 "valid digital of UINT32",
360 return exceptionString
;
363 if (value64
.bitLength() > 32) {
364 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s which "+
365 "exceed the range of UINT32 - 0xFFFFFFFF",
369 return exceptionString
;
374 if (maxDatumSize
!= 8) {
375 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
376 "is UINT64, but datum size is %d, they are not matched!",
380 return exceptionString
;
385 if (datum
.length() > 2) {
386 if ((datum
.charAt(0) == '0') &&
387 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
388 subStr
= datum
.substring(2, datum
.length());
389 value64
= new BigInteger(subStr
, 16);
391 value64
= new BigInteger(datum
);
394 value64
= new BigInteger(datum
);
396 } catch (NumberFormatException nfeExp
) {
397 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid"+
398 " digital of UINT64",
401 return exceptionString
;
404 if (value64
.bitLength() > 64) {
405 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
406 "exceed the range of UINT64 - 0xFFFFFFFFFFFFFFFF",
410 return exceptionString
;
415 if (maxDatumSize
!= 1) {
416 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
417 "is BOOLEAN, but datum size is %d, they are not matched!",
421 return exceptionString
;
425 if (!(datum
.equalsIgnoreCase("TRUE") ||
426 datum
.equalsIgnoreCase("FALSE"))) {
427 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
428 "is BOOELAN, but value is not 'true'/'TRUE' or 'FALSE'/'false'",
431 return exceptionString
;
441 char ch
= datum
.charAt(0);
445 // For void* type PCD, only three datum is support:
446 // 1) Unicode: string with start char is "L"
447 // 2) Ansci: String start char is ""
448 // 3) byte array: String start char "{"
451 start
= datum
.indexOf('\"');
452 end
= datum
.lastIndexOf('\"');
454 (end
> datum
.length())||
455 ((start
== end
) && (datum
.length() > 0))) {
456 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
457 "a UNICODE string because start with L\", but format maybe"+
458 "is not right, correct UNICODE string is L\"...\"!",
461 return exceptionString
;
464 strValue
= datum
.substring(start
+ 1, end
);
465 if ((strValue
.length() * 2) > maxDatumSize
) {
466 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
467 "a UNICODE string, but the datum size is %d exceed to <MaxDatumSize> : %d",
470 strValue
.length() * 2,
472 return exceptionString
;
474 } else if (ch
== '\"'){
475 start
= datum
.indexOf('\"');
476 end
= datum
.lastIndexOf('\"');
478 (end
> datum
.length())||
479 ((start
== end
) && (datum
.length() > 0))) {
480 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
481 "a ANSCII string because start with \", but format maybe"+
482 "is not right, correct ANSIC string is \"...\"!",
485 return exceptionString
;
487 strValue
= datum
.substring(start
+ 1, end
);
488 if ((strValue
.length()) > maxDatumSize
) {
489 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
490 "a ANSCI string, but the datum size is %d which exceed to <MaxDatumSize> : %d",
495 return exceptionString
;
497 } else if (ch
=='{') {
498 String
[] strValueArray
;
500 start
= datum
.indexOf('{');
501 end
= datum
.lastIndexOf('}');
502 strValue
= datum
.substring(start
+ 1, end
);
503 strValue
= strValue
.trim();
504 if (strValue
.length() == 0) {
505 exceptionString
= String
.format ("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
506 "it is byte array in fact, but '{}' is not valid for NULL datam but"+
510 return exceptionString
;
512 strValueArray
= strValue
.split(",");
513 for (index
= 0; index
< strValueArray
.length
; index
++) {
515 value
= Integer
.decode(strValueArray
[index
].trim());
516 } catch (NumberFormatException nfeEx
) {
517 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
518 "it is byte array in fact. For every byte in array should be a valid"+
519 "byte digital, but element %s is not a valid byte digital!",
522 strValueArray
[index
]);
523 return exceptionString
;
526 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, "+
527 "it is byte array in fact. But the element of %s exceed the byte range",
530 strValueArray
[index
]);
531 return exceptionString
;
535 if (strValueArray
.length
> maxDatumSize
) {
536 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is byte"+
537 "array, but the number of bytes is %d which exceed to <MaxDatumSzie> : %d!",
540 strValueArray
.length
,
542 return exceptionString
;
545 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*. For VOID* type, you have three format choise:\n "+
546 "1) UNICODE string: like L\"xxxx\";\r\n"+
547 "2) ANSIC string: like \"xxx\";\r\n"+
548 "3) Byte array: like {0x2, 0x45, 0x23}\r\n"+
549 "But the datum in seems does not following above format!",
552 return exceptionString
;
556 exceptionString
= String
.format("[FPD file error] For PCD entry %s in %s, datum type is unknown, it should be one of "+
557 "UINT8, UINT16, UINT32, UINT64, VOID*, BOOLEAN",
560 return exceptionString
;
566 Override function: Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.
568 This function should be implemented in GlobalData in future.
570 @param token The token instance which has hold module's PCD information
571 @param moduleName The name of module who will use this Dynamic PCD.
573 @return DynamicPcdBuildDefinitions.PcdBuildData
575 public DynamicPcdBuildDefinitions
.PcdBuildData
getDynamicInfoFromFpd(Token token
,
577 throws PlatformPcdPreprocessException
{
579 String exceptionString
= null;
580 String dynamicPrimaryKey
= null;
581 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
582 List
<DynamicPcdBuildDefinitions
.PcdBuildData
> dynamicPcdBuildDataArray
= null;
583 String
[] tokenSpaceStrRet
= null;
586 // If FPD document is not be opened, open and initialize it.
587 // BUGBUG: The code should be moved into GlobalData in future.
589 if (fpdDocInstance
== null) {
591 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
592 } catch(IOException ioE
) {
593 throw new PlatformPcdPreprocessException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
594 } catch(XmlException xmlE
) {
595 throw new PlatformPcdPreprocessException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
599 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
600 if (dynamicPcdBuildDefinitions
== null) {
601 exceptionString
= String
.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+
602 "PCD entry %s in module %s!",
605 throw new PlatformPcdPreprocessException(exceptionString
);
608 dynamicPcdBuildDataArray
= dynamicPcdBuildDefinitions
.getPcdBuildDataList();
609 for (index
= 0; index
< dynamicPcdBuildDataArray
.size(); index
++) {
611 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(dynamicPcdBuildDataArray
.get(index
).getTokenSpaceGuidCName());
612 } catch (Exception e
) {
613 throw new PlatformPcdPreprocessException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName());
616 if (tokenSpaceStrRet
== null) {
617 throw new PlatformPcdPreprocessException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName());
620 dynamicPrimaryKey
= Token
.getPrimaryKeyString(dynamicPcdBuildDataArray
.get(index
).getCName(),
621 tokenSpaceStrRet
[1]);
622 if (dynamicPrimaryKey
.equalsIgnoreCase(token
.getPrimaryKeyString())) {
623 return dynamicPcdBuildDataArray
.get(index
);
631 Override function: get all <DynamicPcdBuildDefinition> from FPD file.
633 @return List<DynamicPcdBuildDefinitions.PcdBuildData> All DYNAMIC PCD list in <DynamicPcdBuildDefinitions> in FPD file.
634 @throws PlatformPcdPreprocessBuildException Failure to get dynamic information list.
637 public List
<DynamicPcdBuildDefinitions
.PcdBuildData
>
638 getAllDynamicPcdInfoFromFpd()
639 throws PlatformPcdPreprocessException
{
640 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
643 // Open fpd document to get <DynamicPcdBuildDefinition> Section.
644 // BUGBUG: the function should be move GlobalData in furture.
646 if (fpdDocInstance
== null) {
648 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
649 } catch(IOException ioE
) {
650 throw new PlatformPcdPreprocessException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
651 } catch(XmlException xmlE
) {
652 throw new PlatformPcdPreprocessException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
656 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
657 if (dynamicPcdBuildDefinitions
== null) {
661 return dynamicPcdBuildDefinitions
.getPcdBuildDataList();
665 check parameter for this action.
667 @throws PlatformPcdPreprocessBuildException Bad parameter.
669 private void checkParameter() throws PlatformPcdPreprocessBuildException
{
672 if (fpdFilePath
== null) {
673 throw new PlatformPcdPreprocessBuildException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
676 if (fpdFilePath
.length() == 0) {
677 throw new PlatformPcdPreprocessBuildException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
680 file
= new File(fpdFilePath
);
683 throw new PlatformPcdPreprocessBuildException("FPD File " + fpdFilePath
+ " does not exist!");
690 @param argv parameter from command line
692 public static void main(String argv
[]) throws PlatformPcdPreprocessBuildException
{
693 PlatformPcdPreprocessActionForBuilding ca
= new PlatformPcdPreprocessActionForBuilding();
694 String projectDir
= "x:/edk2";
695 ca
.setFPDFilePath(projectDir
+ "/EdkNt32Pkg/Nt32.fpd");
696 ca
.setActionMessageLevel(ActionMessage
.MAX_MESSAGE_LEVEL
);
697 GlobalData
.initInfo("Tools" + File
.separator
+ "Conf" + File
.separator
+ "FrameworkDatabase.db",
700 System
.out
.println("After initInfo!");
701 FpdParserTask fpt
= new FpdParserTask();
702 fpt
.parseFpdFile(new File(projectDir
+ "/EdkNt32Pkg/Nt32.fpd"));