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