Refine the code for PCD tools.
[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.util.ArrayList;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.xmlbeans.XmlException;
28 import org.apache.xmlbeans.XmlObject;
29 import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions;
30 import org.tianocore.PcdBuildDefinitionDocument;
31 import org.tianocore.PlatformSurfaceAreaDocument;
32 import org.tianocore.build.exception.PlatformPcdPreprocessBuildException;
33 import org.tianocore.build.fpd.FpdParserTask;
34 import org.tianocore.build.global.GlobalData;
35 import org.tianocore.build.id.FpdModuleIdentification;
36 import org.tianocore.pcd.action.ActionMessage;
37 import org.tianocore.pcd.action.PlatformPcdPreprocessAction;
38 import org.tianocore.pcd.entity.MemoryDatabaseManager;
39 import org.tianocore.pcd.entity.ModulePcdInfoFromFpd;
40 import org.tianocore.pcd.entity.Token;
41 import org.tianocore.pcd.entity.UsageIdentification;
42 import org.tianocore.pcd.exception.EntityException;
43 import org.tianocore.pcd.exception.PlatformPcdPreprocessException;
44
45 /**
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.
49 **/
50 public class PlatformPcdPreprocessActionForBuilding extends PlatformPcdPreprocessAction {
51 ///
52 /// FPD file path.
53 ///
54 private String fpdFilePath;
55
56 ///
57 /// Message level for CollectPCDAction.
58 ///
59 private int originalMessageLevel;
60
61 ///
62 /// Cache the fpd docment instance for private usage.
63 ///
64 private PlatformSurfaceAreaDocument fpdDocInstance;
65
66 /**
67 Set action message level for CollectPcdAction tool.
68
69 The message should be restored when this action exit.
70
71 @param actionMessageLevel parameter for this action
72 **/
73 public void setActionMessageLevel(int actionMessageLevel) {
74 originalMessageLevel = ActionMessage.messageLevel;
75 ActionMessage.messageLevel = actionMessageLevel;
76 }
77
78 /**
79 Set FPDFileName parameter for this action class.
80
81 @param fpdFilePath fpd file path
82 **/
83 public void setFPDFilePath(String fpdFilePath) {
84 this.fpdFilePath = fpdFilePath;
85 }
86
87 /**
88 Common function interface for outer.
89
90 @param fpdFilePath The fpd file path of current build or processing.
91 @param messageLevel The message level for this Action.
92
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.
96
97 **/
98 public void perform(String fpdFilePath, int messageLevel)
99 throws PlatformPcdPreprocessBuildException {
100 this.fpdFilePath = fpdFilePath;
101 setActionMessageLevel(messageLevel);
102 checkParameter();
103 execute();
104 ActionMessage.messageLevel = originalMessageLevel;
105 }
106
107 /**
108 Core execution function for this action class.
109
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.
117
118
119 @throws EntityException Exception indicate failed to execute this action.
120
121 **/
122 public void execute() throws PlatformPcdPreprocessBuildException {
123 String errorMessageHeader = "Failed to initialize the Pcd memory database because: ";
124 String errorsForPreprocess = null;
125
126 //
127 // Get memoryDatabaseManager instance from GlobalData.
128 // The memoryDatabaseManager should be initialized as static variable
129 // in some Pre-process class.
130 //
131 setPcdDbManager(GlobalData.getPCDMemoryDBManager());
132
133 //
134 // Collect all PCD information defined in FPD file.
135 // Evenry token defind in FPD will be created as an token into
136 // memory database.
137 //
138 try {
139 initPcdMemoryDbWithPlatformInfo();
140 } catch (PlatformPcdPreprocessException exp) {
141 throw new PlatformPcdPreprocessBuildException(errorMessageHeader + exp.getMessage());
142 }
143 errorsForPreprocess = this.getErrorString();
144 if (errorsForPreprocess != null) {
145 throw new PlatformPcdPreprocessBuildException(errorMessageHeader + "\r\n" + errorsForPreprocess);
146 }
147
148 //
149 // Generate for PEI, DXE PCD DATABASE's definition and initialization.
150 //
151 try {
152 genPcdDatabaseSourceCode ();
153 } catch (EntityException exp) {
154 throw new PlatformPcdPreprocessBuildException(errorMessageHeader + "\r\n" + exp.getMessage());
155 }
156 }
157
158 /**
159 Override function: implementate the method of get Guid string information from SPD file.
160
161 @param guidCName Guid CName string.
162
163 @return String Guid information from SPD file.
164 @throws PlatformPcdPreprocessException
165 Fail to get Guid information from SPD file.
166 **/
167 public String getGuidInfoFromSpd(String guidCName) throws PlatformPcdPreprocessException {
168 String tokenSpaceStrRet = null;
169 try {
170 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(guidCName);
171 } catch ( Exception e ) {
172 throw new PlatformPcdPreprocessException ("Failed to get Guid CName " + guidCName + " from the SPD file!");
173 }
174 return tokenSpaceStrRet;
175 }
176
177 /**
178 This function generates source code for PCD Database.
179
180 @throws EntityException If the token does *not* exist in memory database.
181
182 **/
183 private void genPcdDatabaseSourceCode()
184 throws EntityException {
185 String PcdCommonHeaderString = PcdDatabase.getPcdDatabaseCommonDefinitions();
186
187 ArrayList<Token> alPei = new ArrayList<Token> ();
188 ArrayList<Token> alDxe = new ArrayList<Token> ();
189
190 getPcdDbManager().getTwoPhaseDynamicRecordArray(alPei, alDxe);
191 PcdDatabase pcdPeiDatabase = new PcdDatabase (alPei, "PEI", 0);
192 pcdPeiDatabase.genCode();
193 MemoryDatabaseManager.PcdPeimHString = PcdCommonHeaderString + pcdPeiDatabase.getHString() +
194 PcdDatabase.getPcdPeiDatabaseDefinitions();
195 MemoryDatabaseManager.PcdPeimCString = pcdPeiDatabase.getCString();
196
197 PcdDatabase pcdDxeDatabase = new PcdDatabase(alDxe, "DXE", alPei.size());
198 pcdDxeDatabase.genCode();
199 MemoryDatabaseManager.PcdDxeHString = MemoryDatabaseManager.PcdPeimHString + pcdDxeDatabase.getHString() +
200 PcdDatabase.getPcdDxeDatabaseDefinitions();
201 MemoryDatabaseManager.PcdDxeCString = pcdDxeDatabase.getCString();
202 }
203
204 /**
205 Override function: Get component array from FPD.
206
207 This function maybe provided by some Global class.
208
209 @return List<ModuleInfo> the component array.
210 @throws PlatformPcdPreprocessException get all modules in <ModuleSA> in FPD file.
211
212 **/
213 public List<ModulePcdInfoFromFpd> getComponentsFromFpd()
214 throws PlatformPcdPreprocessException {
215 List<ModulePcdInfoFromFpd> allModules = new ArrayList<ModulePcdInfoFromFpd>();
216 Map<FpdModuleIdentification, XmlObject> pcdBuildDefinitions = null;
217 UsageIdentification usageId = null;
218
219 pcdBuildDefinitions = GlobalData.getFpdPcdBuildDefinitions();
220 if (pcdBuildDefinitions == null) {
221 return null;
222 }
223
224 //
225 // Loop map to retrieve all PCD build definition and Module id
226 //
227 Iterator item = pcdBuildDefinitions.keySet().iterator();
228 while (item.hasNext()){
229 FpdModuleIdentification id = (FpdModuleIdentification) item.next();
230 usageId = new UsageIdentification(id.getModule().getName(),
231 id.getModule().getGuid(),
232 id.getModule().getPackage().getName(),
233 id.getModule().getPackage().getGuid(),
234 id.getArch(),
235 id.getModule().getVersion(),
236 id.getModule().getModuleType());
237 allModules.add(
238 new ModulePcdInfoFromFpd(
239 usageId,
240 ((PcdBuildDefinitionDocument)pcdBuildDefinitions.get(id)).getPcdBuildDefinition()));
241 }
242 return allModules;
243 }
244
245 /**
246 Override function: Verify the datum value according its datum size and datum type, this
247 function maybe moved to FPD verification tools in future.
248
249 @param cName The token name
250 @param moduleName The module who use this PCD token
251 @param datum The PCD's datum
252 @param datumType The PCD's datum type
253 @param maxDatumSize The max size for PCD's Datum.
254
255 @return String exception strings.
256 */
257 public String verifyDatum(String cName,
258 String moduleName,
259 String datum,
260 Token.DATUM_TYPE datumType,
261 int maxDatumSize) {
262 //
263 // In building system, datum should not be checked, the checking work
264 // should be done by wizard tools or PCD verification tools.
265 //
266 return null;
267 }
268
269 /**
270 Override function: Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.
271
272 This function should be implemented in GlobalData in future.
273
274 @param token The token instance which has hold module's PCD information
275 @param moduleName The name of module who will use this Dynamic PCD.
276
277 @return DynamicPcdBuildDefinitions.PcdBuildData
278 **/
279 public DynamicPcdBuildDefinitions.PcdBuildData getDynamicInfoFromFpd(Token token,
280 String moduleName)
281 throws PlatformPcdPreprocessException {
282 int index = 0;
283 String exceptionString = null;
284 String dynamicPrimaryKey = null;
285 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null;
286 List<DynamicPcdBuildDefinitions.PcdBuildData> dynamicPcdBuildDataArray = null;
287 String tokenSpaceStrRet = null;
288
289 //
290 // If FPD document is not be opened, open and initialize it.
291 // BUGBUG: The code should be moved into GlobalData in future.
292 //
293 if (fpdDocInstance == null) {
294 try {
295 fpdDocInstance = (PlatformSurfaceAreaDocument)XmlObject.Factory.parse(new File(fpdFilePath));
296 } catch(IOException ioE) {
297 throw new PlatformPcdPreprocessException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage());
298 } catch(XmlException xmlE) {
299 throw new PlatformPcdPreprocessException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage());
300 }
301 }
302
303 dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
304 if (dynamicPcdBuildDefinitions == null) {
305 exceptionString = String.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> elements in FPD file but there are Dynamic type "+
306 "PCD entries %s in module %s!",
307 token.cName,
308 moduleName);
309 putError(exceptionString);
310 return null;
311 }
312
313 dynamicPcdBuildDataArray = dynamicPcdBuildDefinitions.getPcdBuildDataList();
314 for (index = 0; index < dynamicPcdBuildDataArray.size(); index ++) {
315 tokenSpaceStrRet = getGuidInfoFromSpd(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName());
316
317 if (tokenSpaceStrRet == null) {
318 exceptionString = "Fail to get token space guid for token " + dynamicPcdBuildDataArray.get(index).getCName();
319 putError(exceptionString);
320 continue;
321 }
322
323 dynamicPrimaryKey = Token.getPrimaryKeyString(dynamicPcdBuildDataArray.get(index).getCName(),
324 tokenSpaceStrRet);
325 if (dynamicPrimaryKey.equals(token.getPrimaryKeyString())) {
326 return dynamicPcdBuildDataArray.get(index);
327 }
328 }
329
330 return null;
331 }
332
333 /**
334 Override function: get all <DynamicPcdBuildDefinition> from FPD file.
335
336 @return List<DynamicPcdBuildDefinitions.PcdBuildData> All DYNAMIC PCD list in <DynamicPcdBuildDefinitions> in FPD file.
337 @throws PlatformPcdPreprocessBuildException Failure to get dynamic information list.
338
339 **/
340 public List<DynamicPcdBuildDefinitions.PcdBuildData>
341 getAllDynamicPcdInfoFromFpd()
342 throws PlatformPcdPreprocessException {
343 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null;
344
345 //
346 // Open fpd document to get <DynamicPcdBuildDefinition> Section.
347 // BUGBUG: the function should be move GlobalData in furture.
348 //
349 if (fpdDocInstance == null) {
350 try {
351 fpdDocInstance = (PlatformSurfaceAreaDocument)XmlObject.Factory.parse(new File(fpdFilePath));
352 } catch(IOException ioE) {
353 throw new PlatformPcdPreprocessException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage());
354 } catch(XmlException xmlE) {
355 throw new PlatformPcdPreprocessException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage());
356 }
357 }
358
359 dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
360 if (dynamicPcdBuildDefinitions == null) {
361 return null;
362 }
363
364 return dynamicPcdBuildDefinitions.getPcdBuildDataList();
365 }
366
367 /**
368 check parameter for this action.
369
370 @throws PlatformPcdPreprocessBuildException Bad parameter.
371 **/
372 private void checkParameter() throws PlatformPcdPreprocessBuildException {
373 File file = null;
374
375 if (fpdFilePath == null) {
376 throw new PlatformPcdPreprocessBuildException("FPDFileName should be empty for CollectPCDAtion!");
377 }
378
379 if (fpdFilePath.length() == 0) {
380 throw new PlatformPcdPreprocessBuildException("FPDFileName should be empty for CollectPCDAtion!");
381 }
382
383 file = new File(fpdFilePath);
384
385 if(!file.exists()) {
386 throw new PlatformPcdPreprocessBuildException("FPD File " + fpdFilePath + " does not exist!");
387 }
388 }
389 }