]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java
Fix autogen bug:[Edk67][Edk35].
[mirror_edk2.git] / Tools / Source / GenBuild / org / tianocore / build / pcd / action / CollectPCDAction.java
... / ...
CommitLineData
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.BufferedReader; \r
21import java.io.File;\r
22import java.io.FileReader;\r
23import java.io.IOException;\r
24import java.math.BigInteger;\r
25import java.util.ArrayList;\r
26import java.util.Comparator;\r
27import java.util.HashMap;\r
28import java.util.Iterator;\r
29import java.util.List;\r
30import java.util.Map;\r
31import java.util.Set;\r
32import java.util.UUID;\r
33import java.util.regex.Matcher;\r
34import java.util.regex.Pattern;\r
35\r
36import org.apache.xmlbeans.XmlException;\r
37import org.apache.xmlbeans.XmlObject;\r
38import org.tianocore.DynamicPcdBuildDefinitionsDocument.DynamicPcdBuildDefinitions;\r
39import org.tianocore.FrameworkModulesDocument;\r
40import org.tianocore.PlatformSurfaceAreaDocument;\r
41import org.tianocore.PcdBuildDefinitionDocument;\r
42import org.tianocore.ModuleSADocument;\r
43import org.tianocore.PcdBuildDefinitionDocument.PcdBuildDefinition;\r
44import org.tianocore.build.autogen.CommonDefinition;\r
45import org.tianocore.build.global.GlobalData;\r
46import org.tianocore.build.id.FpdModuleIdentification;\r
47import org.tianocore.build.pcd.action.ActionMessage;\r
48import org.tianocore.build.pcd.entity.DynamicTokenValue;\r
49import org.tianocore.build.pcd.entity.MemoryDatabaseManager;\r
50import org.tianocore.build.pcd.entity.SkuInstance;\r
51import org.tianocore.build.pcd.entity.Token;\r
52import org.tianocore.build.pcd.entity.UsageInstance;\r
53import org.tianocore.build.pcd.exception.EntityException;\r
54\r
55/**\r
56 CStructTypeDeclaration \r
57 \r
58 This class is used to store the declaration string, such as\r
59 "UINT32 PcdPlatformFlashBaseAddress", of \r
60 each memember in the C structure, which is a standard C language\r
61 feature used to implement a simple and efficient database for\r
62 dynamic(ex) type PCD entry.\r
63**/\r
64\r
65class CStructTypeDeclaration {\r
66 String key;\r
67 int alignmentSize;\r
68 String cCode;\r
69 boolean initTable;\r
70 \r
71 public CStructTypeDeclaration (String key, int alignmentSize, String cCode, boolean initTable) {\r
72 this.key = key;\r
73 this.alignmentSize = alignmentSize;\r
74 this.cCode = cCode;\r
75 this.initTable = initTable;\r
76 }\r
77}\r
78\r
79/**\r
80 StringTable \r
81 \r
82 This class is used to store the String in a PCD database.\r
83 \r
84**/\r
85class StringTable {\r
86 private ArrayList<String> al; \r
87 private ArrayList<String> alComments;\r
88 private String phase;\r
89 int len; \r
90\r
91 public StringTable (String phase) {\r
92 this.phase = phase;\r
93 al = new ArrayList<String>();\r
94 alComments = new ArrayList<String>();\r
95 len = 0;\r
96 }\r
97\r
98 public String getSizeMacro () {\r
99 return String.format(PcdDatabase.StringTableSizeMacro, phase, getSize());\r
100 }\r
101\r
102 private int getSize () {\r
103 //\r
104 // We have at least one Unicode Character in the table.\r
105 //\r
106 return len == 0 ? 1 : len;\r
107 }\r
108\r
109 public String getExistanceMacro () {\r
110 return String.format(PcdDatabase.StringTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE");\r
111 }\r
112 \r
113 public void genCode (ArrayList<CStructTypeDeclaration> declaList, HashMap<String, String> instTable) {\r
114 final String stringTable = "StringTable";\r
115 final String tab = "\t";\r
116 final String newLine = "\r\n";\r
117 final String commaNewLine = ",\r\n";\r
118 \r
119 CStructTypeDeclaration decl;\r
120\r
121 String cDeclCode = "";\r
122 String cInstCode = "";\r
123\r
124 //\r
125 // If we have a empty StringTable\r
126 //\r
127 if (al.size() == 0) {\r
128 cDeclCode += String.format("%-20s%s[1]; /* StringTable is empty */", "UINT16", stringTable) + newLine; \r
129 decl = new CStructTypeDeclaration (\r
130 stringTable,\r
131 2,\r
132 cDeclCode,\r
133 true\r
134 ); \r
135 declaList.add(decl);\r
136\r
137 cInstCode = String.format("/* %s */", stringTable) + newLine + tab + "{ 0 }";\r
138 instTable.put(stringTable, cInstCode);\r
139 } else {\r
140\r
141 //\r
142 // If there is any String in the StringTable\r
143 //\r
144 for (int i = 0; i < al.size(); i++) {\r
145 String str = al.get(i);\r
146 String stringTableName;\r
147 \r
148 if (i == 0) {\r
149 //\r
150 // StringTable is a well-known name in the PCD DXE driver\r
151 //\r
152 stringTableName = stringTable;\r
153 \r
154 } else {\r
155 stringTableName = String.format("%s_%d", stringTable, i);\r
156 cDeclCode += tab;\r
157 }\r
158 cDeclCode += String.format("%-20s%s[%d]; /* %s */", "UINT16", \r
159 stringTableName, str.length() + 1, \r
160 alComments.get(i)) \r
161 + newLine;\r
162 \r
163 if (i == 0) {\r
164 cInstCode = "/* StringTable */" + newLine;\r
165 }\r
166 \r
167 cInstCode += tab + String.format("L\"%s\" /* %s */", al.get(i), alComments.get(i));\r
168 if (i != al.size() - 1) {\r
169 cInstCode += commaNewLine;\r
170 }\r
171 }\r
172 \r
173 decl = new CStructTypeDeclaration (\r
174 stringTable,\r
175 2,\r
176 cDeclCode,\r
177 true\r
178 ); \r
179 declaList.add(decl);\r
180 \r
181 instTable.put(stringTable, cInstCode);\r
182 }\r
183 }\r
184\r
185 public int add (String inputStr, Token token) {\r
186 int i;\r
187 int pos;\r
188\r
189 String str = inputStr;\r
190 \r
191 //\r
192 // The input can be two types:\r
193 // "L\"Bootmode\"" or "Bootmode". \r
194 // We drop the L\" and \" for the first type. \r
195 if (str.startsWith("L\"") && str.endsWith("\"")) {\r
196 str = str.substring(2, str.length() - 1);\r
197 }\r
198 //\r
199 // Check if StringTable has this String already.\r
200 // If so, return the current pos.\r
201 //\r
202 for (i = 0, pos = 0; i < al.size(); i++) {\r
203 String s = al.get(i);;\r
204\r
205 if (str.equals(s)) {\r
206 return pos;\r
207 }\r
208 pos = s.length() + 1;\r
209 }\r
210 \r
211 i = len;\r
212 //\r
213 // Include the NULL character at the end of String\r
214 //\r
215 len += str.length() + 1; \r
216 al.add(str);\r
217 alComments.add(token.getPrimaryKeyString());\r
218\r
219 return i;\r
220 }\r
221}\r
222\r
223/**\r
224 SizeTable \r
225 \r
226 This class is used to store the Size information for\r
227 POINTER TYPE PCD entry in a PCD database.\r
228\r
229**/\r
230class SizeTable {\r
231 private ArrayList<Integer> al;\r
232 private ArrayList<String> alComments;\r
233 private String phase;\r
234 private int len;\r
235 \r
236 public SizeTable (String phase) {\r
237 this.phase = phase;\r
238 al = new ArrayList<Integer>();\r
239 alComments = new ArrayList<String>();\r
240 len = 0;\r
241 }\r
242\r
243 public void genCode (ArrayList<CStructTypeDeclaration> declaList, HashMap<String, String> instTable, String phase) {\r
244 final String name = "SizeTable";\r
245 \r
246 CStructTypeDeclaration decl;\r
247 String cCode;\r
248\r
249 cCode = String.format(PcdDatabase.SizeTableDeclaration, phase); \r
250 decl = new CStructTypeDeclaration (\r
251 name,\r
252 2,\r
253 cCode,\r
254 true\r
255 ); \r
256 declaList.add(decl);\r
257\r
258\r
259 cCode = PcdDatabase.genInstantiationStr(getInstantiation());\r
260 instTable.put(name, cCode);\r
261 }\r
262\r
263 private ArrayList<String> getInstantiation () {\r
264 ArrayList<String> Output = new ArrayList<String>();\r
265\r
266 Output.add("/* SizeTable */");\r
267 Output.add("{");\r
268 if (al.size() == 0) {\r
269 Output.add("\t0");\r
270 } else {\r
271 for (int index = 0; index < al.size(); index++) {\r
272 Integer n = al.get(index);\r
273 String str = "\t" + n.toString();\r
274\r
275 if (index != (al.size() - 1)) {\r
276 str += ",";\r
277 }\r
278\r
279 str += " /* " + alComments.get(index) + " */"; \r
280 Output.add(str);\r
281 \r
282 }\r
283 }\r
284 Output.add("}");\r
285\r
286 return Output;\r
287 }\r
288\r
289 public int add (Token token) {\r
290 int index = len;\r
291\r
292 len++; \r
293 al.add(token.datumSize);\r
294 alComments.add(token.getPrimaryKeyString());\r
295\r
296 return index;\r
297 }\r
298 \r
299 public int getTableLen () {\r
300 return al.size() == 0 ? 1 : al.size();\r
301 }\r
302\r
303}\r
304\r
305/**\r
306 GuidTable \r
307 \r
308 This class is used to store the GUIDs in a PCD database.\r
309**/\r
310class GuidTable {\r
311 private ArrayList<UUID> al;\r
312 private ArrayList<String> alComments;\r
313 private String phase;\r
314 private int len;\r
315 private int bodyLineNum;\r
316\r
317 public GuidTable (String phase) {\r
318 this.phase = phase;\r
319 al = new ArrayList<UUID>();\r
320 alComments = new ArrayList<String>();\r
321 len = 0;\r
322 bodyLineNum = 0;\r
323 }\r
324\r
325 public String getSizeMacro () {\r
326 return String.format(PcdDatabase.GuidTableSizeMacro, phase, getSize());\r
327 }\r
328\r
329 private int getSize () {\r
330 return (al.size() == 0)? 1 : al.size();\r
331 }\r
332\r
333 public String getExistanceMacro () {\r
334 return String.format(PcdDatabase.GuidTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE");\r
335 }\r
336\r
337 public void genCode (ArrayList<CStructTypeDeclaration> declaList, HashMap<String, String> instTable, String phase) {\r
338 final String name = "GuidTable";\r
339 \r
340 CStructTypeDeclaration decl;\r
341 String cCode = "";\r
342\r
343 cCode += String.format(PcdDatabase.GuidTableDeclaration, phase); \r
344 decl = new CStructTypeDeclaration (\r
345 name,\r
346 8,\r
347 cCode,\r
348 true\r
349 ); \r
350 declaList.add(decl);\r
351\r
352\r
353 cCode = PcdDatabase.genInstantiationStr(getInstantiation());\r
354 instTable.put(name, cCode);\r
355 }\r
356\r
357 private String getUuidCString (UUID uuid) {\r
358 String[] guidStrArray;\r
359\r
360 guidStrArray =(uuid.toString()).split("-");\r
361\r
362 return String.format("{0x%s, 0x%s, 0x%s, {0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s}}",\r
363 guidStrArray[0],\r
364 guidStrArray[1],\r
365 guidStrArray[2],\r
366 (guidStrArray[3].substring(0, 2)),\r
367 (guidStrArray[3].substring(2, 4)),\r
368 (guidStrArray[4].substring(0, 2)),\r
369 (guidStrArray[4].substring(2, 4)),\r
370 (guidStrArray[4].substring(4, 6)),\r
371 (guidStrArray[4].substring(6, 8)),\r
372 (guidStrArray[4].substring(8, 10)),\r
373 (guidStrArray[4].substring(10, 12))\r
374 );\r
375 }\r
376\r
377 private ArrayList<String> getInstantiation () {\r
378 ArrayList<String> Output = new ArrayList<String>();\r
379\r
380 Output.add("/* GuidTable */");\r
381 Output.add("{");\r
382\r
383 if (al.size() == 0) {\r
384 Output.add("\t" + getUuidCString(new UUID(0, 0)));\r
385 }\r
386 \r
387 for (int i = 0; i < al.size(); i++) {\r
388 String str = "\t" + getUuidCString(al.get(i));\r
389\r
390 str += "/* " + alComments.get(i) + " */";\r
391 if (i != (al.size() - 1)) {\r
392 str += ",";\r
393 }\r
394 Output.add(str);\r
395 bodyLineNum++;\r
396\r
397 }\r
398 Output.add("}");\r
399\r
400 return Output;\r
401 }\r
402\r
403 public int add (UUID uuid, String name) {\r
404 //\r
405 // Check if GuidTable has this entry already.\r
406 // If so, return the GuidTable index.\r
407 //\r
408 for (int i = 0; i < al.size(); i++) {\r
409 if (al.get(i).equals(uuid)) {\r
410 return i;\r
411 }\r
412 }\r
413 \r
414 len++; \r
415 al.add(uuid);\r
416 alComments.add(name);\r
417\r
418 //\r
419 // Return the previous Table Index\r
420 //\r
421 return len - 1;\r
422 }\r
423\r
424}\r
425\r
426/**\r
427 SkuIdTable \r
428 \r
429 This class is used to store the SKU IDs in a PCD database.\r
430\r
431**/\r
432class SkuIdTable {\r
433 private ArrayList<Integer[]> al;\r
434 private ArrayList<String> alComment;\r
435 private String phase;\r
436 private int len;\r
437\r
438 public SkuIdTable (String phase) {\r
439 this.phase = phase;\r
440 al = new ArrayList<Integer[]>();\r
441 alComment = new ArrayList<String>();\r
442 len = 0;\r
443 }\r
444\r
445 public String getSizeMacro () {\r
446 return String.format(PcdDatabase.SkuIdTableSizeMacro, phase, getSize());\r
447 }\r
448\r
449 private int getSize () {\r
450 return (len == 0)? 1 : len;\r
451 }\r
452\r
453 public String getExistanceMacro () {\r
454 return String.format(PcdDatabase.SkuTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE");\r
455 }\r
456\r
457 public void genCode (ArrayList<CStructTypeDeclaration> declaList, HashMap<String, String> instTable, String phase) {\r
458 final String name = "SkuIdTable";\r
459 \r
460 CStructTypeDeclaration decl;\r
461 String cCode = "";\r
462\r
463 cCode += String.format(PcdDatabase.SkuIdTableDeclaration, phase); \r
464 decl = new CStructTypeDeclaration (\r
465 name,\r
466 1,\r
467 cCode,\r
468 true\r
469 ); \r
470 declaList.add(decl);\r
471\r
472\r
473 cCode = PcdDatabase.genInstantiationStr(getInstantiation());\r
474 instTable.put(name, cCode);\r
475\r
476 //\r
477 // SystemSkuId is in PEI phase PCD Database\r
478 //\r
479 if (phase.equalsIgnoreCase("PEI")) {\r
480 decl = new CStructTypeDeclaration (\r
481 "SystemSkuId",\r
482 1,\r
483 String.format("%-20sSystemSkuId;\r\n", "SKU_ID"),\r
484 true\r
485 );\r
486 declaList.add(decl);\r
487 \r
488 instTable.put("SystemSkuId", "0");\r
489 }\r
490\r
491 }\r
492\r
493 private ArrayList<String> getInstantiation () {\r
494 ArrayList<String> Output = new ArrayList<String> ();\r
495\r
496 Output.add("/* SkuIdTable */");\r
497 Output.add("{");\r
498\r
499 if (al.size() == 0) {\r
500 Output.add("\t0");\r
501 }\r
502 \r
503 for (int index = 0; index < al.size(); index++) {\r
504 String str;\r
505\r
506 str = "/* " + alComment.get(index) + "*/ ";\r
507 str += "/* MaxSku */ ";\r
508\r
509\r
510 Integer[] ia = al.get(index);\r
511\r
512 str += "\t" + ia[0].toString() + ", ";\r
513 for (int index2 = 1; index2 < ia.length; index2++) {\r
514 str += ia[index2].toString();\r
515 if (!((index2 == ia.length - 1) && (index == al.size() - 1))) {\r
516 str += ", ";\r
517 }\r
518 }\r
519\r
520 Output.add(str);\r
521\r
522 }\r
523\r
524 Output.add("}");\r
525\r
526 return Output;\r
527 }\r
528\r
529 public int add (Token token) {\r
530\r
531 int index;\r
532 int pos;\r
533 \r
534 //\r
535 // Check if this SKU_ID Array is already in the table\r
536 //\r
537 pos = 0;\r
538 for (Object o: al) {\r
539 Integer [] s = (Integer[]) o;\r
540 boolean different = false;\r
541 if (s[0] == token.getSkuIdCount()) {\r
542 for (index = 1; index < s.length; index++) {\r
543 if (s[index] != token.skuData.get(index-1).id) {\r
544 different = true;\r
545 break;\r
546 }\r
547 }\r
548 } else {\r
549 different = true;\r
550 }\r
551 if (different) {\r
552 pos += s[0] + 1;\r
553 } else {\r
554 return pos;\r
555 }\r
556 }\r
557\r
558 Integer [] skuIds = new Integer[token.skuData.size() + 1];\r
559 skuIds[0] = new Integer(token.skuData.size());\r
560 for (index = 1; index < skuIds.length; index++) {\r
561 skuIds[index] = new Integer(token.skuData.get(index - 1).id);\r
562 }\r
563\r
564 index = len;\r
565\r
566 len += skuIds.length; \r
567 al.add(skuIds);\r
568 alComment.add(token.getPrimaryKeyString());\r
569\r
570 return index;\r
571 }\r
572\r
573}\r
574\r
575class LocalTokenNumberTable {\r
576 private ArrayList<String> al;\r
577 private ArrayList<String> alComment;\r
578 private String phase;\r
579 private int len;\r
580\r
581 public LocalTokenNumberTable (String phase) {\r
582 this.phase = phase;\r
583 al = new ArrayList<String>();\r
584 alComment = new ArrayList<String>();\r
585\r
586 len = 0;\r
587 }\r
588\r
589 public String getSizeMacro () {\r
590 return String.format(PcdDatabase.LocalTokenNumberTableSizeMacro, phase, getSize())\r
591 + String.format(PcdDatabase.LocalTokenNumberSizeMacro, phase, al.size());\r
592 }\r
593\r
594 public int getSize () {\r
595 return (al.size() == 0)? 1 : al.size();\r
596 }\r
597\r
598 public String getExistanceMacro () {\r
599 return String.format(PcdDatabase.DatabaseExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE");\r
600 }\r
601\r
602 public void genCode (ArrayList<CStructTypeDeclaration> declaList, HashMap<String, String> instTable, String phase) {\r
603 final String name = "LocalTokenNumberTable";\r
604 \r
605 CStructTypeDeclaration decl;\r
606 String cCode = "";\r
607\r
608 cCode += String.format(PcdDatabase.LocalTokenNumberTableDeclaration, phase); \r
609 decl = new CStructTypeDeclaration (\r
610 name,\r
611 4,\r
612 cCode,\r
613 true\r
614 ); \r
615 declaList.add(decl);\r
616\r
617 cCode = PcdDatabase.genInstantiationStr(getInstantiation());\r
618 instTable.put(name, cCode);\r
619 }\r
620\r
621 private ArrayList<String> getInstantiation () {\r
622 ArrayList<String> output = new ArrayList<String>();\r
623\r
624 output.add("/* LocalTokenNumberTable */");\r
625 output.add("{");\r
626\r
627 if (al.size() == 0) {\r
628 output.add("\t0");\r
629 }\r
630 \r
631 for (int index = 0; index < al.size(); index++) {\r
632 String str;\r
633\r
634 str = "\t" + (String)al.get(index);\r
635\r
636 str += " /* " + alComment.get(index) + " */ ";\r
637\r
638\r
639 if (index != (al.size() - 1)) {\r
640 str += ",";\r
641 }\r
642\r
643 output.add(str);\r
644\r
645 }\r
646\r
647 output.add("}");\r
648\r
649 return output;\r
650 }\r
651\r
652 public int add (Token token) {\r
653 int index = len;\r
654 String str;\r
655\r
656 len++; \r
657\r
658 str = String.format(PcdDatabase.offsetOfStrTemplate, phase, token.hasDefaultValue() ? "Init" : "Uninit", token.getPrimaryKeyString());\r
659\r
660 if (token.isUnicodeStringType()) {\r
661 str += " | PCD_TYPE_STRING";\r
662 }\r
663\r
664 if (token.isSkuEnable()) {\r
665 str += " | PCD_TYPE_SKU_ENABLED";\r
666 }\r
667\r
668 if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.HII_TYPE) {\r
669 str += " | PCD_TYPE_HII";\r
670 }\r
671\r
672 if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.VPD_TYPE) {\r
673 str += " | PCD_TYPE_VPD";\r
674 }\r
675 \r
676 al.add(str);\r
677 alComment.add(token.getPrimaryKeyString());\r
678\r
679 return index;\r
680 }\r
681}\r
682\r
683/**\r
684 ExMapTable \r
685 \r
686 This class is used to store the table of mapping information\r
687 between DynamicEX ID pair(Guid, TokenNumber) and\r
688 the local token number assigned by PcdDatabase class.\r
689**/\r
690class ExMapTable {\r
691\r
692 /**\r
693 ExTriplet \r
694 \r
695 This class is used to store the mapping information\r
696 between DynamicEX ID pair(Guid, TokenNumber) and\r
697 the local token number assigned by PcdDatabase class.\r
698 **/\r
699 class ExTriplet {\r
700 public Integer guidTableIdx;\r
701 public Long exTokenNumber;\r
702 public Long localTokenIdx;\r
703 \r
704 public ExTriplet (int guidTableIdx, long exTokenNumber, long localTokenIdx) {\r
705 this.guidTableIdx = new Integer(guidTableIdx);\r
706 this.exTokenNumber = new Long(exTokenNumber);\r
707 this.localTokenIdx = new Long(localTokenIdx);\r
708 }\r
709 }\r
710\r
711 private ArrayList<ExTriplet> al;\r
712 private ArrayList<String> alComment;\r
713 private String phase;\r
714 private int len;\r
715 private int bodyLineNum;\r
716 \r
717 public ExMapTable (String phase) {\r
718 this.phase = phase;\r
719 al = new ArrayList<ExTriplet>();\r
720 alComment = new ArrayList<String>();\r
721 bodyLineNum = 0;\r
722 len = 0;\r
723 }\r
724\r
725 public String getSizeMacro () {\r
726 return String.format(PcdDatabase.ExMapTableSizeMacro, phase, getTableLen())\r
727 + String.format(PcdDatabase.ExTokenNumber, phase, al.size());\r
728 }\r
729\r
730 public String getExistanceMacro () {\r
731 return String.format(PcdDatabase.ExMapTableExistenceMacro, phase, (al.size() == 0)? "TRUE":"FALSE");\r
732 }\r
733\r
734 public void genCode (ArrayList<CStructTypeDeclaration> declaList, HashMap<String, String> instTable, String phase) {\r
735 final String exMapTableName = "ExMapTable";\r
736 \r
737 sortTable();\r
738 \r
739 CStructTypeDeclaration decl;\r
740 String cCode = "";\r
741\r
742 cCode += String.format(PcdDatabase.ExMapTableDeclaration, phase); \r
743 decl = new CStructTypeDeclaration (\r
744 exMapTableName,\r
745 4,\r
746 cCode,\r
747 true\r
748 ); \r
749 declaList.add(decl);\r
750\r
751\r
752 cCode = PcdDatabase.genInstantiationStr(getInstantiation());\r
753 instTable.put(exMapTableName, cCode);\r
754 }\r
755 \r
756 private ArrayList<String> getInstantiation () {\r
757 ArrayList<String> Output = new ArrayList<String>();\r
758\r
759 Output.add("/* ExMapTable */");\r
760 Output.add("{");\r
761 if (al.size() == 0) {\r
762 Output.add("\t{0, 0, 0}");\r
763 }\r
764 \r
765 int index;\r
766 for (index = 0; index < al.size(); index++) {\r
767 String str;\r
768\r
769 ExTriplet e = (ExTriplet)al.get(index);\r
770\r
771 str = "\t" + "{ " + String.format("0x%08X", e.exTokenNumber) + ", ";\r
772 str += e.localTokenIdx.toString() + ", ";\r
773 str += e.guidTableIdx.toString();\r
774\r
775 str += "}" + " /* " + alComment.get(index) + " */" ;\r
776\r
777 if (index != al.size() - 1) {\r
778 str += ",";\r
779 }\r
780\r
781 Output.add(str);\r
782 bodyLineNum++;\r
783\r
784 }\r
785\r
786 Output.add("}");\r
787\r
788 return Output;\r
789 }\r
790\r
791 public int add (int localTokenIdx, long exTokenNum, int guidTableIdx, String name) {\r
792 int index = len;\r
793\r
794 len++; \r
795 al.add(new ExTriplet(guidTableIdx, exTokenNum, localTokenIdx));\r
796 alComment.add(name);\r
797\r
798 return index;\r
799 }\r
800\r
801 private int getTableLen () {\r
802 return al.size() == 0 ? 1 : al.size();\r
803 }\r
804\r
805 //\r
806 // To simplify the algorithm for GetNextToken and GetNextTokenSpace in\r
807 // PCD PEIM/Driver, we need to sort the ExMapTable according to the\r
808 // following order:\r
809 // 1) ExGuid\r
810 // 2) ExTokenNumber\r
811 // \r
812 class ExTripletComp implements Comparator<ExTriplet> {\r
813 public int compare (ExTriplet a, ExTriplet b) {\r
814 if (a.guidTableIdx == b.guidTableIdx ) {\r
815 //\r
816 // exTokenNumber is long, we can't use simple substraction.\r
817 //\r
818 if (a.exTokenNumber > b.exTokenNumber) {\r
819 return 1;\r
820 } else if (a.exTokenNumber == b.exTokenNumber) {\r
821 return 0;\r
822 } else {\r
823 return -1;\r
824 }\r
825 }\r
826 \r
827 return a.guidTableIdx - b.guidTableIdx;\r
828 }\r
829 }\r
830\r
831 private void sortTable () {\r
832 java.util.Comparator<ExTriplet> comparator = new ExTripletComp();\r
833 java.util.Collections.sort(al, comparator);\r
834 }\r
835}\r
836\r
837/**\r
838 PcdDatabase \r
839 \r
840 This class is used to generate C code for Autogen.h and Autogen.c of\r
841 a PCD service DXE driver and PCD service PEIM.\r
842**/\r
843class PcdDatabase {\r
844\r
845 private final static int SkuHeadAlignmentSize = 4;\r
846 private final String newLine = "\r\n";\r
847 private final String commaNewLine = ",\r\n";\r
848 private final String tab = "\t";\r
849 public final static String ExMapTableDeclaration = "DYNAMICEX_MAPPING ExMapTable[%s_EXMAPPING_TABLE_SIZE];\r\n";\r
850 public final static String GuidTableDeclaration = "EFI_GUID GuidTable[%s_GUID_TABLE_SIZE];\r\n";\r
851 public final static String LocalTokenNumberTableDeclaration = "UINT32 LocalTokenNumberTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";\r
852 public final static String StringTableDeclaration = "UINT16 StringTable[%s_STRING_TABLE_SIZE];\r\n";\r
853 public final static String SizeTableDeclaration = "UINT16 SizeTable[%s_LOCAL_TOKEN_NUMBER_TABLE_SIZE];\r\n";\r
854 public final static String SkuIdTableDeclaration = "UINT8 SkuIdTable[%s_SKUID_TABLE_SIZE];\r\n";\r
855\r
856\r
857 public final static String ExMapTableSizeMacro = "#define %s_EXMAPPING_TABLE_SIZE %d\r\n";\r
858 public final static String ExTokenNumber = "#define %s_EX_TOKEN_NUMBER %d\r\n";\r
859 public final static String GuidTableSizeMacro = "#define %s_GUID_TABLE_SIZE %d\r\n"; \r
860 public final static String LocalTokenNumberTableSizeMacro = "#define %s_LOCAL_TOKEN_NUMBER_TABLE_SIZE %d\r\n";\r
861 public final static String LocalTokenNumberSizeMacro = "#define %s_LOCAL_TOKEN_NUMBER %d\r\n";\r
862 public final static String StringTableSizeMacro = "#define %s_STRING_TABLE_SIZE %d\r\n";\r
863 public final static String SkuIdTableSizeMacro = "#define %s_SKUID_TABLE_SIZE %d\r\n";\r
864\r
865\r
866 public final static String ExMapTableExistenceMacro = "#define %s_EXMAP_TABLE_EMPTY %s\r\n"; \r
867 public final static String GuidTableExistenceMacro = "#define %s_GUID_TABLE_EMPTY %s\r\n";\r
868 public final static String DatabaseExistenceMacro = "#define %s_DATABASE_EMPTY %s\r\n";\r
869 public final static String StringTableExistenceMacro = "#define %s_STRING_TABLE_EMPTY %s\r\n";\r
870 public final static String SkuTableExistenceMacro = "#define %s_SKUID_TABLE_EMPTY %s\r\n";\r
871\r
872 public final static String offsetOfSkuHeadStrTemplate = "offsetof(%s_PCD_DATABASE, %s.%s_SkuDataTable)";\r
873 public final static String offsetOfVariableEnabledDefault = "offsetof(%s_PCD_DATABASE, %s.%s_VariableDefault_%d)";\r
874 public final static String offsetOfStrTemplate = "offsetof(%s_PCD_DATABASE, %s.%s)";\r
875 \r
876 private final static String skuDataTableTemplate = "SkuDataTable";\r
877\r
878\r
879 private StringTable stringTable;\r
880 private GuidTable guidTable;\r
881 private LocalTokenNumberTable localTokenNumberTable;\r
882 private SkuIdTable skuIdTable;\r
883 private SizeTable sizeTable;\r
884 private ExMapTable exMapTable;\r
885\r
886 private ArrayList<Token> alTokens;\r
887 private String phase;\r
888 private int assignedTokenNumber;\r
889 \r
890 //\r
891 // Use two class global variable to store\r
892 // temperary \r
893 //\r
894 private String privateGlobalName;\r
895 private String privateGlobalCCode;\r
896 //\r
897 // After Major changes done to the PCD\r
898 // database generation class PcdDatabase\r
899 // Please increment the version and please\r
900 // also update the version number in PCD\r
901 // service PEIM and DXE driver accordingly.\r
902 //\r
903 private final int version = 2;\r
904\r
905 private String hString;\r
906 private String cString;\r
907\r
908 /**\r
909 Constructor for PcdDatabase class. \r
910 \r
911 <p>We have two PCD dynamic(ex) database for the Framework implementation. One\r
912 for PEI phase and the other for DXE phase. </p>\r
913 \r
914 @param alTokens A ArrayList of Dynamic(EX) PCD entry.\r
915 @param exePhase The phase to generate PCD database for: valid input\r
916 is "PEI" or "DXE".\r
917 @param startLen The starting Local Token Number for the PCD database. For\r
918 PEI phase, the starting Local Token Number starts from 0.\r
919 For DXE phase, the starting Local Token Number starts\r
920 from the total number of PCD entry of PEI phase.\r
921 @return void\r
922 **/\r
923 public PcdDatabase (ArrayList<Token> alTokens, String exePhase, int startLen) {\r
924 phase = exePhase;\r
925\r
926 stringTable = new StringTable(phase);\r
927 guidTable = new GuidTable(phase);\r
928 localTokenNumberTable = new LocalTokenNumberTable(phase);\r
929 skuIdTable = new SkuIdTable(phase);\r
930 sizeTable = new SizeTable(phase);\r
931 exMapTable = new ExMapTable(phase); \r
932\r
933 //\r
934 // Local token number 0 is reserved for INVALID_TOKEN_NUMBER.\r
935 // So we will increment 1 for the startLen passed from the \r
936 // constructor.\r
937 //\r
938 assignedTokenNumber = startLen + 1;\r
939 this.alTokens = alTokens;\r
940 }\r
941\r
942 private void getNonExAndExTokens (ArrayList<Token> alTokens, List<Token> nexTokens, List<Token> exTokens) {\r
943 for (int i = 0; i < alTokens.size(); i++) {\r
944 Token t = (Token)alTokens.get(i);\r
945 if (t.isDynamicEx()) {\r
946 exTokens.add(t);\r
947 } else {\r
948 nexTokens.add(t);\r
949 }\r
950 }\r
951\r
952 return;\r
953 }\r
954\r
955 private int getDataTypeAlignmentSize (Token token) {\r
956 switch (token.datumType) {\r
957 case UINT8:\r
958 return 1;\r
959 case UINT16:\r
960 return 2;\r
961 case UINT32:\r
962 return 4;\r
963 case UINT64:\r
964 return 8;\r
965 case POINTER:\r
966 return 1;\r
967 case BOOLEAN:\r
968 return 1;\r
969 default:\r
970 return 1;\r
971 }\r
972 }\r
973 \r
974 private int getHiiPtrTypeAlignmentSize(Token token) {\r
975 switch (token.datumType) {\r
976 case UINT8:\r
977 return 1;\r
978 case UINT16:\r
979 return 2;\r
980 case UINT32:\r
981 return 4;\r
982 case UINT64:\r
983 return 8;\r
984 case POINTER:\r
985 if (token.isHiiEnable()) {\r
986 if (token.isHiiDefaultValueUnicodeStringType()) {\r
987 return 2;\r
988 }\r
989 }\r
990 return 1;\r
991 case BOOLEAN:\r
992 return 1;\r
993 default:\r
994 return 1;\r
995 }\r
996 }\r
997 \r
998 private int getAlignmentSize (Token token) {\r
999 if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.HII_TYPE) {\r
1000 return 2;\r
1001 }\r
1002\r
1003 if (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.VPD_TYPE) {\r
1004 return 4;\r
1005 }\r
1006\r
1007 if (token.isUnicodeStringType()) {\r
1008 return 2;\r
1009 }\r
1010 \r
1011 return getDataTypeAlignmentSize(token);\r
1012 }\r
1013\r
1014 public String getCString () {\r
1015 return cString;\r
1016 }\r
1017\r
1018 public String getHString () {\r
1019 return hString;\r
1020 }\r
1021 \r
1022 private void genCodeWorker(Token t,\r
1023 ArrayList<CStructTypeDeclaration> declaList,\r
1024 HashMap<String, String> instTable, String phase)\r
1025 throws EntityException {\r
1026\r
1027 CStructTypeDeclaration decl;\r
1028\r
1029 //\r
1030 // Insert SKU_HEAD if isSkuEnable is true\r
1031 //\r
1032 if (t.isSkuEnable()) {\r
1033 int tableIdx;\r
1034 tableIdx = skuIdTable.add(t);\r
1035 decl = new CStructTypeDeclaration(t.getPrimaryKeyString(),\r
1036 SkuHeadAlignmentSize, getSkuEnabledTypeDeclaration(t), true);\r
1037 declaList.add(decl);\r
1038 instTable.put(t.getPrimaryKeyString(),\r
1039 getSkuEnabledTypeInstantiaion(t, tableIdx));\r
1040 }\r
1041\r
1042 //\r
1043 // Insert PCD_ENTRY declaration and instantiation\r
1044 //\r
1045 getCDeclarationString(t);\r
1046\r
1047 decl = new CStructTypeDeclaration(privateGlobalName,\r
1048 getAlignmentSize(t), privateGlobalCCode, t.hasDefaultValue());\r
1049 declaList.add(decl);\r
1050\r
1051 if (t.hasDefaultValue()) {\r
1052 instTable.put(privateGlobalName, \r
1053 getTypeInstantiation(t, declaList, instTable, phase)\r
1054 );\r
1055 }\r
1056\r
1057 }\r
1058\r
1059 private void ProcessTokens (List<Token> tokens, \r
1060 ArrayList<CStructTypeDeclaration> cStructDeclList,\r
1061 HashMap<String, String> cStructInstTable,\r
1062 String phase\r
1063 ) \r
1064 throws EntityException {\r
1065 \r
1066 for (int idx = 0; idx < tokens.size(); idx++) {\r
1067 Token t = tokens.get(idx);\r
1068 \r
1069 genCodeWorker (t, cStructDeclList, cStructInstTable, phase);\r
1070 \r
1071 sizeTable.add(t);\r
1072 localTokenNumberTable.add(t);\r
1073 t.tokenNumber = assignedTokenNumber++;\r
1074 \r
1075 //\r
1076 // Add a mapping if this dynamic PCD entry is a EX type\r
1077 //\r
1078 if (t.isDynamicEx()) {\r
1079 exMapTable.add((int)t.tokenNumber, \r
1080 t.dynamicExTokenNumber, \r
1081 guidTable.add(t.tokenSpaceName, t.getPrimaryKeyString()), \r
1082 t.getPrimaryKeyString()\r
1083 );\r
1084 }\r
1085 }\r
1086\r
1087 }\r
1088 \r
1089 public void genCode () throws EntityException {\r
1090 \r
1091 ArrayList<CStructTypeDeclaration> cStructDeclList = new ArrayList<CStructTypeDeclaration>();\r
1092 HashMap<String, String> cStructInstTable = new HashMap<String, String>();\r
1093 \r
1094 List<Token> nexTokens = new ArrayList<Token> ();\r
1095 List<Token> exTokens = new ArrayList<Token> ();\r
1096\r
1097 getNonExAndExTokens (alTokens, nexTokens, exTokens);\r
1098\r
1099 //\r
1100 // We have to process Non-Ex type PCD entry first. The reason is\r
1101 // that our optimization assumes that the Token Number of Non-Ex \r
1102 // PCD entry start from 1 (for PEI phase) and grows continously upwards.\r
1103 // \r
1104 // EX type token number starts from the last Non-EX PCD entry and\r
1105 // grows continously upwards.\r
1106 //\r
1107 ProcessTokens (nexTokens, cStructDeclList, cStructInstTable, phase);\r
1108 ProcessTokens (exTokens, cStructDeclList, cStructInstTable, phase);\r
1109 \r
1110 stringTable.genCode(cStructDeclList, cStructInstTable);\r
1111 skuIdTable.genCode(cStructDeclList, cStructInstTable, phase);\r
1112 exMapTable.genCode(cStructDeclList, cStructInstTable, phase);\r
1113 localTokenNumberTable.genCode(cStructDeclList, cStructInstTable, phase);\r
1114 sizeTable.genCode(cStructDeclList, cStructInstTable, phase);\r
1115 guidTable.genCode(cStructDeclList, cStructInstTable, phase);\r
1116 \r
1117 hString = genCMacroCode ();\r
1118 \r
1119 HashMap <String, String> result;\r
1120 \r
1121 result = genCStructCode(cStructDeclList, \r
1122 cStructInstTable, \r
1123 phase\r
1124 );\r
1125 \r
1126 hString += result.get("initDeclStr");\r
1127 hString += result.get("uninitDeclStr");\r
1128 \r
1129 hString += String.format("#define PCD_%s_SERVICE_DRIVER_VERSION %d", phase, version);\r
1130 \r
1131 cString = newLine + newLine + result.get("initInstStr");\r
1132 \r
1133 }\r
1134 \r
1135 private String genCMacroCode () {\r
1136 String macroStr = "";\r
1137\r
1138 //\r
1139 // Generate size info Macro for all Tables\r
1140 //\r
1141 macroStr += guidTable.getSizeMacro();\r
1142 macroStr += stringTable.getSizeMacro();\r
1143 macroStr += skuIdTable.getSizeMacro();\r
1144 macroStr += localTokenNumberTable.getSizeMacro();\r
1145 macroStr += exMapTable.getSizeMacro();\r
1146\r
1147 //\r
1148 // Generate existance info Macro for all Tables\r
1149 //\r
1150 macroStr += guidTable.getExistanceMacro();\r
1151 macroStr += stringTable.getExistanceMacro();\r
1152 macroStr += skuIdTable.getExistanceMacro();\r
1153 macroStr += localTokenNumberTable.getExistanceMacro();\r
1154 macroStr += exMapTable.getExistanceMacro();\r
1155\r
1156 macroStr += newLine;\r
1157 \r
1158 return macroStr;\r
1159 }\r
1160 \r
1161 private HashMap <String, String> genCStructCode(\r
1162 ArrayList<CStructTypeDeclaration> declaList, \r
1163 HashMap<String, String> instTable, \r
1164 String phase\r
1165 ) {\r
1166 \r
1167 int i;\r
1168 HashMap <String, String> result = new HashMap<String, String>();\r
1169 HashMap <Integer, ArrayList<String>> alignmentInitDecl = new HashMap<Integer, ArrayList<String>>();\r
1170 HashMap <Integer, ArrayList<String>> alignmentUninitDecl = new HashMap<Integer, ArrayList<String>>();\r
1171 HashMap <Integer, ArrayList<String>> alignmentInitInst = new HashMap<Integer, ArrayList<String>>();\r
1172 \r
1173 //\r
1174 // Initialize the storage for each alignment\r
1175 //\r
1176 for (i = 8; i > 0; i>>=1) {\r
1177 alignmentInitDecl.put(new Integer(i), new ArrayList<String>());\r
1178 alignmentInitInst.put(new Integer(i), new ArrayList<String>());\r
1179 alignmentUninitDecl.put(new Integer(i), new ArrayList<String>());\r
1180 }\r
1181 \r
1182 String initDeclStr = "typedef struct {" + newLine;\r
1183 String initInstStr = String.format("%s_PCD_DATABASE_INIT g%sPcdDbInit = { ", phase.toUpperCase(), phase.toUpperCase()) + newLine;\r
1184 String uninitDeclStr = "typedef struct {" + newLine;\r
1185\r
1186 //\r
1187 // Sort all C declaration and instantiation base on Alignment Size \r
1188 //\r
1189 for (Object d : declaList) {\r
1190 CStructTypeDeclaration decl = (CStructTypeDeclaration) d;\r
1191 \r
1192 if (decl.initTable) {\r
1193 alignmentInitDecl.get(new Integer(decl.alignmentSize)).add(decl.cCode);\r
1194 alignmentInitInst.get(new Integer(decl.alignmentSize)).add(instTable.get(decl.key));\r
1195 } else {\r
1196 alignmentUninitDecl.get(new Integer(decl.alignmentSize)).add(decl.cCode);\r
1197 }\r
1198 }\r
1199\r
1200 //\r
1201 // Generate code for every alignment size\r
1202 //\r
1203 boolean uinitDatabaseEmpty = true;\r
1204 for (int align = 8; align > 0; align >>= 1) {\r
1205 ArrayList<String> declaListBasedOnAlignment = alignmentInitDecl.get(new Integer(align));\r
1206 ArrayList<String> instListBasedOnAlignment = alignmentInitInst.get(new Integer(align));\r
1207 for (i = 0; i < declaListBasedOnAlignment.size(); i++) {\r
1208 initDeclStr += tab + declaListBasedOnAlignment.get(i);\r
1209 initInstStr += tab + instListBasedOnAlignment.get(i);\r
1210 \r
1211 //\r
1212 // We made a assumption that both PEI_PCD_DATABASE and DXE_PCD_DATABASE\r
1213 // has a least one data memember with alignment size of 1. So we can\r
1214 // remove the last "," in the C structure instantiation string. Luckily,\r
1215 // this is true as both data structure has SKUID_TABLE anyway.\r
1216 //\r
1217 if ((align == 1) && (i == declaListBasedOnAlignment.size() - 1)) {\r
1218 initInstStr += newLine;\r
1219 } else {\r
1220 initInstStr += commaNewLine;\r
1221 }\r
1222 }\r
1223 \r
1224 declaListBasedOnAlignment = alignmentUninitDecl.get(new Integer(align));\r
1225 \r
1226 if (declaListBasedOnAlignment.size() != 0) {\r
1227 uinitDatabaseEmpty = false;\r
1228 }\r
1229 \r
1230 for (Object d : declaListBasedOnAlignment) {\r
1231 String s = (String)d;\r
1232 uninitDeclStr += tab + s;\r
1233 }\r
1234 }\r
1235 \r
1236 if (uinitDatabaseEmpty) {\r
1237 uninitDeclStr += tab + String.format("%-20sdummy; /* PCD_DATABASE_UNINIT is emptry */\r\n", "UINT8");\r
1238 }\r
1239 \r
1240 initDeclStr += String.format("} %s_PCD_DATABASE_INIT;", phase) + newLine + newLine;\r
1241 initInstStr += "};" + newLine;\r
1242 uninitDeclStr += String.format("} %s_PCD_DATABASE_UNINIT;", phase) + newLine + newLine;\r
1243 \r
1244 result.put("initDeclStr", initDeclStr);\r
1245 result.put("initInstStr", initInstStr);\r
1246 result.put("uninitDeclStr", uninitDeclStr);\r
1247\r
1248 return result;\r
1249 }\r
1250\r
1251 public static String genInstantiationStr (ArrayList<String> alStr) {\r
1252 String str = "";\r
1253 for (int i = 0; i< alStr.size(); i++) {\r
1254 if (i != 0) {\r
1255 str += "\t";\r
1256 }\r
1257 str += alStr.get(i);\r
1258 if (i != alStr.size() - 1) {\r
1259 str += "\r\n";\r
1260 }\r
1261 }\r
1262\r
1263 return str;\r
1264 }\r
1265\r
1266 private String getSkuEnabledTypeDeclaration (Token token) {\r
1267 return String.format("%-20s%s;\r\n", "SKU_HEAD", token.getPrimaryKeyString());\r
1268 }\r
1269\r
1270 private String getSkuEnabledTypeInstantiaion (Token token, int SkuTableIdx) {\r
1271\r
1272 String offsetof = String.format(PcdDatabase.offsetOfSkuHeadStrTemplate, phase, token.hasDefaultValue()? "Init" : "Uninit", token.getPrimaryKeyString());\r
1273 return String.format("{ %s, %d } /* SKU_ENABLED: %s */", offsetof, SkuTableIdx, token.getPrimaryKeyString());\r
1274 }\r
1275\r
1276 private String getDataTypeInstantiationForVariableDefault (Token token, String cName, int skuId) {\r
1277 return String.format("%s /* %s */", token.skuData.get(skuId).value.hiiDefaultValue, cName);\r
1278 }\r
1279\r
1280 private String getCType (Token t) \r
1281 throws EntityException {\r
1282 \r
1283 if (t.isHiiEnable()) {\r
1284 return "VARIABLE_HEAD";\r
1285 }\r
1286 \r
1287 if (t.isVpdEnable()) {\r
1288 return "VPD_HEAD";\r
1289 }\r
1290 \r
1291 if (t.isUnicodeStringType()) {\r
1292 return "STRING_HEAD";\r
1293 }\r
1294 \r
1295 switch (t.datumType) {\r
1296 case UINT64:\r
1297 return "UINT64";\r
1298 case UINT32:\r
1299 return "UINT32";\r
1300 case UINT16:\r
1301 return "UINT16";\r
1302 case UINT8:\r
1303 return "UINT8";\r
1304 case BOOLEAN:\r
1305 return "BOOLEAN";\r
1306 case POINTER:\r
1307 return "UINT8";\r
1308 default:\r
1309 throw new EntityException("Unknown type in getDataTypeCDeclaration");\r
1310 }\r
1311 }\r
1312 \r
1313 private void getCDeclarationString(Token t) \r
1314 throws EntityException {\r
1315 \r
1316 if (t.isSkuEnable()) {\r
1317 privateGlobalName = String.format("%s_%s", t.getPrimaryKeyString(), skuDataTableTemplate);\r
1318 } else {\r
1319 privateGlobalName = t.getPrimaryKeyString();\r
1320 }\r
1321\r
1322 String type = getCType(t);\r
1323 if ((t.datumType == Token.DATUM_TYPE.POINTER) && (!t.isHiiEnable())) {\r
1324 int bufferSize;\r
1325 if (t.isASCIIStringType()) {\r
1326 //\r
1327 // Build tool will add a NULL string at the end of the ASCII string\r
1328 //\r
1329 bufferSize = t.datumSize + 1;\r
1330 } else {\r
1331 bufferSize = t.datumSize;\r
1332 }\r
1333 privateGlobalCCode = String.format("%-20s%s[%d][%d];\r\n", type, privateGlobalName, t.getSkuIdCount(), bufferSize);\r
1334 } else {\r
1335 privateGlobalCCode = String.format("%-20s%s[%d];\r\n", type, privateGlobalName, t.getSkuIdCount());\r
1336 }\r
1337 }\r
1338 \r
1339 private String getDataTypeDeclarationForVariableDefault (Token token, String cName, int skuId) \r
1340 throws EntityException {\r
1341\r
1342 String typeStr;\r
1343\r
1344 if (token.datumType == Token.DATUM_TYPE.UINT8) {\r
1345 typeStr = "UINT8";\r
1346 } else if (token.datumType == Token.DATUM_TYPE.UINT16) {\r
1347 typeStr = "UINT16";\r
1348 } else if (token.datumType == Token.DATUM_TYPE.UINT32) {\r
1349 typeStr = "UINT32";\r
1350 } else if (token.datumType == Token.DATUM_TYPE.UINT64) {\r
1351 typeStr = "UINT64";\r
1352 } else if (token.datumType == Token.DATUM_TYPE.BOOLEAN) {\r
1353 typeStr = "BOOLEAN";\r
1354 } else if (token.datumType == Token.DATUM_TYPE.POINTER) {\r
1355 int size;\r
1356 if (token.isHiiDefaultValueUnicodeStringType()) {\r
1357 typeStr = "UINT16";\r
1358 //\r
1359 // Include the NULL charactor\r
1360 //\r
1361 size = token.datumSize / 2 + 1;\r
1362 } else {\r
1363 typeStr = "UINT8";\r
1364 if (token.isHiiDefaultValueASCIIStringType()) {\r
1365 //\r
1366 // Include the NULL charactor\r
1367 //\r
1368 size = token.datumSize + 1;\r
1369 } else {\r
1370 size = token.datumSize;\r
1371 }\r
1372 }\r
1373 return String.format("%-20s%s[%d];\r\n", typeStr, cName, size);\r
1374 } else {\r
1375 throw new EntityException("Unknown DATUM_TYPE type in when generating code for VARIABLE_ENABLED PCD entry");\r
1376 }\r
1377\r
1378 return String.format("%-20s%s;\r\n", typeStr, cName);\r
1379 }\r
1380 \r
1381 private String getTypeInstantiation (Token t, ArrayList<CStructTypeDeclaration> declaList, HashMap<String, String> instTable, String phase) throws EntityException {\r
1382 \r
1383 int i;\r
1384\r
1385 String s;\r
1386 s = String.format("/* %s */", t.getPrimaryKeyString()) + newLine;\r
1387 s += tab + "{" + newLine;\r
1388\r
1389 for (i = 0; i < t.skuData.size(); i++) {\r
1390 if (t.isUnicodeStringType()) {\r
1391 s += tab + tab + String.format("{ %d }", stringTable.add(t.skuData.get(i).value.value, t));\r
1392 } else if (t.isHiiEnable()) {\r
1393 /* VPD_HEAD definition\r
1394 typedef struct {\r
1395 UINT16 GuidTableIndex; // Offset in Guid Table in units of GUID.\r
1396 UINT16 StringIndex; // Offset in String Table in units of UINT16.\r
1397 UINT16 Offset; // Offset in Variable\r
1398 UINT16 DefaultValueOffset; // Offset of the Default Value\r
1399 } VARIABLE_HEAD ;\r
1400 */\r
1401 String variableDefaultName = String.format("%s_VariableDefault_%d", t.getPrimaryKeyString(), i); \r
1402 \r
1403 s += tab + tab + String.format("{ %d, %d, %s, %s }", guidTable.add(t.skuData.get(i).value.variableGuid, t.getPrimaryKeyString()),\r
1404 stringTable.add(t.skuData.get(i).value.getStringOfVariableName(), t),\r
1405 t.skuData.get(i).value.variableOffset,\r
1406 String.format("offsetof(%s_PCD_DATABASE, Init.%s)", phase, variableDefaultName)\r
1407 );\r
1408 //\r
1409 // We need to support the default value, so we add the declaration and\r
1410 // the instantiation for the default value.\r
1411 //\r
1412 CStructTypeDeclaration decl = new CStructTypeDeclaration (variableDefaultName,\r
1413 getHiiPtrTypeAlignmentSize(t),\r
1414 getDataTypeDeclarationForVariableDefault(t, variableDefaultName, i),\r
1415 true\r
1416 ); \r
1417 declaList.add(decl);\r
1418 instTable.put(variableDefaultName, getDataTypeInstantiationForVariableDefault (t, variableDefaultName, i));\r
1419 } else if (t.isVpdEnable()) {\r
1420 /* typedef struct {\r
1421 UINT32 Offset;\r
1422 } VPD_HEAD;\r
1423 */\r
1424 s += tab + tab + String.format("{ %s }", t.skuData.get(i).value.vpdOffset);\r
1425 } else {\r
1426 if (t.isByteStreamType()) {\r
1427 //\r
1428 // Byte stream type input has their own "{" "}", so we won't help to insert.\r
1429 //\r
1430 s += tab + tab + String.format(" %s ", t.skuData.get(i).value.value);\r
1431 } else {\r
1432 s += tab + tab + String.format("{ %s }", t.skuData.get(i).value.value);\r
1433 }\r
1434 }\r
1435 \r
1436 if (i != t.skuData.size() - 1) {\r
1437 s += commaNewLine;\r
1438 } else {\r
1439 s += newLine;\r
1440 }\r
1441\r
1442 }\r
1443 \r
1444 s += tab + "}";\r
1445 \r
1446 return s;\r
1447 }\r
1448 \r
1449 public static String getPcdDatabaseCommonDefinitions () \r
1450 throws EntityException {\r
1451\r
1452 String retStr = "";\r
1453 try {\r
1454 File file = new File(GlobalData.getWorkspacePath() + File.separator + \r
1455 "Tools" + File.separator + \r
1456 "Conf" + File.separator +\r
1457 "Pcd" + File.separator +\r
1458 "PcdDatabaseCommonDefinitions.sample");\r
1459 FileReader reader = new FileReader(file);\r
1460 BufferedReader in = new BufferedReader(reader);\r
1461 String str;\r
1462 while ((str = in.readLine()) != null) {\r
1463 retStr = retStr +"\r\n" + str;\r
1464 }\r
1465 } catch (Exception ex) {\r
1466 throw new EntityException("Fatal error when generating PcdDatabase Common Definitions");\r
1467 }\r
1468\r
1469 return retStr;\r
1470 }\r
1471\r
1472 public static String getPcdDxeDatabaseDefinitions () \r
1473 throws EntityException {\r
1474\r
1475 String retStr = "";\r
1476 try {\r
1477 File file = new File(GlobalData.getWorkspacePath() + File.separator + \r
1478 "Tools" + File.separator + \r
1479 "Conf" + File.separator +\r
1480 "Pcd" + File.separator +\r
1481 "PcdDatabaseDxeDefinitions.sample");\r
1482 FileReader reader = new FileReader(file);\r
1483 BufferedReader in = new BufferedReader(reader);\r
1484 String str;\r
1485 while ((str = in.readLine()) != null) {\r
1486 retStr = retStr +"\r\n" + str;\r
1487 }\r
1488 } catch (Exception ex) {\r
1489 throw new EntityException("Fatal error when generating PcdDatabase Dxe Definitions");\r
1490 }\r
1491\r
1492 return retStr;\r
1493 }\r
1494\r
1495 public static String getPcdPeiDatabaseDefinitions () \r
1496 throws EntityException {\r
1497\r
1498 String retStr = "";\r
1499 try {\r
1500 File file = new File(GlobalData.getWorkspacePath() + File.separator + \r
1501 "Tools" + File.separator + \r
1502 "Conf" + File.separator +\r
1503 "Pcd" + File.separator +\r
1504 "PcdDatabasePeiDefinitions.sample");\r
1505 FileReader reader = new FileReader(file);\r
1506 BufferedReader in = new BufferedReader(reader);\r
1507 String str;\r
1508 while ((str = in.readLine()) != null) {\r
1509 retStr = retStr +"\r\n" + str;\r
1510 }\r
1511 } catch (Exception ex) {\r
1512 throw new EntityException("Fatal error when generating PcdDatabase Pei Definitions");\r
1513 }\r
1514\r
1515 return retStr;\r
1516 }\r
1517\r
1518}\r
1519\r
1520class ModuleInfo {\r
1521 private String type;\r
1522 private FpdModuleIdentification moduleId;\r
1523 private PcdBuildDefinitionDocument.PcdBuildDefinition pcdBuildDef;\r
1524 \r
1525 \r
1526\r
1527 public ModuleInfo (FpdModuleIdentification moduleId, String type, XmlObject pcdDef) {\r
1528 this.moduleId = moduleId;\r
1529 this.type = type;\r
1530 this.pcdBuildDef = ((PcdBuildDefinitionDocument)pcdDef).getPcdBuildDefinition();\r
1531 }\r
1532 public String getModuleType (){\r
1533 return this.type;\r
1534 }\r
1535 public FpdModuleIdentification getModuleId (){\r
1536 return this.moduleId;\r
1537 }\r
1538 public PcdBuildDefinitionDocument.PcdBuildDefinition getPcdBuildDef(){\r
1539 return this.pcdBuildDef;\r
1540 }\r
1541}\r
1542\r
1543/** This action class is to collect PCD information from MSA, SPD, FPD xml file.\r
1544 This class will be used for wizard and build tools, So it can *not* inherit\r
1545 from buildAction or UIAction.\r
1546**/\r
1547public class CollectPCDAction {\r
1548 /// memoryDatabase hold all PCD information collected from SPD, MSA, FPD.\r
1549 private MemoryDatabaseManager dbManager;\r
1550\r
1551 /// Workspacepath hold the workspace information.\r
1552 private String workspacePath;\r
1553\r
1554 /// FPD file is the root file. \r
1555 private String fpdFilePath;\r
1556\r
1557 /// Message level for CollectPCDAction.\r
1558 private int originalMessageLevel;\r
1559\r
1560 /// Cache the fpd docment instance for private usage.\r
1561 private PlatformSurfaceAreaDocument fpdDocInstance;\r
1562 \r
1563 /// xmlObject name\r
1564 private static String xmlObjectName = "PcdBuildDefinition"; \r
1565 \r
1566 /**\r
1567 Set WorkspacePath parameter for this action class.\r
1568\r
1569 @param workspacePath parameter for this action\r
1570 **/\r
1571 public void setWorkspacePath(String workspacePath) {\r
1572 this.workspacePath = workspacePath;\r
1573 }\r
1574\r
1575 /**\r
1576 Set action message level for CollectPcdAction tool.\r
1577\r
1578 The message should be restored when this action exit.\r
1579\r
1580 @param actionMessageLevel parameter for this action\r
1581 **/\r
1582 public void setActionMessageLevel(int actionMessageLevel) {\r
1583 originalMessageLevel = ActionMessage.messageLevel;\r
1584 ActionMessage.messageLevel = actionMessageLevel;\r
1585 }\r
1586\r
1587 /**\r
1588 Set FPDFileName parameter for this action class.\r
1589\r
1590 @param fpdFilePath fpd file path\r
1591 **/\r
1592 public void setFPDFilePath(String fpdFilePath) {\r
1593 this.fpdFilePath = fpdFilePath;\r
1594 }\r
1595\r
1596 /**\r
1597 Common function interface for outer.\r
1598 \r
1599 @param workspacePath The path of workspace of current build or analysis.\r
1600 @param fpdFilePath The fpd file path of current build or analysis.\r
1601 @param messageLevel The message level for this Action.\r
1602 \r
1603 @throws Exception The exception of this function. Because it can *not* be predict\r
1604 where the action class will be used. So only Exception can be throw.\r
1605 \r
1606 **/\r
1607 public void perform(String workspacePath, String fpdFilePath, \r
1608 int messageLevel) throws Exception {\r
1609 setWorkspacePath(workspacePath);\r
1610 setFPDFilePath(fpdFilePath);\r
1611 setActionMessageLevel(messageLevel);\r
1612 checkParameter();\r
1613 execute();\r
1614 ActionMessage.messageLevel = originalMessageLevel;\r
1615 }\r
1616\r
1617 /**\r
1618 Core execution function for this action class.\r
1619 \r
1620 This function work flows will be:\r
1621 1) Collect and prepocess PCD information from FPD file, all PCD\r
1622 information will be stored into memory database.\r
1623 2) Generate 3 strings for\r
1624 a) All modules using Dynamic(Ex) PCD entry.(Token Number)\r
1625 b) PEI PCDDatabase (C Structure) for PCD Service PEIM.\r
1626 c) DXE PCD Database (C structure) for PCD Service DXE.\r
1627 \r
1628 \r
1629 @throws EntityException Exception indicate failed to execute this action.\r
1630 \r
1631 **/\r
1632 public void execute() throws EntityException {\r
1633 //\r
1634 // Get memoryDatabaseManager instance from GlobalData.\r
1635 // The memoryDatabaseManager should be initialized for whatever build\r
1636 // tools or wizard tools\r
1637 //\r
1638 if((dbManager = GlobalData.getPCDMemoryDBManager()) == null) {\r
1639 throw new EntityException("The instance of PCD memory database manager is null");\r
1640 }\r
1641\r
1642 //\r
1643 // Collect all PCD information defined in FPD file.\r
1644 // Evenry token defind in FPD will be created as an token into \r
1645 // memory database.\r
1646 //\r
1647 createTokenInDBFromFPD();\r
1648 \r
1649 //\r
1650 // Call Private function genPcdDatabaseSourceCode (void); ComponentTypeBsDriver\r
1651 // 1) Generate for PEI, DXE PCD DATABASE's definition and initialization.\r
1652 //\r
1653 genPcdDatabaseSourceCode ();\r
1654 \r
1655 }\r
1656\r
1657 /**\r
1658 This function generates source code for PCD Database.\r
1659 \r
1660 @param void\r
1661 @throws EntityException If the token does *not* exist in memory database.\r
1662\r
1663 **/\r
1664 private void genPcdDatabaseSourceCode()\r
1665 throws EntityException {\r
1666 String PcdCommonHeaderString = PcdDatabase.getPcdDatabaseCommonDefinitions ();\r
1667\r
1668 ArrayList<Token> alPei = new ArrayList<Token> ();\r
1669 ArrayList<Token> alDxe = new ArrayList<Token> ();\r
1670\r
1671 dbManager.getTwoPhaseDynamicRecordArray(alPei, alDxe);\r
1672 PcdDatabase pcdPeiDatabase = new PcdDatabase (alPei, "PEI", 0);\r
1673 pcdPeiDatabase.genCode();\r
1674 MemoryDatabaseManager.PcdPeimHString = PcdCommonHeaderString + pcdPeiDatabase.getHString()\r
1675 + PcdDatabase.getPcdPeiDatabaseDefinitions();\r
1676 MemoryDatabaseManager.PcdPeimCString = pcdPeiDatabase.getCString();\r
1677\r
1678 PcdDatabase pcdDxeDatabase = new PcdDatabase (alDxe, \r
1679 "DXE",\r
1680 alPei.size()\r
1681 );\r
1682 pcdDxeDatabase.genCode();\r
1683 MemoryDatabaseManager.PcdDxeHString = MemoryDatabaseManager.PcdPeimHString + pcdDxeDatabase.getHString()\r
1684 + PcdDatabase.getPcdDxeDatabaseDefinitions();\r
1685 MemoryDatabaseManager.PcdDxeCString = pcdDxeDatabase.getCString();\r
1686 }\r
1687\r
1688 /**\r
1689 Get component array from FPD.\r
1690 \r
1691 This function maybe provided by some Global class.\r
1692 \r
1693 @return List<ModuleInfo> the component array.\r
1694 \r
1695 */\r
1696 private List<ModuleInfo> getComponentsFromFPD() \r
1697 throws EntityException {\r
1698 List<ModuleInfo> allModules = new ArrayList<ModuleInfo>();\r
1699 ModuleInfo current = null;\r
1700 int index = 0;\r
1701 FrameworkModulesDocument.FrameworkModules fModules = null;\r
1702 ModuleSADocument.ModuleSA[] modules = null;\r
1703 HashMap<String, XmlObject> map = new HashMap<String, XmlObject>();\r
1704\r
1705 if (fpdDocInstance == null) {\r
1706 try {\r
1707 fpdDocInstance = (PlatformSurfaceAreaDocument)XmlObject.Factory.parse(new File(fpdFilePath));\r
1708 } catch(IOException ioE) {\r
1709 throw new EntityException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage());\r
1710 } catch(XmlException xmlE) {\r
1711 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage());\r
1712 }\r
1713\r
1714 }\r
1715\r
1716 Map<FpdModuleIdentification,XmlObject>pcdBuildDef = GlobalData.getFpdModuleSaXmlObject(CollectPCDAction.xmlObjectName);\r
1717 Set<FpdModuleIdentification> pcdBuildKeySet = pcdBuildDef.keySet();\r
1718 Iterator item = pcdBuildKeySet.iterator();\r
1719 while (item.hasNext()){\r
1720 FpdModuleIdentification id = (FpdModuleIdentification)item.next();\r
1721 allModules.add(new ModuleInfo(id, id.getModule().getModuleType(),pcdBuildDef.get(id))); \r
1722 }\r
1723 \r
1724 return allModules;\r
1725 }\r
1726\r
1727 /**\r
1728 Create token instance object into memory database, the token information\r
1729 comes for FPD file. Normally, FPD file will contain all token platform \r
1730 informations.\r
1731 \r
1732 @return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage.\r
1733 \r
1734 @throws EntityException Failed to parse FPD xml file.\r
1735 \r
1736 **/\r
1737 private void createTokenInDBFromFPD() \r
1738 throws EntityException {\r
1739 int index = 0;\r
1740 int index2 = 0;\r
1741 int pcdIndex = 0;\r
1742 List<PcdBuildDefinition.PcdData> pcdBuildDataArray = new ArrayList<PcdBuildDefinition.PcdData>();\r
1743 PcdBuildDefinition.PcdData pcdBuildData = null;\r
1744 Token token = null;\r
1745 List<ModuleInfo> modules = null;\r
1746 String primaryKey = null;\r
1747 String exceptionString = null;\r
1748 UsageInstance usageInstance = null;\r
1749 String primaryKey1 = null;\r
1750 String primaryKey2 = null;\r
1751 boolean isDuplicate = false;\r
1752 Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN;\r
1753 Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN;\r
1754 long tokenNumber = 0;\r
1755 String moduleName = null;\r
1756 String datum = null;\r
1757 int maxDatumSize = 0;\r
1758 String[] tokenSpaceStrRet = null;\r
1759\r
1760 //\r
1761 // ----------------------------------------------\r
1762 // 1), Get all <ModuleSA> from FPD file.\r
1763 // ----------------------------------------------\r
1764 // \r
1765 modules = getComponentsFromFPD();\r
1766\r
1767 if (modules == null) {\r
1768 throw new EntityException("[FPD file error] No modules in FPD file, Please check whether there are elements in <FrameworkModules> in FPD file!");\r
1769 }\r
1770\r
1771 //\r
1772 // -------------------------------------------------------------------\r
1773 // 2), Loop all modules to process <PcdBuildDeclarations> for each module.\r
1774 // -------------------------------------------------------------------\r
1775 // \r
1776 for (index = 0; index < modules.size(); index ++) {\r
1777 isDuplicate = false;\r
1778 for (index2 = 0; index2 < index; index2 ++) {\r
1779 //\r
1780 // BUGBUG: For transition schema, we can *not* get module's version from \r
1781 // <ModuleSAs>, It is work around code.\r
1782 // \r
1783 primaryKey1 = UsageInstance.getPrimaryKey(modules.get(index).getModuleId().getModule().getName(), \r
1784 null,\r
1785 null,\r
1786 null, \r
1787 modules.get(index).getModuleId().getArch(),\r
1788 null);\r
1789 primaryKey2 = UsageInstance.getPrimaryKey(modules.get(index2).getModuleId().getModule().getName(), \r
1790 null, \r
1791 null, \r
1792 null, \r
1793 modules.get(index2).getModuleId().getArch(), \r
1794 null);\r
1795 if (primaryKey1.equalsIgnoreCase(primaryKey2)) {\r
1796 isDuplicate = true;\r
1797 break;\r
1798 }\r
1799 }\r
1800\r
1801 if (isDuplicate) {\r
1802 continue;\r
1803 }\r
1804\r
1805 //\r
1806 // It is legal for a module does not contains ANY pcd build definitions.\r
1807 // \r
1808 if (modules.get(index).getPcdBuildDef() == null) {\r
1809 continue;\r
1810 }\r
1811 \r
1812 pcdBuildDataArray = modules.get(index).getPcdBuildDef().getPcdDataList();\r
1813\r
1814 moduleName = modules.get(index).getModuleId().getModule().getName();\r
1815\r
1816 //\r
1817 // ----------------------------------------------------------------------\r
1818 // 2.1), Loop all Pcd entry for a module and add it into memory database.\r
1819 // ----------------------------------------------------------------------\r
1820 // \r
1821 for (pcdIndex = 0; pcdIndex < pcdBuildDataArray.size(); pcdIndex ++) {\r
1822 pcdBuildData = pcdBuildDataArray.get(pcdIndex);\r
1823 \r
1824 try {\r
1825 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(pcdBuildData.getTokenSpaceGuidCName());\r
1826 } catch ( Exception e ) {\r
1827 throw new EntityException ("Faile get Guid for token " + pcdBuildData.getCName() + ":" + e.getMessage());\r
1828 }\r
1829\r
1830 if (tokenSpaceStrRet == null) {\r
1831 throw new EntityException ("Fail to get Token space guid for token" + pcdBuildData.getCName());\r
1832 } \r
1833\r
1834 primaryKey = Token.getPrimaryKeyString(pcdBuildData.getCName(),\r
1835 translateSchemaStringToUUID(tokenSpaceStrRet[1]));\r
1836 pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString());\r
1837 datumType = Token.getdatumTypeFromString(pcdBuildData.getDatumType().toString());\r
1838 tokenNumber = Long.decode(pcdBuildData.getToken().toString());\r
1839 if (pcdBuildData.getValue() != null) {\r
1840 datum = pcdBuildData.getValue().toString();\r
1841 } else {\r
1842 datum = null;\r
1843 }\r
1844 maxDatumSize = pcdBuildData.getMaxDatumSize();\r
1845\r
1846 if ((pcdType == Token.PCD_TYPE.FEATURE_FLAG) &&\r
1847 (datumType != Token.DATUM_TYPE.BOOLEAN)){\r
1848 exceptionString = String.format("[FPD file error] For PCD %s in module %s, the PCD type is FEATRUE_FLAG but "+\r
1849 "datum type of this PCD entry is not BOOLEAN!",\r
1850 pcdBuildData.getCName(),\r
1851 moduleName);\r
1852 throw new EntityException(exceptionString);\r
1853 }\r
1854\r
1855 //\r
1856 // -------------------------------------------------------------------------------------------\r
1857 // 2.1.1), Do some necessary checking work for FixedAtBuild, FeatureFlag and PatchableInModule\r
1858 // -------------------------------------------------------------------------------------------\r
1859 // \r
1860 if (!Token.isDynamic(pcdType)) {\r
1861 //\r
1862 // Value is required.\r
1863 // \r
1864 if (datum == null) {\r
1865 exceptionString = String.format("[FPD file error] There is no value for PCD entry %s in module %s!",\r
1866 pcdBuildData.getCName(),\r
1867 moduleName);\r
1868 throw new EntityException(exceptionString);\r
1869 }\r
1870\r
1871 //\r
1872 // Check whether the datum size is matched datum type.\r
1873 // \r
1874 if ((exceptionString = verifyDatum(pcdBuildData.getCName(), \r
1875 moduleName,\r
1876 datum,\r
1877 datumType,\r
1878 maxDatumSize)) != null) {\r
1879 throw new EntityException(exceptionString);\r
1880 }\r
1881 }\r
1882\r
1883 //\r
1884 // ---------------------------------------------------------------------------------\r
1885 // 2.1.2), Create token or update token information for current anaylized PCD data.\r
1886 // ---------------------------------------------------------------------------------\r
1887 // \r
1888 if (dbManager.isTokenInDatabase(primaryKey)) {\r
1889 //\r
1890 // If the token is already exist in database, do some necessary checking\r
1891 // and add a usage instance into this token in database\r
1892 // \r
1893 token = dbManager.getTokenByKey(primaryKey);\r
1894 \r
1895 //\r
1896 // checking for DatumType, DatumType should be unique for one PCD used in different\r
1897 // modules.\r
1898 // \r
1899 if (token.datumType != datumType) {\r
1900 exceptionString = String.format("[FPD file error] The datum type of PCD entry %s is %s, which is different with %s defined in before!",\r
1901 pcdBuildData.getCName(), \r
1902 pcdBuildData.getDatumType().toString(), \r
1903 Token.getStringOfdatumType(token.datumType));\r
1904 throw new EntityException(exceptionString);\r
1905 }\r
1906\r
1907 //\r
1908 // Check token number is valid\r
1909 // \r
1910 if (tokenNumber != token.tokenNumber) {\r
1911 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
1912 pcdBuildData.getCName(),\r
1913 moduleName);\r
1914 throw new EntityException(exceptionString);\r
1915 }\r
1916\r
1917 //\r
1918 // For same PCD used in different modules, the PCD type should all be dynamic or non-dynamic.\r
1919 // \r
1920 if (token.isDynamicPCD != Token.isDynamic(pcdType)) {\r
1921 exceptionString = String.format("[FPD file error] For PCD entry %s in module %s, you define dynamic or non-dynamic PCD type which"+\r
1922 "is different with others module's",\r
1923 token.cName,\r
1924 moduleName);\r
1925 throw new EntityException(exceptionString);\r
1926 }\r
1927\r
1928 if (token.isDynamicPCD) {\r
1929 //\r
1930 // Check datum is equal the datum in dynamic information.\r
1931 // For dynamic PCD, you can do not write <Value> in sperated every <PcdBuildDefinition> in different <ModuleSA>,\r
1932 // But if you write, the <Value> must be same as the value in <DynamicPcdBuildDefinitions>.\r
1933 // \r
1934 if (!token.isSkuEnable() && \r
1935 (token.getDefaultSku().type == DynamicTokenValue.VALUE_TYPE.DEFAULT_TYPE) &&\r
1936 (datum != null)) {\r
1937 if (!datum.equalsIgnoreCase(token.getDefaultSku().value)) {\r
1938 exceptionString = String.format("[FPD file error] For dynamic PCD %s in module %s, the datum in <ModuleSA> is "+\r
1939 "not equal to the datum in <DynamicPcdBuildDefinitions>, it is "+\r
1940 "illega! You could no set <Value> in <ModuleSA> for a dynamic PCD!",\r
1941 token.cName,\r
1942 moduleName);\r
1943 throw new EntityException(exceptionString);\r
1944 }\r
1945 }\r
1946\r
1947 if ((maxDatumSize != 0) &&\r
1948 (maxDatumSize != token.datumSize)){\r
1949 exceptionString = String.format("[FPD file error] For dynamic PCD %s in module %s, the max datum size is %d which "+\r
1950 "is different with <MaxDatumSize> %d defined in <DynamicPcdBuildDefinitions>!",\r
1951 token.cName,\r
1952 moduleName,\r
1953 maxDatumSize,\r
1954 token.datumSize);\r
1955 throw new EntityException(exceptionString);\r
1956 }\r
1957 }\r
1958 \r
1959 } else {\r
1960 //\r
1961 // If the token is not in database, create a new token instance and add\r
1962 // a usage instance into this token in database.\r
1963 // \r
1964 try {\r
1965 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(pcdBuildData.getTokenSpaceGuidCName());\r
1966 } catch (Exception e) {\r
1967 throw new EntityException("Fail to get token space guid for token " + token.cName);\r
1968 }\r
1969\r
1970 if (tokenSpaceStrRet == null) {\r
1971 throw new EntityException("Fail to get token space guid for token " + token.cName);\r
1972 }\r
1973\r
1974 token = new Token(pcdBuildData.getCName(), \r
1975 translateSchemaStringToUUID(tokenSpaceStrRet[1]));\r
1976 \r
1977 token.datumType = datumType;\r
1978 token.tokenNumber = tokenNumber;\r
1979 token.isDynamicPCD = Token.isDynamic(pcdType);\r
1980 token.datumSize = maxDatumSize;\r
1981 \r
1982 if (token.isDynamicPCD) {\r
1983 //\r
1984 // For Dynamic and Dynamic Ex type, need find the dynamic information\r
1985 // in <DynamicPcdBuildDefinition> section in FPD file.\r
1986 // \r
1987 updateDynamicInformation(moduleName, \r
1988 token,\r
1989 datum,\r
1990 maxDatumSize);\r
1991 }\r
1992 \r
1993 dbManager.addTokenToDatabase(primaryKey, token);\r
1994 }\r
1995\r
1996 //\r
1997 // -----------------------------------------------------------------------------------\r
1998 // 2.1.3), Add the PcdType in current module into this Pcd token's supported PCD type.\r
1999 // -----------------------------------------------------------------------------------\r
2000 // \r
2001 token.updateSupportPcdType(pcdType);\r
2002\r
2003 //\r
2004 // ------------------------------------------------\r
2005 // 2.1.4), Create an usage instance for this token.\r
2006 // ------------------------------------------------\r
2007 // \r
2008 usageInstance = new UsageInstance(token, \r
2009 moduleName, \r
2010 null,\r
2011 null,\r
2012 null,\r
2013 CommonDefinition.getModuleType(modules.get(index).getModuleType()), \r
2014 pcdType,\r
2015 modules.get(index).getModuleId().getArch(), \r
2016 null,\r
2017 datum,\r
2018 maxDatumSize);\r
2019 token.addUsageInstance(usageInstance);\r
2020 }\r
2021 }\r
2022 }\r
2023\r
2024 /**\r
2025 Verify the datum value according its datum size and datum type, this\r
2026 function maybe moved to FPD verification tools in future.\r
2027 \r
2028 @param cName\r
2029 @param moduleName\r
2030 @param datum\r
2031 @param datumType\r
2032 @param maxDatumSize\r
2033 \r
2034 @return String\r
2035 */\r
2036 /***/\r
2037 public String verifyDatum(String cName,\r
2038 String moduleName,\r
2039 String datum, \r
2040 Token.DATUM_TYPE datumType, \r
2041 int maxDatumSize) {\r
2042 String exceptionString = null;\r
2043 int value;\r
2044 BigInteger value64;\r
2045 String subStr;\r
2046 int index;\r
2047\r
2048 if (moduleName == null) {\r
2049 moduleName = "section <DynamicPcdBuildDefinitions>";\r
2050 } else {\r
2051 moduleName = "module " + moduleName;\r
2052 }\r
2053\r
2054 if (maxDatumSize == 0) {\r
2055 exceptionString = String.format("[FPD file error] You maybe miss <MaxDatumSize> for PCD %s in %s",\r
2056 cName,\r
2057 moduleName);\r
2058 return exceptionString;\r
2059 }\r
2060\r
2061 switch (datumType) {\r
2062 case UINT8:\r
2063 if (maxDatumSize != 1) {\r
2064 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+\r
2065 "is UINT8, but datum size is %d, they are not matched!",\r
2066 cName,\r
2067 moduleName,\r
2068 maxDatumSize);\r
2069 return exceptionString;\r
2070 }\r
2071\r
2072 if (datum != null) {\r
2073 try {\r
2074 value = Integer.decode(datum);\r
2075 } catch (NumberFormatException nfeExp) {\r
2076 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not valid "+\r
2077 "digital format of UINT8",\r
2078 cName,\r
2079 moduleName);\r
2080 return exceptionString;\r
2081 }\r
2082 if (value > 0xFF) {\r
2083 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s exceed"+\r
2084 " the max size of UINT8 - 0xFF",\r
2085 cName, \r
2086 moduleName,\r
2087 datum);\r
2088 return exceptionString;\r
2089 }\r
2090 }\r
2091 break;\r
2092 case UINT16:\r
2093 if (maxDatumSize != 2) {\r
2094 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+\r
2095 "is UINT16, but datum size is %d, they are not matched!",\r
2096 cName,\r
2097 moduleName,\r
2098 maxDatumSize);\r
2099 return exceptionString;\r
2100 }\r
2101 if (datum != null) {\r
2102 try {\r
2103 value = Integer.decode(datum);\r
2104 } catch (NumberFormatException nfeExp) {\r
2105 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is "+\r
2106 "not valid digital of UINT16",\r
2107 cName,\r
2108 moduleName);\r
2109 return exceptionString;\r
2110 }\r
2111 if (value > 0xFFFF) {\r
2112 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s "+\r
2113 "which exceed the range of UINT16 - 0xFFFF",\r
2114 cName, \r
2115 moduleName,\r
2116 datum);\r
2117 return exceptionString;\r
2118 }\r
2119 }\r
2120 break;\r
2121 case UINT32:\r
2122 if (maxDatumSize != 4) {\r
2123 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+\r
2124 "is UINT32, but datum size is %d, they are not matched!",\r
2125 cName,\r
2126 moduleName,\r
2127 maxDatumSize);\r
2128 return exceptionString;\r
2129 }\r
2130\r
2131 if (datum != null) {\r
2132 try {\r
2133 if (datum.length() > 2) {\r
2134 if ((datum.charAt(0) == '0') && \r
2135 ((datum.charAt(1) == 'x') || (datum.charAt(1) == 'X'))){\r
2136 subStr = datum.substring(2, datum.length());\r
2137 value64 = new BigInteger(subStr, 16);\r
2138 } else {\r
2139 value64 = new BigInteger(datum);\r
2140 }\r
2141 } else {\r
2142 value64 = new BigInteger(datum);\r
2143 }\r
2144 } catch (NumberFormatException nfeExp) {\r
2145 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not "+\r
2146 "valid digital of UINT32",\r
2147 cName,\r
2148 moduleName);\r
2149 return exceptionString;\r
2150 }\r
2151\r
2152 if (value64.bitLength() > 32) {\r
2153 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s which "+\r
2154 "exceed the range of UINT32 - 0xFFFFFFFF",\r
2155 cName, \r
2156 moduleName,\r
2157 datum);\r
2158 return exceptionString;\r
2159 }\r
2160 }\r
2161 break;\r
2162 case UINT64:\r
2163 if (maxDatumSize != 8) {\r
2164 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+\r
2165 "is UINT64, but datum size is %d, they are not matched!",\r
2166 cName,\r
2167 moduleName,\r
2168 maxDatumSize);\r
2169 return exceptionString;\r
2170 }\r
2171\r
2172 if (datum != null) {\r
2173 try {\r
2174 if (datum.length() > 2) {\r
2175 if ((datum.charAt(0) == '0') && \r
2176 ((datum.charAt(1) == 'x') || (datum.charAt(1) == 'X'))){\r
2177 subStr = datum.substring(2, datum.length());\r
2178 value64 = new BigInteger(subStr, 16);\r
2179 } else {\r
2180 value64 = new BigInteger(datum);\r
2181 }\r
2182 } else {\r
2183 value64 = new BigInteger(datum);\r
2184 }\r
2185 } catch (NumberFormatException nfeExp) {\r
2186 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is not valid"+\r
2187 " digital of UINT64",\r
2188 cName,\r
2189 moduleName);\r
2190 return exceptionString;\r
2191 }\r
2192\r
2193 if (value64.bitLength() > 64) {\r
2194 exceptionString = String.format("[FPD file error] The datum for PCD %s in %s is %s "+\r
2195 "exceed the range of UINT64 - 0xFFFFFFFFFFFFFFFF",\r
2196 cName, \r
2197 moduleName,\r
2198 datum);\r
2199 return exceptionString;\r
2200 }\r
2201 }\r
2202 break;\r
2203 case BOOLEAN:\r
2204 if (maxDatumSize != 1) {\r
2205 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+\r
2206 "is BOOLEAN, but datum size is %d, they are not matched!",\r
2207 cName,\r
2208 moduleName,\r
2209 maxDatumSize);\r
2210 return exceptionString;\r
2211 }\r
2212\r
2213 if (datum != null) {\r
2214 if (!(datum.equalsIgnoreCase("TRUE") ||\r
2215 datum.equalsIgnoreCase("FALSE"))) {\r
2216 exceptionString = String.format("[FPD file error] The datum type of PCD data %s in %s "+\r
2217 "is BOOELAN, but value is not 'true'/'TRUE' or 'FALSE'/'false'",\r
2218 cName,\r
2219 moduleName);\r
2220 return exceptionString;\r
2221 }\r
2222\r
2223 }\r
2224 break;\r
2225 case POINTER:\r
2226 if (datum == null) {\r
2227 break;\r
2228 }\r
2229\r
2230 char ch = datum.charAt(0);\r
2231 int start, end;\r
2232 String strValue;\r
2233 //\r
2234 // For void* type PCD, only three datum is support:\r
2235 // 1) Unicode: string with start char is "L"\r
2236 // 2) Ansci: String start char is ""\r
2237 // 3) byte array: String start char "{"\r
2238 // \r
2239 if (ch == 'L') {\r
2240 start = datum.indexOf('\"');\r
2241 end = datum.lastIndexOf('\"');\r
2242 if ((start > end) || \r
2243 (end > datum.length())||\r
2244 ((start == end) && (datum.length() > 0))) {\r
2245 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+\r
2246 "a UNICODE string because start with L\", but format maybe"+\r
2247 "is not right, correct UNICODE string is L\"...\"!",\r
2248 cName,\r
2249 moduleName);\r
2250 return exceptionString;\r
2251 }\r
2252\r
2253 strValue = datum.substring(start + 1, end);\r
2254 if ((strValue.length() * 2) > maxDatumSize) {\r
2255 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+\r
2256 "a UNICODE string, but the datum size is %d exceed to <MaxDatumSize> : %d",\r
2257 cName,\r
2258 moduleName,\r
2259 strValue.length() * 2, \r
2260 maxDatumSize);\r
2261 return exceptionString;\r
2262 }\r
2263 } else if (ch == '\"'){\r
2264 start = datum.indexOf('\"');\r
2265 end = datum.lastIndexOf('\"');\r
2266 if ((start > end) || \r
2267 (end > datum.length())||\r
2268 ((start == end) && (datum.length() > 0))) {\r
2269 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID* and datum is "+\r
2270 "a ANSCII string because start with \", but format maybe"+\r
2271 "is not right, correct ANSIC string is \"...\"!",\r
2272 cName,\r
2273 moduleName);\r
2274 return exceptionString;\r
2275 }\r
2276 strValue = datum.substring(start + 1, end);\r
2277 if ((strValue.length()) > maxDatumSize) {\r
2278 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is "+\r
2279 "a ANSCI string, but the datum size is %d which exceed to <MaxDatumSize> : %d",\r
2280 cName,\r
2281 moduleName,\r
2282 strValue.length(),\r
2283 maxDatumSize);\r
2284 return exceptionString;\r
2285 }\r
2286 } else if (ch =='{') {\r
2287 String[] strValueArray;\r
2288\r
2289 start = datum.indexOf('{');\r
2290 end = datum.lastIndexOf('}');\r
2291 strValue = datum.substring(start + 1, end);\r
2292 strValue = strValue.trim();\r
2293 if (strValue.length() == 0) {\r
2294 break;\r
2295 }\r
2296 strValueArray = strValue.split(",");\r
2297 for (index = 0; index < strValueArray.length; index ++) {\r
2298 try{\r
2299 value = Integer.decode(strValueArray[index].trim());\r
2300 } catch (NumberFormatException nfeEx) {\r
2301 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and "+\r
2302 "it is byte array in fact. For every byte in array should be a valid"+\r
2303 "byte digital, but element %s is not a valid byte digital!",\r
2304 cName,\r
2305 moduleName,\r
2306 strValueArray[index]);\r
2307 return exceptionString;\r
2308 }\r
2309 if (value > 0xFF) {\r
2310 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, "+\r
2311 "it is byte array in fact. But the element of %s exceed the byte range",\r
2312 cName,\r
2313 moduleName,\r
2314 strValueArray[index]);\r
2315 return exceptionString;\r
2316 }\r
2317 }\r
2318\r
2319 if (strValueArray.length > maxDatumSize) {\r
2320 exceptionString = String.format("[FPD file error] The datum type of PCD %s in %s is VOID*, and datum is byte"+\r
2321 "array, but the number of bytes is %d which exceed to <MaxDatumSzie> : %d!",\r
2322 cName,\r
2323 moduleName,\r
2324 strValueArray.length,\r
2325 maxDatumSize);\r
2326 return exceptionString;\r
2327 }\r
2328 } else {\r
2329 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
2330 "1) UNICODE string: like L\"xxxx\";\r\n"+\r
2331 "2) ANSIC string: like \"xxx\";\r\n"+\r
2332 "3) Byte array: like {0x2, 0x45, 0x23}\r\n"+\r
2333 "But the datum in seems does not following above format!",\r
2334 cName, \r
2335 moduleName);\r
2336 return exceptionString;\r
2337 }\r
2338 break;\r
2339 default:\r
2340 exceptionString = String.format("[FPD file error] For PCD entry %s in %s, datum type is unknown, it should be one of "+\r
2341 "UINT8, UINT16, UINT32, UINT64, VOID*, BOOLEAN",\r
2342 cName,\r
2343 moduleName);\r
2344 return exceptionString;\r
2345 }\r
2346 return null;\r
2347 }\r
2348\r
2349 /**\r
2350 Get dynamic information for a dynamic PCD from <DynamicPcdBuildDefinition> seciton in FPD file.\r
2351 \r
2352 This function should be implemented in GlobalData in future.\r
2353 \r
2354 @param token The token instance which has hold module's PCD information\r
2355 @param moduleName The name of module who will use this Dynamic PCD.\r
2356 \r
2357 @return DynamicPcdBuildDefinitions.PcdBuildData\r
2358 */\r
2359 /***/\r
2360 private DynamicPcdBuildDefinitions.PcdBuildData getDynamicInfoFromFPD(Token token,\r
2361 String moduleName)\r
2362 throws EntityException {\r
2363 int index = 0;\r
2364 String exceptionString = null;\r
2365 String dynamicPrimaryKey = null;\r
2366 DynamicPcdBuildDefinitions dynamicPcdBuildDefinitions = null;\r
2367 List<DynamicPcdBuildDefinitions.PcdBuildData> dynamicPcdBuildDataArray = null;\r
2368 String[] tokenSpaceStrRet = null;\r
2369\r
2370 //\r
2371 // If FPD document is not be opened, open and initialize it.\r
2372 // \r
2373 if (fpdDocInstance == null) {\r
2374 try {\r
2375 fpdDocInstance = (PlatformSurfaceAreaDocument)XmlObject.Factory.parse(new File(fpdFilePath));\r
2376 } catch(IOException ioE) {\r
2377 throw new EntityException("File IO error for xml file:" + fpdFilePath + "\n" + ioE.getMessage());\r
2378 } catch(XmlException xmlE) {\r
2379 throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath + "\n" + xmlE.getMessage());\r
2380 }\r
2381 }\r
2382 \r
2383 dynamicPcdBuildDefinitions = fpdDocInstance.getPlatformSurfaceArea().getDynamicPcdBuildDefinitions();\r
2384 if (dynamicPcdBuildDefinitions == null) {\r
2385 exceptionString = String.format("[FPD file error] There are no <PcdDynamicBuildDescriptions> in FPD file but contains Dynamic type "+\r
2386 "PCD entry %s in module %s!",\r
2387 token.cName,\r
2388 moduleName);\r
2389 throw new EntityException(exceptionString);\r
2390 }\r
2391\r
2392 dynamicPcdBuildDataArray = dynamicPcdBuildDefinitions.getPcdBuildDataList();\r
2393 for (index = 0; index < dynamicPcdBuildDataArray.size(); index ++) {\r
2394 //String tokenSpaceGuidString = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName())[1];\r
2395 String tokenSpaceGuidString = null;\r
2396 try {\r
2397 tokenSpaceStrRet = GlobalData.getGuidInfoFromCname(dynamicPcdBuildDataArray.get(index).getTokenSpaceGuidCName());\r
2398 } catch (Exception e) {\r
2399 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray.get(index).getCName());\r
2400 }\r
2401 \r
2402 if (tokenSpaceStrRet == null) {\r
2403 throw new EntityException ("Fail to get token space guid for token " + dynamicPcdBuildDataArray.get(index).getCName());\r
2404 }\r
2405\r
2406 dynamicPrimaryKey = Token.getPrimaryKeyString(dynamicPcdBuildDataArray.get(index).getCName(),\r
2407 translateSchemaStringToUUID(tokenSpaceStrRet[1]));\r
2408 if (dynamicPrimaryKey.equalsIgnoreCase(token.getPrimaryKeyString())) {\r
2409 return dynamicPcdBuildDataArray.get(index);\r
2410 }\r
2411 }\r
2412\r
2413 return null;\r
2414 }\r
2415\r
2416 /**\r
2417 Update dynamic information for PCD entry.\r
2418 \r
2419 Dynamic information is retrieved from <PcdDynamicBuildDeclarations> in\r
2420 FPD file.\r
2421 \r
2422 @param moduleName The name of the module who use this PCD\r
2423 @param token The token instance\r
2424 @param datum The <datum> in module's PCD information\r
2425 @param maxDatumSize The <maxDatumSize> in module's PCD information\r
2426 \r
2427 @return Token\r
2428 */\r
2429 private Token updateDynamicInformation(String moduleName, \r
2430 Token token,\r
2431 String datum,\r
2432 int maxDatumSize) \r
2433 throws EntityException {\r
2434 int index = 0;\r
2435 int offset;\r
2436 String exceptionString = null;\r
2437 DynamicTokenValue dynamicValue;\r
2438 SkuInstance skuInstance = null;\r
2439 String temp;\r
2440 boolean hasSkuId0 = false;\r
2441 Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN;\r
2442 long tokenNumber = 0;\r
2443 String hiiDefaultValue = null;\r
2444 String[] variableGuidString = null;\r
2445\r
2446 List<DynamicPcdBuildDefinitions.PcdBuildData.SkuInfo> skuInfoList = null;\r
2447 DynamicPcdBuildDefinitions.PcdBuildData dynamicInfo = null;\r
2448\r
2449 dynamicInfo = getDynamicInfoFromFPD(token, moduleName);\r
2450 if (dynamicInfo == null) {\r
2451 exceptionString = String.format("[FPD file error] For Dynamic PCD %s used by module %s, "+\r
2452 "there is no dynamic information in <DynamicPcdBuildDefinitions> "+\r
2453 "in FPD file, but it is required!",\r
2454 token.cName,\r
2455 moduleName);\r
2456 throw new EntityException(exceptionString);\r
2457 }\r
2458\r
2459 token.datumSize = dynamicInfo.getMaxDatumSize();\r
2460\r
2461 exceptionString = verifyDatum(token.cName, \r
2462 moduleName,\r
2463 null, \r
2464 token.datumType, \r
2465 token.datumSize);\r
2466 if (exceptionString != null) {\r
2467 throw new EntityException(exceptionString);\r
2468 }\r
2469\r
2470 if ((maxDatumSize != 0) && \r
2471 (maxDatumSize != token.datumSize)) {\r
2472 exceptionString = String.format("FPD file error] For dynamic PCD %s, the datum size in module %s is %d, but "+\r
2473 "the datum size in <DynamicPcdBuildDefinitions> is %d, they are not match!",\r
2474 token.cName,\r
2475 moduleName, \r
2476 maxDatumSize,\r
2477 dynamicInfo.getMaxDatumSize());\r
2478 throw new EntityException(exceptionString);\r
2479 }\r
2480 tokenNumber = Long.decode(dynamicInfo.getToken().toString());\r
2481 if (tokenNumber != token.tokenNumber) {\r
2482 exceptionString = String.format("[FPD file error] For dynamic PCD %s, the token number in module %s is 0x%x, but"+\r
2483 "in <DynamicPcdBuildDefinictions>, the token number is 0x%x, they are not match!",\r
2484 token.cName,\r
2485 moduleName,\r
2486 token.tokenNumber,\r
2487 tokenNumber);\r
2488 throw new EntityException(exceptionString);\r
2489 }\r
2490\r
2491 pcdType = Token.getpcdTypeFromString(dynamicInfo.getItemType().toString());\r
2492 if (pcdType == Token.PCD_TYPE.DYNAMIC_EX) {\r
2493 token.dynamicExTokenNumber = tokenNumber;\r
2494 }\r
2495\r
2496 skuInfoList = dynamicInfo.getSkuInfoList();\r
2497\r
2498 //\r
2499 // Loop all sku data \r
2500 // \r
2501 for (index = 0; index < skuInfoList.size(); index ++) {\r
2502 skuInstance = new SkuInstance();\r
2503 //\r
2504 // Although SkuId in schema is BigInteger, but in fact, sku id is 32 bit value.\r
2505 // \r
2506 temp = skuInfoList.get(index).getSkuId().toString();\r
2507 skuInstance.id = Integer.decode(temp);\r
2508 if (skuInstance.id == 0) {\r
2509 hasSkuId0 = true;\r
2510 }\r
2511 //\r
2512 // Judge whether is DefaultGroup at first, because most case is DefautlGroup.\r
2513 // \r
2514 if (skuInfoList.get(index).getValue() != null) {\r
2515 skuInstance.value.setValue(skuInfoList.get(index).getValue().toString());\r
2516 if ((exceptionString = verifyDatum(token.cName, \r
2517 null, \r
2518 skuInfoList.get(index).getValue().toString(), \r
2519 token.datumType, \r
2520 token.datumSize)) != null) {\r
2521 throw new EntityException(exceptionString);\r
2522 }\r
2523\r
2524 token.skuData.add(skuInstance);\r
2525\r
2526 //\r
2527 // Judege wether is same of datum between module's information\r
2528 // and dynamic information.\r
2529 // \r
2530 if (datum != null) {\r
2531 if ((skuInstance.id == 0) &&\r
2532 !datum.toString().equalsIgnoreCase(skuInfoList.get(index).getValue().toString())) {\r
2533 exceptionString = "[FPD file error] For dynamic PCD " + token.cName + ", the value in module " + moduleName + " is " + datum.toString() + " but the "+\r
2534 "value of sku 0 data in <DynamicPcdBuildDefinition> is " + skuInstance.value.value + ". They are must be same!"+\r
2535 " or you could not define value for a dynamic PCD in every <ModuleSA>!"; \r
2536 throw new EntityException(exceptionString);\r
2537 }\r
2538 }\r
2539 continue;\r
2540 }\r
2541\r
2542 //\r
2543 // Judge whether is HII group case.\r
2544 // \r
2545 if (skuInfoList.get(index).getVariableName() != null) {\r
2546 exceptionString = null;\r
2547 if (skuInfoList.get(index).getVariableGuid() == null) {\r
2548 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
2549 "file, who use HII, but there is no <VariableGuid> defined for Sku %d data!",\r
2550 token.cName,\r
2551 index);\r
2552 if (exceptionString != null) {\r
2553 throw new EntityException(exceptionString);\r
2554 } \r
2555 }\r
2556\r
2557 if (skuInfoList.get(index).getVariableOffset() == null) {\r
2558 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
2559 "file, who use HII, but there is no <VariableOffset> defined for Sku %d data!",\r
2560 token.cName,\r
2561 index);\r
2562 if (exceptionString != null) {\r
2563 throw new EntityException(exceptionString);\r
2564 }\r
2565 }\r
2566\r
2567 if (skuInfoList.get(index).getHiiDefaultValue() == null) {\r
2568 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions> section in FPD "+\r
2569 "file, who use HII, but there is no <HiiDefaultValue> defined for Sku %d data!",\r
2570 token.cName,\r
2571 index);\r
2572 if (exceptionString != null) {\r
2573 throw new EntityException(exceptionString);\r
2574 }\r
2575 }\r
2576\r
2577 if (skuInfoList.get(index).getHiiDefaultValue() != null) {\r
2578 hiiDefaultValue = skuInfoList.get(index).getHiiDefaultValue().toString();\r
2579 } else {\r
2580 hiiDefaultValue = null;\r
2581 }\r
2582\r
2583 if ((exceptionString = verifyDatum(token.cName, \r
2584 null, \r
2585 hiiDefaultValue, \r
2586 token.datumType, \r
2587 token.datumSize)) != null) {\r
2588 throw new EntityException(exceptionString);\r
2589 }\r
2590\r
2591 offset = Integer.decode(skuInfoList.get(index).getVariableOffset());\r
2592 if (offset > 0xFFFF) {\r
2593 throw new EntityException(String.format("[FPD file error] For dynamic PCD %s , the variable offset defined in sku %d data "+\r
2594 "exceed 64K, it is not allowed!",\r
2595 token.cName,\r
2596 index));\r
2597 }\r
2598\r
2599 //\r
2600 // Get variable guid string according to the name of guid which will be mapped into a GUID in SPD file.\r
2601 // \r
2602 variableGuidString = GlobalData.getGuidInfoFromCname(skuInfoList.get(index).getVariableGuid().toString());\r
2603 if (variableGuidString == null) {\r
2604 throw new EntityException(String.format("[GUID Error] For dynamic PCD %s, the variable guid %s can be found in all SPD file!",\r
2605 token.cName, \r
2606 skuInfoList.get(index).getVariableGuid().toString()));\r
2607 }\r
2608 String variableStr = skuInfoList.get(index).getVariableName();\r
2609 Pattern pattern = Pattern.compile("0x([a-fA-F0-9]){4}");\r
2610 Matcher matcher = pattern.matcher(variableStr);\r
2611 List<String> varNameList = new ArrayList<String>();\r
2612 while (matcher.find()){\r
2613 String str = variableStr.substring(matcher.start(),matcher.end());\r
2614 varNameList.add(str);\r
2615 }\r
2616 \r
2617 skuInstance.value.setHiiData(varNameList,\r
2618 translateSchemaStringToUUID(variableGuidString[1]),\r
2619 skuInfoList.get(index).getVariableOffset(),\r
2620 skuInfoList.get(index).getHiiDefaultValue().toString());\r
2621 token.skuData.add(skuInstance);\r
2622 continue;\r
2623 }\r
2624\r
2625 if (skuInfoList.get(index).getVpdOffset() != null) {\r
2626 skuInstance.value.setVpdData(skuInfoList.get(index).getVpdOffset());\r
2627 token.skuData.add(skuInstance);\r
2628 continue;\r
2629 }\r
2630\r
2631 exceptionString = String.format("[FPD file error] For dynamic PCD %s, the dynamic info must "+\r
2632 "be one of 'DefaultGroup', 'HIIGroup', 'VpdGroup'.",\r
2633 token.cName);\r
2634 throw new EntityException(exceptionString);\r
2635 }\r
2636\r
2637 if (!hasSkuId0) {\r
2638 exceptionString = String.format("[FPD file error] For dynamic PCD %s in <DynamicPcdBuildDefinitions>, there are "+\r
2639 "no sku id = 0 data, which is required for every dynamic PCD",\r
2640 token.cName);\r
2641 throw new EntityException(exceptionString);\r
2642 }\r
2643\r
2644 return token;\r
2645 }\r
2646\r
2647 /**\r
2648 Translate the schema string to UUID instance.\r
2649 \r
2650 In schema, the string of UUID is defined as following two types string:\r
2651 1) GuidArrayType: pattern = 0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},(\r
2652 )*0x[a-fA-F0-9]{1,4}(,( )*\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\})?\r
2653 \r
2654 2) GuidNamingConvention: pattern =\r
2655 [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
2656 \r
2657 This function will convert string and create uuid instance.\r
2658 \r
2659 @param uuidString UUID string in XML file\r
2660 \r
2661 @return UUID UUID instance\r
2662 **/\r
2663 private UUID translateSchemaStringToUUID(String uuidString) \r
2664 throws EntityException {\r
2665 String temp;\r
2666 String[] splitStringArray;\r
2667 int index;\r
2668 int chIndex;\r
2669 int chLen;\r
2670\r
2671 if (uuidString == null) {\r
2672 return null;\r
2673 }\r
2674\r
2675 if (uuidString.length() == 0) {\r
2676 return null;\r
2677 }\r
2678\r
2679 if (uuidString.equals("0") ||\r
2680 uuidString.equalsIgnoreCase("0x0")) {\r
2681 return new UUID(0, 0);\r
2682 }\r
2683\r
2684 uuidString = uuidString.replaceAll("\\{", "");\r
2685 uuidString = uuidString.replaceAll("\\}", "");\r
2686\r
2687 //\r
2688 // If the UUID schema string is GuidArrayType type then need translate \r
2689 // to GuidNamingConvention type at first.\r
2690 // \r
2691 if ((uuidString.charAt(0) == '0') && ((uuidString.charAt(1) == 'x') || (uuidString.charAt(1) == 'X'))) {\r
2692 splitStringArray = uuidString.split("," );\r
2693 if (splitStringArray.length != 11) {\r
2694 throw new EntityException ("[FPD file error] Wrong format for UUID string: " + uuidString);\r
2695 }\r
2696\r
2697 //\r
2698 // Remove blank space from these string and remove header string "0x"\r
2699 // \r
2700 for (index = 0; index < 11; index ++) {\r
2701 splitStringArray[index] = splitStringArray[index].trim();\r
2702 splitStringArray[index] = splitStringArray[index].substring(2, splitStringArray[index].length());\r
2703 }\r
2704\r
2705 //\r
2706 // Add heading '0' to normalize the string length\r
2707 // \r
2708 for (index = 3; index < 11; index ++) {\r
2709 chLen = splitStringArray[index].length();\r
2710 for (chIndex = 0; chIndex < 2 - chLen; chIndex ++) {\r
2711 splitStringArray[index] = "0" + splitStringArray[index];\r
2712 }\r
2713 }\r
2714\r
2715 //\r
2716 // construct the final GuidNamingConvention string\r
2717 // \r
2718 temp = String.format("%s-%s-%s-%s%s-%s%s%s%s%s%s",\r
2719 splitStringArray[0],\r
2720 splitStringArray[1],\r
2721 splitStringArray[2],\r
2722 splitStringArray[3],\r
2723 splitStringArray[4],\r
2724 splitStringArray[5],\r
2725 splitStringArray[6],\r
2726 splitStringArray[7],\r
2727 splitStringArray[8],\r
2728 splitStringArray[9],\r
2729 splitStringArray[10]);\r
2730 uuidString = temp;\r
2731 }\r
2732\r
2733 return UUID.fromString(uuidString);\r
2734 }\r
2735\r
2736 /**\r
2737 check parameter for this action.\r
2738 \r
2739 @throws EntityException Bad parameter.\r
2740 **/\r
2741 private void checkParameter() throws EntityException {\r
2742 File file = null;\r
2743\r
2744 if((fpdFilePath == null) ||(workspacePath == null)) {\r
2745 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");\r
2746 }\r
2747\r
2748 if(fpdFilePath.length() == 0 || workspacePath.length() == 0) {\r
2749 throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!");\r
2750 }\r
2751\r
2752 file = new File(workspacePath);\r
2753 if(!file.exists()) {\r
2754 throw new EntityException("WorkpacePath " + workspacePath + " does not exist!");\r
2755 }\r
2756\r
2757 file = new File(fpdFilePath);\r
2758\r
2759 if(!file.exists()) {\r
2760 throw new EntityException("FPD File " + fpdFilePath + " does not exist!");\r
2761 }\r
2762 }\r
2763\r
2764 /**\r
2765 Test case function\r
2766\r
2767 @param argv parameter from command line\r
2768 **/\r
2769 public static void main(String argv[]) throws EntityException {\r
2770 CollectPCDAction ca = new CollectPCDAction();\r
2771 ca.setWorkspacePath("m:/tianocore/edk2");\r
2772 ca.setFPDFilePath("m:/tianocore/edk2/EdkNt32Pkg/Nt32.fpd");\r
2773 ca.setActionMessageLevel(ActionMessage.MAX_MESSAGE_LEVEL);\r
2774// GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db",\r
2775// "m:/tianocore/edk2");\r
2776// ca.execute();\r
2777 }\r
2778}\r