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