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
.PcdBuildDefinitionDocument
;
32 import org
.tianocore
.PlatformSurfaceAreaDocument
;
33 import org
.tianocore
.build
.exception
.PlatformPcdPreprocessBuildException
;
34 import org
.tianocore
.build
.fpd
.FpdParserTask
;
35 import org
.tianocore
.build
.global
.GlobalData
;
36 import org
.tianocore
.build
.id
.FpdModuleIdentification
;
37 import org
.tianocore
.pcd
.action
.ActionMessage
;
38 import org
.tianocore
.pcd
.action
.PlatformPcdPreprocessAction
;
39 import org
.tianocore
.pcd
.entity
.MemoryDatabaseManager
;
40 import org
.tianocore
.pcd
.entity
.ModulePcdInfoFromFpd
;
41 import org
.tianocore
.pcd
.entity
.Token
;
42 import org
.tianocore
.pcd
.entity
.UsageIdentification
;
43 import org
.tianocore
.pcd
.exception
.EntityException
;
44 import org
.tianocore
.pcd
.exception
.PlatformPcdPreprocessException
;
47 This action class is to collect PCD information from MSA, SPD, FPD xml file.
48 This class will be used for wizard and build tools, So it can *not* inherit
49 from buildAction or UIAction.
51 public class PlatformPcdPreprocessActionForBuilding
extends PlatformPcdPreprocessAction
{
53 /// FPD file is the root file.
55 private String fpdFilePath
;
58 /// Message level for CollectPCDAction.
60 private int originalMessageLevel
;
63 /// Cache the fpd docment instance for private usage.
65 private PlatformSurfaceAreaDocument fpdDocInstance
;
68 Set action message level for CollectPcdAction tool.
70 The message should be restored when this action exit.
72 @param actionMessageLevel parameter for this action
74 public void setActionMessageLevel(int actionMessageLevel
) {
75 originalMessageLevel
= ActionMessage
.messageLevel
;
76 ActionMessage
.messageLevel
= actionMessageLevel
;
80 Set FPDFileName parameter for this action class.
82 @param fpdFilePath fpd file path
84 public void setFPDFilePath(String fpdFilePath
) {
85 this.fpdFilePath
= fpdFilePath
;
89 Common function interface for outer.
91 @param fpdFilePath The fpd file path of current build or analysis.
92 @param messageLevel The message level for this Action.
94 @throws PlatformPreprocessBuildException
95 The exception of this function. Because it can *not* be predict
96 where the action class will be used. So only Exception can be throw.
99 public void perform(String fpdFilePath
, int messageLevel
)
100 throws PlatformPcdPreprocessBuildException
{
101 setFPDFilePath(fpdFilePath
);
102 setActionMessageLevel(messageLevel
);
105 ActionMessage
.messageLevel
= originalMessageLevel
;
109 Core execution function for this action class.
111 This function work flows will be:
112 1) Collect and prepocess PCD information from FPD file, all PCD
113 information will be stored into memory database.
114 2) Generate 3 strings for
115 a) All modules using Dynamic(Ex) PCD entry.(Token Number)
116 b) PEI PCDDatabase (C Structure) for PCD Service PEIM.
117 c) DXE PCD Database (C structure) for PCD Service DXE.
120 @throws EntityException Exception indicate failed to execute this action.
123 public void execute() throws PlatformPcdPreprocessBuildException
{
124 String errorMessageHeader
= "Fail to initialize Pcd memory database for building. Because:";
125 String errorsForPreprocess
= null;
128 // Get memoryDatabaseManager instance from GlobalData.
129 // The memoryDatabaseManager should be initialized as static variable
130 // in some Pre-process class.
132 setPcdDbManager(GlobalData
.getPCDMemoryDBManager());
135 // Collect all PCD information defined in FPD file.
136 // Evenry token defind in FPD will be created as an token into
140 initPcdMemoryDbWithPlatformInfo();
141 } catch (PlatformPcdPreprocessException exp
) {
142 throw new PlatformPcdPreprocessBuildException(errorMessageHeader
+ exp
.getMessage());
144 errorsForPreprocess
= this.getErrorString();
145 if (errorsForPreprocess
!= null) {
146 throw new PlatformPcdPreprocessBuildException(errorMessageHeader
+ "\r\n" + errorsForPreprocess
);
150 // Generate for PEI, DXE PCD DATABASE's definition and initialization.
153 genPcdDatabaseSourceCode ();
154 } catch (EntityException exp
) {
155 throw new PlatformPcdPreprocessBuildException(errorMessageHeader
+ exp
.getMessage());
160 Override function: implementate the method of get Guid string information from SPD file.
162 @param guidCName Guid CName string.
164 @return String Guid information from SPD file.
165 @throws PlatformPcdPreprocessException
166 Fail to get Guid information from SPD file.
168 public String
getGuidInfoFromSpd(String guidCName
) throws PlatformPcdPreprocessException
{
169 String tokenSpaceStrRet
= null;
171 tokenSpaceStrRet
= GlobalData
.getGuidInfoFromCname(guidCName
);
172 } catch ( Exception e
) {
173 throw new PlatformPcdPreprocessException ("Failed get Guid CName " + guidCName
+ "from SPD file!");
175 return tokenSpaceStrRet
;
179 This function generates source code for PCD Database.
181 @throws EntityException If the token does *not* exist in memory database.
184 private void genPcdDatabaseSourceCode()
185 throws EntityException
{
186 String PcdCommonHeaderString
= PcdDatabase
.getPcdDatabaseCommonDefinitions();
188 ArrayList
<Token
> alPei
= new ArrayList
<Token
> ();
189 ArrayList
<Token
> alDxe
= new ArrayList
<Token
> ();
191 getPcdDbManager().getTwoPhaseDynamicRecordArray(alPei
, alDxe
);
192 PcdDatabase pcdPeiDatabase
= new PcdDatabase (alPei
, "PEI", 0);
193 pcdPeiDatabase
.genCode();
194 MemoryDatabaseManager
.PcdPeimHString
= PcdCommonHeaderString
+ pcdPeiDatabase
.getHString() +
195 PcdDatabase
.getPcdPeiDatabaseDefinitions();
196 MemoryDatabaseManager
.PcdPeimCString
= pcdPeiDatabase
.getCString();
198 PcdDatabase pcdDxeDatabase
= new PcdDatabase(alDxe
, "DXE", alPei
.size());
199 pcdDxeDatabase
.genCode();
200 MemoryDatabaseManager
.PcdDxeHString
= MemoryDatabaseManager
.PcdPeimHString
+ pcdDxeDatabase
.getHString() +
201 PcdDatabase
.getPcdDxeDatabaseDefinitions();
202 MemoryDatabaseManager
.PcdDxeCString
= pcdDxeDatabase
.getCString();
206 Override function: Get component array from FPD.
208 This function maybe provided by some Global class.
210 @return List<ModuleInfo> the component array.
211 @throws PlatformPcdPreprocessException get all modules in <ModuleSA> in FPD file.
214 public List
<ModulePcdInfoFromFpd
> getComponentsFromFpd()
215 throws PlatformPcdPreprocessException
{
216 List
<ModulePcdInfoFromFpd
> allModules
= new ArrayList
<ModulePcdInfoFromFpd
>();
217 Map
<FpdModuleIdentification
, XmlObject
> pcdBuildDefinitions
= null;
218 UsageIdentification usageId
= null;
220 pcdBuildDefinitions
= GlobalData
.getFpdPcdBuildDefinitions();
221 if (pcdBuildDefinitions
== null) {
226 // Loop map to retrieve all PCD build definition and Module id
228 Iterator item
= pcdBuildDefinitions
.keySet().iterator();
229 while (item
.hasNext()){
230 FpdModuleIdentification id
= (FpdModuleIdentification
) item
.next();
231 usageId
= new UsageIdentification(id
.getModule().getName(),
232 id
.getModule().getGuid(),
233 id
.getModule().getPackage().getName(),
234 id
.getModule().getPackage().getGuid(),
236 id
.getModule().getVersion(),
237 id
.getModule().getModuleType());
239 new ModulePcdInfoFromFpd(
241 ((PcdBuildDefinitionDocument
)pcdBuildDefinitions
.get(id
)).getPcdBuildDefinition()));
247 Override function: Verify the datum value according its datum size and datum type, this
248 function maybe moved to FPD verification tools in future.
250 @param cName The token name
251 @param moduleName The module who use this PCD token
252 @param datum The PCD's datum
253 @param datumType The PCD's datum type
254 @param maxDatumSize The max size for PCD's Datum.
256 @return String exception strings.
258 public String
verifyDatum(String cName
,
261 Token
.DATUM_TYPE datumType
,
263 String exceptionString
= null;
269 if (moduleName
== null) {
270 moduleName
= "section <DynamicPcdBuildDefinitions>";
272 moduleName
= "module " + moduleName
;
275 if (maxDatumSize
== 0) {
276 exceptionString
= String
.format("[FPD file error] You maybe miss <MaxDatumSize> for PCD %s in %s",
279 return exceptionString
;
284 if (maxDatumSize
!= 1) {
285 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
286 "is UINT8, but datum size is %d, they are not matched!",
290 return exceptionString
;
295 value
= Integer
.decode(datum
);
296 } catch (NumberFormatException nfeExp
) {
297 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid "+
298 "digital format of UINT8",
301 return exceptionString
;
304 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s exceed"+
305 " the max size of UINT8 - 0xFF",
309 return exceptionString
;
314 if (maxDatumSize
!= 2) {
315 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
316 "is UINT16, but datum size is %d, they are not matched!",
320 return exceptionString
;
324 value
= Integer
.decode(datum
);
325 } catch (NumberFormatException nfeExp
) {
326 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is "+
327 "not valid digital of UINT16",
330 return exceptionString
;
332 if (value
> 0xFFFF) {
333 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
334 "which exceed the range of UINT16 - 0xFFFF",
338 return exceptionString
;
343 if (maxDatumSize
!= 4) {
344 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
345 "is UINT32, but datum size is %d, they are not matched!",
349 return exceptionString
;
354 if (datum
.length() > 2) {
355 if ((datum
.charAt(0) == '0') &&
356 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
357 subStr
= datum
.substring(2, datum
.length());
358 value64
= new BigInteger(subStr
, 16);
360 value64
= new BigInteger(datum
);
363 value64
= new BigInteger(datum
);
365 } catch (NumberFormatException nfeExp
) {
366 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not "+
367 "valid digital of UINT32",
370 return exceptionString
;
373 if (value64
.bitLength() > 32) {
374 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s which "+
375 "exceed the range of UINT32 - 0xFFFFFFFF",
379 return exceptionString
;
384 if (maxDatumSize
!= 8) {
385 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
386 "is UINT64, but datum size is %d, they are not matched!",
390 return exceptionString
;
395 if (datum
.length() > 2) {
396 if ((datum
.charAt(0) == '0') &&
397 ((datum
.charAt(1) == 'x') || (datum
.charAt(1) == 'X'))){
398 subStr
= datum
.substring(2, datum
.length());
399 value64
= new BigInteger(subStr
, 16);
401 value64
= new BigInteger(datum
);
404 value64
= new BigInteger(datum
);
406 } catch (NumberFormatException nfeExp
) {
407 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is not valid"+
408 " digital of UINT64",
411 return exceptionString
;
414 if (value64
.bitLength() > 64) {
415 exceptionString
= String
.format("[FPD file error] The datum for PCD %s in %s is %s "+
416 "exceed the range of UINT64 - 0xFFFFFFFFFFFFFFFF",
420 return exceptionString
;
425 if (maxDatumSize
!= 1) {
426 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
427 "is BOOLEAN, but datum size is %d, they are not matched!",
431 return exceptionString
;
435 if (!(datum
.equalsIgnoreCase("TRUE") ||
436 datum
.equalsIgnoreCase("FALSE"))) {
437 exceptionString
= String
.format("[FPD file error] The datum type of PCD data %s in %s "+
438 "is BOOELAN, but value is not 'true'/'TRUE' or 'FALSE'/'false'",
441 return exceptionString
;
451 char ch
= datum
.charAt(0);
455 // For void* type PCD, only three datum is support:
456 // 1) Unicode: string with start char is "L"
457 // 2) Ansci: String start char is ""
458 // 3) byte array: String start char "{"
461 start
= datum
.indexOf('\"');
462 end
= datum
.lastIndexOf('\"');
464 (end
> datum
.length())||
465 ((start
== end
) && (datum
.length() > 0))) {
466 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
467 "a UNICODE string because start with L\", but format maybe"+
468 "is not right, correct UNICODE string is L\"...\"!",
471 return exceptionString
;
474 strValue
= datum
.substring(start
+ 1, end
);
475 if ((strValue
.length() * 2) > maxDatumSize
) {
476 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
477 "a UNICODE string, but the datum size is %d exceed to <MaxDatumSize> : %d",
480 strValue
.length() * 2,
482 return exceptionString
;
484 } else if (ch
== '\"'){
485 start
= datum
.indexOf('\"');
486 end
= datum
.lastIndexOf('\"');
488 (end
> datum
.length())||
489 ((start
== end
) && (datum
.length() > 0))) {
490 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
491 "a ANSCII string because start with \", but format maybe"+
492 "is not right, correct ANSIC string is \"...\"!",
495 return exceptionString
;
497 strValue
= datum
.substring(start
+ 1, end
);
498 if ((strValue
.length()) > maxDatumSize
) {
499 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
500 "a ANSCI string, but the datum size is %d which exceed to <MaxDatumSize> : %d",
505 return exceptionString
;
507 } else if (ch
=='{') {
508 String
[] strValueArray
;
510 start
= datum
.indexOf('{');
511 end
= datum
.lastIndexOf('}');
512 strValue
= datum
.substring(start
+ 1, end
);
513 strValue
= strValue
.trim();
514 if (strValue
.length() == 0) {
515 exceptionString
= String
.format ("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
516 "it is byte array in fact, but '{}' is not valid for NULL datam but"+
520 return exceptionString
;
522 strValueArray
= strValue
.split(",");
523 for (index
= 0; index
< strValueArray
.length
; index
++) {
525 value
= Integer
.decode(strValueArray
[index
].trim());
526 } catch (NumberFormatException nfeEx
) {
527 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
528 "it is byte array in fact. For every byte in array should be a valid"+
529 "byte digital, but element %s is not a valid byte digital!",
532 strValueArray
[index
]);
533 return exceptionString
;
536 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, "+
537 "it is byte array in fact. But the element of %s exceed the byte range",
540 strValueArray
[index
]);
541 return exceptionString
;
545 if (strValueArray
.length
> maxDatumSize
) {
546 exceptionString
= String
.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is byte"+
547 "array, but the number of bytes is %d which exceed to <MaxDatumSzie> : %d!",
550 strValueArray
.length
,
552 return exceptionString
;
555 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"+
556 "1) UNICODE string: like L\"xxxx\";\r\n"+
557 "2) ANSIC string: like \"xxx\";\r\n"+
558 "3) Byte array: like {0x2, 0x45, 0x23}\r\n"+
559 "But the datum in seems does not following above format!",
562 return exceptionString
;
566 exceptionString
= String
.format("[FPD file error] For PCD entry %s in %s, datum type is unknown, it should be one of "+
567 "UINT8, UINT16, UINT32, UINT64, VOID*, BOOLEAN",
570 return exceptionString
;
576 Override function: Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.
578 This function should be implemented in GlobalData in future.
580 @param token The token instance which has hold module's PCD information
581 @param moduleName The name of module who will use this Dynamic PCD.
583 @return DynamicPcdBuildDefinitions.PcdBuildData
585 public DynamicPcdBuildDefinitions
.PcdBuildData
getDynamicInfoFromFpd(Token token
,
587 throws PlatformPcdPreprocessException
{
589 String exceptionString
= null;
590 String dynamicPrimaryKey
= null;
591 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
592 List
<DynamicPcdBuildDefinitions
.PcdBuildData
> dynamicPcdBuildDataArray
= null;
593 String tokenSpaceStrRet
= null;
596 // If FPD document is not be opened, open and initialize it.
597 // BUGBUG: The code should be moved into GlobalData in future.
599 if (fpdDocInstance
== null) {
601 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
602 } catch(IOException ioE
) {
603 throw new PlatformPcdPreprocessException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
604 } catch(XmlException xmlE
) {
605 throw new PlatformPcdPreprocessException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
609 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
610 if (dynamicPcdBuildDefinitions
== null) {
611 exceptionString
= String
.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+
612 "PCD entry %s in module %s!",
615 putError(exceptionString
);
619 dynamicPcdBuildDataArray
= dynamicPcdBuildDefinitions
.getPcdBuildDataList();
620 for (index
= 0; index
< dynamicPcdBuildDataArray
.size(); index
++) {
621 tokenSpaceStrRet
= getGuidInfoFromSpd(dynamicPcdBuildDataArray
.get(index
).getTokenSpaceGuidCName());
623 if (tokenSpaceStrRet
== null) {
624 exceptionString
= "Fail to get token space guid for token " + dynamicPcdBuildDataArray
.get(index
).getCName();
625 putError(exceptionString
);
629 dynamicPrimaryKey
= Token
.getPrimaryKeyString(dynamicPcdBuildDataArray
.get(index
).getCName(),
631 if (dynamicPrimaryKey
.equalsIgnoreCase(token
.getPrimaryKeyString())) {
632 return dynamicPcdBuildDataArray
.get(index
);
640 Override function: get all <DynamicPcdBuildDefinition> from FPD file.
642 @return List<DynamicPcdBuildDefinitions.PcdBuildData> All DYNAMIC PCD list in <DynamicPcdBuildDefinitions> in FPD file.
643 @throws PlatformPcdPreprocessBuildException Failure to get dynamic information list.
646 public List
<DynamicPcdBuildDefinitions
.PcdBuildData
>
647 getAllDynamicPcdInfoFromFpd()
648 throws PlatformPcdPreprocessException
{
649 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions
= null;
652 // Open fpd document to get <DynamicPcdBuildDefinition> Section.
653 // BUGBUG: the function should be move GlobalData in furture.
655 if (fpdDocInstance
== null) {
657 fpdDocInstance
= (PlatformSurfaceAreaDocument
)XmlObject
.Factory
.parse(new File(fpdFilePath
));
658 } catch(IOException ioE
) {
659 throw new PlatformPcdPreprocessException("File IO error for xml file:" + fpdFilePath
+ "\n" + ioE
.getMessage());
660 } catch(XmlException xmlE
) {
661 throw new PlatformPcdPreprocessException("Can't parse the FPD xml fle:" + fpdFilePath
+ "\n" + xmlE
.getMessage());
665 dynamicPcdBuildDefinitions
= fpdDocInstance
.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
666 if (dynamicPcdBuildDefinitions
== null) {
667 putError("There is no <DynamicPcdBuildDefinitions> in FPD file!");
671 return dynamicPcdBuildDefinitions
.getPcdBuildDataList();
675 check parameter for this action.
677 @throws PlatformPcdPreprocessBuildException Bad parameter.
679 private void checkParameter() throws PlatformPcdPreprocessBuildException
{
682 if (fpdFilePath
== null) {
683 throw new PlatformPcdPreprocessBuildException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
686 if (fpdFilePath
.length() == 0) {
687 throw new PlatformPcdPreprocessBuildException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
690 file
= new File(fpdFilePath
);
693 throw new PlatformPcdPreprocessBuildException("FPD File " + fpdFilePath
+ " does not exist!");
700 @param argv parameter from command line
702 public static void main(String argv
[]) throws PlatformPcdPreprocessBuildException
{
703 PlatformPcdPreprocessActionForBuilding ca
= new PlatformPcdPreprocessActionForBuilding();
704 String projectDir
= "x:/edk2";
705 ca
.setFPDFilePath(projectDir
+ "/EdkNt32Pkg/Nt32.fpd");
706 ca
.setActionMessageLevel(ActionMessage
.MAX_MESSAGE_LEVEL
);
707 GlobalData
.initInfo("Tools" + File
.separator
+ "Conf" + File
.separator
+ "FrameworkDatabase.db",
710 System
.out
.println("After initInfo!");
711 FpdParserTask fpt
= new FpdParserTask();
712 fpt
.parseFpdFile(new File(projectDir
+ "/EdkNt32Pkg/Nt32.fpd"));