]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/Common/PcdValueCommon.c
BaseTools: CommonLib Fix Crash to write the last byte
[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 UINT8 Byte;
316
317 Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
318 if (Index < 0) {
319 fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
320 exit (EXIT_FAILURE);
321 }
322 switch (PcdList[Index].PcdDataType) {
323 case PcdDataTypeBoolean:
324 case PcdDataTypeUint8:
325 case PcdDataTypeUint16:
326 case PcdDataTypeUint32:
327 case PcdDataTypeUint64:
328 fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
329 exit (EXIT_FAILURE);
330 break;
331 case PcdDataTypePointer:
332 Value = &PcdList[Index].Value[1];
333 printf ("Value = %s\n", PcdList[Index].Value);
334 for (*Size = 0, Byte = (UINT8) strtoul(Value, &End, 16); Value != End; Byte = (UINT8) strtoul(Value, &End, 16), *Size = *Size + 1) {
335 printf("%x\n", Byte);
336 Value = End + 1;
337 }
338 Buffer = malloc(*Size + 1);
339 if (Buffer == NULL) {
340 *Size = 0;
341 return NULL;
342 }
343 Value = &PcdList[Index].Value[1];
344 for (*Size = 0, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16); Value != End; *Size = *Size + 1, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16)) {
345 Value = End + 1;
346 }
347 return Buffer;
348 }
349 *Size = 0;
350 return 0;
351 }
352
353 VOID
354 __PcdSetPtr (
355 CHAR8 *SkuName OPTIONAL,
356 CHAR8 *DefaultValueName OPTIONAL,
357 CHAR8 *TokenSpaceGuidName,
358 CHAR8 *TokenName,
359 UINT32 Size,
360 UINT8 *Value
361 )
362 /*++
363
364 Routine Description:
365
366 Set PCD value buffer
367
368 Arguments:
369
370 SkuName SkuName String
371 DefaultValueName DefaultValueName String
372 TokenSpaceGuidName TokenSpaceGuidName String
373 TokenName TokenName String
374 Size Size of PCD value
375 Value Pointer to the updated PCD value buffer
376
377 Returns:
378
379 None
380 --*/
381 {
382 int Index;
383 UINT32 ValueIndex;
384
385 Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
386 if (Index < 0) {
387 fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
388 exit (EXIT_FAILURE);
389 }
390 switch (PcdList[Index].PcdDataType) {
391 case PcdDataTypeBoolean:
392 case PcdDataTypeUint8:
393 case PcdDataTypeUint16:
394 case PcdDataTypeUint32:
395 case PcdDataTypeUint64:
396 fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName);
397 exit (EXIT_FAILURE);
398 break;
399 case PcdDataTypePointer:
400 free(PcdList[Index].Value);
401 PcdList[Index].Value = malloc(Size * 5 + 3);
402 PcdList[Index].Value[0] = '{';
403 for (ValueIndex = 0; ValueIndex < Size; ValueIndex++) {
404 printf("Value[%d] = %02x\n", ValueIndex, Value[ValueIndex]);
405 sprintf(&PcdList[Index].Value[1 + ValueIndex * 5], "0x%02x,", Value[ValueIndex]);
406 }
407 PcdList[Index].Value[1 + Size * 5 - 1] = '}';
408 PcdList[Index].Value[1 + Size * 5 ] = 0;
409 break;
410 }
411 }
412
413 VOID
414 STATIC
415 ReadInputFile (
416 CHAR8 *InputFileName,
417 UINT8 **FileBuffer,
418 UINT32 *FileSize
419 )
420 /*++
421
422 Routine Description:
423
424 Read the file buffer from the input file.
425
426 Arguments:
427
428 InputFileName Point to the input file name.
429 FileBuffer Point to the input file buffer.
430 FileSize Size of the file buffer.
431
432 Returns:
433
434 None
435 --*/
436 {
437 FILE *InputFile;
438 UINT32 BytesRead;
439
440 //
441 // Open Input file and read file data.
442 //
443 InputFile = fopen (InputFileName, "rb");
444 if (InputFile == NULL) {
445 fprintf (stderr, "Error opening file %s\n", InputFileName);
446 exit (EXIT_FAILURE);
447 }
448
449 //
450 // Go to the end so that we can determine the file size
451 //
452 if (fseek (InputFile, 0, SEEK_END)) {
453 fprintf (stderr, "Error reading input file %s\n", InputFileName);
454 fclose (InputFile);
455 exit (EXIT_FAILURE);
456 }
457
458 //
459 // Get the file size
460 //
461 *FileSize = ftell (InputFile);
462 if (*FileSize == -1) {
463 fprintf (stderr, "Error parsing the input file %s\n", InputFileName);
464 fclose (InputFile);
465 exit (EXIT_FAILURE);
466 }
467
468 //
469 // Allocate a buffer
470 //
471 *FileBuffer = malloc (*FileSize);
472 if (*FileBuffer == NULL) {
473 fprintf (stderr, "Can not allocate buffer for input input file %s\n", InputFileName);
474 fclose (InputFile);
475 exit (EXIT_FAILURE);
476 }
477
478 //
479 // Reset to the beginning of the file
480 //
481 if (fseek (InputFile, 0, SEEK_SET)) {
482 fprintf (stderr, "Error reading the input file %s\n", InputFileName);
483 fclose (InputFile);
484 free (*FileBuffer);
485 exit (EXIT_FAILURE);
486 }
487
488 //
489 // Read all of the file contents.
490 //
491 BytesRead = fread (*FileBuffer, sizeof (UINT8), *FileSize, InputFile);
492 if (BytesRead != *FileSize * sizeof (UINT8)) {
493 fprintf (stderr, "Error reading the input file %s\n", InputFileName);
494 fclose (InputFile);
495 free (*FileBuffer);
496 exit (EXIT_FAILURE);
497 }
498
499 //
500 // Close the file
501 //
502 fclose (InputFile);
503 }
504
505 VOID
506 STATIC
507 ParseFile (
508 UINT8 *FileBuffer,
509 UINT32 FileSize
510 )
511 /*++
512
513 Routine Description:
514
515 Read the initial PCD value from the input file buffer.
516
517 Arguments:
518
519 FileBuffer Point to the input file buffer.
520 FileSize Size of the file buffer.
521
522 Returns:
523
524 None
525 --*/
526 {
527 UINT32 Index;
528 UINT32 NumLines;
529 UINT32 TokenIndex;
530 UINT32 TokenStart;
531
532 for (Index = 0, NumLines = 0; Index < FileSize; Index++) {
533 if (FileBuffer[Index] == '\n') {
534 NumLines++;
535 }
536 }
537 PcdList = malloc((NumLines + 1) * sizeof(PcdList[0]));
538
539 for (Index = 0, TokenIndex = 0, PcdListLength = 0, TokenStart = 0; Index < FileSize; Index++) {
540 if (FileBuffer[Index] == ' ') {
541 continue;
542 }
543 if (FileBuffer[Index] == '|' || FileBuffer[Index] == '.' || FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
544 RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
545 if (FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') {
546 if (TokenIndex != 0) {
547 PcdListLength++;
548 TokenIndex = 0;
549 }
550 } else {
551 TokenIndex++;
552 }
553 TokenStart = Index + 1;
554 continue;
555 }
556 }
557 if (Index > TokenStart) {
558 RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index);
559 if (TokenIndex != 0) {
560 PcdListLength++;
561 }
562 }
563 }
564
565 VOID
566 STATIC
567 WriteOutputFile (
568 CHAR8 *OutputFileName
569 )
570 /*++
571
572 Routine Description:
573
574 Write the updated PCD value into the output file name.
575
576 Arguments:
577
578 OutputFileName Point to the output file name.
579
580 Returns:
581
582 None
583 --*/
584 {
585 FILE *OutputFile;
586 UINT32 Index;
587
588 //
589 // Open output file
590 //
591 OutputFile = fopen (OutputFileName, "wb");
592 if (OutputFile == NULL) {
593 fprintf (stderr, "Error opening file %s\n", OutputFileName);
594 exit (EXIT_FAILURE);
595 }
596
597 for (Index = 0; Index < PcdListLength; Index++) {
598 fprintf (
599 OutputFile,
600 "%s.%s.%s.%s|%s|%s\n",
601 PcdList[Index].SkuName,
602 PcdList[Index].DefaultValueName,
603 PcdList[Index].TokenSpaceGuidName,
604 PcdList[Index].TokenName,
605 PcdList[Index].DataType,
606 PcdList[Index].Value
607 );
608 }
609
610 //
611 // Done, write output file.
612 //
613 if (OutputFile != NULL) {
614 fclose (OutputFile);
615 }
616 }
617
618 VOID
619 STATIC
620 Usage (
621 VOID
622 )
623 /*++
624
625 Routine Description:
626
627 Displays the utility usage syntax to STDOUT
628
629 Arguments:
630
631 None
632
633 Returns:
634
635 None
636
637 --*/
638 {
639 fprintf (stdout, "Usage: -i <input_file> -o <output_file>\n\n");
640 fprintf (stdout, "optional arguments:\n");
641 fprintf (stdout, " -h, --help Show this help message and exit\n");
642 fprintf (stdout, " -i INPUT_FILENAME, --input INPUT_FILENAME\n\
643 PCD Database Input file name\n");
644 fprintf (stdout, " -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\
645 PCD Database Output file name\n");
646 }
647
648 VOID
649 STATIC
650 ParseArguments (
651 int argc,
652 char *argv[],
653 CHAR8 **InputFileName,
654 CHAR8 **OutputFileName
655 )
656 /*++
657
658 Routine Description:
659
660 Parse the input parameters to get the input/output file name.
661
662 Arguments:
663
664 argc Number of command line parameters.
665 argv Array of pointers to parameter strings.
666 InputFileName Point to the input file name.
667 OutputFileName Point to the output file name.
668
669 Returns:
670
671 None
672 --*/
673 {
674 if (argc == 1) {
675 fprintf (stderr, "Missing options\n");
676 exit (EXIT_FAILURE);
677 }
678
679 //
680 // Parse command line
681 //
682 argc--;
683 argv++;
684
685 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
686 Usage ();
687 exit (EXIT_SUCCESS);
688 }
689
690 while (argc > 0) {
691 if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--input") == 0)) {
692 if (argv[1] == NULL || argv[1][0] == '-') {
693 fprintf (stderr, "Invalid option value. Input File name is missing for -i option\n");
694 exit (EXIT_FAILURE);
695 }
696 *InputFileName = argv[1];
697 argc -= 2;
698 argv += 2;
699 continue;
700 }
701
702 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
703 if (argv[1] == NULL || argv[1][0] == '-') {
704 fprintf (stderr, "Invalid option value. Output File name is missing for -i option\n");
705 exit (EXIT_FAILURE);
706 }
707 *OutputFileName = argv[1];
708 argc -= 2;
709 argv += 2;
710 continue;
711 }
712
713 if (argv[0][0] == '-') {
714 fprintf (stderr, "Unknown option %s\n", argv[0]);
715 exit (EXIT_FAILURE);
716 }
717 argc --;
718 argv ++;
719 }
720
721 //
722 // Check Input paramters
723 //
724 if (*InputFileName == NULL) {
725 fprintf (stderr, "Missing option. Input files is not specified\n");
726 exit (EXIT_FAILURE);
727 } else {
728 printf ("Input file name is %s\n", *InputFileName);
729 }
730
731 if (*OutputFileName == NULL) {
732 fprintf (stderr, "Missing option. Output file is not specified\n");
733 exit (EXIT_FAILURE);
734 } else {
735 printf ("Output file name is %s\n", *OutputFileName);
736 }
737 }
738
739 int
740 PcdValueMain (
741 int argc,
742 char *argv[]
743 )
744 /*++
745
746 Routine Description:
747
748 Main function updates PCD values.
749
750 Arguments:
751
752 argc Number of command line parameters.
753 argv Array of pointers to parameter strings.
754
755 Returns:
756 EXIT_SUCCESS
757 --*/
758 {
759 CHAR8 *InputFileName;
760 CHAR8 *OutputFileName;
761 UINT8 *FileBuffer;
762 UINT32 FileSize;
763
764 printf ("PCD tool start.\n");
765 InputFileName = NULL;
766 OutputFileName = NULL;
767
768 //
769 // Parse the input arguments
770 //
771 ParseArguments (argc, argv, &InputFileName, &OutputFileName);
772
773 //
774 // Open Input file and read file data.
775 //
776 ReadInputFile (InputFileName, &FileBuffer, &FileSize);
777
778 //
779 // Read the initial Pcd value
780 //
781 ParseFile (FileBuffer, FileSize);
782
783 //
784 // Customize PCD values in the PCD Database
785 //
786 PcdEntryPoint ();
787
788 //
789 // Save the updated PCD value
790 //
791 WriteOutputFile (OutputFileName);
792
793 printf ("PCD tool done.\n");
794
795 exit (EXIT_SUCCESS);
796 }