]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/PcdValueCommon.c
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / C / Common / PcdValueCommon.c
1 /** @file
2 This file contains the PcdValue structure definition.
3
4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include "CommonLib.h"
14 #include "PcdValueCommon.h"
15
16 typedef enum {
17 PcdDataTypeBoolean,
18 PcdDataTypeUint8,
19 PcdDataTypeUint16,
20 PcdDataTypeUint32,
21 PcdDataTypeUint64,
22 PcdDataTypePointer
23 } PCD_DATA_TYPE;
24
25 typedef struct {
26 CHAR8 *SkuName;
27 CHAR8 *DefaultValueName;
28 CHAR8 *TokenSpaceGuidName;
29 CHAR8 *TokenName;
30 CHAR8 *DataType;
31 CHAR8 *Value;
32 PCD_DATA_TYPE PcdDataType;
33 } PCD_ENTRY;
34
35 PCD_ENTRY *PcdList;
36 UINT32 PcdListLength;
37
38 VOID
39 STATIC
40 RecordToken (
41 UINT8 *FileBuffer,
42 UINT32 PcdIndex,
43 UINT32 TokenIndex,
44 UINT32 TokenStart,
45 UINT32 TokenEnd
46 )
47 /*++
48
49 Routine Description:
50
51 Record new token information
52
53 Arguments:
54
55 FileBuffer File Buffer to be record
56 PcdIndex Index of PCD in database
57 TokenIndex Index of Token
58 TokenStart Start of Token
59 TokenEnd End of Token
60
61 Returns:
62
63 None
64 --*/
65 {
66 CHAR8 *Token;
67
68 Token = malloc (TokenEnd - TokenStart + 1);
69 if (Token == NULL) {
70 return;
71 }
72 memcpy (Token, &FileBuffer[TokenStart], TokenEnd - TokenStart);
73 Token[TokenEnd - TokenStart] = 0;
74 switch (TokenIndex) {
75 case 0:
76 PcdList[PcdIndex].SkuName = Token;
77 break;
78 case 1:
79 PcdList[PcdIndex].DefaultValueName = Token;
80 break;
81 case 2:
82 PcdList[PcdIndex].TokenSpaceGuidName = Token;
83 break;
84 case 3:
85 PcdList[PcdIndex].TokenName = Token;
86 break;
87 case 4:
88 PcdList[PcdIndex].DataType = Token;
89 if (strcmp (Token, "BOOLEAN") == 0) {
90 PcdList[PcdIndex].PcdDataType = PcdDataTypeBoolean;
91 } else if (strcmp (Token, "UINT8") == 0) {
92 PcdList[PcdIndex].PcdDataType = PcdDataTypeUint8;
93 } else if (strcmp (Token, "UINT16") == 0) {
94 PcdList[PcdIndex].PcdDataType = PcdDataTypeUint16;
95 } else if (strcmp (Token, "UINT32") == 0) {
96 PcdList[PcdIndex].PcdDataType = PcdDataTypeUint32;
97 } else if (strcmp (Token, "UINT64") == 0) {
98 PcdList[PcdIndex].PcdDataType = PcdDataTypeUint64;
99 } else {
100 PcdList[PcdIndex].PcdDataType = PcdDataTypePointer;
101 }
102 break;
103 case 5:
104 PcdList[PcdIndex].Value = Token;
105 break;
106 default:
107 free (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 sprintf(PcdList[Index].Value, "0x%016llx", (unsigned long long)Value);
270 break;
271 case PcdDataTypePointer:
272 fprintf (stderr, "PCD %s.%s.%s.%s is structure. Use PcdSetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
273 exit (EXIT_FAILURE);
274 break;
275 }
276 }
277
278 VOID *
279 __PcdGetPtr (
280 CHAR8 *SkuName OPTIONAL,
281 CHAR8 *DefaultValueName OPTIONAL,
282 CHAR8 *TokenSpaceGuidName,
283 CHAR8 *TokenName,
284 UINT32 *Size
285 )
286 /*++
287
288 Routine Description:
289
290 Get PCD value buffer
291
292 Arguments:
293
294 SkuName SkuName String
295 DefaultValueName DefaultValueName String
296 TokenSpaceGuidName TokenSpaceGuidName String
297 TokenName TokenName String
298 Size Size of PCD value buffer
299
300 Returns:
301
302 PCD value buffer
303 --*/
304 {
305 int Index;
306 CHAR8 *Value;
307 UINT8 *Buffer;
308 CHAR8 *End;
309
310 Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
311 if (Index < 0) {
312 fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
313 exit (EXIT_FAILURE);
314 }
315 switch (PcdList[Index].PcdDataType) {
316 case PcdDataTypeBoolean:
317 case PcdDataTypeUint8:
318 case PcdDataTypeUint16:
319 case PcdDataTypeUint32:
320 case PcdDataTypeUint64:
321 fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
322 exit (EXIT_FAILURE);
323 break;
324 case PcdDataTypePointer:
325 Value = &PcdList[Index].Value[1];
326 for (*Size = 0, strtoul(Value, &End, 16); Value != End; strtoul(Value, &End, 16), *Size = *Size + 1) {
327 Value = End + 1;
328 }
329 Buffer = malloc(*Size + 1);
330 if (Buffer == NULL) {
331 *Size = 0;
332 return NULL;
333 }
334 Value = &PcdList[Index].Value[1];
335 for (*Size = 0, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16); Value != End; *Size = *Size + 1, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16)) {
336 Value = End + 1;
337 }
338 return Buffer;
339 }
340 *Size = 0;
341 return 0;
342 }
343
344 VOID
345 __PcdSetPtr (
346 CHAR8 *SkuName OPTIONAL,
347 CHAR8 *DefaultValueName OPTIONAL,
348 CHAR8 *TokenSpaceGuidName,
349 CHAR8 *TokenName,
350 UINT32 Size,
351 UINT8 *Value
352 )
353 /*++
354
355 Routine Description:
356
357 Set PCD value buffer
358
359 Arguments:
360
361 SkuName SkuName String
362 DefaultValueName DefaultValueName String
363 TokenSpaceGuidName TokenSpaceGuidName String
364 TokenName TokenName String
365 Size Size of PCD value
366 Value Pointer to the updated PCD value buffer
367
368 Returns:
369
370 None
371 --*/
372 {
373 int Index;
374 UINT32 ValueIndex;
375
376 Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
377 if (Index < 0) {
378 fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
379 exit (EXIT_FAILURE);
380 }
381 switch (PcdList[Index].PcdDataType) {
382 case PcdDataTypeBoolean:
383 case PcdDataTypeUint8:
384 case PcdDataTypeUint16:
385 case PcdDataTypeUint32:
386 case PcdDataTypeUint64:
387 fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
388 exit (EXIT_FAILURE);
389 break;
390 case PcdDataTypePointer:
391 free(PcdList[Index].Value);
392 PcdList[Index].Value = malloc(Size * 5 + 3);
393 PcdList[Index].Value[0] = '{';
394 for (ValueIndex = 0; ValueIndex < Size; ValueIndex++) {
395 sprintf(&PcdList[Index].Value[1 + ValueIndex * 5], "0x%02x,", Value[ValueIndex]);
396 }
397 PcdList[Index].Value[1 + Size * 5 - 1] = '}';
398 PcdList[Index].Value[1 + Size * 5 ] = 0;
399 break;
400 }
401 }
402
403 VOID
404 STATIC
405 ReadInputFile (
406 CHAR8 *InputFileName,
407 UINT8 **FileBuffer,
408 UINT32 *FileSize
409 )
410 /*++
411
412 Routine Description:
413
414 Read the file buffer from the input file.
415
416 Arguments:
417
418 InputFileName Point to the input file name.
419 FileBuffer Point to the input file buffer.
420 FileSize Size of the file buffer.
421
422 Returns:
423
424 None
425 --*/
426 {
427 FILE *InputFile;
428 UINT32 BytesRead;
429
430 //
431 // Open Input file and read file data.
432 //
433 InputFile = fopen (InputFileName, "rb");
434 if (InputFile == NULL) {
435 fprintf (stderr, "Error opening file %s\n", InputFileName);
436 exit (EXIT_FAILURE);
437 }
438
439 //
440 // Go to the end so that we can determine the file size
441 //
442 if (fseek (InputFile, 0, SEEK_END)) {
443 fprintf (stderr, "Error reading input file %s\n", InputFileName);
444 fclose (InputFile);
445 exit (EXIT_FAILURE);
446 }
447
448 //
449 // Get the file size
450 //
451 *FileSize = ftell (InputFile);
452 if (*FileSize == -1) {
453 fprintf (stderr, "Error parsing the input file %s\n", InputFileName);
454 fclose (InputFile);
455 exit (EXIT_FAILURE);
456 }
457
458 //
459 // Allocate a buffer
460 //
461 *FileBuffer = malloc (*FileSize);
462 if (*FileBuffer == NULL) {
463 fprintf (stderr, "Can not allocate buffer for input input file %s\n", InputFileName);
464 fclose (InputFile);
465 exit (EXIT_FAILURE);
466 }
467
468 //
469 // Reset to the beginning of the file
470 //
471 if (fseek (InputFile, 0, SEEK_SET)) {
472 fprintf (stderr, "Error reading the input file %s\n", InputFileName);
473 fclose (InputFile);
474 free (*FileBuffer);
475 exit (EXIT_FAILURE);
476 }
477
478 //
479 // Read all of the file contents.
480 //
481 BytesRead = fread (*FileBuffer, sizeof (UINT8), *FileSize, InputFile);
482 if (BytesRead != *FileSize * sizeof (UINT8)) {
483 fprintf (stderr, "Error reading the input file %s\n", InputFileName);
484 fclose (InputFile);
485 free (*FileBuffer);
486 exit (EXIT_FAILURE);
487 }
488
489 //
490 // Close the file
491 //
492 fclose (InputFile);
493 }
494
495 VOID
496 STATIC
497 ParseFile (
498 UINT8 *FileBuffer,
499 UINT32 FileSize
500 )
501 /*++
502
503 Routine Description:
504
505 Read the initial PCD value from the input file buffer.
506
507 Arguments:
508
509 FileBuffer Point to the input file buffer.
510 FileSize Size of the file buffer.
511
512 Returns:
513
514 None
515 --*/
516 {
517 UINT32 Index;
518 UINT32 NumLines;
519 UINT32 TokenIndex;
520 UINT32 TokenStart;
521
522 for (Index = 0, NumLines = 0; Index < FileSize; Index++) {
523 if (FileBuffer[Index] == '\n') {
524 NumLines++;
525 }
526 }
527 PcdList = malloc((NumLines + 1) * sizeof(PcdList[0]));
528
529 for (Index = 0, TokenIndex = 0, PcdListLength = 0, TokenStart = 0; Index < FileSize; Index++) {
530 if (FileBuffer[Index] == ' ') {
531 continue;
532 }
533 if (FileBuffer[Index] == '|' || FileBuffer[Index] == '.' || FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
534 RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
535 if (FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
536 if (TokenIndex != 0) {
537 PcdListLength++;
538 TokenIndex = 0;
539 }
540 } else {
541 TokenIndex++;
542 }
543 TokenStart = Index + 1;
544 continue;
545 }
546 }
547 if (Index > TokenStart) {
548 RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
549 if (TokenIndex != 0) {
550 PcdListLength++;
551 }
552 }
553 }
554
555 VOID
556 STATIC
557 WriteOutputFile (
558 CHAR8 *OutputFileName
559 )
560 /*++
561
562 Routine Description:
563
564 Write the updated PCD value into the output file name.
565
566 Arguments:
567
568 OutputFileName Point to the output file name.
569
570 Returns:
571
572 None
573 --*/
574 {
575 FILE *OutputFile;
576 UINT32 Index;
577
578 //
579 // Open output file
580 //
581 OutputFile = fopen (OutputFileName, "wb");
582 if (OutputFile == NULL) {
583 fprintf (stderr, "Error opening file %s\n", OutputFileName);
584 exit (EXIT_FAILURE);
585 }
586
587 for (Index = 0; Index < PcdListLength; Index++) {
588 fprintf (
589 OutputFile,
590 "%s.%s.%s.%s|%s|%s\n",
591 PcdList[Index].SkuName,
592 PcdList[Index].DefaultValueName,
593 PcdList[Index].TokenSpaceGuidName,
594 PcdList[Index].TokenName,
595 PcdList[Index].DataType,
596 PcdList[Index].Value
597 );
598 }
599
600 //
601 // Done, write output file.
602 //
603 if (OutputFile != NULL) {
604 fclose (OutputFile);
605 }
606 }
607
608 VOID
609 STATIC
610 Usage (
611 VOID
612 )
613 /*++
614
615 Routine Description:
616
617 Displays the utility usage syntax to STDOUT
618
619 Arguments:
620
621 None
622
623 Returns:
624
625 None
626
627 --*/
628 {
629 fprintf (stdout, "Usage: -i <input_file> -o <output_file>\n\n");
630 fprintf (stdout, "optional arguments:\n");
631 fprintf (stdout, " -h, --help Show this help message and exit\n");
632 fprintf (stdout, " -i INPUT_FILENAME, --input INPUT_FILENAME\n\
633 PCD Database Input file name\n");
634 fprintf (stdout, " -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\
635 PCD Database Output file name\n");
636 }
637
638 VOID
639 STATIC
640 ParseArguments (
641 int argc,
642 char *argv[],
643 CHAR8 **InputFileName,
644 CHAR8 **OutputFileName
645 )
646 /*++
647
648 Routine Description:
649
650 Parse the input parameters to get the input/output file name.
651
652 Arguments:
653
654 argc Number of command line parameters.
655 argv Array of pointers to parameter strings.
656 InputFileName Point to the input file name.
657 OutputFileName Point to the output file name.
658
659 Returns:
660
661 None
662 --*/
663 {
664 if (argc == 1) {
665 fprintf (stderr, "Missing options\n");
666 exit (EXIT_FAILURE);
667 }
668
669 //
670 // Parse command line
671 //
672 argc--;
673 argv++;
674
675 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
676 Usage ();
677 exit (EXIT_SUCCESS);
678 }
679
680 while (argc > 0) {
681 if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--input") == 0)) {
682 if (argv[1] == NULL || argv[1][0] == '-') {
683 fprintf (stderr, "Invalid option value. Input File name is missing for -i option\n");
684 exit (EXIT_FAILURE);
685 }
686 *InputFileName = argv[1];
687 argc -= 2;
688 argv += 2;
689 continue;
690 }
691
692 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
693 if (argv[1] == NULL || argv[1][0] == '-') {
694 fprintf (stderr, "Invalid option value. Output File name is missing for -i option\n");
695 exit (EXIT_FAILURE);
696 }
697 *OutputFileName = argv[1];
698 argc -= 2;
699 argv += 2;
700 continue;
701 }
702
703 if (argv[0][0] == '-') {
704 fprintf (stderr, "Unknown option %s\n", argv[0]);
705 exit (EXIT_FAILURE);
706 }
707 argc --;
708 argv ++;
709 }
710
711 //
712 // Check Input parameters
713 //
714 if (*InputFileName == NULL) {
715 fprintf (stderr, "Missing option. Input files is not specified\n");
716 exit (EXIT_FAILURE);
717 }
718
719 if (*OutputFileName == NULL) {
720 fprintf (stderr, "Missing option. Output file is not specified\n");
721 exit (EXIT_FAILURE);
722 }
723 }
724
725 int
726 PcdValueMain (
727 int argc,
728 char *argv[]
729 )
730 /*++
731
732 Routine Description:
733
734 Main function updates PCD values.
735
736 Arguments:
737
738 argc Number of command line parameters.
739 argv Array of pointers to parameter strings.
740
741 Returns:
742 EXIT_SUCCESS
743 --*/
744 {
745 CHAR8 *InputFileName;
746 CHAR8 *OutputFileName;
747 UINT8 *FileBuffer;
748 UINT32 FileSize;
749
750 InputFileName = NULL;
751 OutputFileName = NULL;
752
753 //
754 // Parse the input arguments
755 //
756 ParseArguments (argc, argv, &InputFileName, &OutputFileName);
757
758 //
759 // Open Input file and read file data.
760 //
761 ReadInputFile (InputFileName, &FileBuffer, &FileSize);
762
763 //
764 // Read the initial Pcd value
765 //
766 ParseFile (FileBuffer, FileSize);
767
768 //
769 // Customize PCD values in the PCD Database
770 //
771 PcdEntryPoint ();
772
773 //
774 // Save the updated PCD value
775 //
776 WriteOutputFile (OutputFileName);
777
778 exit (EXIT_SUCCESS);
779 }