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