]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java
Miss loop variable incremental, otherwise, will cause dead loop.
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / pcd / action / CollectPCDAction.java
1 /** @file
2 CollectPCDAction class.
3
4 This action class is to collect PCD information from MSA, SPD, FPD xml file.
5 This class will be used for wizard and build tools, So it can *not* inherit
6 from buildAction or wizardAction.
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.build.pcd.action;
19
20 import java.io.File;
21 import java.io.IOException;
22 import java.math.BigInteger;
23 import java.util.ArrayList;
24 import java.util.Comparator;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.UUID;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34 import org.apache.xmlbeans.XmlException;
35 import org.apache.xmlbeans.XmlObject;
36 import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions;
37 import org.tianocore.FrameworkModulesDocument;
38 import org.tianocore.ModuleSADocument;
39 import org.tianocore.PcdBuildDefinitionDocument;
40 import org.tianocore.PcdBuildDefinitionDocument.PcdBuildDefinition;
41 import org.tianocore.PlatformSurfaceAreaDocument;
42 import org.tianocore.build.fpd.FpdParserTask;
43 import org.tianocore.build.global.GlobalData;
44 import org.tianocore.build.id.FpdModuleIdentification;
45 import org.tianocore.build.id.ModuleIdentification;
46 import org.tianocore.pcd.action.ActionMessage;
47 import org.tianocore.pcd.entity.CommonDefinition;
48 import org.tianocore.pcd.entity.DynamicTokenValue;
49 import org.tianocore.pcd.entity.MemoryDatabaseManager;
50 import org.tianocore.pcd.entity.SkuInstance;
51 import org.tianocore.pcd.entity.Token;
52 import org.tianocore.pcd.entity.UsageIdentification;
53 import org.tianocore.pcd.entity.UsageInstance;
54 import org.tianocore.pcd.exception.EntityException;
55
56 /** Module Info class is the data structure to hold information got from GlobalData.
57 */
58 class ModuleInfo {
59 ///
60 /// Module's ID for a <ModuleSA>
61 ///
62 private FpdModuleIdentification moduleId;
63 ///
64 /// <PcdBuildDefinition> xmlobject in FPD file for a <ModuleSA>
65 ///
66 private PcdBuildDefinitionDocument.PcdBuildDefinition pcdBuildDef;
67
68 public ModuleInfo (FpdModuleIdentification moduleId, XmlObject pcdDef) {
69 this.moduleId = moduleId;
70 this.pcdBuildDef = ((PcdBuildDefinitionDocument)pcdDef).getPcdBuildDefinition();
71 }
72
73 public FpdModuleIdentification getModuleId (){
74 return moduleId;
75 }
76
77 public PcdBuildDefinitionDocument.PcdBuildDefinition getPcdBuildDef(){
78 return pcdBuildDef;
79 }
80 }
81
82 /** This action class is to collect PCD information from MSA, SPD, FPD xml file.
83 This class will be used for wizard and build tools, So it can *not* inherit
84 from buildAction or UIAction.
85 **/
86 public class CollectPCDAction {
87 ///
88 /// memoryDatabase hold all PCD information collected from SPD, MSA, FPD.
89 ///
90 private MemoryDatabaseManager dbManager;
91 ///
92 /// Workspacepath hold the workspace information.
93 ///
94 private String workspacePath;
95 ///
96 /// FPD file is the root file.
97 ///
98 private String fpdFilePath;
99 ///
100 /// Message level for CollectPCDAction.
101 ///
102 private int originalMessageLevel;
103 ///
104 /// Cache the fpd docment instance for private usage.
105 ///
106 private PlatformSurfaceAreaDocument fpdDocInstance;
107 ///
108 /// xmlObject name
109 ///
110 private static String xmlObjectName = "PcdBuildDefinition";
111
112 /**
113 Set WorkspacePath parameter for this action class.
114
115 @param workspacePath parameter for this action
116 **/
117 public void setWorkspacePath(String workspacePath) {
118 this.workspacePath = workspacePath;
119 }
120
121 /**
122 Set action message level for CollectPcdAction tool.
123
124 The message should be restored when this action exit.
125
126 @param actionMessageLevel parameter for this action
127 **/
128 public void setActionMessageLevel(int actionMessageLevel) {
129 originalMessageLevel = ActionMessage.messageLevel;
130 ActionMessage.messageLevel = actionMessageLevel;
131 }
132
133 /**
134 Set FPDFileName parameter for this action class.
135
136 @param fpdFilePath fpd file path
137 **/
138 public void setFPDFilePath(String fpdFilePath) {
139 this.fpdFilePath = fpdFilePath;
140 }
141
142 /**
143 Common function interface for outer.
144
145 @param workspacePath The path of workspace of current build or analysis.
146 @param fpdFilePath The fpd file path of current build or analysis.
147 @param messageLevel The message level for this Action.
148
149 @throws Exception The exception of this function. Because it can *not* be predict
150 where the action class will be used. So only Exception can be throw.
151
152 **/
153 public void perform(String workspacePath, String fpdFilePath,
154 int messageLevel) throws Exception {
155 setWorkspacePath(workspacePath);
156 setFPDFilePath(fpdFilePath);
157 setActionMessageLevel(messageLevel);
158 checkParameter();
159 execute();
160 ActionMessage.messageLevel = originalMessageLevel;
161 }
162
163 /**
164 Core execution function for this action class.
165
166 This function work flows will be:
167 1) Collect and prepocess PCD information from FPD file, all PCD
168 information will be stored into memory database.
169 2) Generate 3 strings for
170 a) All modules using Dynamic(Ex) PCD entry.(Token Number)
171 b) PEI PCDDatabase (C Structure) for PCD Service PEIM.
172 c) DXE PCD Database (C structure) for PCD Service DXE.
173
174
175 @throws EntityException Exception indicate failed to execute this action.
176
177 **/
178 public void execute() throws EntityException {
179 //
180 // Get memoryDatabaseManager instance from GlobalData.
181 // The memoryDatabaseManager should be initialized for whatever build
182 // tools or wizard tools
183 //
184 if((dbManager = GlobalData.getPCDMemoryDBManager()) == null) {
185 throw new EntityException("The instance of PCD memory database manager is null");
186 }
187
188 //
189 // Collect all PCD information defined in FPD file.
190 // Evenry token defind in FPD will be created as an token into
191 // memory database.
192 //
193 createTokenInDBFromFPD();
194
195 //
196 // Generate for PEI, DXE PCD DATABASE's definition and initialization.
197 //
198 genPcdDatabaseSourceCode ();
199
200 }
201
202 /**
203 This function generates source code for PCD Database.
204
205 @param void
206 @throws EntityException If the token does *not* exist in memory database.
207
208 **/
209 private void genPcdDatabaseSourceCode()
210 throws EntityException {
211 String PcdCommonHeaderString = PcdDatabase.getPcdDatabaseCommonDefinitions();
212
213 ArrayList<Token> alPei = new ArrayList<Token> ();
214 ArrayList<Token> alDxe = new ArrayList<Token> ();
215
216 dbManager.getTwoPhaseDynamicRecordArray(alPei, alDxe);
217 PcdDatabase pcdPeiDatabase = new PcdDatabase (alPei, "PEI", 0);
218 pcdPeiDatabase.genCode();
219 MemoryDatabaseManager.PcdPeimHString = PcdCommonHeaderString + pcdPeiDatabase.getHString() +
220 PcdDatabase.getPcdPeiDatabaseDefinitions();
221 MemoryDatabaseManager.PcdPeimCString = pcdPeiDatabase.getCString();
222
223 PcdDatabase pcdDxeDatabase = new PcdDatabase(alDxe, "DXE", alPei.size());
224 pcdDxeDatabase.genCode();
225 MemoryDatabaseManager.PcdDxeHString = MemoryDatabaseManager.PcdPeimHString + pcdDxeDatabase.getHString() +
226 PcdDatabase.getPcdDxeDatabaseDefinitions();
227 MemoryDatabaseManager.PcdDxeCString = pcdDxeDatabase.getCString();
228 }
229
230 /**
231 Get component array from FPD.
232
233 This function maybe provided by some Global class.
234
235 @return List<ModuleInfo> the component array.
236
237 */
238 private List<ModuleInfo> getComponentsFromFPD()
239 throws EntityException {
240 List<ModuleInfo> allModules = new ArrayList<ModuleInfo>();
241 FrameworkModulesDocument.FrameworkModules fModules = null;
242 ModuleSADocument.ModuleSA[] modules = null;
243 Map<FpdModuleIdentification, XmlObject> pcdBuildDefinitions = null;
244
245 pcdBuildDefinitions = GlobalData.getFpdPcdBuildDefinitions();
246 if (pcdBuildDefinitions == null) {
247 return null;
248 }
249
250 //
251 // Loop map to retrieve all PCD build definition and Module id
252 //
253 Iterator item = pcdBuildDefinitions.keySet().iterator();
254 while (item.hasNext()){
255 FpdModuleIdentification id = (FpdModuleIdentification) item.next();
256 allModules.add(new ModuleInfo(id, pcdBuildDefinitions.get(id)));
257 }
258
259 return allModules;
260 }
261
262 /**
263 Create token instance object into memory database, the token information
264 comes for FPD file. Normally, FPD file will contain all token platform
265 informations.
266
267 @return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage.
268
269 @throws EntityException Failed to parse FPD xml file.
270
271 **/
272 private void createTokenInDBFromFPD()
273 throws EntityException {
274 int index = 0;
275 int index2 = 0;
276 int pcdIndex = 0;
277 List<PcdBuildDefinition.PcdData> pcdBuildDataArray = new ArrayList<PcdBuildDefinition.PcdData>();
278 PcdBuildDefinition.PcdData pcdBuildData = null;
279 Token token = null;
280 List<ModuleInfo> modules = null;
281 String primaryKey = null;
282 String exceptionString = null;
283 UsageInstance usageInstance = null;
284 String primaryKey1 = null;
285 String primaryKey2 = null;
286 boolean isDuplicate = false;
287 Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN;
288 Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN;
289 long tokenNumber = 0;
290 String moduleName = null;
291 String datum = null;
292 int maxDatumSize = 0;
293 String[] tokenSpaceStrRet = null;
294 UsageIdentification usageId = null;
295 ModuleIdentification moduleId = null;
296
297 //
298 // ----------------------------------------------
299 // 1), Get all <ModuleSA> from FPD file.
300 // ----------------------------------------------
301 //
302 modules = getComponentsFromFPD();
303
304 if (modules == null) {
305 throw new EntityException("[FPD file error] No modules in FPD file, Please check whether there are elements in <FrameworkModules> in FPD file!");
306 }
307
308 //
309 // -------------------------------------------------------------------
310 // 2), Loop all modules to process <PcdBuildDeclarations> for each module.
311 // -------------------------------------------------------------------
312 //
313 for (index = 0; index < modules.size(); index ++) {
314 //
315 // It is legal for a module does not contains ANY pcd build definitions.
316 //
317 if (modules.get(index).getPcdBuildDef() == null) {
318 continue;
319 }
320
321 pcdBuildDataArray = modules.get(index).getPcdBuildDef().getPcdDataList();
322
323 moduleName = modules.get(index).getModuleId().getModule().getName();
324
325 //
326 // ----------------------------------------------------------------------
327 // 2.1), Loop all Pcd entry for a module and add it into memory database.
328 // ----------------------------------------------------------------------
329 //
330 for (pcdIndex = 0; pcdIndex < pcdBuildDataArray.size(); pcdIndex ++) {
331 pcdBuildData = pcdBuildDataArray.get(pcdIndex);
332
333 try {
334 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(pcdBuildData.getTokenSpaceGuidCName());
335 } catch ( Exception e ) {
336 throw new EntityException ("Faile get Guid for token " + pcdBuildData.getCName() + ":" + e.getMessage());
337 }
338
339 if (tokenSpaceStrRet == null) {
340 throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData.getCName());
341 }
342
343 primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(), tokenSpaceStrRet[1]);
344 pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString());
345 datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString());
346 tokenNumber = Long.decode(pcdBuildData.getToken().toString());
347 if (pcdBuildData.getValue() != null) {
348 datum = pcdBuildData.getValue().toString();
349 } else {
350 datum = null;
351 }
352 maxDatumSize = pcdBuildData.getMaxDatumSize();
353
354 if ((pcdType == Token.PCD_TYPE.FEATURE_FLAG) &&
355 (datumType != Token.DATUM_TYPE.BOOLEAN)){
356 exceptionString = String.format("[FPD file error] For PCD %s in module %s, the PCD type is FEATRUE_FLAG but "+
357 "datum type of this PCD entry is not BOOLEAN!",
358 pcdBuildData.getCName(),
359 moduleName);
360 throw new EntityException(exceptionString);
361 }
362
363 //
364 // -------------------------------------------------------------------------------------------
365 // 2.1.1), Do some necessary checking work for FixedAtBuild, FeatureFlag and PatchableInModule
366 // -------------------------------------------------------------------------------------------
367 //
368 if (!Token.isDynamic(pcdType)) {
369 //
370 // Value is required.
371 //
372 if (datum == null) {
373 exceptionString = String.format("[FPD file error] There is no value for PCD entry %s in module %s!",
374 pcdBuildData.getCName(),
375 moduleName);
376 throw new EntityException(exceptionString);
377 }
378
379 //
380 // Check whether the datum size is matched datum type.
381 //
382 if ((exceptionString = verifyDatum(pcdBuildData.getCName(),
383 moduleName,
384 datum,
385 datumType,
386 maxDatumSize)) != null) {
387 throw new EntityException(exceptionString);
388 }
389 }
390
391 //
392 // ---------------------------------------------------------------------------------
393 // 2.1.2), Create token or update token information for current anaylized PCD data.
394 // ---------------------------------------------------------------------------------
395 //
396 if (dbManager.isTokenInDatabase(primaryKey)) {
397 //
398 // If the token is already exist in database, do some necessary checking
399 // and add a usage instance into this token in database
400 //
401 token = dbManager.getTokenByKey(primaryKey);
402
403 //
404 // checking for DatumType, DatumType should be unique for one PCD used in different
405 // modules.
406 //
407 if (token.datumType != datumType) {
408 exceptionString = String.format("[FPD file error] The datum type of PCD entry %s is %s, which is different with %s defined in before!",
409 pcdBuildData.getCName(),
410 pcdBuildData.getDatumType().toString(),
411 Token.getStringOfdatumType(token.datumType));
412 throw new EntityException(exceptionString);
413 }
414
415 //
416 // Check token number is valid
417 //
418 if (tokenNumber != token.tokenNumber) {
419 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!",
420 pcdBuildData.getCName(),
421 moduleName);
422 throw new EntityException(exceptionString);
423 }
424
425 //
426 // For same PCD used in different modules, the PCD type should all be dynamic or non-dynamic.
427 //
428 if (token.isDynamicPCD != Token.isDynamic(pcdType)) {
429 exceptionString = String.format("[FPD file error] For PCD entry %s in module %s, you define dynamic or non-dynamic PCD type which"+
430 "is different with others module's",
431 token.cName,
432 moduleName);
433 throw new EntityException(exceptionString);
434 }
435
436 if (token.isDynamicPCD) {
437 //
438 // Check datum is equal the datum in dynamic information.
439 // For dynamic PCD, you can do not write <Value> in sperated every <PcdBuildDefinition> in different <ModuleSA>,
440 // But if you write, the <Value> must be same as the value in <DynamicPcdBuildDefinitions>.
441 //
442 if (!token.isSkuEnable() &&
443 (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.DEFAULT_TYPE) &&
444 (datum != null)) {
445 if (!datum.equalsIgnoreCase(token.getDefaultSku().value)) {
446 exceptionString = String.format("[FPD file error] For dynamic PCD %s in module %s, the datum in <ModuleSA> is "+
447 "not equal to the datum in <DynamicPcdBuildDefinitions>, it is "+
448 "illega! You could no set <Value> in <ModuleSA> for a dynamic PCD!",
449 token.cName,
450 moduleName);
451 throw new EntityException(exceptionString);
452 }
453 }
454
455 if ((maxDatumSize != 0) &&
456 (maxDatumSize != token.datumSize)){
457 exceptionString = String.format("[FPD file error] For dynamic PCD %s in module %s, the max datum size is %d which "+
458 "is different with <MaxDatumSize> %d defined in <DynamicPcdBuildDefinitions>!",
459 token.cName,
460 moduleName,
461 maxDatumSize,
462 token.datumSize);
463 throw new EntityException(exceptionString);
464 }
465 }
466
467 } else {
468 //
469 // If the token is not in database, create a new token instance and add
470 // a usage instance into this token in database.
471 //
472 try {
473 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(pcdBuildData.getTokenSpaceGuidCName());
474 } catch (Exception e) {
475 throw new EntityException("Fail to get token space guid for token " + token.cName);
476 }
477
478 if (tokenSpaceStrRet == null) {
479 throw new EntityException("Fail to get token space guid for token " + token.cName);
480 }
481
482 token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet[1]);
483
484 token.datumType = datumType;
485 token.tokenNumber = tokenNumber;
486 token.isDynamicPCD = Token.isDynamic(pcdType);
487 token.datumSize = maxDatumSize;
488
489 if (token.isDynamicPCD) {
490 //
491 // For Dynamic and Dynamic Ex type, need find the dynamic information
492 // in <DynamicPcdBuildDefinition> section in FPD file.
493 //
494 updateDynamicInformation(moduleName,
495 token,
496 datum,
497 maxDatumSize);
498 }
499
500 dbManager.addTokenToDatabase(primaryKey, token);
501 }
502
503 //
504 // -----------------------------------------------------------------------------------
505 // 2.1.3), Add the PcdType in current module into this Pcd token's supported PCD type.
506 // -----------------------------------------------------------------------------------
507 //
508 token.updateSupportPcdType(pcdType);
509
510 //
511 // ------------------------------------------------
512 // 2.1.4), Create an usage instance for this token.
513 // ------------------------------------------------
514 //
515 moduleId = modules.get(index).getModuleId().getModule();
516 usageId = new UsageIdentification (moduleId.getName(),
517 moduleId.getGuid(),
518 moduleId.getPackage().getName(),
519 moduleId.getPackage().getGuid(),
520 modules.get(index).getModuleId().getArch(),
521 moduleId.getVersion(),
522 moduleId.getModuleType());
523 usageInstance = new UsageInstance(token,
524 usageId,
525 pcdType,
526 datum,
527 maxDatumSize);
528 token.addUsageInstance(usageInstance);
529 }
530 }
531
532 //
533 // ------------------------------------------------
534 // 3), Add unreference dynamic_Ex pcd token into Pcd database.
535 // ------------------------------------------------
536 //
537 List<Token> tokenArray = getUnreferencedDynamicPcd();
538 if (tokenArray != null) {
539 for (index = 0; index < tokenArray.size(); index ++) {
540 dbManager.addTokenToDatabase(tokenArray.get(index).getPrimaryKeyString(),
541 tokenArray.get(index));
542 }
543 }
544 }
545
546 private List<Token> getUnreferencedDynamicPcd () throws EntityException {
547 List<Token> tokenArray = new ArrayList<Token>();
548 Token token = null;
549 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null;
550 List<DynamicPcdBuildDefinitions.PcdBuildData> dynamicPcdBuildDataArray = null;
551 DynamicPcdBuildDefinitions.PcdBuildData pcdBuildData = null;
552 List<DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo> skuInfoList = null;
553 Token.PCD_TYPE pcdType;
554 SkuInstance skuInstance = null;
555 String primaryKey = null;
556 boolean hasSkuId0 = false;
557 int index, offset, index2;
558 String temp;
559 String exceptionString;
560 String hiiDefaultValue;
561 String tokenSpaceStrRet[];
562 String variableGuidString[];
563
564 //
565 // Open fpd document to get <DynamicPcdBuildDefinition> Section.
566 // BUGBUG: the function should be move GlobalData in furture.
567 //
568 if (fpdDocInstance == null) {
569 try {
570 fpdDocInstance = (PlatformSurfaceAreaDocument)XmlObject.Factory.parse(new File(fpdFilePath));
571 } catch(IOException ioE) {
572 throw new EntityException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage());
573 } catch(XmlException xmlE) {
574 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage());
575 }
576 }
577
578 dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
579 if (dynamicPcdBuildDefinitions == null) {
580 return null;
581 }
582
583 dynamicPcdBuildDataArray = dynamicPcdBuildDefinitions.getPcdBuildDataList();
584 for (index2 = 0; index2 < dynamicPcdBuildDataArray.size(); index2 ++) {
585 pcdBuildData = dynamicPcdBuildDataArray.get(index2);
586 try {
587 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(pcdBuildData.getTokenSpaceGuidCName());
588 } catch ( Exception e ) {
589 throw new EntityException ("Faile get Guid for token " + pcdBuildData.getCName() + ":" + e.getMessage());
590 }
591
592 if (tokenSpaceStrRet == null) {
593 throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData.getCName());
594 }
595
596 primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(),
597 tokenSpaceStrRet[1]);
598
599 if (dbManager.isTokenInDatabase(primaryKey)) {
600 continue;
601 }
602
603 pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString());
604 if (pcdType != Token.PCD_TYPE.DYNAMIC_EX) {
605 throw new EntityException (String.format("[FPD file error] It not allowed for DYNAMIC PCD %s who is no used by any module",
606 pcdBuildData.getCName()));
607 }
608
609 //
610 // Create new token for unreference dynamic PCD token
611 //
612 token = new Token(pcdBuildData.getCName(), tokenSpaceStrRet[1]);
613 token.datumSize = pcdBuildData.getMaxDatumSize();
614
615
616 token.datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString());
617 token.tokenNumber = Long.decode(pcdBuildData.getToken().toString());
618 token.dynamicExTokenNumber = token.tokenNumber;
619 token.isDynamicPCD = true;
620 token.updateSupportPcdType(pcdType);
621
622 exceptionString = verifyDatum(token.cName,
623 null,
624 null,
625 token.datumType,
626 token.datumSize);
627 if (exceptionString != null) {
628 throw new EntityException(exceptionString);
629 }
630
631 skuInfoList = pcdBuildData.getSkuInfoList();
632
633 //
634 // Loop all sku data
635 //
636 for (index = 0; index < skuInfoList.size(); index ++) {
637 skuInstance = new SkuInstance();
638 //
639 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.
640 //
641 temp = skuInfoList.get(index).getSkuId().toString();
642 skuInstance.id = Integer.decode(temp);
643 if (skuInstance.id == 0) {
644 hasSkuId0 = true;
645 }
646 //
647 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.
648 //
649 if (skuInfoList.get(index).getValue() != null) {
650 skuInstance.value.setValue(skuInfoList.get(index).getValue().toString());
651 if ((exceptionString = verifyDatum(token.cName,
652 null,
653 skuInfoList.get(index).getValue().toString(),
654 token.datumType,
655 token.datumSize)) != null) {
656 throw new EntityException(exceptionString);
657 }
658
659 token.skuData.add(skuInstance);
660
661 continue;
662 }
663
664 //
665 // Judge whether is HII group case.
666 //
667 if (skuInfoList.get(index).getVariableName() != null) {
668 exceptionString = null;
669 if (skuInfoList.get(index).getVariableGuid() == null) {
670 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
671 "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",
672 token.cName,
673 index);
674 if (exceptionString != null) {
675 throw new EntityException(exceptionString);
676 }
677 }
678
679 if (skuInfoList.get(index).getVariableOffset() == null) {
680 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
681 "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",
682 token.cName,
683 index);
684 if (exceptionString != null) {
685 throw new EntityException(exceptionString);
686 }
687 }
688
689 if (skuInfoList.get(index).getHiiDefaultValue() == null) {
690 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
691 "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",
692 token.cName,
693 index);
694 if (exceptionString != null) {
695 throw new EntityException(exceptionString);
696 }
697 }
698
699 if (skuInfoList.get(index).getHiiDefaultValue() != null) {
700 hiiDefaultValue = skuInfoList.get(index).getHiiDefaultValue().toString();
701 } else {
702 hiiDefaultValue = null;
703 }
704
705 if ((exceptionString = verifyDatum(token.cName,
706 null,
707 hiiDefaultValue,
708 token.datumType,
709 token.datumSize)) != null) {
710 throw new EntityException(exceptionString);
711 }
712
713 offset = Integer.decode(skuInfoList.get(index).getVariableOffset());
714 if (offset > 0xFFFF) {
715 throw new EntityException(String.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+
716 "exceed 64K, it is not allowed!",
717 token.cName,
718 index));
719 }
720
721 //
722 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.
723 //
724 variableGuidString = GlobalData.getGuidInfoFromCname(skuInfoList.get(index).getVariableGuid().toString());
725 if (variableGuidString == null) {
726 throw new EntityException(String.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",
727 token.cName,
728 skuInfoList.get(index).getVariableGuid().toString()));
729 }
730 String variableStr = skuInfoList.get(index).getVariableName();
731 Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}");
732 Matcher matcher = pattern.matcher(variableStr);
733 List<String> varNameList = new ArrayList<String>();
734 while (matcher.find()){
735 String str = variableStr.substring(matcher.start(),matcher.end());
736 varNameList.add(str);
737 }
738
739 skuInstance.value.setHiiData(varNameList,
740 translateSchemaStringToUUID(variableGuidString[1]),
741 skuInfoList.get(index).getVariableOffset(),
742 skuInfoList.get(index).getHiiDefaultValue().toString());
743 token.skuData.add(skuInstance);
744 continue;
745 }
746
747 if (skuInfoList.get(index).getVpdOffset() != null) {
748 skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset());
749 token.skuData.add(skuInstance);
750 continue;
751 }
752
753 exceptionString = String.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+
754 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",
755 token.cName);
756 throw new EntityException(exceptionString);
757 }
758
759 if (!hasSkuId0) {
760 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+
761 "no sku id = 0 data, which is required for every dynamic PCD",
762 token.cName);
763 throw new EntityException(exceptionString);
764 }
765
766 tokenArray.add(token);
767 }
768
769 return tokenArray;
770 }
771
772 /**
773 Verify the datum value according its datum size and datum type, this
774 function maybe moved to FPD verification tools in future.
775
776 @param cName
777 @param moduleName
778 @param datum
779 @param datumType
780 @param maxDatumSize
781
782 @return String
783 */
784 /***/
785 public String verifyDatum(String cName,
786 String moduleName,
787 String datum,
788 Token.DATUM_TYPE datumType,
789 int maxDatumSize) {
790 String exceptionString = null;
791 int value;
792 BigInteger value64;
793 String subStr;
794 int index;
795
796 if (moduleName == null) {
797 moduleName = "section <DynamicPcdBuildDefinitions>";
798 } else {
799 moduleName = "module " + moduleName;
800 }
801
802 if (maxDatumSize == 0) {
803 exceptionString = String.format("[FPD file error] You maybe miss <MaxDatumSize> for PCD %s in %s",
804 cName,
805 moduleName);
806 return exceptionString;
807 }
808
809 switch (datumType) {
810 case UINT8:
811 if (maxDatumSize != 1) {
812 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+
813 "is UINT8, but datum size is %d, they are not matched!",
814 cName,
815 moduleName,
816 maxDatumSize);
817 return exceptionString;
818 }
819
820 if (datum != null) {
821 try {
822 value = Integer.decode(datum);
823 } catch (NumberFormatException nfeExp) {
824 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not valid "+
825 "digital format of UINT8",
826 cName,
827 moduleName);
828 return exceptionString;
829 }
830 if (value > 0xFF) {
831 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s exceed"+
832 " the max size of UINT8 - 0xFF",
833 cName,
834 moduleName,
835 datum);
836 return exceptionString;
837 }
838 }
839 break;
840 case UINT16:
841 if (maxDatumSize != 2) {
842 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+
843 "is UINT16, but datum size is %d, they are not matched!",
844 cName,
845 moduleName,
846 maxDatumSize);
847 return exceptionString;
848 }
849 if (datum != null) {
850 try {
851 value = Integer.decode(datum);
852 } catch (NumberFormatException nfeExp) {
853 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is "+
854 "not valid digital of UINT16",
855 cName,
856 moduleName);
857 return exceptionString;
858 }
859 if (value > 0xFFFF) {
860 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s "+
861 "which exceed the range of UINT16 - 0xFFFF",
862 cName,
863 moduleName,
864 datum);
865 return exceptionString;
866 }
867 }
868 break;
869 case UINT32:
870 if (maxDatumSize != 4) {
871 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+
872 "is UINT32, but datum size is %d, they are not matched!",
873 cName,
874 moduleName,
875 maxDatumSize);
876 return exceptionString;
877 }
878
879 if (datum != null) {
880 try {
881 if (datum.length() > 2) {
882 if ((datum.charAt(0) == '0') &&
883 ((datum.charAt(1) == 'x') || (datum.charAt(1) == 'X'))){
884 subStr = datum.substring(2, datum.length());
885 value64 = new BigInteger(subStr, 16);
886 } else {
887 value64 = new BigInteger(datum);
888 }
889 } else {
890 value64 = new BigInteger(datum);
891 }
892 } catch (NumberFormatException nfeExp) {
893 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not "+
894 "valid digital of UINT32",
895 cName,
896 moduleName);
897 return exceptionString;
898 }
899
900 if (value64.bitLength() > 32) {
901 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s which "+
902 "exceed the range of UINT32 - 0xFFFFFFFF",
903 cName,
904 moduleName,
905 datum);
906 return exceptionString;
907 }
908 }
909 break;
910 case UINT64:
911 if (maxDatumSize != 8) {
912 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+
913 "is UINT64, but datum size is %d, they are not matched!",
914 cName,
915 moduleName,
916 maxDatumSize);
917 return exceptionString;
918 }
919
920 if (datum != null) {
921 try {
922 if (datum.length() > 2) {
923 if ((datum.charAt(0) == '0') &&
924 ((datum.charAt(1) == 'x') || (datum.charAt(1) == 'X'))){
925 subStr = datum.substring(2, datum.length());
926 value64 = new BigInteger(subStr, 16);
927 } else {
928 value64 = new BigInteger(datum);
929 }
930 } else {
931 value64 = new BigInteger(datum);
932 }
933 } catch (NumberFormatException nfeExp) {
934 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not valid"+
935 " digital of UINT64",
936 cName,
937 moduleName);
938 return exceptionString;
939 }
940
941 if (value64.bitLength() > 64) {
942 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s "+
943 "exceed the range of UINT64 - 0xFFFFFFFFFFFFFFFF",
944 cName,
945 moduleName,
946 datum);
947 return exceptionString;
948 }
949 }
950 break;
951 case BOOLEAN:
952 if (maxDatumSize != 1) {
953 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+
954 "is BOOLEAN, but datum size is %d, they are not matched!",
955 cName,
956 moduleName,
957 maxDatumSize);
958 return exceptionString;
959 }
960
961 if (datum != null) {
962 if (!(datum.equalsIgnoreCase("TRUE") ||
963 datum.equalsIgnoreCase("FALSE"))) {
964 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+
965 "is BOOELAN, but value is not 'true'/'TRUE' or 'FALSE'/'false'",
966 cName,
967 moduleName);
968 return exceptionString;
969 }
970
971 }
972 break;
973 case POINTER:
974 if (datum == null) {
975 break;
976 }
977
978 char ch = datum.charAt(0);
979 int start, end;
980 String strValue;
981 //
982 // For void* type PCD, only three datum is support:
983 // 1) Unicode: string with start char is "L"
984 // 2) Ansci: String start char is ""
985 // 3) byte array: String start char "{"
986 //
987 if (ch == 'L') {
988 start = datum.indexOf('\"');
989 end = datum.lastIndexOf('\"');
990 if ((start > end) ||
991 (end > datum.length())||
992 ((start == end) && (datum.length() > 0))) {
993 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
994 "a UNICODE string because start with L\", but format maybe"+
995 "is not right, correct UNICODE string is L\"...\"!",
996 cName,
997 moduleName);
998 return exceptionString;
999 }
1000
1001 strValue = datum.substring(start + 1, end);
1002 if ((strValue.length() * 2) > maxDatumSize) {
1003 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
1004 "a UNICODE string, but the datum size is %d exceed to <MaxDatumSize> : %d",
1005 cName,
1006 moduleName,
1007 strValue.length() * 2,
1008 maxDatumSize);
1009 return exceptionString;
1010 }
1011 } else if (ch == '\"'){
1012 start = datum.indexOf('\"');
1013 end = datum.lastIndexOf('\"');
1014 if ((start > end) ||
1015 (end > datum.length())||
1016 ((start == end) && (datum.length() > 0))) {
1017 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+
1018 "a ANSCII string because start with \", but format maybe"+
1019 "is not right, correct ANSIC string is \"...\"!",
1020 cName,
1021 moduleName);
1022 return exceptionString;
1023 }
1024 strValue = datum.substring(start + 1, end);
1025 if ((strValue.length()) > maxDatumSize) {
1026 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+
1027 "a ANSCI string, but the datum size is %d which exceed to <MaxDatumSize> : %d",
1028 cName,
1029 moduleName,
1030 strValue.length(),
1031 maxDatumSize);
1032 return exceptionString;
1033 }
1034 } else if (ch =='{') {
1035 String[] strValueArray;
1036
1037 start = datum.indexOf('{');
1038 end = datum.lastIndexOf('}');
1039 strValue = datum.substring(start + 1, end);
1040 strValue = strValue.trim();
1041 if (strValue.length() == 0) {
1042 exceptionString = String.format ("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
1043 "it is byte array in fact, but '{}' is not valid for NULL datam but"+
1044 " need use '{0}'",
1045 cName,
1046 moduleName);
1047 return exceptionString;
1048 }
1049 strValueArray = strValue.split(",");
1050 for (index = 0; index < strValueArray.length; index ++) {
1051 try{
1052 value = Integer.decode(strValueArray[index].trim());
1053 } catch (NumberFormatException nfeEx) {
1054 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+
1055 "it is byte array in fact. For every byte in array should be a valid"+
1056 "byte digital, but element %s is not a valid byte digital!",
1057 cName,
1058 moduleName,
1059 strValueArray[index]);
1060 return exceptionString;
1061 }
1062 if (value > 0xFF) {
1063 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, "+
1064 "it is byte array in fact. But the element of %s exceed the byte range",
1065 cName,
1066 moduleName,
1067 strValueArray[index]);
1068 return exceptionString;
1069 }
1070 }
1071
1072 if (strValueArray.length > maxDatumSize) {
1073 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is byte"+
1074 "array, but the number of bytes is %d which exceed to <MaxDatumSzie> : %d!",
1075 cName,
1076 moduleName,
1077 strValueArray.length,
1078 maxDatumSize);
1079 return exceptionString;
1080 }
1081 } else {
1082 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*. For VOID* type, you have three format choise:\n "+
1083 "1) UNICODE string: like L\"xxxx\";\r\n"+
1084 "2) ANSIC string: like \"xxx\";\r\n"+
1085 "3) Byte array: like {0x2, 0x45, 0x23}\r\n"+
1086 "But the datum in seems does not following above format!",
1087 cName,
1088 moduleName);
1089 return exceptionString;
1090 }
1091 break;
1092 default:
1093 exceptionString = String.format("[FPD file error] For PCD entry %s in %s, datum type is unknown, it should be one of "+
1094 "UINT8, UINT16, UINT32, UINT64, VOID*, BOOLEAN",
1095 cName,
1096 moduleName);
1097 return exceptionString;
1098 }
1099 return null;
1100 }
1101
1102 /**
1103 Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.
1104
1105 This function should be implemented in GlobalData in future.
1106
1107 @param token The token instance which has hold module's PCD information
1108 @param moduleName The name of module who will use this Dynamic PCD.
1109
1110 @return DynamicPcdBuildDefinitions.PcdBuildData
1111 */
1112 /***/
1113 private DynamicPcdBuildDefinitions.PcdBuildData getDynamicInfoFromFPD(Token token,
1114 String moduleName)
1115 throws EntityException {
1116 int index = 0;
1117 String exceptionString = null;
1118 String dynamicPrimaryKey = null;
1119 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null;
1120 List<DynamicPcdBuildDefinitions.PcdBuildData> dynamicPcdBuildDataArray = null;
1121 String[] tokenSpaceStrRet = null;
1122
1123 //
1124 // If FPD document is not be opened, open and initialize it.
1125 // BUGBUG: The code should be moved into GlobalData in future.
1126 //
1127 if (fpdDocInstance == null) {
1128 try {
1129 fpdDocInstance = (PlatformSurfaceAreaDocument)XmlObject.Factory.parse(new File(fpdFilePath));
1130 } catch(IOException ioE) {
1131 throw new EntityException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage());
1132 } catch(XmlException xmlE) {
1133 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage());
1134 }
1135 }
1136
1137 dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();
1138 if (dynamicPcdBuildDefinitions == null) {
1139 exceptionString = String.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+
1140 "PCD entry %s in module %s!",
1141 token.cName,
1142 moduleName);
1143 throw new EntityException(exceptionString);
1144 }
1145
1146 dynamicPcdBuildDataArray = dynamicPcdBuildDefinitions.getPcdBuildDataList();
1147 for (index = 0; index < dynamicPcdBuildDataArray.size(); index ++) {
1148 //String tokenSpaceGuidString = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName())[1];
1149 String tokenSpaceGuidString = null;
1150 try {
1151 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName());
1152 } catch (Exception e) {
1153 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray.get(index).getCName());
1154 }
1155
1156 if (tokenSpaceStrRet == null) {
1157 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray.get(index).getCName());
1158 }
1159
1160 dynamicPrimaryKey = Token.getPrimaryKeyString(dynamicPcdBuildDataArray.get(index).getCName(),
1161 tokenSpaceStrRet[1]);
1162 if (dynamicPrimaryKey.equalsIgnoreCase(token.getPrimaryKeyString())) {
1163 return dynamicPcdBuildDataArray.get(index);
1164 }
1165 }
1166
1167 return null;
1168 }
1169
1170 /**
1171 Update dynamic information for PCD entry.
1172
1173 Dynamic information is retrieved from <PcdDynamicBuildDeclarations> in
1174 FPD file.
1175
1176 @param moduleName The name of the module who use this PCD
1177 @param token The token instance
1178 @param datum The <datum> in module's PCD information
1179 @param maxDatumSize The <maxDatumSize> in module's PCD information
1180
1181 @return Token
1182 */
1183 private Token updateDynamicInformation(String moduleName,
1184 Token token,
1185 String datum,
1186 int maxDatumSize)
1187 throws EntityException {
1188 int index = 0;
1189 int offset;
1190 String exceptionString = null;
1191 DynamicTokenValue dynamicValue;
1192 SkuInstance skuInstance = null;
1193 String temp;
1194 boolean hasSkuId0 = false;
1195 Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN;
1196 long tokenNumber = 0;
1197 String hiiDefaultValue = null;
1198 String[] variableGuidString = null;
1199
1200 List<DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo> skuInfoList = null;
1201 DynamicPcdBuildDefinitions.PcdBuildData dynamicInfo = null;
1202
1203 dynamicInfo = getDynamicInfoFromFPD(token, moduleName);
1204 if (dynamicInfo == null) {
1205 exceptionString = String.format("[FPD file error] For Dynamic PCD %s used by module %s, "+
1206 "there is no dynamic information in <DynamicPcdBuildDefinitions> "+
1207 "in FPD file, but it is required!",
1208 token.cName,
1209 moduleName);
1210 throw new EntityException(exceptionString);
1211 }
1212
1213 token.datumSize = dynamicInfo.getMaxDatumSize();
1214
1215 exceptionString = verifyDatum(token.cName,
1216 moduleName,
1217 null,
1218 token.datumType,
1219 token.datumSize);
1220 if (exceptionString != null) {
1221 throw new EntityException(exceptionString);
1222 }
1223
1224 if ((maxDatumSize != 0) &&
1225 (maxDatumSize != token.datumSize)) {
1226 exceptionString = String.format("FPD file error] For dynamic PCD %s, the datum size in module %s is %d, but "+
1227 "the datum size in <DynamicPcdBuildDefinitions> is %d, they are not match!",
1228 token.cName,
1229 moduleName,
1230 maxDatumSize,
1231 dynamicInfo.getMaxDatumSize());
1232 throw new EntityException(exceptionString);
1233 }
1234 tokenNumber = Long.decode(dynamicInfo.getToken().toString());
1235 if (tokenNumber != token.tokenNumber) {
1236 exceptionString = String.format("[FPD file error] For dynamic PCD %s, the token number in module %s is 0x%x, but"+
1237 "in <DynamicPcdBuildDefinictions>, the token number is 0x%x, they are not match!",
1238 token.cName,
1239 moduleName,
1240 token.tokenNumber,
1241 tokenNumber);
1242 throw new EntityException(exceptionString);
1243 }
1244
1245 pcdType = Token.getpcdTypeFromString(dynamicInfo.getItemType().toString());
1246 token.dynamicExTokenNumber = tokenNumber;
1247
1248 skuInfoList = dynamicInfo.getSkuInfoList();
1249
1250 //
1251 // Loop all sku data
1252 //
1253 for (index = 0; index < skuInfoList.size(); index ++) {
1254 skuInstance = new SkuInstance();
1255 //
1256 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.
1257 //
1258 temp = skuInfoList.get(index).getSkuId().toString();
1259 skuInstance.id = Integer.decode(temp);
1260 if (skuInstance.id == 0) {
1261 hasSkuId0 = true;
1262 }
1263 //
1264 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.
1265 //
1266 if (skuInfoList.get(index).getValue() != null) {
1267 skuInstance.value.setValue(skuInfoList.get(index).getValue().toString());
1268 if ((exceptionString = verifyDatum(token.cName,
1269 null,
1270 skuInfoList.get(index).getValue().toString(),
1271 token.datumType,
1272 token.datumSize)) != null) {
1273 throw new EntityException(exceptionString);
1274 }
1275
1276 token.skuData.add(skuInstance);
1277
1278 //
1279 // Judege wether is same of datum between module's information
1280 // and dynamic information.
1281 //
1282 if (datum != null) {
1283 if ((skuInstance.id == 0) &&
1284 !datum.toString().equalsIgnoreCase(skuInfoList.get(index).getValue().toString())) {
1285 exceptionString = "[FPD file error] For dynamic PCD " + token.cName + ", the value in module " + moduleName + " is " + datum.toString() + " but the "+
1286 "value of sku 0 data in <DynamicPcdBuildDefinition> is " + skuInstance.value.value + ". They are must be same!"+
1287 " or you could not define value for a dynamic PCD in every <ModuleSA>!";
1288 throw new EntityException(exceptionString);
1289 }
1290 }
1291 continue;
1292 }
1293
1294 //
1295 // Judge whether is HII group case.
1296 //
1297 if (skuInfoList.get(index).getVariableName() != null) {
1298 exceptionString = null;
1299 if (skuInfoList.get(index).getVariableGuid() == null) {
1300 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
1301 "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",
1302 token.cName,
1303 index);
1304 if (exceptionString != null) {
1305 throw new EntityException(exceptionString);
1306 }
1307 }
1308
1309 if (skuInfoList.get(index).getVariableOffset() == null) {
1310 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
1311 "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",
1312 token.cName,
1313 index);
1314 if (exceptionString != null) {
1315 throw new EntityException(exceptionString);
1316 }
1317 }
1318
1319 if (skuInfoList.get(index).getHiiDefaultValue() == null) {
1320 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+
1321 "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",
1322 token.cName,
1323 index);
1324 if (exceptionString != null) {
1325 throw new EntityException(exceptionString);
1326 }
1327 }
1328
1329 if (skuInfoList.get(index).getHiiDefaultValue() != null) {
1330 hiiDefaultValue = skuInfoList.get(index).getHiiDefaultValue().toString();
1331 } else {
1332 hiiDefaultValue = null;
1333 }
1334
1335 if ((exceptionString = verifyDatum(token.cName,
1336 null,
1337 hiiDefaultValue,
1338 token.datumType,
1339 token.datumSize)) != null) {
1340 throw new EntityException(exceptionString);
1341 }
1342
1343 offset = Integer.decode(skuInfoList.get(index).getVariableOffset());
1344 if (offset > 0xFFFF) {
1345 throw new EntityException(String.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+
1346 "exceed 64K, it is not allowed!",
1347 token.cName,
1348 index));
1349 }
1350
1351 //
1352 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.
1353 //
1354 variableGuidString = GlobalData.getGuidInfoFromCname(skuInfoList.get(index).getVariableGuid().toString());
1355 if (variableGuidString == null) {
1356 throw new EntityException(String.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",
1357 token.cName,
1358 skuInfoList.get(index).getVariableGuid().toString()));
1359 }
1360 String variableStr = skuInfoList.get(index).getVariableName();
1361 Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}");
1362 Matcher matcher = pattern.matcher(variableStr);
1363 List<String> varNameList = new ArrayList<String>();
1364 while (matcher.find()){
1365 String str = variableStr.substring(matcher.start(),matcher.end());
1366 varNameList.add(str);
1367 }
1368
1369 skuInstance.value.setHiiData(varNameList,
1370 translateSchemaStringToUUID(variableGuidString[1]),
1371 skuInfoList.get(index).getVariableOffset(),
1372 skuInfoList.get(index).getHiiDefaultValue().toString());
1373 token.skuData.add(skuInstance);
1374 continue;
1375 }
1376
1377 if (skuInfoList.get(index).getVpdOffset() != null) {
1378 skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset());
1379 token.skuData.add(skuInstance);
1380 continue;
1381 }
1382
1383 exceptionString = String.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+
1384 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",
1385 token.cName);
1386 throw new EntityException(exceptionString);
1387 }
1388
1389 if (!hasSkuId0) {
1390 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+
1391 "no sku id = 0 data, which is required for every dynamic PCD",
1392 token.cName);
1393 throw new EntityException(exceptionString);
1394 }
1395
1396 return token;
1397 }
1398
1399 /**
1400 Translate the schema string to UUID instance.
1401
1402 In schema, the string of UUID is defined as following two types string:
1403 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(
1404 )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?
1405
1406 2) GuidNamingConvention: pattern =
1407 [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}
1408
1409 This function will convert string and create uuid instance.
1410
1411 @param uuidString UUID string in XML file
1412
1413 @return UUID UUID instance
1414 **/
1415 private UUID translateSchemaStringToUUID(String uuidString)
1416 throws EntityException {
1417 String temp;
1418 String[] splitStringArray;
1419 int index;
1420 int chIndex;
1421 int chLen;
1422
1423 if (uuidString == null) {
1424 return null;
1425 }
1426
1427 if (uuidString.length() == 0) {
1428 return null;
1429 }
1430
1431 if (uuidString.equals("0") ||
1432 uuidString.equalsIgnoreCase("0x0")) {
1433 return new UUID(0, 0);
1434 }
1435
1436 uuidString = uuidString.replaceAll("\\{", "");
1437 uuidString = uuidString.replaceAll("\\}", "");
1438
1439 //
1440 // If the UUID schema string is GuidArrayType type then need translate
1441 // to GuidNamingConvention type at first.
1442 //
1443 if ((uuidString.charAt(0) == '0') && ((uuidString.charAt(1) == 'x') || (uuidString.charAt(1) == 'X'))) {
1444 splitStringArray = uuidString.split("," );
1445 if (splitStringArray.length != 11) {
1446 throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString);
1447 }
1448
1449 //
1450 // Remove blank space from these string and remove header string "0x"
1451 //
1452 for (index = 0; index < 11; index ++) {
1453 splitStringArray[index] = splitStringArray[index].trim();
1454 splitStringArray[index] = splitStringArray[index].substring(2, splitStringArray[index].length());
1455 }
1456
1457 //
1458 // Add heading '0' to normalize the string length
1459 //
1460 for (index = 3; index < 11; index ++) {
1461 chLen = splitStringArray[index].length();
1462 for (chIndex = 0; chIndex < 2 - chLen; chIndex ++) {
1463 splitStringArray[index] = "0" + splitStringArray[index];
1464 }
1465 }
1466
1467 //
1468 // construct the final GuidNamingConvention string
1469 //
1470 temp = String.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",
1471 splitStringArray[0],
1472 splitStringArray[1],
1473 splitStringArray[2],
1474 splitStringArray[3],
1475 splitStringArray[4],
1476 splitStringArray[5],
1477 splitStringArray[6],
1478 splitStringArray[7],
1479 splitStringArray[8],
1480 splitStringArray[9],
1481 splitStringArray[10]);
1482 uuidString = temp;
1483 }
1484
1485 return UUID.fromString(uuidString);
1486 }
1487
1488 /**
1489 check parameter for this action.
1490
1491 @throws EntityException Bad parameter.
1492 **/
1493 private void checkParameter() throws EntityException {
1494 File file = null;
1495
1496 if((fpdFilePath == null) ||(workspacePath == null)) {
1497 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
1498 }
1499
1500 if(fpdFilePath.length() == 0 || workspacePath.length() == 0) {
1501 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");
1502 }
1503
1504 file = new File(workspacePath);
1505 if(!file.exists()) {
1506 throw new EntityException("WorkpacePath " + workspacePath + " does not exist!");
1507 }
1508
1509 file = new File(fpdFilePath);
1510
1511 if(!file.exists()) {
1512 throw new EntityException("FPD File " + fpdFilePath + " does not exist!");
1513 }
1514 }
1515
1516 /**
1517 Test case function
1518
1519 @param argv parameter from command line
1520 **/
1521 public static void main(String argv[]) throws EntityException {
1522 CollectPCDAction ca = new CollectPCDAction();
1523 String projectDir = "x:/edk2";
1524 ca.setWorkspacePath(projectDir);
1525 ca.setFPDFilePath(projectDir + "/EdkNt32Pkg/Nt32.fpd");
1526 ca.setActionMessageLevel(ActionMessage.MAX_MESSAGE_LEVEL);
1527 GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db",
1528 projectDir,
1529 "tools_def.txt");
1530 System.out.println("After initInfo!");
1531 FpdParserTask fpt = new FpdParserTask();
1532 fpt.parseFpdFile(new File(projectDir + "/EdkNt32Pkg/Nt32.fpd"));
1533 ca.execute();
1534 }
1535 }