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