Shutdown the PCD's datum verification when building, it can save 2 minutes for full...
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / pcd / action / PlatformPcdPreprocessActionForBuilding.java
1 /** @file
2 PlatformPcdPreprocessActionForBuilding class.
3
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.
7
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
13
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.
16
17 **/
18 package org.tianocore.build.pcd.action;
19
20 import java.io.File;
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;
26 import java.util.Map;
27
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;
45
46 /**
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.
50 **/
51 public class PlatformPcdPreprocessActionForBuilding extends PlatformPcdPreprocessAction {
52 ///
53 /// FPD file is the root file.
54 ///
55 private String fpdFilePath;
56
57 ///
58 /// Message level for CollectPCDAction.
59 ///
60 private int originalMessageLevel;
61
62 ///
63 /// Cache the fpd docment instance for private usage.
64 ///
65 private PlatformSurfaceAreaDocument fpdDocInstance;
66
67 /**
68 Set action message level for CollectPcdAction tool.
69
70 The message should be restored when this action exit.
71
72 @param actionMessageLevel parameter for this action
73 **/
74 public void setActionMessageLevel(int actionMessageLevel) {
75 originalMessageLevel = ActionMessage.messageLevel;
76 ActionMessage.messageLevel = actionMessageLevel;
77 }
78
79 /**
80 Set FPDFileName parameter for this action class.
81
82 @param fpdFilePath fpd file path
83 **/
84 public void setFPDFilePath(String fpdFilePath) {
85 this.fpdFilePath = fpdFilePath;
86 }
87
88 /**
89 Common function interface for outer.
90
91 @param fpdFilePath The fpd file path of current build or analysis.
92 @param messageLevel The message level for this Action.
93
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.
97
98 **/
99 public void perform(String fpdFilePath, int messageLevel)
100 throws PlatformPcdPreprocessBuildException {
101 setFPDFilePath(fpdFilePath);
102 setActionMessageLevel(messageLevel);
103 checkParameter();
104 execute();
105 ActionMessage.messageLevel = originalMessageLevel;
106 }
107
108 /**
109 Core execution function for this action class.
110
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.
118
119
120 @throws EntityException Exception indicate failed to execute this action.
121
122 **/
123 public void execute() throws PlatformPcdPreprocessBuildException {
124 String errorMessageHeader = "Fail to initialize Pcd memory database for building. Because:";
125 String errorsForPreprocess = null;
126
127 //
128 // Get memoryDatabaseManager instance from GlobalData.
129 // The memoryDatabaseManager should be initialized as static variable
130 // in some Pre-process class.
131 //
132 setPcdDbManager(GlobalData.getPCDMemoryDBManager());
133
134 //
135 // Collect all PCD information defined in FPD file.
136 // Evenry token defind in FPD will be created as an token into
137 // memory database.
138 //
139 try {
140 initPcdMemoryDbWithPlatformInfo();
141 } catch (PlatformPcdPreprocessException exp) {
142 throw new PlatformPcdPreprocessBuildException(errorMessageHeader + exp.getMessage());
143 }
144 errorsForPreprocess = this.getErrorString();
145 if (errorsForPreprocess != null) {
146 throw new PlatformPcdPreprocessBuildException(errorMessageHeader + "\r\n" + errorsForPreprocess);
147 }
148
149 //
150 // Generate for PEI, DXE PCD DATABASE's definition and initialization.
151 //
152 try {
153 genPcdDatabaseSourceCode ();
154 } catch (EntityException exp) {
155 throw new PlatformPcdPreprocessBuildException(errorMessageHeader + exp.getMessage());
156 }
157 }
158
159 /**
160 Override function: implementate the method of get Guid string information from SPD file.
161
162 @param guidCName Guid CName string.
163
164 @return String Guid information from SPD file.
165 @throws PlatformPcdPreprocessException
166 Fail to get Guid information from SPD file.
167 **/
168 public String getGuidInfoFromSpd(String guidCName) throws PlatformPcdPreprocessException {
169 String tokenSpaceStrRet = null;
170 try {
171 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(guidCName);
172 } catch ( Exception e ) {
173 throw new PlatformPcdPreprocessException ("Failed get Guid CName " + guidCName + "from SPD file!");
174 }
175 return tokenSpaceStrRet;
176 }
177
178 /**
179 This function generates source code for PCD Database.
180
181 @throws EntityException If the token does *not* exist in memory database.
182
183 **/
184 private void genPcdDatabaseSourceCode()
185 throws EntityException {
186 String PcdCommonHeaderString = PcdDatabase.getPcdDatabaseCommonDefinitions();
187
188 ArrayList<Token> alPei = new ArrayList<Token> ();
189 ArrayList<Token> alDxe = new ArrayList<Token> ();
190
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();
197
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();
203 }
204
205 /**
206 Override function: Get component array from FPD.
207
208 This function maybe provided by some Global class.
209
210 @return List<ModuleInfo> the component array.
211 @throws PlatformPcdPreprocessException get all modules in <ModuleSA> in FPD file.
212
213 **/
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;
219
220 pcdBuildDefinitions = GlobalData.getFpdPcdBuildDefinitions();
221 if (pcdBuildDefinitions == null) {
222 return null;
223 }
224
225 //
226 // Loop map to retrieve all PCD build definition and Module id
227 //
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(),
235 id.getArch(),
236 id.getModule().getVersion(),
237 id.getModule().getModuleType());
238 allModules.add(
239 new ModulePcdInfoFromFpd(
240 usageId,
241 ((PcdBuildDefinitionDocument)pcdBuildDefinitions.get(id)).getPcdBuildDefinition()));
242 }
243 return allModules;
244 }
245
246 /**
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.
249
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.
255
256 @return String exception strings.
257 */
258 public String verifyDatum(String cName,
259 String moduleName,
260 String datum,
261 Token.DATUM_TYPE datumType,
262 int maxDatumSize) {
263 //
264 // In building system, datum should not be checked, the checking work
265 // should be done by wizard tools or PCD verification tools.
266 //
267 return null;
268 }
269
270 /**
271 Override function: Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.
272
273 This function should be implemented in GlobalData in future.
274
275 @param token The token instance which has hold module's PCD information
276 @param moduleName The name of module who will use this Dynamic PCD.
277
278 @return DynamicPcdBuildDefinitions.PcdBuildData
279 **/
280 public DynamicPcdBuildDefinitions.PcdBuildData getDynamicInfoFromFpd(Token token,
281 String moduleName)
282 throws PlatformPcdPreprocessException {
283 int index = 0;
284 String exceptionString = null;
285 String dynamicPrimaryKey = null;
286 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null;
287 List<DynamicPcdBuildDefinitions.PcdBuildData> dynamicPcdBuildDataArray = null;
288 String tokenSpaceStrRet = null;
289
290 //
291 // If FPD document is not be opened, open and initialize it.
292 // BUGBUG: The code should be moved into GlobalData in future.
293 //
294 if (fpdDocInstance == null) {
295 try {
296 fpdDocInstance = (PlatformSurfaceAreaDocument)XmlObject.Factory.parse(new File(fpdFilePath));
297 } catch(IOException ioE) {
298 throw new PlatformPcdPreprocessException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage());
299 } catch(XmlException xmlE) {
300 throw new PlatformPcdPreprocessException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage());
301 }
302 }
303
304 dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
305 if (dynamicPcdBuildDefinitions == null) {
306 exceptionString = String.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+
307 "PCD entry %s in module %s!",
308 token.cName,
309 moduleName);
310 putError(exceptionString);
311 return null;
312 }
313
314 dynamicPcdBuildDataArray = dynamicPcdBuildDefinitions.getPcdBuildDataList();
315 for (index = 0; index < dynamicPcdBuildDataArray.size(); index ++) {
316 tokenSpaceStrRet = getGuidInfoFromSpd(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName());
317
318 if (tokenSpaceStrRet == null) {
319 exceptionString = "Fail to get token space guid for token " + dynamicPcdBuildDataArray.get(index).getCName();
320 putError(exceptionString);
321 continue;
322 }
323
324 dynamicPrimaryKey = Token.getPrimaryKeyString(dynamicPcdBuildDataArray.get(index).getCName(),
325 tokenSpaceStrRet);
326 if (dynamicPrimaryKey.equalsIgnoreCase(token.getPrimaryKeyString())) {
327 return dynamicPcdBuildDataArray.get(index);
328 }
329 }
330
331 return null;
332 }
333
334 /**
335 Override function: get all <DynamicPcdBuildDefinition> from FPD file.
336
337 @return List<DynamicPcdBuildDefinitions.PcdBuildData> All DYNAMIC PCD list in <DynamicPcdBuildDefinitions> in FPD file.
338 @throws PlatformPcdPreprocessBuildException Failure to get dynamic information list.
339
340 **/
341 public List<DynamicPcdBuildDefinitions.PcdBuildData>
342 getAllDynamicPcdInfoFromFpd()
343 throws PlatformPcdPreprocessException {
344 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null;
345
346 //
347 // Open fpd document to get <DynamicPcdBuildDefinition> Section.
348 // BUGBUG: the function should be move GlobalData in furture.
349 //
350 if (fpdDocInstance == null) {
351 try {
352 fpdDocInstance = (PlatformSurfaceAreaDocument)XmlObject.Factory.parse(new File(fpdFilePath));
353 } catch(IOException ioE) {
354 throw new PlatformPcdPreprocessException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage());
355 } catch(XmlException xmlE) {
356 throw new PlatformPcdPreprocessException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage());
357 }
358 }
359
360 dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
361 if (dynamicPcdBuildDefinitions == null) {
362 putError("There is no <DynamicPcdBuildDefinitions> in FPD file!");
363 return null;
364 }
365
366 return dynamicPcdBuildDefinitions.getPcdBuildDataList();
367 }
368
369 /**
370 check parameter for this action.
371
372 @throws PlatformPcdPreprocessBuildException Bad parameter.
373 **/
374 private void checkParameter() throws PlatformPcdPreprocessBuildException {
375 File file = null;
376
377 if (fpdFilePath == null) {
378 throw new PlatformPcdPreprocessBuildException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
379 }
380
381 if (fpdFilePath.length() == 0) {
382 throw new PlatformPcdPreprocessBuildException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
383 }
384
385 file = new File(fpdFilePath);
386
387 if(!file.exists()) {
388 throw new PlatformPcdPreprocessBuildException("FPD File " + fpdFilePath + " does not exist!");
389 }
390 }
391
392 /**
393 Test case function
394
395 @param argv parameter from command line
396 **/
397 public static void main(String argv[]) throws PlatformPcdPreprocessBuildException {
398 PlatformPcdPreprocessActionForBuilding ca = new PlatformPcdPreprocessActionForBuilding();
399 String projectDir = "x:/edk2";
400 ca.setFPDFilePath(projectDir + "/EdkNt32Pkg/Nt32.fpd");
401 ca.setActionMessageLevel(ActionMessage.MAX_MESSAGE_LEVEL);
402 GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db",
403 projectDir,
404 "tools_def.txt");
405 System.out.println("After initInfo!");
406 FpdParserTask fpt = new FpdParserTask();
407 fpt.parseFpdFile(new File(projectDir + "/EdkNt32Pkg/Nt32.fpd"));
408 ca.execute();
409 }
410 }