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