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