Refine the code for PCD tools.
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / pcd / action / PCDAutoGenAction.java
1 /** @file
2 PCDAutoGenAction class.
3
4 This class is to manage how to generate the PCD information into Autogen.c and
5 Autogen.h.
6
7 Copyright (c) 2006, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
12
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.
15
16 **/
17 package org.tianocore.build.pcd.action;
18
19 import java.io.File;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.regex.Matcher;
23 import java.util.regex.Pattern;
24
25 import org.tianocore.build.autogen.CommonDefinition;
26 import org.tianocore.build.exception.PcdAutogenException;
27 import org.tianocore.build.global.GlobalData;
28 import org.tianocore.build.id.ModuleIdentification;
29 import org.tianocore.pcd.action.ActionMessage;
30 import org.tianocore.pcd.action.BuildAction;
31 import org.tianocore.pcd.entity.MemoryDatabaseManager;
32 import org.tianocore.pcd.entity.Token;
33 import org.tianocore.pcd.entity.UsageIdentification;
34 import org.tianocore.pcd.entity.UsageInstance;
35 import org.tianocore.pcd.exception.BuildActionException;
36
37 /**
38 This class is to manage how to generate the PCD information into Autogen.c
39 and Autogen.h.
40 **/
41 public class PCDAutoGenAction extends BuildAction {
42 ///
43 /// The reference of DBManager in GlobalData class.
44 ///
45 private MemoryDatabaseManager dbManager;
46
47 ///
48 /// The identification for a UsageInstance.
49 ///
50 private UsageIdentification usageId;
51
52 ///
53 /// Whether current autogen is for building library used by current module.
54 ///
55 private boolean isBuildUsedLibrary;
56
57 ///
58 /// One of PEI_PCD_DRIVER, DXE_PCD_DRIVER, NOT_PCD_DRIVER
59 ///
60 private CommonDefinition.PCD_DRIVER_TYPE pcdDriverType;
61
62 ///
63 /// The generated string for header file.
64 ///
65 private String hAutoGenString;
66
67 ///
68 /// The generated string for C code file.
69 ///
70 private String cAutoGenString;
71
72 ///
73 /// The name array of <PcdCoded> in a module.
74 ///
75 private String[] pcdNameArrayInMsa;
76
77 /**
78 Set parameter moduleId
79
80 @param moduleName the module name parameter.
81 **/
82 public void setUsageId(UsageIdentification usageId) {
83 this.usageId = usageId;
84 }
85
86 /**
87 Set paramter pcdDriverType
88
89 @param pcdDriverType the driver type for PCD
90 **/
91 public void setPcdDriverType(CommonDefinition.PCD_DRIVER_TYPE pcdDriverType) {
92 this.pcdDriverType = pcdDriverType;
93 }
94 /**
95 set isBuildUsedLibrary parameter.
96
97 @param isBuildUsedLibrary
98 **/
99 public void setIsBuildUsedLibrary(boolean isBuildUsedLibrary) {
100 this.isBuildUsedLibrary = isBuildUsedLibrary;
101 }
102
103 /**
104 set pcdNameArrayInMsa parameter.
105
106 @param pcdNameArrayInMsa
107 */
108 public void setPcdNameArrayInMsa(String[] pcdNameArrayInMsa) {
109 this.pcdNameArrayInMsa = pcdNameArrayInMsa;
110 }
111
112 /**
113 Get the output of generated string for header file.
114
115 @return the string of header file for PCD
116 **/
117 public String getHAutoGenString() {
118 return hAutoGenString;
119 }
120
121 /**
122 Get the output of generated string for C Code file.
123
124 @return the string of C code file for PCD
125 **/
126 public String getCAutoGenString() {
127 return cAutoGenString;
128 }
129
130
131 /**
132 Construct function
133
134 This function mainly initialize some member variable.
135
136 @param moduleId the identification for module
137 @param arch the architecture for module
138 @param isBuildUsedLibary Is the current module library.
139 @param pcdNameArrayInMsa the pcd name array got from MSA file.
140 @param pcdDriverType one of PEI_PCD_DRIVER, DXE_PCD_DRIVER,
141 NOT_PCD_DRIVER
142 **/
143 public PCDAutoGenAction(ModuleIdentification moduleId,
144 String arch,
145 boolean isBuildUsedLibrary,
146 String[] pcdNameArrayInMsa,
147 CommonDefinition.PCD_DRIVER_TYPE pcdDriverType) {
148 dbManager = null;
149 hAutoGenString = "";
150 cAutoGenString = "";
151
152 setUsageId(new UsageIdentification(moduleId.getName(),
153 moduleId.getGuid(),
154 moduleId.getPackage().getName(),
155 moduleId.getPackage().getGuid(),
156 arch,
157 moduleId.getVersion(),
158 moduleId.getModuleType()));
159 setIsBuildUsedLibrary(isBuildUsedLibrary);
160 setPcdNameArrayInMsa(pcdNameArrayInMsa);
161 setPcdDriverType(pcdDriverType);
162 }
163
164 /**
165 Override function: check the parameter for action class.
166
167 @throws BuildActionException Bad parameter.
168 **/
169 public void checkParameter() {
170 }
171
172 /**
173 Core execution function for this action class.
174
175 All PCD information of this module comes from memory dabase. The collection
176 work should be done before this action execution.
177 Currently, we should generated all PCD information(maybe all dynamic) as array
178 in Pei emulated driver for simulating PCD runtime database.
179
180 @throws BuildActionException Failed to execute this aciton class.
181 **/
182 public void performAction() {
183 ActionMessage.debug(this,
184 "Starting PCDAutoGenAction to generate autogen.h and autogen.c!...");
185
186 dbManager = GlobalData.getPCDMemoryDBManager();
187
188 if(dbManager.getDBSize() == 0) {
189 return;
190 }
191
192 ActionMessage.debug(this,
193 "PCD memory database contains " + dbManager.getDBSize() + " PCD tokens.");
194
195 generateAutogenForModule();
196 }
197
198 /**
199 Generate the autogen string for a common module.
200
201 All PCD information of this module comes from memory dabase. The collection
202 work should be done before this action execution.
203 **/
204 private void generateAutogenForModule()
205 {
206 int index, index2;
207 List<UsageInstance> usageInstanceArray, usageContext;
208 String[] guidStringArray = null;
209 String guidStringCName = null;
210 String guidString = null;
211 String moduleName = usageId.moduleName;
212 UsageInstance usageInstance = null;
213 boolean found = false;
214
215 usageInstanceArray = null;
216 if (!isBuildUsedLibrary) {
217 usageInstanceArray = dbManager.getUsageInstanceArrayById(usageId);
218 MemoryDatabaseManager.UsageInstanceContext = usageInstanceArray;
219 MemoryDatabaseManager.CurrentModuleName = moduleName;
220 } else if ((pcdNameArrayInMsa != null) && (pcdNameArrayInMsa.length > 0)) {
221 usageContext = MemoryDatabaseManager.UsageInstanceContext;
222 //
223 // For building library package, although all module are library, but PCD entries of
224 // these library should be used to autogen.
225 //
226 if (usageContext == null) {
227 usageInstanceArray = dbManager.getUsageInstanceArrayById(usageId);
228 } else {
229 usageInstanceArray = new ArrayList<UsageInstance>();
230
231 //
232 // Try to find all PCD defined in library's PCD in all <PcdEntry> in module's
233 // <ModuleSA> in FPD file.
234 //
235 for (index = 0; index < pcdNameArrayInMsa.length; index++) {
236 found = false;
237 for (index2 = 0; index2 < usageContext.size(); index2 ++) {
238 if (pcdNameArrayInMsa[index].equalsIgnoreCase(usageContext.get(index2).parentToken.cName)) {
239 usageInstanceArray.add(usageContext.get(index2));
240 found = true;
241 break;
242 }
243 }
244
245 if (!found) {
246 //
247 // All library's PCD should instanted in module's <ModuleSA> who
248 // use this library instance. If not, give errors.
249 //
250 throw new BuildActionException (String.format("Module %s using library instance %s; the PCD %s " +
251 "is required by this library instance, but can not be found " +
252 "in the %s's <ModuleSA> in the FPD file!",
253 MemoryDatabaseManager.CurrentModuleName,
254 moduleName,
255 pcdNameArrayInMsa[index],
256 MemoryDatabaseManager.CurrentModuleName
257 ));
258 }
259 }
260 }
261 }
262
263 if (usageInstanceArray == null) {
264 return;
265 }
266
267 //
268 // Generate all PCD entry for a module.
269 //
270 for(index = 0; index < usageInstanceArray.size(); index ++) {
271 usageInstance = usageInstanceArray.get(index);
272 //
273 // Before generate any PCD information into autogen.h/autogen.c for a module,
274 // generate TokenSpaceGuid array variable firstly. For every dynamicEx type
275 // PCD in this module the token, they are all reference to TokenSpaceGuid
276 // array.
277 //
278 if (usageInstanceArray.get(index).modulePcdType == Token.PCD_TYPE.DYNAMIC_EX) {
279 guidStringArray = usageInstance.parentToken.tokenSpaceName.split("-");
280 guidStringCName = "_gPcd_TokenSpaceGuid_" +
281 usageInstance.parentToken.tokenSpaceName.replaceAll("-", "_");
282 guidString = String.format("{ 0x%s, 0x%s, 0x%s, {0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s}}",
283 guidStringArray[0],
284 guidStringArray[1],
285 guidStringArray[2],
286 (guidStringArray[3].substring(0, 2)),
287 (guidStringArray[3].substring(2, 4)),
288 (guidStringArray[4].substring(0, 2)),
289 (guidStringArray[4].substring(2, 4)),
290 (guidStringArray[4].substring(4, 6)),
291 (guidStringArray[4].substring(6, 8)),
292 (guidStringArray[4].substring(8, 10)),
293 (guidStringArray[4].substring(10, 12)));
294
295 Pattern pattern = Pattern.compile("(" + guidStringCName + ")+?");
296 Matcher matcher = pattern.matcher(cAutoGenString + " ");
297 //
298 // Find whether this guid array variable has been generated into autogen.c
299 // For different DyanmicEx pcd token who use same token space guid, the token space
300 // guid array should be only generated once.
301 //
302 if (!matcher.find()) {
303 hAutoGenString += String.format("extern EFI_GUID %s;\r\n", guidStringCName);
304 if (!isBuildUsedLibrary) {
305 cAutoGenString += String.format("GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID %s = %s;\r\n",
306 guidStringCName,
307 guidString);
308 }
309 }
310 }
311
312 usageInstance.generateAutoGen(isBuildUsedLibrary);
313 //
314 // For every PCD entry for this module(usage instance), autogen string would
315 // be appand.
316 //
317 hAutoGenString += usageInstance.getHAutogenStr() + "\r\n";
318 cAutoGenString += usageInstance.getCAutogenStr();
319 }
320
321 if (pcdDriverType == CommonDefinition.PCD_DRIVER_TYPE.PEI_PCD_DRIVER) {
322 hAutoGenString += MemoryDatabaseManager.PcdPeimHString;
323 cAutoGenString += MemoryDatabaseManager.PcdPeimCString;
324 } else if (pcdDriverType == CommonDefinition.PCD_DRIVER_TYPE.DXE_PCD_DRIVER) {
325 hAutoGenString += MemoryDatabaseManager.PcdDxeHString;
326 cAutoGenString += MemoryDatabaseManager.PcdDxeCString;
327 }
328 }
329 }