BaseTools: Add PcdValueCommon logic into C source CommonLib
[mirror_edk2.git] / BaseTools / Source / C / Common / PcdValueCommon.c
1 /** @file
2 This file contains the PcdValue structure definition.
3
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include "CommonLib.h"
20 #include "PcdValueCommon.h"
21
22 typedef enum {
23 PcdDataTypeBoolean,
24 PcdDataTypeUint8,
25 PcdDataTypeUint16,
26 PcdDataTypeUint32,
27 PcdDataTypeUint64,
28 PcdDataTypePointer
29 } PCD_DATA_TYPE;
30
31 typedef struct {
32 CHAR8 *SkuName;
33 CHAR8 *DefaultValueName;
34 CHAR8 *TokenSpaceGuidName;
35 CHAR8 *TokenName;
36 CHAR8 *DataType;
37 CHAR8 *Value;
38 PCD_DATA_TYPE PcdDataType;
39 } PCD_ENTRY;
40
41 PCD_ENTRY *PcdList;
42 UINT32 PcdListLength;
43
44 VOID
45 STATIC
46 RecordToken (
47 UINT8 *FileBuffer,
48 UINT32 PcdIndex,
49 UINT32 TokenIndex,
50 UINT32 TokenStart,
51 UINT32 TokenEnd
52 )
53 /*++
54
55 Routine Description:
56
57 Record new token information
58
59 Arguments:
60
61 FileBuffer File Buffer to be record
62 PcdIndex Index of PCD in database
63 TokenIndex Index of Token
64 TokenStart Start of Token
65 TokenEnd End of Token
66
67 Returns:
68
69 None
70 --*/
71 {
72 CHAR8 *Token;
73
74 Token = malloc (TokenEnd - TokenStart + 1);
75 memcpy (Token, &FileBuffer[TokenStart], TokenEnd - TokenStart);
76 Token[TokenEnd - TokenStart] = 0;
77 switch (TokenIndex) {
78 case 0:
79 PcdList[PcdIndex].SkuName = Token;
80 break;
81 case 1:
82 PcdList[PcdIndex].DefaultValueName = Token;
83 break;
84 case 2:
85 PcdList[PcdIndex].TokenSpaceGuidName = Token;
86 break;
87 case 3:
88 PcdList[PcdIndex].TokenName = Token;
89 break;
90 case 4:
91 PcdList[PcdIndex].DataType = Token;
92 if (strcmp (Token, "BOOLEAN") == 0) {
93 PcdList[PcdIndex].PcdDataType = PcdDataTypeBoolean;
94 } else if (strcmp (Token, "UINT8") == 0) {
95 PcdList[PcdIndex].PcdDataType = PcdDataTypeUint8;
96 } else if (strcmp (Token, "UINT16") == 0) {
97 PcdList[PcdIndex].PcdDataType = PcdDataTypeUint16;
98 } else if (strcmp (Token, "UINT32") == 0) {
99 PcdList[PcdIndex].PcdDataType = PcdDataTypeUint32;
100 } else if (strcmp (Token, "UINT64") == 0) {
101 PcdList[PcdIndex].PcdDataType = PcdDataTypeUint64;
102 } else {
103 PcdList[PcdIndex].PcdDataType = PcdDataTypePointer;
104 }
105 break;
106 case 5:
107 PcdList[PcdIndex].Value = Token;
108 break;
109 }
110 }
111
112 int
113 STATIC
114 LookupPcdIndex (
115 CHAR8 *SkuName OPTIONAL,
116 CHAR8 *DefaultValueName OPTIONAL,
117 CHAR8 *TokenSpaceGuidName,
118 CHAR8 *TokenName
119 )
120 /*++
121
122 Routine Description:
123
124 Get PCD index in Pcd database
125
126 Arguments:
127
128 SkuName SkuName String
129 DefaultValueName DefaultValueName String
130 TokenSpaceGuidName TokenSpaceGuidName String
131 TokenName TokenName String
132
133 Returns:
134
135 Index of PCD in Pcd database
136 --*/
137 {
138 UINT32 Index;
139
140 if (SkuName == NULL) {
141 SkuName = "DEFAULT";
142 }
143 if (DefaultValueName == NULL) {
144 DefaultValueName = "DEFAULT";
145 }
146 for (Index = 0; Index < PcdListLength; Index++) {
147 if (strcmp(PcdList[Index].TokenSpaceGuidName, TokenSpaceGuidName) != 0) {
148 continue;
149 }
150 if (strcmp(PcdList[Index].TokenName, TokenName) != 0) {
151 continue;
152 }
153 if (strcmp(PcdList[Index].SkuName, SkuName) != 0) {
154 continue;
155 }
156 if (strcmp(PcdList[Index].DefaultValueName, DefaultValueName) != 0) {
157 continue;
158 }
159 return Index;
160 }
161 return -1;
162 }
163
164 UINT64
165 __PcdGet (
166 CHAR8 *SkuName OPTIONAL,
167 CHAR8 *DefaultValueName OPTIONAL,
168 CHAR8 *TokenSpaceGuidName,
169 CHAR8 *TokenName
170 )
171 /*++
172
173 Routine Description:
174
175 Get PCD value
176
177 Arguments:
178
179 SkuName SkuName String
180 DefaultValueName DefaultValueName String
181 TokenSpaceGuidName TokenSpaceGuidName String
182 TokenName TokenName String
183
184 Returns:
185
186 PCD value
187 --*/
188 {
189 int Index;
190 CHAR8 *End;
191
192 Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
193 if (Index < 0) {
194 fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
195 exit (EXIT_FAILURE);
196 }
197 switch (PcdList[Index].PcdDataType) {
198 case PcdDataTypeBoolean:
199 case PcdDataTypeUint8:
200 case PcdDataTypeUint16:
201 case PcdDataTypeUint32:
202 return (UINT64)strtoul(PcdList[Index].Value, &End, 16);
203 break;
204 case PcdDataTypeUint64:
205 return (UINT64)strtoul(PcdList[Index].Value, &End, 16);
206 break;
207 case PcdDataTypePointer:
208 fprintf (stderr, "PCD %s.%s.%s.%s is structure. Use PcdGetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
209 exit (EXIT_FAILURE);
210 break;
211 }
212 return 0;
213 }
214
215 VOID
216 __PcdSet (
217 CHAR8 *SkuName OPTIONAL,
218 CHAR8 *DefaultValueName OPTIONAL,
219 CHAR8 *TokenSpaceGuidName,
220 CHAR8 *TokenName,
221 UINT64 Value
222 )
223 /*++
224
225 Routine Description:
226
227 Set PCD value
228
229 Arguments:
230
231 SkuName SkuName String
232 DefaultValueName DefaultValueName String
233 TokenSpaceGuidName TokenSpaceGuidName String
234 TokenName TokenName String
235 Value PCD value to be set
236
237 Returns:
238
239 None
240 --*/
241 {
242 int Index;
243
244 Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
245 if (Index < 0) {
246 fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
247 exit (EXIT_FAILURE);
248 }
249 free(PcdList[Index].Value);
250 PcdList[Index].Value = malloc(20);
251 switch (PcdList[Index].PcdDataType) {
252 case PcdDataTypeBoolean:
253 if (Value == 0) {
254 strcpy (PcdList[Index].Value, "0x00");
255 } else {
256 strcpy (PcdList[Index].Value, "0x01");
257 }
258 break;
259 case PcdDataTypeUint8:
260 sprintf(PcdList[Index].Value, "0x%02x", (UINT8)(Value & 0xff));
261 break;
262 case PcdDataTypeUint16:
263 sprintf(PcdList[Index].Value, "0x%04x", (UINT16)(Value & 0xffff));
264 break;
265 case PcdDataTypeUint32:
266 sprintf(PcdList[Index].Value, "0x%08x", (UINT32)(Value & 0xffffffff));
267 break;
268 case PcdDataTypeUint64:
269 #ifdef __GNUC__
270 sprintf(PcdList[Index].Value, "0x%016lx", Value);
271 #else
272 sprintf(PcdList[Index].Value, "0x%016llx", Value);
273 #endif
274 break;
275 case PcdDataTypePointer:
276 fprintf (stderr, "PCD %s.%s.%s.%s is structure. Use PcdSetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
277 exit (EXIT_FAILURE);
278 break;
279 }
280 }
281
282 VOID *
283 __PcdGetPtr (
284 CHAR8 *SkuName OPTIONAL,
285 CHAR8 *DefaultValueName OPTIONAL,
286 CHAR8 *TokenSpaceGuidName,
287 CHAR8 *TokenName,
288 UINT32 *Size
289 )
290 /*++
291
292 Routine Description:
293
294 Get PCD value buffer
295
296 Arguments:
297
298 SkuName SkuName String
299 DefaultValueName DefaultValueName String
300 TokenSpaceGuidName TokenSpaceGuidName String
301 TokenName TokenName String
302 Size Size of PCD value buffer
303
304 Returns:
305
306 PCD value buffer
307 --*/
308 {
309 int Index;
310 CHAR8 *Value;
311 UINT8 *Buffer;
312 CHAR8 *End;
313 UINT8 Byte;
314
315 Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
316 if (Index < 0) {
317 fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
318 exit (EXIT_FAILURE);
319 }
320 switch (PcdList[Index].PcdDataType) {
321 case PcdDataTypeBoolean:
322 case PcdDataTypeUint8:
323 case PcdDataTypeUint16:
324 case PcdDataTypeUint32:
325 case PcdDataTypeUint64:
326 fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
327 exit (EXIT_FAILURE);
328 break;
329 case PcdDataTypePointer:
330 Value = &PcdList[Index].Value[1];
331 printf ("Value = %s\n", PcdList[Index].Value);
332 for (*Size = 0, Byte = (UINT8) strtoul(Value, &End, 16); Value != End; Byte = (UINT8) strtoul(Value, &End, 16), *Size = *Size + 1) {
333 printf("%x\n", Byte);
334 Value = End + 1;
335 }
336 Buffer = malloc(*Size);
337 Value = &PcdList[Index].Value[1];
338 for (*Size = 0, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16); Value != End; *Size = *Size + 1, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16)) {
339 Value = End + 1;
340 }
341 return Buffer;
342 }
343 *Size = 0;
344 return 0;
345 }
346
347 VOID
348 __PcdSetPtr (
349 CHAR8 *SkuName OPTIONAL,
350 CHAR8 *DefaultValueName OPTIONAL,
351 CHAR8 *TokenSpaceGuidName,
352 CHAR8 *TokenName,
353 UINT32 Size,
354 UINT8 *Value
355 )
356 /*++
357
358 Routine Description:
359
360 Set PCD value buffer
361
362 Arguments:
363
364 SkuName SkuName String
365 DefaultValueName DefaultValueName String
366 TokenSpaceGuidName TokenSpaceGuidName String
367 TokenName TokenName String
368 Size Size of PCD value
369 Value Pointer to the updated PCD value buffer
370
371 Returns:
372
373 None
374 --*/
375 {
376 int Index;
377 UINT32 ValueIndex;
378
379 Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
380 if (Index < 0) {
381 fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
382 exit (EXIT_FAILURE);
383 }
384 switch (PcdList[Index].PcdDataType) {
385 case PcdDataTypeBoolean:
386 case PcdDataTypeUint8:
387 case PcdDataTypeUint16:
388 case PcdDataTypeUint32:
389 case PcdDataTypeUint64:
390 fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
391 exit (EXIT_FAILURE);
392 break;
393 case PcdDataTypePointer:
394 free(PcdList[Index].Value);
395 PcdList[Index].Value = malloc(Size * 5 + 3);
396 PcdList[Index].Value[0] = '{';
397 for (ValueIndex = 0; ValueIndex < Size; ValueIndex++) {
398 printf("Value[%d] = %02x\n", ValueIndex, Value[ValueIndex]);
399 sprintf(&PcdList[Index].Value[1 + ValueIndex * 5], "0x%02x,", Value[ValueIndex]);
400 }
401 PcdList[Index].Value[1 + Size * 5 - 1] = '}';
402 PcdList[Index].Value[1 + Size * 5 ] = 0;
403 break;
404 }
405 }
406
407 VOID
408 STATIC
409 ReadInputFile (
410 CHAR8 *InputFileName,
411 UINT8 **FileBuffer,
412 UINT32 *FileSize
413 )
414 /*++
415
416 Routine Description:
417
418 Read the file buffer from the input file.
419
420 Arguments:
421
422 InputFileName Point to the input file name.
423 FileBuffer Point to the input file buffer.
424 FileSize Size of the file buffer.
425
426 Returns:
427
428 None
429 --*/
430 {
431 FILE *InputFile;
432 UINT32 BytesRead;
433
434 //
435 // Open Input file and read file data.
436 //
437 InputFile = fopen (InputFileName, "rb");
438 if (InputFile == NULL) {
439 fprintf (stderr, "Error opening file %s\n", InputFileName);
440 exit (EXIT_FAILURE);
441 }
442
443 //
444 // Go to the end so that we can determine the file size
445 //
446 if (fseek (InputFile, 0, SEEK_END)) {
447 fprintf (stderr, "Error reading input file %s\n", InputFileName);
448 fclose (InputFile);
449 exit (EXIT_FAILURE);
450 }
451
452 //
453 // Get the file size
454 //
455 *FileSize = ftell (InputFile);
456 if (*FileSize == -1) {
457 fprintf (stderr, "Error parsing the input file %s\n", InputFileName);
458 fclose (InputFile);
459 exit (EXIT_FAILURE);
460 }
461
462 //
463 // Allocate a buffer
464 //
465 *FileBuffer = malloc (*FileSize);
466 if (*FileBuffer == NULL) {
467 fprintf (stderr, "Can not allocate buffer for input input file %s\n", InputFileName);
468 fclose (InputFile);
469 exit (EXIT_FAILURE);
470 }
471
472 //
473 // Reset to the beginning of the file
474 //
475 if (fseek (InputFile, 0, SEEK_SET)) {
476 fprintf (stderr, "Error reading the input file %s\n", InputFileName);
477 fclose (InputFile);
478 free (*FileBuffer);
479 exit (EXIT_FAILURE);
480 }
481
482 //
483 // Read all of the file contents.
484 //
485 BytesRead = fread (*FileBuffer, sizeof (UINT8), *FileSize, InputFile);
486 if (BytesRead != *FileSize * sizeof (UINT8)) {
487 fprintf (stderr, "Error reading the input file %s\n", InputFileName);
488 fclose (InputFile);
489 free (*FileBuffer);
490 exit (EXIT_FAILURE);
491 }
492
493 //
494 // Close the file
495 //
496 fclose (InputFile);
497 }
498
499 VOID
500 STATIC
501 ParseFile (
502 UINT8 *FileBuffer,
503 UINT32 FileSize
504 )
505 /*++
506
507 Routine Description:
508
509 Read the initial PCD value from the input file buffer.
510
511 Arguments:
512
513 FileBuffer Point to the input file buffer.
514 FileSize Size of the file buffer.
515
516 Returns:
517
518 None
519 --*/
520 {
521 UINT32 Index;
522 UINT32 NumLines;
523 UINT32 TokenIndex;
524 UINT32 TokenStart;
525
526 for (Index = 0, NumLines = 0; Index < FileSize; Index++) {
527 if (FileBuffer[Index] == '\n') {
528 NumLines++;
529 }
530 }
531 PcdList = malloc((NumLines + 1) * sizeof(PcdList[0]));
532
533 for (Index = 0, TokenIndex = 0, PcdListLength = 0, TokenStart = 0; Index < FileSize; Index++) {
534 if (FileBuffer[Index] == ' ') {
535 continue;
536 }
537 if (FileBuffer[Index] == '|' || FileBuffer[Index] == '.' || FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
538 RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
539 if (FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
540 if (TokenIndex != 0) {
541 PcdListLength++;
542 TokenIndex = 0;
543 }
544 } else {
545 TokenIndex++;
546 }
547 TokenStart = Index + 1;
548 continue;
549 }
550 }
551 if (Index > TokenStart) {
552 RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
553 if (TokenIndex != 0) {
554 PcdListLength++;
555 }
556 }
557 }
558
559 VOID
560 STATIC
561 WriteOutputFile (
562 CHAR8 *OutputFileName
563 )
564 /*++
565
566 Routine Description:
567
568 Write the updated PCD value into the output file name.
569
570 Arguments:
571
572 OutputFileName Point to the output file name.
573
574 Returns:
575
576 None
577 --*/
578 {
579 FILE *OutputFile;
580 UINT32 Index;
581
582 //
583 // Open output file
584 //
585 OutputFile = fopen (OutputFileName, "wb");
586 if (OutputFile == NULL) {
587 fprintf (stderr, "Error opening file %s\n", OutputFileName);
588 exit (EXIT_FAILURE);
589 }
590
591 for (Index = 0; Index < PcdListLength; Index++) {
592 fprintf (
593 OutputFile,
594 "%s.%s.%s.%s|%s|%s\n",
595 PcdList[Index].SkuName,
596 PcdList[Index].DefaultValueName,
597 PcdList[Index].TokenSpaceGuidName,
598 PcdList[Index].TokenName,
599 PcdList[Index].DataType,
600 PcdList[Index].Value
601 );
602 }
603
604 //
605 // Done, write output file.
606 //
607 if (OutputFile != NULL) {
608 fclose (OutputFile);
609 }
610 }
611
612 VOID
613 STATIC
614 Usage (
615 VOID
616 )
617 /*++
618
619 Routine Description:
620
621 Displays the utility usage syntax to STDOUT
622
623 Arguments:
624
625 None
626
627 Returns:
628
629 None
630
631 --*/
632 {
633 fprintf (stdout, "Usage: -i <input_file> -o <output_file>\n\n");
634 fprintf (stdout, "optional arguments:\n");
635 fprintf (stdout, " -h, --help Show this help message and exit\n");
636 fprintf (stdout, " -i INPUT_FILENAME, --input INPUT_FILENAME\n\
637 PCD Database Input file name\n");
638 fprintf (stdout, " -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\
639 PCD Database Output file name\n");
640 }
641
642 VOID
643 STATIC
644 ParseArguments (
645 int argc,
646 char *argv[],
647 CHAR8 **InputFileName,
648 CHAR8 **OutputFileName
649 )
650 /*++
651
652 Routine Description:
653
654 Parse the input parameters to get the input/output file name.
655
656 Arguments:
657
658 argc Number of command line parameters.
659 argv Array of pointers to parameter strings.
660 InputFileName Point to the input file name.
661 OutputFileName Point to the output file name.
662
663 Returns:
664
665 None
666 --*/
667 {
668 if (argc == 1) {
669 fprintf (stderr, "Missing options\n");
670 exit (EXIT_FAILURE);
671 }
672
673 //
674 // Parse command line
675 //
676 argc--;
677 argv++;
678
679 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
680 Usage ();
681 exit (EXIT_SUCCESS);
682 }
683
684 while (argc > 0) {
685 if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--input") == 0)) {
686 if (argv[1] == NULL || argv[1][0] == '-') {
687 fprintf (stderr, "Invalid option value. Input File name is missing for -i option\n");
688 exit (EXIT_FAILURE);
689 }
690 *InputFileName = argv[1];
691 argc -= 2;
692 argv += 2;
693 continue;
694 }
695
696 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
697 if (argv[1] == NULL || argv[1][0] == '-') {
698 fprintf (stderr, "Invalid option value. Output File name is missing for -i option\n");
699 exit (EXIT_FAILURE);
700 }
701 *OutputFileName = argv[1];
702 argc -= 2;
703 argv += 2;
704 continue;
705 }
706
707 if (argv[0][0] == '-') {
708 fprintf (stderr, "Unknown option %s\n", argv[0]);
709 exit (EXIT_FAILURE);
710 }
711 argc --;
712 argv ++;
713 }
714
715 //
716 // Check Input paramters
717 //
718 if (*InputFileName == NULL) {
719 fprintf (stderr, "Missing option. Input files is not specified\n");
720 exit (EXIT_FAILURE);
721 } else {
722 printf ("Input file name is %s\n", *InputFileName);
723 }
724
725 if (*OutputFileName == NULL) {
726 fprintf (stderr, "Missing option. Output file is not specified\n");
727 exit (EXIT_FAILURE);
728 } else {
729 printf ("Output file name is %s\n", *OutputFileName);
730 }
731 }
732
733 int
734 PcdValueMain (
735 int argc,
736 char *argv[]
737 )
738 /*++
739
740 Routine Description:
741
742 Main function updates PCD values.
743
744 Arguments:
745
746 argc Number of command line parameters.
747 argv Array of pointers to parameter strings.
748
749 Returns:
750 EXIT_SUCCESS
751 --*/
752 {
753 CHAR8 *InputFileName;
754 CHAR8 *OutputFileName;
755 UINT8 *FileBuffer;
756 UINT32 FileSize;
757
758 printf ("PCD tool start.\n");
759 InputFileName = NULL;
760 OutputFileName = NULL;
761
762 //
763 // Parse the input arguments
764 //
765 ParseArguments (argc, argv, &InputFileName, &OutputFileName);
766
767 //
768 // Open Input file and read file data.
769 //
770 ReadInputFile (InputFileName, &FileBuffer, &FileSize);
771
772 //
773 // Read the initial Pcd value
774 //
775 ParseFile (FileBuffer, FileSize);
776
777 //
778 // Customize PCD values in the PCD Database
779 //
780 PcdEntryPoint ();
781
782 //
783 // Save the updated PCD value
784 //
785 WriteOutputFile (OutputFileName);
786
787 printf ("PCD tool done.\n");
788
789 exit (EXIT_SUCCESS);
790 }