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