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