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