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