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