Refine the code for PCD tools.
[mirror_edk2.git] / Tools / Source / PcdTools / org / tianocore / pcd / action / PlatformPcdPreprocessAction.java
CommitLineData
bc262841 1/** @file\r
2 PlatformPcdPreprocessAction class.\r
3\r
4 The abstract parent class PlatformPcdPreprocessAction, This class is to collect platform's\r
5 pcd build information from fpd file.\r
6 This class will be extended by building tools and wizard tools.\r
7\r
8Copyright (c) 2006, Intel Corporation\r
9All rights reserved. This program and the accompanying materials\r
10are licensed and made available under the terms and conditions of the BSD License\r
11which accompanies this distribution. The full text of the license may be found at\r
12http://opensource.org/licenses/bsd-license.php\r
13\r
14THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
15WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
16\r
17**/\r
18package org.tianocore.pcd.action;\r
19\r
20import java.util.ArrayList;\r
21import java.util.List;\r
22import java.util.UUID;\r
23import java.util.regex.Matcher;\r
24import java.util.regex.Pattern;\r
25\r
26import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions;\r
27import org.tianocore.PcdBuildDefinitionDocument.PcdBuildDefinition;\r
bc262841 28import org.tianocore.pcd.entity.*;\r
29import org.tianocore.pcd.entity.Token;\r
8b7bd455 30import org.tianocore.pcd.entity.MemoryDatabaseManager;\r
31import org.tianocore.pcd.exception.PlatformPcdPreprocessException;\r
bc262841 32\r
33/**\r
34 The abstract parent class PlatformPcdPreprocessAction, This class is to collect platform's\r
35 pcd build information from fpd file.\r
36 This class will be extended by building tools and wizard tools.\r
37\r
38**/\r
39public abstract class PlatformPcdPreprocessAction {\r
40 ///\r
41 /// PCD memory database\r
42 ///\r
43 private MemoryDatabaseManager pcdDbManager;\r
44\r
e55d8a3c 45 ///\r
46 /// Errors string when perform preprocess \r
47 /// \r
48 private String errorString;\r
49\r
50 ///\r
51 /// the count of errors when perform preprocess\r
52 /// \r
53 private int errorCount;\r
54\r
55 /**\r
56 Default contructor function \r
57 **/\r
58 public PlatformPcdPreprocessAction() {\r
59 pcdDbManager = null;\r
60 errorString = null;\r
11eb278a 61 errorCount = 0;\r
e55d8a3c 62 }\r
63\r
bc262841 64 /**\r
65 Set parameter pcdDbManager\r
66\r
67 @param pcdDbManager\r
68 **/\r
69 public void setPcdDbManager(MemoryDatabaseManager pcdDbManager) {\r
70 this.pcdDbManager = pcdDbManager;\r
71 }\r
72\r
73 /**\r
74 Get parameter pcdDbManager\r
8b7bd455 75\r
bc262841 76 @return MemoryDatabaseManager\r
77 **/\r
78 public MemoryDatabaseManager getPcdDbManager() {\r
79 return pcdDbManager;\r
80 }\r
11eb278a 81\r
bc262841 82 /**\r
83 Abstract function: retrieve module information from FPD file.\r
84\r
85 In building environement, this function will be implementated by FpdParserTask.\r
86\r
11eb278a 87 @return List<ModulePcdInfoFromFpd> the component array.\r
8b7bd455 88 @throws PlatformPcdPreprocessException get all modules in <ModuleSA> in FPD file.\r
89\r
bc262841 90 **/\r
91 public abstract List<ModulePcdInfoFromFpd> getComponentsFromFpd()\r
8b7bd455 92 throws PlatformPcdPreprocessException;\r
bc262841 93\r
94 /**\r
95 Abstract function to get GUID string from SPD file.\r
96\r
97 In building evnironment, this function will be implementated by GlobaData.\r
98\r
99 @param guidCName the CName of GUID\r
100\r
20c5c53f 101 @return String Guid information from SPD file.\r
8b7bd455 102 @throws PlatformPcdPreprocessException\r
103 Fail to get Guid information from SPD file.\r
bc262841 104 **/\r
11eb278a 105 public abstract String getGuidInfoFromSpd(String guidCName) throws PlatformPcdPreprocessException;\r
bc262841 106\r
107 /**\r
108 Abstract function: Verification the PCD data.\r
109\r
110 In different environment, such as building environment and wizard environment,\r
111 it has different implementation according to optimization.\r
112\r
8b7bd455 113 @param cName The token name\r
114 @param moduleName The module who use this PCD token\r
115 @param datum The PCD's datum\r
116 @param datumType The PCD's datum type\r
117 @param maxDatumSize The max size for PCD's Datum.\r
118\r
119 @return String exception strings.\r
bc262841 120\r
bc262841 121 **/\r
11eb278a 122 public abstract String verifyDatum(String cName, String moduleName, String datum,\r
123 Token.DATUM_TYPE datumType, int maxDatumSize);\r
bc262841 124\r
125 /**\r
126 Abstract function: Get dynamic information for a token\r
127\r
128 @param token\r
129 @param moduleName\r
130\r
131 @return DynamicPcdBuildDefinitions.PcdBuildData\r
132 **/\r
133 public abstract DynamicPcdBuildDefinitions.PcdBuildData\r
134 getDynamicInfoFromFpd(Token token,\r
135 String moduleName)\r
8b7bd455 136 throws PlatformPcdPreprocessException;\r
bc262841 137\r
138 /**\r
139 Abstract function: Get all dynamic PCD information from FPD file.\r
140\r
8b7bd455 141 @return List<DynamicPcdBuildDefinitions.PcdBuildData> All DYNAMIC PCD list in <DynamicPcdBuildDefinitions> in FPD file.\r
142 @throws PlatformPcdPreprocessBuildException Failure to get dynamic information list.\r
143\r
bc262841 144 **/\r
145 public abstract List<DynamicPcdBuildDefinitions.PcdBuildData>\r
146 getAllDynamicPcdInfoFromFpd()\r
8b7bd455 147 throws PlatformPcdPreprocessException;\r
bc262841 148\r
e55d8a3c 149 /**\r
150 Return the error string after preprocess \r
151\r
152 @return String error string\r
153 **/\r
154 public String getErrorString() {\r
155 return errorString;\r
156 }\r
157\r
158 public void putError(String error) {\r
159 if (errorString == null) {\r
b6297711 160 errorString = "### ERROR[" + errorCount + "] ###\r\n" + error + "\r\n";\r
e55d8a3c 161 } else {\r
b6297711 162 errorString += "### ERROR[" + errorCount + "] ###\r\n" + error + "\r\n";\r
e55d8a3c 163 }\r
164\r
165 errorCount++;\r
166 }\r
167\r
bc262841 168 /**\r
169 Collect all PCD information from FPD file into PCD memory database.\r
170\r
171 **/\r
172 public void initPcdMemoryDbWithPlatformInfo()\r
8b7bd455 173 throws PlatformPcdPreprocessException {\r
11eb278a 174 int index;\r
175 int pcdIndex;\r
bc262841 176 List<PcdBuildDefinition.PcdData> pcdBuildDataArray = new ArrayList<PcdBuildDefinition.PcdData>();\r
11eb278a 177 PcdBuildDefinition.PcdData pcdBuildData;\r
bc262841 178 Token token = null;\r
11eb278a 179 List<ModulePcdInfoFromFpd> modules;\r
180 String primaryKey;\r
181 String exceptionString;\r
182 UsageInstance usageInstance;\r
bc262841 183 Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN;\r
184 Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN;\r
11eb278a 185 long tokenNumber;\r
186 String moduleName;\r
187 String datum;\r
188 int maxDatumSize;\r
189 String tokenSpaceStrRet;\r
190 ModulePcdInfoFromFpd curModule;\r
bc262841 191\r
192 //\r
193 // ----------------------------------------------\r
194 // 1), Get all <ModuleSA> from FPD file.\r
195 // ----------------------------------------------\r
196 //\r
197 modules = getComponentsFromFpd();\r
198\r
199 if (modules == null) {\r
8b7bd455 200 throw new PlatformPcdPreprocessException(\r
d653c17a 201 "No modules found in the FPD file.\nPlease check whether there are elements in <FrameworkModules> in the FPD file!");\r
bc262841 202 }\r
203\r
204 //\r
205 // -------------------------------------------------------------------\r
206 // 2), Loop all modules to process <PcdBuildDeclarations> for each module.\r
207 // -------------------------------------------------------------------\r
208 //\r
f28c0830 209 for (index = 0; index < modules.size(); index++) {\r
11eb278a 210 curModule = modules.get(index);\r
211\r
212 //\r
bc262841 213 // It is legal for a module does not contains ANY pcd build definitions.\r
214 //\r
11eb278a 215 if (curModule.pcdBuildDefinition == null) {\r
bc262841 216 continue;\r
217 }\r
218\r
11eb278a 219 pcdBuildDataArray = curModule.pcdBuildDefinition.getPcdDataList();\r
220 moduleName = curModule.usageId.moduleName;\r
bc262841 221\r
222 //\r
223 // ----------------------------------------------------------------------\r
224 // 2.1), Loop all Pcd entry for a module and add it into memory database.\r
225 // ----------------------------------------------------------------------\r
226 //\r
f28c0830 227 for (pcdIndex = 0; pcdIndex < pcdBuildDataArray.size(); pcdIndex++) {\r
bc262841 228 pcdBuildData = pcdBuildDataArray.get(pcdIndex);\r
229\r
230 tokenSpaceStrRet = getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName());\r
231\r
232 if (tokenSpaceStrRet == null) {\r
d653c17a 233 putError("Failed to get Token Space Guid for token " + pcdBuildData.getCName() +\r
234 " from any SPD file. You must have an <GuidDeclaration> for this Token Space Guid!");\r
e55d8a3c 235 //\r
236 // Do not break preprocess, continues to analysis.\r
237 // All errors will be summary to be shown.\r
238 // \r
239 continue;\r
bc262841 240 }\r
241\r
20c5c53f 242 primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(), tokenSpaceStrRet);\r
f28c0830 243 pcdType = Token.getPcdTypeFromString(pcdBuildData.getItemType().toString());\r
bc262841 244 datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString());\r
245 tokenNumber = Long.decode(pcdBuildData.getToken().toString());\r
246 if (pcdBuildData.getValue() != null) {\r
247 datum = pcdBuildData.getValue().toString();\r
248 } else {\r
249 datum = null;\r
250 }\r
251 maxDatumSize = pcdBuildData.getMaxDatumSize();\r
252\r
253 if ((pcdType == Token.PCD_TYPE.FEATURE_FLAG) &&\r
254 (datumType != Token.DATUM_TYPE.BOOLEAN)){\r
d653c17a 255 exceptionString = String.format("In FPD file, for PCD %s in module %s, the PCD type is FEATURE_FLAG but "+\r
256 "datum type for this PCD entry is not BOOLEAN!",\r
bc262841 257 pcdBuildData.getCName(),\r
258 moduleName);\r
e55d8a3c 259 putError(exceptionString);\r
260 //\r
261 // Do not break preprocess, continues to analysis.\r
262 // All errors will be summary to be shown.\r
263 // \r
264 continue;\r
bc262841 265 }\r
266\r
267 //\r
268 // -------------------------------------------------------------------------------------------\r
269 // 2.1.1), Do some necessary checking work for FixedAtBuild, FeatureFlag and PatchableInModule\r
270 // -------------------------------------------------------------------------------------------\r
271 //\r
272 if (!Token.isDynamic(pcdType)) {\r
273 //\r
274 // Value is required.\r
275 //\r
276 if (datum == null) {\r
d653c17a 277 exceptionString = String.format("In the FPD file, there is no value for PCD entry %s in module %s!",\r
bc262841 278 pcdBuildData.getCName(),\r
279 moduleName);\r
e55d8a3c 280 putError(exceptionString);\r
281 //\r
282 // Do not break preprocess, continues to analysis.\r
283 // All errors will be summary to be shown.\r
284 // \r
285 continue;\r
bc262841 286 }\r
287\r
288 //\r
289 // Check whether the datum size is matched datum type.\r
290 //\r
291 if ((exceptionString = verifyDatum(pcdBuildData.getCName(),\r
292 moduleName,\r
293 datum,\r
294 datumType,\r
295 maxDatumSize)) != null) {\r
e55d8a3c 296 putError(exceptionString);\r
297 //\r
298 // Do not break preprocess, continues to analysis.\r
299 // All errors will be summary to be shown.\r
300 // \r
301 continue;\r
bc262841 302 }\r
303 }\r
304\r
305 //\r
306 // ---------------------------------------------------------------------------------\r
307 // 2.1.2), Create token or update token information for current anaylized PCD data.\r
308 // ---------------------------------------------------------------------------------\r
309 //\r
310 if (pcdDbManager.isTokenInDatabase(primaryKey)) {\r
311 //\r
312 // If the token is already exist in database, do some necessary checking\r
313 // and add a usage instance into this token in database\r
314 //\r
315 token = pcdDbManager.getTokenByKey(primaryKey);\r
316\r
317 //\r
318 // checking for DatumType, DatumType should be unique for one PCD used in different\r
319 // modules.\r
320 //\r
321 if (token.datumType != datumType) {\r
d653c17a 322 exceptionString = String.format("In the FPD file, the datum type of the PCD entry %s is %s, which is different from %s which was previously defined!",\r
bc262841 323 pcdBuildData.getCName(),\r
324 pcdBuildData.getDatumType().toString(),\r
325 Token.getStringOfdatumType(token.datumType));\r
e55d8a3c 326 putError(exceptionString);\r
327 //\r
328 // Do not break preprocess, continues to analysis.\r
329 // All errors will be summary to be shown.\r
330 // \r
331 continue;\r
bc262841 332 }\r
333\r
334 //\r
335 // Check token number is valid\r
336 //\r
337 if (tokenNumber != token.tokenNumber) {\r
d653c17a 338 exceptionString = String.format("In the FPD file, the token number of PCD entry %s in module %s is different from the same PCD entry in other modules!",\r
bc262841 339 pcdBuildData.getCName(),\r
340 moduleName);\r
e55d8a3c 341 putError(exceptionString);\r
342 //\r
343 // Do not break preprocess, continues to analysis.\r
344 // All errors will be summary to be shown.\r
345 // \r
346 continue;\r
bc262841 347 }\r
348\r
349 //\r
350 // For same PCD used in different modules, the PCD type should all be dynamic or non-dynamic.\r
351 //\r
352 if (token.isDynamicPCD != Token.isDynamic(pcdType)) {\r
d653c17a 353 exceptionString = String.format("In the FPD file, for PCD entry %s in module %s, you defined dynamic or non-dynamic PCD type which"+\r
354 " is different from other module's definition.",\r
bc262841 355 token.cName,\r
356 moduleName);\r
e55d8a3c 357 putError(exceptionString);\r
358 //\r
359 // Do not break preprocess, continues to analysis.\r
360 // All errors will be summary to be shown.\r
361 // \r
362 continue;\r
bc262841 363 }\r
364\r
365 if (token.isDynamicPCD) {\r
bc262841 366 if ((maxDatumSize != 0) &&\r
367 (maxDatumSize != token.datumSize)){\r
d653c17a 368 exceptionString = String.format("In the FPD file, for dynamic PCD %s in module %s, the max datum size is %d which "+\r
369 "is different than <MaxDatumSize> %d defined in <DynamicPcdBuildDefinitions>!",\r
bc262841 370 token.cName,\r
371 moduleName,\r
372 maxDatumSize,\r
373 token.datumSize);\r
e55d8a3c 374 putError(exceptionString);\r
375 //\r
376 // Do not break preprocess, continues to analysis.\r
377 // All errors will be summary to be shown.\r
378 // \r
379 continue;\r
bc262841 380 }\r
381 }\r
382\r
383 } else {\r
384 //\r
385 // If the token is not in database, create a new token instance and add\r
386 // a usage instance into this token in database.\r
387 //\r
20c5c53f 388 tokenSpaceStrRet = getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName());\r
bc262841 389\r
390 if (tokenSpaceStrRet == null) {\r
d653c17a 391 putError("Failed to get the Token Space Guid for token" + token.cName +\r
392 " from any SPD file. You must have a <GuidDeclaration> for this Token Space Guid!");\r
e55d8a3c 393 //\r
394 // Do not break preprocess, continues to analysis.\r
395 // All errors will be summary to be shown.\r
396 // \r
397 continue;\r
bc262841 398 }\r
399\r
20c5c53f 400 token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet);\r
bc262841 401\r
402 token.datumType = datumType;\r
403 token.tokenNumber = tokenNumber;\r
404 token.isDynamicPCD = Token.isDynamic(pcdType);\r
405 token.datumSize = maxDatumSize;\r
406\r
407 if (token.isDynamicPCD) {\r
408 //\r
409 // For Dynamic and Dynamic Ex type, need find the dynamic information\r
410 // in <DynamicPcdBuildDefinition> section in FPD file.\r
411 //\r
e55d8a3c 412 if (null == updateDynamicInformation(moduleName,\r
413 token,\r
414 datum,\r
415 maxDatumSize)) {\r
416 continue;\r
417 }\r
bc262841 418 }\r
419\r
420 pcdDbManager.addTokenToDatabase(primaryKey, token);\r
421 }\r
422\r
423 //\r
424 // -----------------------------------------------------------------------------------\r
425 // 2.1.3), Add the PcdType in current module into this Pcd token's supported PCD type.\r
426 // -----------------------------------------------------------------------------------\r
427 //\r
428 token.updateSupportPcdType(pcdType);\r
429\r
430 //\r
431 // ------------------------------------------------\r
432 // 2.1.4), Create an usage instance for this token.\r
433 // ------------------------------------------------\r
434 //\r
435 usageInstance = new UsageInstance(token,\r
11eb278a 436 curModule.usageId,\r
bc262841 437 pcdType,\r
438 datum,\r
439 maxDatumSize);\r
8b7bd455 440 if (!token.addUsageInstance(usageInstance)) {\r
d653c17a 441 putError(String.format("PCD %s for module %s(%s) already exists in the database.\nPlease check all PCD build entries "+\r
442 "in the %s module's <ModuleSA> section to make sure there are no duplicated definitions in the FPD file!",\r
e55d8a3c 443 token.cName,\r
11eb278a 444 curModule.usageId.moduleGuid,\r
e55d8a3c 445 moduleName,\r
446 moduleName));\r
447 continue;\r
8b7bd455 448 }\r
bc262841 449 }\r
450 }\r
451\r
452 //\r
453 // ------------------------------------------------\r
454 // 3), Add unreference dynamic_Ex pcd token into Pcd database.\r
455 // ------------------------------------------------\r
456 //\r
457 List<Token> tokenArray = getUnreferencedDynamicPcd();\r
458 if (tokenArray != null) {\r
f28c0830 459 for (index = 0; index < tokenArray.size(); index++) {\r
bc262841 460 pcdDbManager.addTokenToDatabase(tokenArray.get(index).getPrimaryKeyString(),\r
461 tokenArray.get(index));\r
462 }\r
463 }\r
464 }\r
465\r
466 /**\r
467 Update dynamic information for PCD entry.\r
468\r
469 Dynamic information is retrieved from <PcdDynamicBuildDeclarations> in\r
470 FPD file.\r
471\r
472 @param moduleName The name of the module who use this PCD\r
473 @param token The token instance\r
474 @param datum The <datum> in module's PCD information\r
475 @param maxDatumSize The <maxDatumSize> in module's PCD information\r
476\r
477 @return Token\r
478 */\r
479 private Token updateDynamicInformation(String moduleName,\r
480 Token token,\r
481 String datum,\r
482 int maxDatumSize)\r
8b7bd455 483 throws PlatformPcdPreprocessException {\r
bc262841 484 int index = 0;\r
485 int offset;\r
486 String exceptionString = null;\r
487 SkuInstance skuInstance = null;\r
488 String temp;\r
489 boolean hasSkuId0 = false;\r
490 long tokenNumber = 0;\r
491 String hiiDefaultValue = null;\r
20c5c53f 492 String variableGuidString = null;\r
bc262841 493\r
494 List<DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo> skuInfoList = null;\r
495 DynamicPcdBuildDefinitions.PcdBuildData dynamicInfo = null;\r
496\r
497 dynamicInfo = getDynamicInfoFromFpd(token, moduleName);\r
498 if (dynamicInfo == null) {\r
d653c17a 499 exceptionString = String.format("In the FPD file, the Dynamic PCD %s is used by module %s.\n" +\r
500 "However, there is no dynamic information in the <DynamicPcdBuildDefinitions> " +\r
501 "section of the FPD file. This section is required!",\r
bc262841 502 token.cName,\r
503 moduleName);\r
e55d8a3c 504 putError(exceptionString);\r
505 return null;\r
bc262841 506 }\r
507\r
508 token.datumSize = dynamicInfo.getMaxDatumSize();\r
509\r
510 exceptionString = verifyDatum(token.cName,\r
511 moduleName,\r
512 null,\r
513 token.datumType,\r
514 token.datumSize);\r
515 if (exceptionString != null) {\r
8b7bd455 516 throw new PlatformPcdPreprocessException(exceptionString);\r
bc262841 517 }\r
518\r
519 if ((maxDatumSize != 0) &&\r
520 (maxDatumSize != token.datumSize)) {\r
d653c17a 521 exceptionString = String.format("In the FPD file, for dynamic PCD %s, the datum size in module %s is %d, but "+\r
522 "the datum size in <DynamicPcdBuildDefinitions> is %d, they do not match!",\r
bc262841 523 token.cName,\r
524 moduleName,\r
525 maxDatumSize,\r
526 dynamicInfo.getMaxDatumSize());\r
e55d8a3c 527 putError(exceptionString);\r
528 return null;\r
bc262841 529 }\r
530 tokenNumber = Long.decode(dynamicInfo.getToken().toString());\r
531 if (tokenNumber != token.tokenNumber) {\r
d653c17a 532 exceptionString = String.format("In the FPD file, for dynamic PCD %s, the token number in module %s is 0x%x, but "+\r
533 "in the <DynamicPcdBuildDefinictions> section, the token number is 0x%x, they do not match!",\r
bc262841 534 token.cName,\r
535 moduleName,\r
536 token.tokenNumber,\r
537 tokenNumber);\r
e55d8a3c 538 putError(exceptionString);\r
539 return null;\r
bc262841 540 }\r
541\r
542 token.dynamicExTokenNumber = tokenNumber;\r
543\r
544 skuInfoList = dynamicInfo.getSkuInfoList();\r
545\r
546 //\r
547 // Loop all sku data\r
548 //\r
f28c0830 549 for (index = 0; index < skuInfoList.size(); index++) {\r
bc262841 550 skuInstance = new SkuInstance();\r
551 //\r
552 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.\r
553 //\r
554 temp = skuInfoList.get(index).getSkuId().toString();\r
555 skuInstance.id = Integer.decode(temp);\r
556 if (skuInstance.id == 0) {\r
557 hasSkuId0 = true;\r
558 }\r
559 //\r
560 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.\r
561 //\r
562 if (skuInfoList.get(index).getValue() != null) {\r
563 skuInstance.value.setValue(skuInfoList.get(index).getValue().toString());\r
564 if ((exceptionString = verifyDatum(token.cName,\r
565 null,\r
566 skuInfoList.get(index).getValue().toString(),\r
567 token.datumType,\r
568 token.datumSize)) != null) {\r
e55d8a3c 569 putError(exceptionString);\r
570 return null;\r
bc262841 571 }\r
572\r
573 token.skuData.add(skuInstance);\r
574\r
bc262841 575 continue;\r
576 }\r
577\r
578 //\r
579 // Judge whether is HII group case.\r
580 //\r
581 if (skuInfoList.get(index).getVariableName() != null) {\r
582 exceptionString = null;\r
583 if (skuInfoList.get(index).getVariableGuid() == null) {\r
d653c17a 584 exceptionString = String.format("In the FPD file, for dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
585 "file, use of HII was defined, but there is no <VariableGuid> defined for SKU %d data!",\r
bc262841 586 token.cName,\r
587 index);\r
e55d8a3c 588 putError(exceptionString);\r
589 return null;\r
bc262841 590 }\r
591\r
592 if (skuInfoList.get(index).getVariableOffset() == null) {\r
d653c17a 593 exceptionString = String.format("In the FPD file, for dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
594 "file, use of HII was defined, but there is no <VariableOffset> defined for SKU %d data!",\r
bc262841 595 token.cName,\r
596 index);\r
e55d8a3c 597 putError(exceptionString);\r
598 return null;\r
bc262841 599 }\r
600\r
601 if (skuInfoList.get(index).getHiiDefaultValue() == null) {\r
d653c17a 602 exceptionString = String.format("In the FPD file, for dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
603 "file, use of HII was defined, but there is no <HiiDefaultValue> defined for SKU %d data!",\r
bc262841 604 token.cName,\r
605 index);\r
e55d8a3c 606 putError(exceptionString);\r
607 return null;\r
bc262841 608 }\r
609\r
610 if (skuInfoList.get(index).getHiiDefaultValue() != null) {\r
611 hiiDefaultValue = skuInfoList.get(index).getHiiDefaultValue().toString();\r
612 } else {\r
613 hiiDefaultValue = null;\r
614 }\r
615\r
616 if ((exceptionString = verifyDatum(token.cName,\r
617 null,\r
618 hiiDefaultValue,\r
619 token.datumType,\r
620 token.datumSize)) != null) {\r
8b7bd455 621 throw new PlatformPcdPreprocessException(exceptionString);\r
bc262841 622 }\r
623\r
624 offset = Integer.decode(skuInfoList.get(index).getVariableOffset());\r
625 if (offset > 0xFFFF) {\r
d653c17a 626 putError(String.format("In the FPD file, for dynamic PCD %s, the variable offset defined in SKU %d data "+\r
627 "exceeds 64K, which is not allowed!",\r
e55d8a3c 628 token.cName,\r
629 index));\r
630 return null;\r
bc262841 631 }\r
632\r
633 //\r
634 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.\r
635 //\r
636 variableGuidString = getGuidInfoFromSpd(skuInfoList.get(index).getVariableGuid().toString());\r
637 if (variableGuidString == null) {\r
d653c17a 638 putError(String.format("In the FPD file, for dynamic PCD %s, the variable guid: %s cannot be found in any SPD file!",\r
e55d8a3c 639 token.cName,\r
640 skuInfoList.get(index).getVariableGuid().toString()));\r
641 return null;\r
bc262841 642 }\r
643 String variableStr = skuInfoList.get(index).getVariableName();\r
644 Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}");\r
645 Matcher matcher = pattern.matcher(variableStr);\r
646 List<String> varNameList = new ArrayList<String>();\r
647 while (matcher.find()){\r
8b7bd455 648 String str = variableStr.substring(matcher.start(),matcher.end());\r
649 varNameList.add(str);\r
bc262841 650 }\r
651\r
652 skuInstance.value.setHiiData(varNameList,\r
20c5c53f 653 translateSchemaStringToUUID(variableGuidString),\r
bc262841 654 skuInfoList.get(index).getVariableOffset(),\r
655 skuInfoList.get(index).getHiiDefaultValue().toString());\r
656 token.skuData.add(skuInstance);\r
657 continue;\r
658 }\r
659\r
660 if (skuInfoList.get(index).getVpdOffset() != null) {\r
661 skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset());\r
662 token.skuData.add(skuInstance);\r
663 continue;\r
664 }\r
665\r
d653c17a 666 exceptionString = String.format("In the FPD file, for dynamic PCD %s, the dynamic info must "+\r
667 "be one of: 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",\r
bc262841 668 token.cName);\r
e55d8a3c 669 putError(exceptionString);\r
670 return null;\r
bc262841 671 }\r
672\r
673 if (!hasSkuId0) {\r
d653c17a 674 exceptionString = String.format("In the FPD file, for dynamic PCD %s in <DynamicPcdBuildDefinitions>, there is "+\r
675 "no SKU ID = 0 data, which is required for every dynamic PCD",\r
bc262841 676 token.cName);\r
e55d8a3c 677 putError(exceptionString);\r
678 return null;\r
bc262841 679 }\r
680\r
681 return token;\r
682 }\r
683\r
684 /**\r
8b7bd455 685 Get all dynamic PCD defined in <DynamicPcdBuildDefinitions> which unreferenced by\r
bc262841 686 any <ModuleSA> in FPD file.\r
8b7bd455 687\r
688 @return List<Token> Return PCD token\r
bc262841 689 **/\r
8b7bd455 690 private List<Token> getUnreferencedDynamicPcd () throws PlatformPcdPreprocessException {\r
bc262841 691 List<Token> tokenArray = new ArrayList<Token>();\r
692 Token token = null;\r
693 List<DynamicPcdBuildDefinitions.PcdBuildData> dynamicPcdBuildDataArray = null;\r
694 DynamicPcdBuildDefinitions.PcdBuildData pcdBuildData = null;\r
695 List<DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo> skuInfoList = null;\r
696 Token.PCD_TYPE pcdType;\r
697 SkuInstance skuInstance = null;\r
698 String primaryKey = null;\r
699 boolean hasSkuId0 = false;\r
700 int index, offset, index2;\r
701 String temp;\r
702 String exceptionString;\r
703 String hiiDefaultValue;\r
20c5c53f 704 String tokenSpaceStrRet;\r
705 String variableGuidString;\r
bc262841 706\r
707 dynamicPcdBuildDataArray = getAllDynamicPcdInfoFromFpd();\r
708 if (dynamicPcdBuildDataArray == null) {\r
709 return null;\r
710 }\r
711\r
f28c0830 712 for (index2 = 0; index2 < dynamicPcdBuildDataArray.size(); index2++) {\r
bc262841 713 pcdBuildData = dynamicPcdBuildDataArray.get(index2);\r
20c5c53f 714 tokenSpaceStrRet = getGuidInfoFromSpd(pcdBuildData.getTokenSpaceGuidCName());\r
bc262841 715\r
716 if (tokenSpaceStrRet == null) {\r
d653c17a 717 putError("Failed to get the Token Space Guid for token" + pcdBuildData.getCName());\r
e55d8a3c 718 continue;\r
bc262841 719 }\r
720\r
721 primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(),\r
20c5c53f 722 tokenSpaceStrRet);\r
bc262841 723\r
724 if (pcdDbManager.isTokenInDatabase(primaryKey)) {\r
725 continue;\r
726 }\r
727\r
f28c0830 728 pcdType = Token.getPcdTypeFromString(pcdBuildData.getItemType().toString());\r
bc262841 729 if (pcdType != Token.PCD_TYPE.DYNAMIC_EX) {\r
d653c17a 730 putError(String.format("In the FPD file, it not allowed to define DYNAMIC PCD %s that is not used by any module",\r
e55d8a3c 731 pcdBuildData.getCName()));\r
732 continue;\r
bc262841 733 }\r
734\r
735 //\r
736 // Create new token for unreference dynamic PCD token\r
737 //\r
20c5c53f 738 token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet);\r
bc262841 739 token.datumSize = pcdBuildData.getMaxDatumSize();\r
740\r
741\r
742 token.datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString());\r
743 token.tokenNumber = Long.decode(pcdBuildData.getToken().toString());\r
744 token.dynamicExTokenNumber = token.tokenNumber;\r
745 token.isDynamicPCD = true;\r
746 token.updateSupportPcdType(pcdType);\r
747\r
748 exceptionString = verifyDatum(token.cName,\r
749 null,\r
750 null,\r
751 token.datumType,\r
752 token.datumSize);\r
753 if (exceptionString != null) {\r
e55d8a3c 754 putError(exceptionString);\r
755 continue;\r
bc262841 756 }\r
757\r
758 skuInfoList = pcdBuildData.getSkuInfoList();\r
759\r
760 //\r
761 // Loop all sku data\r
762 //\r
f28c0830 763 for (index = 0; index < skuInfoList.size(); index++) {\r
bc262841 764 skuInstance = new SkuInstance();\r
765 //\r
766 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.\r
767 //\r
768 temp = skuInfoList.get(index).getSkuId().toString();\r
769 skuInstance.id = Integer.decode(temp);\r
770 if (skuInstance.id == 0) {\r
771 hasSkuId0 = true;\r
772 }\r
773 //\r
774 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.\r
775 //\r
776 if (skuInfoList.get(index).getValue() != null) {\r
777 skuInstance.value.setValue(skuInfoList.get(index).getValue().toString());\r
778 if ((exceptionString = verifyDatum(token.cName,\r
779 null,\r
780 skuInfoList.get(index).getValue().toString(),\r
781 token.datumType,\r
782 token.datumSize)) != null) {\r
e55d8a3c 783 putError(exceptionString);\r
784 continue;\r
bc262841 785 }\r
786\r
787 token.skuData.add(skuInstance);\r
788\r
789 continue;\r
790 }\r
791\r
792 //\r
793 // Judge whether is HII group case.\r
794 //\r
795 if (skuInfoList.get(index).getVariableName() != null) {\r
796 exceptionString = null;\r
797 if (skuInfoList.get(index).getVariableGuid() == null) {\r
d653c17a 798 exceptionString = String.format("In the FPD file, for dynamic PCD %s in the <DynamicPcdBuildDefinitions> section of the FPD "+\r
799 "file, use of HII is defined, but there is no <VariableGuid> defined for SKU %d data!",\r
bc262841 800 token.cName,\r
801 index);\r
e55d8a3c 802 putError(exceptionString);\r
803 continue;\r
bc262841 804 }\r
805\r
806 if (skuInfoList.get(index).getVariableOffset() == null) {\r
d653c17a 807 exceptionString = String.format("In the FPD file, for dynamic PCD %s in the <DynamicPcdBuildDefinitions> section of the FPD "+\r
808 "file, use of HII is defined, but there is no <VariableOffset> defined for SKU %d data!",\r
bc262841 809 token.cName,\r
810 index);\r
e55d8a3c 811 putError(exceptionString);\r
812 continue;\r
bc262841 813 }\r
814\r
815 if (skuInfoList.get(index).getHiiDefaultValue() == null) {\r
d653c17a 816 exceptionString = String.format("In the FPD file, for dynamic PCD %s in the <DynamicPcdBuildDefinitions> section of the FPD "+\r
817 "file, use of HII is defined, but there is no <HiiDefaultValue> defined for SKU %d data!",\r
bc262841 818 token.cName,\r
819 index);\r
e55d8a3c 820 putError(exceptionString);\r
821 continue;\r
bc262841 822 }\r
823\r
824 if (skuInfoList.get(index).getHiiDefaultValue() != null) {\r
825 hiiDefaultValue = skuInfoList.get(index).getHiiDefaultValue().toString();\r
826 } else {\r
827 hiiDefaultValue = null;\r
828 }\r
829\r
830 if ((exceptionString = verifyDatum(token.cName,\r
831 null,\r
832 hiiDefaultValue,\r
833 token.datumType,\r
834 token.datumSize)) != null) {\r
e55d8a3c 835 putError(exceptionString);\r
836 continue;\r
bc262841 837 }\r
838\r
839 offset = Integer.decode(skuInfoList.get(index).getVariableOffset());\r
840 if (offset > 0xFFFF) {\r
d653c17a 841 exceptionString = String.format("In the FPD file, for dynamic PCD %s, the variable offset defined in SKU %d data "+\r
842 "exceeds 64K, which is not allowed!",\r
8b7bd455 843 token.cName,\r
e55d8a3c 844 index);\r
845 putError(exceptionString);\r
846 continue;\r
bc262841 847 }\r
848\r
849 //\r
850 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.\r
851 //\r
20c5c53f 852 variableGuidString = getGuidInfoFromSpd(skuInfoList.get(index).getVariableGuid().toString());\r
bc262841 853 if (variableGuidString == null) {\r
d653c17a 854 exceptionString = String.format("In the FPD file, for dynamic PCD %s, the variable guid %s cannot be found in any SPD file!",\r
e55d8a3c 855 token.cName,\r
856 skuInfoList.get(index).getVariableGuid().toString());\r
857 putError(exceptionString);\r
858 continue;\r
bc262841 859 }\r
860 String variableStr = skuInfoList.get(index).getVariableName();\r
861 Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}");\r
862 Matcher matcher = pattern.matcher(variableStr);\r
863 List<String> varNameList = new ArrayList<String>();\r
864 while (matcher.find()){\r
8b7bd455 865 String str = variableStr.substring(matcher.start(),matcher.end());\r
866 varNameList.add(str);\r
bc262841 867 }\r
868\r
869 skuInstance.value.setHiiData(varNameList,\r
20c5c53f 870 translateSchemaStringToUUID(variableGuidString),\r
bc262841 871 skuInfoList.get(index).getVariableOffset(),\r
872 skuInfoList.get(index).getHiiDefaultValue().toString());\r
873 token.skuData.add(skuInstance);\r
874 continue;\r
875 }\r
876\r
877 if (skuInfoList.get(index).getVpdOffset() != null) {\r
878 skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset());\r
879 token.skuData.add(skuInstance);\r
880 continue;\r
881 }\r
882\r
d653c17a 883 exceptionString = String.format("In the FPD file, for dynamic PCD %s, the dynamic info must "+\r
bc262841 884 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",\r
885 token.cName);\r
e55d8a3c 886 putError(exceptionString);\r
bc262841 887 }\r
888\r
889 if (!hasSkuId0) {\r
d653c17a 890 exceptionString = String.format("In the FPD file, for dynamic PCD %s in <DynamicPcdBuildDefinitions>, there is "+\r
891 "no SKU ID = 0 data, which is required for every dynamic PCD",\r
bc262841 892 token.cName);\r
e55d8a3c 893 putError(exceptionString);\r
894 continue;\r
bc262841 895 }\r
896\r
897 tokenArray.add(token);\r
898 }\r
899\r
900 return tokenArray;\r
901 }\r
902\r
903 /**\r
904 Translate the schema string to UUID instance.\r
905\r
906 In schema, the string of UUID is defined as following two types string:\r
907 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(\r
908 )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?\r
909\r
910 2) GuidNamingConvention: pattern =\r
911 [a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\r
912\r
913 This function will convert string and create uuid instance.\r
914\r
915 @param uuidString UUID string in XML file\r
916\r
917 @return UUID UUID instance\r
918 **/\r
919 private UUID translateSchemaStringToUUID(String uuidString)\r
8b7bd455 920 throws PlatformPcdPreprocessException {\r
bc262841 921 String temp;\r
922 String[] splitStringArray;\r
923 int index;\r
924 int chIndex;\r
925 int chLen;\r
926\r
927 if (uuidString == null) {\r
928 return null;\r
929 }\r
930\r
931 if (uuidString.length() == 0) {\r
932 return null;\r
933 }\r
934\r
935 if (uuidString.equals("0") ||\r
936 uuidString.equalsIgnoreCase("0x0")) {\r
937 return new UUID(0, 0);\r
938 }\r
939\r
940 uuidString = uuidString.replaceAll("\\{", "");\r
941 uuidString = uuidString.replaceAll("\\}", "");\r
942\r
943 //\r
944 // If the UUID schema string is GuidArrayType type then need translate\r
945 // to GuidNamingConvention type at first.\r
946 //\r
947 if ((uuidString.charAt(0) == '0') && ((uuidString.charAt(1) == 'x') || (uuidString.charAt(1) == 'X'))) {\r
948 splitStringArray = uuidString.split("," );\r
949 if (splitStringArray.length != 11) {\r
d653c17a 950 throw new PlatformPcdPreprocessException ("Wrong format for GUID string: " + uuidString);\r
bc262841 951 }\r
952\r
953 //\r
954 // Remove blank space from these string and remove header string "0x"\r
955 //\r
f28c0830 956 for (index = 0; index < 11; index++) {\r
bc262841 957 splitStringArray[index] = splitStringArray[index].trim();\r
958 splitStringArray[index] = splitStringArray[index].substring(2, splitStringArray[index].length());\r
959 }\r
960\r
961 //\r
962 // Add heading '0' to normalize the string length\r
963 //\r
f28c0830 964 for (index = 3; index < 11; index++) {\r
bc262841 965 chLen = splitStringArray[index].length();\r
f28c0830 966 for (chIndex = 0; chIndex < 2 - chLen; chIndex++) {\r
bc262841 967 splitStringArray[index] = "0" + splitStringArray[index];\r
968 }\r
969 }\r
970\r
971 //\r
972 // construct the final GuidNamingConvention string\r
973 //\r
974 temp = String.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",\r
975 splitStringArray[0],\r
976 splitStringArray[1],\r
977 splitStringArray[2],\r
978 splitStringArray[3],\r
979 splitStringArray[4],\r
980 splitStringArray[5],\r
981 splitStringArray[6],\r
982 splitStringArray[7],\r
983 splitStringArray[8],\r
984 splitStringArray[9],\r
985 splitStringArray[10]);\r
986 uuidString = temp;\r
987 }\r
988\r
989 return UUID.fromString(uuidString);\r
990 }\r
991}\r
992\r